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

Cache object: bc10dce224356c8244a570ebc50da069


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