Home | History | Annotate | Line # | Download | only in coda
coda_psdev.c revision 1.1
      1  1.1  rvb /*
      2  1.1  rvb 
      3  1.1  rvb             Coda: an Experimental Distributed File System
      4  1.1  rvb                              Release 3.1
      5  1.1  rvb 
      6  1.1  rvb           Copyright (c) 1987-1998 Carnegie Mellon University
      7  1.1  rvb                          All Rights Reserved
      8  1.1  rvb 
      9  1.1  rvb Permission  to  use, copy, modify and distribute this software and its
     10  1.1  rvb documentation is hereby granted,  provided  that  both  the  copyright
     11  1.1  rvb notice  and  this  permission  notice  appear  in  all  copies  of the
     12  1.1  rvb software, derivative works or  modified  versions,  and  any  portions
     13  1.1  rvb thereof, and that both notices appear in supporting documentation, and
     14  1.1  rvb that credit is given to Carnegie Mellon University  in  all  documents
     15  1.1  rvb and publicity pertaining to direct or indirect use of this code or its
     16  1.1  rvb derivatives.
     17  1.1  rvb 
     18  1.1  rvb CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS  KNOWN  TO  HAVE  BUGS,
     19  1.1  rvb SOME  OF  WHICH MAY HAVE SERIOUS CONSEQUENCES.  CARNEGIE MELLON ALLOWS
     20  1.1  rvb FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.   CARNEGIE  MELLON
     21  1.1  rvb DISCLAIMS  ANY  LIABILITY  OF  ANY  KIND  FOR  ANY  DAMAGES WHATSOEVER
     22  1.1  rvb RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE  OR  OF
     23  1.1  rvb ANY DERIVATIVE WORK.
     24  1.1  rvb 
     25  1.1  rvb Carnegie  Mellon  encourages  users  of  this  software  to return any
     26  1.1  rvb improvements or extensions that  they  make,  and  to  grant  Carnegie
     27  1.1  rvb Mellon the rights to redistribute these changes without encumbrance.
     28  1.1  rvb */
     29  1.1  rvb 
     30  1.1  rvb /* $Header: /tank/opengrok/rsync2/NetBSD/src/sys/coda/coda_psdev.c,v 1.1 1998/08/29 21:26:45 rvb Exp $ */
     31  1.1  rvb 
     32  1.1  rvb #define CTL_C
     33  1.1  rvb 
     34  1.1  rvb /*
     35  1.1  rvb  * Mach Operating System
     36  1.1  rvb  * Copyright (c) 1989 Carnegie-Mellon University
     37  1.1  rvb  * All rights reserved.  The CMU software License Agreement specifies
     38  1.1  rvb  * the terms and conditions for use and redistribution.
     39  1.1  rvb  */
     40  1.1  rvb 
     41  1.1  rvb /*
     42  1.1  rvb  * This code was written for the Coda file system at Carnegie Mellon
     43  1.1  rvb  * University.  Contributers include David Steere, James Kistler, and
     44  1.1  rvb  * M. Satyanarayanan.  */
     45  1.1  rvb 
     46  1.1  rvb /* ************************************************** */
     47  1.1  rvb /* These routines define the psuedo device for communication between
     48  1.1  rvb  * Coda's Venus and Minicache in Mach 2.6. They used to be in cfs_subr.c,
     49  1.1  rvb  * but I moved them to make it easier to port the Minicache without
     50  1.1  rvb  * porting coda. -- DCS 10/12/94
     51  1.1  rvb  */
     52  1.1  rvb 
     53  1.1  rvb /*
     54  1.1  rvb  * Renamed to cfs_psdev: pseudo-device driver.
     55  1.1  rvb  */
     56  1.1  rvb 
     57  1.1  rvb /*
     58  1.1  rvb  * HISTORY
     59  1.1  rvb  * $Log: coda_psdev.c,v $
     60  1.1  rvb  * Revision 1.1  1998/08/29 21:26:45  rvb
     61  1.1  rvb  * Initial revision
     62  1.1  rvb  *
     63  1.1  rvb  * Revision 1.9  1998/08/28 18:12:17  rvb
     64  1.1  rvb  * Now it also works on FreeBSD -current.  This code will be
     65  1.1  rvb  * committed to the FreeBSD -current and NetBSD -current
     66  1.1  rvb  * trees.  It will then be tailored to the particular platform
     67  1.1  rvb  * by flushing conditional code.
     68  1.1  rvb  *
     69  1.1  rvb  * Revision 1.8  1998/08/18 17:05:15  rvb
     70  1.1  rvb  * Don't use __RCSID now
     71  1.1  rvb  *
     72  1.1  rvb  * Revision 1.7  1998/08/18 16:31:41  rvb
     73  1.1  rvb  * Sync the code for NetBSD -current; test on 1.3 later
     74  1.1  rvb  *
     75  1.1  rvb  * Revision 1.8  1998/06/09 23:30:42  rvb
     76  1.1  rvb  * Try to allow ^C -- take 1
     77  1.1  rvb  *
     78  1.1  rvb  * Revision 1.5.2.8  98/01/23  11:21:04  rvb
     79  1.1  rvb  * Sync with 2.2.5
     80  1.1  rvb  *
     81  1.1  rvb  * Revision 1.5.2.7  98/01/22  22:22:21  rvb
     82  1.1  rvb  * sync 1.2 and 1.3
     83  1.1  rvb  *
     84  1.1  rvb  * Revision 1.5.2.6  98/01/22  13:11:24  rvb
     85  1.1  rvb  * Move makecfsnode ctlfid later so vfsp is known; work on ^c and ^z
     86  1.1  rvb  *
     87  1.1  rvb  * Revision 1.5.2.5  97/12/16  22:01:27  rvb
     88  1.1  rvb  * Oops add cfs_subr.h cfs_venus.h; sync with peter
     89  1.1  rvb  *
     90  1.1  rvb  * Revision 1.5.2.4  97/12/16  12:40:05  rvb
     91  1.1  rvb  * Sync with 1.3
     92  1.1  rvb  *
     93  1.1  rvb  * Revision 1.5.2.3  97/12/10  14:08:24  rvb
     94  1.1  rvb  * Fix O_ flags; check result in cfscall
     95  1.1  rvb  *
     96  1.1  rvb  * Revision 1.5.2.2  97/12/10  11:40:24  rvb
     97  1.1  rvb  * No more ody
     98  1.1  rvb  *
     99  1.1  rvb  * Revision 1.5.2.1  97/12/06  17:41:20  rvb
    100  1.1  rvb  * Sync with peters coda.h
    101  1.1  rvb  *
    102  1.1  rvb  * Revision 1.5  97/12/05  10:39:16  rvb
    103  1.1  rvb  * Read CHANGES
    104  1.1  rvb  *
    105  1.1  rvb  * Revision 1.4.18.9  97/12/05  08:58:07  rvb
    106  1.1  rvb  * peter found this one
    107  1.1  rvb  *
    108  1.1  rvb  * Revision 1.4.18.8  97/11/26  15:28:57  rvb
    109  1.1  rvb  * Cant make downcall pbuf == union cfs_downcalls yet
    110  1.1  rvb  *
    111  1.1  rvb  * Revision 1.4.18.7  97/11/25  09:40:49  rvb
    112  1.1  rvb  * Final cfs_venus.c w/o macros, but one locking bug
    113  1.1  rvb  *
    114  1.1  rvb  * Revision 1.4.18.6  97/11/20  11:46:41  rvb
    115  1.1  rvb  * Capture current cfs_venus
    116  1.1  rvb  *
    117  1.1  rvb  * Revision 1.4.18.5  97/11/18  10:27:15  rvb
    118  1.1  rvb  * cfs_nbsd.c is DEAD!!!; integrated into cfs_vf/vnops.c
    119  1.1  rvb  * cfs_nb_foo and cfs_foo are joined
    120  1.1  rvb  *
    121  1.1  rvb  * Revision 1.4.18.4  97/11/13  22:02:59  rvb
    122  1.1  rvb  * pass2 cfs_NetBSD.h mt
    123  1.1  rvb  *
    124  1.1  rvb  * Revision 1.4.18.3  97/11/12  12:09:38  rvb
    125  1.1  rvb  * reorg pass1
    126  1.1  rvb  *
    127  1.1  rvb  * Revision 1.4.18.2  97/10/29  16:06:09  rvb
    128  1.1  rvb  * Kill DYING
    129  1.1  rvb  *
    130  1.1  rvb  * Revision 1.4.18.1  1997/10/28 23:10:15  rvb
    131  1.1  rvb  * >64Meg; venus can be killed!
    132  1.1  rvb  *
    133  1.1  rvb  * Revision 1.4  1996/12/12 22:10:58  bnoble
    134  1.1  rvb  * Fixed the "downcall invokes venus operation" deadlock in all known cases.
    135  1.1  rvb  * There may be more
    136  1.1  rvb  *
    137  1.1  rvb  * Revision 1.3  1996/11/13 04:14:20  bnoble
    138  1.1  rvb  * Merging BNOBLE_WORK_6_20_96 into main line
    139  1.1  rvb  *
    140  1.1  rvb  * Revision 1.2.8.1  1996/08/22 14:25:04  bnoble
    141  1.1  rvb  * Added a return code from vc_nb_close
    142  1.1  rvb  *
    143  1.1  rvb  * Revision 1.2  1996/01/02 16:56:58  bnoble
    144  1.1  rvb  * Added support for Coda MiniCache and raw inode calls (final commit)
    145  1.1  rvb  *
    146  1.1  rvb  * Revision 1.1.2.1  1995/12/20 01:57:24  bnoble
    147  1.1  rvb  * Added CFS-specific files
    148  1.1  rvb  *
    149  1.1  rvb  * Revision 1.1  1995/03/14  20:52:15  bnoble
    150  1.1  rvb  * Initial revision
    151  1.1  rvb  *
    152  1.1  rvb  */
    153  1.1  rvb 
    154  1.1  rvb /* These routines are the device entry points for Venus. */
    155  1.1  rvb 
    156  1.1  rvb extern int cfsnc_initialized;    /* Set if cache has been initialized */
    157  1.1  rvb 
    158  1.1  rvb #include <vcfs.h>
    159  1.1  rvb #include <sys/param.h>
    160  1.1  rvb #include <sys/systm.h>
    161  1.1  rvb #include <sys/kernel.h>
    162  1.1  rvb #include <sys/malloc.h>
    163  1.1  rvb #include <sys/proc.h>
    164  1.1  rvb #include <sys/mount.h>
    165  1.1  rvb #include <sys/file.h>
    166  1.1  rvb #ifdef	__FreeBSD_version
    167  1.1  rvb #include <sys/ioccom.h>
    168  1.1  rvb #else
    169  1.1  rvb #include <sys/ioctl.h>
    170  1.1  rvb #endif
    171  1.1  rvb #ifdef	NetBSD1_3
    172  1.1  rvb #include <sys/poll.h>
    173  1.1  rvb #endif
    174  1.1  rvb #ifdef	__FreeBSD_version
    175  1.1  rvb #include <sys/poll.h>
    176  1.1  rvb #else
    177  1.1  rvb #include <sys/select.h>
    178  1.1  rvb #endif
    179  1.1  rvb 
    180  1.1  rvb #include <cfs/coda.h>
    181  1.1  rvb #include <cfs/cnode.h>
    182  1.1  rvb #include <cfs/cfsnc.h>
    183  1.1  rvb #include <cfs/cfsio.h>
    184  1.1  rvb 
    185  1.1  rvb int cfs_psdev_print_entry = 0;
    186  1.1  rvb 
    187  1.1  rvb #ifdef __GNUC__
    188  1.1  rvb #define ENTRY    \
    189  1.1  rvb     if(cfs_psdev_print_entry) myprintf(("Entered %s\n",__FUNCTION__))
    190  1.1  rvb #else
    191  1.1  rvb #define ENTRY
    192  1.1  rvb #endif
    193  1.1  rvb 
    194  1.1  rvb void vcfsattach(int n);
    195  1.1  rvb int vc_nb_open(dev_t dev, int flag, int mode, struct proc *p);
    196  1.1  rvb int vc_nb_close (dev_t dev, int flag, int mode, struct proc *p);
    197  1.1  rvb int vc_nb_read(dev_t dev, struct uio *uiop, int flag);
    198  1.1  rvb int vc_nb_write(dev_t dev, struct uio *uiop, int flag);
    199  1.1  rvb int vc_nb_ioctl(dev_t dev, int cmd, caddr_t addr, int flag, struct proc *p);
    200  1.1  rvb #if	defined(NetBSD1_3) || defined(__FreeBSD_version)
    201  1.1  rvb int vc_nb_poll(dev_t dev, int events, struct proc *p);
    202  1.1  rvb #else
    203  1.1  rvb int vc_nb_select(dev_t dev, int flag, struct proc *p);
    204  1.1  rvb #endif
    205  1.1  rvb 
    206  1.1  rvb struct vmsg {
    207  1.1  rvb     struct queue vm_chain;
    208  1.1  rvb     caddr_t	 vm_data;
    209  1.1  rvb     u_short	 vm_flags;
    210  1.1  rvb     u_short      vm_inSize;	/* Size is at most 5000 bytes */
    211  1.1  rvb     u_short	 vm_outSize;
    212  1.1  rvb     u_short	 vm_opcode; 	/* copied from data to save ptr lookup */
    213  1.1  rvb     int		 vm_unique;
    214  1.1  rvb     caddr_t	 vm_sleep;	/* Not used by Mach. */
    215  1.1  rvb };
    216  1.1  rvb 
    217  1.1  rvb #define	VM_READ	    1
    218  1.1  rvb #define	VM_WRITE    2
    219  1.1  rvb #define	VM_INTR	    4
    220  1.1  rvb 
    221  1.1  rvb /* vcfsattach: do nothing */
    222  1.1  rvb void
    223  1.1  rvb vcfsattach(n)
    224  1.1  rvb     int n;
    225  1.1  rvb {
    226  1.1  rvb }
    227  1.1  rvb 
    228  1.1  rvb /*
    229  1.1  rvb  * These functions are written for NetBSD.
    230  1.1  rvb  */
    231  1.1  rvb int
    232  1.1  rvb vc_nb_open(dev, flag, mode, p)
    233  1.1  rvb     dev_t        dev;
    234  1.1  rvb     int          flag;
    235  1.1  rvb     int          mode;
    236  1.1  rvb     struct proc *p;             /* NetBSD only */
    237  1.1  rvb {
    238  1.1  rvb     register struct vcomm *vcp;
    239  1.1  rvb 
    240  1.1  rvb     ENTRY;
    241  1.1  rvb 
    242  1.1  rvb     if (minor(dev) >= NVCFS || minor(dev) < 0)
    243  1.1  rvb 	return(ENXIO);
    244  1.1  rvb 
    245  1.1  rvb     if (!cfsnc_initialized)
    246  1.1  rvb 	cfsnc_init();
    247  1.1  rvb 
    248  1.1  rvb     vcp = &cfs_mnttbl[minor(dev)].mi_vcomm;
    249  1.1  rvb     if (VC_OPEN(vcp))
    250  1.1  rvb 	return(EBUSY);
    251  1.1  rvb 
    252  1.1  rvb     bzero(&(vcp->vc_selproc), sizeof (struct selinfo));
    253  1.1  rvb     INIT_QUEUE(vcp->vc_requests);
    254  1.1  rvb     INIT_QUEUE(vcp->vc_replys);
    255  1.1  rvb     MARK_VC_OPEN(vcp);
    256  1.1  rvb 
    257  1.1  rvb     cfs_mnttbl[minor(dev)].mi_vfsp = NULL;
    258  1.1  rvb     cfs_mnttbl[minor(dev)].mi_rootvp = NULL;
    259  1.1  rvb 
    260  1.1  rvb     return(0);
    261  1.1  rvb }
    262  1.1  rvb 
    263  1.1  rvb int
    264  1.1  rvb vc_nb_close (dev, flag, mode, p)
    265  1.1  rvb     dev_t        dev;
    266  1.1  rvb     int          flag;
    267  1.1  rvb     int          mode;
    268  1.1  rvb     struct proc *p;
    269  1.1  rvb {
    270  1.1  rvb     register struct vcomm *vcp;
    271  1.1  rvb     register struct vmsg *vmp;
    272  1.1  rvb     struct cfs_mntinfo *mi;
    273  1.1  rvb     int                 err;
    274  1.1  rvb 
    275  1.1  rvb     ENTRY;
    276  1.1  rvb 
    277  1.1  rvb     if (minor(dev) >= NVCFS || minor(dev) < 0)
    278  1.1  rvb 	return(ENXIO);
    279  1.1  rvb 
    280  1.1  rvb     mi = &cfs_mnttbl[minor(dev)];
    281  1.1  rvb     vcp = &(mi->mi_vcomm);
    282  1.1  rvb 
    283  1.1  rvb     if (!VC_OPEN(vcp))
    284  1.1  rvb 	panic("vcclose: not open");
    285  1.1  rvb 
    286  1.1  rvb     /* prevent future operations on this vfs from succeeding by auto-
    287  1.1  rvb      * unmounting any vfs mounted via this device. This frees user or
    288  1.1  rvb      * sysadm from having to remember where all mount points are located.
    289  1.1  rvb      * Put this before WAKEUPs to avoid queuing new messages between
    290  1.1  rvb      * the WAKEUP and the unmount (which can happen if we're unlucky)
    291  1.1  rvb      */
    292  1.1  rvb     if (mi->mi_rootvp) {
    293  1.1  rvb 	/* Let unmount know this is for real */
    294  1.1  rvb 	VTOC(mi->mi_rootvp)->c_flags |= C_UNMOUNTING;
    295  1.1  rvb #ifdef	NEW_LOCKMGR
    296  1.1  rvb #ifdef	__FreeBSD_version
    297  1.1  rvb 	/* dounmount is different ... probably wrong ... */
    298  1.1  rvb #else
    299  1.1  rvb 	if (vfs_busy(mi->mi_vfsp, 0, 0))
    300  1.1  rvb 	    return (EBUSY);
    301  1.1  rvb #endif
    302  1.1  rvb #endif
    303  1.1  rvb 	cfs_unmounting(mi->mi_vfsp);
    304  1.1  rvb 	err = dounmount(mi->mi_vfsp, flag, p);
    305  1.1  rvb 	if (err)
    306  1.1  rvb 	    myprintf(("Error %d unmounting vfs in vcclose(%d)\n",
    307  1.1  rvb 		      err, minor(dev)));
    308  1.1  rvb     }
    309  1.1  rvb 
    310  1.1  rvb     /* Wakeup clients so they can return. */
    311  1.1  rvb     for (vmp = (struct vmsg *)GETNEXT(vcp->vc_requests);
    312  1.1  rvb 	 !EOQ(vmp, vcp->vc_requests);
    313  1.1  rvb 	 vmp = (struct vmsg *)GETNEXT(vmp->vm_chain))
    314  1.1  rvb     {
    315  1.1  rvb 	/* Free signal request messages and don't wakeup cause
    316  1.1  rvb 	   no one is waiting. */
    317  1.1  rvb 	if (vmp->vm_opcode == CFS_SIGNAL) {
    318  1.1  rvb 	    CFS_FREE((caddr_t)vmp->vm_data, (u_int)VC_IN_NO_DATA);
    319  1.1  rvb 	    CFS_FREE((caddr_t)vmp, (u_int)sizeof(struct vmsg));
    320  1.1  rvb 	    continue;
    321  1.1  rvb 	}
    322  1.1  rvb 
    323  1.1  rvb 	wakeup(&vmp->vm_sleep);
    324  1.1  rvb     }
    325  1.1  rvb 
    326  1.1  rvb     for (vmp = (struct vmsg *)GETNEXT(vcp->vc_replys);
    327  1.1  rvb 	 !EOQ(vmp, vcp->vc_replys);
    328  1.1  rvb 	 vmp = (struct vmsg *)GETNEXT(vmp->vm_chain))
    329  1.1  rvb     {
    330  1.1  rvb 	wakeup(&vmp->vm_sleep);
    331  1.1  rvb     }
    332  1.1  rvb 
    333  1.1  rvb     MARK_VC_CLOSED(vcp);
    334  1.1  rvb     return 0;
    335  1.1  rvb }
    336  1.1  rvb 
    337  1.1  rvb int
    338  1.1  rvb vc_nb_read(dev, uiop, flag)
    339  1.1  rvb     dev_t        dev;
    340  1.1  rvb     struct uio  *uiop;
    341  1.1  rvb     int          flag;
    342  1.1  rvb {
    343  1.1  rvb     register struct vcomm *	vcp;
    344  1.1  rvb     register struct vmsg *vmp;
    345  1.1  rvb     int error = 0;
    346  1.1  rvb 
    347  1.1  rvb     ENTRY;
    348  1.1  rvb 
    349  1.1  rvb     if (minor(dev) >= NVCFS || minor(dev) < 0)
    350  1.1  rvb 	return(ENXIO);
    351  1.1  rvb 
    352  1.1  rvb     vcp = &cfs_mnttbl[minor(dev)].mi_vcomm;
    353  1.1  rvb     /* Get message at head of request queue. */
    354  1.1  rvb     if (EMPTY(vcp->vc_requests))
    355  1.1  rvb 	return(0);	/* Nothing to read */
    356  1.1  rvb 
    357  1.1  rvb     vmp = (struct vmsg *)GETNEXT(vcp->vc_requests);
    358  1.1  rvb 
    359  1.1  rvb     /* Move the input args into userspace */
    360  1.1  rvb     uiop->uio_rw = UIO_READ;
    361  1.1  rvb     error = uiomove(vmp->vm_data, vmp->vm_inSize, uiop);
    362  1.1  rvb     if (error) {
    363  1.1  rvb 	myprintf(("vcread: error (%d) on uiomove\n", error));
    364  1.1  rvb 	error = EINVAL;
    365  1.1  rvb     }
    366  1.1  rvb 
    367  1.1  rvb #ifdef DIAGNOSTIC
    368  1.1  rvb     if (vmp->vm_chain.forw == 0 || vmp->vm_chain.back == 0)
    369  1.1  rvb 	panic("vc_nb_read: bad chain");
    370  1.1  rvb #endif
    371  1.1  rvb 
    372  1.1  rvb     REMQUE(vmp->vm_chain);
    373  1.1  rvb 
    374  1.1  rvb     /* If request was a signal, free up the message and don't
    375  1.1  rvb        enqueue it in the reply queue. */
    376  1.1  rvb     if (vmp->vm_opcode == CFS_SIGNAL) {
    377  1.1  rvb 	if (cfsdebug)
    378  1.1  rvb 	    myprintf(("vcread: signal msg (%d, %d)\n",
    379  1.1  rvb 		      vmp->vm_opcode, vmp->vm_unique));
    380  1.1  rvb 	CFS_FREE((caddr_t)vmp->vm_data, (u_int)VC_IN_NO_DATA);
    381  1.1  rvb 	CFS_FREE((caddr_t)vmp, (u_int)sizeof(struct vmsg));
    382  1.1  rvb 	return(error);
    383  1.1  rvb     }
    384  1.1  rvb 
    385  1.1  rvb     vmp->vm_flags |= VM_READ;
    386  1.1  rvb     INSQUE(vmp->vm_chain, vcp->vc_replys);
    387  1.1  rvb 
    388  1.1  rvb     return(error);
    389  1.1  rvb }
    390  1.1  rvb 
    391  1.1  rvb int
    392  1.1  rvb vc_nb_write(dev, uiop, flag)
    393  1.1  rvb     dev_t        dev;
    394  1.1  rvb     struct uio  *uiop;
    395  1.1  rvb     int          flag;
    396  1.1  rvb {
    397  1.1  rvb     register struct vcomm *	vcp;
    398  1.1  rvb     register struct vmsg *vmp;
    399  1.1  rvb     struct cfs_out_hdr *out;
    400  1.1  rvb     u_long seq;
    401  1.1  rvb     u_long opcode;
    402  1.1  rvb     int buf[2];
    403  1.1  rvb     int error = 0;
    404  1.1  rvb 
    405  1.1  rvb     ENTRY;
    406  1.1  rvb 
    407  1.1  rvb     if (minor(dev) >= NVCFS || minor(dev) < 0)
    408  1.1  rvb 	return(ENXIO);
    409  1.1  rvb 
    410  1.1  rvb     vcp = &cfs_mnttbl[minor(dev)].mi_vcomm;
    411  1.1  rvb 
    412  1.1  rvb     /* Peek at the opcode, unique without transfering the data. */
    413  1.1  rvb     uiop->uio_rw = UIO_WRITE;
    414  1.1  rvb     error = uiomove((caddr_t)buf, sizeof(int) * 2, uiop);
    415  1.1  rvb     if (error) {
    416  1.1  rvb 	myprintf(("vcwrite: error (%d) on uiomove\n", error));
    417  1.1  rvb 	return(EINVAL);
    418  1.1  rvb     }
    419  1.1  rvb 
    420  1.1  rvb     opcode = buf[0];
    421  1.1  rvb     seq = buf[1];
    422  1.1  rvb 
    423  1.1  rvb     if (cfsdebug)
    424  1.1  rvb 	myprintf(("vcwrite got a call for %ld.%ld\n", opcode, seq));
    425  1.1  rvb 
    426  1.1  rvb     if (DOWNCALL(opcode)) {
    427  1.1  rvb 	union outputArgs pbuf;
    428  1.1  rvb 
    429  1.1  rvb 	/* get the rest of the data. */
    430  1.1  rvb 	uiop->uio_rw = UIO_WRITE;
    431  1.1  rvb 	error = uiomove((caddr_t)&pbuf.cfs_purgeuser.oh.result, sizeof(pbuf) - (sizeof(int)*2), uiop);
    432  1.1  rvb 	if (error) {
    433  1.1  rvb 	    myprintf(("vcwrite: error (%d) on uiomove (Op %ld seq %ld)\n",
    434  1.1  rvb 		      error, opcode, seq));
    435  1.1  rvb 	    return(EINVAL);
    436  1.1  rvb 	    }
    437  1.1  rvb 
    438  1.1  rvb 	return handleDownCall(opcode, &pbuf);
    439  1.1  rvb     }
    440  1.1  rvb 
    441  1.1  rvb     /* Look for the message on the (waiting for) reply queue. */
    442  1.1  rvb     for (vmp = (struct vmsg *)GETNEXT(vcp->vc_replys);
    443  1.1  rvb 	 !EOQ(vmp, vcp->vc_replys);
    444  1.1  rvb 	 vmp = (struct vmsg *)GETNEXT(vmp->vm_chain))
    445  1.1  rvb     {
    446  1.1  rvb 	if (vmp->vm_unique == seq) break;
    447  1.1  rvb     }
    448  1.1  rvb 
    449  1.1  rvb     if (EOQ(vmp, vcp->vc_replys)) {
    450  1.1  rvb 	if (cfsdebug)
    451  1.1  rvb 	    myprintf(("vcwrite: msg (%ld, %ld) not found\n", opcode, seq));
    452  1.1  rvb 
    453  1.1  rvb 	return(ESRCH);
    454  1.1  rvb 	}
    455  1.1  rvb 
    456  1.1  rvb     /* Remove the message from the reply queue */
    457  1.1  rvb     REMQUE(vmp->vm_chain);
    458  1.1  rvb 
    459  1.1  rvb     /* move data into response buffer. */
    460  1.1  rvb     out = (struct cfs_out_hdr *)vmp->vm_data;
    461  1.1  rvb     /* Don't need to copy opcode and uniquifier. */
    462  1.1  rvb 
    463  1.1  rvb     /* get the rest of the data. */
    464  1.1  rvb     if (vmp->vm_outSize < uiop->uio_resid) {
    465  1.1  rvb 	myprintf(("vcwrite: more data than asked for (%d < %d)\n",
    466  1.1  rvb 		  vmp->vm_outSize, uiop->uio_resid));
    467  1.1  rvb 	wakeup(&vmp->vm_sleep); 	/* Notify caller of the error. */
    468  1.1  rvb 	return(EINVAL);
    469  1.1  rvb     }
    470  1.1  rvb 
    471  1.1  rvb     buf[0] = uiop->uio_resid; 	/* Save this value. */
    472  1.1  rvb     uiop->uio_rw = UIO_WRITE;
    473  1.1  rvb     error = uiomove((caddr_t) &out->result, vmp->vm_outSize - (sizeof(int) * 2), uiop);
    474  1.1  rvb     if (error) {
    475  1.1  rvb 	myprintf(("vcwrite: error (%d) on uiomove (op %ld seq %ld)\n",
    476  1.1  rvb 		  error, opcode, seq));
    477  1.1  rvb 	return(EINVAL);
    478  1.1  rvb     }
    479  1.1  rvb 
    480  1.1  rvb     /* I don't think these are used, but just in case. */
    481  1.1  rvb     /* XXX - aren't these two already correct? -bnoble */
    482  1.1  rvb     out->opcode = opcode;
    483  1.1  rvb     out->unique = seq;
    484  1.1  rvb     vmp->vm_outSize	= buf[0];	/* Amount of data transferred? */
    485  1.1  rvb     vmp->vm_flags |= VM_WRITE;
    486  1.1  rvb     wakeup(&vmp->vm_sleep);
    487  1.1  rvb 
    488  1.1  rvb     return(0);
    489  1.1  rvb }
    490  1.1  rvb 
    491  1.1  rvb int
    492  1.1  rvb vc_nb_ioctl(dev, cmd, addr, flag, p)
    493  1.1  rvb     dev_t         dev;
    494  1.1  rvb     int           cmd;
    495  1.1  rvb     caddr_t       addr;
    496  1.1  rvb     int           flag;
    497  1.1  rvb     struct proc  *p;
    498  1.1  rvb {
    499  1.1  rvb     ENTRY;
    500  1.1  rvb 
    501  1.1  rvb     switch(cmd) {
    502  1.1  rvb     case CFSRESIZE: {
    503  1.1  rvb 	struct cfs_resize *data = (struct cfs_resize *)addr;
    504  1.1  rvb 	return(cfsnc_resize(data->hashsize, data->heapsize, IS_DOWNCALL));
    505  1.1  rvb 	break;
    506  1.1  rvb     }
    507  1.1  rvb     case CFSSTATS:
    508  1.1  rvb 	if (cfsnc_use) {
    509  1.1  rvb 	    cfsnc_gather_stats();
    510  1.1  rvb 	    return(0);
    511  1.1  rvb 	} else {
    512  1.1  rvb 	    return(ENODEV);
    513  1.1  rvb 	}
    514  1.1  rvb 	break;
    515  1.1  rvb     case CFSPRINT:
    516  1.1  rvb 	if (cfsnc_use) {
    517  1.1  rvb 	    print_cfsnc();
    518  1.1  rvb 	    return(0);
    519  1.1  rvb 	} else {
    520  1.1  rvb 	    return(ENODEV);
    521  1.1  rvb 	}
    522  1.1  rvb 	break;
    523  1.1  rvb     default :
    524  1.1  rvb 	return(EINVAL);
    525  1.1  rvb 	break;
    526  1.1  rvb     }
    527  1.1  rvb }
    528  1.1  rvb 
    529  1.1  rvb #if	defined(NetBSD1_3) || defined(__FreeBSD_version)
    530  1.1  rvb int
    531  1.1  rvb vc_nb_poll(dev, events, p)
    532  1.1  rvb     dev_t         dev;
    533  1.1  rvb     int           events;
    534  1.1  rvb     struct proc  *p;
    535  1.1  rvb {
    536  1.1  rvb     register struct vcomm *vcp;
    537  1.1  rvb     int event_msk = 0;
    538  1.1  rvb 
    539  1.1  rvb     ENTRY;
    540  1.1  rvb 
    541  1.1  rvb     if (minor(dev) >= NVCFS || minor(dev) < 0)
    542  1.1  rvb 	return(ENXIO);
    543  1.1  rvb 
    544  1.1  rvb     vcp = &cfs_mnttbl[minor(dev)].mi_vcomm;
    545  1.1  rvb 
    546  1.1  rvb     event_msk = events & (POLLIN|POLLRDNORM);
    547  1.1  rvb     if (!event_msk)
    548  1.1  rvb 	return(0);
    549  1.1  rvb 
    550  1.1  rvb     if (!EMPTY(vcp->vc_requests))
    551  1.1  rvb 	return(events & (POLLIN|POLLRDNORM));
    552  1.1  rvb 
    553  1.1  rvb     selrecord(p, &(vcp->vc_selproc));
    554  1.1  rvb 
    555  1.1  rvb     return(0);
    556  1.1  rvb }
    557  1.1  rvb #else
    558  1.1  rvb int
    559  1.1  rvb vc_nb_select(dev, flag, p)
    560  1.1  rvb     dev_t         dev;
    561  1.1  rvb     int           flag;
    562  1.1  rvb     struct proc  *p;
    563  1.1  rvb {
    564  1.1  rvb     register struct vcomm *vcp;
    565  1.1  rvb 
    566  1.1  rvb     ENTRY;
    567  1.1  rvb 
    568  1.1  rvb     if (minor(dev) >= NVCFS || minor(dev) < 0)
    569  1.1  rvb 	return(ENXIO);
    570  1.1  rvb 
    571  1.1  rvb     vcp = &cfs_mnttbl[minor(dev)].mi_vcomm;
    572  1.1  rvb 
    573  1.1  rvb     if (flag != FREAD)
    574  1.1  rvb 	return(0);
    575  1.1  rvb 
    576  1.1  rvb     if (!EMPTY(vcp->vc_requests))
    577  1.1  rvb 	return(1);
    578  1.1  rvb 
    579  1.1  rvb     selrecord(p, &(vcp->vc_selproc));
    580  1.1  rvb 
    581  1.1  rvb     return(0);
    582  1.1  rvb }
    583  1.1  rvb #endif
    584  1.1  rvb 
    585  1.1  rvb /*
    586  1.1  rvb  * Statistics
    587  1.1  rvb  */
    588  1.1  rvb struct cfs_clstat cfs_clstat;
    589  1.1  rvb 
    590  1.1  rvb /*
    591  1.1  rvb  * Key question: whether to sleep interuptably or uninteruptably when
    592  1.1  rvb  * waiting for Venus.  The former seems better (cause you can ^C a
    593  1.1  rvb  * job), but then GNU-EMACS completion breaks. Use tsleep with no
    594  1.1  rvb  * timeout, and no longjmp happens. But, when sleeping
    595  1.1  rvb  * "uninterruptibly", we don't get told if it returns abnormally
    596  1.1  rvb  * (e.g. kill -9).
    597  1.1  rvb  */
    598  1.1  rvb 
    599  1.1  rvb /* If you want this to be interruptible, set this to > PZERO */
    600  1.1  rvb int cfscall_sleep = PZERO - 1;
    601  1.1  rvb #ifdef	CTL_C
    602  1.1  rvb int cfs_pcatch = PCATCH;
    603  1.1  rvb #else
    604  1.1  rvb #endif
    605  1.1  rvb 
    606  1.1  rvb int
    607  1.1  rvb cfscall(mntinfo, inSize, outSize, buffer)
    608  1.1  rvb      struct cfs_mntinfo *mntinfo; int inSize; int *outSize; caddr_t buffer;
    609  1.1  rvb {
    610  1.1  rvb 	struct vcomm *vcp;
    611  1.1  rvb 	struct vmsg *vmp;
    612  1.1  rvb 	int error;
    613  1.1  rvb #ifdef	CTL_C
    614  1.1  rvb 	struct proc *p = curproc;
    615  1.1  rvb 	unsigned int psig_omask = p->p_sigmask;
    616  1.1  rvb 	int i;
    617  1.1  rvb #endif
    618  1.1  rvb 	if (mntinfo == NULL) {
    619  1.1  rvb 	    /* Unlikely, but could be a race condition with a dying warden */
    620  1.1  rvb 	    return ENODEV;
    621  1.1  rvb 	}
    622  1.1  rvb 
    623  1.1  rvb 	vcp = &(mntinfo->mi_vcomm);
    624  1.1  rvb 
    625  1.1  rvb 	cfs_clstat.ncalls++;
    626  1.1  rvb 	cfs_clstat.reqs[((struct cfs_in_hdr *)buffer)->opcode]++;
    627  1.1  rvb 
    628  1.1  rvb 	if (!VC_OPEN(vcp))
    629  1.1  rvb 	    return(ENODEV);
    630  1.1  rvb 
    631  1.1  rvb 	CFS_ALLOC(vmp,struct vmsg *,sizeof(struct vmsg));
    632  1.1  rvb 	/* Format the request message. */
    633  1.1  rvb 	vmp->vm_data = buffer;
    634  1.1  rvb 	vmp->vm_flags = 0;
    635  1.1  rvb 	vmp->vm_inSize = inSize;
    636  1.1  rvb 	vmp->vm_outSize
    637  1.1  rvb 	    = *outSize ? *outSize : inSize; /* |buffer| >= inSize */
    638  1.1  rvb 	vmp->vm_opcode = ((struct cfs_in_hdr *)buffer)->opcode;
    639  1.1  rvb 	vmp->vm_unique = ++vcp->vc_seq;
    640  1.1  rvb 	if (cfsdebug)
    641  1.1  rvb 	    myprintf(("Doing a call for %d.%d\n",
    642  1.1  rvb 		      vmp->vm_opcode, vmp->vm_unique));
    643  1.1  rvb 
    644  1.1  rvb 	/* Fill in the common input args. */
    645  1.1  rvb 	((struct cfs_in_hdr *)buffer)->unique = vmp->vm_unique;
    646  1.1  rvb 
    647  1.1  rvb 	/* Append msg to request queue and poke Venus. */
    648  1.1  rvb 	INSQUE(vmp->vm_chain, vcp->vc_requests);
    649  1.1  rvb 	selwakeup(&(vcp->vc_selproc));
    650  1.1  rvb 
    651  1.1  rvb 	/* We can be interrupted while we wait for Venus to process
    652  1.1  rvb 	 * our request.  If the interrupt occurs before Venus has read
    653  1.1  rvb 	 * the request, we dequeue and return. If it occurs after the
    654  1.1  rvb 	 * read but before the reply, we dequeue, send a signal
    655  1.1  rvb 	 * message, and return. If it occurs after the reply we ignore
    656  1.1  rvb 	 * it. In no case do we want to restart the syscall.  If it
    657  1.1  rvb 	 * was interrupted by a venus shutdown (vcclose), return
    658  1.1  rvb 	 * ENODEV.  */
    659  1.1  rvb 
    660  1.1  rvb 	/* Ignore return, We have to check anyway */
    661  1.1  rvb #ifdef	CTL_C
    662  1.1  rvb 	/* This is work in progress.  Setting cfs_pcatch lets tsleep reawaken
    663  1.1  rvb 	   on a ^c or ^z.  The problem is that emacs sets certain interrupts
    664  1.1  rvb 	   as SA_RESTART.  This means that we should exit sleep handle the
    665  1.1  rvb 	   "signal" and then go to sleep again.  Mostly this is done by letting
    666  1.1  rvb 	   the syscall complete and be restarted.  We are not idempotent and
    667  1.1  rvb 	   can not do this.  A better solution is necessary.
    668  1.1  rvb 	 */
    669  1.1  rvb 	i = 0;
    670  1.1  rvb 	do {
    671  1.1  rvb 	    error = tsleep(&vmp->vm_sleep, (cfscall_sleep|cfs_pcatch), "cfscall", hz*2);
    672  1.1  rvb 	    if (error == 0)
    673  1.1  rvb 	    	break;
    674  1.1  rvb 	    else if (error == EWOULDBLOCK) {
    675  1.1  rvb 		    printf("cfscall: tsleep TIMEOUT %d sec\n", 2+2*i);
    676  1.1  rvb     	    } else if (p->p_siglist == sigmask(SIGIO)) {
    677  1.1  rvb 		    p->p_sigmask |= p->p_siglist;
    678  1.1  rvb 		    printf("cfscall: tsleep returns %d SIGIO, cnt %d\n", error, i);
    679  1.1  rvb 	    } else {
    680  1.1  rvb 		    printf("cfscall: tsleep returns %d, cnt %d\n", error, i);
    681  1.1  rvb 		    printf("cfscall: siglist = %x, sigmask = %x, mask %x\n",
    682  1.1  rvb 			    p->p_siglist, p->p_sigmask,
    683  1.1  rvb 			    p->p_siglist & ~p->p_sigmask);
    684  1.1  rvb 		    break;
    685  1.1  rvb 		    p->p_sigmask |= p->p_siglist;
    686  1.1  rvb 		    printf("cfscall: new mask, siglist = %x, sigmask = %x, mask %x\n",
    687  1.1  rvb 			    p->p_siglist, p->p_sigmask,
    688  1.1  rvb 			    p->p_siglist & ~p->p_sigmask);
    689  1.1  rvb 	    }
    690  1.1  rvb 	} while (error && i++ < 128);
    691  1.1  rvb 	p->p_sigmask = psig_omask;
    692  1.1  rvb #else
    693  1.1  rvb 	(void) tsleep(&vmp->vm_sleep, cfscall_sleep, "cfscall", 0);
    694  1.1  rvb #endif
    695  1.1  rvb 	if (VC_OPEN(vcp)) {	/* Venus is still alive */
    696  1.1  rvb  	/* Op went through, interrupt or not... */
    697  1.1  rvb 	    if (vmp->vm_flags & VM_WRITE) {
    698  1.1  rvb 		error = 0;
    699  1.1  rvb 		*outSize = vmp->vm_outSize;
    700  1.1  rvb 	    }
    701  1.1  rvb 
    702  1.1  rvb 	    else if (!(vmp->vm_flags & VM_READ)) {
    703  1.1  rvb 		/* Interrupted before venus read it. */
    704  1.1  rvb 		if (cfsdebug||1)
    705  1.1  rvb 		    myprintf(("interrupted before read: op = %d.%d, flags = %x\n",
    706  1.1  rvb 			   vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags));
    707  1.1  rvb 		REMQUE(vmp->vm_chain);
    708  1.1  rvb 		error = EINTR;
    709  1.1  rvb 	    }
    710  1.1  rvb 
    711  1.1  rvb 	    else {
    712  1.1  rvb 		/* (!(vmp->vm_flags & VM_WRITE)) means interrupted after
    713  1.1  rvb                    upcall started */
    714  1.1  rvb 		/* Interrupted after start of upcall, send venus a signal */
    715  1.1  rvb 		struct cfs_in_hdr *dog;
    716  1.1  rvb 		struct vmsg *svmp;
    717  1.1  rvb 
    718  1.1  rvb 		if (cfsdebug||1)
    719  1.1  rvb 		    myprintf(("Sending Venus a signal: op = %d.%d, flags = %x\n",
    720  1.1  rvb 			   vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags));
    721  1.1  rvb 
    722  1.1  rvb 		REMQUE(vmp->vm_chain);
    723  1.1  rvb 		error = EINTR;
    724  1.1  rvb 
    725  1.1  rvb 		CFS_ALLOC(svmp, struct vmsg *, sizeof (struct vmsg));
    726  1.1  rvb 
    727  1.1  rvb 		CFS_ALLOC((svmp->vm_data), char *, sizeof (struct cfs_in_hdr));
    728  1.1  rvb 		dog = (struct cfs_in_hdr *)svmp->vm_data;
    729  1.1  rvb 
    730  1.1  rvb 		svmp->vm_flags = 0;
    731  1.1  rvb 		dog->opcode = svmp->vm_opcode = CFS_SIGNAL;
    732  1.1  rvb 		dog->unique = svmp->vm_unique = vmp->vm_unique;
    733  1.1  rvb 		svmp->vm_inSize = sizeof (struct cfs_in_hdr);
    734  1.1  rvb /*??? rvb */	svmp->vm_outSize = sizeof (struct cfs_in_hdr);
    735  1.1  rvb 
    736  1.1  rvb 		if (cfsdebug)
    737  1.1  rvb 		    myprintf(("cfscall: enqueing signal msg (%d, %d)\n",
    738  1.1  rvb 			   svmp->vm_opcode, svmp->vm_unique));
    739  1.1  rvb 
    740  1.1  rvb 		/* insert at head of queue! */
    741  1.1  rvb 		INSQUE(svmp->vm_chain, vcp->vc_requests);
    742  1.1  rvb 		selwakeup(&(vcp->vc_selproc));
    743  1.1  rvb 	    }
    744  1.1  rvb 	}
    745  1.1  rvb 
    746  1.1  rvb 	else {	/* If venus died (!VC_OPEN(vcp)) */
    747  1.1  rvb 	    if (cfsdebug)
    748  1.1  rvb 		myprintf(("vcclose woke op %d.%d flags %d\n",
    749  1.1  rvb 		       vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags));
    750  1.1  rvb 
    751  1.1  rvb 		error = ENODEV;
    752  1.1  rvb 	}
    753  1.1  rvb 
    754  1.1  rvb 	CFS_FREE(vmp, sizeof(struct vmsg));
    755  1.1  rvb 
    756  1.1  rvb 	if (!error)
    757           		error = ((struct cfs_out_hdr *)buffer)->result;
    758           	return(error);
    759           }
    760