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 /*
   54  * HISTORY
   55  * $Log: coda_psdev.c,v $
   56  * Revision 1.10  1999/01/17 21:04:53  peter
   57  * Missed a stray LKM #ifdef
   58  *
   59  * Revision 1.9  1998/11/11 20:32:20  rvb
   60  * coda_lookup now passes up an extra flag.  But old veni will
   61  * be ok; new veni will check /dev/cfs0 to make sure that a new
   62  * kernel is running.
   63  * Also, a bug in vc_nb_close iff CODA_SIGNAL's were seen has been
   64  * fixed.
   65  *
   66  * Revision 1.8  1998/10/28 20:31:13  rvb
   67  * Change the way unmounting happens to guarantee that the
   68  * client programs are allowed to finish up (coda_call is
   69  * forced to complete) and release their locks.  Thus there
   70  * is a reasonable chance that the vflush implicit in the
   71  * unmount will not get hung on held locks.
   72  *
   73  * Revision 1.7  1998/09/29 20:19:45  rvb
   74  * Fixes for lkm:
   75  * 1. use VFS_LKM vs ACTUALLY_LKM_NOT_KERNEL
   76  * 2. don't pass -DCODA to lkm build
   77  *
   78  * Revision 1.6  1998/09/28 20:52:58  rvb
   79  * Cleanup and fix THE bug
   80  *
   81  * Revision 1.5  1998/09/25 17:38:31  rvb
   82  * Put "stray" printouts under DIAGNOSTIC.  Make everything build
   83  * with DEBUG on.  Add support for lkm.  (The macro's don't work
   84  * for me; for a good chuckle look at the end of coda_fbsd.c.)
   85  *
   86  * Revision 1.4  1998/09/13 13:57:59  rvb
   87  * Finish conversion of cfs -> coda
   88  *
   89  * Revision 1.3  1998/09/11 18:50:17  rvb
   90  * All the references to cfs, in symbols, structs, and strings
   91  * have been changed to coda.  (Same for CFS.)
   92  *
   93  * Revision 1.2  1998/09/02 19:09:53  rvb
   94  * Pass2 complete
   95  *
   96  * Revision 1.1.1.1  1998/08/29 21:14:52  rvb
   97  * Very Preliminary Coda
   98  *
   99  * Revision 1.9  1998/08/28 18:12:17  rvb
  100  * Now it also works on FreeBSD -current.  This code will be
  101  * committed to the FreeBSD -current and NetBSD -current
  102  * trees.  It will then be tailored to the particular platform
  103  * by flushing conditional code.
  104  *
  105  * Revision 1.8  1998/08/18 17:05:15  rvb
  106  * Don't use __RCSID now
  107  *
  108  * Revision 1.7  1998/08/18 16:31:41  rvb
  109  * Sync the code for NetBSD -current; test on 1.3 later
  110  *
  111  * Revision 1.8  1998/06/09 23:30:42  rvb
  112  * Try to allow ^C -- take 1
  113  *
  114  * Revision 1.5.2.8  98/01/23  11:21:04  rvb
  115  * Sync with 2.2.5
  116  * 
  117  * Revision 1.5.2.7  98/01/22  22:22:21  rvb
  118  * sync 1.2 and 1.3
  119  * 
  120  * Revision 1.5.2.6  98/01/22  13:11:24  rvb
  121  * Move make_coda_node ctlfid later so vfsp is known; work on ^c and ^z
  122  * 
  123  * Revision 1.5.2.5  97/12/16  22:01:27  rvb
  124  * Oops add cfs_subr.h cfs_venus.h; sync with peter
  125  * 
  126  * Revision 1.5.2.4  97/12/16  12:40:05  rvb
  127  * Sync with 1.3
  128  * 
  129  * Revision 1.5.2.3  97/12/10  14:08:24  rvb
  130  * Fix O_ flags; check result in coda_call
  131  * 
  132  * Revision 1.5.2.2  97/12/10  11:40:24  rvb
  133  * No more ody
  134  * 
  135  * Revision 1.5.2.1  97/12/06  17:41:20  rvb
  136  * Sync with peters coda.h
  137  * 
  138  * Revision 1.5  97/12/05  10:39:16  rvb
  139  * Read CHANGES
  140  * 
  141  * Revision 1.4.18.9  97/12/05  08:58:07  rvb
  142  * peter found this one
  143  * 
  144  * Revision 1.4.18.8  97/11/26  15:28:57  rvb
  145  * Cant make downcall pbuf == union cfs_downcalls yet
  146  * 
  147  * Revision 1.4.18.7  97/11/25  09:40:49  rvb
  148  * Final cfs_venus.c w/o macros, but one locking bug
  149  * 
  150  * Revision 1.4.18.6  97/11/20  11:46:41  rvb
  151  * Capture current cfs_venus
  152  * 
  153  * Revision 1.4.18.5  97/11/18  10:27:15  rvb
  154  * cfs_nbsd.c is DEAD!!!; integrated into cfs_vf/vnops.c
  155  * cfs_nb_foo and cfs_foo are joined
  156  * 
  157  * Revision 1.4.18.4  97/11/13  22:02:59  rvb
  158  * pass2 cfs_NetBSD.h mt
  159  * 
  160  * Revision 1.4.18.3  97/11/12  12:09:38  rvb
  161  * reorg pass1
  162  * 
  163  * Revision 1.4.18.2  97/10/29  16:06:09  rvb
  164  * Kill DYING
  165  * 
  166  * Revision 1.4.18.1  1997/10/28 23:10:15  rvb
  167  * >64Meg; venus can be killed!
  168  *
  169  * Revision 1.4  1996/12/12 22:10:58  bnoble
  170  * Fixed the "downcall invokes venus operation" deadlock in all known cases.
  171  * There may be more
  172  *
  173  * Revision 1.3  1996/11/13 04:14:20  bnoble
  174  * Merging BNOBLE_WORK_6_20_96 into main line
  175  *
  176  * Revision 1.2.8.1  1996/08/22 14:25:04  bnoble
  177  * Added a return code from vc_nb_close
  178  *
  179  * Revision 1.2  1996/01/02 16:56:58  bnoble
  180  * Added support for Coda MiniCache and raw inode calls (final commit)
  181  *
  182  * Revision 1.1.2.1  1995/12/20 01:57:24  bnoble
  183  * Added CODA-specific files
  184  *
  185  * Revision 1.1  1995/03/14  20:52:15  bnoble
  186  * Initial revision
  187  *
  188  */
  189 
  190 /* These routines are the device entry points for Venus. */
  191 
  192 extern int coda_nc_initialized;    /* Set if cache has been initialized */
  193 
  194 #include <vcoda.h>
  195 
  196 #include <sys/param.h>
  197 #include <sys/systm.h>
  198 #include <sys/kernel.h>
  199 #include <sys/proc.h>
  200 #include <sys/malloc.h>
  201 #include <sys/mount.h>
  202 #include <sys/file.h>
  203 #include <sys/ioccom.h>
  204 #include <sys/poll.h>
  205 #include <sys/conf.h>
  206 
  207 #include <coda/coda.h>
  208 #include <coda/cnode.h>
  209 #include <coda/coda_namecache.h>
  210 #include <coda/coda_io.h>
  211 #include <coda/coda_psdev.h>
  212 
  213 #define CTL_C
  214 
  215 int coda_psdev_print_entry = 0;
  216 static
  217 int outstanding_upcalls = 0;
  218 int coda_call_sleep = PZERO - 1;
  219 #ifdef  CTL_C
  220 int coda_pcatch = PCATCH;
  221 #else
  222 #endif
  223 
  224 #define ENTRY if(coda_psdev_print_entry) myprintf(("Entered %s\n",__FUNCTION__))
  225 
  226 void vcodaattach(int n);
  227 
  228 struct vmsg {
  229     struct queue vm_chain;
  230     caddr_t      vm_data;
  231     u_short      vm_flags;
  232     u_short      vm_inSize;     /* Size is at most 5000 bytes */
  233     u_short      vm_outSize;
  234     u_short      vm_opcode;     /* copied from data to save ptr lookup */
  235     int          vm_unique;
  236     caddr_t      vm_sleep;      /* Not used by Mach. */
  237 };
  238 
  239 #define VM_READ     1
  240 #define VM_WRITE    2
  241 #define VM_INTR     4
  242 
  243 /* vcodaattach: do nothing */
  244 void
  245 vcodaattach(n)
  246     int n;
  247 {
  248 }
  249 
  250 int 
  251 vc_nb_open(dev, flag, mode, p)    
  252     dev_t        dev;      
  253     int          flag;     
  254     int          mode;     
  255     struct proc *p;             /* NetBSD only */
  256 {
  257     register struct vcomm *vcp;
  258     
  259     ENTRY;
  260 
  261     if (minor(dev) >= NVCODA || minor(dev) < 0)
  262         return(ENXIO);
  263     
  264     if (!coda_nc_initialized)
  265         coda_nc_init();
  266     
  267     vcp = &coda_mnttbl[minor(dev)].mi_vcomm;
  268     if (VC_OPEN(vcp))
  269         return(EBUSY);
  270     
  271     bzero(&(vcp->vc_selproc), sizeof (struct selinfo));
  272     INIT_QUEUE(vcp->vc_requests);
  273     INIT_QUEUE(vcp->vc_replys);
  274     MARK_VC_OPEN(vcp);
  275     
  276     coda_mnttbl[minor(dev)].mi_vfsp = NULL;
  277     coda_mnttbl[minor(dev)].mi_rootvp = NULL;
  278 
  279     return(0);
  280 }
  281 
  282 int 
  283 vc_nb_close (dev, flag, mode, p)    
  284     dev_t        dev;      
  285     int          flag;     
  286     int          mode;     
  287     struct proc *p;
  288 {
  289     register struct vcomm *vcp;
  290     register struct vmsg *vmp, *nvmp = NULL;
  291     struct coda_mntinfo *mi;
  292     int                 err;
  293         
  294     ENTRY;
  295 
  296     if (minor(dev) >= NVCODA || minor(dev) < 0)
  297         return(ENXIO);
  298 
  299     mi = &coda_mnttbl[minor(dev)];
  300     vcp = &(mi->mi_vcomm);
  301     
  302     if (!VC_OPEN(vcp))
  303         panic("vcclose: not open");
  304     
  305     /* prevent future operations on this vfs from succeeding by auto-
  306      * unmounting any vfs mounted via this device. This frees user or
  307      * sysadm from having to remember where all mount points are located.
  308      * Put this before WAKEUPs to avoid queuing new messages between
  309      * the WAKEUP and the unmount (which can happen if we're unlucky)
  310      */
  311     if (!mi->mi_rootvp) {
  312         /* just a simple open/close w no mount */
  313         MARK_VC_CLOSED(vcp);
  314         return 0;
  315     }
  316 
  317     /* Let unmount know this is for real */
  318     VTOC(mi->mi_rootvp)->c_flags |= C_UNMOUNTING;
  319     coda_unmounting(mi->mi_vfsp);
  320 
  321     outstanding_upcalls = 0;
  322     /* Wakeup clients so they can return. */
  323     for (vmp = (struct vmsg *)GETNEXT(vcp->vc_requests);
  324          !EOQ(vmp, vcp->vc_requests);
  325          vmp = nvmp)
  326     {
  327         nvmp = (struct vmsg *)GETNEXT(vmp->vm_chain);
  328         /* Free signal request messages and don't wakeup cause
  329            no one is waiting. */
  330         if (vmp->vm_opcode == CODA_SIGNAL) {
  331             CODA_FREE((caddr_t)vmp->vm_data, (u_int)VC_IN_NO_DATA);
  332             CODA_FREE((caddr_t)vmp, (u_int)sizeof(struct vmsg));
  333             continue;
  334         }
  335         outstanding_upcalls++;  
  336         wakeup(&vmp->vm_sleep);
  337     }
  338 
  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         outstanding_upcalls++;  
  344         wakeup(&vmp->vm_sleep);
  345     }
  346 
  347     MARK_VC_CLOSED(vcp);
  348 
  349     if (outstanding_upcalls) {
  350 #ifdef  CODA_VERBOSE
  351         printf("presleep: outstanding_upcalls = %d\n", outstanding_upcalls);
  352         (void) tsleep(&outstanding_upcalls, coda_call_sleep, "coda_umount", 0);
  353         printf("postsleep: outstanding_upcalls = %d\n", outstanding_upcalls);
  354 #else
  355         (void) tsleep(&outstanding_upcalls, coda_call_sleep, "coda_umount", 0);
  356 #endif
  357     }
  358 
  359     err = dounmount(mi->mi_vfsp, flag, p);
  360     if (err)
  361         myprintf(("Error %d unmounting vfs in vcclose(%d)\n", 
  362                    err, minor(dev)));
  363     return 0;
  364 }
  365 
  366 int 
  367 vc_nb_read(dev, uiop, flag)   
  368     dev_t        dev;  
  369     struct uio  *uiop; 
  370     int          flag;
  371 {
  372     register struct vcomm *     vcp;
  373     register struct vmsg *vmp;
  374     int error = 0;
  375     
  376     ENTRY;
  377 
  378     if (minor(dev) >= NVCODA || minor(dev) < 0)
  379         return(ENXIO);
  380     
  381     vcp = &coda_mnttbl[minor(dev)].mi_vcomm;
  382     /* Get message at head of request queue. */
  383     if (EMPTY(vcp->vc_requests))
  384         return(0);      /* Nothing to read */
  385     
  386     vmp = (struct vmsg *)GETNEXT(vcp->vc_requests);
  387     
  388     /* Move the input args into userspace */
  389     uiop->uio_rw = UIO_READ;
  390     error = uiomove(vmp->vm_data, vmp->vm_inSize, uiop);
  391     if (error) {
  392         myprintf(("vcread: error (%d) on uiomove\n", error));
  393         error = EINVAL;
  394     }
  395 
  396 #ifdef OLD_DIAGNOSTIC    
  397     if (vmp->vm_chain.forw == 0 || vmp->vm_chain.back == 0)
  398         panic("vc_nb_read: bad chain");
  399 #endif
  400 
  401     REMQUE(vmp->vm_chain);
  402     
  403     /* If request was a signal, free up the message and don't
  404        enqueue it in the reply queue. */
  405     if (vmp->vm_opcode == CODA_SIGNAL) {
  406         if (codadebug)
  407             myprintf(("vcread: signal msg (%d, %d)\n", 
  408                       vmp->vm_opcode, vmp->vm_unique));
  409         CODA_FREE((caddr_t)vmp->vm_data, (u_int)VC_IN_NO_DATA);
  410         CODA_FREE((caddr_t)vmp, (u_int)sizeof(struct vmsg));
  411         return(error);
  412     }
  413     
  414     vmp->vm_flags |= VM_READ;
  415     INSQUE(vmp->vm_chain, vcp->vc_replys);
  416     
  417     return(error);
  418 }
  419 
  420 int
  421 vc_nb_write(dev, uiop, flag)   
  422     dev_t        dev;  
  423     struct uio  *uiop; 
  424     int          flag;
  425 {
  426     register struct vcomm *     vcp;
  427     register struct vmsg *vmp;
  428     struct coda_out_hdr *out;
  429     u_long seq;
  430     u_long opcode;
  431     int buf[2];
  432     int error = 0;
  433 
  434     ENTRY;
  435 
  436     if (minor(dev) >= NVCODA || minor(dev) < 0)
  437         return(ENXIO);
  438     
  439     vcp = &coda_mnttbl[minor(dev)].mi_vcomm;
  440     
  441     /* Peek at the opcode, unique without transfering the data. */
  442     uiop->uio_rw = UIO_WRITE;
  443     error = uiomove((caddr_t)buf, sizeof(int) * 2, uiop);
  444     if (error) {
  445         myprintf(("vcwrite: error (%d) on uiomove\n", error));
  446         return(EINVAL);
  447     }
  448     
  449     opcode = buf[0];
  450     seq = buf[1];
  451         
  452     if (codadebug)
  453         myprintf(("vcwrite got a call for %ld.%ld\n", opcode, seq));
  454     
  455     if (DOWNCALL(opcode)) {
  456         union outputArgs pbuf;
  457         
  458         /* get the rest of the data. */
  459         uiop->uio_rw = UIO_WRITE;
  460         error = uiomove((caddr_t)&pbuf.coda_purgeuser.oh.result, sizeof(pbuf) - (sizeof(int)*2), uiop);
  461         if (error) {
  462             myprintf(("vcwrite: error (%d) on uiomove (Op %ld seq %ld)\n", 
  463                       error, opcode, seq));
  464             return(EINVAL);
  465             }
  466         
  467         return handleDownCall(opcode, &pbuf);
  468     }
  469     
  470     /* Look for the message on the (waiting for) reply queue. */
  471     for (vmp = (struct vmsg *)GETNEXT(vcp->vc_replys);
  472          !EOQ(vmp, vcp->vc_replys);
  473          vmp = (struct vmsg *)GETNEXT(vmp->vm_chain))
  474     {
  475         if (vmp->vm_unique == seq) break;
  476     }
  477     
  478     if (EOQ(vmp, vcp->vc_replys)) {
  479         if (codadebug)
  480             myprintf(("vcwrite: msg (%ld, %ld) not found\n", opcode, seq));
  481         
  482         return(ESRCH);
  483         }
  484     
  485     /* Remove the message from the reply queue */
  486     REMQUE(vmp->vm_chain);
  487     
  488     /* move data into response buffer. */
  489     out = (struct coda_out_hdr *)vmp->vm_data;
  490     /* Don't need to copy opcode and uniquifier. */
  491     
  492     /* get the rest of the data. */
  493     if (vmp->vm_outSize < uiop->uio_resid) {
  494         myprintf(("vcwrite: more data than asked for (%d < %d)\n",
  495                   vmp->vm_outSize, uiop->uio_resid));
  496         wakeup(&vmp->vm_sleep);         /* Notify caller of the error. */
  497         return(EINVAL);
  498     } 
  499     
  500     buf[0] = uiop->uio_resid;   /* Save this value. */
  501     uiop->uio_rw = UIO_WRITE;
  502     error = uiomove((caddr_t) &out->result, vmp->vm_outSize - (sizeof(int) * 2), uiop);
  503     if (error) {
  504         myprintf(("vcwrite: error (%d) on uiomove (op %ld seq %ld)\n", 
  505                   error, opcode, seq));
  506         return(EINVAL);
  507     }
  508     
  509     /* I don't think these are used, but just in case. */
  510     /* XXX - aren't these two already correct? -bnoble */
  511     out->opcode = opcode;
  512     out->unique = seq;
  513     vmp->vm_outSize     = buf[0];       /* Amount of data transferred? */
  514     vmp->vm_flags |= VM_WRITE;
  515     wakeup(&vmp->vm_sleep);
  516     
  517     return(0);
  518 }
  519 
  520 int
  521 vc_nb_ioctl(dev, cmd, addr, flag, p) 
  522     dev_t         dev;       
  523     u_long        cmd;       
  524     caddr_t       addr;      
  525     int           flag;      
  526     struct proc  *p;
  527 {
  528     ENTRY;
  529 
  530     switch(cmd) {
  531     case CODARESIZE: {
  532         struct coda_resize *data = (struct coda_resize *)addr;
  533         return(coda_nc_resize(data->hashsize, data->heapsize, IS_DOWNCALL));
  534         break;
  535     }
  536     case CODASTATS:
  537         if (coda_nc_use) {
  538             coda_nc_gather_stats();
  539             return(0);
  540         } else {
  541             return(ENODEV);
  542         }
  543         break;
  544     case CODAPRINT:
  545         if (coda_nc_use) {
  546             print_coda_nc();
  547             return(0);
  548         } else {
  549             return(ENODEV);
  550         }
  551         break;
  552     case CIOC_KERNEL_VERSION:
  553         switch (*(u_int *)addr) {
  554         case 0:
  555                 *(u_int *)addr = coda_kernel_version;
  556                 return 0;
  557                 break;
  558         case 1:
  559         case 2:
  560                 if (coda_kernel_version != *(u_int *)addr)
  561                     return ENOENT;
  562                 else
  563                     return 0;
  564         default:
  565                 return ENOENT;
  566         }
  567         break;
  568     default :
  569         return(EINVAL);
  570         break;
  571     }
  572 }
  573 
  574 int
  575 vc_nb_poll(dev, events, p)         
  576     dev_t         dev;    
  577     int           events;   
  578     struct proc  *p;
  579 {
  580     register struct vcomm *vcp;
  581     int event_msk = 0;
  582 
  583     ENTRY;
  584     
  585     if (minor(dev) >= NVCODA || minor(dev) < 0)
  586         return(ENXIO);
  587     
  588     vcp = &coda_mnttbl[minor(dev)].mi_vcomm;
  589     
  590     event_msk = events & (POLLIN|POLLRDNORM);
  591     if (!event_msk)
  592         return(0);
  593     
  594     if (!EMPTY(vcp->vc_requests))
  595         return(events & (POLLIN|POLLRDNORM));
  596 
  597     selrecord(p, &(vcp->vc_selproc));
  598     
  599     return(0);
  600 }
  601 
  602 /*
  603  * Statistics
  604  */
  605 struct coda_clstat coda_clstat;
  606 
  607 /* 
  608  * Key question: whether to sleep interuptably or uninteruptably when
  609  * waiting for Venus.  The former seems better (cause you can ^C a
  610  * job), but then GNU-EMACS completion breaks. Use tsleep with no
  611  * timeout, and no longjmp happens. But, when sleeping
  612  * "uninterruptibly", we don't get told if it returns abnormally
  613  * (e.g. kill -9).  
  614  */
  615 
  616 int
  617 coda_call(mntinfo, inSize, outSize, buffer) 
  618      struct coda_mntinfo *mntinfo; int inSize; int *outSize; caddr_t buffer;
  619 {
  620         struct vcomm *vcp;
  621         struct vmsg *vmp;
  622         int error;
  623 #ifdef  CTL_C
  624         struct proc *p = curproc;
  625         unsigned int psig_omask = p->p_sigmask;
  626         int i;
  627 #endif
  628         if (mntinfo == NULL) {
  629             /* Unlikely, but could be a race condition with a dying warden */
  630             return ENODEV;
  631         }
  632 
  633         vcp = &(mntinfo->mi_vcomm);
  634         
  635         coda_clstat.ncalls++;
  636         coda_clstat.reqs[((struct coda_in_hdr *)buffer)->opcode]++;
  637 
  638         if (!VC_OPEN(vcp))
  639             return(ENODEV);
  640 
  641         CODA_ALLOC(vmp,struct vmsg *,sizeof(struct vmsg));
  642         /* Format the request message. */
  643         vmp->vm_data = buffer;
  644         vmp->vm_flags = 0;
  645         vmp->vm_inSize = inSize;
  646         vmp->vm_outSize 
  647             = *outSize ? *outSize : inSize; /* |buffer| >= inSize */
  648         vmp->vm_opcode = ((struct coda_in_hdr *)buffer)->opcode;
  649         vmp->vm_unique = ++vcp->vc_seq;
  650         if (codadebug)
  651             myprintf(("Doing a call for %d.%d\n", 
  652                       vmp->vm_opcode, vmp->vm_unique));
  653         
  654         /* Fill in the common input args. */
  655         ((struct coda_in_hdr *)buffer)->unique = vmp->vm_unique;
  656 
  657         /* Append msg to request queue and poke Venus. */
  658         INSQUE(vmp->vm_chain, vcp->vc_requests);
  659         selwakeup(&(vcp->vc_selproc));
  660 
  661         /* We can be interrupted while we wait for Venus to process
  662          * our request.  If the interrupt occurs before Venus has read
  663          * the request, we dequeue and return. If it occurs after the
  664          * read but before the reply, we dequeue, send a signal
  665          * message, and return. If it occurs after the reply we ignore
  666          * it. In no case do we want to restart the syscall.  If it
  667          * was interrupted by a venus shutdown (vcclose), return
  668          * ENODEV.  */
  669 
  670         /* Ignore return, We have to check anyway */
  671 #ifdef  CTL_C
  672         /* This is work in progress.  Setting coda_pcatch lets tsleep reawaken
  673            on a ^c or ^z.  The problem is that emacs sets certain interrupts
  674            as SA_RESTART.  This means that we should exit sleep handle the
  675            "signal" and then go to sleep again.  Mostly this is done by letting
  676            the syscall complete and be restarted.  We are not idempotent and 
  677            can not do this.  A better solution is necessary.
  678          */
  679         i = 0;
  680         do {
  681             error = tsleep(&vmp->vm_sleep, (coda_call_sleep|coda_pcatch), "coda_call", hz*2);
  682             if (error == 0)
  683                 break;
  684             else if (error == EWOULDBLOCK) {
  685 #ifdef  CODA_VERBOSE
  686                     printf("coda_call: tsleep TIMEOUT %d sec\n", 2+2*i);
  687 #endif
  688             } else if (p->p_siglist == sigmask(SIGIO)) {
  689                     p->p_sigmask |= p->p_siglist;
  690 #ifdef  CODA_VERBOSE
  691                     printf("coda_call: tsleep returns %d SIGIO, cnt %d\n", error, i);
  692 #endif
  693             } else if (p->p_siglist == sigmask(SIGALRM)) {
  694                     p->p_sigmask |= p->p_siglist;
  695 #ifdef  CODA_VERBOSE
  696                     printf("coda_call: tsleep returns %d SIGALRM, cnt %d\n", error, i);
  697 #endif
  698             } else {
  699                     printf("coda_call: tsleep returns %d, cnt %d\n", error, i);
  700                     printf("coda_call: siglist = %x, sigmask = %x, mask %x\n",
  701                             p->p_siglist, p->p_sigmask,
  702                             p->p_siglist & ~p->p_sigmask);
  703                     break;
  704 #ifdef  notyet
  705                     p->p_sigmask |= p->p_siglist;
  706                     printf("coda_call: new mask, siglist = %x, sigmask = %x, mask %x\n",
  707                             p->p_siglist, p->p_sigmask,
  708                             p->p_siglist & ~p->p_sigmask);
  709 #endif
  710             }
  711         } while (error && i++ < 128 && VC_OPEN(vcp));
  712         p->p_sigmask = psig_omask;
  713 #else
  714         (void) tsleep(&vmp->vm_sleep, coda_call_sleep, "coda_call", 0);
  715 #endif
  716         if (VC_OPEN(vcp)) {     /* Venus is still alive */
  717         /* Op went through, interrupt or not... */
  718             if (vmp->vm_flags & VM_WRITE) {
  719                 error = 0;
  720                 *outSize = vmp->vm_outSize;
  721             }
  722 
  723             else if (!(vmp->vm_flags & VM_READ)) { 
  724                 /* Interrupted before venus read it. */
  725 #ifdef  CODA_VERBOSE
  726                 if (1)
  727 #else
  728                 if (codadebug)
  729 #endif
  730                     myprintf(("interrupted before read: op = %d.%d, flags = %x\n",
  731                            vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags));
  732                 REMQUE(vmp->vm_chain);
  733                 error = EINTR;
  734             }
  735             
  736             else {      
  737                 /* (!(vmp->vm_flags & VM_WRITE)) means interrupted after
  738                    upcall started */
  739                 /* Interrupted after start of upcall, send venus a signal */
  740                 struct coda_in_hdr *dog;
  741                 struct vmsg *svmp;
  742                 
  743 #ifdef  CODA_VERBOSE
  744                 if (1)
  745 #else
  746                 if (codadebug)
  747 #endif
  748                     myprintf(("Sending Venus a signal: op = %d.%d, flags = %x\n",
  749                            vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags));
  750                 
  751                 REMQUE(vmp->vm_chain);
  752                 error = EINTR;
  753                 
  754                 CODA_ALLOC(svmp, struct vmsg *, sizeof (struct vmsg));
  755 
  756                 CODA_ALLOC((svmp->vm_data), char *, sizeof (struct coda_in_hdr));
  757                 dog = (struct coda_in_hdr *)svmp->vm_data;
  758                 
  759                 svmp->vm_flags = 0;
  760                 dog->opcode = svmp->vm_opcode = CODA_SIGNAL;
  761                 dog->unique = svmp->vm_unique = vmp->vm_unique;
  762                 svmp->vm_inSize = sizeof (struct coda_in_hdr);
  763 /*??? rvb */    svmp->vm_outSize = sizeof (struct coda_in_hdr);
  764                 
  765                 if (codadebug)
  766                     myprintf(("coda_call: enqueing signal msg (%d, %d)\n",
  767                            svmp->vm_opcode, svmp->vm_unique));
  768                 
  769                 /* insert at head of queue! */
  770                 INSQUE(svmp->vm_chain, vcp->vc_requests);
  771                 selwakeup(&(vcp->vc_selproc));
  772             }
  773         }
  774 
  775         else {  /* If venus died (!VC_OPEN(vcp)) */
  776             if (codadebug)
  777                 myprintf(("vcclose woke op %d.%d flags %d\n",
  778                        vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags));
  779             
  780                 error = ENODEV;
  781         }
  782 
  783         CODA_FREE(vmp, sizeof(struct vmsg));
  784 
  785         if (outstanding_upcalls > 0 && (--outstanding_upcalls == 0))
  786                 wakeup(&outstanding_upcalls);
  787 
  788         if (!error)
  789                 error = ((struct coda_out_hdr *)buffer)->result;
  790         return(error);
  791 }

Cache object: 9b0e142f43cba7b998216fa5795deee6


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