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

Cache object: ad787916da722209f89c6d038275235e


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