Home | History | Annotate | Line # | Download | only in nfs
nfs_vfsops.c revision 1.1.1.2
      1      1.1   cgd /*
      2  1.1.1.2  fvdl  * Copyright (c) 1989, 1993
      3  1.1.1.2  fvdl  *	The Regents of the University of California.  All rights reserved.
      4      1.1   cgd  *
      5      1.1   cgd  * This code is derived from software contributed to Berkeley by
      6      1.1   cgd  * Rick Macklem at The University of Guelph.
      7      1.1   cgd  *
      8      1.1   cgd  * Redistribution and use in source and binary forms, with or without
      9      1.1   cgd  * modification, are permitted provided that the following conditions
     10      1.1   cgd  * are met:
     11      1.1   cgd  * 1. Redistributions of source code must retain the above copyright
     12      1.1   cgd  *    notice, this list of conditions and the following disclaimer.
     13      1.1   cgd  * 2. Redistributions in binary form must reproduce the above copyright
     14      1.1   cgd  *    notice, this list of conditions and the following disclaimer in the
     15      1.1   cgd  *    documentation and/or other materials provided with the distribution.
     16      1.1   cgd  * 3. All advertising materials mentioning features or use of this software
     17      1.1   cgd  *    must display the following acknowledgement:
     18      1.1   cgd  *	This product includes software developed by the University of
     19      1.1   cgd  *	California, Berkeley and its contributors.
     20      1.1   cgd  * 4. Neither the name of the University nor the names of its contributors
     21      1.1   cgd  *    may be used to endorse or promote products derived from this software
     22      1.1   cgd  *    without specific prior written permission.
     23      1.1   cgd  *
     24      1.1   cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25      1.1   cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26      1.1   cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27      1.1   cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28      1.1   cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29      1.1   cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30      1.1   cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31      1.1   cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32      1.1   cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33      1.1   cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34      1.1   cgd  * SUCH DAMAGE.
     35      1.1   cgd  *
     36  1.1.1.2  fvdl  *	@(#)nfs_vfsops.c	8.3 (Berkeley) 1/4/94
     37      1.1   cgd  */
     38      1.1   cgd 
     39  1.1.1.2  fvdl #include <sys/param.h>
     40  1.1.1.2  fvdl #include <sys/conf.h>
     41  1.1.1.2  fvdl #include <sys/ioctl.h>
     42  1.1.1.2  fvdl #include <sys/signal.h>
     43  1.1.1.2  fvdl #include <sys/proc.h>
     44  1.1.1.2  fvdl #include <sys/namei.h>
     45  1.1.1.2  fvdl #include <sys/vnode.h>
     46  1.1.1.2  fvdl #include <sys/kernel.h>
     47  1.1.1.2  fvdl #include <sys/mount.h>
     48  1.1.1.2  fvdl #include <sys/buf.h>
     49  1.1.1.2  fvdl #include <sys/mbuf.h>
     50  1.1.1.2  fvdl #include <sys/socket.h>
     51  1.1.1.2  fvdl #include <sys/systm.h>
     52  1.1.1.2  fvdl 
     53  1.1.1.2  fvdl #include <net/if.h>
     54  1.1.1.2  fvdl #include <net/route.h>
     55  1.1.1.2  fvdl #include <netinet/in.h>
     56  1.1.1.2  fvdl 
     57  1.1.1.2  fvdl #include <nfs/rpcv2.h>
     58  1.1.1.2  fvdl #include <nfs/nfsv2.h>
     59  1.1.1.2  fvdl #include <nfs/nfsnode.h>
     60  1.1.1.2  fvdl #include <nfs/nfsmount.h>
     61  1.1.1.2  fvdl #include <nfs/nfs.h>
     62  1.1.1.2  fvdl #include <nfs/xdr_subs.h>
     63  1.1.1.2  fvdl #include <nfs/nfsm_subs.h>
     64  1.1.1.2  fvdl #include <nfs/nfsdiskless.h>
     65  1.1.1.2  fvdl #include <nfs/nqnfs.h>
     66      1.1   cgd 
     67      1.1   cgd /*
     68      1.1   cgd  * nfs vfs operations.
     69      1.1   cgd  */
     70      1.1   cgd struct vfsops nfs_vfsops = {
     71      1.1   cgd 	nfs_mount,
     72      1.1   cgd 	nfs_start,
     73      1.1   cgd 	nfs_unmount,
     74      1.1   cgd 	nfs_root,
     75      1.1   cgd 	nfs_quotactl,
     76      1.1   cgd 	nfs_statfs,
     77      1.1   cgd 	nfs_sync,
     78  1.1.1.2  fvdl 	nfs_vget,
     79      1.1   cgd 	nfs_fhtovp,
     80      1.1   cgd 	nfs_vptofh,
     81      1.1   cgd 	nfs_init,
     82      1.1   cgd };
     83      1.1   cgd 
     84  1.1.1.2  fvdl /*
     85  1.1.1.2  fvdl  * This structure must be filled in by a primary bootstrap or bootstrap
     86  1.1.1.2  fvdl  * server for a diskless/dataless machine. It is initialized below just
     87  1.1.1.2  fvdl  * to ensure that it is allocated to initialized data (.data not .bss).
     88  1.1.1.2  fvdl  */
     89  1.1.1.2  fvdl struct nfs_diskless nfs_diskless = { 0 };
     90  1.1.1.2  fvdl 
     91      1.1   cgd extern u_long nfs_procids[NFS_NPROCS];
     92      1.1   cgd extern u_long nfs_prog, nfs_vers;
     93  1.1.1.2  fvdl void nfs_disconnect __P((struct nfsmount *));
     94  1.1.1.2  fvdl void nfsargs_ntoh __P((struct nfs_args *));
     95  1.1.1.2  fvdl static struct mount *nfs_mountdiskless __P((char *, char *, int,
     96  1.1.1.2  fvdl     struct sockaddr_in *, struct nfs_args *, register struct vnode **));
     97      1.1   cgd 
     98      1.1   cgd #define TRUE	1
     99      1.1   cgd #define	FALSE	0
    100      1.1   cgd 
    101      1.1   cgd /*
    102      1.1   cgd  * nfs statfs call
    103      1.1   cgd  */
    104  1.1.1.2  fvdl int
    105      1.1   cgd nfs_statfs(mp, sbp, p)
    106      1.1   cgd 	struct mount *mp;
    107      1.1   cgd 	register struct statfs *sbp;
    108      1.1   cgd 	struct proc *p;
    109      1.1   cgd {
    110      1.1   cgd 	register struct vnode *vp;
    111      1.1   cgd 	register struct nfsv2_statfs *sfp;
    112      1.1   cgd 	register caddr_t cp;
    113      1.1   cgd 	register long t1;
    114      1.1   cgd 	caddr_t bpos, dpos, cp2;
    115  1.1.1.2  fvdl 	int error = 0, isnq;
    116      1.1   cgd 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
    117      1.1   cgd 	struct nfsmount *nmp;
    118      1.1   cgd 	struct ucred *cred;
    119      1.1   cgd 	struct nfsnode *np;
    120      1.1   cgd 
    121      1.1   cgd 	nmp = VFSTONFS(mp);
    122  1.1.1.2  fvdl 	isnq = (nmp->nm_flag & NFSMNT_NQNFS);
    123      1.1   cgd 	if (error = nfs_nget(mp, &nmp->nm_fh, &np))
    124      1.1   cgd 		return (error);
    125      1.1   cgd 	vp = NFSTOV(np);
    126      1.1   cgd 	nfsstats.rpccnt[NFSPROC_STATFS]++;
    127      1.1   cgd 	cred = crget();
    128      1.1   cgd 	cred->cr_ngroups = 1;
    129  1.1.1.2  fvdl 	nfsm_reqhead(vp, NFSPROC_STATFS, NFSX_FH);
    130      1.1   cgd 	nfsm_fhtom(vp);
    131  1.1.1.2  fvdl 	nfsm_request(vp, NFSPROC_STATFS, p, cred);
    132  1.1.1.2  fvdl 	nfsm_dissect(sfp, struct nfsv2_statfs *, NFSX_STATFS(isnq));
    133      1.1   cgd 	sbp->f_type = MOUNT_NFS;
    134      1.1   cgd 	sbp->f_flags = nmp->nm_flag;
    135  1.1.1.2  fvdl 	sbp->f_iosize = NFS_MAXDGRAMDATA;
    136  1.1.1.2  fvdl 	sbp->f_bsize = fxdr_unsigned(long, sfp->sf_bsize);
    137      1.1   cgd 	sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks);
    138      1.1   cgd 	sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree);
    139      1.1   cgd 	sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail);
    140  1.1.1.2  fvdl 	if (isnq) {
    141  1.1.1.2  fvdl 		sbp->f_files = fxdr_unsigned(long, sfp->sf_files);
    142  1.1.1.2  fvdl 		sbp->f_ffree = fxdr_unsigned(long, sfp->sf_ffree);
    143  1.1.1.2  fvdl 	} else {
    144  1.1.1.2  fvdl 		sbp->f_files = 0;
    145  1.1.1.2  fvdl 		sbp->f_ffree = 0;
    146  1.1.1.2  fvdl 	}
    147      1.1   cgd 	if (sbp != &mp->mnt_stat) {
    148      1.1   cgd 		bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
    149      1.1   cgd 		bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
    150      1.1   cgd 	}
    151      1.1   cgd 	nfsm_reqdone;
    152  1.1.1.2  fvdl 	vrele(vp);
    153      1.1   cgd 	crfree(cred);
    154      1.1   cgd 	return (error);
    155      1.1   cgd }
    156      1.1   cgd 
    157      1.1   cgd /*
    158      1.1   cgd  * Mount a remote root fs via. nfs. This depends on the info in the
    159      1.1   cgd  * nfs_diskless structure that has been filled in properly by some primary
    160      1.1   cgd  * bootstrap.
    161      1.1   cgd  * It goes something like this:
    162      1.1   cgd  * - do enough of "ifconfig" by calling ifioctl() so that the system
    163      1.1   cgd  *   can talk to the server
    164      1.1   cgd  * - If nfs_diskless.mygateway is filled in, use that address as
    165      1.1   cgd  *   a default gateway.
    166      1.1   cgd  * - hand craft the swap nfs vnode hanging off a fake mount point
    167  1.1.1.2  fvdl  *	if swdevt[0].sw_dev == NODEV
    168      1.1   cgd  * - build the rootfs mount point and call mountnfs() to do the rest.
    169      1.1   cgd  */
    170  1.1.1.2  fvdl int
    171      1.1   cgd nfs_mountroot()
    172      1.1   cgd {
    173      1.1   cgd 	register struct mount *mp;
    174  1.1.1.2  fvdl 	register struct nfs_diskless *nd = &nfs_diskless;
    175      1.1   cgd 	struct socket *so;
    176      1.1   cgd 	struct vnode *vp;
    177  1.1.1.2  fvdl 	struct proc *p = curproc;		/* XXX */
    178  1.1.1.2  fvdl 	int error, i;
    179  1.1.1.2  fvdl 
    180  1.1.1.2  fvdl 	/*
    181  1.1.1.2  fvdl 	 * XXX time must be non-zero when we init the interface or else
    182  1.1.1.2  fvdl 	 * the arp code will wedge...
    183  1.1.1.2  fvdl 	 */
    184  1.1.1.2  fvdl 	if (time.tv_sec == 0)
    185  1.1.1.2  fvdl 		time.tv_sec = 1;
    186  1.1.1.2  fvdl 
    187  1.1.1.2  fvdl #ifdef notyet
    188  1.1.1.2  fvdl 	/* Set up swap credentials. */
    189  1.1.1.2  fvdl 	proc0.p_ucred->cr_uid = ntohl(nd->swap_ucred.cr_uid);
    190  1.1.1.2  fvdl 	proc0.p_ucred->cr_gid = ntohl(nd->swap_ucred.cr_gid);
    191  1.1.1.2  fvdl 	if ((proc0.p_ucred->cr_ngroups = ntohs(nd->swap_ucred.cr_ngroups)) >
    192  1.1.1.2  fvdl 		NGROUPS)
    193  1.1.1.2  fvdl 		proc0.p_ucred->cr_ngroups = NGROUPS;
    194  1.1.1.2  fvdl 	for (i = 0; i < proc0.p_ucred->cr_ngroups; i++)
    195  1.1.1.2  fvdl 	    proc0.p_ucred->cr_groups[i] = ntohl(nd->swap_ucred.cr_groups[i]);
    196  1.1.1.2  fvdl #endif
    197      1.1   cgd 
    198      1.1   cgd 	/*
    199  1.1.1.2  fvdl 	 * Do enough of ifconfig(8) so that the critical net interface can
    200      1.1   cgd 	 * talk to the server.
    201      1.1   cgd 	 */
    202  1.1.1.2  fvdl 	if (error = socreate(nd->myif.ifra_addr.sa_family, &so, SOCK_DGRAM, 0))
    203  1.1.1.2  fvdl 		panic("nfs_mountroot: socreate: %d", error);
    204  1.1.1.2  fvdl 	if (error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, p))
    205  1.1.1.2  fvdl 		panic("nfs_mountroot: SIOCAIFADDR: %d", error);
    206      1.1   cgd 	soclose(so);
    207      1.1   cgd 
    208      1.1   cgd 	/*
    209      1.1   cgd 	 * If the gateway field is filled in, set it as the default route.
    210      1.1   cgd 	 */
    211  1.1.1.2  fvdl 	if (nd->mygateway.sin_len != 0) {
    212  1.1.1.2  fvdl 		struct sockaddr_in mask, sin;
    213  1.1.1.2  fvdl 
    214  1.1.1.2  fvdl 		bzero((caddr_t)&mask, sizeof(mask));
    215  1.1.1.2  fvdl 		sin = mask;
    216  1.1.1.2  fvdl 		sin.sin_family = AF_INET;
    217  1.1.1.2  fvdl 		sin.sin_len = sizeof(sin);
    218  1.1.1.2  fvdl 		if (error = rtrequest(RTM_ADD, (struct sockaddr *)&sin,
    219  1.1.1.2  fvdl 		    (struct sockaddr *)&nd->mygateway,
    220  1.1.1.2  fvdl 		    (struct sockaddr *)&mask,
    221  1.1.1.2  fvdl 		    RTF_UP | RTF_GATEWAY, (struct rtentry **)0))
    222  1.1.1.2  fvdl 			panic("nfs_mountroot: RTM_ADD: %d", error);
    223      1.1   cgd 	}
    224      1.1   cgd 
    225      1.1   cgd 	/*
    226      1.1   cgd 	 * If swapping to an nfs node (indicated by swdevt[0].sw_dev == NODEV):
    227      1.1   cgd 	 * Create a fake mount point just for the swap vnode so that the
    228      1.1   cgd 	 * swap file can be on a different server from the rootfs.
    229      1.1   cgd 	 */
    230      1.1   cgd 	if (swdevt[0].sw_dev == NODEV) {
    231  1.1.1.2  fvdl 		nd->swap_args.fh = (nfsv2fh_t *)nd->swap_fh;
    232  1.1.1.2  fvdl 		(void) nfs_mountdiskless(nd->swap_hostnam, "/swap", 0,
    233  1.1.1.2  fvdl 		    &nd->swap_saddr, &nd->swap_args, &vp);
    234      1.1   cgd 
    235      1.1   cgd 		/*
    236      1.1   cgd 		 * Since the swap file is not the root dir of a file system,
    237      1.1   cgd 		 * hack it to a regular file.
    238      1.1   cgd 		 */
    239      1.1   cgd 		vp->v_type = VREG;
    240      1.1   cgd 		vp->v_flag = 0;
    241      1.1   cgd 		swapdev_vp = vp;
    242      1.1   cgd 		VREF(vp);
    243      1.1   cgd 		swdevt[0].sw_vp = vp;
    244  1.1.1.2  fvdl 		swdevt[0].sw_nblks = ntohl(nd->swap_nblks);
    245  1.1.1.2  fvdl 	} else if (bdevvp(swapdev, &swapdev_vp))
    246  1.1.1.2  fvdl 		panic("nfs_mountroot: can't setup swapdev_vp");
    247      1.1   cgd 
    248      1.1   cgd 	/*
    249      1.1   cgd 	 * Create the rootfs mount point.
    250      1.1   cgd 	 */
    251  1.1.1.2  fvdl 	nd->root_args.fh = (nfsv2fh_t *)nd->root_fh;
    252  1.1.1.2  fvdl 	mp = nfs_mountdiskless(nd->root_hostnam, "/", MNT_RDONLY,
    253  1.1.1.2  fvdl 	    &nd->root_saddr, &nd->root_args, &vp);
    254      1.1   cgd 
    255      1.1   cgd 	if (vfs_lock(mp))
    256  1.1.1.2  fvdl 		panic("nfs_mountroot: vfs_lock");
    257  1.1.1.2  fvdl 	TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
    258  1.1.1.2  fvdl 	mp->mnt_flag |= MNT_ROOTFS;
    259      1.1   cgd 	mp->mnt_vnodecovered = NULLVP;
    260      1.1   cgd 	vfs_unlock(mp);
    261      1.1   cgd 	rootvp = vp;
    262  1.1.1.2  fvdl 
    263  1.1.1.2  fvdl 	/*
    264  1.1.1.2  fvdl 	 * This is not really an nfs issue, but it is much easier to
    265  1.1.1.2  fvdl 	 * set hostname here and then let the "/etc/rc.xxx" files
    266  1.1.1.2  fvdl 	 * mount the right /var based upon its preset value.
    267  1.1.1.2  fvdl 	 */
    268  1.1.1.2  fvdl 	bcopy(nd->my_hostnam, hostname, MAXHOSTNAMELEN);
    269  1.1.1.2  fvdl 	hostname[MAXHOSTNAMELEN - 1] = '\0';
    270  1.1.1.2  fvdl 	for (i = 0; i < MAXHOSTNAMELEN; i++)
    271  1.1.1.2  fvdl 		if (hostname[i] == '\0')
    272  1.1.1.2  fvdl 			break;
    273  1.1.1.2  fvdl 	hostnamelen = i;
    274  1.1.1.2  fvdl 	inittodr(ntohl(nd->root_time));
    275      1.1   cgd 	return (0);
    276      1.1   cgd }
    277      1.1   cgd 
    278      1.1   cgd /*
    279  1.1.1.2  fvdl  * Internal version of mount system call for diskless setup.
    280  1.1.1.2  fvdl  */
    281  1.1.1.2  fvdl static struct mount *
    282  1.1.1.2  fvdl nfs_mountdiskless(path, which, mountflag, sin, args, vpp)
    283  1.1.1.2  fvdl 	char *path;
    284  1.1.1.2  fvdl 	char *which;
    285  1.1.1.2  fvdl 	int mountflag;
    286  1.1.1.2  fvdl 	struct sockaddr_in *sin;
    287  1.1.1.2  fvdl 	struct nfs_args *args;
    288  1.1.1.2  fvdl 	register struct vnode **vpp;
    289  1.1.1.2  fvdl {
    290  1.1.1.2  fvdl 	register struct mount *mp;
    291  1.1.1.2  fvdl 	register struct mbuf *m;
    292  1.1.1.2  fvdl 	register int error;
    293  1.1.1.2  fvdl 
    294  1.1.1.2  fvdl 	mp = (struct mount *)malloc((u_long)sizeof(struct mount),
    295  1.1.1.2  fvdl 	    M_MOUNT, M_NOWAIT);
    296  1.1.1.2  fvdl 	if (mp == NULL)
    297  1.1.1.2  fvdl 		panic("nfs_mountroot: %s mount malloc", which);
    298  1.1.1.2  fvdl 	bzero((char *)mp, (u_long)sizeof(struct mount));
    299  1.1.1.2  fvdl 	mp->mnt_op = &nfs_vfsops;
    300  1.1.1.2  fvdl 	mp->mnt_flag = mountflag;
    301  1.1.1.2  fvdl 
    302  1.1.1.2  fvdl 	MGET(m, MT_SONAME, M_DONTWAIT);
    303  1.1.1.2  fvdl 	if (m == NULL)
    304  1.1.1.2  fvdl 		panic("nfs_mountroot: %s mount mbuf", which);
    305  1.1.1.2  fvdl 	bcopy((caddr_t)sin, mtod(m, caddr_t), sin->sin_len);
    306  1.1.1.2  fvdl 	m->m_len = sin->sin_len;
    307  1.1.1.2  fvdl 	nfsargs_ntoh(args);
    308  1.1.1.2  fvdl 	if (error = mountnfs(args, mp, m, which, path, vpp))
    309  1.1.1.2  fvdl 		panic("nfs_mountroot: mount %s on %s: %d", path, which, error);
    310  1.1.1.2  fvdl 
    311  1.1.1.2  fvdl 	return (mp);
    312  1.1.1.2  fvdl }
    313  1.1.1.2  fvdl 
    314  1.1.1.2  fvdl /*
    315  1.1.1.2  fvdl  * Convert the integer fields of the nfs_args structure from net byte order
    316  1.1.1.2  fvdl  * to host byte order. Called by nfs_mountroot() above.
    317  1.1.1.2  fvdl  */
    318  1.1.1.2  fvdl void
    319  1.1.1.2  fvdl nfsargs_ntoh(nfsp)
    320  1.1.1.2  fvdl 	register struct nfs_args *nfsp;
    321  1.1.1.2  fvdl {
    322  1.1.1.2  fvdl 
    323  1.1.1.2  fvdl 	NTOHL(nfsp->sotype);
    324  1.1.1.2  fvdl 	NTOHL(nfsp->proto);
    325  1.1.1.2  fvdl 	NTOHL(nfsp->flags);
    326  1.1.1.2  fvdl 	NTOHL(nfsp->wsize);
    327  1.1.1.2  fvdl 	NTOHL(nfsp->rsize);
    328  1.1.1.2  fvdl 	NTOHL(nfsp->timeo);
    329  1.1.1.2  fvdl 	NTOHL(nfsp->retrans);
    330  1.1.1.2  fvdl 	NTOHL(nfsp->maxgrouplist);
    331  1.1.1.2  fvdl 	NTOHL(nfsp->readahead);
    332  1.1.1.2  fvdl 	NTOHL(nfsp->leaseterm);
    333  1.1.1.2  fvdl 	NTOHL(nfsp->deadthresh);
    334  1.1.1.2  fvdl }
    335  1.1.1.2  fvdl 
    336  1.1.1.2  fvdl /*
    337      1.1   cgd  * VFS Operations.
    338      1.1   cgd  *
    339      1.1   cgd  * mount system call
    340      1.1   cgd  * It seems a bit dumb to copyinstr() the host and path here and then
    341      1.1   cgd  * bcopy() them in mountnfs(), but I wanted to detect errors before
    342      1.1   cgd  * doing the sockargs() call because sockargs() allocates an mbuf and
    343      1.1   cgd  * an error after that means that I have to release the mbuf.
    344      1.1   cgd  */
    345      1.1   cgd /* ARGSUSED */
    346  1.1.1.2  fvdl int
    347      1.1   cgd nfs_mount(mp, path, data, ndp, p)
    348      1.1   cgd 	struct mount *mp;
    349      1.1   cgd 	char *path;
    350      1.1   cgd 	caddr_t data;
    351      1.1   cgd 	struct nameidata *ndp;
    352      1.1   cgd 	struct proc *p;
    353      1.1   cgd {
    354      1.1   cgd 	int error;
    355      1.1   cgd 	struct nfs_args args;
    356      1.1   cgd 	struct mbuf *nam;
    357      1.1   cgd 	struct vnode *vp;
    358      1.1   cgd 	char pth[MNAMELEN], hst[MNAMELEN];
    359      1.1   cgd 	u_int len;
    360      1.1   cgd 	nfsv2fh_t nfh;
    361      1.1   cgd 
    362      1.1   cgd 	if (error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args)))
    363      1.1   cgd 		return (error);
    364      1.1   cgd 	if (error = copyin((caddr_t)args.fh, (caddr_t)&nfh, sizeof (nfsv2fh_t)))
    365      1.1   cgd 		return (error);
    366      1.1   cgd 	if (error = copyinstr(path, pth, MNAMELEN-1, &len))
    367      1.1   cgd 		return (error);
    368      1.1   cgd 	bzero(&pth[len], MNAMELEN - len);
    369      1.1   cgd 	if (error = copyinstr(args.hostname, hst, MNAMELEN-1, &len))
    370      1.1   cgd 		return (error);
    371      1.1   cgd 	bzero(&hst[len], MNAMELEN - len);
    372      1.1   cgd 	/* sockargs() call must be after above copyin() calls */
    373      1.1   cgd 	if (error = sockargs(&nam, (caddr_t)args.addr,
    374  1.1.1.2  fvdl 		args.addrlen, MT_SONAME))
    375      1.1   cgd 		return (error);
    376      1.1   cgd 	args.fh = &nfh;
    377      1.1   cgd 	error = mountnfs(&args, mp, nam, pth, hst, &vp);
    378      1.1   cgd 	return (error);
    379      1.1   cgd }
    380      1.1   cgd 
    381      1.1   cgd /*
    382      1.1   cgd  * Common code for mount and mountroot
    383      1.1   cgd  */
    384  1.1.1.2  fvdl int
    385      1.1   cgd mountnfs(argp, mp, nam, pth, hst, vpp)
    386      1.1   cgd 	register struct nfs_args *argp;
    387      1.1   cgd 	register struct mount *mp;
    388      1.1   cgd 	struct mbuf *nam;
    389      1.1   cgd 	char *pth, *hst;
    390      1.1   cgd 	struct vnode **vpp;
    391      1.1   cgd {
    392      1.1   cgd 	register struct nfsmount *nmp;
    393      1.1   cgd 	struct nfsnode *np;
    394      1.1   cgd 	int error;
    395      1.1   cgd 
    396  1.1.1.2  fvdl 	if (mp->mnt_flag & MNT_UPDATE) {
    397  1.1.1.2  fvdl 		nmp = VFSTONFS(mp);
    398  1.1.1.2  fvdl 		/* update paths, file handles, etc, here	XXX */
    399  1.1.1.2  fvdl 		m_freem(nam);
    400  1.1.1.2  fvdl 		return (0);
    401  1.1.1.2  fvdl 	} else {
    402  1.1.1.2  fvdl 		MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount),
    403  1.1.1.2  fvdl 		    M_NFSMNT, M_WAITOK);
    404  1.1.1.2  fvdl 		bzero((caddr_t)nmp, sizeof (struct nfsmount));
    405  1.1.1.2  fvdl 		mp->mnt_data = (qaddr_t)nmp;
    406      1.1   cgd 	}
    407  1.1.1.2  fvdl 	getnewfsid(mp, MOUNT_NFS);
    408      1.1   cgd 	nmp->nm_mountp = mp;
    409      1.1   cgd 	nmp->nm_flag = argp->flags;
    410  1.1.1.2  fvdl 	if ((nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_MYWRITE)) ==
    411  1.1.1.2  fvdl 		(NFSMNT_NQNFS | NFSMNT_MYWRITE)) {
    412  1.1.1.2  fvdl 		error = EPERM;
    413  1.1.1.2  fvdl 		goto bad;
    414  1.1.1.2  fvdl 	}
    415  1.1.1.2  fvdl 	if (nmp->nm_flag & NFSMNT_NQNFS)
    416  1.1.1.2  fvdl 		/*
    417  1.1.1.2  fvdl 		 * We have to set mnt_maxsymlink to a non-zero value so
    418  1.1.1.2  fvdl 		 * that COMPAT_43 routines will know that we are setting
    419  1.1.1.2  fvdl 		 * the d_type field in directories (and can zero it for
    420  1.1.1.2  fvdl 		 * unsuspecting binaries).
    421  1.1.1.2  fvdl 		 */
    422  1.1.1.2  fvdl 		mp->mnt_maxsymlinklen = 1;
    423  1.1.1.2  fvdl 	nmp->nm_timeo = NFS_TIMEO;
    424      1.1   cgd 	nmp->nm_retry = NFS_RETRANS;
    425      1.1   cgd 	nmp->nm_wsize = NFS_WSIZE;
    426      1.1   cgd 	nmp->nm_rsize = NFS_RSIZE;
    427  1.1.1.2  fvdl 	nmp->nm_numgrps = NFS_MAXGRPS;
    428  1.1.1.2  fvdl 	nmp->nm_readahead = NFS_DEFRAHEAD;
    429  1.1.1.2  fvdl 	nmp->nm_leaseterm = NQ_DEFLEASE;
    430  1.1.1.2  fvdl 	nmp->nm_deadthresh = NQ_DEADTHRESH;
    431  1.1.1.2  fvdl 	nmp->nm_tnext = (struct nfsnode *)nmp;
    432  1.1.1.2  fvdl 	nmp->nm_tprev = (struct nfsnode *)nmp;
    433  1.1.1.2  fvdl 	nmp->nm_inprog = NULLVP;
    434      1.1   cgd 	bcopy((caddr_t)argp->fh, (caddr_t)&nmp->nm_fh, sizeof(nfsv2fh_t));
    435  1.1.1.2  fvdl 	mp->mnt_stat.f_type = MOUNT_NFS;
    436      1.1   cgd 	bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
    437      1.1   cgd 	bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN);
    438      1.1   cgd 	nmp->nm_nam = nam;
    439      1.1   cgd 
    440      1.1   cgd 	if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
    441  1.1.1.2  fvdl 		nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
    442  1.1.1.2  fvdl 		if (nmp->nm_timeo < NFS_MINTIMEO)
    443  1.1.1.2  fvdl 			nmp->nm_timeo = NFS_MINTIMEO;
    444  1.1.1.2  fvdl 		else if (nmp->nm_timeo > NFS_MAXTIMEO)
    445  1.1.1.2  fvdl 			nmp->nm_timeo = NFS_MAXTIMEO;
    446      1.1   cgd 	}
    447      1.1   cgd 
    448      1.1   cgd 	if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
    449      1.1   cgd 		nmp->nm_retry = argp->retrans;
    450      1.1   cgd 		if (nmp->nm_retry > NFS_MAXREXMIT)
    451      1.1   cgd 			nmp->nm_retry = NFS_MAXREXMIT;
    452      1.1   cgd 	}
    453      1.1   cgd 
    454      1.1   cgd 	if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
    455      1.1   cgd 		nmp->nm_wsize = argp->wsize;
    456      1.1   cgd 		/* Round down to multiple of blocksize */
    457      1.1   cgd 		nmp->nm_wsize &= ~0x1ff;
    458      1.1   cgd 		if (nmp->nm_wsize <= 0)
    459      1.1   cgd 			nmp->nm_wsize = 512;
    460      1.1   cgd 		else if (nmp->nm_wsize > NFS_MAXDATA)
    461      1.1   cgd 			nmp->nm_wsize = NFS_MAXDATA;
    462      1.1   cgd 	}
    463      1.1   cgd 	if (nmp->nm_wsize > MAXBSIZE)
    464      1.1   cgd 		nmp->nm_wsize = MAXBSIZE;
    465      1.1   cgd 
    466      1.1   cgd 	if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
    467      1.1   cgd 		nmp->nm_rsize = argp->rsize;
    468      1.1   cgd 		/* Round down to multiple of blocksize */
    469      1.1   cgd 		nmp->nm_rsize &= ~0x1ff;
    470      1.1   cgd 		if (nmp->nm_rsize <= 0)
    471      1.1   cgd 			nmp->nm_rsize = 512;
    472      1.1   cgd 		else if (nmp->nm_rsize > NFS_MAXDATA)
    473      1.1   cgd 			nmp->nm_rsize = NFS_MAXDATA;
    474      1.1   cgd 	}
    475      1.1   cgd 	if (nmp->nm_rsize > MAXBSIZE)
    476      1.1   cgd 		nmp->nm_rsize = MAXBSIZE;
    477  1.1.1.2  fvdl 	if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0 &&
    478  1.1.1.2  fvdl 		argp->maxgrouplist <= NFS_MAXGRPS)
    479  1.1.1.2  fvdl 		nmp->nm_numgrps = argp->maxgrouplist;
    480  1.1.1.2  fvdl 	if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0 &&
    481  1.1.1.2  fvdl 		argp->readahead <= NFS_MAXRAHEAD)
    482  1.1.1.2  fvdl 		nmp->nm_readahead = argp->readahead;
    483  1.1.1.2  fvdl 	if ((argp->flags & NFSMNT_LEASETERM) && argp->leaseterm >= 2 &&
    484  1.1.1.2  fvdl 		argp->leaseterm <= NQ_MAXLEASE)
    485  1.1.1.2  fvdl 		nmp->nm_leaseterm = argp->leaseterm;
    486  1.1.1.2  fvdl 	if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 1 &&
    487  1.1.1.2  fvdl 		argp->deadthresh <= NQ_NEVERDEAD)
    488  1.1.1.2  fvdl 		nmp->nm_deadthresh = argp->deadthresh;
    489      1.1   cgd 	/* Set up the sockets and per-host congestion */
    490      1.1   cgd 	nmp->nm_sotype = argp->sotype;
    491      1.1   cgd 	nmp->nm_soproto = argp->proto;
    492      1.1   cgd 
    493  1.1.1.2  fvdl 	/*
    494  1.1.1.2  fvdl 	 * For Connection based sockets (TCP,...) defer the connect until
    495  1.1.1.2  fvdl 	 * the first request, in case the server is not responding.
    496  1.1.1.2  fvdl 	 */
    497  1.1.1.2  fvdl 	if (nmp->nm_sotype == SOCK_DGRAM &&
    498  1.1.1.2  fvdl 		(error = nfs_connect(nmp, (struct nfsreq *)0)))
    499      1.1   cgd 		goto bad;
    500  1.1.1.2  fvdl 
    501  1.1.1.2  fvdl 	/*
    502  1.1.1.2  fvdl 	 * This is silly, but it has to be set so that vinifod() works.
    503  1.1.1.2  fvdl 	 * We do not want to do an nfs_statfs() here since we can get
    504  1.1.1.2  fvdl 	 * stuck on a dead server and we are holding a lock on the mount
    505  1.1.1.2  fvdl 	 * point.
    506  1.1.1.2  fvdl 	 */
    507  1.1.1.2  fvdl 	mp->mnt_stat.f_iosize = NFS_MAXDGRAMDATA;
    508      1.1   cgd 	/*
    509      1.1   cgd 	 * A reference count is needed on the nfsnode representing the
    510      1.1   cgd 	 * remote root.  If this object is not persistent, then backward
    511      1.1   cgd 	 * traversals of the mount point (i.e. "..") will not work if
    512      1.1   cgd 	 * the nfsnode gets flushed out of the cache. Ufs does not have
    513      1.1   cgd 	 * this problem, because one can identify root inodes by their
    514      1.1   cgd 	 * number == ROOTINO (2).
    515      1.1   cgd 	 */
    516      1.1   cgd 	if (error = nfs_nget(mp, &nmp->nm_fh, &np))
    517      1.1   cgd 		goto bad;
    518      1.1   cgd 	*vpp = NFSTOV(np);
    519      1.1   cgd 
    520      1.1   cgd 	return (0);
    521      1.1   cgd bad:
    522      1.1   cgd 	nfs_disconnect(nmp);
    523  1.1.1.2  fvdl 	free((caddr_t)nmp, M_NFSMNT);
    524      1.1   cgd 	m_freem(nam);
    525      1.1   cgd 	return (error);
    526      1.1   cgd }
    527      1.1   cgd 
    528      1.1   cgd /*
    529      1.1   cgd  * unmount system call
    530      1.1   cgd  */
    531  1.1.1.2  fvdl int
    532      1.1   cgd nfs_unmount(mp, mntflags, p)
    533      1.1   cgd 	struct mount *mp;
    534      1.1   cgd 	int mntflags;
    535      1.1   cgd 	struct proc *p;
    536      1.1   cgd {
    537      1.1   cgd 	register struct nfsmount *nmp;
    538      1.1   cgd 	struct nfsnode *np;
    539      1.1   cgd 	struct vnode *vp;
    540      1.1   cgd 	int error, flags = 0;
    541      1.1   cgd 	extern int doforce;
    542      1.1   cgd 
    543      1.1   cgd 	if (mntflags & MNT_FORCE) {
    544  1.1.1.2  fvdl 		if (!doforce || (mp->mnt_flag & MNT_ROOTFS))
    545      1.1   cgd 			return (EINVAL);
    546      1.1   cgd 		flags |= FORCECLOSE;
    547      1.1   cgd 	}
    548      1.1   cgd 	nmp = VFSTONFS(mp);
    549      1.1   cgd 	/*
    550      1.1   cgd 	 * Goes something like this..
    551      1.1   cgd 	 * - Check for activity on the root vnode (other than ourselves).
    552      1.1   cgd 	 * - Call vflush() to clear out vnodes for this file system,
    553      1.1   cgd 	 *   except for the root vnode.
    554      1.1   cgd 	 * - Decrement reference on the vnode representing remote root.
    555      1.1   cgd 	 * - Close the socket
    556      1.1   cgd 	 * - Free up the data structures
    557      1.1   cgd 	 */
    558      1.1   cgd 	/*
    559      1.1   cgd 	 * We need to decrement the ref. count on the nfsnode representing
    560      1.1   cgd 	 * the remote root.  See comment in mountnfs().  The VFS unmount()
    561      1.1   cgd 	 * has done vput on this vnode, otherwise we would get deadlock!
    562      1.1   cgd 	 */
    563      1.1   cgd 	if (error = nfs_nget(mp, &nmp->nm_fh, &np))
    564      1.1   cgd 		return(error);
    565      1.1   cgd 	vp = NFSTOV(np);
    566      1.1   cgd 	if (vp->v_usecount > 2) {
    567      1.1   cgd 		vput(vp);
    568      1.1   cgd 		return (EBUSY);
    569      1.1   cgd 	}
    570  1.1.1.2  fvdl 
    571  1.1.1.2  fvdl 	/*
    572  1.1.1.2  fvdl 	 * Must handshake with nqnfs_clientd() if it is active.
    573  1.1.1.2  fvdl 	 */
    574  1.1.1.2  fvdl 	nmp->nm_flag |= NFSMNT_DISMINPROG;
    575  1.1.1.2  fvdl 	while (nmp->nm_inprog != NULLVP)
    576  1.1.1.2  fvdl 		(void) tsleep((caddr_t)&lbolt, PSOCK, "nfsdism", 0);
    577      1.1   cgd 	if (error = vflush(mp, vp, flags)) {
    578      1.1   cgd 		vput(vp);
    579  1.1.1.2  fvdl 		nmp->nm_flag &= ~NFSMNT_DISMINPROG;
    580      1.1   cgd 		return (error);
    581      1.1   cgd 	}
    582  1.1.1.2  fvdl 
    583  1.1.1.2  fvdl 	/*
    584  1.1.1.2  fvdl 	 * We are now committed to the unmount.
    585  1.1.1.2  fvdl 	 * For NQNFS, let the server daemon free the nfsmount structure.
    586  1.1.1.2  fvdl 	 */
    587  1.1.1.2  fvdl 	if (nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB))
    588  1.1.1.2  fvdl 		nmp->nm_flag |= NFSMNT_DISMNT;
    589  1.1.1.2  fvdl 
    590      1.1   cgd 	/*
    591  1.1.1.2  fvdl 	 * There are two reference counts to get rid of here.
    592      1.1   cgd 	 */
    593      1.1   cgd 	vrele(vp);
    594  1.1.1.2  fvdl 	vrele(vp);
    595  1.1.1.2  fvdl 	vgone(vp);
    596      1.1   cgd 	nfs_disconnect(nmp);
    597      1.1   cgd 	m_freem(nmp->nm_nam);
    598  1.1.1.2  fvdl 
    599  1.1.1.2  fvdl 	if ((nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB)) == 0)
    600  1.1.1.2  fvdl 		free((caddr_t)nmp, M_NFSMNT);
    601      1.1   cgd 	return (0);
    602      1.1   cgd }
    603      1.1   cgd 
    604      1.1   cgd /*
    605      1.1   cgd  * Return root of a filesystem
    606      1.1   cgd  */
    607  1.1.1.2  fvdl int
    608      1.1   cgd nfs_root(mp, vpp)
    609      1.1   cgd 	struct mount *mp;
    610      1.1   cgd 	struct vnode **vpp;
    611      1.1   cgd {
    612      1.1   cgd 	register struct vnode *vp;
    613      1.1   cgd 	struct nfsmount *nmp;
    614      1.1   cgd 	struct nfsnode *np;
    615      1.1   cgd 	int error;
    616      1.1   cgd 
    617      1.1   cgd 	nmp = VFSTONFS(mp);
    618      1.1   cgd 	if (error = nfs_nget(mp, &nmp->nm_fh, &np))
    619      1.1   cgd 		return (error);
    620      1.1   cgd 	vp = NFSTOV(np);
    621      1.1   cgd 	vp->v_type = VDIR;
    622      1.1   cgd 	vp->v_flag = VROOT;
    623      1.1   cgd 	*vpp = vp;
    624      1.1   cgd 	return (0);
    625      1.1   cgd }
    626      1.1   cgd 
    627      1.1   cgd extern int syncprt;
    628      1.1   cgd 
    629      1.1   cgd /*
    630      1.1   cgd  * Flush out the buffer cache
    631      1.1   cgd  */
    632      1.1   cgd /* ARGSUSED */
    633  1.1.1.2  fvdl int
    634  1.1.1.2  fvdl nfs_sync(mp, waitfor, cred, p)
    635      1.1   cgd 	struct mount *mp;
    636      1.1   cgd 	int waitfor;
    637  1.1.1.2  fvdl 	struct ucred *cred;
    638  1.1.1.2  fvdl 	struct proc *p;
    639      1.1   cgd {
    640  1.1.1.2  fvdl 	register struct vnode *vp;
    641  1.1.1.2  fvdl 	int error, allerror = 0;
    642  1.1.1.2  fvdl 
    643      1.1   cgd 	/*
    644      1.1   cgd 	 * Force stale buffer cache information to be flushed.
    645      1.1   cgd 	 */
    646  1.1.1.2  fvdl loop:
    647  1.1.1.2  fvdl 	for (vp = mp->mnt_vnodelist.lh_first;
    648  1.1.1.2  fvdl 	     vp != NULL;
    649  1.1.1.2  fvdl 	     vp = vp->v_mntvnodes.le_next) {
    650  1.1.1.2  fvdl 		/*
    651  1.1.1.2  fvdl 		 * If the vnode that we are about to sync is no longer
    652  1.1.1.2  fvdl 		 * associated with this mount point, start over.
    653  1.1.1.2  fvdl 		 */
    654  1.1.1.2  fvdl 		if (vp->v_mount != mp)
    655  1.1.1.2  fvdl 			goto loop;
    656  1.1.1.2  fvdl 		if (VOP_ISLOCKED(vp) || vp->v_dirtyblkhd.lh_first == NULL)
    657  1.1.1.2  fvdl 			continue;
    658  1.1.1.2  fvdl 		if (vget(vp, 1))
    659  1.1.1.2  fvdl 			goto loop;
    660  1.1.1.2  fvdl 		if (error = VOP_FSYNC(vp, cred, waitfor, p))
    661  1.1.1.2  fvdl 			allerror = error;
    662  1.1.1.2  fvdl 		vput(vp);
    663  1.1.1.2  fvdl 	}
    664  1.1.1.2  fvdl 	return (allerror);
    665      1.1   cgd }
    666      1.1   cgd 
    667      1.1   cgd /*
    668  1.1.1.2  fvdl  * NFS flat namespace lookup.
    669  1.1.1.2  fvdl  * Currently unsupported.
    670      1.1   cgd  */
    671      1.1   cgd /* ARGSUSED */
    672  1.1.1.2  fvdl int
    673  1.1.1.2  fvdl nfs_vget(mp, ino, vpp)
    674      1.1   cgd 	struct mount *mp;
    675  1.1.1.2  fvdl 	ino_t ino;
    676  1.1.1.2  fvdl 	struct vnode **vpp;
    677  1.1.1.2  fvdl {
    678  1.1.1.2  fvdl 
    679  1.1.1.2  fvdl 	return (EOPNOTSUPP);
    680  1.1.1.2  fvdl }
    681  1.1.1.2  fvdl 
    682  1.1.1.2  fvdl /*
    683  1.1.1.2  fvdl  * At this point, this should never happen
    684  1.1.1.2  fvdl  */
    685  1.1.1.2  fvdl /* ARGSUSED */
    686  1.1.1.2  fvdl int
    687  1.1.1.2  fvdl nfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
    688  1.1.1.2  fvdl 	register struct mount *mp;
    689      1.1   cgd 	struct fid *fhp;
    690  1.1.1.2  fvdl 	struct mbuf *nam;
    691      1.1   cgd 	struct vnode **vpp;
    692  1.1.1.2  fvdl 	int *exflagsp;
    693  1.1.1.2  fvdl 	struct ucred **credanonp;
    694      1.1   cgd {
    695      1.1   cgd 
    696      1.1   cgd 	return (EINVAL);
    697      1.1   cgd }
    698      1.1   cgd 
    699      1.1   cgd /*
    700      1.1   cgd  * Vnode pointer to File handle, should never happen either
    701      1.1   cgd  */
    702      1.1   cgd /* ARGSUSED */
    703  1.1.1.2  fvdl int
    704      1.1   cgd nfs_vptofh(vp, fhp)
    705      1.1   cgd 	struct vnode *vp;
    706      1.1   cgd 	struct fid *fhp;
    707      1.1   cgd {
    708      1.1   cgd 
    709      1.1   cgd 	return (EINVAL);
    710      1.1   cgd }
    711      1.1   cgd 
    712      1.1   cgd /*
    713      1.1   cgd  * Vfs start routine, a no-op.
    714      1.1   cgd  */
    715      1.1   cgd /* ARGSUSED */
    716  1.1.1.2  fvdl int
    717      1.1   cgd nfs_start(mp, flags, p)
    718      1.1   cgd 	struct mount *mp;
    719      1.1   cgd 	int flags;
    720      1.1   cgd 	struct proc *p;
    721      1.1   cgd {
    722      1.1   cgd 
    723      1.1   cgd 	return (0);
    724      1.1   cgd }
    725      1.1   cgd 
    726      1.1   cgd /*
    727      1.1   cgd  * Do operations associated with quotas, not supported
    728      1.1   cgd  */
    729  1.1.1.2  fvdl /* ARGSUSED */
    730  1.1.1.2  fvdl int
    731      1.1   cgd nfs_quotactl(mp, cmd, uid, arg, p)
    732      1.1   cgd 	struct mount *mp;
    733      1.1   cgd 	int cmd;
    734      1.1   cgd 	uid_t uid;
    735      1.1   cgd 	caddr_t arg;
    736      1.1   cgd 	struct proc *p;
    737      1.1   cgd {
    738  1.1.1.2  fvdl 
    739      1.1   cgd 	return (EOPNOTSUPP);
    740      1.1   cgd }
    741