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
   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$");
   53 
   54 #include <sys/param.h>
   55 #include <sys/systm.h>
   56 #include <sys/ioccom.h>
   57 #include <sys/kernel.h>
   58 #include <sys/lock.h>
   59 #include <sys/malloc.h>
   60 #include <sys/file.h>           /* must come after sys/malloc.h */
   61 #include <sys/mount.h>
   62 #include <sys/mutex.h>
   63 #include <sys/poll.h>
   64 #include <sys/proc.h>
   65 #include <sys/filedesc.h>
   66 
   67 #include <fs/coda/coda.h>
   68 #include <fs/coda/cnode.h>
   69 #include <fs/coda/coda_namecache.h>
   70 #include <fs/coda/coda_io.h>
   71 #include <fs/coda/coda_psdev.h>
   72 
   73 #define CTL_C
   74 
   75 #ifdef CTL_C
   76 #include <sys/signalvar.h>
   77 #endif
   78 
   79 int coda_psdev_print_entry = 0;
   80 static
   81 int outstanding_upcalls = 0;
   82 int coda_call_sleep = PZERO - 1;
   83 #ifdef  CTL_C
   84 int coda_pcatch = PCATCH;
   85 #else
   86 #endif
   87 
   88 #define ENTRY if(coda_psdev_print_entry) myprintf(("Entered %s\n",__func__))
   89 
   90 void vcodaattach(int n);
   91 
   92 struct vmsg {
   93     struct queue vm_chain;
   94     caddr_t      vm_data;
   95     u_short      vm_flags;
   96     u_short      vm_inSize;     /* Size is at most 5000 bytes */
   97     u_short      vm_outSize;
   98     u_short      vm_opcode;     /* copied from data to save ptr lookup */
   99     int          vm_unique;
  100     caddr_t      vm_sleep;      /* Not used by Mach. */
  101 };
  102 
  103 #define VM_READ     1
  104 #define VM_WRITE    2
  105 #define VM_INTR     4
  106 
  107 /* vcodaattach: do nothing */
  108 void
  109 vcodaattach(n)
  110     int n;
  111 {
  112 }
  113 
  114 int 
  115 vc_nb_open(dev, flag, mode, td)    
  116     struct cdev *dev;      
  117     int          flag;     
  118     int          mode;     
  119     struct thread *td;             /* NetBSD only */
  120 {
  121     struct vcomm *vcp;
  122     struct coda_mntinfo *mnt;
  123     
  124     ENTRY;
  125 
  126     if (!coda_nc_initialized)
  127         coda_nc_init();
  128     
  129     mnt = dev2coda_mntinfo(dev);
  130     KASSERT(mnt, ("Coda: tried to open uninitialized cfs device"));
  131 
  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     KASSERT(mi, ("Coda: closing unknown cfs device"));
  163 
  164     vcp = &mi->mi_vcomm;
  165     KASSERT(VC_OPEN(vcp), ("Coda: closing unopened cfs device"));
  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 
  372     error = 0;
  373     if (opcode == CODA_OPEN_BY_FD) {
  374         struct coda_open_by_fd_out *tmp = (struct coda_open_by_fd_out *)out;
  375         struct file *fp;
  376         struct vnode *vp = NULL;
  377 
  378         if (tmp->oh.result == 0) {
  379             error = getvnode(uiop->uio_td->td_proc->p_fd, tmp->fd, &fp);
  380             if (!error) {
  381                 mtx_lock(&Giant);
  382                 vp = fp->f_vnode;
  383                 VREF(vp);
  384                 fdrop(fp, uiop->uio_td);
  385                 mtx_unlock(&Giant);
  386             }
  387         }
  388         tmp->vp = vp;
  389     }
  390 
  391     wakeup(&vmp->vm_sleep);
  392     
  393     return(error);
  394 }
  395 
  396 int
  397 vc_nb_ioctl(dev, cmd, addr, flag, td) 
  398     struct cdev *dev;       
  399     u_long        cmd;       
  400     caddr_t       addr;      
  401     int           flag;      
  402     struct thread *td;
  403 {
  404     ENTRY;
  405 
  406     switch(cmd) {
  407     case CODARESIZE: {
  408         struct coda_resize *data = (struct coda_resize *)addr;
  409         return(coda_nc_resize(data->hashsize, data->heapsize, IS_DOWNCALL));
  410         break;
  411     }
  412     case CODASTATS:
  413         if (coda_nc_use) {
  414             coda_nc_gather_stats();
  415             return(0);
  416         } else {
  417             return(ENODEV);
  418         }
  419         break;
  420     case CODAPRINT:
  421         if (coda_nc_use) {
  422             print_coda_nc();
  423             return(0);
  424         } else {
  425             return(ENODEV);
  426         }
  427         break;
  428     case CIOC_KERNEL_VERSION:
  429         switch (*(u_int *)addr) {
  430         case 0:
  431                 *(u_int *)addr = coda_kernel_version;
  432                 return 0;
  433                 break;
  434         case 1:
  435         case 2:
  436                 if (coda_kernel_version != *(u_int *)addr)
  437                     return ENOENT;
  438                 else
  439                     return 0;
  440         default:
  441                 return ENOENT;
  442         }
  443         break;
  444     default :
  445         return(EINVAL);
  446         break;
  447     }
  448 }
  449 
  450 int
  451 vc_nb_poll(dev, events, td)         
  452     struct cdev *dev;    
  453     int           events;   
  454     struct thread *td;
  455 {
  456     register struct vcomm *vcp;
  457     int event_msk = 0;
  458 
  459     ENTRY;
  460     
  461     vcp = &dev2coda_mntinfo(dev)->mi_vcomm;
  462     
  463     event_msk = events & (POLLIN|POLLRDNORM);
  464     if (!event_msk)
  465         return(0);
  466     
  467     if (!EMPTY(vcp->vc_requests))
  468         return(events & (POLLIN|POLLRDNORM));
  469 
  470     selrecord(td, &(vcp->vc_selproc));
  471     
  472     return(0);
  473 }
  474 
  475 /*
  476  * Statistics
  477  */
  478 struct coda_clstat coda_clstat;
  479 
  480 /* 
  481  * Key question: whether to sleep interuptably or uninteruptably when
  482  * waiting for Venus.  The former seems better (cause you can ^C a
  483  * job), but then GNU-EMACS completion breaks. Use tsleep with no
  484  * timeout, and no longjmp happens. But, when sleeping
  485  * "uninterruptibly", we don't get told if it returns abnormally
  486  * (e.g. kill -9).  
  487  */
  488 
  489 int
  490 coda_call(mntinfo, inSize, outSize, buffer) 
  491      struct coda_mntinfo *mntinfo; int inSize; int *outSize; caddr_t buffer;
  492 {
  493         struct vcomm *vcp;
  494         struct vmsg *vmp;
  495         int error;
  496 #ifdef  CTL_C
  497         struct thread *td = curthread;
  498         struct proc *p = td->td_proc;
  499         sigset_t psig_omask;
  500         sigset_t tempset;
  501         int i;
  502 #endif
  503         if (mntinfo == NULL) {
  504             /* Unlikely, but could be a race condition with a dying warden */
  505             return ENODEV;
  506         }
  507 
  508         vcp = &(mntinfo->mi_vcomm);
  509         
  510         coda_clstat.ncalls++;
  511         coda_clstat.reqs[((struct coda_in_hdr *)buffer)->opcode]++;
  512 
  513         if (!VC_OPEN(vcp))
  514             return(ENODEV);
  515 
  516         CODA_ALLOC(vmp,struct vmsg *,sizeof(struct vmsg));
  517         /* Format the request message. */
  518         vmp->vm_data = buffer;
  519         vmp->vm_flags = 0;
  520         vmp->vm_inSize = inSize;
  521         vmp->vm_outSize 
  522             = *outSize ? *outSize : inSize; /* |buffer| >= inSize */
  523         vmp->vm_opcode = ((struct coda_in_hdr *)buffer)->opcode;
  524         vmp->vm_unique = ++vcp->vc_seq;
  525         if (codadebug)
  526             myprintf(("Doing a call for %d.%d\n", 
  527                       vmp->vm_opcode, vmp->vm_unique));
  528         
  529         /* Fill in the common input args. */
  530         ((struct coda_in_hdr *)buffer)->unique = vmp->vm_unique;
  531 
  532         /* Append msg to request queue and poke Venus. */
  533         INSQUE(vmp->vm_chain, vcp->vc_requests);
  534         selwakeuppri(&(vcp->vc_selproc), coda_call_sleep);
  535 
  536         /* We can be interrupted while we wait for Venus to process
  537          * our request.  If the interrupt occurs before Venus has read
  538          * the request, we dequeue and return. If it occurs after the
  539          * read but before the reply, we dequeue, send a signal
  540          * message, and return. If it occurs after the reply we ignore
  541          * it. In no case do we want to restart the syscall.  If it
  542          * was interrupted by a venus shutdown (vcclose), return
  543          * ENODEV.  */
  544 
  545         /* Ignore return, We have to check anyway */
  546 #ifdef  CTL_C
  547         /* This is work in progress.  Setting coda_pcatch lets tsleep reawaken
  548            on a ^c or ^z.  The problem is that emacs sets certain interrupts
  549            as SA_RESTART.  This means that we should exit sleep handle the
  550            "signal" and then go to sleep again.  Mostly this is done by letting
  551            the syscall complete and be restarted.  We are not idempotent and 
  552            can not do this.  A better solution is necessary.
  553          */
  554         i = 0;
  555         PROC_LOCK(p);
  556         psig_omask = td->td_sigmask;
  557         do {
  558                 error = msleep(&vmp->vm_sleep, &p->p_mtx,
  559                                (coda_call_sleep|coda_pcatch), "coda_call",
  560                                hz*2);
  561                 if (error == 0)
  562                         break;
  563                 else if (error == EWOULDBLOCK) {
  564 #ifdef  CODA_VERBOSE
  565                         printf("coda_call: tsleep TIMEOUT %d sec\n", 2+2*i);
  566 #endif
  567                 }
  568                 else {
  569                         SIGEMPTYSET(tempset);
  570                         SIGADDSET(tempset, SIGIO);
  571                         if (SIGSETEQ(td->td_siglist, tempset)) {
  572                                 SIGADDSET(td->td_sigmask, SIGIO);
  573 #ifdef  CODA_VERBOSE
  574                                 printf("coda_call: tsleep returns %d SIGIO, cnt %d\n",
  575                                        error, i);
  576 #endif
  577                         } else {
  578                                 SIGDELSET(tempset, SIGIO);
  579                                 SIGADDSET(tempset, SIGALRM);
  580                                 if (SIGSETEQ(td->td_siglist, tempset)) {
  581                                         SIGADDSET(td->td_sigmask, SIGALRM);
  582 #ifdef  CODA_VERBOSE
  583                                         printf("coda_call: tsleep returns %d SIGALRM, cnt %d\n",
  584                                                error, i);
  585 #endif
  586                                 }
  587                                 else {
  588 #ifdef  CODA_VERBOSE
  589                                         printf("coda_call: tsleep returns %d, cnt %d\n",
  590                                                error, i);
  591 #endif
  592 
  593 #ifdef notyet
  594                                         tempset = td->td_siglist;
  595                                         SIGSETNAND(tempset, td->td_sigmask);
  596                                         printf("coda_call: siglist = %p, sigmask = %p, mask %p\n",
  597                                                td->td_siglist, td->td_sigmask,
  598                                                tempset);
  599                                         break;
  600                                         SIGSETOR(td->td_sigmask, td->td_siglist);
  601                                         tempset = td->td_siglist;
  602                                         SIGSETNAND(tempset, td->td_sigmask);
  603                                         printf("coda_call: new mask, siglist = %p, sigmask = %p, mask %p\n",
  604                                                td->td_siglist, td->td_sigmask,
  605                                                tempset);
  606 #endif
  607                                 }
  608                         }
  609                 }
  610         } while (error && i++ < 128 && VC_OPEN(vcp));
  611         td->td_sigmask = psig_omask;
  612         signotify(td);
  613         PROC_UNLOCK(p);
  614 #else
  615         (void) tsleep(&vmp->vm_sleep, coda_call_sleep, "coda_call", 0);
  616 #endif
  617         if (VC_OPEN(vcp)) {     /* Venus is still alive */
  618         /* Op went through, interrupt or not... */
  619             if (vmp->vm_flags & VM_WRITE) {
  620                 error = 0;
  621                 *outSize = vmp->vm_outSize;
  622             }
  623 
  624             else if (!(vmp->vm_flags & VM_READ)) { 
  625                 /* Interrupted before venus read it. */
  626 #ifdef  CODA_VERBOSE
  627                 if (1)
  628 #else
  629                 if (codadebug)
  630 #endif
  631                     myprintf(("interrupted before read: op = %d.%d, flags = %x\n",
  632                            vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags));
  633                 REMQUE(vmp->vm_chain);
  634                 error = EINTR;
  635             }
  636             
  637             else {      
  638                 /* (!(vmp->vm_flags & VM_WRITE)) means interrupted after
  639                    upcall started */
  640                 /* Interrupted after start of upcall, send venus a signal */
  641                 struct coda_in_hdr *dog;
  642                 struct vmsg *svmp;
  643                 
  644 #ifdef  CODA_VERBOSE
  645                 if (1)
  646 #else
  647                 if (codadebug)
  648 #endif
  649                     myprintf(("Sending Venus a signal: op = %d.%d, flags = %x\n",
  650                            vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags));
  651                 
  652                 REMQUE(vmp->vm_chain);
  653                 error = EINTR;
  654                 
  655                 CODA_ALLOC(svmp, struct vmsg *, sizeof (struct vmsg));
  656 
  657                 CODA_ALLOC((svmp->vm_data), char *, sizeof (struct coda_in_hdr));
  658                 dog = (struct coda_in_hdr *)svmp->vm_data;
  659                 
  660                 svmp->vm_flags = 0;
  661                 dog->opcode = svmp->vm_opcode = CODA_SIGNAL;
  662                 dog->unique = svmp->vm_unique = vmp->vm_unique;
  663                 svmp->vm_inSize = sizeof (struct coda_in_hdr);
  664 /*??? rvb */    svmp->vm_outSize = sizeof (struct coda_in_hdr);
  665                 
  666                 if (codadebug)
  667                     myprintf(("coda_call: enqueing signal msg (%d, %d)\n",
  668                            svmp->vm_opcode, svmp->vm_unique));
  669                 
  670                 /* insert at head of queue! */
  671                 INSQUE(svmp->vm_chain, vcp->vc_requests);
  672                 selwakeuppri(&(vcp->vc_selproc), coda_call_sleep);
  673             }
  674         }
  675 
  676         else {  /* If venus died (!VC_OPEN(vcp)) */
  677             if (codadebug)
  678                 myprintf(("vcclose woke op %d.%d flags %d\n",
  679                        vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags));
  680             
  681                 error = ENODEV;
  682         }
  683 
  684         CODA_FREE(vmp, sizeof(struct vmsg));
  685 
  686         if (outstanding_upcalls > 0 && (--outstanding_upcalls == 0))
  687                 wakeup(&outstanding_upcalls);
  688 
  689         if (!error)
  690                 error = ((struct coda_out_hdr *)buffer)->result;
  691         return(error);
  692 }

Cache object: 3c6dbc72008a3c12e31878d8715b52b3


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