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