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