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