nfs_clvfsops.c revision 260107
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: stable/10/sys/fs/nfsclient/nfs_clvfsops.c 260107 2013-12-30 21:17:20Z rmacklem $");
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", "noncontigwr", "pnfs",
723    "wcommitsize",
724    NULL };
725
726/*
727 * VFS Operations.
728 *
729 * mount system call
730 * It seems a bit dumb to copyinstr() the host and path here and then
731 * bcopy() them in mountnfs(), but I wanted to detect errors before
732 * doing the sockargs() call because sockargs() allocates an mbuf and
733 * an error after that means that I have to release the mbuf.
734 */
735/* ARGSUSED */
736static int
737nfs_mount(struct mount *mp)
738{
739	struct nfs_args args = {
740	    .version = NFS_ARGSVERSION,
741	    .addr = NULL,
742	    .addrlen = sizeof (struct sockaddr_in),
743	    .sotype = SOCK_STREAM,
744	    .proto = 0,
745	    .fh = NULL,
746	    .fhsize = 0,
747	    .flags = NFSMNT_RESVPORT,
748	    .wsize = NFS_WSIZE,
749	    .rsize = NFS_RSIZE,
750	    .readdirsize = NFS_READDIRSIZE,
751	    .timeo = 10,
752	    .retrans = NFS_RETRANS,
753	    .readahead = NFS_DEFRAHEAD,
754	    .wcommitsize = 0,			/* was: NQ_DEFLEASE */
755	    .hostname = NULL,
756	    .acregmin = NFS_MINATTRTIMO,
757	    .acregmax = NFS_MAXATTRTIMO,
758	    .acdirmin = NFS_MINDIRATTRTIMO,
759	    .acdirmax = NFS_MAXDIRATTRTIMO,
760	};
761	int error = 0, ret, len;
762	struct sockaddr *nam = NULL;
763	struct vnode *vp;
764	struct thread *td;
765	char hst[MNAMELEN];
766	u_char nfh[NFSX_FHMAX], krbname[100], dirpath[100], srvkrbname[100];
767	char *opt, *name, *secname;
768	int nametimeo = NFS_DEFAULT_NAMETIMEO;
769	int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
770	int minvers = 0;
771	int dirlen, has_nfs_args_opt, krbnamelen, srvkrbnamelen;
772	size_t hstlen;
773
774	has_nfs_args_opt = 0;
775	if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
776		error = EINVAL;
777		goto out;
778	}
779
780	td = curthread;
781	if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS) {
782		error = nfs_mountroot(mp);
783		goto out;
784	}
785
786	nfscl_init();
787
788	/*
789	 * The old mount_nfs program passed the struct nfs_args
790	 * from userspace to kernel.  The new mount_nfs program
791	 * passes string options via nmount() from userspace to kernel
792	 * and we populate the struct nfs_args in the kernel.
793	 */
794	if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
795		error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
796		    sizeof(args));
797		if (error != 0)
798			goto out;
799
800		if (args.version != NFS_ARGSVERSION) {
801			error = EPROGMISMATCH;
802			goto out;
803		}
804		has_nfs_args_opt = 1;
805	}
806
807	/* Handle the new style options. */
808	if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
809		args.flags |= NFSMNT_NOCONN;
810	if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
811		args.flags |= NFSMNT_NOCONN;
812	if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
813		args.flags |= NFSMNT_NOLOCKD;
814	if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
815		args.flags &= ~NFSMNT_NOLOCKD;
816	if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
817		args.flags |= NFSMNT_INT;
818	if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
819		args.flags |= NFSMNT_RDIRPLUS;
820	if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
821		args.flags |= NFSMNT_RESVPORT;
822	if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
823		args.flags &= ~NFSMNT_RESVPORT;
824	if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
825		args.flags |= NFSMNT_SOFT;
826	if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
827		args.flags &= ~NFSMNT_SOFT;
828	if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
829		args.sotype = SOCK_DGRAM;
830	if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
831		args.sotype = SOCK_DGRAM;
832	if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
833		args.sotype = SOCK_STREAM;
834	if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
835		args.flags |= NFSMNT_NFSV3;
836	if (vfs_getopt(mp->mnt_optnew, "nfsv4", NULL, NULL) == 0) {
837		args.flags |= NFSMNT_NFSV4;
838		args.sotype = SOCK_STREAM;
839	}
840	if (vfs_getopt(mp->mnt_optnew, "allgssname", NULL, NULL) == 0)
841		args.flags |= NFSMNT_ALLGSSNAME;
842	if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0)
843		args.flags |= NFSMNT_NOCTO;
844	if (vfs_getopt(mp->mnt_optnew, "noncontigwr", NULL, NULL) == 0)
845		args.flags |= NFSMNT_NONCONTIGWR;
846	if (vfs_getopt(mp->mnt_optnew, "pnfs", NULL, NULL) == 0)
847		args.flags |= NFSMNT_PNFS;
848	if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
849		if (opt == NULL) {
850			vfs_mount_error(mp, "illegal readdirsize");
851			error = EINVAL;
852			goto out;
853		}
854		ret = sscanf(opt, "%d", &args.readdirsize);
855		if (ret != 1 || args.readdirsize <= 0) {
856			vfs_mount_error(mp, "illegal readdirsize: %s",
857			    opt);
858			error = EINVAL;
859			goto out;
860		}
861		args.flags |= NFSMNT_READDIRSIZE;
862	}
863	if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
864		if (opt == NULL) {
865			vfs_mount_error(mp, "illegal readahead");
866			error = EINVAL;
867			goto out;
868		}
869		ret = sscanf(opt, "%d", &args.readahead);
870		if (ret != 1 || args.readahead <= 0) {
871			vfs_mount_error(mp, "illegal readahead: %s",
872			    opt);
873			error = EINVAL;
874			goto out;
875		}
876		args.flags |= NFSMNT_READAHEAD;
877	}
878	if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
879		if (opt == NULL) {
880			vfs_mount_error(mp, "illegal wsize");
881			error = EINVAL;
882			goto out;
883		}
884		ret = sscanf(opt, "%d", &args.wsize);
885		if (ret != 1 || args.wsize <= 0) {
886			vfs_mount_error(mp, "illegal wsize: %s",
887			    opt);
888			error = EINVAL;
889			goto out;
890		}
891		args.flags |= NFSMNT_WSIZE;
892	}
893	if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
894		if (opt == NULL) {
895			vfs_mount_error(mp, "illegal rsize");
896			error = EINVAL;
897			goto out;
898		}
899		ret = sscanf(opt, "%d", &args.rsize);
900		if (ret != 1 || args.rsize <= 0) {
901			vfs_mount_error(mp, "illegal wsize: %s",
902			    opt);
903			error = EINVAL;
904			goto out;
905		}
906		args.flags |= NFSMNT_RSIZE;
907	}
908	if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
909		if (opt == NULL) {
910			vfs_mount_error(mp, "illegal retrans");
911			error = EINVAL;
912			goto out;
913		}
914		ret = sscanf(opt, "%d", &args.retrans);
915		if (ret != 1 || args.retrans <= 0) {
916			vfs_mount_error(mp, "illegal retrans: %s",
917			    opt);
918			error = EINVAL;
919			goto out;
920		}
921		args.flags |= NFSMNT_RETRANS;
922	}
923	if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
924		ret = sscanf(opt, "%d", &args.acregmin);
925		if (ret != 1 || args.acregmin < 0) {
926			vfs_mount_error(mp, "illegal acregmin: %s",
927			    opt);
928			error = EINVAL;
929			goto out;
930		}
931		args.flags |= NFSMNT_ACREGMIN;
932	}
933	if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
934		ret = sscanf(opt, "%d", &args.acregmax);
935		if (ret != 1 || args.acregmax < 0) {
936			vfs_mount_error(mp, "illegal acregmax: %s",
937			    opt);
938			error = EINVAL;
939			goto out;
940		}
941		args.flags |= NFSMNT_ACREGMAX;
942	}
943	if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
944		ret = sscanf(opt, "%d", &args.acdirmin);
945		if (ret != 1 || args.acdirmin < 0) {
946			vfs_mount_error(mp, "illegal acdirmin: %s",
947			    opt);
948			error = EINVAL;
949			goto out;
950		}
951		args.flags |= NFSMNT_ACDIRMIN;
952	}
953	if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
954		ret = sscanf(opt, "%d", &args.acdirmax);
955		if (ret != 1 || args.acdirmax < 0) {
956			vfs_mount_error(mp, "illegal acdirmax: %s",
957			    opt);
958			error = EINVAL;
959			goto out;
960		}
961		args.flags |= NFSMNT_ACDIRMAX;
962	}
963	if (vfs_getopt(mp->mnt_optnew, "wcommitsize", (void **)&opt, NULL) == 0) {
964		ret = sscanf(opt, "%d", &args.wcommitsize);
965		if (ret != 1 || args.wcommitsize < 0) {
966			vfs_mount_error(mp, "illegal wcommitsize: %s", opt);
967			error = EINVAL;
968			goto out;
969		}
970		args.flags |= NFSMNT_WCOMMITSIZE;
971	}
972	if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
973		ret = sscanf(opt, "%d", &args.timeo);
974		if (ret != 1 || args.timeo <= 0) {
975			vfs_mount_error(mp, "illegal timeout: %s",
976			    opt);
977			error = EINVAL;
978			goto out;
979		}
980		args.flags |= NFSMNT_TIMEO;
981	}
982	if (vfs_getopt(mp->mnt_optnew, "nametimeo", (void **)&opt, NULL) == 0) {
983		ret = sscanf(opt, "%d", &nametimeo);
984		if (ret != 1 || nametimeo < 0) {
985			vfs_mount_error(mp, "illegal nametimeo: %s", opt);
986			error = EINVAL;
987			goto out;
988		}
989	}
990	if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
991	    == 0) {
992		ret = sscanf(opt, "%d", &negnametimeo);
993		if (ret != 1 || negnametimeo < 0) {
994			vfs_mount_error(mp, "illegal negnametimeo: %s",
995			    opt);
996			error = EINVAL;
997			goto out;
998		}
999	}
1000	if (vfs_getopt(mp->mnt_optnew, "minorversion", (void **)&opt, NULL) ==
1001	    0) {
1002		ret = sscanf(opt, "%d", &minvers);
1003		if (ret != 1 || minvers < 0 || minvers > 1 ||
1004		    (args.flags & NFSMNT_NFSV4) == 0) {
1005			vfs_mount_error(mp, "illegal minorversion: %s", opt);
1006			error = EINVAL;
1007			goto out;
1008		}
1009	}
1010	if (vfs_getopt(mp->mnt_optnew, "sec",
1011		(void **) &secname, NULL) == 0)
1012		nfs_sec_name(secname, &args.flags);
1013
1014	if (mp->mnt_flag & MNT_UPDATE) {
1015		struct nfsmount *nmp = VFSTONFS(mp);
1016
1017		if (nmp == NULL) {
1018			error = EIO;
1019			goto out;
1020		}
1021
1022		/*
1023		 * If a change from TCP->UDP is done and there are thread(s)
1024		 * that have I/O RPC(s) in progress with a tranfer size
1025		 * greater than NFS_MAXDGRAMDATA, those thread(s) will be
1026		 * hung, retrying the RPC(s) forever. Usually these threads
1027		 * will be seen doing an uninterruptible sleep on wait channel
1028		 * "newnfsreq" (truncated to "newnfsre" by procstat).
1029		 */
1030		if (args.sotype == SOCK_DGRAM && nmp->nm_sotype == SOCK_STREAM)
1031			tprintf(td->td_proc, LOG_WARNING,
1032	"Warning: mount -u that changes TCP->UDP can result in hung threads\n");
1033
1034		/*
1035		 * When doing an update, we can't change version,
1036		 * security, switch lockd strategies or change cookie
1037		 * translation
1038		 */
1039		args.flags = (args.flags &
1040		    ~(NFSMNT_NFSV3 |
1041		      NFSMNT_NFSV4 |
1042		      NFSMNT_KERB |
1043		      NFSMNT_INTEGRITY |
1044		      NFSMNT_PRIVACY |
1045		      NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
1046		    (nmp->nm_flag &
1047			(NFSMNT_NFSV3 |
1048			 NFSMNT_NFSV4 |
1049			 NFSMNT_KERB |
1050			 NFSMNT_INTEGRITY |
1051			 NFSMNT_PRIVACY |
1052			 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
1053		nfs_decode_args(mp, nmp, &args, NULL, td->td_ucred, td);
1054		goto out;
1055	}
1056
1057	/*
1058	 * Make the nfs_ip_paranoia sysctl serve as the default connection
1059	 * or no-connection mode for those protocols that support
1060	 * no-connection mode (the flag will be cleared later for protocols
1061	 * that do not support no-connection mode).  This will allow a client
1062	 * to receive replies from a different IP then the request was
1063	 * sent to.  Note: default value for nfs_ip_paranoia is 1 (paranoid),
1064	 * not 0.
1065	 */
1066	if (nfs_ip_paranoia == 0)
1067		args.flags |= NFSMNT_NOCONN;
1068
1069	if (has_nfs_args_opt != 0) {
1070		/*
1071		 * In the 'nfs_args' case, the pointers in the args
1072		 * structure are in userland - we copy them in here.
1073		 */
1074		if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
1075			vfs_mount_error(mp, "Bad file handle");
1076			error = EINVAL;
1077			goto out;
1078		}
1079		error = copyin((caddr_t)args.fh, (caddr_t)nfh,
1080		    args.fhsize);
1081		if (error != 0)
1082			goto out;
1083		error = copyinstr(args.hostname, hst, MNAMELEN - 1, &hstlen);
1084		if (error != 0)
1085			goto out;
1086		bzero(&hst[hstlen], MNAMELEN - hstlen);
1087		args.hostname = hst;
1088		/* sockargs() call must be after above copyin() calls */
1089		error = getsockaddr(&nam, (caddr_t)args.addr,
1090		    args.addrlen);
1091		if (error != 0)
1092			goto out;
1093	} else {
1094		if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
1095		    &args.fhsize) == 0) {
1096			if (args.fhsize < 0 || args.fhsize > NFSX_FHMAX) {
1097				vfs_mount_error(mp, "Bad file handle");
1098				error = EINVAL;
1099				goto out;
1100			}
1101			bcopy(args.fh, nfh, args.fhsize);
1102		} else {
1103			args.fhsize = 0;
1104		}
1105		(void) vfs_getopt(mp->mnt_optnew, "hostname",
1106		    (void **)&args.hostname, &len);
1107		if (args.hostname == NULL) {
1108			vfs_mount_error(mp, "Invalid hostname");
1109			error = EINVAL;
1110			goto out;
1111		}
1112		bcopy(args.hostname, hst, MNAMELEN);
1113		hst[MNAMELEN - 1] = '\0';
1114	}
1115
1116	if (vfs_getopt(mp->mnt_optnew, "principal", (void **)&name, NULL) == 0)
1117		strlcpy(srvkrbname, name, sizeof (srvkrbname));
1118	else
1119		snprintf(srvkrbname, sizeof (srvkrbname), "nfs@%s", hst);
1120	srvkrbnamelen = strlen(srvkrbname);
1121
1122	if (vfs_getopt(mp->mnt_optnew, "gssname", (void **)&name, NULL) == 0)
1123		strlcpy(krbname, name, sizeof (krbname));
1124	else
1125		krbname[0] = '\0';
1126	krbnamelen = strlen(krbname);
1127
1128	if (vfs_getopt(mp->mnt_optnew, "dirpath", (void **)&name, NULL) == 0)
1129		strlcpy(dirpath, name, sizeof (dirpath));
1130	else
1131		dirpath[0] = '\0';
1132	dirlen = strlen(dirpath);
1133
1134	if (has_nfs_args_opt == 0) {
1135		if (vfs_getopt(mp->mnt_optnew, "addr",
1136		    (void **)&args.addr, &args.addrlen) == 0) {
1137			if (args.addrlen > SOCK_MAXADDRLEN) {
1138				error = ENAMETOOLONG;
1139				goto out;
1140			}
1141			nam = malloc(args.addrlen, M_SONAME, M_WAITOK);
1142			bcopy(args.addr, nam, args.addrlen);
1143			nam->sa_len = args.addrlen;
1144		} else {
1145			vfs_mount_error(mp, "No server address");
1146			error = EINVAL;
1147			goto out;
1148		}
1149	}
1150
1151	args.fh = nfh;
1152	error = mountnfs(&args, mp, nam, hst, krbname, krbnamelen, dirpath,
1153	    dirlen, srvkrbname, srvkrbnamelen, &vp, td->td_ucred, td,
1154	    nametimeo, negnametimeo, minvers);
1155out:
1156	if (!error) {
1157		MNT_ILOCK(mp);
1158		mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED | MNTK_NO_IOPF;
1159		MNT_IUNLOCK(mp);
1160	}
1161	return (error);
1162}
1163
1164
1165/*
1166 * VFS Operations.
1167 *
1168 * mount system call
1169 * It seems a bit dumb to copyinstr() the host and path here and then
1170 * bcopy() them in mountnfs(), but I wanted to detect errors before
1171 * doing the sockargs() call because sockargs() allocates an mbuf and
1172 * an error after that means that I have to release the mbuf.
1173 */
1174/* ARGSUSED */
1175static int
1176nfs_cmount(struct mntarg *ma, void *data, uint64_t flags)
1177{
1178	int error;
1179	struct nfs_args args;
1180
1181	error = copyin(data, &args, sizeof (struct nfs_args));
1182	if (error)
1183		return error;
1184
1185	ma = mount_arg(ma, "nfs_args", &args, sizeof args);
1186
1187	error = kernel_mount(ma, flags);
1188	return (error);
1189}
1190
1191/*
1192 * Common code for mount and mountroot
1193 */
1194static int
1195mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
1196    char *hst, u_char *krbname, int krbnamelen, u_char *dirpath, int dirlen,
1197    u_char *srvkrbname, int srvkrbnamelen, struct vnode **vpp,
1198    struct ucred *cred, struct thread *td, int nametimeo, int negnametimeo,
1199    int minvers)
1200{
1201	struct nfsmount *nmp;
1202	struct nfsnode *np;
1203	int error, trycnt, ret;
1204	struct nfsvattr nfsva;
1205	struct nfsclclient *clp;
1206	struct nfsclds *dsp, *tdsp;
1207	uint32_t lease;
1208	static u_int64_t clval = 0;
1209
1210	NFSCL_DEBUG(3, "in mnt\n");
1211	clp = NULL;
1212	if (mp->mnt_flag & MNT_UPDATE) {
1213		nmp = VFSTONFS(mp);
1214		printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
1215		FREE(nam, M_SONAME);
1216		return (0);
1217	} else {
1218		MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount) +
1219		    krbnamelen + dirlen + srvkrbnamelen + 2,
1220		    M_NEWNFSMNT, M_WAITOK | M_ZERO);
1221		TAILQ_INIT(&nmp->nm_bufq);
1222		if (clval == 0)
1223			clval = (u_int64_t)nfsboottime.tv_sec;
1224		nmp->nm_clval = clval++;
1225		nmp->nm_krbnamelen = krbnamelen;
1226		nmp->nm_dirpathlen = dirlen;
1227		nmp->nm_srvkrbnamelen = srvkrbnamelen;
1228		if (td->td_ucred->cr_uid != (uid_t)0) {
1229			/*
1230			 * nm_uid is used to get KerberosV credentials for
1231			 * the nfsv4 state handling operations if there is
1232			 * no host based principal set. Use the uid of
1233			 * this user if not root, since they are doing the
1234			 * mount. I don't think setting this for root will
1235			 * work, since root normally does not have user
1236			 * credentials in a credentials cache.
1237			 */
1238			nmp->nm_uid = td->td_ucred->cr_uid;
1239		} else {
1240			/*
1241			 * Just set to -1, so it won't be used.
1242			 */
1243			nmp->nm_uid = (uid_t)-1;
1244		}
1245
1246		/* Copy and null terminate all the names */
1247		if (nmp->nm_krbnamelen > 0) {
1248			bcopy(krbname, nmp->nm_krbname, nmp->nm_krbnamelen);
1249			nmp->nm_name[nmp->nm_krbnamelen] = '\0';
1250		}
1251		if (nmp->nm_dirpathlen > 0) {
1252			bcopy(dirpath, NFSMNT_DIRPATH(nmp),
1253			    nmp->nm_dirpathlen);
1254			nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1255			    + 1] = '\0';
1256		}
1257		if (nmp->nm_srvkrbnamelen > 0) {
1258			bcopy(srvkrbname, NFSMNT_SRVKRBNAME(nmp),
1259			    nmp->nm_srvkrbnamelen);
1260			nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1261			    + nmp->nm_srvkrbnamelen + 2] = '\0';
1262		}
1263		nmp->nm_sockreq.nr_cred = crhold(cred);
1264		mtx_init(&nmp->nm_sockreq.nr_mtx, "nfssock", NULL, MTX_DEF);
1265		mp->mnt_data = nmp;
1266		nmp->nm_getinfo = nfs_getnlminfo;
1267		nmp->nm_vinvalbuf = ncl_vinvalbuf;
1268	}
1269	vfs_getnewfsid(mp);
1270	nmp->nm_mountp = mp;
1271	mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF | MTX_DUPOK);
1272
1273	/*
1274	 * Since nfs_decode_args() might optionally set them, these
1275	 * need to be set to defaults before the call, so that the
1276	 * optional settings aren't overwritten.
1277	 */
1278	nmp->nm_nametimeo = nametimeo;
1279	nmp->nm_negnametimeo = negnametimeo;
1280	nmp->nm_timeo = NFS_TIMEO;
1281	nmp->nm_retry = NFS_RETRANS;
1282	nmp->nm_readahead = NFS_DEFRAHEAD;
1283	if (desiredvnodes >= 11000)
1284		nmp->nm_wcommitsize = hibufspace / (desiredvnodes / 1000);
1285	else
1286		nmp->nm_wcommitsize = hibufspace / 10;
1287	if ((argp->flags & NFSMNT_NFSV4) != 0)
1288		nmp->nm_minorvers = minvers;
1289	else
1290		nmp->nm_minorvers = 0;
1291
1292	nfs_decode_args(mp, nmp, argp, hst, cred, td);
1293
1294	/*
1295	 * V2 can only handle 32 bit filesizes.  A 4GB-1 limit may be too
1296	 * high, depending on whether we end up with negative offsets in
1297	 * the client or server somewhere.  2GB-1 may be safer.
1298	 *
1299	 * For V3, ncl_fsinfo will adjust this as necessary.  Assume maximum
1300	 * that we can handle until we find out otherwise.
1301	 */
1302	if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0)
1303		nmp->nm_maxfilesize = 0xffffffffLL;
1304	else
1305		nmp->nm_maxfilesize = OFF_MAX;
1306
1307	if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
1308		nmp->nm_wsize = NFS_WSIZE;
1309		nmp->nm_rsize = NFS_RSIZE;
1310		nmp->nm_readdirsize = NFS_READDIRSIZE;
1311	}
1312	nmp->nm_numgrps = NFS_MAXGRPS;
1313	nmp->nm_tprintf_delay = nfs_tprintf_delay;
1314	if (nmp->nm_tprintf_delay < 0)
1315		nmp->nm_tprintf_delay = 0;
1316	nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
1317	if (nmp->nm_tprintf_initial_delay < 0)
1318		nmp->nm_tprintf_initial_delay = 0;
1319	nmp->nm_fhsize = argp->fhsize;
1320	if (nmp->nm_fhsize > 0)
1321		bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
1322	bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
1323	nmp->nm_nam = nam;
1324	/* Set up the sockets and per-host congestion */
1325	nmp->nm_sotype = argp->sotype;
1326	nmp->nm_soproto = argp->proto;
1327	nmp->nm_sockreq.nr_prog = NFS_PROG;
1328	if ((argp->flags & NFSMNT_NFSV4))
1329		nmp->nm_sockreq.nr_vers = NFS_VER4;
1330	else if ((argp->flags & NFSMNT_NFSV3))
1331		nmp->nm_sockreq.nr_vers = NFS_VER3;
1332	else
1333		nmp->nm_sockreq.nr_vers = NFS_VER2;
1334
1335
1336	if ((error = newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0)))
1337		goto bad;
1338	/* For NFSv4.1, get the clientid now. */
1339	if (nmp->nm_minorvers > 0) {
1340		NFSCL_DEBUG(3, "at getcl\n");
1341		error = nfscl_getcl(mp, cred, td, 0, &clp);
1342		NFSCL_DEBUG(3, "aft getcl=%d\n", error);
1343		if (error != 0)
1344			goto bad;
1345	}
1346
1347	if (nmp->nm_fhsize == 0 && (nmp->nm_flag & NFSMNT_NFSV4) &&
1348	    nmp->nm_dirpathlen > 0) {
1349		NFSCL_DEBUG(3, "in dirp\n");
1350		/*
1351		 * If the fhsize on the mount point == 0 for V4, the mount
1352		 * path needs to be looked up.
1353		 */
1354		trycnt = 3;
1355		do {
1356			error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp),
1357			    cred, td);
1358			NFSCL_DEBUG(3, "aft dirp=%d\n", error);
1359			if (error)
1360				(void) nfs_catnap(PZERO, error, "nfsgetdirp");
1361		} while (error && --trycnt > 0);
1362		if (error) {
1363			error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
1364			goto bad;
1365		}
1366	}
1367
1368	/*
1369	 * A reference count is needed on the nfsnode representing the
1370	 * remote root.  If this object is not persistent, then backward
1371	 * traversals of the mount point (i.e. "..") will not work if
1372	 * the nfsnode gets flushed out of the cache. Ufs does not have
1373	 * this problem, because one can identify root inodes by their
1374	 * number == ROOTINO (2).
1375	 */
1376	if (nmp->nm_fhsize > 0) {
1377		/*
1378		 * Set f_iosize to NFS_DIRBLKSIZ so that bo_bsize gets set
1379		 * non-zero for the root vnode. f_iosize will be set correctly
1380		 * by nfs_statfs() before any I/O occurs.
1381		 */
1382		mp->mnt_stat.f_iosize = NFS_DIRBLKSIZ;
1383		error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np,
1384		    LK_EXCLUSIVE);
1385		if (error)
1386			goto bad;
1387		*vpp = NFSTOV(np);
1388
1389		/*
1390		 * Get file attributes and transfer parameters for the
1391		 * mountpoint.  This has the side effect of filling in
1392		 * (*vpp)->v_type with the correct value.
1393		 */
1394		ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
1395		    cred, td, &nfsva, NULL, &lease);
1396		if (ret) {
1397			/*
1398			 * Just set default values to get things going.
1399			 */
1400			NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
1401			nfsva.na_vattr.va_type = VDIR;
1402			nfsva.na_vattr.va_mode = 0777;
1403			nfsva.na_vattr.va_nlink = 100;
1404			nfsva.na_vattr.va_uid = (uid_t)0;
1405			nfsva.na_vattr.va_gid = (gid_t)0;
1406			nfsva.na_vattr.va_fileid = 2;
1407			nfsva.na_vattr.va_gen = 1;
1408			nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
1409			nfsva.na_vattr.va_size = 512 * 1024;
1410			lease = 60;
1411		}
1412		(void) nfscl_loadattrcache(vpp, &nfsva, NULL, NULL, 0, 1);
1413		if (nmp->nm_minorvers > 0) {
1414			NFSCL_DEBUG(3, "lease=%d\n", (int)lease);
1415			NFSLOCKCLSTATE();
1416			clp->nfsc_renew = NFSCL_RENEW(lease);
1417			clp->nfsc_expire = NFSD_MONOSEC + clp->nfsc_renew;
1418			clp->nfsc_clientidrev++;
1419			if (clp->nfsc_clientidrev == 0)
1420				clp->nfsc_clientidrev++;
1421			NFSUNLOCKCLSTATE();
1422			/*
1423			 * Mount will succeed, so the renew thread can be
1424			 * started now.
1425			 */
1426			nfscl_start_renewthread(clp);
1427			nfscl_clientrelease(clp);
1428		}
1429		if (argp->flags & NFSMNT_NFSV3)
1430			ncl_fsinfo(nmp, *vpp, cred, td);
1431
1432		/* Mark if the mount point supports NFSv4 ACLs. */
1433		if ((argp->flags & NFSMNT_NFSV4) != 0 && nfsrv_useacl != 0 &&
1434		    ret == 0 &&
1435		    NFSISSET_ATTRBIT(&nfsva.na_suppattr, NFSATTRBIT_ACL)) {
1436			MNT_ILOCK(mp);
1437			mp->mnt_flag |= MNT_NFS4ACLS;
1438			MNT_IUNLOCK(mp);
1439		}
1440
1441		/*
1442		 * Lose the lock but keep the ref.
1443		 */
1444		NFSVOPUNLOCK(*vpp, 0);
1445		return (0);
1446	}
1447	error = EIO;
1448
1449bad:
1450	if (clp != NULL)
1451		nfscl_clientrelease(clp);
1452	newnfs_disconnect(&nmp->nm_sockreq);
1453	crfree(nmp->nm_sockreq.nr_cred);
1454	if (nmp->nm_sockreq.nr_auth != NULL)
1455		AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
1456	mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1457	mtx_destroy(&nmp->nm_mtx);
1458	if (nmp->nm_clp != NULL) {
1459		NFSLOCKCLSTATE();
1460		LIST_REMOVE(nmp->nm_clp, nfsc_list);
1461		NFSUNLOCKCLSTATE();
1462		free(nmp->nm_clp, M_NFSCLCLIENT);
1463	}
1464	TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp)
1465		nfscl_freenfsclds(dsp);
1466	FREE(nmp, M_NEWNFSMNT);
1467	FREE(nam, M_SONAME);
1468	return (error);
1469}
1470
1471/*
1472 * unmount system call
1473 */
1474static int
1475nfs_unmount(struct mount *mp, int mntflags)
1476{
1477	struct thread *td;
1478	struct nfsmount *nmp;
1479	int error, flags = 0, i, trycnt = 0;
1480	struct nfsclds *dsp, *tdsp;
1481
1482	td = curthread;
1483
1484	if (mntflags & MNT_FORCE)
1485		flags |= FORCECLOSE;
1486	nmp = VFSTONFS(mp);
1487	/*
1488	 * Goes something like this..
1489	 * - Call vflush() to clear out vnodes for this filesystem
1490	 * - Close the socket
1491	 * - Free up the data structures
1492	 */
1493	/* In the forced case, cancel any outstanding requests. */
1494	if (mntflags & MNT_FORCE) {
1495		error = newnfs_nmcancelreqs(nmp);
1496		if (error)
1497			goto out;
1498		/* For a forced close, get rid of the renew thread now */
1499		nfscl_umount(nmp, td);
1500	}
1501	/* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
1502	do {
1503		error = vflush(mp, 1, flags, td);
1504		if ((mntflags & MNT_FORCE) && error != 0 && ++trycnt < 30)
1505			(void) nfs_catnap(PSOCK, error, "newndm");
1506	} while ((mntflags & MNT_FORCE) && error != 0 && trycnt < 30);
1507	if (error)
1508		goto out;
1509
1510	/*
1511	 * We are now committed to the unmount.
1512	 */
1513	if ((mntflags & MNT_FORCE) == 0)
1514		nfscl_umount(nmp, td);
1515	/* Make sure no nfsiods are assigned to this mount. */
1516	mtx_lock(&ncl_iod_mutex);
1517	for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
1518		if (ncl_iodmount[i] == nmp) {
1519			ncl_iodwant[i] = NFSIOD_AVAILABLE;
1520			ncl_iodmount[i] = NULL;
1521		}
1522	mtx_unlock(&ncl_iod_mutex);
1523	newnfs_disconnect(&nmp->nm_sockreq);
1524	crfree(nmp->nm_sockreq.nr_cred);
1525	FREE(nmp->nm_nam, M_SONAME);
1526	if (nmp->nm_sockreq.nr_auth != NULL)
1527		AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
1528	mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1529	mtx_destroy(&nmp->nm_mtx);
1530	TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp)
1531		nfscl_freenfsclds(dsp);
1532	FREE(nmp, M_NEWNFSMNT);
1533out:
1534	return (error);
1535}
1536
1537/*
1538 * Return root of a filesystem
1539 */
1540static int
1541nfs_root(struct mount *mp, int flags, struct vnode **vpp)
1542{
1543	struct vnode *vp;
1544	struct nfsmount *nmp;
1545	struct nfsnode *np;
1546	int error;
1547
1548	nmp = VFSTONFS(mp);
1549	error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, flags);
1550	if (error)
1551		return error;
1552	vp = NFSTOV(np);
1553	/*
1554	 * Get transfer parameters and attributes for root vnode once.
1555	 */
1556	mtx_lock(&nmp->nm_mtx);
1557	if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
1558		mtx_unlock(&nmp->nm_mtx);
1559		ncl_fsinfo(nmp, vp, curthread->td_ucred, curthread);
1560	} else
1561		mtx_unlock(&nmp->nm_mtx);
1562	if (vp->v_type == VNON)
1563	    vp->v_type = VDIR;
1564	vp->v_vflag |= VV_ROOT;
1565	*vpp = vp;
1566	return (0);
1567}
1568
1569/*
1570 * Flush out the buffer cache
1571 */
1572/* ARGSUSED */
1573static int
1574nfs_sync(struct mount *mp, int waitfor)
1575{
1576	struct vnode *vp, *mvp;
1577	struct thread *td;
1578	int error, allerror = 0;
1579
1580	td = curthread;
1581
1582	MNT_ILOCK(mp);
1583	/*
1584	 * If a forced dismount is in progress, return from here so that
1585	 * the umount(2) syscall doesn't get stuck in VFS_SYNC() before
1586	 * calling VFS_UNMOUNT().
1587	 */
1588	if ((mp->mnt_kern_flag & MNTK_UNMOUNTF) != 0) {
1589		MNT_IUNLOCK(mp);
1590		return (EBADF);
1591	}
1592	MNT_IUNLOCK(mp);
1593
1594	/*
1595	 * Force stale buffer cache information to be flushed.
1596	 */
1597loop:
1598	MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
1599		/* XXX Racy bv_cnt check. */
1600		if (NFSVOPISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
1601		    waitfor == MNT_LAZY) {
1602			VI_UNLOCK(vp);
1603			continue;
1604		}
1605		if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
1606			MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
1607			goto loop;
1608		}
1609		error = VOP_FSYNC(vp, waitfor, td);
1610		if (error)
1611			allerror = error;
1612		NFSVOPUNLOCK(vp, 0);
1613		vrele(vp);
1614	}
1615	return (allerror);
1616}
1617
1618static int
1619nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
1620{
1621	struct nfsmount *nmp = VFSTONFS(mp);
1622	struct vfsquery vq;
1623	int error;
1624
1625	bzero(&vq, sizeof(vq));
1626	switch (op) {
1627#if 0
1628	case VFS_CTL_NOLOCKS:
1629		val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
1630 		if (req->oldptr != NULL) {
1631 			error = SYSCTL_OUT(req, &val, sizeof(val));
1632 			if (error)
1633 				return (error);
1634 		}
1635 		if (req->newptr != NULL) {
1636 			error = SYSCTL_IN(req, &val, sizeof(val));
1637 			if (error)
1638 				return (error);
1639			if (val)
1640				nmp->nm_flag |= NFSMNT_NOLOCKS;
1641			else
1642				nmp->nm_flag &= ~NFSMNT_NOLOCKS;
1643 		}
1644		break;
1645#endif
1646	case VFS_CTL_QUERY:
1647		mtx_lock(&nmp->nm_mtx);
1648		if (nmp->nm_state & NFSSTA_TIMEO)
1649			vq.vq_flags |= VQ_NOTRESP;
1650		mtx_unlock(&nmp->nm_mtx);
1651#if 0
1652		if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
1653		    (nmp->nm_state & NFSSTA_LOCKTIMEO))
1654			vq.vq_flags |= VQ_NOTRESPLOCK;
1655#endif
1656		error = SYSCTL_OUT(req, &vq, sizeof(vq));
1657		break;
1658 	case VFS_CTL_TIMEO:
1659 		if (req->oldptr != NULL) {
1660 			error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
1661 			    sizeof(nmp->nm_tprintf_initial_delay));
1662 			if (error)
1663 				return (error);
1664 		}
1665 		if (req->newptr != NULL) {
1666			error = vfs_suser(mp, req->td);
1667			if (error)
1668				return (error);
1669 			error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
1670 			    sizeof(nmp->nm_tprintf_initial_delay));
1671 			if (error)
1672 				return (error);
1673 			if (nmp->nm_tprintf_initial_delay < 0)
1674 				nmp->nm_tprintf_initial_delay = 0;
1675 		}
1676		break;
1677	default:
1678		return (ENOTSUP);
1679	}
1680	return (0);
1681}
1682
1683/*
1684 * Purge any RPCs in progress, so that they will all return errors.
1685 * This allows dounmount() to continue as far as VFS_UNMOUNT() for a
1686 * forced dismount.
1687 */
1688static void
1689nfs_purge(struct mount *mp)
1690{
1691	struct nfsmount *nmp = VFSTONFS(mp);
1692
1693	newnfs_nmcancelreqs(nmp);
1694}
1695
1696/*
1697 * Extract the information needed by the nlm from the nfs vnode.
1698 */
1699static void
1700nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp,
1701    struct sockaddr_storage *sp, int *is_v3p, off_t *sizep,
1702    struct timeval *timeop)
1703{
1704	struct nfsmount *nmp;
1705	struct nfsnode *np = VTONFS(vp);
1706
1707	nmp = VFSTONFS(vp->v_mount);
1708	if (fhlenp != NULL)
1709		*fhlenp = (size_t)np->n_fhp->nfh_len;
1710	if (fhp != NULL)
1711		bcopy(np->n_fhp->nfh_fh, fhp, np->n_fhp->nfh_len);
1712	if (sp != NULL)
1713		bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp)));
1714	if (is_v3p != NULL)
1715		*is_v3p = NFS_ISV3(vp);
1716	if (sizep != NULL)
1717		*sizep = np->n_size;
1718	if (timeop != NULL) {
1719		timeop->tv_sec = nmp->nm_timeo / NFS_HZ;
1720		timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ);
1721	}
1722}
1723
1724/*
1725 * This function prints out an option name, based on the conditional
1726 * argument.
1727 */
1728static __inline void nfscl_printopt(struct nfsmount *nmp, int testval,
1729    char *opt, char **buf, size_t *blen)
1730{
1731	int len;
1732
1733	if (testval != 0 && *blen > strlen(opt)) {
1734		len = snprintf(*buf, *blen, "%s", opt);
1735		if (len != strlen(opt))
1736			printf("EEK!!\n");
1737		*buf += len;
1738		*blen -= len;
1739	}
1740}
1741
1742/*
1743 * This function printf out an options integer value.
1744 */
1745static __inline void nfscl_printoptval(struct nfsmount *nmp, int optval,
1746    char *opt, char **buf, size_t *blen)
1747{
1748	int len;
1749
1750	if (*blen > strlen(opt) + 1) {
1751		/* Could result in truncated output string. */
1752		len = snprintf(*buf, *blen, "%s=%d", opt, optval);
1753		if (len < *blen) {
1754			*buf += len;
1755			*blen -= len;
1756		}
1757	}
1758}
1759
1760/*
1761 * Load the option flags and values into the buffer.
1762 */
1763void nfscl_retopts(struct nfsmount *nmp, char *buffer, size_t buflen)
1764{
1765	char *buf;
1766	size_t blen;
1767
1768	buf = buffer;
1769	blen = buflen;
1770	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV4) != 0, "nfsv4", &buf,
1771	    &blen);
1772	if ((nmp->nm_flag & NFSMNT_NFSV4) != 0) {
1773		nfscl_printoptval(nmp, nmp->nm_minorvers, ",minorversion", &buf,
1774		    &blen);
1775		nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_PNFS) != 0, ",pnfs",
1776		    &buf, &blen);
1777	}
1778	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV3) != 0, "nfsv3", &buf,
1779	    &blen);
1780	nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0,
1781	    "nfsv2", &buf, &blen);
1782	nfscl_printopt(nmp, nmp->nm_sotype == SOCK_STREAM, ",tcp", &buf, &blen);
1783	nfscl_printopt(nmp, nmp->nm_sotype != SOCK_STREAM, ",udp", &buf, &blen);
1784	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RESVPORT) != 0, ",resvport",
1785	    &buf, &blen);
1786	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCONN) != 0, ",noconn",
1787	    &buf, &blen);
1788	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) == 0, ",hard", &buf,
1789	    &blen);
1790	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) != 0, ",soft", &buf,
1791	    &blen);
1792	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_INT) != 0, ",intr", &buf,
1793	    &blen);
1794	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) == 0, ",cto", &buf,
1795	    &blen);
1796	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) != 0, ",nocto", &buf,
1797	    &blen);
1798	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NONCONTIGWR) != 0,
1799	    ",noncontigwr", &buf, &blen);
1800	nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
1801	    0, ",lockd", &buf, &blen);
1802	nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
1803	    NFSMNT_NOLOCKD, ",nolockd", &buf, &blen);
1804	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RDIRPLUS) != 0, ",rdirplus",
1805	    &buf, &blen);
1806	nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_KERB) == 0, ",sec=sys",
1807	    &buf, &blen);
1808	nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
1809	    NFSMNT_PRIVACY)) == NFSMNT_KERB, ",sec=krb5", &buf, &blen);
1810	nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
1811	    NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_INTEGRITY), ",sec=krb5i",
1812	    &buf, &blen);
1813	nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
1814	    NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_PRIVACY), ",sec=krb5p",
1815	    &buf, &blen);
1816	nfscl_printoptval(nmp, nmp->nm_acdirmin, ",acdirmin", &buf, &blen);
1817	nfscl_printoptval(nmp, nmp->nm_acdirmax, ",acdirmax", &buf, &blen);
1818	nfscl_printoptval(nmp, nmp->nm_acregmin, ",acregmin", &buf, &blen);
1819	nfscl_printoptval(nmp, nmp->nm_acregmax, ",acregmax", &buf, &blen);
1820	nfscl_printoptval(nmp, nmp->nm_nametimeo, ",nametimeo", &buf, &blen);
1821	nfscl_printoptval(nmp, nmp->nm_negnametimeo, ",negnametimeo", &buf,
1822	    &blen);
1823	nfscl_printoptval(nmp, nmp->nm_rsize, ",rsize", &buf, &blen);
1824	nfscl_printoptval(nmp, nmp->nm_wsize, ",wsize", &buf, &blen);
1825	nfscl_printoptval(nmp, nmp->nm_readdirsize, ",readdirsize", &buf,
1826	    &blen);
1827	nfscl_printoptval(nmp, nmp->nm_readahead, ",readahead", &buf, &blen);
1828	nfscl_printoptval(nmp, nmp->nm_wcommitsize, ",wcommitsize", &buf,
1829	    &blen);
1830	nfscl_printoptval(nmp, nmp->nm_timeo, ",timeout", &buf, &blen);
1831	nfscl_printoptval(nmp, nmp->nm_retry, ",retrans", &buf, &blen);
1832}
1833
1834