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

Cache object: b5084586cd59316d222590db054c8c23


[ 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.