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