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/fs/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 Coda's
   44  * Venus and Minicache in Mach 2.6. They used to be in cfs_subr.c, but I
   45  * moved them to make it easier to port the Minicache without porting coda.
   46  * -- DCS 10/12/94
   47  */
   48 
   49 /*
   50  * These routines are the device entry points for Venus.
   51  */
   52 
   53 #include <sys/cdefs.h>
   54 __FBSDID("$FreeBSD: releng/8.4/sys/fs/coda/coda_psdev.c 194990 2009-06-25 18:46:30Z kib $");
   55 
   56 #include <sys/param.h>
   57 #include <sys/systm.h>
   58 #include <sys/conf.h>
   59 #include <sys/ioccom.h>
   60 #include <sys/kernel.h>
   61 #include <sys/lock.h>
   62 #include <sys/malloc.h>
   63 #include <sys/file.h>           /* must come after sys/malloc.h */
   64 #include <sys/mount.h>
   65 #include <sys/mutex.h>
   66 #include <sys/poll.h>
   67 #include <sys/proc.h>
   68 #include <sys/filedesc.h>
   69 
   70 #include <fs/coda/coda.h>
   71 #include <fs/coda/cnode.h>
   72 #include <fs/coda/coda_io.h>
   73 #include <fs/coda/coda_psdev.h>
   74 
   75 /*
   76  * Variables to determine how Coda sleeps and whether or not it is
   77  * interruptible when it does sleep waiting for Venus.
   78  */
   79 /* #define      CTL_C */
   80 
   81 #ifdef CTL_C
   82 #include <sys/signalvar.h>
   83 #endif
   84 
   85 int coda_psdev_print_entry = 0;
   86 static int outstanding_upcalls = 0;
   87 int coda_call_sleep = PZERO - 1;
   88 #ifdef CTL_C
   89 int coda_pcatch = PCATCH;
   90 #else
   91 #endif
   92 
   93 #define ENTRY do {                                                      \
   94         if (coda_psdev_print_entry)                                     \
   95                 myprintf(("Entered %s\n", __func__));                   \
   96 } while (0)
   97 
   98 struct vmsg {
   99         TAILQ_ENTRY(vmsg)       vm_chain;
  100         caddr_t         vm_data;
  101         u_short         vm_flags;
  102         u_short         vm_inSize;      /* Size is at most 5000 bytes */
  103         u_short         vm_outSize;
  104         u_short         vm_opcode;      /* Copied from data to save ptr deref */
  105         int             vm_unique;
  106         caddr_t         vm_sleep;       /* Not used by Mach. */
  107 };
  108 
  109 #define VM_READ         1
  110 #define VM_WRITE        2
  111 #define VM_INTR         4               /* Unused. */
  112 
  113 int
  114 vc_open(struct cdev *dev, int flag, int mode, struct thread *td)
  115 {
  116         struct vcomm *vcp;
  117         struct coda_mntinfo *mnt;
  118 
  119         ENTRY;
  120         mnt = dev2coda_mntinfo(dev);
  121         KASSERT(mnt, ("Coda: tried to open uninitialized cfs device"));
  122         vcp = &mnt->mi_vcomm;
  123         if (VC_OPEN(vcp))
  124                 return (EBUSY);
  125         bzero(&(vcp->vc_selproc), sizeof (struct selinfo));
  126         TAILQ_INIT(&vcp->vc_requests);
  127         TAILQ_INIT(&vcp->vc_replies);
  128         MARK_VC_OPEN(vcp);
  129         mnt->mi_vfsp = NULL;
  130         mnt->mi_rootvp = NULL;
  131         return (0);
  132 }
  133 
  134 int
  135 vc_close(struct cdev *dev, int flag, int mode, struct thread *td)
  136 {
  137         struct vcomm *vcp;
  138         struct vmsg *vmp, *nvmp = NULL;
  139         struct coda_mntinfo *mi;
  140         int err;
  141 
  142         ENTRY;
  143         mi = dev2coda_mntinfo(dev);
  144         KASSERT(mi, ("Coda: closing unknown cfs device"));
  145         vcp = &mi->mi_vcomm;
  146         KASSERT(VC_OPEN(vcp), ("Coda: closing unopened cfs device"));
  147 
  148         /*
  149          * Prevent future operations on this vfs from succeeding by
  150          * auto-unmounting any vfs mounted via this device.  This frees user
  151          * or sysadm from having to remember where all mount points are
  152          * located.  Put this before WAKEUPs to avoid queuing new messages
  153          * between the WAKEUP and the unmount (which can happen if we're
  154          * unlucky).
  155          */
  156         if (mi->mi_rootvp == NULL) {
  157                 /*
  158                  * Just a simple open/close with no mount.
  159                  */
  160                 MARK_VC_CLOSED(vcp);
  161                 return (0);
  162         }
  163 
  164         /*
  165          * Let unmount know this is for real.
  166          */
  167         VTOC(mi->mi_rootvp)->c_flags |= C_UNMOUNTING;
  168         coda_unmounting(mi->mi_vfsp);
  169 
  170         /*
  171          * Wakeup clients so they can return.
  172          */
  173         outstanding_upcalls = 0;
  174         TAILQ_FOREACH_SAFE(vmp, &vcp->vc_requests, vm_chain, nvmp) {
  175                 /*
  176                  * Free signal request messages and don't wakeup cause no one
  177                  * is waiting.
  178                  */
  179                 if (vmp->vm_opcode == CODA_SIGNAL) {
  180                         CODA_FREE((caddr_t)vmp->vm_data,
  181                             (u_int)VC_IN_NO_DATA);
  182                         CODA_FREE((caddr_t)vmp, (u_int)sizeof(struct vmsg));
  183                         continue;
  184                 }
  185                 outstanding_upcalls++;
  186                 wakeup(&vmp->vm_sleep);
  187         }
  188         TAILQ_FOREACH(vmp, &vcp->vc_replies, vm_chain) {
  189                 outstanding_upcalls++;
  190                 wakeup(&vmp->vm_sleep);
  191         }
  192         MARK_VC_CLOSED(vcp);
  193         if (outstanding_upcalls) {
  194 #ifdef CODA_VERBOSE
  195                 printf("presleep: outstanding_upcalls = %d\n",
  196                     outstanding_upcalls);
  197 #endif
  198                 (void) tsleep(&outstanding_upcalls, coda_call_sleep,
  199                     "coda_umount", 0);
  200 #ifdef CODA_VERBOSE
  201                 printf("postsleep: outstanding_upcalls = %d\n",
  202                     outstanding_upcalls);
  203 #endif
  204         }
  205         err = dounmount(mi->mi_vfsp, flag, td);
  206         if (err)
  207                 myprintf(("Error %d unmounting vfs in vcclose(%s)\n", err,
  208                     devtoname(dev)));
  209         return (0);
  210 }
  211 
  212 int
  213 vc_read(struct cdev *dev, struct uio *uiop, int flag)
  214 {
  215         struct vcomm *vcp;
  216         struct vmsg *vmp;
  217         int error = 0;
  218 
  219         ENTRY;
  220         vcp = &dev2coda_mntinfo(dev)->mi_vcomm;
  221 
  222         /*
  223          * Get message at head of request queue.
  224          */
  225         vmp = TAILQ_FIRST(&vcp->vc_requests);
  226         if (vmp == NULL)
  227                 return (0);     /* Nothing to read */
  228 
  229         /*
  230          * Move the input args into userspace.
  231          *
  232          * XXXRW: This is not safe in the presence of >1 reader, as vmp is
  233          * still on the head of the list.
  234          */
  235         uiop->uio_rw = UIO_READ;
  236         error = uiomove(vmp->vm_data, vmp->vm_inSize, uiop);
  237         if (error) {
  238                 myprintf(("vcread: error (%d) on uiomove\n", error));
  239                 error = EINVAL;
  240         }
  241         TAILQ_REMOVE(&vcp->vc_requests, vmp, vm_chain);
  242 
  243         /*
  244          * If request was a signal, free up the message and don't enqueue it
  245          * in the reply queue.
  246          */
  247         if (vmp->vm_opcode == CODA_SIGNAL) {
  248                 if (codadebug)
  249                         myprintf(("vcread: signal msg (%d, %d)\n",
  250                             vmp->vm_opcode, vmp->vm_unique));
  251                 CODA_FREE((caddr_t)vmp->vm_data, (u_int)VC_IN_NO_DATA);
  252                 CODA_FREE((caddr_t)vmp, (u_int)sizeof(struct vmsg));
  253                 return (error);
  254         }
  255         vmp->vm_flags |= VM_READ;
  256         TAILQ_INSERT_TAIL(&vcp->vc_replies, vmp, vm_chain);
  257         return (error);
  258 }
  259 
  260 int
  261 vc_write(struct cdev *dev, struct uio *uiop, int flag)
  262 {
  263         struct vcomm *vcp;
  264         struct vmsg *vmp;
  265         struct coda_out_hdr *out;
  266         u_long seq;
  267         u_long opcode;
  268         int buf[2];
  269         int error = 0;
  270 
  271         ENTRY;
  272         vcp = &dev2coda_mntinfo(dev)->mi_vcomm;
  273 
  274         /*
  275          * Peek at the opcode, unique without transfering the data.
  276          */
  277         uiop->uio_rw = UIO_WRITE;
  278         error = uiomove((caddr_t)buf, sizeof(int) * 2, uiop);
  279         if (error) {
  280                 myprintf(("vcwrite: error (%d) on uiomove\n", error));
  281                 return (EINVAL);
  282         }
  283         opcode = buf[0];
  284         seq = buf[1];
  285         if (codadebug)
  286                 myprintf(("vcwrite got a call for %ld.%ld\n", opcode, seq));
  287         if (DOWNCALL(opcode)) {
  288                 union outputArgs pbuf;
  289 
  290                 /*
  291                  * Get the rest of the data.
  292                  */
  293                 uiop->uio_rw = UIO_WRITE;
  294                 error = uiomove((caddr_t)&pbuf.coda_purgeuser.oh.result,
  295                     sizeof(pbuf) - (sizeof(int)*2), uiop);
  296                 if (error) {
  297                         myprintf(("vcwrite: error (%d) on uiomove (Op %ld "
  298                             "seq %ld)\n", error, opcode, seq));
  299                         return (EINVAL);
  300                 }
  301                 return (handleDownCall(dev2coda_mntinfo(dev), opcode, &pbuf));
  302         }
  303 
  304         /*
  305          * Look for the message on the (waiting for) reply queue.
  306          */
  307         TAILQ_FOREACH(vmp, &vcp->vc_replies, vm_chain) {
  308                 if (vmp->vm_unique == seq)
  309                         break;
  310         }
  311         if (vmp == NULL) {
  312                 if (codadebug)
  313                         myprintf(("vcwrite: msg (%ld, %ld) not found\n",
  314                             opcode, seq));
  315                 return (ESRCH);
  316         }
  317 
  318         /*
  319          * Remove the message from the reply queue.
  320          */
  321         TAILQ_REMOVE(&vcp->vc_replies, vmp, vm_chain);
  322 
  323         /*
  324          * Move data into response buffer.
  325          */
  326         out = (struct coda_out_hdr *)vmp->vm_data;
  327 
  328         /*
  329          * Don't need to copy opcode and uniquifier.
  330          *
  331          * Get the rest of the data.
  332          */
  333         if (vmp->vm_outSize < uiop->uio_resid) {
  334                 myprintf(("vcwrite: more data than asked for (%d < %zd)\n",
  335                     vmp->vm_outSize, uiop->uio_resid));
  336 
  337                 /*
  338                  * Notify caller of the error.
  339                  */
  340                 wakeup(&vmp->vm_sleep);
  341                 return (EINVAL);
  342         }
  343 
  344         /*
  345          * Save the value.
  346          */
  347         buf[0] = uiop->uio_resid;
  348         uiop->uio_rw = UIO_WRITE;
  349         error = uiomove((caddr_t) &out->result, vmp->vm_outSize -
  350             (sizeof(int) * 2), uiop);
  351         if (error) {
  352                 myprintf(("vcwrite: error (%d) on uiomove (op %ld seq %ld)\n",
  353                     error, opcode, seq));
  354                 return (EINVAL);
  355         }
  356 
  357         /*
  358          * I don't think these are used, but just in case.
  359          *
  360          * XXX - aren't these two already correct? -bnoble
  361          */
  362         out->opcode = opcode;
  363         out->unique = seq;
  364         vmp->vm_outSize = buf[0];       /* Amount of data transferred? */
  365         vmp->vm_flags |= VM_WRITE;
  366         error = 0;
  367         if (opcode == CODA_OPEN_BY_FD) {
  368                 struct coda_open_by_fd_out *tmp =
  369                     (struct coda_open_by_fd_out *)out;
  370                 struct file *fp;
  371                 struct vnode *vp = NULL;
  372 
  373                 if (tmp->oh.result == 0) {
  374                         error = getvnode(uiop->uio_td->td_proc->p_fd,
  375                             tmp->fd, &fp);
  376                         if (!error) {
  377                                 /*
  378                                  * XXX: Since the whole driver runs with
  379                                  * Giant, don't actually need to acquire it
  380                                  * explicitly here yet.
  381                                  */
  382                                 mtx_lock(&Giant);
  383                                 vp = fp->f_vnode;
  384                                 VREF(vp);
  385                                 fdrop(fp, uiop->uio_td);
  386                                 mtx_unlock(&Giant);
  387                         }
  388                 }
  389                 tmp->vp = vp;
  390         }
  391         wakeup(&vmp->vm_sleep);
  392         return (error);
  393 }
  394 
  395 int
  396 vc_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
  397     struct thread *t)
  398 {
  399 
  400         ENTRY;
  401         switch(cmd) {
  402         case CODARESIZE:
  403                 return (ENODEV);
  404 
  405         case CODASTATS:
  406                 return (ENODEV);
  407 
  408         case CODAPRINT:
  409                 return (ENODEV);
  410 
  411         case CIOC_KERNEL_VERSION:
  412                 switch (*(u_int *)addr) {
  413                 case 0:
  414                         *(u_int *)addr = coda_kernel_version;
  415                         return (0);
  416 
  417                 case 1:
  418                 case 2:
  419                         if (coda_kernel_version != *(u_int *)addr)
  420                                 return (ENOENT);
  421                         else
  422                                 return (0);
  423 
  424                 default:
  425                         return (ENOENT);
  426                 }
  427 
  428         default:
  429                 return (EINVAL);
  430         }
  431 }
  432 
  433 int
  434 vc_poll(struct cdev *dev, int events, struct thread *td)
  435 {
  436         struct vcomm *vcp;
  437         int event_msk = 0;
  438 
  439         ENTRY;
  440         vcp = &dev2coda_mntinfo(dev)->mi_vcomm;
  441         event_msk = events & (POLLIN|POLLRDNORM);
  442         if (!event_msk)
  443                 return (0);
  444         if (!TAILQ_EMPTY(&vcp->vc_requests))
  445                 return (events & (POLLIN|POLLRDNORM));
  446         selrecord(td, &(vcp->vc_selproc));
  447         return (0);
  448 }
  449 
  450 /*
  451  * Statistics.
  452  */
  453 struct coda_clstat coda_clstat;
  454 
  455 /*
  456  * Key question: whether to sleep interuptably or uninteruptably when waiting
  457  * for Venus.  The former seems better (cause you can ^C a job), but then
  458  * GNU-EMACS completion breaks.  Use tsleep with no timeout, and no longjmp
  459  * happens.  But, when sleeping "uninterruptibly", we don't get told if it
  460  * returns abnormally (e.g. kill -9).
  461  */
  462 int
  463 coda_call(struct coda_mntinfo *mntinfo, int inSize, int *outSize,
  464     caddr_t buffer)
  465 {
  466         struct vcomm *vcp;
  467         struct vmsg *vmp;
  468         int error;
  469 #ifdef CTL_C
  470         struct thread *td = curthread;
  471         struct proc *p = td->td_proc;
  472         sigset_t psig_omask;
  473         sigset_t tempset;
  474         int i;
  475 #endif
  476 
  477         /*
  478          * Unlikely, but could be a race condition with a dying warden.
  479          */
  480         if (mntinfo == NULL)
  481                 return ENODEV;
  482         vcp = &(mntinfo->mi_vcomm);
  483         coda_clstat.ncalls++;
  484         coda_clstat.reqs[((struct coda_in_hdr *)buffer)->opcode]++;
  485         if (!VC_OPEN(vcp))
  486                 return (ENODEV);
  487         CODA_ALLOC(vmp,struct vmsg *,sizeof(struct vmsg));
  488 
  489         /*
  490          * Format the request message.
  491          */
  492         vmp->vm_data = buffer;
  493         vmp->vm_flags = 0;
  494         vmp->vm_inSize = inSize;
  495         vmp->vm_outSize
  496             = *outSize ? *outSize : inSize; /* |buffer| >= inSize */
  497         vmp->vm_opcode = ((struct coda_in_hdr *)buffer)->opcode;
  498         vmp->vm_unique = ++vcp->vc_seq;
  499         if (codadebug)
  500                 myprintf(("Doing a call for %d.%d\n", vmp->vm_opcode,
  501                     vmp->vm_unique));
  502 
  503         /*
  504          * Fill in the common input args.
  505          */
  506         ((struct coda_in_hdr *)buffer)->unique = vmp->vm_unique;
  507 
  508         /*
  509          * Append msg to request queue and poke Venus.
  510          */
  511         TAILQ_INSERT_TAIL(&vcp->vc_requests, vmp, vm_chain);
  512         selwakeuppri(&(vcp->vc_selproc), coda_call_sleep);
  513 
  514         /*
  515          * We can be interrupted while we wait for Venus to process our
  516          * request.  If the interrupt occurs before Venus has read the
  517          * request, we dequeue and return. If it occurs after the read but
  518          * before the reply, we dequeue, send a signal message, and return.
  519          * If it occurs after the reply we ignore it.  In no case do we want
  520          * to restart the syscall.  If it was interrupted by a venus shutdown
  521          * (vcclose), return ENODEV.
  522          *
  523          * Ignore return, we have to check anyway.
  524          */
  525 #ifdef CTL_C
  526         /*
  527          * This is work in progress.  Setting coda_pcatch lets tsleep
  528          * reawaken on a ^c or ^z.  The problem is that emacs sets certain
  529          * interrupts as SA_RESTART.  This means that we should exit sleep
  530          * handle the "signal" and then go to sleep again.  Mostly this is
  531          * done by letting the syscall complete and be restarted.  We are not
  532          * idempotent and can not do this.  A better solution is necessary.
  533          */
  534         i = 0;
  535         PROC_LOCK(p);
  536         psig_omask = td->td_sigmask;
  537         do {
  538                 error = msleep(&vmp->vm_sleep, &p->p_mtx,
  539                     (coda_call_sleep|coda_pcatch), "coda_call", hz*2);
  540                 if (error == 0)
  541                         break;
  542                 else if (error == EWOULDBLOCK) {
  543 #ifdef CODA_VERBOSE
  544                         printf("coda_call: tsleep TIMEOUT %d sec\n", 2+2*i);
  545 #endif
  546                 }
  547                 else {
  548                         SIGEMPTYSET(tempset);
  549                         SIGADDSET(tempset, SIGIO);
  550                         if (SIGSETEQ(td->td_siglist, tempset)) {
  551                                 SIGADDSET(td->td_sigmask, SIGIO);
  552 #ifdef CODA_VERBOSE
  553                                 printf("coda_call: tsleep returns %d SIGIO, "
  554                                     "cnt %d\n", error, i);
  555 #endif
  556                         } else {
  557                                 SIGDELSET(tempset, SIGIO);
  558                                 SIGADDSET(tempset, SIGALRM);
  559                                 if (SIGSETEQ(td->td_siglist, tempset)) {
  560                                         SIGADDSET(td->td_sigmask, SIGALRM);
  561 #ifdef CODA_VERBOSE
  562                                         printf("coda_call: tsleep returns "
  563                                             "%d SIGALRM, cnt %d\n", error, i);
  564 #endif
  565                                 } else {
  566 #ifdef CODA_VERBOSE
  567                                         printf("coda_call: tsleep returns "
  568                                             "%d, cnt %d\n", error, i);
  569 #endif
  570 
  571 #ifdef notyet
  572                                         tempset = td->td_siglist;
  573                                         SIGSETNAND(tempset, td->td_sigmask);
  574                                         printf("coda_call: siglist = %p, "
  575                                             "sigmask = %p, mask %p\n",
  576                                             td->td_siglist, td->td_sigmask,
  577                                             tempset);
  578                                         break;
  579                                         SIGSETOR(td->td_sigmask, td->td_siglist);
  580                                         tempset = td->td_siglist;
  581                                         SIGSETNAND(tempset, td->td_sigmask);
  582                                         printf("coda_call: new mask, "
  583                                             "siglist = %p, sigmask = %p, "
  584                                             "mask %p\n", td->td_siglist,
  585                                             td->td_sigmask, tempset);
  586 #endif
  587                                 }
  588                         }
  589                 }
  590         } while (error && i++ < 128 && VC_OPEN(vcp));
  591         td->td_sigmask = psig_omask;
  592         signotify(td);
  593         PROC_UNLOCK(p);
  594 #else
  595         (void)tsleep(&vmp->vm_sleep, coda_call_sleep, "coda_call", 0);
  596 #endif
  597         if (VC_OPEN(vcp)) {
  598                 /*
  599                  * Venus is still alive.
  600                  *
  601                  * Op went through, interrupt or not...
  602                  */
  603                 if (vmp->vm_flags & VM_WRITE) {
  604                         error = 0;
  605                         *outSize = vmp->vm_outSize;
  606                 } else if (!(vmp->vm_flags & VM_READ)) {
  607                         /* Interrupted before venus read it. */
  608 #ifdef CODA_VERBOSE
  609                         if (1)
  610 #else
  611                         if (codadebug)
  612 #endif
  613                                 myprintf(("interrupted before read: op = "
  614                                     "%d.%d, flags = %x\n", vmp->vm_opcode,
  615                                     vmp->vm_unique, vmp->vm_flags));
  616                         TAILQ_REMOVE(&vcp->vc_requests, vmp, vm_chain);
  617                         error = EINTR;
  618                 } else {
  619                         /*
  620                          * (!(vmp->vm_flags & VM_WRITE)) means interrupted
  621                          * after upcall started.
  622                          *
  623                          * Interrupted after start of upcall, send venus a
  624                          * signal.
  625                          */
  626                         struct coda_in_hdr *dog;
  627                         struct vmsg *svmp;
  628 
  629 #ifdef CODA_VERBOSE
  630                         if (1)
  631 #else
  632                         if (codadebug)
  633 #endif
  634                                 myprintf(("Sending Venus a signal: op = "
  635                                     "%d.%d, flags = %x\n", vmp->vm_opcode,
  636                                     vmp->vm_unique, vmp->vm_flags));
  637                         TAILQ_REMOVE(&vcp->vc_requests, vmp, vm_chain);
  638                         error = EINTR;
  639                         CODA_ALLOC(svmp, struct vmsg *, sizeof(struct vmsg));
  640                         CODA_ALLOC((svmp->vm_data), char *,
  641                             sizeof(struct coda_in_hdr));
  642                         dog = (struct coda_in_hdr *)svmp->vm_data;
  643                         svmp->vm_flags = 0;
  644                         dog->opcode = svmp->vm_opcode = CODA_SIGNAL;
  645                         dog->unique = svmp->vm_unique = vmp->vm_unique;
  646                         svmp->vm_inSize = sizeof (struct coda_in_hdr);
  647 /*??? rvb */            svmp->vm_outSize = sizeof (struct coda_in_hdr);
  648                         if (codadebug)
  649                                 myprintf(("coda_call: enqueing signal msg "
  650                                     "(%d, %d)\n", svmp->vm_opcode,
  651                                     svmp->vm_unique));
  652 
  653                         /*
  654                          * Insert at head of queue!
  655                          *
  656                          * XXXRW: Actually, the tail.
  657                          */
  658                         TAILQ_INSERT_TAIL(&vcp->vc_requests, svmp, vm_chain);
  659                         selwakeuppri(&(vcp->vc_selproc), coda_call_sleep);
  660                 }
  661         } else {
  662                 /* If venus died (!VC_OPEN(vcp)) */
  663                 if (codadebug)
  664                         myprintf(("vcclose woke op %d.%d flags %d\n",
  665                             vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags));
  666                 error = ENODEV;
  667         }
  668         CODA_FREE(vmp, sizeof(struct vmsg));
  669         if (outstanding_upcalls > 0 && (--outstanding_upcalls == 0))
  670                 wakeup(&outstanding_upcalls);
  671         if (!error)
  672                 error = ((struct coda_out_hdr *)buffer)->result;
  673         return (error);
  674 }

Cache object: ff098e1479d1fd7e2b12fec203a8a666


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