coda_vfsops.c revision 38625
138625Srvb/*
238625Srvb
338625Srvb            Coda: an Experimental Distributed File System
438625Srvb                             Release 3.1
538625Srvb
638625Srvb          Copyright (c) 1987-1998 Carnegie Mellon University
738625Srvb                         All Rights Reserved
838625Srvb
938625SrvbPermission  to  use, copy, modify and distribute this software and its
1038625Srvbdocumentation is hereby granted,  provided  that  both  the  copyright
1138625Srvbnotice  and  this  permission  notice  appear  in  all  copies  of the
1238625Srvbsoftware, derivative works or  modified  versions,  and  any  portions
1338625Srvbthereof, and that both notices appear in supporting documentation, and
1438625Srvbthat credit is given to Carnegie Mellon University  in  all  documents
1538625Srvband publicity pertaining to direct or indirect use of this code or its
1638625Srvbderivatives.
1738625Srvb
1838625SrvbCODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS  KNOWN  TO  HAVE  BUGS,
1938625SrvbSOME  OF  WHICH MAY HAVE SERIOUS CONSEQUENCES.  CARNEGIE MELLON ALLOWS
2038625SrvbFREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.   CARNEGIE  MELLON
2138625SrvbDISCLAIMS  ANY  LIABILITY  OF  ANY  KIND  FOR  ANY  DAMAGES WHATSOEVER
2238625SrvbRESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE  OR  OF
2338625SrvbANY DERIVATIVE WORK.
2438625Srvb
2538625SrvbCarnegie  Mellon  encourages  users  of  this  software  to return any
2638625Srvbimprovements or extensions that  they  make,  and  to  grant  Carnegie
2738625SrvbMellon the rights to redistribute these changes without encumbrance.
2838625Srvb*/
2938625Srvb
3038625Srvb/* $Header: /afs/cs/project/coda-src/cvs/coda/kernel-src/vfs/freebsd/cfs/cfs_vfsops.c,v 1.11 1998/08/28 18:12:22 rvb Exp $ */
3138625Srvb
3238625Srvb/*
3338625Srvb * Mach Operating System
3438625Srvb * Copyright (c) 1989 Carnegie-Mellon University
3538625Srvb * All rights reserved.  The CMU software License Agreement specifies
3638625Srvb * the terms and conditions for use and redistribution.
3738625Srvb */
3838625Srvb
3938625Srvb/*
4038625Srvb * This code was written for the Coda file system at Carnegie Mellon
4138625Srvb * University.  Contributers include David Steere, James Kistler, and
4238625Srvb * M. Satyanarayanan.
4338625Srvb */
4438625Srvb
4538625Srvb/*
4638625Srvb * HISTORY
4738625Srvb * $Log: cfs_vfsops.c,v $
4838625Srvb * Revision 1.11  1998/08/28 18:12:22  rvb
4938625Srvb * Now it also works on FreeBSD -current.  This code will be
5038625Srvb * committed to the FreeBSD -current and NetBSD -current
5138625Srvb * trees.  It will then be tailored to the particular platform
5238625Srvb * by flushing conditional code.
5338625Srvb *
5438625Srvb * Revision 1.10  1998/08/18 17:05:19  rvb
5538625Srvb * Don't use __RCSID now
5638625Srvb *
5738625Srvb * Revision 1.9  1998/08/18 16:31:44  rvb
5838625Srvb * Sync the code for NetBSD -current; test on 1.3 later
5938625Srvb *
6038625Srvb * Revision 1.8  98/02/24  22:22:48  rvb
6138625Srvb * Fixes up mainly to flush iopen and friends
6238625Srvb *
6338625Srvb * Revision 1.7  98/01/23  11:53:45  rvb
6438625Srvb * Bring RVB_CFS1_1 to HEAD
6538625Srvb *
6638625Srvb * Revision 1.6.2.6  98/01/23  11:21:07  rvb
6738625Srvb * Sync with 2.2.5
6838625Srvb *
6938625Srvb * Revision 1.6.2.5  98/01/22  13:05:33  rvb
7038625Srvb * Move makecfsnode ctlfid later so vfsp is known
7138625Srvb *
7238625Srvb * Revision 1.6.2.4  97/12/19  14:26:05  rvb
7338625Srvb * session id
7438625Srvb *
7538625Srvb * Revision 1.6.2.3  97/12/16  12:40:11  rvb
7638625Srvb * Sync with 1.3
7738625Srvb *
7838625Srvb * Revision 1.6.2.2  97/12/10  11:40:25  rvb
7938625Srvb * No more ody
8038625Srvb *
8138625Srvb * Revision 1.6.2.1  97/12/06  17:41:24  rvb
8238625Srvb * Sync with peters coda.h
8338625Srvb *
8438625Srvb * Revision 1.6  97/12/05  10:39:21  rvb
8538625Srvb * Read CHANGES
8638625Srvb *
8738625Srvb * Revision 1.5.14.8  97/11/24  15:44:46  rvb
8838625Srvb * Final cfs_venus.c w/o macros, but one locking bug
8938625Srvb *
9038625Srvb * Revision 1.5.14.7  97/11/21  13:22:03  rvb
9138625Srvb * Catch a few cfscalls in cfs_vfsops.c
9238625Srvb *
9338625Srvb * Revision 1.5.14.6  97/11/20  11:46:48  rvb
9438625Srvb * Capture current cfs_venus
9538625Srvb *
9638625Srvb * Revision 1.5.14.5  97/11/18  10:27:17  rvb
9738625Srvb * cfs_nbsd.c is DEAD!!!; integrated into cfs_vf/vnops.c
9838625Srvb * cfs_nb_foo and cfs_foo are joined
9938625Srvb *
10038625Srvb * Revision 1.5.14.4  97/11/13  22:03:01  rvb
10138625Srvb * pass2 cfs_NetBSD.h mt
10238625Srvb *
10338625Srvb * Revision 1.5.14.3  97/11/12  12:09:40  rvb
10438625Srvb * reorg pass1
10538625Srvb *
10638625Srvb * Revision 1.5.14.2  97/10/29  16:06:28  rvb
10738625Srvb * Kill DYING
10838625Srvb *
10938625Srvb * Revision 1.5.14.1  1997/10/28 23:10:17  rvb
11038625Srvb * >64Meg; venus can be killed!
11138625Srvb *
11238625Srvb * Revision 1.5  1997/01/13 17:11:07  bnoble
11338625Srvb * Coda statfs needs to return something other than -1 for blocks avail. and
11438625Srvb * files available for wabi (and other windowsish) programs to install
11538625Srvb * there correctly.
11638625Srvb *
11738625Srvb * Revision 1.4  1996/12/12 22:11:00  bnoble
11838625Srvb * Fixed the "downcall invokes venus operation" deadlock in all known cases.
11938625Srvb * There may be more
12038625Srvb *
12138625Srvb * Revision 1.3  1996/11/08 18:06:12  bnoble
12238625Srvb * Minor changes in vnode operation signature, VOP_UPDATE signature, and
12338625Srvb * some newly defined bits in the include files.
12438625Srvb *
12538625Srvb * Revision 1.2  1996/01/02 16:57:04  bnoble
12638625Srvb * Added support for Coda MiniCache and raw inode calls (final commit)
12738625Srvb *
12838625Srvb * Revision 1.1.2.1  1995/12/20 01:57:32  bnoble
12938625Srvb * Added CFS-specific files
13038625Srvb *
13138625Srvb * Revision 3.1.1.1  1995/03/04  19:08:02  bnoble
13238625Srvb * Branch for NetBSD port revisions
13338625Srvb *
13438625Srvb * Revision 3.1  1995/03/04  19:08:01  bnoble
13538625Srvb * Bump to major revision 3 to prepare for NetBSD port
13638625Srvb *
13738625Srvb * Revision 2.4  1995/02/17  16:25:22  dcs
13838625Srvb * These versions represent several changes:
13938625Srvb * 1. Allow venus to restart even if outstanding references exist.
14038625Srvb * 2. Have only one ctlvp per client, as opposed to one per mounted cfs device.d
14138625Srvb * 3. Allow ody_expand to return many members, not just one.
14238625Srvb *
14338625Srvb * Revision 2.3  94/10/14  09:58:21  dcs
14438625Srvb * Made changes 'cause sun4s have braindead compilers
14538625Srvb *
14638625Srvb * Revision 2.2  94/10/12  16:46:33  dcs
14738625Srvb * Cleaned kernel/venus interface by removing XDR junk, plus
14838625Srvb * so cleanup to allow this code to be more easily ported.
14938625Srvb *
15038625Srvb * Revision 1.3  93/05/28  16:24:29  bnoble
15138625Srvb * *** empty log message ***
15238625Srvb *
15338625Srvb * Revision 1.2  92/10/27  17:58:24  lily
15438625Srvb * merge kernel/latest and alpha/src/cfs
15538625Srvb *
15638625Srvb * Revision 2.3  92/09/30  14:16:32  mja
15738625Srvb * 	Added call to cfs_flush to cfs_unmount.
15838625Srvb * 	[90/12/15            dcs]
15938625Srvb *
16038625Srvb * 	Added contributors blurb.
16138625Srvb * 	[90/12/13            jjk]
16238625Srvb *
16338625Srvb * Revision 2.2  90/07/05  11:26:40  mrt
16438625Srvb * 	Created for the Coda File System.
16538625Srvb * 	[90/05/23            dcs]
16638625Srvb *
16738625Srvb * Revision 1.3  90/05/31  17:01:42  dcs
16838625Srvb * Prepare for merge with facilities kernel.
16938625Srvb *
17038625Srvb *
17138625Srvb */
17238625Srvb#include <vcfs.h>
17338625Srvb
17438625Srvb#include <sys/param.h>
17538625Srvb#include <sys/systm.h>
17638625Srvb#include <sys/malloc.h>
17738625Srvb#include <sys/conf.h>
17838625Srvb#include <sys/namei.h>
17938625Srvb#include <sys/mount.h>
18038625Srvb#include <sys/proc.h>
18138625Srvb#include <sys/select.h>
18238625Srvb
18338625Srvb#include <cfs/coda.h>
18438625Srvb#include <cfs/cnode.h>
18538625Srvb#include <cfs/cfs_vfsops.h>
18638625Srvb#include <cfs/cfs_venus.h>
18738625Srvb#include <cfs/cfs_subr.h>
18838625Srvb#include <cfs/coda_opstats.h>
18938625Srvb/* for VN_RDEV */
19038625Srvb#include <miscfs/specfs/specdev.h>
19138625Srvb
19238625Srvb#ifdef	__FreeBSD__
19338625Srvb#ifdef	__FreeBSD_version
19438625SrvbMALLOC_DEFINE(M_CFS, "CFS storage", "Various Coda Structures");
19538625Srvb#endif
19638625Srvb#endif
19738625Srvb
19838625Srvbint cfsdebug = 0;
19938625Srvb
20038625Srvbint cfs_vfsop_print_entry = 0;
20138625Srvb#ifdef __GNUC__
20238625Srvb#define ENTRY    \
20338625Srvb    if(cfs_vfsop_print_entry) myprintf(("Entered %s\n",__FUNCTION__))
20438625Srvb#else
20538625Srvb#define ENTRY
20638625Srvb#endif
20738625Srvb
20838625Srvb
20938625Srvbstruct vnode *cfs_ctlvp;
21038625Srvbstruct cfs_mntinfo cfs_mnttbl[NVCFS]; /* indexed by minor device number */
21138625Srvb
21238625Srvb/* structure to keep statistics of internally generated/satisfied calls */
21338625Srvb
21438625Srvbstruct cfs_op_stats cfs_vfsopstats[CFS_VFSOPS_SIZE];
21538625Srvb
21638625Srvb#define MARK_ENTRY(op) (cfs_vfsopstats[op].entries++)
21738625Srvb#define MARK_INT_SAT(op) (cfs_vfsopstats[op].sat_intrn++)
21838625Srvb#define MARK_INT_FAIL(op) (cfs_vfsopstats[op].unsat_intrn++)
21938625Srvb#define MRAK_INT_GEN(op) (cfs_vfsopstats[op].gen_intrn++)
22038625Srvb
22138625Srvbextern int cfsnc_initialized;     /* Set if cache has been initialized */
22238625Srvbextern int vc_nb_open __P((dev_t, int, int, struct proc *));
22338625Srvb#ifdef	__NetBSD__
22438625Srvbextern struct cdevsw cdevsw[];    /* For sanity check in cfs_mount */
22538625Srvb#endif
22638625Srvb/* NetBSD interface to statfs */
22738625Srvb
22838625Srvb#if	defined(__NetBSD__) && defined(NetBSD1_3) && (NetBSD1_3 >= 5)
22938625Srvbextern struct vnodeopv_desc cfs_vnodeop_opv_desc;
23038625Srvb
23138625Srvbstruct vnodeopv_desc *cfs_vnodeopv_descs[] = {
23238625Srvb	&cfs_vnodeop_opv_desc,
23338625Srvb	NULL,
23438625Srvb};
23538625Srvb
23638625Srvbstruct vfsops cfs_vfsops = {
23738625Srvb    MOUNT_CFS,
23838625Srvb    cfs_mount,
23938625Srvb    cfs_start,
24038625Srvb    cfs_unmount,
24138625Srvb    cfs_root,
24238625Srvb    cfs_quotactl,
24338625Srvb    cfs_nb_statfs,
24438625Srvb    cfs_sync,
24538625Srvb    cfs_vget,
24638625Srvb    (int (*) (struct mount *, struct fid *, struct mbuf *, struct vnode **,
24738625Srvb	      int *, struct ucred **))
24838625Srvb	eopnotsupp,
24938625Srvb    (int (*) (struct vnode *, struct fid *)) eopnotsupp,
25038625Srvb    cfs_init,
25138625Srvb#if (NetBSD1_3 >= 7)
25238625Srvb    cfs_sysctl,
25338625Srvb#endif
25438625Srvb    (int (*)(void)) eopnotsupp,
25538625Srvb    cfs_vnodeopv_descs,
25638625Srvb    0
25738625Srvb};
25838625Srvb#elif	defined(__NetBSD__)
25938625Srvbstruct vfsops cfs_vfsops = {
26038625Srvb    MOUNT_CFS,
26138625Srvb    cfs_mount,
26238625Srvb    cfs_start,
26338625Srvb    cfs_unmount,
26438625Srvb    cfs_root,
26538625Srvb    cfs_quotactl,
26638625Srvb    cfs_nb_statfs,
26738625Srvb    cfs_sync,
26838625Srvb    cfs_vget,
26938625Srvb    (int (*) (struct mount *, struct fid *, struct mbuf *, struct vnode **,
27038625Srvb	      int *, struct ucred **))
27138625Srvb	eopnotsupp,
27238625Srvb    (int (*) (struct vnode *, struct fid *)) eopnotsupp,
27338625Srvb    cfs_init,
27438625Srvb#ifdef	NetBSD1_3
27538625Srvb    (int (*)(void)) eopnotsupp,
27638625Srvb#endif
27738625Srvb    0
27838625Srvb};
27938625Srvb
28038625Srvb#elif	defined(__FreeBSD__)
28138625Srvb#ifdef	__FreeBSD_version
28238625Srvbstruct vfsops cfs_vfsops = {
28338625Srvb    cfs_mount,
28438625Srvb    cfs_start,
28538625Srvb    cfs_unmount,
28638625Srvb    cfs_root,
28738625Srvb    cfs_quotactl,
28838625Srvb    cfs_nb_statfs,
28938625Srvb    cfs_sync,
29038625Srvb    cfs_vget,
29138625Srvb    (int (*) (struct mount *, struct fid *, struct sockaddr *, struct vnode **,
29238625Srvb	      int *, struct ucred **))
29338625Srvb	eopnotsupp,
29438625Srvb    (int (*) (struct vnode *, struct fid *)) eopnotsupp,
29538625Srvb    cfs_init,
29638625Srvb};
29738625Srvb
29838625Srvb#else
29938625Srvbstruct vfsops cfs_vfsops = {
30038625Srvb    cfs_mount,
30138625Srvb    cfs_start,
30238625Srvb    cfs_unmount,
30338625Srvb    cfs_root,
30438625Srvb    cfs_quotactl,
30538625Srvb    cfs_nb_statfs,
30638625Srvb    cfs_sync,
30738625Srvb    cfs_vget,
30838625Srvb    (int (*) (struct mount *, struct fid *, struct mbuf *, struct vnode **,
30938625Srvb	      int *, struct ucred **))
31038625Srvb	eopnotsupp,
31138625Srvb    (int (*) (struct vnode *, struct fid *)) eopnotsupp,
31238625Srvb    cfs_init,
31338625Srvb};
31438625Srvb
31538625Srvb#endif
31638625Srvb
31738625Srvb
31838625Srvb#include <sys/kernel.h>
31938625SrvbVFS_SET(cfs_vfsops, cfs, MOUNT_CFS, VFCF_NETWORK);
32038625Srvb#endif
32138625Srvb
32238625Srvbint
32338625Srvbcfs_vfsopstats_init(void)
32438625Srvb{
32538625Srvb	register int i;
32638625Srvb
32738625Srvb	for (i=0;i<CFS_VFSOPS_SIZE;i++) {
32838625Srvb		cfs_vfsopstats[i].opcode = i;
32938625Srvb		cfs_vfsopstats[i].entries = 0;
33038625Srvb		cfs_vfsopstats[i].sat_intrn = 0;
33138625Srvb		cfs_vfsopstats[i].unsat_intrn = 0;
33238625Srvb		cfs_vfsopstats[i].gen_intrn = 0;
33338625Srvb	}
33438625Srvb
33538625Srvb	return 0;
33638625Srvb}
33738625Srvb
33838625Srvb
33938625Srvb/*
34038625Srvb * cfs mount vfsop
34138625Srvb * Set up mount info record and attach it to vfs struct.
34238625Srvb */
34338625Srvb/*ARGSUSED*/
34438625Srvbint
34538625Srvbcfs_mount(vfsp, path, data, ndp, p)
34638625Srvb    struct mount *vfsp;		/* Allocated and initialized by mount(2) */
34738625Srvb#ifdef	NetBSD1_3
34838625Srvb    const char *path;		/* path covered: ignored by the fs-layer */
34938625Srvb    void *data;			/* Need to define a data type for this in netbsd? */
35038625Srvb#else
35138625Srvb    char *path;			/* path covered: ignored by the fs-layer */
35238625Srvb    caddr_t data;		/* Need to define a data type for this in netbsd? */
35338625Srvb#endif
35438625Srvb    struct nameidata *ndp;	/* Clobber this to lookup the device name */
35538625Srvb    struct proc *p;		/* The ever-famous proc pointer */
35638625Srvb{
35738625Srvb    struct vnode *dvp;
35838625Srvb    struct cnode *cp;
35938625Srvb    dev_t dev;
36038625Srvb    struct cfs_mntinfo *mi;
36138625Srvb    struct vnode *rootvp;
36238625Srvb    ViceFid rootfid;
36338625Srvb    ViceFid ctlfid;
36438625Srvb    int error;
36538625Srvb
36638625Srvb    ENTRY;
36738625Srvb
36838625Srvb    cfs_vfsopstats_init();
36938625Srvb    cfs_vnodeopstats_init();
37038625Srvb
37138625Srvb    MARK_ENTRY(CFS_MOUNT_STATS);
37238625Srvb    if (CFS_MOUNTED(vfsp)) {
37338625Srvb	MARK_INT_FAIL(CFS_MOUNT_STATS);
37438625Srvb	return(EBUSY);
37538625Srvb    }
37638625Srvb
37738625Srvb    /* Validate mount device.  Similar to getmdev(). */
37838625Srvb
37938625Srvb    NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, data, p);
38038625Srvb    error = namei(ndp);
38138625Srvb    dvp = ndp->ni_vp;
38238625Srvb
38338625Srvb    if (error) {
38438625Srvb	MARK_INT_FAIL(CFS_MOUNT_STATS);
38538625Srvb	return (error);
38638625Srvb    }
38738625Srvb    if (dvp->v_type != VCHR) {
38838625Srvb	MARK_INT_FAIL(CFS_MOUNT_STATS);
38938625Srvb	vrele(dvp);
39038625Srvb	return(ENXIO);
39138625Srvb    }
39238625Srvb    dev = dvp->v_specinfo->si_rdev;
39338625Srvb    vrele(dvp);
39438625Srvb    if (major(dev) >= nchrdev || major(dev) < 0) {
39538625Srvb	MARK_INT_FAIL(CFS_MOUNT_STATS);
39638625Srvb	return(ENXIO);
39738625Srvb    }
39838625Srvb
39938625Srvb    /*
40038625Srvb     * See if the device table matches our expectations.
40138625Srvb     */
40238625Srvb#ifdef	__NetBSD__
40338625Srvb    if (cdevsw[major(dev)].d_open != vc_nb_open)
40438625Srvb#elif	defined(__FreeBSD__)
40538625Srvb    if (cdevsw[major(dev)]->d_open != vc_nb_open)
40638625Srvb#endif
40738625Srvb    {
40838625Srvb	MARK_INT_FAIL(CFS_MOUNT_STATS);
40938625Srvb	return(ENXIO);
41038625Srvb    }
41138625Srvb
41238625Srvb    if (minor(dev) >= NVCFS || minor(dev) < 0) {
41338625Srvb	MARK_INT_FAIL(CFS_MOUNT_STATS);
41438625Srvb	return(ENXIO);
41538625Srvb    }
41638625Srvb
41738625Srvb    /*
41838625Srvb     * Initialize the mount record and link it to the vfs struct
41938625Srvb     */
42038625Srvb    mi = &cfs_mnttbl[minor(dev)];
42138625Srvb
42238625Srvb    if (!VC_OPEN(&mi->mi_vcomm)) {
42338625Srvb	MARK_INT_FAIL(CFS_MOUNT_STATS);
42438625Srvb	return(ENODEV);
42538625Srvb    }
42638625Srvb
42738625Srvb    /* No initialization (here) of mi_vcomm! */
42838625Srvb    vfsp->mnt_data = (qaddr_t)mi;
42938625Srvb#ifdef	__NetBSD__
43038625Srvb    vfsp->mnt_stat.f_fsid.val[0] = 0;
43138625Srvb    vfsp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_CFS);
43238625Srvb#elif	defined(__FreeBSD__) && defined(__FreeBSD_version)
43338625Srvb
43438625Srvb    vfs_getnewfsid (vfsp);
43538625Srvb
43638625Srvb#elif	defined(__FreeBSD__)
43738625Srvb    /* Seems a bit overkill, since usualy /coda is the only mount point
43838625Srvb     * for cfs.
43938625Srvb     */
44038625Srvb    getnewfsid (vfsp, MOUNT_CFS);
44138625Srvb#endif
44238625Srvb    mi->mi_vfsp = vfsp;
44338625Srvb
44438625Srvb    /*
44538625Srvb     * Make a root vnode to placate the Vnode interface, but don't
44638625Srvb     * actually make the CFS_ROOT call to venus until the first call
44738625Srvb     * to cfs_root in case a server is down while venus is starting.
44838625Srvb     */
44938625Srvb    rootfid.Volume = 0;
45038625Srvb    rootfid.Vnode = 0;
45138625Srvb    rootfid.Unique = 0;
45238625Srvb    cp = makecfsnode(&rootfid, vfsp, VDIR);
45338625Srvb    rootvp = CTOV(cp);
45438625Srvb    rootvp->v_flag |= VROOT;
45538625Srvb
45638625Srvb    ctlfid.Volume = CTL_VOL;
45738625Srvb    ctlfid.Vnode = CTL_VNO;
45838625Srvb    ctlfid.Unique = CTL_UNI;
45938625Srvb/*  cp = makecfsnode(&ctlfid, vfsp, VCHR);
46038625Srvb    The above code seems to cause a loop in the cnode links.
46138625Srvb    I don't totally understand when it happens, it is caught
46238625Srvb    when closing down the system.
46338625Srvb */
46438625Srvb    cp = makecfsnode(&ctlfid, 0, VCHR);
46538625Srvb
46638625Srvb    cfs_ctlvp = CTOV(cp);
46738625Srvb
46838625Srvb    /* Add vfs and rootvp to chain of vfs hanging off mntinfo */
46938625Srvb    mi->mi_vfsp = vfsp;
47038625Srvb    mi->mi_rootvp = rootvp;
47138625Srvb
47238625Srvb    /* set filesystem block size */
47338625Srvb    vfsp->mnt_stat.f_bsize = 8192;	    /* XXX -JJK */
47438625Srvb#ifdef	 __FreeBSD__
47538625Srvb    /* Set f_iosize.  XXX -- inamura@isl.ntt.co.jp.
47638625Srvb       For vnode_pager_haspage() references. The value should be obtained
47738625Srvb       from underlying UFS. */
47838625Srvb    /* Checked UFS. iosize is set as 8192 */
47938625Srvb    vfsp->mnt_stat.f_iosize = 8192;
48038625Srvb#endif
48138625Srvb
48238625Srvb    /* error is currently guaranteed to be zero, but in case some
48338625Srvb       code changes... */
48438625Srvb    CFSDEBUG(1,
48538625Srvb	     myprintf(("cfs_mount returned %d\n",error)););
48638625Srvb    if (error)
48738625Srvb	MARK_INT_FAIL(CFS_MOUNT_STATS);
48838625Srvb    else
48938625Srvb	MARK_INT_SAT(CFS_MOUNT_STATS);
49038625Srvb
49138625Srvb    return(error);
49238625Srvb}
49338625Srvb
49438625Srvbint
49538625Srvbcfs_start(vfsp, flags, p)
49638625Srvb    struct mount *vfsp;
49738625Srvb    int flags;
49838625Srvb    struct proc *p;
49938625Srvb{
50038625Srvb    ENTRY;
50138625Srvb    return (0);
50238625Srvb}
50338625Srvb
50438625Srvbint
50538625Srvbcfs_unmount(vfsp, mntflags, p)
50638625Srvb    struct mount *vfsp;
50738625Srvb    int mntflags;
50838625Srvb    struct proc *p;
50938625Srvb{
51038625Srvb    struct cfs_mntinfo *mi = vftomi(vfsp);
51138625Srvb    int active, error = 0;
51238625Srvb
51338625Srvb    ENTRY;
51438625Srvb    MARK_ENTRY(CFS_UMOUNT_STATS);
51538625Srvb    if (!CFS_MOUNTED(vfsp)) {
51638625Srvb	MARK_INT_FAIL(CFS_UMOUNT_STATS);
51738625Srvb	return(EINVAL);
51838625Srvb    }
51938625Srvb
52038625Srvb    if (mi->mi_vfsp == vfsp) {	/* We found the victim */
52138625Srvb	if (!IS_UNMOUNTING(VTOC(mi->mi_rootvp)))
52238625Srvb	    return (EBUSY); 	/* Venus is still running */
52338625Srvb
52438625Srvb#ifdef	DEBUG
52538625Srvb	printf("cfs_unmount: ROOT: vp %p, cp %p\n", mi->mi_rootvp, VTOC(mi->mi_rootvp));
52638625Srvb#endif
52738625Srvb	vrele(mi->mi_rootvp);
52838625Srvb
52938625Srvb#ifdef	NetBSD1_3
53038625Srvb	active = cfs_kill(vfsp, NOT_DOWNCALL);
53138625Srvb
53238625Srvb#if	defined(__NetBSD__) && defined(NetBSD1_3) && (NetBSD1_3 >= 7)
53338625Srvb	if (1)
53438625Srvb#else
53538625Srvb	if ((error = vfs_busy(mi->mi_vfsp)) == 0)
53638625Srvb#endif
53738625Srvb	{
53838625Srvb		error = vflush(mi->mi_vfsp, NULLVP, FORCECLOSE);
53938625Srvb		printf("cfs_unmount: active = %d, vflush active %d\n", active, error);
54038625Srvb		error = 0;
54138625Srvb	} else {
54238625Srvb		printf("cfs_unmount: busy\n");
54338625Srvb	}
54438625Srvb#else	/* FreeBSD I guess */
54538625Srvb	active = cfs_kill(vfsp, NOT_DOWNCALL);
54638625Srvb	error = vflush(mi->mi_vfsp, NULLVP, FORCECLOSE);
54738625Srvb	printf("cfs_unmount: active = %d, vflush active %d\n", active, error);
54838625Srvb	error = 0;
54938625Srvb#endif
55038625Srvb	/* I'm going to take this out to allow lookups to go through. I'm
55138625Srvb	 * not sure it's important anyway. -- DCS 2/2/94
55238625Srvb	 */
55338625Srvb	/* vfsp->VFS_DATA = NULL; */
55438625Srvb
55538625Srvb	/* No more vfsp's to hold onto */
55638625Srvb	mi->mi_vfsp = NULL;
55738625Srvb	mi->mi_rootvp = NULL;
55838625Srvb
55938625Srvb	if (error)
56038625Srvb	    MARK_INT_FAIL(CFS_UMOUNT_STATS);
56138625Srvb	else
56238625Srvb	    MARK_INT_SAT(CFS_UMOUNT_STATS);
56338625Srvb
56438625Srvb	return(error);
56538625Srvb    }
56638625Srvb    return (EINVAL);
56738625Srvb}
56838625Srvb
56938625Srvb/*
57038625Srvb * find root of cfs
57138625Srvb */
57238625Srvbint
57338625Srvbcfs_root(vfsp, vpp)
57438625Srvb	struct mount *vfsp;
57538625Srvb	struct vnode **vpp;
57638625Srvb{
57738625Srvb    struct cfs_mntinfo *mi = vftomi(vfsp);
57838625Srvb    struct vnode **result;
57938625Srvb    int error;
58038625Srvb    struct proc *p = curproc;    /* XXX - bnoble */
58138625Srvb    ViceFid VFid;
58238625Srvb
58338625Srvb    ENTRY;
58438625Srvb    MARK_ENTRY(CFS_ROOT_STATS);
58538625Srvb    result = NULL;
58638625Srvb
58738625Srvb    if (vfsp == mi->mi_vfsp) {
58838625Srvb	if ((VTOC(mi->mi_rootvp)->c_fid.Volume != 0) ||
58938625Srvb	    (VTOC(mi->mi_rootvp)->c_fid.Vnode != 0) ||
59038625Srvb	    (VTOC(mi->mi_rootvp)->c_fid.Unique != 0))
59138625Srvb	    { /* Found valid root. */
59238625Srvb		*vpp = mi->mi_rootvp;
59338625Srvb		/* On Mach, this is vref.  On NetBSD, VOP_LOCK */
59438625Srvb		vref(*vpp);
59538625Srvb		VOP_X_LOCK(*vpp, LK_EXCLUSIVE);
59638625Srvb		MARK_INT_SAT(CFS_ROOT_STATS);
59738625Srvb		return(0);
59838625Srvb	    }
59938625Srvb    }
60038625Srvb
60138625Srvb    error = venus_root(vftomi(vfsp), p->p_cred->pc_ucred, p, &VFid);
60238625Srvb
60338625Srvb    if (!error) {
60438625Srvb	/*
60538625Srvb	 * Save the new rootfid in the cnode, and rehash the cnode into the
60638625Srvb	 * cnode hash with the new fid key.
60738625Srvb	 */
60838625Srvb	cfs_unsave(VTOC(mi->mi_rootvp));
60938625Srvb	VTOC(mi->mi_rootvp)->c_fid = VFid;
61038625Srvb	cfs_save(VTOC(mi->mi_rootvp));
61138625Srvb
61238625Srvb	*vpp = mi->mi_rootvp;
61338625Srvb	vref(*vpp);
61438625Srvb	VOP_X_LOCK(*vpp, LK_EXCLUSIVE);
61538625Srvb	MARK_INT_SAT(CFS_ROOT_STATS);
61638625Srvb	goto exit;
61738625Srvb    } else if (error == ENODEV) {
61838625Srvb	/* Gross hack here! */
61938625Srvb	/*
62038625Srvb	 * If Venus fails to respond to the CFS_ROOT call, cfscall returns
62138625Srvb	 * ENODEV. Return the uninitialized root vnode to allow vfs
62238625Srvb	 * operations such as unmount to continue. Without this hack,
62338625Srvb	 * there is no way to do an unmount if Venus dies before a
62438625Srvb	 * successful CFS_ROOT call is done. All vnode operations
62538625Srvb	 * will fail.
62638625Srvb	 */
62738625Srvb	*vpp = mi->mi_rootvp;
62838625Srvb	vref(*vpp);
62938625Srvb	VOP_X_LOCK(*vpp, LK_EXCLUSIVE);
63038625Srvb	MARK_INT_FAIL(CFS_ROOT_STATS);
63138625Srvb	error = 0;
63238625Srvb	goto exit;
63338625Srvb    } else {
63438625Srvb	CFSDEBUG( CFS_ROOT, myprintf(("error %d in CFS_ROOT\n", error)); );
63538625Srvb	MARK_INT_FAIL(CFS_ROOT_STATS);
63638625Srvb
63738625Srvb	goto exit;
63838625Srvb    }
63938625Srvb exit:
64038625Srvb    return(error);
64138625Srvb}
64238625Srvb
64338625Srvbint
64438625Srvbcfs_quotactl(vfsp, cmd, uid, arg, p)
64538625Srvb    struct mount *vfsp;
64638625Srvb    int cmd;
64738625Srvb    uid_t uid;
64838625Srvb    caddr_t arg;
64938625Srvb    struct proc *p;
65038625Srvb{
65138625Srvb    ENTRY;
65238625Srvb    return (EOPNOTSUPP);
65338625Srvb}
65438625Srvb
65538625Srvb/*
65638625Srvb * Get file system statistics.
65738625Srvb */
65838625Srvbint
65938625Srvbcfs_nb_statfs(vfsp, sbp, p)
66038625Srvb    register struct mount *vfsp;
66138625Srvb    struct statfs *sbp;
66238625Srvb    struct proc *p;
66338625Srvb{
66438625Srvb    ENTRY;
66538625Srvb/*  MARK_ENTRY(CFS_STATFS_STATS); */
66638625Srvb    if (!CFS_MOUNTED(vfsp)) {
66738625Srvb/*	MARK_INT_FAIL(CFS_STATFS_STATS);*/
66838625Srvb	return(EINVAL);
66938625Srvb    }
67038625Srvb
67138625Srvb    bzero(sbp, sizeof(struct statfs));
67238625Srvb    /* XXX - what to do about f_flags, others? --bnoble */
67338625Srvb    /* Below This is what AFS does
67438625Srvb    	#define NB_SFS_SIZ 0x895440
67538625Srvb     */
67638625Srvb    /* Note: Normal fs's have a bsize of 0x400 == 1024 */
67738625Srvb#ifdef	__NetBSD__
67838625Srvb    sbp->f_type = 0;
67938625Srvb#elif	defined(__FreeBSD__)
68038625Srvb    sbp->f_type = MOUNT_CFS;
68138625Srvb#endif
68238625Srvb    sbp->f_bsize = 8192; /* XXX */
68338625Srvb    sbp->f_iosize = 8192; /* XXX */
68438625Srvb#define NB_SFS_SIZ 0x8AB75D
68538625Srvb    sbp->f_blocks = NB_SFS_SIZ;
68638625Srvb    sbp->f_bfree = NB_SFS_SIZ;
68738625Srvb    sbp->f_bavail = NB_SFS_SIZ;
68838625Srvb    sbp->f_files = NB_SFS_SIZ;
68938625Srvb    sbp->f_ffree = NB_SFS_SIZ;
69038625Srvb    bcopy((caddr_t)&(vfsp->mnt_stat.f_fsid), (caddr_t)&(sbp->f_fsid), sizeof (fsid_t));
69138625Srvb#ifdef	__NetBSD__
69238625Srvb    strncpy(sbp->f_fstypename, MOUNT_CFS, MFSNAMELEN-1);
69338625Srvb#endif
69438625Srvb    strcpy(sbp->f_mntonname, "/coda");
69538625Srvb    strcpy(sbp->f_mntfromname, "CFS");
69638625Srvb/*  MARK_INT_SAT(CFS_STATFS_STATS); */
69738625Srvb    return(0);
69838625Srvb}
69938625Srvb
70038625Srvb/*
70138625Srvb * Flush any pending I/O.
70238625Srvb */
70338625Srvbint
70438625Srvbcfs_sync(vfsp, waitfor, cred, p)
70538625Srvb    struct mount *vfsp;
70638625Srvb    int    waitfor;
70738625Srvb    struct ucred *cred;
70838625Srvb    struct proc *p;
70938625Srvb{
71038625Srvb    ENTRY;
71138625Srvb    MARK_ENTRY(CFS_SYNC_STATS);
71238625Srvb    MARK_INT_SAT(CFS_SYNC_STATS);
71338625Srvb    return(0);
71438625Srvb}
71538625Srvb
71638625Srvbint
71738625Srvbcfs_vget(vfsp, ino, vpp)
71838625Srvb    struct mount *vfsp;
71938625Srvb    ino_t ino;
72038625Srvb    struct vnode **vpp;
72138625Srvb{
72238625Srvb    ENTRY;
72338625Srvb    return (EOPNOTSUPP);
72438625Srvb}
72538625Srvb
72638625Srvb/*
72738625Srvb * fhtovp is now what vget used to be in 4.3-derived systems.  For
72838625Srvb * some silly reason, vget is now keyed by a 32 bit ino_t, rather than
72938625Srvb * a type-specific fid.
73038625Srvb */
73138625Srvbint
73238625Srvbcfs_fhtovp(vfsp, fhp, nam, vpp, exflagsp, creadanonp)
73338625Srvb    register struct mount *vfsp;
73438625Srvb    struct fid *fhp;
73538625Srvb    struct mbuf *nam;
73638625Srvb    struct vnode **vpp;
73738625Srvb    int *exflagsp;
73838625Srvb    struct ucred **creadanonp;
73938625Srvb{
74038625Srvb    struct cfid *cfid = (struct cfid *)fhp;
74138625Srvb    struct cnode *cp = 0;
74238625Srvb    int error;
74338625Srvb    struct proc *p = curproc; /* XXX -mach */
74438625Srvb    ViceFid VFid;
74538625Srvb    int vtype;
74638625Srvb
74738625Srvb    ENTRY;
74838625Srvb
74938625Srvb    MARK_ENTRY(CFS_VGET_STATS);
75038625Srvb    /* Check for vget of control object. */
75138625Srvb    if (IS_CTL_FID(&cfid->cfid_fid)) {
75238625Srvb	*vpp = cfs_ctlvp;
75338625Srvb	vref(cfs_ctlvp);
75438625Srvb	MARK_INT_SAT(CFS_VGET_STATS);
75538625Srvb	return(0);
75638625Srvb    }
75738625Srvb
75838625Srvb    error = venus_fhtovp(vftomi(vfsp), &cfid->cfid_fid, p->p_cred->pc_ucred, p, &VFid, &vtype);
75938625Srvb
76038625Srvb    if (error) {
76138625Srvb	CFSDEBUG(CFS_VGET, myprintf(("vget error %d\n",error));)
76238625Srvb	    *vpp = (struct vnode *)0;
76338625Srvb    } else {
76438625Srvb	CFSDEBUG(CFS_VGET,
76538625Srvb		 myprintf(("vget: vol %lx vno %lx uni %lx type %d result %d\n",
76638625Srvb			VFid.Volume, VFid.Vnode, VFid.Unique, vtype, error)); )
76738625Srvb
76838625Srvb	cp = makecfsnode(&VFid, vfsp, vtype);
76938625Srvb	*vpp = CTOV(cp);
77038625Srvb    }
77138625Srvb    return(error);
77238625Srvb}
77338625Srvb
77438625Srvbint
77538625Srvbcfs_vptofh(vnp, fidp)
77638625Srvb    struct vnode *vnp;
77738625Srvb    struct fid   *fidp;
77838625Srvb{
77938625Srvb    ENTRY;
78038625Srvb    return (EOPNOTSUPP);
78138625Srvb}
78238625Srvb
78338625Srvb#ifdef	__NetBSD__
78438625Srvbvoid
78538625Srvbcfs_init(void)
78638625Srvb{
78738625Srvb    ENTRY;
78838625Srvb}
78938625Srvb#elif	defined(__FreeBSD__)
79038625Srvb#ifdef	__FreeBSD_version
79138625Srvbint
79238625Srvbcfs_init(struct vfsconf *vfsp)
79338625Srvb{
79438625Srvb    ENTRY;
79538625Srvb    return 0;
79638625Srvb}
79738625Srvb#else
79838625Srvbint
79938625Srvbcfs_init(void)
80038625Srvb{
80138625Srvb    ENTRY;
80238625Srvb    return 0;
80338625Srvb}
80438625Srvb#endif
80538625Srvb#endif
80638625Srvb
80738625Srvb#if	defined(__NetBSD__) && defined(NetBSD1_3) && (NetBSD1_3 >= 7)
80838625Srvbint
80938625Srvbcfs_sysctl(name, namelen, oldp, oldlp, newp, newl, p)
81038625Srvb	int *name;
81138625Srvb	u_int namelen;
81238625Srvb	void *oldp;
81338625Srvb	size_t *oldlp;
81438625Srvb	void *newp;
81538625Srvb	size_t newl;
81638625Srvb	struct proc *p;
81738625Srvb{
81838625Srvb
81938625Srvb	/* all sysctl names at this level are terminal */
82038625Srvb	if (namelen != 1)
82138625Srvb		return (ENOTDIR);		/* overloaded */
82238625Srvb
82338625Srvb	switch (name[0]) {
82438625Srvb/*
82538625Srvb	case FFS_CLUSTERREAD:
82638625Srvb		return (sysctl_int(oldp, oldlp, newp, newl, &doclusterread));
82738625Srvb */
82838625Srvb	default:
82938625Srvb		return (EOPNOTSUPP);
83038625Srvb	}
83138625Srvb	/* NOTREACHED */
83238625Srvb}
83338625Srvb#endif
83438625Srvb
83538625Srvb/*
83638625Srvb * To allow for greater ease of use, some vnodes may be orphaned when
83738625Srvb * Venus dies.  Certain operations should still be allowed to go
83838625Srvb * through, but without propagating ophan-ness.  So this function will
83938625Srvb * get a new vnode for the file from the current run of Venus.  */
84038625Srvb
84138625Srvbint
84238625SrvbgetNewVnode(vpp)
84338625Srvb     struct vnode **vpp;
84438625Srvb{
84538625Srvb    struct cfid cfid;
84638625Srvb    struct cfs_mntinfo *mi = vftomi((*vpp)->v_mount);
84738625Srvb
84838625Srvb    ENTRY;
84938625Srvb
85038625Srvb    cfid.cfid_len = (short)sizeof(ViceFid);
85138625Srvb    cfid.cfid_fid = VTOC(*vpp)->c_fid;	/* Structure assignment. */
85238625Srvb    /* XXX ? */
85338625Srvb
85438625Srvb    /* We're guessing that if set, the 1st element on the list is a
85538625Srvb     * valid vnode to use. If not, return ENODEV as venus is dead.
85638625Srvb     */
85738625Srvb    if (mi->mi_vfsp == NULL)
85838625Srvb	return ENODEV;
85938625Srvb
86038625Srvb    return cfs_fhtovp(mi->mi_vfsp, (struct fid*)&cfid, NULL, vpp,
86138625Srvb		      NULL, NULL);
86238625Srvb}
86338625Srvb
86438625Srvb#include <ufs/ufs/quota.h>
86538625Srvb#include <ufs/ufs/ufsmount.h>
86638625Srvb/* get the mount structure corresponding to a given device.  Assume
86738625Srvb * device corresponds to a UFS. Return NULL if no device is found.
86838625Srvb */
86938625Srvbstruct mount *devtomp(dev)
87038625Srvb    dev_t dev;
87138625Srvb{
87238625Srvb    struct mount *mp, *nmp;
87338625Srvb
87438625Srvb    for (mp = mountlist.cqh_first; mp != (void*)&mountlist; mp = nmp) {
87538625Srvb	nmp = mp->mnt_list.cqe_next;
87638625Srvb	if (
87738625Srvb#ifdef	__NetBSD__
87838625Srvb	    (!strcmp(mp->mnt_op->vfs_name, MOUNT_UFS)) &&
87938625Srvb#endif
88038625Srvb	    ((VFSTOUFS(mp))->um_dev == (dev_t) dev)) {
88138625Srvb	    /* mount corresponds to UFS and the device matches one we want */
88238625Srvb	    return(mp);
88338625Srvb	}
88438625Srvb    }
88538625Srvb    /* mount structure wasn't found */
88638625Srvb    return(NULL);
88738625Srvb}
888