The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/coda/coda_psdev.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * 
    3  *             Coda: an Experimental Distributed File System
    4  *                              Release 3.1
    5  * 
    6  *           Copyright (c) 1987-1998 Carnegie Mellon University
    7  *                          All Rights Reserved
    8  * 
    9  * Permission  to  use, copy, modify and distribute this software and its
   10  * documentation is hereby granted,  provided  that  both  the  copyright
   11  * notice  and  this  permission  notice  appear  in  all  copies  of the
   12  * software, derivative works or  modified  versions,  and  any  portions
   13  * thereof, and that both notices appear in supporting documentation, and
   14  * that credit is given to Carnegie Mellon University  in  all  documents
   15  * and publicity pertaining to direct or indirect use of this code or its
   16  * derivatives.
   17  * 
   18  * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS  KNOWN  TO  HAVE  BUGS,
   19  * SOME  OF  WHICH MAY HAVE SERIOUS CONSEQUENCES.  CARNEGIE MELLON ALLOWS
   20  * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.   CARNEGIE  MELLON
   21  * DISCLAIMS  ANY  LIABILITY  OF  ANY  KIND  FOR  ANY  DAMAGES WHATSOEVER
   22  * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE  OR  OF
   23  * ANY DERIVATIVE WORK.
   24  * 
   25  * Carnegie  Mellon  encourages  users  of  this  software  to return any
   26  * improvements or extensions that  they  make,  and  to  grant  Carnegie
   27  * Mellon the rights to redistribute these changes without encumbrance.
   28  * 
   29  *      @(#) src/sys/coda/coda_psdev.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $
   30  * $FreeBSD$
   31  * 
   32  */
   33 
   34 /* 
   35  * Mach Operating System
   36  * Copyright (c) 1989 Carnegie-Mellon University
   37  * All rights reserved.  The CMU software License Agreement specifies
   38  * the terms and conditions for use and redistribution.
   39  */
   40 
   41 /*
   42  * This code was written for the Coda file system at Carnegie Mellon
   43  * University.  Contributers include David Steere, James Kistler, and
   44  * M. Satyanarayanan.  */
   45 
   46 /* 
   47  * These routines define the psuedo device for communication between
   48  * Coda's Venus and Minicache in Mach 2.6. They used to be in cfs_subr.c, 
   49  * but I moved them to make it easier to port the Minicache without 
   50  * porting coda. -- DCS 10/12/94
   51  */
   52 
   53 /* These routines are the device entry points for Venus. */
   54 
   55 extern int coda_nc_initialized;    /* Set if cache has been initialized */
   56 
   57 #include <vcoda.h>
   58 
   59 #include <sys/param.h>
   60 #include <sys/systm.h>
   61 #include <sys/kernel.h>
   62 #include <sys/proc.h>
   63 #include <sys/malloc.h>
   64 #include <sys/mount.h>
   65 #include <sys/file.h>
   66 #include <sys/ioccom.h>
   67 #include <sys/poll.h>
   68 #include <sys/conf.h>
   69 
   70 #include <coda/coda.h>
   71 #include <coda/cnode.h>
   72 #include <coda/coda_namecache.h>
   73 #include <coda/coda_io.h>
   74 #include <coda/coda_psdev.h>
   75 
   76 #define CTL_C
   77 
   78 #ifdef CTL_C
   79 #include <sys/signalvar.h>
   80 #endif
   81 
   82 int coda_psdev_print_entry = 0;
   83 static
   84 int outstanding_upcalls = 0;
   85 int coda_call_sleep = PZERO - 1;
   86 #ifdef  CTL_C
   87 int coda_pcatch = PCATCH;
   88 #else
   89 #endif
   90 
   91 #define ENTRY if(coda_psdev_print_entry) myprintf(("Entered %s\n",__FUNCTION__))
   92 
   93 void vcodaattach(int n);
   94 
   95 struct vmsg {
   96     struct queue vm_chain;
   97     caddr_t      vm_data;
   98     u_short      vm_flags;
   99     u_short      vm_inSize;     /* Size is at most 5000 bytes */
  100     u_short      vm_outSize;
  101     u_short      vm_opcode;     /* copied from data to save ptr lookup */
  102     int          vm_unique;
  103     caddr_t      vm_sleep;      /* Not used by Mach. */
  104 };
  105 
  106 #define VM_READ     1
  107 #define VM_WRITE    2
  108 #define VM_INTR     4
  109 
  110 /* vcodaattach: do nothing */
  111 void
  112 vcodaattach(n)
  113     int n;
  114 {
  115 }
  116 
  117 int 
  118 vc_nb_open(dev, flag, mode, p)    
  119     dev_t        dev;      
  120     int          flag;     
  121     int          mode;     
  122     struct proc *p;             /* NetBSD only */
  123 {
  124     register struct vcomm *vcp;
  125     
  126     ENTRY;
  127 
  128     if (minor(dev) >= NVCODA || minor(dev) < 0)
  129         return(ENXIO);
  130     
  131     if (!coda_nc_initialized)
  132         coda_nc_init();
  133     
  134     vcp = &coda_mnttbl[minor(dev)].mi_vcomm;
  135     if (VC_OPEN(vcp))
  136         return(EBUSY);
  137     
  138     bzero(&(vcp->vc_selproc), sizeof (struct selinfo));
  139     INIT_QUEUE(vcp->vc_requests);
  140     INIT_QUEUE(vcp->vc_replys);
  141     MARK_VC_OPEN(vcp);
  142     
  143     coda_mnttbl[minor(dev)].mi_vfsp = NULL;
  144     coda_mnttbl[minor(dev)].mi_rootvp = NULL;
  145 
  146     return(0);
  147 }
  148 
  149 int 
  150 vc_nb_close (dev, flag, mode, p)    
  151     dev_t        dev;      
  152     int          flag;     
  153     int          mode;     
  154     struct proc *p;
  155 {
  156     register struct vcomm *vcp;
  157     register struct vmsg *vmp, *nvmp = NULL;
  158     struct coda_mntinfo *mi;
  159     int                 err;
  160         
  161     ENTRY;
  162 
  163     if (minor(dev) >= NVCODA || minor(dev) < 0)
  164         return(ENXIO);
  165 
  166     mi = &coda_mnttbl[minor(dev)];
  167     vcp = &(mi->mi_vcomm);
  168     
  169     if (!VC_OPEN(vcp))
  170         panic("vcclose: not open");
  171     
  172     /* prevent future operations on this vfs from succeeding by auto-
  173      * unmounting any vfs mounted via this device. This frees user or
  174      * sysadm from having to remember where all mount points are located.
  175      * Put this before WAKEUPs to avoid queuing new messages between
  176      * the WAKEUP and the unmount (which can happen if we're unlucky)
  177      */
  178     if (!mi->mi_rootvp) {
  179         /* just a simple open/close w no mount */
  180         MARK_VC_CLOSED(vcp);
  181         return 0;
  182     }
  183 
  184     /* Let unmount know this is for real */
  185     VTOC(mi->mi_rootvp)->c_flags |= C_UNMOUNTING;
  186     coda_unmounting(mi->mi_vfsp);
  187 
  188     outstanding_upcalls = 0;
  189     /* Wakeup clients so they can return. */
  190     for (vmp = (struct vmsg *)GETNEXT(vcp->vc_requests);
  191          !EOQ(vmp, vcp->vc_requests);
  192          vmp = nvmp)
  193     {
  194         nvmp = (struct vmsg *)GETNEXT(vmp->vm_chain);
  195         /* Free signal request messages and don't wakeup cause
  196            no one is waiting. */
  197         if (vmp->vm_opcode == CODA_SIGNAL) {
  198             CODA_FREE((caddr_t)vmp->vm_data, (u_int)VC_IN_NO_DATA);
  199             CODA_FREE((caddr_t)vmp, (u_int)sizeof(struct vmsg));
  200             continue;
  201         }
  202         outstanding_upcalls++;  
  203         wakeup(&vmp->vm_sleep);
  204     }
  205 
  206     for (vmp = (struct vmsg *)GETNEXT(vcp->vc_replys);
  207          !EOQ(vmp, vcp->vc_replys);
  208          vmp = (struct vmsg *)GETNEXT(vmp->vm_chain))
  209     {
  210         outstanding_upcalls++;  
  211         wakeup(&vmp->vm_sleep);
  212     }
  213 
  214     MARK_VC_CLOSED(vcp);
  215 
  216     if (outstanding_upcalls) {
  217 #ifdef  CODA_VERBOSE
  218         printf("presleep: outstanding_upcalls = %d\n", outstanding_upcalls);
  219         (void) tsleep(&outstanding_upcalls, coda_call_sleep, "coda_umount", 0);
  220         printf("postsleep: outstanding_upcalls = %d\n", outstanding_upcalls);
  221 #else
  222         (void) tsleep(&outstanding_upcalls, coda_call_sleep, "coda_umount", 0);
  223 #endif
  224     }
  225 
  226     err = dounmount(mi->mi_vfsp, flag, p);
  227     if (err)
  228         myprintf(("Error %d unmounting vfs in vcclose(%d)\n", 
  229                    err, minor(dev)));
  230     return 0;
  231 }
  232 
  233 int 
  234 vc_nb_read(dev, uiop, flag)   
  235     dev_t        dev;  
  236     struct uio  *uiop; 
  237     int          flag;
  238 {
  239     register struct vcomm *     vcp;
  240     register struct vmsg *vmp;
  241     int error = 0;
  242     
  243     ENTRY;
  244 
  245     if (minor(dev) >= NVCODA || minor(dev) < 0)
  246         return(ENXIO);
  247     
  248     vcp = &coda_mnttbl[minor(dev)].mi_vcomm;
  249     /* Get message at head of request queue. */
  250     if (EMPTY(vcp->vc_requests))
  251         return(0);      /* Nothing to read */
  252     
  253     vmp = (struct vmsg *)GETNEXT(vcp->vc_requests);
  254     
  255     /* Move the input args into userspace */
  256     uiop->uio_rw = UIO_READ;
  257     error = uiomove(vmp->vm_data, vmp->vm_inSize, uiop);
  258     if (error) {
  259         myprintf(("vcread: error (%d) on uiomove\n", error));
  260         error = EINVAL;
  261     }
  262 
  263 #ifdef OLD_DIAGNOSTIC    
  264     if (vmp->vm_chain.forw == 0 || vmp->vm_chain.back == 0)
  265         panic("vc_nb_read: bad chain");
  266 #endif
  267 
  268     REMQUE(vmp->vm_chain);
  269     
  270     /* If request was a signal, free up the message and don't
  271        enqueue it in the reply queue. */
  272     if (vmp->vm_opcode == CODA_SIGNAL) {
  273         if (codadebug)
  274             myprintf(("vcread: signal msg (%d, %d)\n", 
  275                       vmp->vm_opcode, vmp->vm_unique));
  276         CODA_FREE((caddr_t)vmp->vm_data, (u_int)VC_IN_NO_DATA);
  277         CODA_FREE((caddr_t)vmp, (u_int)sizeof(struct vmsg));
  278         return(error);
  279     }
  280     
  281     vmp->vm_flags |= VM_READ;
  282     INSQUE(vmp->vm_chain, vcp->vc_replys);
  283     
  284     return(error);
  285 }
  286 
  287 int
  288 vc_nb_write(dev, uiop, flag)   
  289     dev_t        dev;  
  290     struct uio  *uiop; 
  291     int          flag;
  292 {
  293     register struct vcomm *     vcp;
  294     register struct vmsg *vmp;
  295     struct coda_out_hdr *out;
  296     u_long seq;
  297     u_long opcode;
  298     int buf[2];
  299     int error = 0;
  300 
  301     ENTRY;
  302 
  303     if (minor(dev) >= NVCODA || minor(dev) < 0)
  304         return(ENXIO);
  305     
  306     vcp = &coda_mnttbl[minor(dev)].mi_vcomm;
  307     
  308     /* Peek at the opcode, unique without transfering the data. */
  309     uiop->uio_rw = UIO_WRITE;
  310     error = uiomove((caddr_t)buf, sizeof(int) * 2, uiop);
  311     if (error) {
  312         myprintf(("vcwrite: error (%d) on uiomove\n", error));
  313         return(EINVAL);
  314     }
  315     
  316     opcode = buf[0];
  317     seq = buf[1];
  318         
  319     if (codadebug)
  320         myprintf(("vcwrite got a call for %ld.%ld\n", opcode, seq));
  321     
  322     if (DOWNCALL(opcode)) {
  323         union outputArgs pbuf;
  324         
  325         /* get the rest of the data. */
  326         uiop->uio_rw = UIO_WRITE;
  327         error = uiomove((caddr_t)&pbuf.coda_purgeuser.oh.result, sizeof(pbuf) - (sizeof(int)*2), uiop);
  328         if (error) {
  329             myprintf(("vcwrite: error (%d) on uiomove (Op %ld seq %ld)\n", 
  330                       error, opcode, seq));
  331             return(EINVAL);
  332             }
  333         
  334         return handleDownCall(opcode, &pbuf);
  335     }
  336     
  337     /* Look for the message on the (waiting for) reply queue. */
  338     for (vmp = (struct vmsg *)GETNEXT(vcp->vc_replys);
  339          !EOQ(vmp, vcp->vc_replys);
  340          vmp = (struct vmsg *)GETNEXT(vmp->vm_chain))
  341     {
  342         if (vmp->vm_unique == seq) break;
  343     }
  344     
  345     if (EOQ(vmp, vcp->vc_replys)) {
  346         if (codadebug)
  347             myprintf(("vcwrite: msg (%ld, %ld) not found\n", opcode, seq));
  348         
  349         return(ESRCH);
  350         }
  351     
  352     /* Remove the message from the reply queue */
  353     REMQUE(vmp->vm_chain);
  354     
  355     /* move data into response buffer. */
  356     out = (struct coda_out_hdr *)vmp->vm_data;
  357     /* Don't need to copy opcode and uniquifier. */
  358     
  359     /* get the rest of the data. */
  360     if (vmp->vm_outSize < uiop->uio_resid) {
  361         myprintf(("vcwrite: more data than asked for (%d < %d)\n",
  362                   vmp->vm_outSize, uiop->uio_resid));
  363         wakeup(&vmp->vm_sleep);         /* Notify caller of the error. */
  364         return(EINVAL);
  365     } 
  366     
  367     buf[0] = uiop->uio_resid;   /* Save this value. */
  368     uiop->uio_rw = UIO_WRITE;
  369     error = uiomove((caddr_t) &out->result, vmp->vm_outSize - (sizeof(int) * 2), uiop);
  370     if (error) {
  371         myprintf(("vcwrite: error (%d) on uiomove (op %ld seq %ld)\n", 
  372                   error, opcode, seq));
  373         return(EINVAL);
  374     }
  375     
  376     /* I don't think these are used, but just in case. */
  377     /* XXX - aren't these two already correct? -bnoble */
  378     out->opcode = opcode;
  379     out->unique = seq;
  380     vmp->vm_outSize     = buf[0];       /* Amount of data transferred? */
  381     vmp->vm_flags |= VM_WRITE;
  382     wakeup(&vmp->vm_sleep);
  383     
  384     return(0);
  385 }
  386 
  387 int
  388 vc_nb_ioctl(dev, cmd, addr, flag, p) 
  389     dev_t         dev;       
  390     u_long        cmd;       
  391     caddr_t       addr;      
  392     int           flag;      
  393     struct proc  *p;
  394 {
  395     ENTRY;
  396 
  397     switch(cmd) {
  398     case CODARESIZE: {
  399         struct coda_resize *data = (struct coda_resize *)addr;
  400         return(coda_nc_resize(data->hashsize, data->heapsize, IS_DOWNCALL));
  401         break;
  402     }
  403     case CODASTATS:
  404         if (coda_nc_use) {
  405             coda_nc_gather_stats();
  406             return(0);
  407         } else {
  408             return(ENODEV);
  409         }
  410         break;
  411     case CODAPRINT:
  412         if (coda_nc_use) {
  413             print_coda_nc();
  414             return(0);
  415         } else {
  416             return(ENODEV);
  417         }
  418         break;
  419     case CIOC_KERNEL_VERSION:
  420         switch (*(u_int *)addr) {
  421         case 0:
  422                 *(u_int *)addr = coda_kernel_version;
  423                 return 0;
  424                 break;
  425         case 1:
  426         case 2:
  427                 if (coda_kernel_version != *(u_int *)addr)
  428                     return ENOENT;
  429                 else
  430                     return 0;
  431         default:
  432                 return ENOENT;
  433         }
  434         break;
  435     default :
  436         return(EINVAL);
  437         break;
  438     }
  439 }
  440 
  441 int
  442 vc_nb_poll(dev, events, p)         
  443     dev_t         dev;    
  444     int           events;   
  445     struct proc  *p;
  446 {
  447     register struct vcomm *vcp;
  448     int event_msk = 0;
  449 
  450     ENTRY;
  451     
  452     if (minor(dev) >= NVCODA || minor(dev) < 0)
  453         return(ENXIO);
  454     
  455     vcp = &coda_mnttbl[minor(dev)].mi_vcomm;
  456     
  457     event_msk = events & (POLLIN|POLLRDNORM);
  458     if (!event_msk)
  459         return(0);
  460     
  461     if (!EMPTY(vcp->vc_requests))
  462         return(events & (POLLIN|POLLRDNORM));
  463 
  464     selrecord(p, &(vcp->vc_selproc));
  465     
  466     return(0);
  467 }
  468 
  469 /*
  470  * Statistics
  471  */
  472 struct coda_clstat coda_clstat;
  473 
  474 /* 
  475  * Key question: whether to sleep interuptably or uninteruptably when
  476  * waiting for Venus.  The former seems better (cause you can ^C a
  477  * job), but then GNU-EMACS completion breaks. Use tsleep with no
  478  * timeout, and no longjmp happens. But, when sleeping
  479  * "uninterruptibly", we don't get told if it returns abnormally
  480  * (e.g. kill -9).  
  481  */
  482 
  483 int
  484 coda_call(mntinfo, inSize, outSize, buffer) 
  485      struct coda_mntinfo *mntinfo; int inSize; int *outSize; caddr_t buffer;
  486 {
  487         struct vcomm *vcp;
  488         struct vmsg *vmp;
  489         int error;
  490 #ifdef  CTL_C
  491         struct proc *p = curproc;
  492         sigset_t psig_omask = p->p_sigmask;
  493         sigset_t tempset;
  494         int i;
  495 #endif
  496         if (mntinfo == NULL) {
  497             /* Unlikely, but could be a race condition with a dying warden */
  498             return ENODEV;
  499         }
  500 
  501         vcp = &(mntinfo->mi_vcomm);
  502         
  503         coda_clstat.ncalls++;
  504         coda_clstat.reqs[((struct coda_in_hdr *)buffer)->opcode]++;
  505 
  506         if (!VC_OPEN(vcp))
  507             return(ENODEV);
  508 
  509         CODA_ALLOC(vmp,struct vmsg *,sizeof(struct vmsg));
  510         /* Format the request message. */
  511         vmp->vm_data = buffer;
  512         vmp->vm_flags = 0;
  513         vmp->vm_inSize = inSize;
  514         vmp->vm_outSize 
  515             = *outSize ? *outSize : inSize; /* |buffer| >= inSize */
  516         vmp->vm_opcode = ((struct coda_in_hdr *)buffer)->opcode;
  517         vmp->vm_unique = ++vcp->vc_seq;
  518         if (codadebug)
  519             myprintf(("Doing a call for %d.%d\n", 
  520                       vmp->vm_opcode, vmp->vm_unique));
  521         
  522         /* Fill in the common input args. */
  523         ((struct coda_in_hdr *)buffer)->unique = vmp->vm_unique;
  524 
  525         /* Append msg to request queue and poke Venus. */
  526         INSQUE(vmp->vm_chain, vcp->vc_requests);
  527         selwakeup(&(vcp->vc_selproc));
  528 
  529         /* We can be interrupted while we wait for Venus to process
  530          * our request.  If the interrupt occurs before Venus has read
  531          * the request, we dequeue and return. If it occurs after the
  532          * read but before the reply, we dequeue, send a signal
  533          * message, and return. If it occurs after the reply we ignore
  534          * it. In no case do we want to restart the syscall.  If it
  535          * was interrupted by a venus shutdown (vcclose), return
  536          * ENODEV.  */
  537 
  538         /* Ignore return, We have to check anyway */
  539 #ifdef  CTL_C
  540         /* This is work in progress.  Setting coda_pcatch lets tsleep reawaken
  541            on a ^c or ^z.  The problem is that emacs sets certain interrupts
  542            as SA_RESTART.  This means that we should exit sleep handle the
  543            "signal" and then go to sleep again.  Mostly this is done by letting
  544            the syscall complete and be restarted.  We are not idempotent and 
  545            can not do this.  A better solution is necessary.
  546          */
  547         i = 0;
  548         do {
  549                 error = tsleep(&vmp->vm_sleep,
  550                                (coda_call_sleep|coda_pcatch), "coda_call",
  551                                hz*2);
  552                 if (error == 0)
  553                         break;
  554                 else if (error == EWOULDBLOCK) {
  555 #ifdef  CODA_VERBOSE
  556                         printf("coda_call: tsleep TIMEOUT %d sec\n", 2+2*i);
  557 #endif
  558                 }
  559                 else {
  560                         SIGEMPTYSET(tempset);
  561                         SIGADDSET(tempset, SIGIO);
  562                         if (SIGSETEQ(p->p_siglist, tempset)) {
  563                                 SIGADDSET(p->p_sigmask, SIGIO);
  564 #ifdef  CODA_VERBOSE
  565                                 printf("coda_call: tsleep returns %d SIGIO, cnt %d\n",
  566                                        error, i);
  567 #endif
  568                         } else {
  569                                 SIGDELSET(tempset, SIGIO);
  570                                 SIGADDSET(tempset, SIGALRM);
  571                                 if (SIGSETEQ(p->p_siglist, tempset)) {
  572                                         SIGADDSET(p->p_sigmask, SIGALRM);
  573 #ifdef  CODA_VERBOSE
  574                                         printf("coda_call: tsleep returns %d SIGALRM, cnt %d\n",
  575                                                error, i);
  576 #endif
  577                                 }
  578                                 else {
  579                                         printf("coda_call: tsleep returns %d, cnt %d\n",
  580                                                error, i);
  581 
  582 #if notyet
  583                                         tempset = p->p_siglist;
  584                                         SIGSETNAND(tempset, p->p_sigmask);
  585                                         printf("coda_call: siglist = %p, sigmask = %p, mask %p\n",
  586                                                p->p_siglist, p->p_sigmask,
  587                                                tempset);
  588                                         break;
  589                                         SIGSETOR(p->p_sigmask, p->p_siglist);
  590                                         tempset = p->p_siglist;
  591                                         SIGSETNAND(tempset, p->p_sigmask);
  592                                         printf("coda_call: new mask, siglist = %p, sigmask = %p, mask %p\n",
  593                                                p->p_siglist, p->p_sigmask,
  594                                                tempset);
  595 #endif
  596                                 }
  597                         }
  598                 }
  599         } while (error && i++ < 128 && VC_OPEN(vcp));
  600         p->p_sigmask = psig_omask;
  601 #else
  602         (void) tsleep(&vmp->vm_sleep, coda_call_sleep, "coda_call", 0);
  603 #endif
  604         if (VC_OPEN(vcp)) {     /* Venus is still alive */
  605         /* Op went through, interrupt or not... */
  606             if (vmp->vm_flags & VM_WRITE) {
  607                 error = 0;
  608                 *outSize = vmp->vm_outSize;
  609             }
  610 
  611             else if (!(vmp->vm_flags & VM_READ)) { 
  612                 /* Interrupted before venus read it. */
  613 #ifdef  CODA_VERBOSE
  614                 if (1)
  615 #else
  616                 if (codadebug)
  617 #endif
  618                     myprintf(("interrupted before read: op = %d.%d, flags = %x\n",
  619                            vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags));
  620                 REMQUE(vmp->vm_chain);
  621                 error = EINTR;
  622             }
  623             
  624             else {      
  625                 /* (!(vmp->vm_flags & VM_WRITE)) means interrupted after
  626                    upcall started */
  627                 /* Interrupted after start of upcall, send venus a signal */
  628                 struct coda_in_hdr *dog;
  629                 struct vmsg *svmp;
  630                 
  631 #ifdef  CODA_VERBOSE
  632                 if (1)
  633 #else
  634                 if (codadebug)
  635 #endif
  636                     myprintf(("Sending Venus a signal: op = %d.%d, flags = %x\n",
  637                            vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags));
  638                 
  639                 REMQUE(vmp->vm_chain);
  640                 error = EINTR;
  641                 
  642                 CODA_ALLOC(svmp, struct vmsg *, sizeof (struct vmsg));
  643 
  644                 CODA_ALLOC((svmp->vm_data), char *, sizeof (struct coda_in_hdr));
  645                 dog = (struct coda_in_hdr *)svmp->vm_data;
  646                 
  647                 svmp->vm_flags = 0;
  648                 dog->opcode = svmp->vm_opcode = CODA_SIGNAL;
  649                 dog->unique = svmp->vm_unique = vmp->vm_unique;
  650                 svmp->vm_inSize = sizeof (struct coda_in_hdr);
  651 /*??? rvb */    svmp->vm_outSize = sizeof (struct coda_in_hdr);
  652                 
  653                 if (codadebug)
  654                     myprintf(("coda_call: enqueing signal msg (%d, %d)\n",
  655                            svmp->vm_opcode, svmp->vm_unique));
  656                 
  657                 /* insert at head of queue! */
  658                 INSQUE(svmp->vm_chain, vcp->vc_requests);
  659                 selwakeup(&(vcp->vc_selproc));
  660             }
  661         }
  662 
  663         else {  /* If venus died (!VC_OPEN(vcp)) */
  664             if (codadebug)
  665                 myprintf(("vcclose woke op %d.%d flags %d\n",
  666                        vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags));
  667             
  668                 error = ENODEV;
  669         }
  670 
  671         CODA_FREE(vmp, sizeof(struct vmsg));
  672 
  673         if (outstanding_upcalls > 0 && (--outstanding_upcalls == 0))
  674                 wakeup(&outstanding_upcalls);
  675 
  676         if (!error)
  677                 error = ((struct coda_out_hdr *)buffer)->result;
  678         return(error);
  679 }

Cache object: 670f84549d3e92cc191125c883929ed6


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.