Home | History | Annotate | Line # | Download | only in nfs
nfs_vfsops.c revision 1.4.4.3
      1      1.1      cgd /*
      2      1.1      cgd  * Copyright (c) 1989 The Regents of the University of California.
      3      1.1      cgd  * 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.2      cgd  *	from: @(#)nfs_vfsops.c	7.31 (Berkeley) 5/6/91
     37  1.4.4.3      cgd  *	$Id: nfs_vfsops.c,v 1.4.4.3 1993/11/20 02:02:11 cgd Exp $
     38      1.1      cgd  */
     39      1.1      cgd 
     40  1.4.4.2  mycroft #include <sys/param.h>
     41  1.4.4.2  mycroft #include <sys/conf.h>
     42  1.4.4.2  mycroft #include <sys/ioctl.h>
     43  1.4.4.2  mycroft #include <sys/signal.h>
     44  1.4.4.2  mycroft #include <sys/proc.h>
     45  1.4.4.2  mycroft #include <sys/namei.h>
     46  1.4.4.2  mycroft #include <sys/vnode.h>
     47  1.4.4.2  mycroft #include <sys/mount.h>
     48  1.4.4.2  mycroft #include <sys/buf.h>
     49  1.4.4.2  mycroft #include <sys/mbuf.h>
     50  1.4.4.2  mycroft #include <sys/socket.h>
     51  1.4.4.2  mycroft #include <sys/systm.h>
     52      1.1      cgd 
     53  1.4.4.2  mycroft #include <net/if.h>
     54  1.4.4.2  mycroft #include <net/route.h>
     55  1.4.4.2  mycroft #include <netinet/in.h>
     56      1.1      cgd 
     57  1.4.4.2  mycroft #include <nfs/nfsv2.h>
     58  1.4.4.2  mycroft #include <nfs/nfsnode.h>
     59  1.4.4.2  mycroft #include <nfs/nfsmount.h>
     60  1.4.4.2  mycroft #include <nfs/nfs.h>
     61  1.4.4.2  mycroft #include <nfs/xdr_subs.h>
     62  1.4.4.2  mycroft #include <nfs/nfsm_subs.h>
     63  1.4.4.2  mycroft #include <nfs/nfsdiskless.h>
     64      1.1      cgd 
     65      1.1      cgd /*
     66      1.1      cgd  * nfs vfs operations.
     67      1.1      cgd  */
     68      1.1      cgd struct vfsops nfs_vfsops = {
     69      1.1      cgd 	nfs_mount,
     70      1.1      cgd 	nfs_start,
     71      1.1      cgd 	nfs_unmount,
     72      1.1      cgd 	nfs_root,
     73      1.1      cgd 	nfs_quotactl,
     74      1.1      cgd 	nfs_statfs,
     75      1.1      cgd 	nfs_sync,
     76      1.1      cgd 	nfs_fhtovp,
     77      1.1      cgd 	nfs_vptofh,
     78      1.1      cgd 	nfs_init,
     79      1.1      cgd };
     80      1.1      cgd 
     81      1.1      cgd static u_char nfs_mntid;
     82      1.1      cgd extern u_long nfs_procids[NFS_NPROCS];
     83      1.1      cgd extern u_long nfs_prog, nfs_vers;
     84      1.1      cgd struct nfs_diskless nfs_diskless;
     85      1.1      cgd void nfs_disconnect();
     86      1.1      cgd 
     87      1.1      cgd #define TRUE	1
     88      1.1      cgd #define	FALSE	0
     89      1.1      cgd 
     90      1.1      cgd /*
     91      1.1      cgd  * nfs statfs call
     92      1.1      cgd  */
     93      1.1      cgd nfs_statfs(mp, sbp, p)
     94      1.1      cgd 	struct mount *mp;
     95      1.1      cgd 	register struct statfs *sbp;
     96      1.1      cgd 	struct proc *p;
     97      1.1      cgd {
     98      1.1      cgd 	register struct vnode *vp;
     99      1.1      cgd 	register struct nfsv2_statfs *sfp;
    100      1.1      cgd 	register caddr_t cp;
    101      1.1      cgd 	register long t1;
    102      1.1      cgd 	caddr_t bpos, dpos, cp2;
    103      1.1      cgd 	u_long xid;
    104      1.1      cgd 	int error = 0;
    105      1.1      cgd 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
    106      1.1      cgd 	struct nfsmount *nmp;
    107      1.1      cgd 	struct ucred *cred;
    108      1.1      cgd 	struct nfsnode *np;
    109      1.1      cgd 
    110      1.1      cgd 	nmp = VFSTONFS(mp);
    111      1.1      cgd 	if (error = nfs_nget(mp, &nmp->nm_fh, &np))
    112      1.1      cgd 		return (error);
    113      1.1      cgd 	vp = NFSTOV(np);
    114      1.1      cgd 	nfsstats.rpccnt[NFSPROC_STATFS]++;
    115      1.1      cgd 	cred = crget();
    116      1.1      cgd 	cred->cr_ngroups = 1;
    117      1.1      cgd 	nfsm_reqhead(nfs_procids[NFSPROC_STATFS], cred, NFSX_FH);
    118      1.1      cgd 	nfsm_fhtom(vp);
    119      1.1      cgd 	nfsm_request(vp, NFSPROC_STATFS, p, 0);
    120      1.1      cgd 	nfsm_disect(sfp, struct nfsv2_statfs *, NFSX_STATFS);
    121      1.1      cgd 	sbp->f_type = MOUNT_NFS;
    122      1.1      cgd 	sbp->f_flags = nmp->nm_flag;
    123      1.1      cgd 	sbp->f_bsize = fxdr_unsigned(long, sfp->sf_tsize);
    124      1.1      cgd 	sbp->f_fsize = fxdr_unsigned(long, sfp->sf_bsize);
    125      1.1      cgd 	sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks);
    126      1.1      cgd 	sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree);
    127      1.1      cgd 	sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail);
    128      1.1      cgd 	sbp->f_files = 0;
    129      1.1      cgd 	sbp->f_ffree = 0;
    130      1.1      cgd 	if (sbp != &mp->mnt_stat) {
    131      1.1      cgd 		bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
    132      1.1      cgd 		bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
    133      1.1      cgd 	}
    134      1.1      cgd 	nfsm_reqdone;
    135      1.1      cgd 	nfs_nput(vp);
    136      1.1      cgd 	crfree(cred);
    137      1.1      cgd 	return (error);
    138      1.1      cgd }
    139      1.1      cgd 
    140      1.1      cgd /*
    141      1.1      cgd  * Mount a remote root fs via. nfs. This depends on the info in the
    142      1.1      cgd  * nfs_diskless structure that has been filled in properly by some primary
    143      1.1      cgd  * bootstrap.
    144      1.1      cgd  * It goes something like this:
    145      1.1      cgd  * - do enough of "ifconfig" by calling ifioctl() so that the system
    146      1.1      cgd  *   can talk to the server
    147      1.1      cgd  * - If nfs_diskless.mygateway is filled in, use that address as
    148      1.1      cgd  *   a default gateway.
    149      1.1      cgd  *   (This is done the 4.3 way with rtioctl() and should be changed)
    150      1.1      cgd  * - hand craft the swap nfs vnode hanging off a fake mount point
    151      1.1      cgd  * - build the rootfs mount point and call mountnfs() to do the rest.
    152      1.1      cgd  */
    153      1.1      cgd nfs_mountroot()
    154      1.1      cgd {
    155      1.1      cgd 	register struct mount *mp;
    156      1.1      cgd 	register struct mbuf *m;
    157      1.1      cgd 	struct socket *so;
    158      1.1      cgd 	struct vnode *vp;
    159      1.1      cgd 	int error;
    160      1.1      cgd 
    161      1.1      cgd 	/*
    162      1.1      cgd 	 * Do enough of ifconfig(8) so that critical net interface can
    163      1.1      cgd 	 * talk to the server.
    164      1.1      cgd 	 */
    165      1.1      cgd 	if (socreate(nfs_diskless.myif.ifra_addr.sa_family, &so, SOCK_DGRAM, 0))
    166      1.1      cgd 		panic("nfs ifconf");
    167      1.1      cgd 	if (ifioctl(so, SIOCAIFADDR, &nfs_diskless.myif))
    168      1.1      cgd 		panic("nfs ifconf2");
    169      1.1      cgd 	soclose(so);
    170      1.1      cgd 
    171      1.1      cgd 	/*
    172      1.1      cgd 	 * If the gateway field is filled in, set it as the default route.
    173      1.1      cgd 	 */
    174      1.1      cgd #ifdef COMPAT_43
    175      1.1      cgd 	if (nfs_diskless.mygateway.sa_family == AF_INET) {
    176      1.1      cgd 		struct ortentry rt;
    177      1.1      cgd 		struct sockaddr_in *sin;
    178      1.1      cgd 
    179      1.1      cgd 		sin = (struct sockaddr_in *) &rt.rt_dst;
    180      1.1      cgd 		sin->sin_len = sizeof (struct sockaddr_in);
    181      1.1      cgd 		sin->sin_family = AF_INET;
    182      1.1      cgd 		sin->sin_addr.s_addr = 0;	/* default */
    183      1.1      cgd 		bcopy((caddr_t)&nfs_diskless.mygateway, (caddr_t)&rt.rt_gateway,
    184      1.1      cgd 			sizeof (struct sockaddr_in));
    185      1.1      cgd 		rt.rt_flags = (RTF_UP | RTF_GATEWAY);
    186      1.3      cgd 		if (rtioctl(SIOCADDRT, (caddr_t)&rt, curproc))
    187      1.1      cgd 			panic("nfs root route");
    188      1.1      cgd 	}
    189      1.1      cgd #endif	/* COMPAT_43 */
    190      1.1      cgd 
    191      1.1      cgd 	/*
    192      1.1      cgd 	 * If swapping to an nfs node (indicated by swdevt[0].sw_dev == NODEV):
    193      1.1      cgd 	 * Create a fake mount point just for the swap vnode so that the
    194      1.1      cgd 	 * swap file can be on a different server from the rootfs.
    195      1.1      cgd 	 */
    196      1.1      cgd 	if (swdevt[0].sw_dev == NODEV) {
    197      1.1      cgd 		mp = (struct mount *)malloc((u_long)sizeof(struct mount),
    198      1.1      cgd 			M_MOUNT, M_NOWAIT);
    199      1.1      cgd 		if (mp == NULL)
    200      1.1      cgd 			panic("nfs root mount");
    201      1.1      cgd 		mp->mnt_op = &nfs_vfsops;
    202      1.1      cgd 		mp->mnt_flag = 0;
    203      1.1      cgd 		mp->mnt_exroot = 0;
    204      1.1      cgd 		mp->mnt_mounth = NULLVP;
    205      1.1      cgd 
    206      1.1      cgd 		/*
    207      1.1      cgd 		 * Set up the diskless nfs_args for the swap mount point
    208      1.1      cgd 		 * and then call mountnfs() to mount it.
    209      1.1      cgd 		 * Since the swap file is not the root dir of a file system,
    210      1.1      cgd 		 * hack it to a regular file.
    211      1.1      cgd 		 */
    212      1.1      cgd 		nfs_diskless.swap_args.fh = (nfsv2fh_t *)nfs_diskless.swap_fh;
    213      1.1      cgd 		MGET(m, MT_SONAME, M_DONTWAIT);
    214      1.1      cgd 		if (m == NULL)
    215      1.1      cgd 			panic("nfs root mbuf");
    216      1.1      cgd 		bcopy((caddr_t)&nfs_diskless.swap_saddr, mtod(m, caddr_t),
    217      1.1      cgd 			nfs_diskless.swap_saddr.sa_len);
    218      1.1      cgd 		m->m_len = nfs_diskless.swap_saddr.sa_len;
    219      1.1      cgd 		if (mountnfs(&nfs_diskless.swap_args, mp, m, "/swap",
    220      1.1      cgd 			nfs_diskless.swap_hostnam, &vp))
    221      1.1      cgd 			panic("nfs swap");
    222      1.1      cgd 		vp->v_type = VREG;
    223      1.1      cgd 		vp->v_flag = 0;
    224      1.1      cgd 		swapdev_vp = vp;
    225      1.1      cgd 		VREF(vp);
    226      1.1      cgd 		swdevt[0].sw_vp = vp;
    227      1.3      cgd 		{
    228      1.3      cgd 			struct vattr attr;
    229      1.3      cgd 
    230      1.4      cgd 			if (nfs_dogetattr(vp,&attr,NOCRED,0,0)) {
    231      1.3      cgd 			    panic("nfs swap");
    232      1.3      cgd 			}
    233      1.3      cgd 			swdevt[0].sw_nblks = attr.va_size / DEV_BSIZE;
    234      1.3      cgd 		}
    235      1.1      cgd 	}
    236      1.1      cgd 
    237      1.1      cgd 	/*
    238      1.1      cgd 	 * Create the rootfs mount point.
    239      1.1      cgd 	 */
    240      1.1      cgd 	mp = (struct mount *)malloc((u_long)sizeof(struct mount),
    241      1.1      cgd 		M_MOUNT, M_NOWAIT);
    242      1.1      cgd 	if (mp == NULL)
    243      1.1      cgd 		panic("nfs root mount2");
    244      1.1      cgd 	mp->mnt_op = &nfs_vfsops;
    245      1.1      cgd 	mp->mnt_flag = MNT_RDONLY;
    246      1.1      cgd 	mp->mnt_exroot = 0;
    247      1.1      cgd 	mp->mnt_mounth = NULLVP;
    248      1.1      cgd 
    249      1.1      cgd 	/*
    250      1.1      cgd 	 * Set up the root fs args and call mountnfs() to do the rest.
    251      1.1      cgd 	 */
    252      1.1      cgd 	nfs_diskless.root_args.fh = (nfsv2fh_t *)nfs_diskless.root_fh;
    253      1.1      cgd 	MGET(m, MT_SONAME, M_DONTWAIT);
    254      1.1      cgd 	if (m == NULL)
    255      1.1      cgd 		panic("nfs root mbuf2");
    256      1.1      cgd 	bcopy((caddr_t)&nfs_diskless.root_saddr, mtod(m, caddr_t),
    257      1.1      cgd 		nfs_diskless.root_saddr.sa_len);
    258      1.1      cgd 	m->m_len = nfs_diskless.root_saddr.sa_len;
    259      1.1      cgd 	if (mountnfs(&nfs_diskless.root_args, mp, m, "/",
    260      1.1      cgd 		nfs_diskless.root_hostnam, &vp))
    261      1.1      cgd 		panic("nfs root");
    262      1.1      cgd 	if (vfs_lock(mp))
    263      1.1      cgd 		panic("nfs root2");
    264      1.1      cgd 	rootfs = mp;
    265      1.1      cgd 	mp->mnt_next = mp;
    266      1.1      cgd 	mp->mnt_prev = mp;
    267      1.1      cgd 	mp->mnt_vnodecovered = NULLVP;
    268      1.1      cgd 	vfs_unlock(mp);
    269      1.1      cgd 	rootvp = vp;
    270      1.1      cgd 	inittodr((time_t)0);	/* There is no time in the nfs fsstat so ?? */
    271      1.1      cgd 	return (0);
    272      1.1      cgd }
    273      1.1      cgd 
    274      1.1      cgd /*
    275      1.1      cgd  * VFS Operations.
    276      1.1      cgd  *
    277      1.1      cgd  * mount system call
    278      1.1      cgd  * It seems a bit dumb to copyinstr() the host and path here and then
    279      1.1      cgd  * bcopy() them in mountnfs(), but I wanted to detect errors before
    280      1.1      cgd  * doing the sockargs() call because sockargs() allocates an mbuf and
    281      1.1      cgd  * an error after that means that I have to release the mbuf.
    282      1.1      cgd  */
    283      1.1      cgd /* ARGSUSED */
    284      1.1      cgd nfs_mount(mp, path, data, ndp, p)
    285      1.1      cgd 	struct mount *mp;
    286      1.1      cgd 	char *path;
    287      1.1      cgd 	caddr_t data;
    288      1.1      cgd 	struct nameidata *ndp;
    289      1.1      cgd 	struct proc *p;
    290      1.1      cgd {
    291      1.1      cgd 	int error;
    292      1.1      cgd 	struct nfs_args args;
    293      1.1      cgd 	struct mbuf *nam;
    294      1.1      cgd 	struct vnode *vp;
    295      1.1      cgd 	char pth[MNAMELEN], hst[MNAMELEN];
    296      1.1      cgd 	u_int len;
    297      1.1      cgd 	nfsv2fh_t nfh;
    298      1.1      cgd 
    299      1.1      cgd 	if (mp->mnt_flag & MNT_UPDATE)
    300      1.1      cgd 		return (0);
    301      1.1      cgd 	if (error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args)))
    302      1.1      cgd 		return (error);
    303      1.1      cgd 	if (error = copyin((caddr_t)args.fh, (caddr_t)&nfh, sizeof (nfsv2fh_t)))
    304      1.1      cgd 		return (error);
    305      1.1      cgd 	if (error = copyinstr(path, pth, MNAMELEN-1, &len))
    306      1.1      cgd 		return (error);
    307      1.1      cgd 	bzero(&pth[len], MNAMELEN - len);
    308      1.1      cgd 	if (error = copyinstr(args.hostname, hst, MNAMELEN-1, &len))
    309      1.1      cgd 		return (error);
    310      1.1      cgd 	bzero(&hst[len], MNAMELEN - len);
    311      1.1      cgd 	/* sockargs() call must be after above copyin() calls */
    312      1.1      cgd 	if (error = sockargs(&nam, (caddr_t)args.addr,
    313      1.1      cgd 		sizeof (struct sockaddr), MT_SONAME))
    314      1.1      cgd 		return (error);
    315      1.1      cgd 	args.fh = &nfh;
    316      1.1      cgd 	error = mountnfs(&args, mp, nam, pth, hst, &vp);
    317      1.1      cgd 	return (error);
    318      1.1      cgd }
    319      1.1      cgd 
    320      1.1      cgd /*
    321      1.1      cgd  * Common code for mount and mountroot
    322      1.1      cgd  */
    323      1.1      cgd mountnfs(argp, mp, nam, pth, hst, vpp)
    324      1.1      cgd 	register struct nfs_args *argp;
    325      1.1      cgd 	register struct mount *mp;
    326      1.1      cgd 	struct mbuf *nam;
    327      1.1      cgd 	char *pth, *hst;
    328      1.1      cgd 	struct vnode **vpp;
    329      1.1      cgd {
    330      1.1      cgd 	register struct nfsmount *nmp;
    331      1.1      cgd 	struct proc *p = curproc;		/* XXX */
    332      1.1      cgd 	struct nfsnode *np;
    333      1.1      cgd 	int error;
    334      1.1      cgd 	fsid_t tfsid;
    335      1.1      cgd 
    336      1.1      cgd 	MALLOC(nmp, struct nfsmount *, sizeof *nmp, M_NFSMNT, M_WAITOK);
    337      1.1      cgd 	bzero((caddr_t)nmp, sizeof *nmp);
    338      1.1      cgd 	mp->mnt_data = (qaddr_t)nmp;
    339  1.4.4.3      cgd 
    340  1.4.4.3      cgd 	getnewfsid(mp, MOUNT_NFS);
    341      1.1      cgd 	nmp->nm_mountp = mp;
    342      1.1      cgd 	nmp->nm_flag = argp->flags;
    343      1.1      cgd 	nmp->nm_rto = NFS_TIMEO;
    344      1.1      cgd 	nmp->nm_rtt = -1;
    345      1.1      cgd 	nmp->nm_rttvar = nmp->nm_rto << 1;
    346      1.1      cgd 	nmp->nm_retry = NFS_RETRANS;
    347      1.1      cgd 	nmp->nm_wsize = NFS_WSIZE;
    348      1.1      cgd 	nmp->nm_rsize = NFS_RSIZE;
    349      1.1      cgd 	bcopy((caddr_t)argp->fh, (caddr_t)&nmp->nm_fh, sizeof(nfsv2fh_t));
    350      1.1      cgd 	bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
    351      1.1      cgd 	bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN);
    352      1.1      cgd 	nmp->nm_nam = nam;
    353      1.1      cgd 
    354      1.1      cgd 	if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
    355      1.1      cgd 		nmp->nm_rto = argp->timeo;
    356      1.1      cgd 		/* NFS timeouts are specified in 1/10 sec. */
    357      1.1      cgd 		nmp->nm_rto = (nmp->nm_rto * 10) / NFS_HZ;
    358      1.1      cgd 		if (nmp->nm_rto < NFS_MINTIMEO)
    359      1.1      cgd 			nmp->nm_rto = NFS_MINTIMEO;
    360      1.1      cgd 		else if (nmp->nm_rto > NFS_MAXTIMEO)
    361      1.1      cgd 			nmp->nm_rto = NFS_MAXTIMEO;
    362      1.1      cgd 		nmp->nm_rttvar = nmp->nm_rto << 1;
    363      1.1      cgd 	}
    364      1.1      cgd 
    365      1.1      cgd 	if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
    366      1.1      cgd 		nmp->nm_retry = argp->retrans;
    367      1.1      cgd 		if (nmp->nm_retry > NFS_MAXREXMIT)
    368      1.1      cgd 			nmp->nm_retry = NFS_MAXREXMIT;
    369      1.1      cgd 	}
    370      1.1      cgd 
    371      1.1      cgd 	if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
    372      1.1      cgd 		nmp->nm_wsize = argp->wsize;
    373      1.1      cgd 		/* Round down to multiple of blocksize */
    374      1.1      cgd 		nmp->nm_wsize &= ~0x1ff;
    375      1.1      cgd 		if (nmp->nm_wsize <= 0)
    376      1.1      cgd 			nmp->nm_wsize = 512;
    377      1.1      cgd 		else if (nmp->nm_wsize > NFS_MAXDATA)
    378      1.1      cgd 			nmp->nm_wsize = NFS_MAXDATA;
    379      1.1      cgd 	}
    380      1.1      cgd 	if (nmp->nm_wsize > MAXBSIZE)
    381      1.1      cgd 		nmp->nm_wsize = MAXBSIZE;
    382      1.1      cgd 
    383      1.1      cgd 	if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
    384      1.1      cgd 		nmp->nm_rsize = argp->rsize;
    385      1.1      cgd 		/* Round down to multiple of blocksize */
    386      1.1      cgd 		nmp->nm_rsize &= ~0x1ff;
    387      1.1      cgd 		if (nmp->nm_rsize <= 0)
    388      1.1      cgd 			nmp->nm_rsize = 512;
    389      1.1      cgd 		else if (nmp->nm_rsize > NFS_MAXDATA)
    390      1.1      cgd 			nmp->nm_rsize = NFS_MAXDATA;
    391      1.1      cgd 	}
    392      1.1      cgd 	if (nmp->nm_rsize > MAXBSIZE)
    393      1.1      cgd 		nmp->nm_rsize = MAXBSIZE;
    394      1.1      cgd 	/* Set up the sockets and per-host congestion */
    395      1.1      cgd 	nmp->nm_sotype = argp->sotype;
    396      1.1      cgd 	nmp->nm_soproto = argp->proto;
    397      1.1      cgd 	if (error = nfs_connect(nmp))
    398      1.1      cgd 		goto bad;
    399      1.1      cgd 
    400      1.1      cgd 	if (error = nfs_statfs(mp, &mp->mnt_stat, p))
    401      1.1      cgd 		goto bad;
    402      1.1      cgd 	/*
    403      1.1      cgd 	 * A reference count is needed on the nfsnode representing the
    404      1.1      cgd 	 * remote root.  If this object is not persistent, then backward
    405      1.1      cgd 	 * traversals of the mount point (i.e. "..") will not work if
    406      1.1      cgd 	 * the nfsnode gets flushed out of the cache. Ufs does not have
    407      1.1      cgd 	 * this problem, because one can identify root inodes by their
    408      1.1      cgd 	 * number == ROOTINO (2).
    409      1.1      cgd 	 */
    410      1.1      cgd 	if (error = nfs_nget(mp, &nmp->nm_fh, &np))
    411      1.1      cgd 		goto bad;
    412      1.1      cgd 	/*
    413      1.1      cgd 	 * Unlock it, but keep the reference count.
    414      1.1      cgd 	 */
    415      1.1      cgd 	nfs_unlock(NFSTOV(np));
    416      1.1      cgd 	*vpp = NFSTOV(np);
    417      1.1      cgd 
    418      1.1      cgd 	return (0);
    419      1.1      cgd bad:
    420      1.1      cgd 	nfs_disconnect(nmp);
    421      1.1      cgd 	FREE(nmp, M_NFSMNT);
    422      1.1      cgd 	m_freem(nam);
    423      1.1      cgd 	return (error);
    424      1.1      cgd }
    425      1.1      cgd 
    426      1.1      cgd /*
    427      1.1      cgd  * unmount system call
    428      1.1      cgd  */
    429      1.1      cgd nfs_unmount(mp, mntflags, p)
    430      1.1      cgd 	struct mount *mp;
    431      1.1      cgd 	int mntflags;
    432      1.1      cgd 	struct proc *p;
    433      1.1      cgd {
    434      1.1      cgd 	register struct nfsmount *nmp;
    435      1.1      cgd 	struct nfsnode *np;
    436      1.1      cgd 	struct vnode *vp;
    437      1.1      cgd 	int error, flags = 0;
    438      1.1      cgd 	extern int doforce;
    439      1.1      cgd 
    440      1.1      cgd 	if (mntflags & MNT_FORCE) {
    441      1.1      cgd 		if (!doforce || mp == rootfs)
    442      1.1      cgd 			return (EINVAL);
    443      1.1      cgd 		flags |= FORCECLOSE;
    444      1.1      cgd 	}
    445      1.1      cgd 	nmp = VFSTONFS(mp);
    446      1.1      cgd 	/*
    447      1.1      cgd 	 * Clear out the buffer cache
    448      1.1      cgd 	 */
    449      1.1      cgd 	mntflushbuf(mp, 0);
    450      1.1      cgd 	if (mntinvalbuf(mp))
    451      1.1      cgd 		return (EBUSY);
    452      1.1      cgd 	/*
    453      1.1      cgd 	 * Goes something like this..
    454      1.1      cgd 	 * - Check for activity on the root vnode (other than ourselves).
    455      1.1      cgd 	 * - Call vflush() to clear out vnodes for this file system,
    456      1.1      cgd 	 *   except for the root vnode.
    457      1.1      cgd 	 * - Decrement reference on the vnode representing remote root.
    458      1.1      cgd 	 * - Close the socket
    459      1.1      cgd 	 * - Free up the data structures
    460      1.1      cgd 	 */
    461      1.1      cgd 	/*
    462      1.1      cgd 	 * We need to decrement the ref. count on the nfsnode representing
    463      1.1      cgd 	 * the remote root.  See comment in mountnfs().  The VFS unmount()
    464      1.1      cgd 	 * has done vput on this vnode, otherwise we would get deadlock!
    465      1.1      cgd 	 */
    466      1.1      cgd 	if (error = nfs_nget(mp, &nmp->nm_fh, &np))
    467      1.1      cgd 		return(error);
    468      1.1      cgd 	vp = NFSTOV(np);
    469      1.1      cgd 	if (vp->v_usecount > 2) {
    470      1.1      cgd 		vput(vp);
    471      1.1      cgd 		return (EBUSY);
    472      1.1      cgd 	}
    473      1.1      cgd 	if (error = vflush(mp, vp, flags)) {
    474      1.1      cgd 		vput(vp);
    475      1.1      cgd 		return (error);
    476      1.1      cgd 	}
    477      1.1      cgd 	/*
    478      1.1      cgd 	 * Get rid of two reference counts, and unlock it on the second.
    479      1.1      cgd 	 */
    480      1.1      cgd 	vrele(vp);
    481      1.1      cgd 	vput(vp);
    482      1.1      cgd 	nfs_disconnect(nmp);
    483      1.1      cgd 	m_freem(nmp->nm_nam);
    484      1.1      cgd 	free((caddr_t)nmp, M_NFSMNT);
    485      1.1      cgd 	return (0);
    486      1.1      cgd }
    487      1.1      cgd 
    488      1.1      cgd /*
    489      1.1      cgd  * Return root of a filesystem
    490      1.1      cgd  */
    491      1.1      cgd nfs_root(mp, vpp)
    492      1.1      cgd 	struct mount *mp;
    493      1.1      cgd 	struct vnode **vpp;
    494      1.1      cgd {
    495      1.1      cgd 	register struct vnode *vp;
    496      1.1      cgd 	struct nfsmount *nmp;
    497      1.1      cgd 	struct nfsnode *np;
    498      1.1      cgd 	int error;
    499      1.1      cgd 
    500      1.1      cgd 	nmp = VFSTONFS(mp);
    501      1.1      cgd 	if (error = nfs_nget(mp, &nmp->nm_fh, &np))
    502      1.1      cgd 		return (error);
    503      1.1      cgd 	vp = NFSTOV(np);
    504      1.1      cgd 	vp->v_type = VDIR;
    505      1.1      cgd 	vp->v_flag = VROOT;
    506      1.1      cgd 	*vpp = vp;
    507      1.1      cgd 	return (0);
    508      1.1      cgd }
    509      1.1      cgd 
    510      1.1      cgd extern int syncprt;
    511      1.1      cgd 
    512      1.1      cgd /*
    513      1.1      cgd  * Flush out the buffer cache
    514      1.1      cgd  */
    515      1.1      cgd /* ARGSUSED */
    516      1.1      cgd nfs_sync(mp, waitfor)
    517      1.1      cgd 	struct mount *mp;
    518      1.1      cgd 	int waitfor;
    519      1.1      cgd {
    520      1.1      cgd 	if (syncprt)
    521      1.1      cgd 		bufstats();
    522      1.1      cgd 	/*
    523      1.1      cgd 	 * Force stale buffer cache information to be flushed.
    524      1.1      cgd 	 */
    525      1.1      cgd 	mntflushbuf(mp, waitfor == MNT_WAIT ? B_SYNC : 0);
    526      1.1      cgd 	return (0);
    527      1.1      cgd }
    528      1.1      cgd 
    529      1.1      cgd /*
    530      1.1      cgd  * At this point, this should never happen
    531      1.1      cgd  */
    532      1.1      cgd /* ARGSUSED */
    533      1.1      cgd nfs_fhtovp(mp, fhp, vpp)
    534      1.1      cgd 	struct mount *mp;
    535      1.1      cgd 	struct fid *fhp;
    536      1.1      cgd 	struct vnode **vpp;
    537      1.1      cgd {
    538      1.1      cgd 
    539      1.1      cgd 	return (EINVAL);
    540      1.1      cgd }
    541      1.1      cgd 
    542      1.1      cgd /*
    543      1.1      cgd  * Vnode pointer to File handle, should never happen either
    544      1.1      cgd  */
    545      1.1      cgd /* ARGSUSED */
    546      1.1      cgd nfs_vptofh(vp, fhp)
    547      1.1      cgd 	struct vnode *vp;
    548      1.1      cgd 	struct fid *fhp;
    549      1.1      cgd {
    550      1.1      cgd 
    551      1.1      cgd 	return (EINVAL);
    552      1.1      cgd }
    553      1.1      cgd 
    554      1.1      cgd /*
    555      1.1      cgd  * Vfs start routine, a no-op.
    556      1.1      cgd  */
    557      1.1      cgd /* ARGSUSED */
    558      1.1      cgd nfs_start(mp, flags, p)
    559      1.1      cgd 	struct mount *mp;
    560      1.1      cgd 	int flags;
    561      1.1      cgd 	struct proc *p;
    562      1.1      cgd {
    563      1.1      cgd 
    564      1.1      cgd 	return (0);
    565      1.1      cgd }
    566      1.1      cgd 
    567      1.1      cgd /*
    568      1.1      cgd  * Do operations associated with quotas, not supported
    569      1.1      cgd  */
    570      1.1      cgd nfs_quotactl(mp, cmd, uid, arg, p)
    571      1.1      cgd 	struct mount *mp;
    572      1.1      cgd 	int cmd;
    573  1.4.4.1  mycroft 	int uid;
    574      1.1      cgd 	caddr_t arg;
    575      1.1      cgd 	struct proc *p;
    576      1.1      cgd {
    577      1.1      cgd #ifdef lint
    578      1.1      cgd 	mp = mp; cmd = cmd; uid = uid; arg = arg;
    579      1.1      cgd #endif /* lint */
    580      1.1      cgd 	return (EOPNOTSUPP);
    581      1.1      cgd }
    582