Home | History | Annotate | Line # | Download | only in coda
coda_vfsops.c revision 1.1.1.1
      1 /*
      2 
      3             Coda: an Experimental Distributed File System
      4                              Release 3.1
      5 
      6           Copyright (c) 1987-1998 Carnegie Mellon University
      7                          All Rights Reserved
      8 
      9 Permission  to  use, copy, modify and distribute this software and its
     10 documentation is hereby granted,  provided  that  both  the  copyright
     11 notice  and  this  permission  notice  appear  in  all  copies  of the
     12 software, derivative works or  modified  versions,  and  any  portions
     13 thereof, and that both notices appear in supporting documentation, and
     14 that credit is given to Carnegie Mellon University  in  all  documents
     15 and publicity pertaining to direct or indirect use of this code or its
     16 derivatives.
     17 
     18 CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS  KNOWN  TO  HAVE  BUGS,
     19 SOME  OF  WHICH MAY HAVE SERIOUS CONSEQUENCES.  CARNEGIE MELLON ALLOWS
     20 FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.   CARNEGIE  MELLON
     21 DISCLAIMS  ANY  LIABILITY  OF  ANY  KIND  FOR  ANY  DAMAGES WHATSOEVER
     22 RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE  OR  OF
     23 ANY DERIVATIVE WORK.
     24 
     25 Carnegie  Mellon  encourages  users  of  this  software  to return any
     26 improvements or extensions that  they  make,  and  to  grant  Carnegie
     27 Mellon the rights to redistribute these changes without encumbrance.
     28 */
     29 
     30 /* $Header: /tank/opengrok/rsync2/NetBSD/src/sys/coda/coda_vfsops.c,v 1.1.1.1 1998/08/29 21:26:45 rvb Exp $ */
     31 
     32 /*
     33  * Mach Operating System
     34  * Copyright (c) 1989 Carnegie-Mellon University
     35  * All rights reserved.  The CMU software License Agreement specifies
     36  * the terms and conditions for use and redistribution.
     37  */
     38 
     39 /*
     40  * This code was written for the Coda file system at Carnegie Mellon
     41  * University.  Contributers include David Steere, James Kistler, and
     42  * M. Satyanarayanan.
     43  */
     44 
     45 /*
     46  * HISTORY
     47  * $Log: coda_vfsops.c,v $
     48  * Revision 1.1.1.1  1998/08/29 21:26:45  rvb
     49  * Very Preliminary Coda
     50  *
     51  * Revision 1.11  1998/08/28 18:12:22  rvb
     52  * Now it also works on FreeBSD -current.  This code will be
     53  * committed to the FreeBSD -current and NetBSD -current
     54  * trees.  It will then be tailored to the particular platform
     55  * by flushing conditional code.
     56  *
     57  * Revision 1.10  1998/08/18 17:05:19  rvb
     58  * Don't use __RCSID now
     59  *
     60  * Revision 1.9  1998/08/18 16:31:44  rvb
     61  * Sync the code for NetBSD -current; test on 1.3 later
     62  *
     63  * Revision 1.8  98/02/24  22:22:48  rvb
     64  * Fixes up mainly to flush iopen and friends
     65  *
     66  * Revision 1.7  98/01/23  11:53:45  rvb
     67  * Bring RVB_CFS1_1 to HEAD
     68  *
     69  * Revision 1.6.2.6  98/01/23  11:21:07  rvb
     70  * Sync with 2.2.5
     71  *
     72  * Revision 1.6.2.5  98/01/22  13:05:33  rvb
     73  * Move makecfsnode ctlfid later so vfsp is known
     74  *
     75  * Revision 1.6.2.4  97/12/19  14:26:05  rvb
     76  * session id
     77  *
     78  * Revision 1.6.2.3  97/12/16  12:40:11  rvb
     79  * Sync with 1.3
     80  *
     81  * Revision 1.6.2.2  97/12/10  11:40:25  rvb
     82  * No more ody
     83  *
     84  * Revision 1.6.2.1  97/12/06  17:41:24  rvb
     85  * Sync with peters coda.h
     86  *
     87  * Revision 1.6  97/12/05  10:39:21  rvb
     88  * Read CHANGES
     89  *
     90  * Revision 1.5.14.8  97/11/24  15:44:46  rvb
     91  * Final cfs_venus.c w/o macros, but one locking bug
     92  *
     93  * Revision 1.5.14.7  97/11/21  13:22:03  rvb
     94  * Catch a few cfscalls in cfs_vfsops.c
     95  *
     96  * Revision 1.5.14.6  97/11/20  11:46:48  rvb
     97  * Capture current cfs_venus
     98  *
     99  * Revision 1.5.14.5  97/11/18  10:27:17  rvb
    100  * cfs_nbsd.c is DEAD!!!; integrated into cfs_vf/vnops.c
    101  * cfs_nb_foo and cfs_foo are joined
    102  *
    103  * Revision 1.5.14.4  97/11/13  22:03:01  rvb
    104  * pass2 cfs_NetBSD.h mt
    105  *
    106  * Revision 1.5.14.3  97/11/12  12:09:40  rvb
    107  * reorg pass1
    108  *
    109  * Revision 1.5.14.2  97/10/29  16:06:28  rvb
    110  * Kill DYING
    111  *
    112  * Revision 1.5.14.1  1997/10/28 23:10:17  rvb
    113  * >64Meg; venus can be killed!
    114  *
    115  * Revision 1.5  1997/01/13 17:11:07  bnoble
    116  * Coda statfs needs to return something other than -1 for blocks avail. and
    117  * files available for wabi (and other windowsish) programs to install
    118  * there correctly.
    119  *
    120  * Revision 1.4  1996/12/12 22:11:00  bnoble
    121  * Fixed the "downcall invokes venus operation" deadlock in all known cases.
    122  * There may be more
    123  *
    124  * Revision 1.3  1996/11/08 18:06:12  bnoble
    125  * Minor changes in vnode operation signature, VOP_UPDATE signature, and
    126  * some newly defined bits in the include files.
    127  *
    128  * Revision 1.2  1996/01/02 16:57:04  bnoble
    129  * Added support for Coda MiniCache and raw inode calls (final commit)
    130  *
    131  * Revision 1.1.2.1  1995/12/20 01:57:32  bnoble
    132  * Added CFS-specific files
    133  *
    134  * Revision 3.1.1.1  1995/03/04  19:08:02  bnoble
    135  * Branch for NetBSD port revisions
    136  *
    137  * Revision 3.1  1995/03/04  19:08:01  bnoble
    138  * Bump to major revision 3 to prepare for NetBSD port
    139  *
    140  * Revision 2.4  1995/02/17  16:25:22  dcs
    141  * These versions represent several changes:
    142  * 1. Allow venus to restart even if outstanding references exist.
    143  * 2. Have only one ctlvp per client, as opposed to one per mounted cfs device.d
    144  * 3. Allow ody_expand to return many members, not just one.
    145  *
    146  * Revision 2.3  94/10/14  09:58:21  dcs
    147  * Made changes 'cause sun4s have braindead compilers
    148  *
    149  * Revision 2.2  94/10/12  16:46:33  dcs
    150  * Cleaned kernel/venus interface by removing XDR junk, plus
    151  * so cleanup to allow this code to be more easily ported.
    152  *
    153  * Revision 1.3  93/05/28  16:24:29  bnoble
    154  * *** empty log message ***
    155  *
    156  * Revision 1.2  92/10/27  17:58:24  lily
    157  * merge kernel/latest and alpha/src/cfs
    158  *
    159  * Revision 2.3  92/09/30  14:16:32  mja
    160  * 	Added call to cfs_flush to cfs_unmount.
    161  * 	[90/12/15            dcs]
    162  *
    163  * 	Added contributors blurb.
    164  * 	[90/12/13            jjk]
    165  *
    166  * Revision 2.2  90/07/05  11:26:40  mrt
    167  * 	Created for the Coda File System.
    168  * 	[90/05/23            dcs]
    169  *
    170  * Revision 1.3  90/05/31  17:01:42  dcs
    171  * Prepare for merge with facilities kernel.
    172  *
    173  *
    174  */
    175 #include <vcfs.h>
    176 
    177 #include <sys/param.h>
    178 #include <sys/systm.h>
    179 #include <sys/malloc.h>
    180 #include <sys/conf.h>
    181 #include <sys/namei.h>
    182 #include <sys/mount.h>
    183 #include <sys/proc.h>
    184 #include <sys/select.h>
    185 
    186 #include <cfs/coda.h>
    187 #include <cfs/cnode.h>
    188 #include <cfs/cfs_vfsops.h>
    189 #include <cfs/cfs_venus.h>
    190 #include <cfs/cfs_subr.h>
    191 #include <cfs/coda_opstats.h>
    192 /* for VN_RDEV */
    193 #include <miscfs/specfs/specdev.h>
    194 
    195 #ifdef	__FreeBSD__
    196 #ifdef	__FreeBSD_version
    197 MALLOC_DEFINE(M_CFS, "CFS storage", "Various Coda Structures");
    198 #endif
    199 #endif
    200 
    201 int cfsdebug = 0;
    202 
    203 int cfs_vfsop_print_entry = 0;
    204 #ifdef __GNUC__
    205 #define ENTRY    \
    206     if(cfs_vfsop_print_entry) myprintf(("Entered %s\n",__FUNCTION__))
    207 #else
    208 #define ENTRY
    209 #endif
    210 
    211 
    212 struct vnode *cfs_ctlvp;
    213 struct cfs_mntinfo cfs_mnttbl[NVCFS]; /* indexed by minor device number */
    214 
    215 /* structure to keep statistics of internally generated/satisfied calls */
    216 
    217 struct cfs_op_stats cfs_vfsopstats[CFS_VFSOPS_SIZE];
    218 
    219 #define MARK_ENTRY(op) (cfs_vfsopstats[op].entries++)
    220 #define MARK_INT_SAT(op) (cfs_vfsopstats[op].sat_intrn++)
    221 #define MARK_INT_FAIL(op) (cfs_vfsopstats[op].unsat_intrn++)
    222 #define MRAK_INT_GEN(op) (cfs_vfsopstats[op].gen_intrn++)
    223 
    224 extern int cfsnc_initialized;     /* Set if cache has been initialized */
    225 extern int vc_nb_open __P((dev_t, int, int, struct proc *));
    226 #ifdef	__NetBSD__
    227 extern struct cdevsw cdevsw[];    /* For sanity check in cfs_mount */
    228 #endif
    229 /* NetBSD interface to statfs */
    230 
    231 #if	defined(__NetBSD__) && defined(NetBSD1_3) && (NetBSD1_3 >= 5)
    232 extern struct vnodeopv_desc cfs_vnodeop_opv_desc;
    233 
    234 struct vnodeopv_desc *cfs_vnodeopv_descs[] = {
    235 	&cfs_vnodeop_opv_desc,
    236 	NULL,
    237 };
    238 
    239 struct vfsops cfs_vfsops = {
    240     MOUNT_CFS,
    241     cfs_mount,
    242     cfs_start,
    243     cfs_unmount,
    244     cfs_root,
    245     cfs_quotactl,
    246     cfs_nb_statfs,
    247     cfs_sync,
    248     cfs_vget,
    249     (int (*) (struct mount *, struct fid *, struct mbuf *, struct vnode **,
    250 	      int *, struct ucred **))
    251 	eopnotsupp,
    252     (int (*) (struct vnode *, struct fid *)) eopnotsupp,
    253     cfs_init,
    254 #if (NetBSD1_3 >= 7)
    255     cfs_sysctl,
    256 #endif
    257     (int (*)(void)) eopnotsupp,
    258     cfs_vnodeopv_descs,
    259     0
    260 };
    261 #elif	defined(__NetBSD__)
    262 struct vfsops cfs_vfsops = {
    263     MOUNT_CFS,
    264     cfs_mount,
    265     cfs_start,
    266     cfs_unmount,
    267     cfs_root,
    268     cfs_quotactl,
    269     cfs_nb_statfs,
    270     cfs_sync,
    271     cfs_vget,
    272     (int (*) (struct mount *, struct fid *, struct mbuf *, struct vnode **,
    273 	      int *, struct ucred **))
    274 	eopnotsupp,
    275     (int (*) (struct vnode *, struct fid *)) eopnotsupp,
    276     cfs_init,
    277 #ifdef	NetBSD1_3
    278     (int (*)(void)) eopnotsupp,
    279 #endif
    280     0
    281 };
    282 
    283 #elif	defined(__FreeBSD__)
    284 #ifdef	__FreeBSD_version
    285 struct vfsops cfs_vfsops = {
    286     cfs_mount,
    287     cfs_start,
    288     cfs_unmount,
    289     cfs_root,
    290     cfs_quotactl,
    291     cfs_nb_statfs,
    292     cfs_sync,
    293     cfs_vget,
    294     (int (*) (struct mount *, struct fid *, struct sockaddr *, struct vnode **,
    295 	      int *, struct ucred **))
    296 	eopnotsupp,
    297     (int (*) (struct vnode *, struct fid *)) eopnotsupp,
    298     cfs_init,
    299 };
    300 
    301 #else
    302 struct vfsops cfs_vfsops = {
    303     cfs_mount,
    304     cfs_start,
    305     cfs_unmount,
    306     cfs_root,
    307     cfs_quotactl,
    308     cfs_nb_statfs,
    309     cfs_sync,
    310     cfs_vget,
    311     (int (*) (struct mount *, struct fid *, struct mbuf *, struct vnode **,
    312 	      int *, struct ucred **))
    313 	eopnotsupp,
    314     (int (*) (struct vnode *, struct fid *)) eopnotsupp,
    315     cfs_init,
    316 };
    317 
    318 #endif
    319 
    320 
    321 #include <sys/kernel.h>
    322 VFS_SET(cfs_vfsops, cfs, MOUNT_CFS, VFCF_NETWORK);
    323 #endif
    324 
    325 int
    326 cfs_vfsopstats_init(void)
    327 {
    328 	register int i;
    329 
    330 	for (i=0;i<CFS_VFSOPS_SIZE;i++) {
    331 		cfs_vfsopstats[i].opcode = i;
    332 		cfs_vfsopstats[i].entries = 0;
    333 		cfs_vfsopstats[i].sat_intrn = 0;
    334 		cfs_vfsopstats[i].unsat_intrn = 0;
    335 		cfs_vfsopstats[i].gen_intrn = 0;
    336 	}
    337 
    338 	return 0;
    339 }
    340 
    341 
    342 /*
    343  * cfs mount vfsop
    344  * Set up mount info record and attach it to vfs struct.
    345  */
    346 /*ARGSUSED*/
    347 int
    348 cfs_mount(vfsp, path, data, ndp, p)
    349     struct mount *vfsp;		/* Allocated and initialized by mount(2) */
    350 #ifdef	NetBSD1_3
    351     const char *path;		/* path covered: ignored by the fs-layer */
    352     void *data;			/* Need to define a data type for this in netbsd? */
    353 #else
    354     char *path;			/* path covered: ignored by the fs-layer */
    355     caddr_t data;		/* Need to define a data type for this in netbsd? */
    356 #endif
    357     struct nameidata *ndp;	/* Clobber this to lookup the device name */
    358     struct proc *p;		/* The ever-famous proc pointer */
    359 {
    360     struct vnode *dvp;
    361     struct cnode *cp;
    362     dev_t dev;
    363     struct cfs_mntinfo *mi;
    364     struct vnode *rootvp;
    365     ViceFid rootfid;
    366     ViceFid ctlfid;
    367     int error;
    368 
    369     ENTRY;
    370 
    371     cfs_vfsopstats_init();
    372     cfs_vnodeopstats_init();
    373 
    374     MARK_ENTRY(CFS_MOUNT_STATS);
    375     if (CFS_MOUNTED(vfsp)) {
    376 	MARK_INT_FAIL(CFS_MOUNT_STATS);
    377 	return(EBUSY);
    378     }
    379 
    380     /* Validate mount device.  Similar to getmdev(). */
    381 
    382     NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, data, p);
    383     error = namei(ndp);
    384     dvp = ndp->ni_vp;
    385 
    386     if (error) {
    387 	MARK_INT_FAIL(CFS_MOUNT_STATS);
    388 	return (error);
    389     }
    390     if (dvp->v_type != VCHR) {
    391 	MARK_INT_FAIL(CFS_MOUNT_STATS);
    392 	vrele(dvp);
    393 	return(ENXIO);
    394     }
    395     dev = dvp->v_specinfo->si_rdev;
    396     vrele(dvp);
    397     if (major(dev) >= nchrdev || major(dev) < 0) {
    398 	MARK_INT_FAIL(CFS_MOUNT_STATS);
    399 	return(ENXIO);
    400     }
    401 
    402     /*
    403      * See if the device table matches our expectations.
    404      */
    405 #ifdef	__NetBSD__
    406     if (cdevsw[major(dev)].d_open != vc_nb_open)
    407 #elif	defined(__FreeBSD__)
    408     if (cdevsw[major(dev)]->d_open != vc_nb_open)
    409 #endif
    410     {
    411 	MARK_INT_FAIL(CFS_MOUNT_STATS);
    412 	return(ENXIO);
    413     }
    414 
    415     if (minor(dev) >= NVCFS || minor(dev) < 0) {
    416 	MARK_INT_FAIL(CFS_MOUNT_STATS);
    417 	return(ENXIO);
    418     }
    419 
    420     /*
    421      * Initialize the mount record and link it to the vfs struct
    422      */
    423     mi = &cfs_mnttbl[minor(dev)];
    424 
    425     if (!VC_OPEN(&mi->mi_vcomm)) {
    426 	MARK_INT_FAIL(CFS_MOUNT_STATS);
    427 	return(ENODEV);
    428     }
    429 
    430     /* No initialization (here) of mi_vcomm! */
    431     vfsp->mnt_data = (qaddr_t)mi;
    432 #ifdef	__NetBSD__
    433     vfsp->mnt_stat.f_fsid.val[0] = 0;
    434     vfsp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_CFS);
    435 #elif	defined(__FreeBSD__) && defined(__FreeBSD_version)
    436 
    437     vfs_getnewfsid (vfsp);
    438 
    439 #elif	defined(__FreeBSD__)
    440     /* Seems a bit overkill, since usualy /coda is the only mount point
    441      * for cfs.
    442      */
    443     getnewfsid (vfsp, MOUNT_CFS);
    444 #endif
    445     mi->mi_vfsp = vfsp;
    446 
    447     /*
    448      * Make a root vnode to placate the Vnode interface, but don't
    449      * actually make the CFS_ROOT call to venus until the first call
    450      * to cfs_root in case a server is down while venus is starting.
    451      */
    452     rootfid.Volume = 0;
    453     rootfid.Vnode = 0;
    454     rootfid.Unique = 0;
    455     cp = makecfsnode(&rootfid, vfsp, VDIR);
    456     rootvp = CTOV(cp);
    457     rootvp->v_flag |= VROOT;
    458 
    459     ctlfid.Volume = CTL_VOL;
    460     ctlfid.Vnode = CTL_VNO;
    461     ctlfid.Unique = CTL_UNI;
    462 /*  cp = makecfsnode(&ctlfid, vfsp, VCHR);
    463     The above code seems to cause a loop in the cnode links.
    464     I don't totally understand when it happens, it is caught
    465     when closing down the system.
    466  */
    467     cp = makecfsnode(&ctlfid, 0, VCHR);
    468 
    469     cfs_ctlvp = CTOV(cp);
    470 
    471     /* Add vfs and rootvp to chain of vfs hanging off mntinfo */
    472     mi->mi_vfsp = vfsp;
    473     mi->mi_rootvp = rootvp;
    474 
    475     /* set filesystem block size */
    476     vfsp->mnt_stat.f_bsize = 8192;	    /* XXX -JJK */
    477 #ifdef	 __FreeBSD__
    478     /* Set f_iosize.  XXX -- inamura (at) isl.ntt.co.jp.
    479        For vnode_pager_haspage() references. The value should be obtained
    480        from underlying UFS. */
    481     /* Checked UFS. iosize is set as 8192 */
    482     vfsp->mnt_stat.f_iosize = 8192;
    483 #endif
    484 
    485     /* error is currently guaranteed to be zero, but in case some
    486        code changes... */
    487     CFSDEBUG(1,
    488 	     myprintf(("cfs_mount returned %d\n",error)););
    489     if (error)
    490 	MARK_INT_FAIL(CFS_MOUNT_STATS);
    491     else
    492 	MARK_INT_SAT(CFS_MOUNT_STATS);
    493 
    494     return(error);
    495 }
    496 
    497 int
    498 cfs_start(vfsp, flags, p)
    499     struct mount *vfsp;
    500     int flags;
    501     struct proc *p;
    502 {
    503     ENTRY;
    504     return (0);
    505 }
    506 
    507 int
    508 cfs_unmount(vfsp, mntflags, p)
    509     struct mount *vfsp;
    510     int mntflags;
    511     struct proc *p;
    512 {
    513     struct cfs_mntinfo *mi = vftomi(vfsp);
    514     int active, error = 0;
    515 
    516     ENTRY;
    517     MARK_ENTRY(CFS_UMOUNT_STATS);
    518     if (!CFS_MOUNTED(vfsp)) {
    519 	MARK_INT_FAIL(CFS_UMOUNT_STATS);
    520 	return(EINVAL);
    521     }
    522 
    523     if (mi->mi_vfsp == vfsp) {	/* We found the victim */
    524 	if (!IS_UNMOUNTING(VTOC(mi->mi_rootvp)))
    525 	    return (EBUSY); 	/* Venus is still running */
    526 
    527 #ifdef	DEBUG
    528 	printf("cfs_unmount: ROOT: vp %p, cp %p\n", mi->mi_rootvp, VTOC(mi->mi_rootvp));
    529 #endif
    530 	vrele(mi->mi_rootvp);
    531 
    532 #ifdef	NetBSD1_3
    533 	active = cfs_kill(vfsp, NOT_DOWNCALL);
    534 
    535 #if	defined(__NetBSD__) && defined(NetBSD1_3) && (NetBSD1_3 >= 7)
    536 	if (1)
    537 #else
    538 	if ((error = vfs_busy(mi->mi_vfsp)) == 0)
    539 #endif
    540 	{
    541 		error = vflush(mi->mi_vfsp, NULLVP, FORCECLOSE);
    542 		printf("cfs_unmount: active = %d, vflush active %d\n", active, error);
    543 		error = 0;
    544 	} else {
    545 		printf("cfs_unmount: busy\n");
    546 	}
    547 #else	/* FreeBSD I guess */
    548 	active = cfs_kill(vfsp, NOT_DOWNCALL);
    549 	error = vflush(mi->mi_vfsp, NULLVP, FORCECLOSE);
    550 	printf("cfs_unmount: active = %d, vflush active %d\n", active, error);
    551 	error = 0;
    552 #endif
    553 	/* I'm going to take this out to allow lookups to go through. I'm
    554 	 * not sure it's important anyway. -- DCS 2/2/94
    555 	 */
    556 	/* vfsp->VFS_DATA = NULL; */
    557 
    558 	/* No more vfsp's to hold onto */
    559 	mi->mi_vfsp = NULL;
    560 	mi->mi_rootvp = NULL;
    561 
    562 	if (error)
    563 	    MARK_INT_FAIL(CFS_UMOUNT_STATS);
    564 	else
    565 	    MARK_INT_SAT(CFS_UMOUNT_STATS);
    566 
    567 	return(error);
    568     }
    569     return (EINVAL);
    570 }
    571 
    572 /*
    573  * find root of cfs
    574  */
    575 int
    576 cfs_root(vfsp, vpp)
    577 	struct mount *vfsp;
    578 	struct vnode **vpp;
    579 {
    580     struct cfs_mntinfo *mi = vftomi(vfsp);
    581     struct vnode **result;
    582     int error;
    583     struct proc *p = curproc;    /* XXX - bnoble */
    584     ViceFid VFid;
    585 
    586     ENTRY;
    587     MARK_ENTRY(CFS_ROOT_STATS);
    588     result = NULL;
    589 
    590     if (vfsp == mi->mi_vfsp) {
    591 	if ((VTOC(mi->mi_rootvp)->c_fid.Volume != 0) ||
    592 	    (VTOC(mi->mi_rootvp)->c_fid.Vnode != 0) ||
    593 	    (VTOC(mi->mi_rootvp)->c_fid.Unique != 0))
    594 	    { /* Found valid root. */
    595 		*vpp = mi->mi_rootvp;
    596 		/* On Mach, this is vref.  On NetBSD, VOP_LOCK */
    597 		vref(*vpp);
    598 		VOP_X_LOCK(*vpp, LK_EXCLUSIVE);
    599 		MARK_INT_SAT(CFS_ROOT_STATS);
    600 		return(0);
    601 	    }
    602     }
    603 
    604     error = venus_root(vftomi(vfsp), p->p_cred->pc_ucred, p, &VFid);
    605 
    606     if (!error) {
    607 	/*
    608 	 * Save the new rootfid in the cnode, and rehash the cnode into the
    609 	 * cnode hash with the new fid key.
    610 	 */
    611 	cfs_unsave(VTOC(mi->mi_rootvp));
    612 	VTOC(mi->mi_rootvp)->c_fid = VFid;
    613 	cfs_save(VTOC(mi->mi_rootvp));
    614 
    615 	*vpp = mi->mi_rootvp;
    616 	vref(*vpp);
    617 	VOP_X_LOCK(*vpp, LK_EXCLUSIVE);
    618 	MARK_INT_SAT(CFS_ROOT_STATS);
    619 	goto exit;
    620     } else if (error == ENODEV) {
    621 	/* Gross hack here! */
    622 	/*
    623 	 * If Venus fails to respond to the CFS_ROOT call, cfscall returns
    624 	 * ENODEV. Return the uninitialized root vnode to allow vfs
    625 	 * operations such as unmount to continue. Without this hack,
    626 	 * there is no way to do an unmount if Venus dies before a
    627 	 * successful CFS_ROOT call is done. All vnode operations
    628 	 * will fail.
    629 	 */
    630 	*vpp = mi->mi_rootvp;
    631 	vref(*vpp);
    632 	VOP_X_LOCK(*vpp, LK_EXCLUSIVE);
    633 	MARK_INT_FAIL(CFS_ROOT_STATS);
    634 	error = 0;
    635 	goto exit;
    636     } else {
    637 	CFSDEBUG( CFS_ROOT, myprintf(("error %d in CFS_ROOT\n", error)); );
    638 	MARK_INT_FAIL(CFS_ROOT_STATS);
    639 
    640 	goto exit;
    641     }
    642  exit:
    643     return(error);
    644 }
    645 
    646 int
    647 cfs_quotactl(vfsp, cmd, uid, arg, p)
    648     struct mount *vfsp;
    649     int cmd;
    650     uid_t uid;
    651     caddr_t arg;
    652     struct proc *p;
    653 {
    654     ENTRY;
    655     return (EOPNOTSUPP);
    656 }
    657 
    658 /*
    659  * Get file system statistics.
    660  */
    661 int
    662 cfs_nb_statfs(vfsp, sbp, p)
    663     register struct mount *vfsp;
    664     struct statfs *sbp;
    665     struct proc *p;
    666 {
    667     ENTRY;
    668 /*  MARK_ENTRY(CFS_STATFS_STATS); */
    669     if (!CFS_MOUNTED(vfsp)) {
    670 /*	MARK_INT_FAIL(CFS_STATFS_STATS);*/
    671 	return(EINVAL);
    672     }
    673 
    674     bzero(sbp, sizeof(struct statfs));
    675     /* XXX - what to do about f_flags, others? --bnoble */
    676     /* Below This is what AFS does
    677     	#define NB_SFS_SIZ 0x895440
    678      */
    679     /* Note: Normal fs's have a bsize of 0x400 == 1024 */
    680 #ifdef	__NetBSD__
    681     sbp->f_type = 0;
    682 #elif	defined(__FreeBSD__)
    683     sbp->f_type = MOUNT_CFS;
    684 #endif
    685     sbp->f_bsize = 8192; /* XXX */
    686     sbp->f_iosize = 8192; /* XXX */
    687 #define NB_SFS_SIZ 0x8AB75D
    688     sbp->f_blocks = NB_SFS_SIZ;
    689     sbp->f_bfree = NB_SFS_SIZ;
    690     sbp->f_bavail = NB_SFS_SIZ;
    691     sbp->f_files = NB_SFS_SIZ;
    692     sbp->f_ffree = NB_SFS_SIZ;
    693     bcopy((caddr_t)&(vfsp->mnt_stat.f_fsid), (caddr_t)&(sbp->f_fsid), sizeof (fsid_t));
    694 #ifdef	__NetBSD__
    695     strncpy(sbp->f_fstypename, MOUNT_CFS, MFSNAMELEN-1);
    696 #endif
    697     strcpy(sbp->f_mntonname, "/coda");
    698     strcpy(sbp->f_mntfromname, "CFS");
    699 /*  MARK_INT_SAT(CFS_STATFS_STATS); */
    700     return(0);
    701 }
    702 
    703 /*
    704  * Flush any pending I/O.
    705  */
    706 int
    707 cfs_sync(vfsp, waitfor, cred, p)
    708     struct mount *vfsp;
    709     int    waitfor;
    710     struct ucred *cred;
    711     struct proc *p;
    712 {
    713     ENTRY;
    714     MARK_ENTRY(CFS_SYNC_STATS);
    715     MARK_INT_SAT(CFS_SYNC_STATS);
    716     return(0);
    717 }
    718 
    719 int
    720 cfs_vget(vfsp, ino, vpp)
    721     struct mount *vfsp;
    722     ino_t ino;
    723     struct vnode **vpp;
    724 {
    725     ENTRY;
    726     return (EOPNOTSUPP);
    727 }
    728 
    729 /*
    730  * fhtovp is now what vget used to be in 4.3-derived systems.  For
    731  * some silly reason, vget is now keyed by a 32 bit ino_t, rather than
    732  * a type-specific fid.
    733  */
    734 int
    735 cfs_fhtovp(vfsp, fhp, nam, vpp, exflagsp, creadanonp)
    736     register struct mount *vfsp;
    737     struct fid *fhp;
    738     struct mbuf *nam;
    739     struct vnode **vpp;
    740     int *exflagsp;
    741     struct ucred **creadanonp;
    742 {
    743     struct cfid *cfid = (struct cfid *)fhp;
    744     struct cnode *cp = 0;
    745     int error;
    746     struct proc *p = curproc; /* XXX -mach */
    747     ViceFid VFid;
    748     int vtype;
    749 
    750     ENTRY;
    751 
    752     MARK_ENTRY(CFS_VGET_STATS);
    753     /* Check for vget of control object. */
    754     if (IS_CTL_FID(&cfid->cfid_fid)) {
    755 	*vpp = cfs_ctlvp;
    756 	vref(cfs_ctlvp);
    757 	MARK_INT_SAT(CFS_VGET_STATS);
    758 	return(0);
    759     }
    760 
    761     error = venus_fhtovp(vftomi(vfsp), &cfid->cfid_fid, p->p_cred->pc_ucred, p, &VFid, &vtype);
    762 
    763     if (error) {
    764 	CFSDEBUG(CFS_VGET, myprintf(("vget error %d\n",error));)
    765 	    *vpp = (struct vnode *)0;
    766     } else {
    767 	CFSDEBUG(CFS_VGET,
    768 		 myprintf(("vget: vol %lx vno %lx uni %lx type %d result %d\n",
    769 			VFid.Volume, VFid.Vnode, VFid.Unique, vtype, error)); )
    770 
    771 	cp = makecfsnode(&VFid, vfsp, vtype);
    772 	*vpp = CTOV(cp);
    773     }
    774     return(error);
    775 }
    776 
    777 int
    778 cfs_vptofh(vnp, fidp)
    779     struct vnode *vnp;
    780     struct fid   *fidp;
    781 {
    782     ENTRY;
    783     return (EOPNOTSUPP);
    784 }
    785 
    786 #ifdef	__NetBSD__
    787 void
    788 cfs_init(void)
    789 {
    790     ENTRY;
    791 }
    792 #elif	defined(__FreeBSD__)
    793 #ifdef	__FreeBSD_version
    794 int
    795 cfs_init(struct vfsconf *vfsp)
    796 {
    797     ENTRY;
    798     return 0;
    799 }
    800 #else
    801 int
    802 cfs_init(void)
    803 {
    804     ENTRY;
    805     return 0;
    806 }
    807 #endif
    808 #endif
    809 
    810 #if	defined(__NetBSD__) && defined(NetBSD1_3) && (NetBSD1_3 >= 7)
    811 int
    812 cfs_sysctl(name, namelen, oldp, oldlp, newp, newl, p)
    813 	int *name;
    814 	u_int namelen;
    815 	void *oldp;
    816 	size_t *oldlp;
    817 	void *newp;
    818 	size_t newl;
    819 	struct proc *p;
    820 {
    821 
    822 	/* all sysctl names at this level are terminal */
    823 	if (namelen != 1)
    824 		return (ENOTDIR);		/* overloaded */
    825 
    826 	switch (name[0]) {
    827 /*
    828 	case FFS_CLUSTERREAD:
    829 		return (sysctl_int(oldp, oldlp, newp, newl, &doclusterread));
    830  */
    831 	default:
    832 		return (EOPNOTSUPP);
    833 	}
    834 	/* NOTREACHED */
    835 }
    836 #endif
    837 
    838 /*
    839  * To allow for greater ease of use, some vnodes may be orphaned when
    840  * Venus dies.  Certain operations should still be allowed to go
    841  * through, but without propagating ophan-ness.  So this function will
    842  * get a new vnode for the file from the current run of Venus.  */
    843 
    844 int
    845 getNewVnode(vpp)
    846      struct vnode **vpp;
    847 {
    848     struct cfid cfid;
    849     struct cfs_mntinfo *mi = vftomi((*vpp)->v_mount);
    850 
    851     ENTRY;
    852 
    853     cfid.cfid_len = (short)sizeof(ViceFid);
    854     cfid.cfid_fid = VTOC(*vpp)->c_fid;	/* Structure assignment. */
    855     /* XXX ? */
    856 
    857     /* We're guessing that if set, the 1st element on the list is a
    858      * valid vnode to use. If not, return ENODEV as venus is dead.
    859      */
    860     if (mi->mi_vfsp == NULL)
    861 	return ENODEV;
    862 
    863     return cfs_fhtovp(mi->mi_vfsp, (struct fid*)&cfid, NULL, vpp,
    864 		      NULL, NULL);
    865 }
    866 
    867 #include <ufs/ufs/quota.h>
    868 #include <ufs/ufs/ufsmount.h>
    869 /* get the mount structure corresponding to a given device.  Assume
    870  * device corresponds to a UFS. Return NULL if no device is found.
    871  */
    872 struct mount *devtomp(dev)
    873     dev_t dev;
    874 {
    875     struct mount *mp, *nmp;
    876 
    877     for (mp = mountlist.cqh_first; mp != (void*)&mountlist; mp = nmp) {
    878 	nmp = mp->mnt_list.cqe_next;
    879 	if (
    880 #ifdef	__NetBSD__
    881 	    (!strcmp(mp->mnt_op->vfs_name, MOUNT_UFS)) &&
    882 #endif
    883 	    ((VFSTOUFS(mp))->um_dev == (dev_t) dev)) {
    884 	    /* mount corresponds to UFS and the device matches one we want */
    885 	    return(mp);
    886 	}
    887     }
    888     /* mount structure wasn't found */
    889     return(NULL);
    890 }
    891