Home | History | Annotate | Line # | Download | only in coda
coda_subr.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_subr.c,v 1.1 1998/08/29 21:26:45 rvb Exp $ */
     31  1.1  rvb 
     32  1.1  rvb /*
     33  1.1  rvb  * Mach Operating System
     34  1.1  rvb  * Copyright (c) 1989 Carnegie-Mellon University
     35  1.1  rvb  * All rights reserved.  The CMU software License Agreement specifies
     36  1.1  rvb  * the terms and conditions for use and redistribution.
     37  1.1  rvb  */
     38  1.1  rvb 
     39  1.1  rvb /*
     40  1.1  rvb  * This code was written for the Coda file system at Carnegie Mellon
     41  1.1  rvb  * University.  Contributers include David Steere, James Kistler, and
     42  1.1  rvb  * M. Satyanarayanan.  */
     43  1.1  rvb 
     44  1.1  rvb /*
     45  1.1  rvb  * HISTORY
     46  1.1  rvb  * $Log: coda_subr.c,v $
     47  1.1  rvb  * Revision 1.1  1998/08/29 21:26:45  rvb
     48  1.1  rvb  * Initial revision
     49  1.1  rvb  *
     50  1.1  rvb  * Revision 1.11  1998/08/28 18:12:18  rvb
     51  1.1  rvb  * Now it also works on FreeBSD -current.  This code will be
     52  1.1  rvb  * committed to the FreeBSD -current and NetBSD -current
     53  1.1  rvb  * trees.  It will then be tailored to the particular platform
     54  1.1  rvb  * by flushing conditional code.
     55  1.1  rvb  *
     56  1.1  rvb  * Revision 1.10  1998/08/18 17:05:16  rvb
     57  1.1  rvb  * Don't use __RCSID now
     58  1.1  rvb  *
     59  1.1  rvb  * Revision 1.9  1998/08/18 16:31:41  rvb
     60  1.1  rvb  * Sync the code for NetBSD -current; test on 1.3 later
     61  1.1  rvb  *
     62  1.1  rvb  * Revision 1.8  98/01/31  20:53:12  rvb
     63  1.1  rvb  * First version that works on FreeBSD 2.2.5
     64  1.1  rvb  *
     65  1.1  rvb  * Revision 1.7  98/01/23  11:53:42  rvb
     66  1.1  rvb  * Bring RVB_CFS1_1 to HEAD
     67  1.1  rvb  *
     68  1.1  rvb  * Revision 1.6.2.3  98/01/23  11:21:05  rvb
     69  1.1  rvb  * Sync with 2.2.5
     70  1.1  rvb  *
     71  1.1  rvb  * Revision 1.6.2.2  97/12/16  12:40:06  rvb
     72  1.1  rvb  * Sync with 1.3
     73  1.1  rvb  *
     74  1.1  rvb  * Revision 1.6.2.1  97/12/06  17:41:21  rvb
     75  1.1  rvb  * Sync with peters coda.h
     76  1.1  rvb  *
     77  1.1  rvb  * Revision 1.6  97/12/05  10:39:17  rvb
     78  1.1  rvb  * Read CHANGES
     79  1.1  rvb  *
     80  1.1  rvb  * Revision 1.5.4.8  97/11/26  15:28:58  rvb
     81  1.1  rvb  * Cant make downcall pbuf == union cfs_downcalls yet
     82  1.1  rvb  *
     83  1.1  rvb  * Revision 1.5.4.7  97/11/20  11:46:42  rvb
     84  1.1  rvb  * Capture current cfs_venus
     85  1.1  rvb  *
     86  1.1  rvb  * Revision 1.5.4.6  97/11/18  10:27:16  rvb
     87  1.1  rvb  * cfs_nbsd.c is DEAD!!!; integrated into cfs_vf/vnops.c
     88  1.1  rvb  * cfs_nb_foo and cfs_foo are joined
     89  1.1  rvb  *
     90  1.1  rvb  * Revision 1.5.4.5  97/11/13  22:03:00  rvb
     91  1.1  rvb  * pass2 cfs_NetBSD.h mt
     92  1.1  rvb  *
     93  1.1  rvb  * Revision 1.5.4.4  97/11/12  12:09:39  rvb
     94  1.1  rvb  * reorg pass1
     95  1.1  rvb  *
     96  1.1  rvb  * Revision 1.5.4.3  97/11/06  21:02:38  rvb
     97  1.1  rvb  * first pass at ^c ^z
     98  1.1  rvb  *
     99  1.1  rvb  * Revision 1.5.4.2  97/10/29  16:06:27  rvb
    100  1.1  rvb  * Kill DYING
    101  1.1  rvb  *
    102  1.1  rvb  * Revision 1.5.4.1  97/10/28 23:10:16  rvb
    103  1.1  rvb  * >64Meg; venus can be killed!
    104  1.1  rvb  *
    105  1.1  rvb  * Revision 1.5  97/08/05  11:08:17  lily
    106  1.1  rvb  * Removed cfsnc_replace, replaced it with a cfs_find, unhash, and
    107  1.1  rvb  * rehash.  This fixes a cnode leak and a bug in which the fid is
    108  1.1  rvb  * not actually replaced.  (cfs_namecache.c, cfsnc.h, cfs_subr.c)
    109  1.1  rvb  *
    110  1.1  rvb  * Revision 1.4  96/12/12  22:10:59  bnoble
    111  1.1  rvb  * Fixed the "downcall invokes venus operation" deadlock in all known cases.
    112  1.1  rvb  * There may be more
    113  1.1  rvb  *
    114  1.1  rvb  * Revision 1.3  1996/12/05 16:20:15  bnoble
    115  1.1  rvb  * Minor debugging aids
    116  1.1  rvb  *
    117  1.1  rvb  * Revision 1.2  1996/01/02 16:57:01  bnoble
    118  1.1  rvb  * Added support for Coda MiniCache and raw inode calls (final commit)
    119  1.1  rvb  *
    120  1.1  rvb  * Revision 1.1.2.1  1995/12/20 01:57:27  bnoble
    121  1.1  rvb  * Added CFS-specific files
    122  1.1  rvb  *
    123  1.1  rvb  * Revision 3.1.1.1  1995/03/04  19:07:59  bnoble
    124  1.1  rvb  * Branch for NetBSD port revisions
    125  1.1  rvb  *
    126  1.1  rvb  * Revision 3.1  1995/03/04  19:07:58  bnoble
    127  1.1  rvb  * Bump to major revision 3 to prepare for NetBSD port
    128  1.1  rvb  *
    129  1.1  rvb  * Revision 2.8  1995/03/03  17:00:04  dcs
    130  1.1  rvb  * Fixed kernel bug involving sleep and upcalls. Basically if you killed
    131  1.1  rvb  * a job waiting on venus, the venus upcall queues got trashed. Depending
    132  1.1  rvb  * on luck, you could kill the kernel or not.
    133  1.1  rvb  * (mods to cfs_subr.c and cfs_mach.d)
    134  1.1  rvb  *
    135  1.1  rvb  * Revision 2.7  95/03/02  22:45:21  dcs
    136  1.1  rvb  * Sun4 compatibility
    137  1.1  rvb  *
    138  1.1  rvb  * Revision 2.6  95/02/17  16:25:17  dcs
    139  1.1  rvb  * These versions represent several changes:
    140  1.1  rvb  * 1. Allow venus to restart even if outstanding references exist.
    141  1.1  rvb  * 2. Have only one ctlvp per client, as opposed to one per mounted cfs device.d
    142  1.1  rvb  * 3. Allow ody_expand to return many members, not just one.
    143  1.1  rvb  *
    144  1.1  rvb  * Revision 2.5  94/11/09  15:56:26  dcs
    145  1.1  rvb  * Had the thread sleeping on the wrong thing!
    146  1.1  rvb  *
    147  1.1  rvb  * Revision 2.4  94/10/14  09:57:57  dcs
    148  1.1  rvb  * Made changes 'cause sun4s have braindead compilers
    149  1.1  rvb  *
    150  1.1  rvb  * Revision 2.3  94/10/12  16:46:26  dcs
    151  1.1  rvb  * Cleaned kernel/venus interface by removing XDR junk, plus
    152  1.1  rvb  * so cleanup to allow this code to be more easily ported.
    153  1.1  rvb  *
    154  1.1  rvb  * Revision 1.2  92/10/27  17:58:22  lily
    155  1.1  rvb  * merge kernel/latest and alpha/src/cfs
    156  1.1  rvb  *
    157  1.1  rvb  * Revision 2.4  92/09/30  14:16:26  mja
    158  1.1  rvb  * 	Incorporated Dave Steere's fix for the GNU-Emacs bug.
    159  1.1  rvb  * 	Also, included his cfs_flush routine in place of the former cfsnc_flush.
    160  1.1  rvb  * 	[91/02/07            jjk]
    161  1.1  rvb  *
    162  1.1  rvb  * 	Added contributors blurb.
    163  1.1  rvb  * 	[90/12/13            jjk]
    164  1.1  rvb  *
    165  1.1  rvb  * 	Hack to allow users to keep coda venus calls uninterruptible. THis
    166  1.1  rvb  * 	basically prevents the Gnu-emacs bug from appearing, in which a call
    167  1.1  rvb  * 	was being interrupted, and return EINTR, but gnu didn't check for the
    168  1.1  rvb  * 	error and figured the file was buggered.
    169  1.1  rvb  * 	[90/12/09            dcs]
    170  1.1  rvb  *
    171  1.1  rvb  * Revision 2.3  90/08/10  10:23:20  mrt
    172  1.1  rvb  * 	Removed include of vm/vm_page.h as it no longer exists.
    173  1.1  rvb  * 	[90/08/10            mrt]
    174  1.1  rvb  *
    175  1.1  rvb  * Revision 2.2  90/07/05  11:26:35  mrt
    176  1.1  rvb  * 	Initialize name cache on first call to vcopen.
    177  1.1  rvb  * 	[90/05/23            dcs]
    178  1.1  rvb  *
    179  1.1  rvb  * 	Created for the Coda File System.
    180  1.1  rvb  * 	[90/05/23            dcs]
    181  1.1  rvb  *
    182  1.1  rvb  * Revision 1.5  90/05/31  17:01:35  dcs
    183  1.1  rvb  * Prepare for merge with facilities kernel.
    184  1.1  rvb  *
    185  1.1  rvb  * Revision 1.2  90/03/19  15:56:25  dcs
    186  1.1  rvb  * Initialize name cache on first call to vcopen.
    187  1.1  rvb  *
    188  1.1  rvb  * Revision 1.1  90/03/15  10:43:26  jjk
    189  1.1  rvb  * Initial revision
    190  1.1  rvb  *
    191  1.1  rvb  */
    192  1.1  rvb 
    193  1.1  rvb /* NOTES: rvb
    194  1.1  rvb  * 1.	Added cfs_unmounting to mark all cnodes as being UNMOUNTING.  This has to
    195  1.1  rvb  *	 be done before dounmount is called.  Because some of the routines that
    196  1.1  rvb  *	 dounmount calls before cfs_unmounted might try to force flushes to venus.
    197  1.1  rvb  *	 The vnode pager does this.
    198  1.1  rvb  * 2.	cfs_unmounting marks all cnodes scanning cfs_cache.
    199  1.1  rvb  * 3.	cfs_checkunmounting (under DEBUG) checks all cnodes by chasing the vnodes
    200  1.1  rvb  *	 under the /coda mount point.
    201  1.1  rvb  * 4.	cfs_cacheprint (under DEBUG) prints names with vnode/cnode address
    202  1.1  rvb  */
    203  1.1  rvb 
    204  1.1  rvb #include <vcfs.h>
    205  1.1  rvb 
    206  1.1  rvb #include <sys/param.h>
    207  1.1  rvb #include <sys/systm.h>
    208  1.1  rvb #include <sys/malloc.h>
    209  1.1  rvb #include <sys/proc.h>
    210  1.1  rvb #include <sys/select.h>
    211  1.1  rvb #include <sys/mount.h>
    212  1.1  rvb 
    213  1.1  rvb #include <cfs/coda.h>
    214  1.1  rvb #include <cfs/cnode.h>
    215  1.1  rvb #include <cfs/cfs_subr.h>
    216  1.1  rvb #include <cfs/cfsnc.h>
    217  1.1  rvb 
    218  1.1  rvb #if	NVCFS
    219  1.1  rvb 
    220  1.1  rvb int cfs_active = 0;
    221  1.1  rvb int cfs_reuse = 0;
    222  1.1  rvb int cfs_new = 0;
    223  1.1  rvb 
    224  1.1  rvb struct cnode *cfs_freelist = NULL;
    225  1.1  rvb struct cnode *cfs_cache[CFS_CACHESIZE];
    226  1.1  rvb 
    227  1.1  rvb #define cfshash(fid) \
    228  1.1  rvb     (((fid)->Volume + (fid)->Vnode) & (CFS_CACHESIZE-1))
    229  1.1  rvb 
    230  1.1  rvb #define	CNODE_NEXT(cp)	((cp)->c_next)
    231  1.1  rvb 
    232  1.1  rvb #define ODD(vnode)        ((vnode) & 0x1)
    233  1.1  rvb 
    234  1.1  rvb /*
    235  1.1  rvb  * Allocate a cnode.
    236  1.1  rvb  */
    237  1.1  rvb struct cnode *
    238  1.1  rvb cfs_alloc(void)
    239  1.1  rvb {
    240  1.1  rvb     struct cnode *cp;
    241  1.1  rvb 
    242  1.1  rvb     if (cfs_freelist) {
    243  1.1  rvb 	cp = cfs_freelist;
    244  1.1  rvb 	cfs_freelist = CNODE_NEXT(cp);
    245  1.1  rvb 	cfs_reuse++;
    246  1.1  rvb     }
    247  1.1  rvb     else {
    248  1.1  rvb 	CFS_ALLOC(cp, struct cnode *, sizeof(struct cnode));
    249  1.1  rvb 	/* NetBSD vnodes don't have any Pager info in them ('cause there are
    250  1.1  rvb 	   no external pagers, duh!) */
    251  1.1  rvb #define VNODE_VM_INFO_INIT(vp)         /* MT */
    252  1.1  rvb 	VNODE_VM_INFO_INIT(CTOV(cp));
    253  1.1  rvb 	cfs_new++;
    254  1.1  rvb     }
    255  1.1  rvb     bzero(cp, sizeof (struct cnode));
    256  1.1  rvb 
    257  1.1  rvb     return(cp);
    258  1.1  rvb }
    259  1.1  rvb 
    260  1.1  rvb /*
    261  1.1  rvb  * Deallocate a cnode.
    262  1.1  rvb  */
    263  1.1  rvb void
    264  1.1  rvb cfs_free(cp)
    265  1.1  rvb      register struct cnode *cp;
    266  1.1  rvb {
    267  1.1  rvb 
    268  1.1  rvb     CNODE_NEXT(cp) = cfs_freelist;
    269  1.1  rvb     cfs_freelist = cp;
    270  1.1  rvb }
    271  1.1  rvb 
    272  1.1  rvb /*
    273  1.1  rvb  * Put a cnode in the hash table
    274  1.1  rvb  */
    275  1.1  rvb void
    276  1.1  rvb cfs_save(cp)
    277  1.1  rvb      struct cnode *cp;
    278  1.1  rvb {
    279  1.1  rvb 	CNODE_NEXT(cp) = cfs_cache[cfshash(&cp->c_fid)];
    280  1.1  rvb 	cfs_cache[cfshash(&cp->c_fid)] = cp;
    281  1.1  rvb }
    282  1.1  rvb 
    283  1.1  rvb /*
    284  1.1  rvb  * Remove a cnode from the hash table
    285  1.1  rvb  */
    286  1.1  rvb void
    287  1.1  rvb cfs_unsave(cp)
    288  1.1  rvb      struct cnode *cp;
    289  1.1  rvb {
    290  1.1  rvb     struct cnode *ptr;
    291  1.1  rvb     struct cnode *ptrprev = NULL;
    292  1.1  rvb 
    293  1.1  rvb     ptr = cfs_cache[cfshash(&cp->c_fid)];
    294  1.1  rvb     while (ptr != NULL) {
    295  1.1  rvb 	if (ptr == cp) {
    296  1.1  rvb 	    if (ptrprev == NULL) {
    297  1.1  rvb 		cfs_cache[cfshash(&cp->c_fid)]
    298  1.1  rvb 		    = CNODE_NEXT(ptr);
    299  1.1  rvb 	    } else {
    300  1.1  rvb 		CNODE_NEXT(ptrprev) = CNODE_NEXT(ptr);
    301  1.1  rvb 	    }
    302  1.1  rvb 	    CNODE_NEXT(cp) = (struct cnode *)NULL;
    303  1.1  rvb 
    304  1.1  rvb 	    return;
    305  1.1  rvb 	}
    306  1.1  rvb 	ptrprev = ptr;
    307  1.1  rvb 	ptr = CNODE_NEXT(ptr);
    308  1.1  rvb     }
    309  1.1  rvb }
    310  1.1  rvb 
    311  1.1  rvb /*
    312  1.1  rvb  * Lookup a cnode by fid. If the cnode is dying, it is bogus so skip it.
    313  1.1  rvb  * NOTE: this allows multiple cnodes with same fid -- dcs 1/25/95
    314  1.1  rvb  */
    315  1.1  rvb struct cnode *
    316  1.1  rvb cfs_find(fid)
    317  1.1  rvb      ViceFid *fid;
    318  1.1  rvb {
    319  1.1  rvb     struct cnode *cp;
    320  1.1  rvb 
    321  1.1  rvb     cp = cfs_cache[cfshash(fid)];
    322  1.1  rvb     while (cp) {
    323  1.1  rvb 	if ((cp->c_fid.Vnode == fid->Vnode) &&
    324  1.1  rvb 	    (cp->c_fid.Volume == fid->Volume) &&
    325  1.1  rvb 	    (cp->c_fid.Unique == fid->Unique) &&
    326  1.1  rvb 	    (!IS_UNMOUNTING(cp)))
    327  1.1  rvb 	    {
    328  1.1  rvb 		cfs_active++;
    329  1.1  rvb 		return(cp);
    330  1.1  rvb 	    }
    331  1.1  rvb 	cp = CNODE_NEXT(cp);
    332  1.1  rvb     }
    333  1.1  rvb     return(NULL);
    334  1.1  rvb }
    335  1.1  rvb 
    336  1.1  rvb /*
    337  1.1  rvb  * cfs_kill is called as a side effect to vcopen. To prevent any
    338  1.1  rvb  * cnodes left around from an earlier run of a venus or warden from
    339  1.1  rvb  * causing problems with the new instance, mark any outstanding cnodes
    340  1.1  rvb  * as dying. Future operations on these cnodes should fail (excepting
    341  1.1  rvb  * cfs_inactive of course!). Since multiple venii/wardens can be
    342  1.1  rvb  * running, only kill the cnodes for a particular entry in the
    343  1.1  rvb  * cfs_mnttbl. -- DCS 12/1/94 */
    344  1.1  rvb 
    345  1.1  rvb int
    346  1.1  rvb cfs_kill(whoIam, dcstat)
    347  1.1  rvb 	struct mount *whoIam;
    348  1.1  rvb 	enum dc_status dcstat;
    349  1.1  rvb {
    350  1.1  rvb 	int hash, count = 0;
    351  1.1  rvb 	struct cnode *cp;
    352  1.1  rvb 
    353  1.1  rvb 	/*
    354  1.1  rvb 	 * Algorithm is as follows:
    355  1.1  rvb 	 *     Second, flush whatever vnodes we can from the name cache.
    356  1.1  rvb 	 *
    357  1.1  rvb 	 *     Finally, step through whatever is left and mark them dying.
    358  1.1  rvb 	 *        This prevents any operation at all.
    359  1.1  rvb 	 */
    360  1.1  rvb 
    361  1.1  rvb 	/* This is slightly overkill, but should work. Eventually it'd be
    362  1.1  rvb 	 * nice to only flush those entries from the namecache that
    363  1.1  rvb 	 * reference a vnode in this vfs.  */
    364  1.1  rvb 	cfsnc_flush(dcstat);
    365  1.1  rvb 
    366  1.1  rvb 	for (hash = 0; hash < CFS_CACHESIZE; hash++) {
    367  1.1  rvb 		for (cp = cfs_cache[hash]; cp != NULL; cp = CNODE_NEXT(cp)) {
    368  1.1  rvb 			if (CTOV(cp)->v_mount == whoIam) {
    369  1.1  rvb #ifdef	DEBUG
    370  1.1  rvb 				printf("cfs_kill: vp %p, cp %p\n", CTOV(cp), cp);
    371  1.1  rvb #endif
    372  1.1  rvb 				count++;
    373  1.1  rvb 				CFSDEBUG(CFS_FLUSH,
    374  1.1  rvb 					 myprintf(("Live cnode fid %lx.%lx.%lx flags %d count %d\n",
    375  1.1  rvb 						   (cp->c_fid).Volume,
    376  1.1  rvb 						   (cp->c_fid).Vnode,
    377  1.1  rvb 						   (cp->c_fid).Unique,
    378  1.1  rvb 						   cp->c_flags,
    379  1.1  rvb 						   CTOV(cp)->v_usecount)); );
    380  1.1  rvb 			}
    381  1.1  rvb 		}
    382  1.1  rvb 	}
    383  1.1  rvb 	return count;
    384  1.1  rvb }
    385  1.1  rvb 
    386  1.1  rvb /*
    387  1.1  rvb  * There are two reasons why a cnode may be in use, it may be in the
    388  1.1  rvb  * name cache or it may be executing.
    389  1.1  rvb  */
    390  1.1  rvb void
    391  1.1  rvb cfs_flush(dcstat)
    392  1.1  rvb 	enum dc_status dcstat;
    393  1.1  rvb {
    394  1.1  rvb     int hash;
    395  1.1  rvb     struct cnode *cp;
    396  1.1  rvb 
    397  1.1  rvb     cfs_clstat.ncalls++;
    398  1.1  rvb     cfs_clstat.reqs[CFS_FLUSH]++;
    399  1.1  rvb 
    400  1.1  rvb     cfsnc_flush(dcstat);	    /* flush files from the name cache */
    401  1.1  rvb 
    402  1.1  rvb     for (hash = 0; hash < CFS_CACHESIZE; hash++) {
    403  1.1  rvb 	for (cp = cfs_cache[hash]; cp != NULL; cp = CNODE_NEXT(cp)) {
    404  1.1  rvb 	    if (!ODD(cp->c_fid.Vnode)) /* only files can be executed */
    405  1.1  rvb 		cfs_vmflush(cp);
    406  1.1  rvb 	}
    407  1.1  rvb     }
    408  1.1  rvb }
    409  1.1  rvb 
    410  1.1  rvb /*
    411  1.1  rvb  * As a debugging measure, print out any cnodes that lived through a
    412  1.1  rvb  * name cache flush.
    413  1.1  rvb  */
    414  1.1  rvb void
    415  1.1  rvb cfs_testflush(void)
    416  1.1  rvb {
    417  1.1  rvb     int hash;
    418  1.1  rvb     struct cnode *cp;
    419  1.1  rvb 
    420  1.1  rvb     for (hash = 0; hash < CFS_CACHESIZE; hash++) {
    421  1.1  rvb 	for (cp = cfs_cache[hash];
    422  1.1  rvb 	     cp != NULL;
    423  1.1  rvb 	     cp = CNODE_NEXT(cp)) {
    424  1.1  rvb 	    myprintf(("Live cnode fid %lx.%lx.%lx count %d\n",
    425  1.1  rvb 		      (cp->c_fid).Volume,(cp->c_fid).Vnode,
    426  1.1  rvb 		      (cp->c_fid).Unique, CTOV(cp)->v_usecount));
    427  1.1  rvb 	}
    428  1.1  rvb     }
    429  1.1  rvb }
    430  1.1  rvb 
    431  1.1  rvb /*
    432  1.1  rvb  *     First, step through all cnodes and mark them unmounting.
    433  1.1  rvb  *         NetBSD kernels may try to fsync them now that venus
    434  1.1  rvb  *         is dead, which would be a bad thing.
    435  1.1  rvb  *
    436  1.1  rvb  */
    437  1.1  rvb void
    438  1.1  rvb cfs_unmounting(whoIam)
    439  1.1  rvb 	struct mount *whoIam;
    440  1.1  rvb {
    441  1.1  rvb 	int hash;
    442  1.1  rvb 	struct cnode *cp;
    443  1.1  rvb 
    444  1.1  rvb 	for (hash = 0; hash < CFS_CACHESIZE; hash++) {
    445  1.1  rvb 		for (cp = cfs_cache[hash]; cp != NULL; cp = CNODE_NEXT(cp)) {
    446  1.1  rvb 			if (CTOV(cp)->v_mount == whoIam) {
    447  1.1  rvb 				if (cp->c_flags & (C_LOCKED|C_WANTED)) {
    448  1.1  rvb 					printf("cfs_unmounting: Unlocking %p\n", cp);
    449  1.1  rvb 					cp->c_flags &= ~(C_LOCKED|C_WANTED);
    450  1.1  rvb 					wakeup((caddr_t) cp);
    451  1.1  rvb 				}
    452  1.1  rvb 				cp->c_flags |= C_UNMOUNTING;
    453  1.1  rvb 			}
    454  1.1  rvb 		}
    455  1.1  rvb 	}
    456  1.1  rvb }
    457  1.1  rvb 
    458  1.1  rvb #ifdef	DEBUG
    459  1.1  rvb cfs_checkunmounting(mp)
    460  1.1  rvb 	struct mount *mp;
    461  1.1  rvb {
    462  1.1  rvb 	register struct vnode *vp, *nvp;
    463  1.1  rvb 	struct cnode *cp;
    464  1.1  rvb 	int count = 0, bad = 0;
    465  1.1  rvb loop:
    466  1.1  rvb 	for (vp = mp->mnt_vnodelist.lh_first; vp; vp = nvp) {
    467  1.1  rvb 		if (vp->v_mount != mp)
    468  1.1  rvb 			goto loop;
    469  1.1  rvb 		nvp = vp->v_mntvnodes.le_next;
    470  1.1  rvb 		cp = VTOC(vp);
    471  1.1  rvb 		count++;
    472  1.1  rvb 		if (!(cp->c_flags & C_UNMOUNTING)) {
    473  1.1  rvb 			bad++;
    474  1.1  rvb 			printf("vp %p, cp %p missed\n", vp, cp);
    475  1.1  rvb 			cp->c_flags |= C_UNMOUNTING;
    476  1.1  rvb 		}
    477  1.1  rvb 	}
    478  1.1  rvb }
    479  1.1  rvb 
    480  1.1  rvb int
    481  1.1  rvb cfs_cacheprint(whoIam)
    482  1.1  rvb 	struct mount *whoIam;
    483  1.1  rvb {
    484  1.1  rvb 	int hash;
    485  1.1  rvb 	struct cnode *cp;
    486  1.1  rvb 	int count = 0;
    487  1.1  rvb 
    488  1.1  rvb 	printf("cfs_cacheprint: cfs_ctlvp %p, cp %p", cfs_ctlvp, VTOC(cfs_ctlvp));
    489  1.1  rvb 	cfsnc_name(cfs_ctlvp);
    490  1.1  rvb 	printf("\n");
    491  1.1  rvb 
    492  1.1  rvb 	for (hash = 0; hash < CFS_CACHESIZE; hash++) {
    493  1.1  rvb 		for (cp = cfs_cache[hash]; cp != NULL; cp = CNODE_NEXT(cp)) {
    494  1.1  rvb 			if (CTOV(cp)->v_mount == whoIam) {
    495  1.1  rvb 				printf("cfs_cacheprint: vp %p, cp %p", CTOV(cp), cp);
    496  1.1  rvb 				cfsnc_name(cp);
    497  1.1  rvb 				printf("\n");
    498  1.1  rvb 				count++;
    499  1.1  rvb 			}
    500  1.1  rvb 		}
    501  1.1  rvb 	}
    502  1.1  rvb 	printf("cfs_cacheprint: count %d\n", count);
    503  1.1  rvb }
    504  1.1  rvb #endif
    505  1.1  rvb 
    506  1.1  rvb /*
    507  1.1  rvb  * There are 6 cases where invalidations occur. The semantics of each
    508  1.1  rvb  * is listed here.
    509  1.1  rvb  *
    510  1.1  rvb  * CFS_FLUSH     -- flush all entries from the name cache and the cnode cache.
    511  1.1  rvb  * CFS_PURGEUSER -- flush all entries from the name cache for a specific user
    512  1.1  rvb  *                  This call is a result of token expiration.
    513  1.1  rvb  *
    514  1.1  rvb  * The next two are the result of callbacks on a file or directory.
    515  1.1  rvb  * CFS_ZAPDIR    -- flush the attributes for the dir from its cnode.
    516  1.1  rvb  *                  Zap all children of this directory from the namecache.
    517  1.1  rvb  * CFS_ZAPFILE   -- flush the attributes for a file.
    518  1.1  rvb  *
    519  1.1  rvb  * The fifth is a result of Venus detecting an inconsistent file.
    520  1.1  rvb  * CFS_PURGEFID  -- flush the attribute for the file
    521  1.1  rvb  *                  If it is a dir (odd vnode), purge its
    522  1.1  rvb  *                  children from the namecache
    523  1.1  rvb  *                  remove the file from the namecache.
    524  1.1  rvb  *
    525  1.1  rvb  * The sixth allows Venus to replace local fids with global ones
    526  1.1  rvb  * during reintegration.
    527  1.1  rvb  *
    528  1.1  rvb  * CFS_REPLACE -- replace one ViceFid with another throughout the name cache
    529  1.1  rvb  */
    530  1.1  rvb 
    531  1.1  rvb int handleDownCall(opcode, out)
    532  1.1  rvb      int opcode; union outputArgs *out;
    533  1.1  rvb {
    534  1.1  rvb     int error;
    535  1.1  rvb 
    536  1.1  rvb     /* Handle invalidate requests. */
    537  1.1  rvb     switch (opcode) {
    538  1.1  rvb       case CFS_FLUSH : {
    539  1.1  rvb 
    540  1.1  rvb 	  cfs_flush(IS_DOWNCALL);
    541  1.1  rvb 
    542  1.1  rvb 	  CFSDEBUG(CFS_FLUSH,cfs_testflush();)    /* print remaining cnodes */
    543  1.1  rvb 	      return(0);
    544  1.1  rvb       }
    545  1.1  rvb 
    546  1.1  rvb       case CFS_PURGEUSER : {
    547  1.1  rvb 	  cfs_clstat.ncalls++;
    548  1.1  rvb 	  cfs_clstat.reqs[CFS_PURGEUSER]++;
    549  1.1  rvb 
    550  1.1  rvb 	  /* XXX - need to prevent fsync's */
    551  1.1  rvb 	  cfsnc_purge_user(out->cfs_purgeuser.cred.cr_uid, IS_DOWNCALL);
    552  1.1  rvb 	  return(0);
    553  1.1  rvb       }
    554  1.1  rvb 
    555  1.1  rvb       case CFS_ZAPFILE : {
    556  1.1  rvb 	  struct cnode *cp;
    557  1.1  rvb 
    558  1.1  rvb 	  error = 0;
    559  1.1  rvb 	  cfs_clstat.ncalls++;
    560  1.1  rvb 	  cfs_clstat.reqs[CFS_ZAPFILE]++;
    561  1.1  rvb 
    562  1.1  rvb 	  cp = cfs_find(&out->cfs_zapfile.CodaFid);
    563  1.1  rvb 	  if (cp != NULL) {
    564  1.1  rvb 	      vref(CTOV(cp));
    565  1.1  rvb 
    566  1.1  rvb 	      cp->c_flags &= ~C_VATTR;
    567  1.1  rvb 	      if (CTOV(cp)->v_flag & VTEXT)
    568  1.1  rvb 		  error = cfs_vmflush(cp);
    569  1.1  rvb 	      CFSDEBUG(CFS_ZAPFILE, myprintf(("zapfile: fid = (%lx.%lx.%lx),
    570  1.1  rvb                                               refcnt = %d, error = %d\n",
    571  1.1  rvb 					      cp->c_fid.Volume,
    572  1.1  rvb 					      cp->c_fid.Vnode,
    573  1.1  rvb 					      cp->c_fid.Unique,
    574  1.1  rvb 					      CTOV(cp)->v_usecount - 1, error)););
    575  1.1  rvb 	      if (CTOV(cp)->v_usecount == 1) {
    576  1.1  rvb 		  cp->c_flags |= C_PURGING;
    577  1.1  rvb 	      }
    578  1.1  rvb 	      vrele(CTOV(cp));
    579  1.1  rvb 	  }
    580  1.1  rvb 
    581  1.1  rvb 	  return(error);
    582  1.1  rvb       }
    583  1.1  rvb 
    584  1.1  rvb       case CFS_ZAPDIR : {
    585  1.1  rvb 	  struct cnode *cp;
    586  1.1  rvb 
    587  1.1  rvb 	  cfs_clstat.ncalls++;
    588  1.1  rvb 	  cfs_clstat.reqs[CFS_ZAPDIR]++;
    589  1.1  rvb 
    590  1.1  rvb 	  cp = cfs_find(&out->cfs_zapdir.CodaFid);
    591  1.1  rvb 	  if (cp != NULL) {
    592  1.1  rvb 	      vref(CTOV(cp));
    593  1.1  rvb 
    594  1.1  rvb 	      cp->c_flags &= ~C_VATTR;
    595  1.1  rvb 	      cfsnc_zapParentfid(&out->cfs_zapdir.CodaFid, IS_DOWNCALL);
    596  1.1  rvb 
    597  1.1  rvb 	      CFSDEBUG(CFS_ZAPDIR, myprintf(("zapdir: fid = (%lx.%lx.%lx),
    598  1.1  rvb                                           refcnt = %d\n",cp->c_fid.Volume,
    599  1.1  rvb 					     cp->c_fid.Vnode,
    600  1.1  rvb 					     cp->c_fid.Unique,
    601  1.1  rvb 					     CTOV(cp)->v_usecount - 1)););
    602  1.1  rvb 	      if (CTOV(cp)->v_usecount == 1) {
    603  1.1  rvb 		  cp->c_flags |= C_PURGING;
    604  1.1  rvb 	      }
    605  1.1  rvb 	      vrele(CTOV(cp));
    606  1.1  rvb 	  }
    607  1.1  rvb 
    608  1.1  rvb 	  return(0);
    609  1.1  rvb       }
    610  1.1  rvb 
    611  1.1  rvb       case CFS_ZAPVNODE : {
    612  1.1  rvb 	  cfs_clstat.ncalls++;
    613  1.1  rvb 	  cfs_clstat.reqs[CFS_ZAPVNODE]++;
    614  1.1  rvb 
    615  1.1  rvb 	  myprintf(("CFS_ZAPVNODE: Called, but uniplemented\n"));
    616  1.1  rvb 	  /*
    617  1.1  rvb 	   * Not that below we must really translate the returned coda_cred to
    618  1.1  rvb 	   * a netbsd cred.  This is a bit muddled at present and the cfsnc_zapnode
    619  1.1  rvb 	   * is further unimplemented, so punt!
    620  1.1  rvb 	   * I suppose we could use just the uid.
    621  1.1  rvb 	   */
    622  1.1  rvb 	  /* cfsnc_zapvnode(&out->cfs_zapvnode.VFid, &out->cfs_zapvnode.cred,
    623  1.1  rvb 			 IS_DOWNCALL); */
    624  1.1  rvb 	  return(0);
    625  1.1  rvb       }
    626  1.1  rvb 
    627  1.1  rvb       case CFS_PURGEFID : {
    628  1.1  rvb 	  struct cnode *cp;
    629  1.1  rvb 
    630  1.1  rvb 	  error = 0;
    631  1.1  rvb 	  cfs_clstat.ncalls++;
    632  1.1  rvb 	  cfs_clstat.reqs[CFS_PURGEFID]++;
    633  1.1  rvb 
    634  1.1  rvb 	  cp = cfs_find(&out->cfs_purgefid.CodaFid);
    635  1.1  rvb 	  if (cp != NULL) {
    636  1.1  rvb 	      vref(CTOV(cp));
    637  1.1  rvb 	      if (ODD(out->cfs_purgefid.CodaFid.Vnode)) { /* Vnode is a directory */
    638  1.1  rvb 		  cfsnc_zapParentfid(&out->cfs_purgefid.CodaFid,
    639  1.1  rvb 				     IS_DOWNCALL);
    640  1.1  rvb 	      }
    641  1.1  rvb 	      cp->c_flags &= ~C_VATTR;
    642  1.1  rvb 	      cfsnc_zapfid(&out->cfs_purgefid.CodaFid, IS_DOWNCALL);
    643  1.1  rvb 	      if (!(ODD(out->cfs_purgefid.CodaFid.Vnode))
    644  1.1  rvb 		  && (CTOV(cp)->v_flag & VTEXT)) {
    645  1.1  rvb 
    646  1.1  rvb 		  error = cfs_vmflush(cp);
    647  1.1  rvb 	      }
    648  1.1  rvb 	      CFSDEBUG(CFS_PURGEFID, myprintf(("purgefid: fid = (%lx.%lx.%lx), refcnt = %d, error = %d\n",
    649  1.1  rvb                                             cp->c_fid.Volume, cp->c_fid.Vnode,
    650  1.1  rvb                                             cp->c_fid.Unique,
    651  1.1  rvb 					    CTOV(cp)->v_usecount - 1, error)););
    652  1.1  rvb 	      if (CTOV(cp)->v_usecount == 1) {
    653  1.1  rvb 		  cp->c_flags |= C_PURGING;
    654  1.1  rvb 	      }
    655  1.1  rvb 	      vrele(CTOV(cp));
    656  1.1  rvb 	  }
    657  1.1  rvb 	  return(error);
    658  1.1  rvb       }
    659  1.1  rvb 
    660  1.1  rvb       case CFS_REPLACE : {
    661  1.1  rvb 	  struct cnode *cp = NULL;
    662  1.1  rvb 
    663  1.1  rvb 	  cfs_clstat.ncalls++;
    664  1.1  rvb 	  cfs_clstat.reqs[CFS_REPLACE]++;
    665  1.1  rvb 
    666  1.1  rvb 	  cp = cfs_find(&out->cfs_replace.OldFid);
    667  1.1  rvb 	  if (cp != NULL) {
    668  1.1  rvb 	      /* remove the cnode from the hash table, replace the fid, and reinsert */
    669  1.1  rvb 	      vref(CTOV(cp));
    670  1.1  rvb 	      cfs_unsave(cp);
    671  1.1  rvb 	      cp->c_fid = out->cfs_replace.NewFid;
    672  1.1  rvb 	      cfs_save(cp);
    673  1.1  rvb 
    674  1.1  rvb 	      CFSDEBUG(CFS_REPLACE, myprintf(("replace: oldfid = (%lx.%lx.%lx), newfid = (%lx.%lx.%lx), cp = %p\n",
    675  1.1  rvb 					   out->cfs_replace.OldFid.Volume,
    676  1.1  rvb 					   out->cfs_replace.OldFid.Vnode,
    677  1.1  rvb 					   out->cfs_replace.OldFid.Unique,
    678  1.1  rvb 					   cp->c_fid.Volume, cp->c_fid.Vnode,
    679  1.1  rvb 					   cp->c_fid.Unique, cp));)
    680  1.1  rvb 	      vrele(CTOV(cp));
    681  1.1  rvb 	  }
    682  1.1  rvb 	  return (0);
    683  1.1  rvb       }
    684  1.1  rvb       default:
    685  1.1  rvb       	myprintf(("handleDownCall: unknown opcode %d\n", opcode));
    686  1.1  rvb 	return (EINVAL);
    687  1.1  rvb     }
    688  1.1  rvb }
    689  1.1  rvb 
    690  1.1  rvb /* cfs_grab_vnode: lives in either cfs_mach.c or cfs_nbsd.c */
    691  1.1  rvb 
    692  1.1  rvb int
    693  1.1  rvb cfs_vmflush(cp)
    694  1.1  rvb      struct cnode *cp;
    695  1.1  rvb {
    696  1.1  rvb #if	0
    697  1.1  rvb   /* old code */
    698  1.1  rvb     /* Unset <device, inode> so that page_read doesn't try to use
    699  1.1  rvb        (possibly) invalid cache file. */
    700  1.1  rvb     cp->c_device = 0;
    701  1.1  rvb     cp->c_inode = 0;
    702  1.1  rvb 
    703  1.1  rvb     return(inode_uncache_try(VTOI(CTOV(cp))) ? 0 : ETXTBSY);
    704  1.1  rvb #else /* __NetBSD__ || __FreeBSD__ */
    705  1.1  rvb     return 0;
    706  1.1  rvb #endif /* __NetBSD__ || __FreeBSD__ */
    707  1.1  rvb }
    708  1.1  rvb 
    709  1.1  rvb 
    710  1.1  rvb /*
    711  1.1  rvb  * kernel-internal debugging switches
    712  1.1  rvb  */
    713  1.1  rvb 
    714  1.1  rvb void cfs_debugon(void)
    715  1.1  rvb {
    716  1.1  rvb     cfsdebug = -1;
    717  1.1  rvb     cfsnc_debug = -1;
    718  1.1  rvb     cfs_vnop_print_entry = 1;
    719  1.1  rvb     cfs_psdev_print_entry = 1;
    720  1.1  rvb     cfs_vfsop_print_entry = 1;
    721  1.1  rvb }
    722  1.1  rvb 
    723  1.1  rvb void cfs_debugoff(void)
    724  1.1  rvb {
    725  1.1  rvb     cfsdebug = 0;
    726  1.1  rvb     cfsnc_debug = 0;
    727  1.1  rvb     cfs_vnop_print_entry = 0;
    728  1.1  rvb     cfs_psdev_print_entry = 0;
    729  1.1  rvb     cfs_vfsop_print_entry = 0;
    730  1.1  rvb }
    731  1.1  rvb 
    732  1.1  rvb /*
    733  1.1  rvb  * Utilities used by both client and server
    734  1.1  rvb  * Standard levels:
    735  1.1  rvb  * 0) no debugging
    736  1.1  rvb  * 1) hard failures
    737  1.1  rvb  * 2) soft failures
    738  1.1  rvb  * 3) current test software
    739  1.1  rvb  * 4) main procedure entry points
    740  1.1  rvb  * 5) main procedure exit points
    741  1.1  rvb  * 6) utility procedure entry points
    742  1.1  rvb  * 7) utility procedure exit points
    743  1.1  rvb  * 8) obscure procedure entry points
    744  1.1  rvb  * 9) obscure procedure exit points
    745  1.1  rvb  * 10) random stuff
    746  1.1  rvb  * 11) all <= 1
    747  1.1  rvb  * 12) all <= 2
    748  1.1  rvb  * 13) all <= 3
    749  1.1  rvb  * ...
    750  1.1  rvb  */
    751           
    752           
    753           #endif	/* NVCFS */
    754