Home | History | Annotate | Line # | Download | only in client
nfs_clvfsops.c revision 1.1.1.2
      1 /*	$NetBSD: nfs_clvfsops.c,v 1.1.1.2 2016/11/18 07:49:11 pgoyette Exp $	*/
      2 /*-
      3  * Copyright (c) 1989, 1993, 1995
      4  *	The Regents of the University of California.  All rights reserved.
      5  *
      6  * This code is derived from software contributed to Berkeley by
      7  * Rick Macklem at The University of Guelph.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  * 4. Neither the name of the University nor the names of its contributors
     18  *    may be used to endorse or promote products derived from this software
     19  *    without specific prior written permission.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     31  * SUCH DAMAGE.
     32  *
     33  *	from nfs_vfsops.c	8.12 (Berkeley) 5/20/95
     34  */
     35 
     36 #include <sys/cdefs.h>
     37 /* __FBSDID("FreeBSD: head/sys/fs/nfsclient/nfs_clvfsops.c 304026 2016-08-12 22:44:59Z rmacklem "); */
     38 __RCSID("$NetBSD: nfs_clvfsops.c,v 1.1.1.2 2016/11/18 07:49:11 pgoyette Exp $");
     39 
     40 
     41 #include "opt_bootp.h"
     42 #include "opt_nfsroot.h"
     43 
     44 #include <sys/param.h>
     45 #include <sys/systm.h>
     46 #include <sys/kernel.h>
     47 #include <sys/bio.h>
     48 #include <sys/buf.h>
     49 #include <sys/clock.h>
     50 #include <sys/jail.h>
     51 #include <sys/limits.h>
     52 #include <sys/lock.h>
     53 #include <sys/malloc.h>
     54 #include <sys/mbuf.h>
     55 #include <sys/module.h>
     56 #include <sys/mount.h>
     57 #include <sys/proc.h>
     58 #include <sys/socket.h>
     59 #include <sys/socketvar.h>
     60 #include <sys/sockio.h>
     61 #include <sys/sysctl.h>
     62 #include <sys/vnode.h>
     63 #include <sys/signalvar.h>
     64 
     65 #include <vm/vm.h>
     66 #include <vm/vm_extern.h>
     67 #include <vm/uma.h>
     68 
     69 #include <net/if.h>
     70 #include <net/route.h>
     71 #include <netinet/in.h>
     72 
     73 #include <fs/nfs/nfsport.h>
     74 #include <fs/nfsclient/nfsnode.h>
     75 #include <fs/nfsclient/nfsmount.h>
     76 #include <fs/nfsclient/nfs.h>
     77 #include <nfs/nfsdiskless.h>
     78 
     79 FEATURE(nfscl, "NFSv4 client");
     80 
     81 extern int nfscl_ticks;
     82 extern struct timeval nfsboottime;
     83 extern int nfsrv_useacl;
     84 extern int nfscl_debuglevel;
     85 extern enum nfsiod_state ncl_iodwant[NFS_MAXASYNCDAEMON];
     86 extern struct nfsmount *ncl_iodmount[NFS_MAXASYNCDAEMON];
     87 extern struct mtx ncl_iod_mutex;
     88 NFSCLSTATEMUTEX;
     89 
     90 MALLOC_DEFINE(M_NEWNFSREQ, "newnfsclient_req", "NFS request header");
     91 MALLOC_DEFINE(M_NEWNFSMNT, "newnfsmnt", "NFS mount struct");
     92 
     93 SYSCTL_DECL(_vfs_nfs);
     94 static int nfs_ip_paranoia = 1;
     95 SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW,
     96     &nfs_ip_paranoia, 0, "");
     97 static int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
     98 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_INITIAL_DELAY,
     99         downdelayinitial, CTLFLAG_RW, &nfs_tprintf_initial_delay, 0, "");
    100 /* how long between console messages "nfs server foo not responding" */
    101 static int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
    102 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_DELAY,
    103         downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0, "");
    104 #ifdef NFS_DEBUG
    105 int nfs_debug;
    106 SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0,
    107     "Toggle debug flag");
    108 #endif
    109 
    110 static int	nfs_mountroot(struct mount *);
    111 static void	nfs_sec_name(char *, int *);
    112 static void	nfs_decode_args(struct mount *mp, struct nfsmount *nmp,
    113 		    struct nfs_args *argp, const char *, struct ucred *,
    114 		    struct thread *);
    115 static int	mountnfs(struct nfs_args *, struct mount *,
    116 		    struct sockaddr *, char *, u_char *, int, u_char *, int,
    117 		    u_char *, int, struct vnode **, struct ucred *,
    118 		    struct thread *, int, int, int);
    119 static void	nfs_getnlminfo(struct vnode *, uint8_t *, size_t *,
    120 		    struct sockaddr_storage *, int *, off_t *,
    121 		    struct timeval *);
    122 static vfs_mount_t nfs_mount;
    123 static vfs_cmount_t nfs_cmount;
    124 static vfs_unmount_t nfs_unmount;
    125 static vfs_root_t nfs_root;
    126 static vfs_statfs_t nfs_statfs;
    127 static vfs_sync_t nfs_sync;
    128 static vfs_sysctl_t nfs_sysctl;
    129 static vfs_purge_t nfs_purge;
    130 
    131 /*
    132  * nfs vfs operations.
    133  */
    134 static struct vfsops nfs_vfsops = {
    135 	.vfs_init =		ncl_init,
    136 	.vfs_mount =		nfs_mount,
    137 	.vfs_cmount =		nfs_cmount,
    138 	.vfs_root =		nfs_root,
    139 	.vfs_statfs =		nfs_statfs,
    140 	.vfs_sync =		nfs_sync,
    141 	.vfs_uninit =		ncl_uninit,
    142 	.vfs_unmount =		nfs_unmount,
    143 	.vfs_sysctl =		nfs_sysctl,
    144 	.vfs_purge =		nfs_purge,
    145 };
    146 VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK | VFCF_SBDRY);
    147 
    148 /* So that loader and kldload(2) can find us, wherever we are.. */
    149 MODULE_VERSION(nfs, 1);
    150 MODULE_DEPEND(nfs, nfscommon, 1, 1, 1);
    151 MODULE_DEPEND(nfs, krpc, 1, 1, 1);
    152 MODULE_DEPEND(nfs, nfssvc, 1, 1, 1);
    153 MODULE_DEPEND(nfs, nfslock, 1, 1, 1);
    154 
    155 /*
    156  * This structure is now defined in sys/nfs/nfs_diskless.c so that it
    157  * can be shared by both NFS clients. It is declared here so that it
    158  * will be defined for kernels built without NFS_ROOT, although it
    159  * isn't used in that case.
    160  */
    161 #if !defined(NFS_ROOT)
    162 struct nfs_diskless	nfs_diskless = { { { 0 } } };
    163 struct nfsv3_diskless	nfsv3_diskless = { { { 0 } } };
    164 int			nfs_diskless_valid = 0;
    165 #endif
    166 
    167 SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
    168     &nfs_diskless_valid, 0,
    169     "Has the diskless struct been filled correctly");
    170 
    171 SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
    172     nfsv3_diskless.root_hostnam, 0, "Path to nfs root");
    173 
    174 SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
    175     &nfsv3_diskless.root_saddr, sizeof(nfsv3_diskless.root_saddr),
    176     "%Ssockaddr_in", "Diskless root nfs address");
    177 
    178 
    179 void		newnfsargs_ntoh(struct nfs_args *);
    180 static int	nfs_mountdiskless(char *,
    181 		    struct sockaddr_in *, struct nfs_args *,
    182 		    struct thread *, struct vnode **, struct mount *);
    183 static void	nfs_convert_diskless(void);
    184 static void	nfs_convert_oargs(struct nfs_args *args,
    185 		    struct onfs_args *oargs);
    186 
    187 int
    188 newnfs_iosize(struct nfsmount *nmp)
    189 {
    190 	int iosize, maxio;
    191 
    192 	/* First, set the upper limit for iosize */
    193 	if (nmp->nm_flag & NFSMNT_NFSV4) {
    194 		maxio = NFS_MAXBSIZE;
    195 	} else if (nmp->nm_flag & NFSMNT_NFSV3) {
    196 		if (nmp->nm_sotype == SOCK_DGRAM)
    197 			maxio = NFS_MAXDGRAMDATA;
    198 		else
    199 			maxio = NFS_MAXBSIZE;
    200 	} else {
    201 		maxio = NFS_V2MAXDATA;
    202 	}
    203 	if (nmp->nm_rsize > maxio || nmp->nm_rsize == 0)
    204 		nmp->nm_rsize = maxio;
    205 	if (nmp->nm_rsize > NFS_MAXBSIZE)
    206 		nmp->nm_rsize = NFS_MAXBSIZE;
    207 	if (nmp->nm_readdirsize > maxio || nmp->nm_readdirsize == 0)
    208 		nmp->nm_readdirsize = maxio;
    209 	if (nmp->nm_readdirsize > nmp->nm_rsize)
    210 		nmp->nm_readdirsize = nmp->nm_rsize;
    211 	if (nmp->nm_wsize > maxio || nmp->nm_wsize == 0)
    212 		nmp->nm_wsize = maxio;
    213 	if (nmp->nm_wsize > NFS_MAXBSIZE)
    214 		nmp->nm_wsize = NFS_MAXBSIZE;
    215 
    216 	/*
    217 	 * Calculate the size used for io buffers.  Use the larger
    218 	 * of the two sizes to minimise nfs requests but make sure
    219 	 * that it is at least one VM page to avoid wasting buffer
    220 	 * space.  It must also be at least NFS_DIRBLKSIZ, since
    221 	 * that is the buffer size used for directories.
    222 	 */
    223 	iosize = imax(nmp->nm_rsize, nmp->nm_wsize);
    224 	iosize = imax(iosize, PAGE_SIZE);
    225 	iosize = imax(iosize, NFS_DIRBLKSIZ);
    226 	nmp->nm_mountp->mnt_stat.f_iosize = iosize;
    227 	return (iosize);
    228 }
    229 
    230 static void
    231 nfs_convert_oargs(struct nfs_args *args, struct onfs_args *oargs)
    232 {
    233 
    234 	args->version = NFS_ARGSVERSION;
    235 	args->addr = oargs->addr;
    236 	args->addrlen = oargs->addrlen;
    237 	args->sotype = oargs->sotype;
    238 	args->proto = oargs->proto;
    239 	args->fh = oargs->fh;
    240 	args->fhsize = oargs->fhsize;
    241 	args->flags = oargs->flags;
    242 	args->wsize = oargs->wsize;
    243 	args->rsize = oargs->rsize;
    244 	args->readdirsize = oargs->readdirsize;
    245 	args->timeo = oargs->timeo;
    246 	args->retrans = oargs->retrans;
    247 	args->readahead = oargs->readahead;
    248 	args->hostname = oargs->hostname;
    249 }
    250 
    251 static void
    252 nfs_convert_diskless(void)
    253 {
    254 
    255 	bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
    256 		sizeof(struct ifaliasreq));
    257 	bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
    258 		sizeof(struct sockaddr_in));
    259 	nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
    260 	if (nfsv3_diskless.root_args.flags & NFSMNT_NFSV3) {
    261 		nfsv3_diskless.root_fhsize = NFSX_MYFH;
    262 		bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_MYFH);
    263 	} else {
    264 		nfsv3_diskless.root_fhsize = NFSX_V2FH;
    265 		bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
    266 	}
    267 	bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
    268 		sizeof(struct sockaddr_in));
    269 	bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN);
    270 	nfsv3_diskless.root_time = nfs_diskless.root_time;
    271 	bcopy(nfs_diskless.my_hostnam, nfsv3_diskless.my_hostnam,
    272 		MAXHOSTNAMELEN);
    273 	nfs_diskless_valid = 3;
    274 }
    275 
    276 /*
    277  * nfs statfs call
    278  */
    279 static int
    280 nfs_statfs(struct mount *mp, struct statfs *sbp)
    281 {
    282 	struct vnode *vp;
    283 	struct thread *td;
    284 	struct nfsmount *nmp = VFSTONFS(mp);
    285 	struct nfsvattr nfsva;
    286 	struct nfsfsinfo fs;
    287 	struct nfsstatfs sb;
    288 	int error = 0, attrflag, gotfsinfo = 0, ret;
    289 	struct nfsnode *np;
    290 
    291 	td = curthread;
    292 
    293 	error = vfs_busy(mp, MBF_NOWAIT);
    294 	if (error)
    295 		return (error);
    296 	error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
    297 	if (error) {
    298 		vfs_unbusy(mp);
    299 		return (error);
    300 	}
    301 	vp = NFSTOV(np);
    302 	mtx_lock(&nmp->nm_mtx);
    303 	if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
    304 		mtx_unlock(&nmp->nm_mtx);
    305 		error = nfsrpc_fsinfo(vp, &fs, td->td_ucred, td, &nfsva,
    306 		    &attrflag, NULL);
    307 		if (!error)
    308 			gotfsinfo = 1;
    309 	} else
    310 		mtx_unlock(&nmp->nm_mtx);
    311 	if (!error)
    312 		error = nfsrpc_statfs(vp, &sb, &fs, td->td_ucred, td, &nfsva,
    313 		    &attrflag, NULL);
    314 	if (error != 0)
    315 		NFSCL_DEBUG(2, "statfs=%d\n", error);
    316 	if (attrflag == 0) {
    317 		ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
    318 		    td->td_ucred, td, &nfsva, NULL, NULL);
    319 		if (ret) {
    320 			/*
    321 			 * Just set default values to get things going.
    322 			 */
    323 			NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
    324 			nfsva.na_vattr.va_type = VDIR;
    325 			nfsva.na_vattr.va_mode = 0777;
    326 			nfsva.na_vattr.va_nlink = 100;
    327 			nfsva.na_vattr.va_uid = (uid_t)0;
    328 			nfsva.na_vattr.va_gid = (gid_t)0;
    329 			nfsva.na_vattr.va_fileid = 2;
    330 			nfsva.na_vattr.va_gen = 1;
    331 			nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
    332 			nfsva.na_vattr.va_size = 512 * 1024;
    333 		}
    334 	}
    335 	(void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
    336 	if (!error) {
    337 	    mtx_lock(&nmp->nm_mtx);
    338 	    if (gotfsinfo || (nmp->nm_flag & NFSMNT_NFSV4))
    339 		nfscl_loadfsinfo(nmp, &fs);
    340 	    nfscl_loadsbinfo(nmp, &sb, sbp);
    341 	    sbp->f_iosize = newnfs_iosize(nmp);
    342 	    mtx_unlock(&nmp->nm_mtx);
    343 	    if (sbp != &mp->mnt_stat) {
    344 		bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
    345 		bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
    346 	    }
    347 	    strncpy(&sbp->f_fstypename[0], mp->mnt_vfc->vfc_name, MFSNAMELEN);
    348 	} else if (NFS_ISV4(vp)) {
    349 		error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
    350 	}
    351 	vput(vp);
    352 	vfs_unbusy(mp);
    353 	return (error);
    354 }
    355 
    356 /*
    357  * nfs version 3 fsinfo rpc call
    358  */
    359 int
    360 ncl_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred,
    361     struct thread *td)
    362 {
    363 	struct nfsfsinfo fs;
    364 	struct nfsvattr nfsva;
    365 	int error, attrflag;
    366 
    367 	error = nfsrpc_fsinfo(vp, &fs, cred, td, &nfsva, &attrflag, NULL);
    368 	if (!error) {
    369 		if (attrflag)
    370 			(void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0,
    371 			    1);
    372 		mtx_lock(&nmp->nm_mtx);
    373 		nfscl_loadfsinfo(nmp, &fs);
    374 		mtx_unlock(&nmp->nm_mtx);
    375 	}
    376 	return (error);
    377 }
    378 
    379 /*
    380  * Mount a remote root fs via. nfs. This depends on the info in the
    381  * nfs_diskless structure that has been filled in properly by some primary
    382  * bootstrap.
    383  * It goes something like this:
    384  * - do enough of "ifconfig" by calling ifioctl() so that the system
    385  *   can talk to the server
    386  * - If nfs_diskless.mygateway is filled in, use that address as
    387  *   a default gateway.
    388  * - build the rootfs mount point and call mountnfs() to do the rest.
    389  *
    390  * It is assumed to be safe to read, modify, and write the nfsv3_diskless
    391  * structure, as well as other global NFS client variables here, as
    392  * nfs_mountroot() will be called once in the boot before any other NFS
    393  * client activity occurs.
    394  */
    395 static int
    396 nfs_mountroot(struct mount *mp)
    397 {
    398 	struct thread *td = curthread;
    399 	struct nfsv3_diskless *nd = &nfsv3_diskless;
    400 	struct socket *so;
    401 	struct vnode *vp;
    402 	struct ifreq ir;
    403 	int error;
    404 	u_long l;
    405 	char buf[128];
    406 	char *cp;
    407 
    408 #if defined(BOOTP_NFSROOT) && defined(BOOTP)
    409 	bootpc_init();		/* use bootp to get nfs_diskless filled in */
    410 #elif defined(NFS_ROOT)
    411 	nfs_setup_diskless();
    412 #endif
    413 
    414 	if (nfs_diskless_valid == 0)
    415 		return (-1);
    416 	if (nfs_diskless_valid == 1)
    417 		nfs_convert_diskless();
    418 
    419 	/*
    420 	 * XXX splnet, so networks will receive...
    421 	 */
    422 	splnet();
    423 
    424 	/*
    425 	 * Do enough of ifconfig(8) so that the critical net interface can
    426 	 * talk to the server.
    427 	 */
    428 	error = socreate(nd->myif.ifra_addr.sa_family, &so, nd->root_args.sotype, 0,
    429 	    td->td_ucred, td);
    430 	if (error)
    431 		panic("nfs_mountroot: socreate(%04x): %d",
    432 			nd->myif.ifra_addr.sa_family, error);
    433 
    434 #if 0 /* XXX Bad idea */
    435 	/*
    436 	 * We might not have been told the right interface, so we pass
    437 	 * over the first ten interfaces of the same kind, until we get
    438 	 * one of them configured.
    439 	 */
    440 
    441 	for (i = strlen(nd->myif.ifra_name) - 1;
    442 		nd->myif.ifra_name[i] >= '0' &&
    443 		nd->myif.ifra_name[i] <= '9';
    444 		nd->myif.ifra_name[i] ++) {
    445 		error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
    446 		if(!error)
    447 			break;
    448 	}
    449 #endif
    450 	error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
    451 	if (error)
    452 		panic("nfs_mountroot: SIOCAIFADDR: %d", error);
    453 	if ((cp = kern_getenv("boot.netif.mtu")) != NULL) {
    454 		ir.ifr_mtu = strtol(cp, NULL, 10);
    455 		bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ);
    456 		freeenv(cp);
    457 		error = ifioctl(so, SIOCSIFMTU, (caddr_t)&ir, td);
    458 		if (error)
    459 			printf("nfs_mountroot: SIOCSIFMTU: %d", error);
    460 	}
    461 	soclose(so);
    462 
    463 	/*
    464 	 * If the gateway field is filled in, set it as the default route.
    465 	 * Note that pxeboot will set a default route of 0 if the route
    466 	 * is not set by the DHCP server.  Check also for a value of 0
    467 	 * to avoid panicking inappropriately in that situation.
    468 	 */
    469 	if (nd->mygateway.sin_len != 0 &&
    470 	    nd->mygateway.sin_addr.s_addr != 0) {
    471 		struct sockaddr_in mask, sin;
    472 
    473 		bzero((caddr_t)&mask, sizeof(mask));
    474 		sin = mask;
    475 		sin.sin_family = AF_INET;
    476 		sin.sin_len = sizeof(sin);
    477                 /* XXX MRT use table 0 for this sort of thing */
    478 		CURVNET_SET(TD_TO_VNET(td));
    479 		error = rtrequest_fib(RTM_ADD, (struct sockaddr *)&sin,
    480 		    (struct sockaddr *)&nd->mygateway,
    481 		    (struct sockaddr *)&mask,
    482 		    RTF_UP | RTF_GATEWAY, NULL, RT_DEFAULT_FIB);
    483 		CURVNET_RESTORE();
    484 		if (error)
    485 			panic("nfs_mountroot: RTM_ADD: %d", error);
    486 	}
    487 
    488 	/*
    489 	 * Create the rootfs mount point.
    490 	 */
    491 	nd->root_args.fh = nd->root_fh;
    492 	nd->root_args.fhsize = nd->root_fhsize;
    493 	l = ntohl(nd->root_saddr.sin_addr.s_addr);
    494 	snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
    495 		(l >> 24) & 0xff, (l >> 16) & 0xff,
    496 		(l >>  8) & 0xff, (l >>  0) & 0xff, nd->root_hostnam);
    497 	printf("NFS ROOT: %s\n", buf);
    498 	nd->root_args.hostname = buf;
    499 	if ((error = nfs_mountdiskless(buf,
    500 	    &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) {
    501 		return (error);
    502 	}
    503 
    504 	/*
    505 	 * This is not really an nfs issue, but it is much easier to
    506 	 * set hostname here and then let the "/etc/rc.xxx" files
    507 	 * mount the right /var based upon its preset value.
    508 	 */
    509 	mtx_lock(&prison0.pr_mtx);
    510 	strlcpy(prison0.pr_hostname, nd->my_hostnam,
    511 	    sizeof(prison0.pr_hostname));
    512 	mtx_unlock(&prison0.pr_mtx);
    513 	inittodr(ntohl(nd->root_time));
    514 	return (0);
    515 }
    516 
    517 /*
    518  * Internal version of mount system call for diskless setup.
    519  */
    520 static int
    521 nfs_mountdiskless(char *path,
    522     struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
    523     struct vnode **vpp, struct mount *mp)
    524 {
    525 	struct sockaddr *nam;
    526 	int dirlen, error;
    527 	char *dirpath;
    528 
    529 	/*
    530 	 * Find the directory path in "path", which also has the server's
    531 	 * name/ip address in it.
    532 	 */
    533 	dirpath = strchr(path, ':');
    534 	if (dirpath != NULL)
    535 		dirlen = strlen(++dirpath);
    536 	else
    537 		dirlen = 0;
    538 	nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
    539 	if ((error = mountnfs(args, mp, nam, path, NULL, 0, dirpath, dirlen,
    540 	    NULL, 0, vpp, td->td_ucred, td, NFS_DEFAULT_NAMETIMEO,
    541 	    NFS_DEFAULT_NEGNAMETIMEO, 0)) != 0) {
    542 		printf("nfs_mountroot: mount %s on /: %d\n", path, error);
    543 		return (error);
    544 	}
    545 	return (0);
    546 }
    547 
    548 static void
    549 nfs_sec_name(char *sec, int *flagsp)
    550 {
    551 	if (!strcmp(sec, "krb5"))
    552 		*flagsp |= NFSMNT_KERB;
    553 	else if (!strcmp(sec, "krb5i"))
    554 		*flagsp |= (NFSMNT_KERB | NFSMNT_INTEGRITY);
    555 	else if (!strcmp(sec, "krb5p"))
    556 		*flagsp |= (NFSMNT_KERB | NFSMNT_PRIVACY);
    557 }
    558 
    559 static void
    560 nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
    561     const char *hostname, struct ucred *cred, struct thread *td)
    562 {
    563 	int s;
    564 	int adjsock;
    565 	char *p;
    566 
    567 	s = splnet();
    568 
    569 	/*
    570 	 * Set read-only flag if requested; otherwise, clear it if this is
    571 	 * an update.  If this is not an update, then either the read-only
    572 	 * flag is already clear, or this is a root mount and it was set
    573 	 * intentionally at some previous point.
    574 	 */
    575 	if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) {
    576 		MNT_ILOCK(mp);
    577 		mp->mnt_flag |= MNT_RDONLY;
    578 		MNT_IUNLOCK(mp);
    579 	} else if (mp->mnt_flag & MNT_UPDATE) {
    580 		MNT_ILOCK(mp);
    581 		mp->mnt_flag &= ~MNT_RDONLY;
    582 		MNT_IUNLOCK(mp);
    583 	}
    584 
    585 	/*
    586 	 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
    587 	 * no sense in that context.  Also, set up appropriate retransmit
    588 	 * and soft timeout behavior.
    589 	 */
    590 	if (argp->sotype == SOCK_STREAM) {
    591 		nmp->nm_flag &= ~NFSMNT_NOCONN;
    592 		nmp->nm_timeo = NFS_MAXTIMEO;
    593 		if ((argp->flags & NFSMNT_NFSV4) != 0)
    594 			nmp->nm_retry = INT_MAX;
    595 		else
    596 			nmp->nm_retry = NFS_RETRANS_TCP;
    597 	}
    598 
    599 	/* Also clear RDIRPLUS if NFSv2, it crashes some servers */
    600 	if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
    601 		argp->flags &= ~NFSMNT_RDIRPLUS;
    602 		nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
    603 	}
    604 
    605 	/* Re-bind if rsrvd port requested and wasn't on one */
    606 	adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
    607 		  && (argp->flags & NFSMNT_RESVPORT);
    608 	/* Also re-bind if we're switching to/from a connected UDP socket */
    609 	adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
    610 		    (argp->flags & NFSMNT_NOCONN));
    611 
    612 	/* Update flags atomically.  Don't change the lock bits. */
    613 	nmp->nm_flag = argp->flags | nmp->nm_flag;
    614 	splx(s);
    615 
    616 	if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
    617 		nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
    618 		if (nmp->nm_timeo < NFS_MINTIMEO)
    619 			nmp->nm_timeo = NFS_MINTIMEO;
    620 		else if (nmp->nm_timeo > NFS_MAXTIMEO)
    621 			nmp->nm_timeo = NFS_MAXTIMEO;
    622 	}
    623 
    624 	if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
    625 		nmp->nm_retry = argp->retrans;
    626 		if (nmp->nm_retry > NFS_MAXREXMIT)
    627 			nmp->nm_retry = NFS_MAXREXMIT;
    628 	}
    629 
    630 	if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
    631 		nmp->nm_wsize = argp->wsize;
    632 		/*
    633 		 * Clip at the power of 2 below the size. There is an
    634 		 * issue (not isolated) that causes intermittent page
    635 		 * faults if this is not done.
    636 		 */
    637 		if (nmp->nm_wsize > NFS_FABLKSIZE)
    638 			nmp->nm_wsize = 1 << (fls(nmp->nm_wsize) - 1);
    639 		else
    640 			nmp->nm_wsize = NFS_FABLKSIZE;
    641 	}
    642 
    643 	if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
    644 		nmp->nm_rsize = argp->rsize;
    645 		/*
    646 		 * Clip at the power of 2 below the size. There is an
    647 		 * issue (not isolated) that causes intermittent page
    648 		 * faults if this is not done.
    649 		 */
    650 		if (nmp->nm_rsize > NFS_FABLKSIZE)
    651 			nmp->nm_rsize = 1 << (fls(nmp->nm_rsize) - 1);
    652 		else
    653 			nmp->nm_rsize = NFS_FABLKSIZE;
    654 	}
    655 
    656 	if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
    657 		nmp->nm_readdirsize = argp->readdirsize;
    658 	}
    659 
    660 	if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
    661 		nmp->nm_acregmin = argp->acregmin;
    662 	else
    663 		nmp->nm_acregmin = NFS_MINATTRTIMO;
    664 	if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
    665 		nmp->nm_acregmax = argp->acregmax;
    666 	else
    667 		nmp->nm_acregmax = NFS_MAXATTRTIMO;
    668 	if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
    669 		nmp->nm_acdirmin = argp->acdirmin;
    670 	else
    671 		nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
    672 	if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
    673 		nmp->nm_acdirmax = argp->acdirmax;
    674 	else
    675 		nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
    676 	if (nmp->nm_acdirmin > nmp->nm_acdirmax)
    677 		nmp->nm_acdirmin = nmp->nm_acdirmax;
    678 	if (nmp->nm_acregmin > nmp->nm_acregmax)
    679 		nmp->nm_acregmin = nmp->nm_acregmax;
    680 
    681 	if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
    682 		if (argp->readahead <= NFS_MAXRAHEAD)
    683 			nmp->nm_readahead = argp->readahead;
    684 		else
    685 			nmp->nm_readahead = NFS_MAXRAHEAD;
    686 	}
    687 	if ((argp->flags & NFSMNT_WCOMMITSIZE) && argp->wcommitsize >= 0) {
    688 		if (argp->wcommitsize < nmp->nm_wsize)
    689 			nmp->nm_wcommitsize = nmp->nm_wsize;
    690 		else
    691 			nmp->nm_wcommitsize = argp->wcommitsize;
    692 	}
    693 
    694 	adjsock |= ((nmp->nm_sotype != argp->sotype) ||
    695 		    (nmp->nm_soproto != argp->proto));
    696 
    697 	if (nmp->nm_client != NULL && adjsock) {
    698 		int haslock = 0, error = 0;
    699 
    700 		if (nmp->nm_sotype == SOCK_STREAM) {
    701 			error = newnfs_sndlock(&nmp->nm_sockreq.nr_lock);
    702 			if (!error)
    703 				haslock = 1;
    704 		}
    705 		if (!error) {
    706 		    newnfs_disconnect(&nmp->nm_sockreq);
    707 		    if (haslock)
    708 			newnfs_sndunlock(&nmp->nm_sockreq.nr_lock);
    709 		    nmp->nm_sotype = argp->sotype;
    710 		    nmp->nm_soproto = argp->proto;
    711 		    if (nmp->nm_sotype == SOCK_DGRAM)
    712 			while (newnfs_connect(nmp, &nmp->nm_sockreq,
    713 			    cred, td, 0)) {
    714 				printf("newnfs_args: retrying connect\n");
    715 				(void) nfs_catnap(PSOCK, 0, "nfscon");
    716 			}
    717 		}
    718 	} else {
    719 		nmp->nm_sotype = argp->sotype;
    720 		nmp->nm_soproto = argp->proto;
    721 	}
    722 
    723 	if (hostname != NULL) {
    724 		strlcpy(nmp->nm_hostname, hostname,
    725 		    sizeof(nmp->nm_hostname));
    726 		p = strchr(nmp->nm_hostname, ':');
    727 		if (p != NULL)
    728 			*p = '\0';
    729 	}
    730 }
    731 
    732 static const char *nfs_opts[] = { "from", "nfs_args",
    733     "noac", "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
    734     "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
    735     "async", "noconn", "nolockd", "conn", "lockd", "intr", "rdirplus",
    736     "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize",
    737     "retrans", "actimeo", "acregmin", "acregmax", "acdirmin", "acdirmax",
    738     "resvport", "readahead", "hostname", "timeo", "timeout", "addr", "fh",
    739     "nfsv3", "sec", "principal", "nfsv4", "gssname", "allgssname", "dirpath",
    740     "minorversion", "nametimeo", "negnametimeo", "nocto", "noncontigwr",
    741     "pnfs", "wcommitsize",
    742     NULL };
    743 
    744 /*
    745  * Parse the "from" mountarg, passed by the generic mount(8) program
    746  * or the mountroot code.  This is used when rerooting into NFS.
    747  *
    748  * Note that the "hostname" is actually a "hostname:/share/path" string.
    749  */
    750 static int
    751 nfs_mount_parse_from(struct vfsoptlist *opts, char **hostnamep,
    752     struct sockaddr_in **sinp, char *dirpath, size_t dirpathsize, int *dirlenp)
    753 {
    754 	char nam[MNAMELEN + 1];
    755 	char *delimp, *hostp, *spec;
    756 	int error, have_bracket = 0, offset, rv, speclen;
    757 	struct sockaddr_in *sin;
    758 	size_t len;
    759 
    760 	error = vfs_getopt(opts, "from", (void **)&spec, &speclen);
    761 	if (error != 0)
    762 		return (error);
    763 
    764 	/*
    765 	 * This part comes from sbin/mount_nfs/mount_nfs.c:getnfsargs().
    766 	 */
    767 	if (*spec == '[' && (delimp = strchr(spec + 1, ']')) != NULL &&
    768 	    *(delimp + 1) == ':') {
    769 		hostp = spec + 1;
    770 		spec = delimp + 2;
    771 		have_bracket = 1;
    772 	} else if ((delimp = strrchr(spec, ':')) != NULL) {
    773 		hostp = spec;
    774 		spec = delimp + 1;
    775 	} else if ((delimp = strrchr(spec, '@')) != NULL) {
    776 		printf("%s: path@server syntax is deprecated, "
    777 		    "use server:path\n", __func__);
    778 		hostp = delimp + 1;
    779 	} else {
    780 		printf("%s: no <host>:<dirpath> nfs-name\n", __func__);
    781 		return (EINVAL);
    782 	}
    783 	*delimp = '\0';
    784 
    785 	/*
    786 	 * If there has been a trailing slash at mounttime it seems
    787 	 * that some mountd implementations fail to remove the mount
    788 	 * entries from their mountlist while unmounting.
    789 	 */
    790 	for (speclen = strlen(spec);
    791 	    speclen > 1 && spec[speclen - 1] == '/';
    792 	    speclen--)
    793 		spec[speclen - 1] = '\0';
    794 	if (strlen(hostp) + strlen(spec) + 1 > MNAMELEN) {
    795 		printf("%s: %s:%s: name too long", __func__, hostp, spec);
    796 		return (EINVAL);
    797 	}
    798 	/* Make both '@' and ':' notations equal */
    799 	if (*hostp != '\0') {
    800 		len = strlen(hostp);
    801 		offset = 0;
    802 		if (have_bracket)
    803 			nam[offset++] = '[';
    804 		memmove(nam + offset, hostp, len);
    805 		if (have_bracket)
    806 			nam[len + offset++] = ']';
    807 		nam[len + offset++] = ':';
    808 		memmove(nam + len + offset, spec, speclen);
    809 		nam[len + speclen + offset] = '\0';
    810 	} else
    811 		nam[0] = '\0';
    812 
    813 	/*
    814 	 * XXX: IPv6
    815 	 */
    816 	sin = malloc(sizeof(*sin), M_SONAME, M_WAITOK);
    817 	rv = inet_pton(AF_INET, hostp, &sin->sin_addr);
    818 	if (rv != 1) {
    819 		printf("%s: cannot parse '%s', inet_pton() returned %d\n",
    820 		    __func__, hostp, rv);
    821 		free(sin, M_SONAME);
    822 		return (EINVAL);
    823 	}
    824 
    825 	sin->sin_len = sizeof(*sin);
    826 	sin->sin_family = AF_INET;
    827 	/*
    828 	 * XXX: hardcoded port number.
    829 	 */
    830 	sin->sin_port = htons(2049);
    831 
    832 	*hostnamep = strdup(nam, M_NEWNFSMNT);
    833 	*sinp = sin;
    834 	strlcpy(dirpath, spec, dirpathsize);
    835 	*dirlenp = strlen(dirpath);
    836 
    837 	return (0);
    838 }
    839 
    840 /*
    841  * VFS Operations.
    842  *
    843  * mount system call
    844  * It seems a bit dumb to copyinstr() the host and path here and then
    845  * bcopy() them in mountnfs(), but I wanted to detect errors before
    846  * doing the getsockaddr() call because getsockaddr() allocates an mbuf and
    847  * an error after that means that I have to release the mbuf.
    848  */
    849 /* ARGSUSED */
    850 static int
    851 nfs_mount(struct mount *mp)
    852 {
    853 	struct nfs_args args = {
    854 	    .version = NFS_ARGSVERSION,
    855 	    .addr = NULL,
    856 	    .addrlen = sizeof (struct sockaddr_in),
    857 	    .sotype = SOCK_STREAM,
    858 	    .proto = 0,
    859 	    .fh = NULL,
    860 	    .fhsize = 0,
    861 	    .flags = NFSMNT_RESVPORT,
    862 	    .wsize = NFS_WSIZE,
    863 	    .rsize = NFS_RSIZE,
    864 	    .readdirsize = NFS_READDIRSIZE,
    865 	    .timeo = 10,
    866 	    .retrans = NFS_RETRANS,
    867 	    .readahead = NFS_DEFRAHEAD,
    868 	    .wcommitsize = 0,			/* was: NQ_DEFLEASE */
    869 	    .hostname = NULL,
    870 	    .acregmin = NFS_MINATTRTIMO,
    871 	    .acregmax = NFS_MAXATTRTIMO,
    872 	    .acdirmin = NFS_MINDIRATTRTIMO,
    873 	    .acdirmax = NFS_MAXDIRATTRTIMO,
    874 	};
    875 	int error = 0, ret, len;
    876 	struct sockaddr *nam = NULL;
    877 	struct vnode *vp;
    878 	struct thread *td;
    879 	char hst[MNAMELEN];
    880 	u_char nfh[NFSX_FHMAX], krbname[100], dirpath[100], srvkrbname[100];
    881 	char *cp, *opt, *name, *secname;
    882 	int nametimeo = NFS_DEFAULT_NAMETIMEO;
    883 	int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
    884 	int minvers = 0;
    885 	int dirlen, has_nfs_args_opt, has_nfs_from_opt,
    886 	    krbnamelen, srvkrbnamelen;
    887 	size_t hstlen;
    888 
    889 	has_nfs_args_opt = 0;
    890 	has_nfs_from_opt = 0;
    891 	if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
    892 		error = EINVAL;
    893 		goto out;
    894 	}
    895 
    896 	td = curthread;
    897 	if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS &&
    898 	    nfs_diskless_valid != 0) {
    899 		error = nfs_mountroot(mp);
    900 		goto out;
    901 	}
    902 
    903 	nfscl_init();
    904 
    905 	/*
    906 	 * The old mount_nfs program passed the struct nfs_args
    907 	 * from userspace to kernel.  The new mount_nfs program
    908 	 * passes string options via nmount() from userspace to kernel
    909 	 * and we populate the struct nfs_args in the kernel.
    910 	 */
    911 	if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
    912 		error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
    913 		    sizeof(args));
    914 		if (error != 0)
    915 			goto out;
    916 
    917 		if (args.version != NFS_ARGSVERSION) {
    918 			error = EPROGMISMATCH;
    919 			goto out;
    920 		}
    921 		has_nfs_args_opt = 1;
    922 	}
    923 
    924 	/* Handle the new style options. */
    925 	if (vfs_getopt(mp->mnt_optnew, "noac", NULL, NULL) == 0) {
    926 		args.acdirmin = args.acdirmax =
    927 		    args.acregmin = args.acregmax = 0;
    928 		args.flags |= NFSMNT_ACDIRMIN | NFSMNT_ACDIRMAX |
    929 		    NFSMNT_ACREGMIN | NFSMNT_ACREGMAX;
    930 	}
    931 	if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
    932 		args.flags |= NFSMNT_NOCONN;
    933 	if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
    934 		args.flags &= ~NFSMNT_NOCONN;
    935 	if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
    936 		args.flags |= NFSMNT_NOLOCKD;
    937 	if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
    938 		args.flags &= ~NFSMNT_NOLOCKD;
    939 	if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
    940 		args.flags |= NFSMNT_INT;
    941 	if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
    942 		args.flags |= NFSMNT_RDIRPLUS;
    943 	if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
    944 		args.flags |= NFSMNT_RESVPORT;
    945 	if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
    946 		args.flags &= ~NFSMNT_RESVPORT;
    947 	if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
    948 		args.flags |= NFSMNT_SOFT;
    949 	if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
    950 		args.flags &= ~NFSMNT_SOFT;
    951 	if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
    952 		args.sotype = SOCK_DGRAM;
    953 	if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
    954 		args.sotype = SOCK_DGRAM;
    955 	if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
    956 		args.sotype = SOCK_STREAM;
    957 	if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
    958 		args.flags |= NFSMNT_NFSV3;
    959 	if (vfs_getopt(mp->mnt_optnew, "nfsv4", NULL, NULL) == 0) {
    960 		args.flags |= NFSMNT_NFSV4;
    961 		args.sotype = SOCK_STREAM;
    962 	}
    963 	if (vfs_getopt(mp->mnt_optnew, "allgssname", NULL, NULL) == 0)
    964 		args.flags |= NFSMNT_ALLGSSNAME;
    965 	if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0)
    966 		args.flags |= NFSMNT_NOCTO;
    967 	if (vfs_getopt(mp->mnt_optnew, "noncontigwr", NULL, NULL) == 0)
    968 		args.flags |= NFSMNT_NONCONTIGWR;
    969 	if (vfs_getopt(mp->mnt_optnew, "pnfs", NULL, NULL) == 0)
    970 		args.flags |= NFSMNT_PNFS;
    971 	if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
    972 		if (opt == NULL) {
    973 			vfs_mount_error(mp, "illegal readdirsize");
    974 			error = EINVAL;
    975 			goto out;
    976 		}
    977 		ret = sscanf(opt, "%d", &args.readdirsize);
    978 		if (ret != 1 || args.readdirsize <= 0) {
    979 			vfs_mount_error(mp, "illegal readdirsize: %s",
    980 			    opt);
    981 			error = EINVAL;
    982 			goto out;
    983 		}
    984 		args.flags |= NFSMNT_READDIRSIZE;
    985 	}
    986 	if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
    987 		if (opt == NULL) {
    988 			vfs_mount_error(mp, "illegal readahead");
    989 			error = EINVAL;
    990 			goto out;
    991 		}
    992 		ret = sscanf(opt, "%d", &args.readahead);
    993 		if (ret != 1 || args.readahead <= 0) {
    994 			vfs_mount_error(mp, "illegal readahead: %s",
    995 			    opt);
    996 			error = EINVAL;
    997 			goto out;
    998 		}
    999 		args.flags |= NFSMNT_READAHEAD;
   1000 	}
   1001 	if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
   1002 		if (opt == NULL) {
   1003 			vfs_mount_error(mp, "illegal wsize");
   1004 			error = EINVAL;
   1005 			goto out;
   1006 		}
   1007 		ret = sscanf(opt, "%d", &args.wsize);
   1008 		if (ret != 1 || args.wsize <= 0) {
   1009 			vfs_mount_error(mp, "illegal wsize: %s",
   1010 			    opt);
   1011 			error = EINVAL;
   1012 			goto out;
   1013 		}
   1014 		args.flags |= NFSMNT_WSIZE;
   1015 	}
   1016 	if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
   1017 		if (opt == NULL) {
   1018 			vfs_mount_error(mp, "illegal rsize");
   1019 			error = EINVAL;
   1020 			goto out;
   1021 		}
   1022 		ret = sscanf(opt, "%d", &args.rsize);
   1023 		if (ret != 1 || args.rsize <= 0) {
   1024 			vfs_mount_error(mp, "illegal wsize: %s",
   1025 			    opt);
   1026 			error = EINVAL;
   1027 			goto out;
   1028 		}
   1029 		args.flags |= NFSMNT_RSIZE;
   1030 	}
   1031 	if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
   1032 		if (opt == NULL) {
   1033 			vfs_mount_error(mp, "illegal retrans");
   1034 			error = EINVAL;
   1035 			goto out;
   1036 		}
   1037 		ret = sscanf(opt, "%d", &args.retrans);
   1038 		if (ret != 1 || args.retrans <= 0) {
   1039 			vfs_mount_error(mp, "illegal retrans: %s",
   1040 			    opt);
   1041 			error = EINVAL;
   1042 			goto out;
   1043 		}
   1044 		args.flags |= NFSMNT_RETRANS;
   1045 	}
   1046 	if (vfs_getopt(mp->mnt_optnew, "actimeo", (void **)&opt, NULL) == 0) {
   1047 		ret = sscanf(opt, "%d", &args.acregmin);
   1048 		if (ret != 1 || args.acregmin < 0) {
   1049 			vfs_mount_error(mp, "illegal actimeo: %s",
   1050 			    opt);
   1051 			error = EINVAL;
   1052 			goto out;
   1053 		}
   1054 		args.acdirmin = args.acdirmax = args.acregmax = args.acregmin;
   1055 		args.flags |= NFSMNT_ACDIRMIN | NFSMNT_ACDIRMAX |
   1056 		    NFSMNT_ACREGMIN | NFSMNT_ACREGMAX;
   1057 	}
   1058 	if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
   1059 		ret = sscanf(opt, "%d", &args.acregmin);
   1060 		if (ret != 1 || args.acregmin < 0) {
   1061 			vfs_mount_error(mp, "illegal acregmin: %s",
   1062 			    opt);
   1063 			error = EINVAL;
   1064 			goto out;
   1065 		}
   1066 		args.flags |= NFSMNT_ACREGMIN;
   1067 	}
   1068 	if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
   1069 		ret = sscanf(opt, "%d", &args.acregmax);
   1070 		if (ret != 1 || args.acregmax < 0) {
   1071 			vfs_mount_error(mp, "illegal acregmax: %s",
   1072 			    opt);
   1073 			error = EINVAL;
   1074 			goto out;
   1075 		}
   1076 		args.flags |= NFSMNT_ACREGMAX;
   1077 	}
   1078 	if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
   1079 		ret = sscanf(opt, "%d", &args.acdirmin);
   1080 		if (ret != 1 || args.acdirmin < 0) {
   1081 			vfs_mount_error(mp, "illegal acdirmin: %s",
   1082 			    opt);
   1083 			error = EINVAL;
   1084 			goto out;
   1085 		}
   1086 		args.flags |= NFSMNT_ACDIRMIN;
   1087 	}
   1088 	if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
   1089 		ret = sscanf(opt, "%d", &args.acdirmax);
   1090 		if (ret != 1 || args.acdirmax < 0) {
   1091 			vfs_mount_error(mp, "illegal acdirmax: %s",
   1092 			    opt);
   1093 			error = EINVAL;
   1094 			goto out;
   1095 		}
   1096 		args.flags |= NFSMNT_ACDIRMAX;
   1097 	}
   1098 	if (vfs_getopt(mp->mnt_optnew, "wcommitsize", (void **)&opt, NULL) == 0) {
   1099 		ret = sscanf(opt, "%d", &args.wcommitsize);
   1100 		if (ret != 1 || args.wcommitsize < 0) {
   1101 			vfs_mount_error(mp, "illegal wcommitsize: %s", opt);
   1102 			error = EINVAL;
   1103 			goto out;
   1104 		}
   1105 		args.flags |= NFSMNT_WCOMMITSIZE;
   1106 	}
   1107 	if (vfs_getopt(mp->mnt_optnew, "timeo", (void **)&opt, NULL) == 0) {
   1108 		ret = sscanf(opt, "%d", &args.timeo);
   1109 		if (ret != 1 || args.timeo <= 0) {
   1110 			vfs_mount_error(mp, "illegal timeo: %s",
   1111 			    opt);
   1112 			error = EINVAL;
   1113 			goto out;
   1114 		}
   1115 		args.flags |= NFSMNT_TIMEO;
   1116 	}
   1117 	if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
   1118 		ret = sscanf(opt, "%d", &args.timeo);
   1119 		if (ret != 1 || args.timeo <= 0) {
   1120 			vfs_mount_error(mp, "illegal timeout: %s",
   1121 			    opt);
   1122 			error = EINVAL;
   1123 			goto out;
   1124 		}
   1125 		args.flags |= NFSMNT_TIMEO;
   1126 	}
   1127 	if (vfs_getopt(mp->mnt_optnew, "nametimeo", (void **)&opt, NULL) == 0) {
   1128 		ret = sscanf(opt, "%d", &nametimeo);
   1129 		if (ret != 1 || nametimeo < 0) {
   1130 			vfs_mount_error(mp, "illegal nametimeo: %s", opt);
   1131 			error = EINVAL;
   1132 			goto out;
   1133 		}
   1134 	}
   1135 	if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
   1136 	    == 0) {
   1137 		ret = sscanf(opt, "%d", &negnametimeo);
   1138 		if (ret != 1 || negnametimeo < 0) {
   1139 			vfs_mount_error(mp, "illegal negnametimeo: %s",
   1140 			    opt);
   1141 			error = EINVAL;
   1142 			goto out;
   1143 		}
   1144 	}
   1145 	if (vfs_getopt(mp->mnt_optnew, "minorversion", (void **)&opt, NULL) ==
   1146 	    0) {
   1147 		ret = sscanf(opt, "%d", &minvers);
   1148 		if (ret != 1 || minvers < 0 || minvers > 1 ||
   1149 		    (args.flags & NFSMNT_NFSV4) == 0) {
   1150 			vfs_mount_error(mp, "illegal minorversion: %s", opt);
   1151 			error = EINVAL;
   1152 			goto out;
   1153 		}
   1154 	}
   1155 	if (vfs_getopt(mp->mnt_optnew, "sec",
   1156 		(void **) &secname, NULL) == 0)
   1157 		nfs_sec_name(secname, &args.flags);
   1158 
   1159 	if (mp->mnt_flag & MNT_UPDATE) {
   1160 		struct nfsmount *nmp = VFSTONFS(mp);
   1161 
   1162 		if (nmp == NULL) {
   1163 			error = EIO;
   1164 			goto out;
   1165 		}
   1166 
   1167 		/*
   1168 		 * If a change from TCP->UDP is done and there are thread(s)
   1169 		 * that have I/O RPC(s) in progress with a transfer size
   1170 		 * greater than NFS_MAXDGRAMDATA, those thread(s) will be
   1171 		 * hung, retrying the RPC(s) forever. Usually these threads
   1172 		 * will be seen doing an uninterruptible sleep on wait channel
   1173 		 * "nfsreq".
   1174 		 */
   1175 		if (args.sotype == SOCK_DGRAM && nmp->nm_sotype == SOCK_STREAM)
   1176 			tprintf(td->td_proc, LOG_WARNING,
   1177 	"Warning: mount -u that changes TCP->UDP can result in hung threads\n");
   1178 
   1179 		/*
   1180 		 * When doing an update, we can't change version,
   1181 		 * security, switch lockd strategies or change cookie
   1182 		 * translation
   1183 		 */
   1184 		args.flags = (args.flags &
   1185 		    ~(NFSMNT_NFSV3 |
   1186 		      NFSMNT_NFSV4 |
   1187 		      NFSMNT_KERB |
   1188 		      NFSMNT_INTEGRITY |
   1189 		      NFSMNT_PRIVACY |
   1190 		      NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
   1191 		    (nmp->nm_flag &
   1192 			(NFSMNT_NFSV3 |
   1193 			 NFSMNT_NFSV4 |
   1194 			 NFSMNT_KERB |
   1195 			 NFSMNT_INTEGRITY |
   1196 			 NFSMNT_PRIVACY |
   1197 			 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
   1198 		nfs_decode_args(mp, nmp, &args, NULL, td->td_ucred, td);
   1199 		goto out;
   1200 	}
   1201 
   1202 	/*
   1203 	 * Make the nfs_ip_paranoia sysctl serve as the default connection
   1204 	 * or no-connection mode for those protocols that support
   1205 	 * no-connection mode (the flag will be cleared later for protocols
   1206 	 * that do not support no-connection mode).  This will allow a client
   1207 	 * to receive replies from a different IP then the request was
   1208 	 * sent to.  Note: default value for nfs_ip_paranoia is 1 (paranoid),
   1209 	 * not 0.
   1210 	 */
   1211 	if (nfs_ip_paranoia == 0)
   1212 		args.flags |= NFSMNT_NOCONN;
   1213 
   1214 	if (has_nfs_args_opt != 0) {
   1215 		/*
   1216 		 * In the 'nfs_args' case, the pointers in the args
   1217 		 * structure are in userland - we copy them in here.
   1218 		 */
   1219 		if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
   1220 			vfs_mount_error(mp, "Bad file handle");
   1221 			error = EINVAL;
   1222 			goto out;
   1223 		}
   1224 		error = copyin((caddr_t)args.fh, (caddr_t)nfh,
   1225 		    args.fhsize);
   1226 		if (error != 0)
   1227 			goto out;
   1228 		error = copyinstr(args.hostname, hst, MNAMELEN - 1, &hstlen);
   1229 		if (error != 0)
   1230 			goto out;
   1231 		bzero(&hst[hstlen], MNAMELEN - hstlen);
   1232 		args.hostname = hst;
   1233 		/* getsockaddr() call must be after above copyin() calls */
   1234 		error = getsockaddr(&nam, (caddr_t)args.addr,
   1235 		    args.addrlen);
   1236 		if (error != 0)
   1237 			goto out;
   1238 	} else if (nfs_mount_parse_from(mp->mnt_optnew,
   1239 	    &args.hostname, (struct sockaddr_in **)&nam, dirpath,
   1240 	    sizeof(dirpath), &dirlen) == 0) {
   1241 		has_nfs_from_opt = 1;
   1242 		bcopy(args.hostname, hst, MNAMELEN);
   1243 		hst[MNAMELEN - 1] = '\0';
   1244 
   1245 		/*
   1246 		 * This only works with NFSv4 for now.
   1247 		 */
   1248 		args.fhsize = 0;
   1249 		args.flags |= NFSMNT_NFSV4;
   1250 		args.sotype = SOCK_STREAM;
   1251 	} else {
   1252 		if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
   1253 		    &args.fhsize) == 0) {
   1254 			if (args.fhsize < 0 || args.fhsize > NFSX_FHMAX) {
   1255 				vfs_mount_error(mp, "Bad file handle");
   1256 				error = EINVAL;
   1257 				goto out;
   1258 			}
   1259 			bcopy(args.fh, nfh, args.fhsize);
   1260 		} else {
   1261 			args.fhsize = 0;
   1262 		}
   1263 		(void) vfs_getopt(mp->mnt_optnew, "hostname",
   1264 		    (void **)&args.hostname, &len);
   1265 		if (args.hostname == NULL) {
   1266 			vfs_mount_error(mp, "Invalid hostname");
   1267 			error = EINVAL;
   1268 			goto out;
   1269 		}
   1270 		bcopy(args.hostname, hst, MNAMELEN);
   1271 		hst[MNAMELEN - 1] = '\0';
   1272 	}
   1273 
   1274 	if (vfs_getopt(mp->mnt_optnew, "principal", (void **)&name, NULL) == 0)
   1275 		strlcpy(srvkrbname, name, sizeof (srvkrbname));
   1276 	else {
   1277 		snprintf(srvkrbname, sizeof (srvkrbname), "nfs@%s", hst);
   1278 		cp = strchr(srvkrbname, ':');
   1279 		if (cp != NULL)
   1280 			*cp = '\0';
   1281 	}
   1282 	srvkrbnamelen = strlen(srvkrbname);
   1283 
   1284 	if (vfs_getopt(mp->mnt_optnew, "gssname", (void **)&name, NULL) == 0)
   1285 		strlcpy(krbname, name, sizeof (krbname));
   1286 	else
   1287 		krbname[0] = '\0';
   1288 	krbnamelen = strlen(krbname);
   1289 
   1290 	if (has_nfs_from_opt == 0) {
   1291 		if (vfs_getopt(mp->mnt_optnew,
   1292 		    "dirpath", (void **)&name, NULL) == 0)
   1293 			strlcpy(dirpath, name, sizeof (dirpath));
   1294 		else
   1295 			dirpath[0] = '\0';
   1296 		dirlen = strlen(dirpath);
   1297 	}
   1298 
   1299 	if (has_nfs_args_opt == 0 && has_nfs_from_opt == 0) {
   1300 		if (vfs_getopt(mp->mnt_optnew, "addr",
   1301 		    (void **)&args.addr, &args.addrlen) == 0) {
   1302 			if (args.addrlen > SOCK_MAXADDRLEN) {
   1303 				error = ENAMETOOLONG;
   1304 				goto out;
   1305 			}
   1306 			nam = malloc(args.addrlen, M_SONAME, M_WAITOK);
   1307 			bcopy(args.addr, nam, args.addrlen);
   1308 			nam->sa_len = args.addrlen;
   1309 		} else {
   1310 			vfs_mount_error(mp, "No server address");
   1311 			error = EINVAL;
   1312 			goto out;
   1313 		}
   1314 	}
   1315 
   1316 	args.fh = nfh;
   1317 	error = mountnfs(&args, mp, nam, hst, krbname, krbnamelen, dirpath,
   1318 	    dirlen, srvkrbname, srvkrbnamelen, &vp, td->td_ucred, td,
   1319 	    nametimeo, negnametimeo, minvers);
   1320 out:
   1321 	if (!error) {
   1322 		MNT_ILOCK(mp);
   1323 		mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED | MNTK_NO_IOPF |
   1324 		    MNTK_USES_BCACHE;
   1325 		MNT_IUNLOCK(mp);
   1326 	}
   1327 	return (error);
   1328 }
   1329 
   1330 
   1331 /*
   1332  * VFS Operations.
   1333  *
   1334  * mount system call
   1335  * It seems a bit dumb to copyinstr() the host and path here and then
   1336  * bcopy() them in mountnfs(), but I wanted to detect errors before
   1337  * doing the getsockaddr() call because getsockaddr() allocates an mbuf and
   1338  * an error after that means that I have to release the mbuf.
   1339  */
   1340 /* ARGSUSED */
   1341 static int
   1342 nfs_cmount(struct mntarg *ma, void *data, uint64_t flags)
   1343 {
   1344 	int error;
   1345 	struct nfs_args args;
   1346 
   1347 	error = copyin(data, &args, sizeof (struct nfs_args));
   1348 	if (error)
   1349 		return error;
   1350 
   1351 	ma = mount_arg(ma, "nfs_args", &args, sizeof args);
   1352 
   1353 	error = kernel_mount(ma, flags);
   1354 	return (error);
   1355 }
   1356 
   1357 /*
   1358  * Common code for mount and mountroot
   1359  */
   1360 static int
   1361 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
   1362     char *hst, u_char *krbname, int krbnamelen, u_char *dirpath, int dirlen,
   1363     u_char *srvkrbname, int srvkrbnamelen, struct vnode **vpp,
   1364     struct ucred *cred, struct thread *td, int nametimeo, int negnametimeo,
   1365     int minvers)
   1366 {
   1367 	struct nfsmount *nmp;
   1368 	struct nfsnode *np;
   1369 	int error, trycnt, ret;
   1370 	struct nfsvattr nfsva;
   1371 	struct nfsclclient *clp;
   1372 	struct nfsclds *dsp, *tdsp;
   1373 	uint32_t lease;
   1374 	static u_int64_t clval = 0;
   1375 
   1376 	NFSCL_DEBUG(3, "in mnt\n");
   1377 	clp = NULL;
   1378 	if (mp->mnt_flag & MNT_UPDATE) {
   1379 		nmp = VFSTONFS(mp);
   1380 		printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
   1381 		FREE(nam, M_SONAME);
   1382 		return (0);
   1383 	} else {
   1384 		MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount) +
   1385 		    krbnamelen + dirlen + srvkrbnamelen + 2,
   1386 		    M_NEWNFSMNT, M_WAITOK | M_ZERO);
   1387 		TAILQ_INIT(&nmp->nm_bufq);
   1388 		if (clval == 0)
   1389 			clval = (u_int64_t)nfsboottime.tv_sec;
   1390 		nmp->nm_clval = clval++;
   1391 		nmp->nm_krbnamelen = krbnamelen;
   1392 		nmp->nm_dirpathlen = dirlen;
   1393 		nmp->nm_srvkrbnamelen = srvkrbnamelen;
   1394 		if (td->td_ucred->cr_uid != (uid_t)0) {
   1395 			/*
   1396 			 * nm_uid is used to get KerberosV credentials for
   1397 			 * the nfsv4 state handling operations if there is
   1398 			 * no host based principal set. Use the uid of
   1399 			 * this user if not root, since they are doing the
   1400 			 * mount. I don't think setting this for root will
   1401 			 * work, since root normally does not have user
   1402 			 * credentials in a credentials cache.
   1403 			 */
   1404 			nmp->nm_uid = td->td_ucred->cr_uid;
   1405 		} else {
   1406 			/*
   1407 			 * Just set to -1, so it won't be used.
   1408 			 */
   1409 			nmp->nm_uid = (uid_t)-1;
   1410 		}
   1411 
   1412 		/* Copy and null terminate all the names */
   1413 		if (nmp->nm_krbnamelen > 0) {
   1414 			bcopy(krbname, nmp->nm_krbname, nmp->nm_krbnamelen);
   1415 			nmp->nm_name[nmp->nm_krbnamelen] = '\0';
   1416 		}
   1417 		if (nmp->nm_dirpathlen > 0) {
   1418 			bcopy(dirpath, NFSMNT_DIRPATH(nmp),
   1419 			    nmp->nm_dirpathlen);
   1420 			nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
   1421 			    + 1] = '\0';
   1422 		}
   1423 		if (nmp->nm_srvkrbnamelen > 0) {
   1424 			bcopy(srvkrbname, NFSMNT_SRVKRBNAME(nmp),
   1425 			    nmp->nm_srvkrbnamelen);
   1426 			nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
   1427 			    + nmp->nm_srvkrbnamelen + 2] = '\0';
   1428 		}
   1429 		nmp->nm_sockreq.nr_cred = crhold(cred);
   1430 		mtx_init(&nmp->nm_sockreq.nr_mtx, "nfssock", NULL, MTX_DEF);
   1431 		mp->mnt_data = nmp;
   1432 		nmp->nm_getinfo = nfs_getnlminfo;
   1433 		nmp->nm_vinvalbuf = ncl_vinvalbuf;
   1434 	}
   1435 	vfs_getnewfsid(mp);
   1436 	nmp->nm_mountp = mp;
   1437 	mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF | MTX_DUPOK);
   1438 
   1439 	/*
   1440 	 * Since nfs_decode_args() might optionally set them, these
   1441 	 * need to be set to defaults before the call, so that the
   1442 	 * optional settings aren't overwritten.
   1443 	 */
   1444 	nmp->nm_nametimeo = nametimeo;
   1445 	nmp->nm_negnametimeo = negnametimeo;
   1446 	nmp->nm_timeo = NFS_TIMEO;
   1447 	nmp->nm_retry = NFS_RETRANS;
   1448 	nmp->nm_readahead = NFS_DEFRAHEAD;
   1449 
   1450 	/* This is empirical approximation of sqrt(hibufspace) * 256. */
   1451 	nmp->nm_wcommitsize = NFS_MAXBSIZE / 256;
   1452 	while ((long)nmp->nm_wcommitsize * nmp->nm_wcommitsize < hibufspace)
   1453 		nmp->nm_wcommitsize *= 2;
   1454 	nmp->nm_wcommitsize *= 256;
   1455 
   1456 	if ((argp->flags & NFSMNT_NFSV4) != 0)
   1457 		nmp->nm_minorvers = minvers;
   1458 	else
   1459 		nmp->nm_minorvers = 0;
   1460 
   1461 	nfs_decode_args(mp, nmp, argp, hst, cred, td);
   1462 
   1463 	/*
   1464 	 * V2 can only handle 32 bit filesizes.  A 4GB-1 limit may be too
   1465 	 * high, depending on whether we end up with negative offsets in
   1466 	 * the client or server somewhere.  2GB-1 may be safer.
   1467 	 *
   1468 	 * For V3, ncl_fsinfo will adjust this as necessary.  Assume maximum
   1469 	 * that we can handle until we find out otherwise.
   1470 	 */
   1471 	if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0)
   1472 		nmp->nm_maxfilesize = 0xffffffffLL;
   1473 	else
   1474 		nmp->nm_maxfilesize = OFF_MAX;
   1475 
   1476 	if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
   1477 		nmp->nm_wsize = NFS_WSIZE;
   1478 		nmp->nm_rsize = NFS_RSIZE;
   1479 		nmp->nm_readdirsize = NFS_READDIRSIZE;
   1480 	}
   1481 	nmp->nm_numgrps = NFS_MAXGRPS;
   1482 	nmp->nm_tprintf_delay = nfs_tprintf_delay;
   1483 	if (nmp->nm_tprintf_delay < 0)
   1484 		nmp->nm_tprintf_delay = 0;
   1485 	nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
   1486 	if (nmp->nm_tprintf_initial_delay < 0)
   1487 		nmp->nm_tprintf_initial_delay = 0;
   1488 	nmp->nm_fhsize = argp->fhsize;
   1489 	if (nmp->nm_fhsize > 0)
   1490 		bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
   1491 	bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
   1492 	nmp->nm_nam = nam;
   1493 	/* Set up the sockets and per-host congestion */
   1494 	nmp->nm_sotype = argp->sotype;
   1495 	nmp->nm_soproto = argp->proto;
   1496 	nmp->nm_sockreq.nr_prog = NFS_PROG;
   1497 	if ((argp->flags & NFSMNT_NFSV4))
   1498 		nmp->nm_sockreq.nr_vers = NFS_VER4;
   1499 	else if ((argp->flags & NFSMNT_NFSV3))
   1500 		nmp->nm_sockreq.nr_vers = NFS_VER3;
   1501 	else
   1502 		nmp->nm_sockreq.nr_vers = NFS_VER2;
   1503 
   1504 
   1505 	if ((error = newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0)))
   1506 		goto bad;
   1507 	/* For NFSv4.1, get the clientid now. */
   1508 	if (nmp->nm_minorvers > 0) {
   1509 		NFSCL_DEBUG(3, "at getcl\n");
   1510 		error = nfscl_getcl(mp, cred, td, 0, &clp);
   1511 		NFSCL_DEBUG(3, "aft getcl=%d\n", error);
   1512 		if (error != 0)
   1513 			goto bad;
   1514 	}
   1515 
   1516 	if (nmp->nm_fhsize == 0 && (nmp->nm_flag & NFSMNT_NFSV4) &&
   1517 	    nmp->nm_dirpathlen > 0) {
   1518 		NFSCL_DEBUG(3, "in dirp\n");
   1519 		/*
   1520 		 * If the fhsize on the mount point == 0 for V4, the mount
   1521 		 * path needs to be looked up.
   1522 		 */
   1523 		trycnt = 3;
   1524 		do {
   1525 			error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp),
   1526 			    cred, td);
   1527 			NFSCL_DEBUG(3, "aft dirp=%d\n", error);
   1528 			if (error)
   1529 				(void) nfs_catnap(PZERO, error, "nfsgetdirp");
   1530 		} while (error && --trycnt > 0);
   1531 		if (error) {
   1532 			error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
   1533 			goto bad;
   1534 		}
   1535 	}
   1536 
   1537 	/*
   1538 	 * A reference count is needed on the nfsnode representing the
   1539 	 * remote root.  If this object is not persistent, then backward
   1540 	 * traversals of the mount point (i.e. "..") will not work if
   1541 	 * the nfsnode gets flushed out of the cache. Ufs does not have
   1542 	 * this problem, because one can identify root inodes by their
   1543 	 * number == ROOTINO (2).
   1544 	 */
   1545 	if (nmp->nm_fhsize > 0) {
   1546 		/*
   1547 		 * Set f_iosize to NFS_DIRBLKSIZ so that bo_bsize gets set
   1548 		 * non-zero for the root vnode. f_iosize will be set correctly
   1549 		 * by nfs_statfs() before any I/O occurs.
   1550 		 */
   1551 		mp->mnt_stat.f_iosize = NFS_DIRBLKSIZ;
   1552 		error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np,
   1553 		    LK_EXCLUSIVE);
   1554 		if (error)
   1555 			goto bad;
   1556 		*vpp = NFSTOV(np);
   1557 
   1558 		/*
   1559 		 * Get file attributes and transfer parameters for the
   1560 		 * mountpoint.  This has the side effect of filling in
   1561 		 * (*vpp)->v_type with the correct value.
   1562 		 */
   1563 		ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
   1564 		    cred, td, &nfsva, NULL, &lease);
   1565 		if (ret) {
   1566 			/*
   1567 			 * Just set default values to get things going.
   1568 			 */
   1569 			NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
   1570 			nfsva.na_vattr.va_type = VDIR;
   1571 			nfsva.na_vattr.va_mode = 0777;
   1572 			nfsva.na_vattr.va_nlink = 100;
   1573 			nfsva.na_vattr.va_uid = (uid_t)0;
   1574 			nfsva.na_vattr.va_gid = (gid_t)0;
   1575 			nfsva.na_vattr.va_fileid = 2;
   1576 			nfsva.na_vattr.va_gen = 1;
   1577 			nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
   1578 			nfsva.na_vattr.va_size = 512 * 1024;
   1579 			lease = 60;
   1580 		}
   1581 		(void) nfscl_loadattrcache(vpp, &nfsva, NULL, NULL, 0, 1);
   1582 		if (nmp->nm_minorvers > 0) {
   1583 			NFSCL_DEBUG(3, "lease=%d\n", (int)lease);
   1584 			NFSLOCKCLSTATE();
   1585 			clp->nfsc_renew = NFSCL_RENEW(lease);
   1586 			clp->nfsc_expire = NFSD_MONOSEC + clp->nfsc_renew;
   1587 			clp->nfsc_clientidrev++;
   1588 			if (clp->nfsc_clientidrev == 0)
   1589 				clp->nfsc_clientidrev++;
   1590 			NFSUNLOCKCLSTATE();
   1591 			/*
   1592 			 * Mount will succeed, so the renew thread can be
   1593 			 * started now.
   1594 			 */
   1595 			nfscl_start_renewthread(clp);
   1596 			nfscl_clientrelease(clp);
   1597 		}
   1598 		if (argp->flags & NFSMNT_NFSV3)
   1599 			ncl_fsinfo(nmp, *vpp, cred, td);
   1600 
   1601 		/* Mark if the mount point supports NFSv4 ACLs. */
   1602 		if ((argp->flags & NFSMNT_NFSV4) != 0 && nfsrv_useacl != 0 &&
   1603 		    ret == 0 &&
   1604 		    NFSISSET_ATTRBIT(&nfsva.na_suppattr, NFSATTRBIT_ACL)) {
   1605 			MNT_ILOCK(mp);
   1606 			mp->mnt_flag |= MNT_NFS4ACLS;
   1607 			MNT_IUNLOCK(mp);
   1608 		}
   1609 
   1610 		/*
   1611 		 * Lose the lock but keep the ref.
   1612 		 */
   1613 		NFSVOPUNLOCK(*vpp, 0);
   1614 		return (0);
   1615 	}
   1616 	error = EIO;
   1617 
   1618 bad:
   1619 	if (clp != NULL)
   1620 		nfscl_clientrelease(clp);
   1621 	newnfs_disconnect(&nmp->nm_sockreq);
   1622 	crfree(nmp->nm_sockreq.nr_cred);
   1623 	if (nmp->nm_sockreq.nr_auth != NULL)
   1624 		AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
   1625 	mtx_destroy(&nmp->nm_sockreq.nr_mtx);
   1626 	mtx_destroy(&nmp->nm_mtx);
   1627 	if (nmp->nm_clp != NULL) {
   1628 		NFSLOCKCLSTATE();
   1629 		LIST_REMOVE(nmp->nm_clp, nfsc_list);
   1630 		NFSUNLOCKCLSTATE();
   1631 		free(nmp->nm_clp, M_NFSCLCLIENT);
   1632 	}
   1633 	TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp)
   1634 		nfscl_freenfsclds(dsp);
   1635 	FREE(nmp, M_NEWNFSMNT);
   1636 	FREE(nam, M_SONAME);
   1637 	return (error);
   1638 }
   1639 
   1640 /*
   1641  * unmount system call
   1642  */
   1643 static int
   1644 nfs_unmount(struct mount *mp, int mntflags)
   1645 {
   1646 	struct thread *td;
   1647 	struct nfsmount *nmp;
   1648 	int error, flags = 0, i, trycnt = 0;
   1649 	struct nfsclds *dsp, *tdsp;
   1650 
   1651 	td = curthread;
   1652 
   1653 	if (mntflags & MNT_FORCE)
   1654 		flags |= FORCECLOSE;
   1655 	nmp = VFSTONFS(mp);
   1656 	/*
   1657 	 * Goes something like this..
   1658 	 * - Call vflush() to clear out vnodes for this filesystem
   1659 	 * - Close the socket
   1660 	 * - Free up the data structures
   1661 	 */
   1662 	/* In the forced case, cancel any outstanding requests. */
   1663 	if (mntflags & MNT_FORCE) {
   1664 		error = newnfs_nmcancelreqs(nmp);
   1665 		if (error)
   1666 			goto out;
   1667 		/* For a forced close, get rid of the renew thread now */
   1668 		nfscl_umount(nmp, td);
   1669 	}
   1670 	/* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
   1671 	do {
   1672 		error = vflush(mp, 1, flags, td);
   1673 		if ((mntflags & MNT_FORCE) && error != 0 && ++trycnt < 30)
   1674 			(void) nfs_catnap(PSOCK, error, "newndm");
   1675 	} while ((mntflags & MNT_FORCE) && error != 0 && trycnt < 30);
   1676 	if (error)
   1677 		goto out;
   1678 
   1679 	/*
   1680 	 * We are now committed to the unmount.
   1681 	 */
   1682 	if ((mntflags & MNT_FORCE) == 0)
   1683 		nfscl_umount(nmp, td);
   1684 	/* Make sure no nfsiods are assigned to this mount. */
   1685 	mtx_lock(&ncl_iod_mutex);
   1686 	for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
   1687 		if (ncl_iodmount[i] == nmp) {
   1688 			ncl_iodwant[i] = NFSIOD_AVAILABLE;
   1689 			ncl_iodmount[i] = NULL;
   1690 		}
   1691 	mtx_unlock(&ncl_iod_mutex);
   1692 	newnfs_disconnect(&nmp->nm_sockreq);
   1693 	crfree(nmp->nm_sockreq.nr_cred);
   1694 	FREE(nmp->nm_nam, M_SONAME);
   1695 	if (nmp->nm_sockreq.nr_auth != NULL)
   1696 		AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
   1697 	mtx_destroy(&nmp->nm_sockreq.nr_mtx);
   1698 	mtx_destroy(&nmp->nm_mtx);
   1699 	TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp)
   1700 		nfscl_freenfsclds(dsp);
   1701 	FREE(nmp, M_NEWNFSMNT);
   1702 out:
   1703 	return (error);
   1704 }
   1705 
   1706 /*
   1707  * Return root of a filesystem
   1708  */
   1709 static int
   1710 nfs_root(struct mount *mp, int flags, struct vnode **vpp)
   1711 {
   1712 	struct vnode *vp;
   1713 	struct nfsmount *nmp;
   1714 	struct nfsnode *np;
   1715 	int error;
   1716 
   1717 	nmp = VFSTONFS(mp);
   1718 	error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, flags);
   1719 	if (error)
   1720 		return error;
   1721 	vp = NFSTOV(np);
   1722 	/*
   1723 	 * Get transfer parameters and attributes for root vnode once.
   1724 	 */
   1725 	mtx_lock(&nmp->nm_mtx);
   1726 	if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
   1727 		mtx_unlock(&nmp->nm_mtx);
   1728 		ncl_fsinfo(nmp, vp, curthread->td_ucred, curthread);
   1729 	} else
   1730 		mtx_unlock(&nmp->nm_mtx);
   1731 	if (vp->v_type == VNON)
   1732 	    vp->v_type = VDIR;
   1733 	vp->v_vflag |= VV_ROOT;
   1734 	*vpp = vp;
   1735 	return (0);
   1736 }
   1737 
   1738 /*
   1739  * Flush out the buffer cache
   1740  */
   1741 /* ARGSUSED */
   1742 static int
   1743 nfs_sync(struct mount *mp, int waitfor)
   1744 {
   1745 	struct vnode *vp, *mvp;
   1746 	struct thread *td;
   1747 	int error, allerror = 0;
   1748 
   1749 	td = curthread;
   1750 
   1751 	MNT_ILOCK(mp);
   1752 	/*
   1753 	 * If a forced dismount is in progress, return from here so that
   1754 	 * the umount(2) syscall doesn't get stuck in VFS_SYNC() before
   1755 	 * calling VFS_UNMOUNT().
   1756 	 */
   1757 	if ((mp->mnt_kern_flag & MNTK_UNMOUNTF) != 0) {
   1758 		MNT_IUNLOCK(mp);
   1759 		return (EBADF);
   1760 	}
   1761 	MNT_IUNLOCK(mp);
   1762 
   1763 	/*
   1764 	 * Force stale buffer cache information to be flushed.
   1765 	 */
   1766 loop:
   1767 	MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
   1768 		/* XXX Racy bv_cnt check. */
   1769 		if (NFSVOPISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
   1770 		    waitfor == MNT_LAZY) {
   1771 			VI_UNLOCK(vp);
   1772 			continue;
   1773 		}
   1774 		if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
   1775 			MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
   1776 			goto loop;
   1777 		}
   1778 		error = VOP_FSYNC(vp, waitfor, td);
   1779 		if (error)
   1780 			allerror = error;
   1781 		NFSVOPUNLOCK(vp, 0);
   1782 		vrele(vp);
   1783 	}
   1784 	return (allerror);
   1785 }
   1786 
   1787 static int
   1788 nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
   1789 {
   1790 	struct nfsmount *nmp = VFSTONFS(mp);
   1791 	struct vfsquery vq;
   1792 	int error;
   1793 
   1794 	bzero(&vq, sizeof(vq));
   1795 	switch (op) {
   1796 #if 0
   1797 	case VFS_CTL_NOLOCKS:
   1798 		val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
   1799  		if (req->oldptr != NULL) {
   1800  			error = SYSCTL_OUT(req, &val, sizeof(val));
   1801  			if (error)
   1802  				return (error);
   1803  		}
   1804  		if (req->newptr != NULL) {
   1805  			error = SYSCTL_IN(req, &val, sizeof(val));
   1806  			if (error)
   1807  				return (error);
   1808 			if (val)
   1809 				nmp->nm_flag |= NFSMNT_NOLOCKS;
   1810 			else
   1811 				nmp->nm_flag &= ~NFSMNT_NOLOCKS;
   1812  		}
   1813 		break;
   1814 #endif
   1815 	case VFS_CTL_QUERY:
   1816 		mtx_lock(&nmp->nm_mtx);
   1817 		if (nmp->nm_state & NFSSTA_TIMEO)
   1818 			vq.vq_flags |= VQ_NOTRESP;
   1819 		mtx_unlock(&nmp->nm_mtx);
   1820 #if 0
   1821 		if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
   1822 		    (nmp->nm_state & NFSSTA_LOCKTIMEO))
   1823 			vq.vq_flags |= VQ_NOTRESPLOCK;
   1824 #endif
   1825 		error = SYSCTL_OUT(req, &vq, sizeof(vq));
   1826 		break;
   1827  	case VFS_CTL_TIMEO:
   1828  		if (req->oldptr != NULL) {
   1829  			error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
   1830  			    sizeof(nmp->nm_tprintf_initial_delay));
   1831  			if (error)
   1832  				return (error);
   1833  		}
   1834  		if (req->newptr != NULL) {
   1835 			error = vfs_suser(mp, req->td);
   1836 			if (error)
   1837 				return (error);
   1838  			error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
   1839  			    sizeof(nmp->nm_tprintf_initial_delay));
   1840  			if (error)
   1841  				return (error);
   1842  			if (nmp->nm_tprintf_initial_delay < 0)
   1843  				nmp->nm_tprintf_initial_delay = 0;
   1844  		}
   1845 		break;
   1846 	default:
   1847 		return (ENOTSUP);
   1848 	}
   1849 	return (0);
   1850 }
   1851 
   1852 /*
   1853  * Purge any RPCs in progress, so that they will all return errors.
   1854  * This allows dounmount() to continue as far as VFS_UNMOUNT() for a
   1855  * forced dismount.
   1856  */
   1857 static void
   1858 nfs_purge(struct mount *mp)
   1859 {
   1860 	struct nfsmount *nmp = VFSTONFS(mp);
   1861 
   1862 	newnfs_nmcancelreqs(nmp);
   1863 }
   1864 
   1865 /*
   1866  * Extract the information needed by the nlm from the nfs vnode.
   1867  */
   1868 static void
   1869 nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp,
   1870     struct sockaddr_storage *sp, int *is_v3p, off_t *sizep,
   1871     struct timeval *timeop)
   1872 {
   1873 	struct nfsmount *nmp;
   1874 	struct nfsnode *np = VTONFS(vp);
   1875 
   1876 	nmp = VFSTONFS(vp->v_mount);
   1877 	if (fhlenp != NULL)
   1878 		*fhlenp = (size_t)np->n_fhp->nfh_len;
   1879 	if (fhp != NULL)
   1880 		bcopy(np->n_fhp->nfh_fh, fhp, np->n_fhp->nfh_len);
   1881 	if (sp != NULL)
   1882 		bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp)));
   1883 	if (is_v3p != NULL)
   1884 		*is_v3p = NFS_ISV3(vp);
   1885 	if (sizep != NULL)
   1886 		*sizep = np->n_size;
   1887 	if (timeop != NULL) {
   1888 		timeop->tv_sec = nmp->nm_timeo / NFS_HZ;
   1889 		timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ);
   1890 	}
   1891 }
   1892 
   1893 /*
   1894  * This function prints out an option name, based on the conditional
   1895  * argument.
   1896  */
   1897 static __inline void nfscl_printopt(struct nfsmount *nmp, int testval,
   1898     char *opt, char **buf, size_t *blen)
   1899 {
   1900 	int len;
   1901 
   1902 	if (testval != 0 && *blen > strlen(opt)) {
   1903 		len = snprintf(*buf, *blen, "%s", opt);
   1904 		if (len != strlen(opt))
   1905 			printf("EEK!!\n");
   1906 		*buf += len;
   1907 		*blen -= len;
   1908 	}
   1909 }
   1910 
   1911 /*
   1912  * This function printf out an options integer value.
   1913  */
   1914 static __inline void nfscl_printoptval(struct nfsmount *nmp, int optval,
   1915     char *opt, char **buf, size_t *blen)
   1916 {
   1917 	int len;
   1918 
   1919 	if (*blen > strlen(opt) + 1) {
   1920 		/* Could result in truncated output string. */
   1921 		len = snprintf(*buf, *blen, "%s=%d", opt, optval);
   1922 		if (len < *blen) {
   1923 			*buf += len;
   1924 			*blen -= len;
   1925 		}
   1926 	}
   1927 }
   1928 
   1929 /*
   1930  * Load the option flags and values into the buffer.
   1931  */
   1932 void nfscl_retopts(struct nfsmount *nmp, char *buffer, size_t buflen)
   1933 {
   1934 	char *buf;
   1935 	size_t blen;
   1936 
   1937 	buf = buffer;
   1938 	blen = buflen;
   1939 	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV4) != 0, "nfsv4", &buf,
   1940 	    &blen);
   1941 	if ((nmp->nm_flag & NFSMNT_NFSV4) != 0) {
   1942 		nfscl_printoptval(nmp, nmp->nm_minorvers, ",minorversion", &buf,
   1943 		    &blen);
   1944 		nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_PNFS) != 0, ",pnfs",
   1945 		    &buf, &blen);
   1946 	}
   1947 	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV3) != 0, "nfsv3", &buf,
   1948 	    &blen);
   1949 	nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0,
   1950 	    "nfsv2", &buf, &blen);
   1951 	nfscl_printopt(nmp, nmp->nm_sotype == SOCK_STREAM, ",tcp", &buf, &blen);
   1952 	nfscl_printopt(nmp, nmp->nm_sotype != SOCK_STREAM, ",udp", &buf, &blen);
   1953 	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RESVPORT) != 0, ",resvport",
   1954 	    &buf, &blen);
   1955 	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCONN) != 0, ",noconn",
   1956 	    &buf, &blen);
   1957 	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) == 0, ",hard", &buf,
   1958 	    &blen);
   1959 	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) != 0, ",soft", &buf,
   1960 	    &blen);
   1961 	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_INT) != 0, ",intr", &buf,
   1962 	    &blen);
   1963 	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) == 0, ",cto", &buf,
   1964 	    &blen);
   1965 	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) != 0, ",nocto", &buf,
   1966 	    &blen);
   1967 	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NONCONTIGWR) != 0,
   1968 	    ",noncontigwr", &buf, &blen);
   1969 	nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
   1970 	    0, ",lockd", &buf, &blen);
   1971 	nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
   1972 	    NFSMNT_NOLOCKD, ",nolockd", &buf, &blen);
   1973 	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RDIRPLUS) != 0, ",rdirplus",
   1974 	    &buf, &blen);
   1975 	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_KERB) == 0, ",sec=sys",
   1976 	    &buf, &blen);
   1977 	nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
   1978 	    NFSMNT_PRIVACY)) == NFSMNT_KERB, ",sec=krb5", &buf, &blen);
   1979 	nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
   1980 	    NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_INTEGRITY), ",sec=krb5i",
   1981 	    &buf, &blen);
   1982 	nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
   1983 	    NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_PRIVACY), ",sec=krb5p",
   1984 	    &buf, &blen);
   1985 	nfscl_printoptval(nmp, nmp->nm_acdirmin, ",acdirmin", &buf, &blen);
   1986 	nfscl_printoptval(nmp, nmp->nm_acdirmax, ",acdirmax", &buf, &blen);
   1987 	nfscl_printoptval(nmp, nmp->nm_acregmin, ",acregmin", &buf, &blen);
   1988 	nfscl_printoptval(nmp, nmp->nm_acregmax, ",acregmax", &buf, &blen);
   1989 	nfscl_printoptval(nmp, nmp->nm_nametimeo, ",nametimeo", &buf, &blen);
   1990 	nfscl_printoptval(nmp, nmp->nm_negnametimeo, ",negnametimeo", &buf,
   1991 	    &blen);
   1992 	nfscl_printoptval(nmp, nmp->nm_rsize, ",rsize", &buf, &blen);
   1993 	nfscl_printoptval(nmp, nmp->nm_wsize, ",wsize", &buf, &blen);
   1994 	nfscl_printoptval(nmp, nmp->nm_readdirsize, ",readdirsize", &buf,
   1995 	    &blen);
   1996 	nfscl_printoptval(nmp, nmp->nm_readahead, ",readahead", &buf, &blen);
   1997 	nfscl_printoptval(nmp, nmp->nm_wcommitsize, ",wcommitsize", &buf,
   1998 	    &blen);
   1999 	nfscl_printoptval(nmp, nmp->nm_timeo, ",timeout", &buf, &blen);
   2000 	nfscl_printoptval(nmp, nmp->nm_retry, ",retrans", &buf, &blen);
   2001 }
   2002 
   2003