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