2 * SPDX-License-Identifier: BSD-3-Clause
4 * Copyright (c) 1989, 1993, 1995
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Rick Macklem at The University of Guelph.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * from nfs_vfsops.c 8.12 (Berkeley) 5/20/95
37 #include <sys/cdefs.h>
38 __FBSDID("$FreeBSD$");
41 #include "opt_bootp.h"
42 #include "opt_nfsroot.h"
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/kernel.h>
49 #include <sys/clock.h>
51 #include <sys/limits.h>
53 #include <sys/malloc.h>
55 #include <sys/module.h>
56 #include <sys/mount.h>
58 #include <sys/socket.h>
59 #include <sys/socketvar.h>
60 #include <sys/sockio.h>
61 #include <sys/sysctl.h>
62 #include <sys/vnode.h>
63 #include <sys/signalvar.h>
66 #include <vm/vm_extern.h>
70 #include <net/route.h>
71 #include <netinet/in.h>
73 #include <fs/nfs/nfsport.h>
74 #include <fs/nfsclient/nfsnode.h>
75 #include <fs/nfsclient/nfsmount.h>
76 #include <fs/nfsclient/nfs.h>
77 #include <nfs/nfsdiskless.h>
79 FEATURE(nfscl, "NFSv4 client");
81 extern int nfscl_ticks;
82 extern struct timeval nfsboottime;
83 extern int nfsrv_useacl;
84 extern int nfscl_debuglevel;
85 extern enum nfsiod_state ncl_iodwant[NFS_MAXASYNCDAEMON];
86 extern struct nfsmount *ncl_iodmount[NFS_MAXASYNCDAEMON];
87 extern struct mtx ncl_iod_mutex;
89 extern struct mtx nfsrv_dslock_mtx;
91 MALLOC_DEFINE(M_NEWNFSREQ, "newnfsclient_req", "NFS request header");
92 MALLOC_DEFINE(M_NEWNFSMNT, "newnfsmnt", "NFS mount struct");
94 SYSCTL_DECL(_vfs_nfs);
95 static int nfs_ip_paranoia = 1;
96 SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW,
97 &nfs_ip_paranoia, 0, "");
98 static int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
99 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_INITIAL_DELAY,
100 downdelayinitial, CTLFLAG_RW, &nfs_tprintf_initial_delay, 0, "");
101 /* how long between console messages "nfs server foo not responding" */
102 static int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
103 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_DELAY,
104 downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0, "");
107 SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0,
108 "Toggle debug flag");
111 static int nfs_mountroot(struct mount *);
112 static void nfs_sec_name(char *, int *);
113 static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp,
114 struct nfs_args *argp, const char *, struct ucred *,
116 static int mountnfs(struct nfs_args *, struct mount *,
117 struct sockaddr *, char *, u_char *, int, u_char *, int,
118 u_char *, int, struct vnode **, struct ucred *,
119 struct thread *, int, int, int);
120 static void nfs_getnlminfo(struct vnode *, uint8_t *, size_t *,
121 struct sockaddr_storage *, int *, off_t *,
123 static vfs_mount_t nfs_mount;
124 static vfs_cmount_t nfs_cmount;
125 static vfs_unmount_t nfs_unmount;
126 static vfs_root_t nfs_root;
127 static vfs_statfs_t nfs_statfs;
128 static vfs_sync_t nfs_sync;
129 static vfs_sysctl_t nfs_sysctl;
130 static vfs_purge_t nfs_purge;
133 * nfs vfs operations.
135 static struct vfsops nfs_vfsops = {
136 .vfs_init = ncl_init,
137 .vfs_mount = nfs_mount,
138 .vfs_cmount = nfs_cmount,
139 .vfs_root = vfs_cache_root,
140 .vfs_cachedroot = nfs_root,
141 .vfs_statfs = nfs_statfs,
142 .vfs_sync = nfs_sync,
143 .vfs_uninit = ncl_uninit,
144 .vfs_unmount = nfs_unmount,
145 .vfs_sysctl = nfs_sysctl,
146 .vfs_purge = nfs_purge,
148 VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK | VFCF_SBDRY);
150 /* So that loader and kldload(2) can find us, wherever we are.. */
151 MODULE_VERSION(nfs, 1);
152 MODULE_DEPEND(nfs, nfscommon, 1, 1, 1);
153 MODULE_DEPEND(nfs, krpc, 1, 1, 1);
154 MODULE_DEPEND(nfs, nfssvc, 1, 1, 1);
155 MODULE_DEPEND(nfs, nfslock, 1, 1, 1);
158 * This structure is now defined in sys/nfs/nfs_diskless.c so that it
159 * can be shared by both NFS clients. It is declared here so that it
160 * will be defined for kernels built without NFS_ROOT, although it
161 * isn't used in that case.
163 #if !defined(NFS_ROOT)
164 struct nfs_diskless nfs_diskless = { { { 0 } } };
165 struct nfsv3_diskless nfsv3_diskless = { { { 0 } } };
166 int nfs_diskless_valid = 0;
169 SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
170 &nfs_diskless_valid, 0,
171 "Has the diskless struct been filled correctly");
173 SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
174 nfsv3_diskless.root_hostnam, 0, "Path to nfs root");
176 SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
177 &nfsv3_diskless.root_saddr, sizeof(nfsv3_diskless.root_saddr),
178 "%Ssockaddr_in", "Diskless root nfs address");
181 void newnfsargs_ntoh(struct nfs_args *);
182 static int nfs_mountdiskless(char *,
183 struct sockaddr_in *, struct nfs_args *,
184 struct thread *, struct vnode **, struct mount *);
185 static void nfs_convert_diskless(void);
186 static void nfs_convert_oargs(struct nfs_args *args,
187 struct onfs_args *oargs);
190 newnfs_iosize(struct nfsmount *nmp)
194 /* First, set the upper limit for iosize */
195 if (nmp->nm_flag & NFSMNT_NFSV4) {
196 maxio = NFS_MAXBSIZE;
197 } else if (nmp->nm_flag & NFSMNT_NFSV3) {
198 if (nmp->nm_sotype == SOCK_DGRAM)
199 maxio = NFS_MAXDGRAMDATA;
201 maxio = NFS_MAXBSIZE;
203 maxio = NFS_V2MAXDATA;
205 if (nmp->nm_rsize > maxio || nmp->nm_rsize == 0)
206 nmp->nm_rsize = maxio;
207 if (nmp->nm_rsize > NFS_MAXBSIZE)
208 nmp->nm_rsize = NFS_MAXBSIZE;
209 if (nmp->nm_readdirsize > maxio || nmp->nm_readdirsize == 0)
210 nmp->nm_readdirsize = maxio;
211 if (nmp->nm_readdirsize > nmp->nm_rsize)
212 nmp->nm_readdirsize = nmp->nm_rsize;
213 if (nmp->nm_wsize > maxio || nmp->nm_wsize == 0)
214 nmp->nm_wsize = maxio;
215 if (nmp->nm_wsize > NFS_MAXBSIZE)
216 nmp->nm_wsize = NFS_MAXBSIZE;
219 * Calculate the size used for io buffers. Use the larger
220 * of the two sizes to minimise nfs requests but make sure
221 * that it is at least one VM page to avoid wasting buffer
222 * space. It must also be at least NFS_DIRBLKSIZ, since
223 * that is the buffer size used for directories.
225 iosize = imax(nmp->nm_rsize, nmp->nm_wsize);
226 iosize = imax(iosize, PAGE_SIZE);
227 iosize = imax(iosize, NFS_DIRBLKSIZ);
228 nmp->nm_mountp->mnt_stat.f_iosize = iosize;
233 nfs_convert_oargs(struct nfs_args *args, struct onfs_args *oargs)
236 args->version = NFS_ARGSVERSION;
237 args->addr = oargs->addr;
238 args->addrlen = oargs->addrlen;
239 args->sotype = oargs->sotype;
240 args->proto = oargs->proto;
241 args->fh = oargs->fh;
242 args->fhsize = oargs->fhsize;
243 args->flags = oargs->flags;
244 args->wsize = oargs->wsize;
245 args->rsize = oargs->rsize;
246 args->readdirsize = oargs->readdirsize;
247 args->timeo = oargs->timeo;
248 args->retrans = oargs->retrans;
249 args->readahead = oargs->readahead;
250 args->hostname = oargs->hostname;
254 nfs_convert_diskless(void)
257 bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
258 sizeof(struct ifaliasreq));
259 bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
260 sizeof(struct sockaddr_in));
261 nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
262 if (nfsv3_diskless.root_args.flags & NFSMNT_NFSV3) {
263 nfsv3_diskless.root_fhsize = NFSX_MYFH;
264 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_MYFH);
266 nfsv3_diskless.root_fhsize = NFSX_V2FH;
267 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
269 bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
270 sizeof(struct sockaddr_in));
271 bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN);
272 nfsv3_diskless.root_time = nfs_diskless.root_time;
273 bcopy(nfs_diskless.my_hostnam, nfsv3_diskless.my_hostnam,
275 nfs_diskless_valid = 3;
282 nfs_statfs(struct mount *mp, struct statfs *sbp)
286 struct nfsmount *nmp = VFSTONFS(mp);
287 struct nfsvattr nfsva;
290 int error = 0, attrflag, gotfsinfo = 0, ret;
295 error = vfs_busy(mp, MBF_NOWAIT);
298 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
304 mtx_lock(&nmp->nm_mtx);
305 if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
306 mtx_unlock(&nmp->nm_mtx);
307 error = nfsrpc_fsinfo(vp, &fs, td->td_ucred, td, &nfsva,
312 mtx_unlock(&nmp->nm_mtx);
314 error = nfsrpc_statfs(vp, &sb, &fs, td->td_ucred, td, &nfsva,
317 NFSCL_DEBUG(2, "statfs=%d\n", error);
319 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
320 td->td_ucred, td, &nfsva, NULL, NULL);
323 * Just set default values to get things going.
325 NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
326 nfsva.na_vattr.va_type = VDIR;
327 nfsva.na_vattr.va_mode = 0777;
328 nfsva.na_vattr.va_nlink = 100;
329 nfsva.na_vattr.va_uid = (uid_t)0;
330 nfsva.na_vattr.va_gid = (gid_t)0;
331 nfsva.na_vattr.va_fileid = 2;
332 nfsva.na_vattr.va_gen = 1;
333 nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
334 nfsva.na_vattr.va_size = 512 * 1024;
337 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
339 mtx_lock(&nmp->nm_mtx);
340 if (gotfsinfo || (nmp->nm_flag & NFSMNT_NFSV4))
341 nfscl_loadfsinfo(nmp, &fs);
342 nfscl_loadsbinfo(nmp, &sb, sbp);
343 sbp->f_iosize = newnfs_iosize(nmp);
344 mtx_unlock(&nmp->nm_mtx);
345 if (sbp != &mp->mnt_stat) {
346 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
347 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
349 strncpy(&sbp->f_fstypename[0], mp->mnt_vfc->vfc_name, MFSNAMELEN);
350 } else if (NFS_ISV4(vp)) {
351 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
359 * nfs version 3 fsinfo rpc call
362 ncl_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred,
366 struct nfsvattr nfsva;
369 error = nfsrpc_fsinfo(vp, &fs, cred, td, &nfsva, &attrflag, NULL);
372 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0,
374 mtx_lock(&nmp->nm_mtx);
375 nfscl_loadfsinfo(nmp, &fs);
376 mtx_unlock(&nmp->nm_mtx);
382 * Mount a remote root fs via. nfs. This depends on the info in the
383 * nfs_diskless structure that has been filled in properly by some primary
385 * It goes something like this:
386 * - do enough of "ifconfig" by calling ifioctl() so that the system
387 * can talk to the server
388 * - If nfs_diskless.mygateway is filled in, use that address as
390 * - build the rootfs mount point and call mountnfs() to do the rest.
392 * It is assumed to be safe to read, modify, and write the nfsv3_diskless
393 * structure, as well as other global NFS client variables here, as
394 * nfs_mountroot() will be called once in the boot before any other NFS
395 * client activity occurs.
398 nfs_mountroot(struct mount *mp)
400 struct thread *td = curthread;
401 struct nfsv3_diskless *nd = &nfsv3_diskless;
410 #if defined(BOOTP_NFSROOT) && defined(BOOTP)
411 bootpc_init(); /* use bootp to get nfs_diskless filled in */
412 #elif defined(NFS_ROOT)
413 nfs_setup_diskless();
416 if (nfs_diskless_valid == 0)
418 if (nfs_diskless_valid == 1)
419 nfs_convert_diskless();
422 * Do enough of ifconfig(8) so that the critical net interface can
423 * talk to the server.
425 error = socreate(nd->myif.ifra_addr.sa_family, &so, nd->root_args.sotype, 0,
428 panic("nfs_mountroot: socreate(%04x): %d",
429 nd->myif.ifra_addr.sa_family, error);
431 #if 0 /* XXX Bad idea */
433 * We might not have been told the right interface, so we pass
434 * over the first ten interfaces of the same kind, until we get
435 * one of them configured.
438 for (i = strlen(nd->myif.ifra_name) - 1;
439 nd->myif.ifra_name[i] >= '0' &&
440 nd->myif.ifra_name[i] <= '9';
441 nd->myif.ifra_name[i] ++) {
442 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
447 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
449 panic("nfs_mountroot: SIOCAIFADDR: %d", error);
450 if ((cp = kern_getenv("boot.netif.mtu")) != NULL) {
451 ir.ifr_mtu = strtol(cp, NULL, 10);
452 bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ);
454 error = ifioctl(so, SIOCSIFMTU, (caddr_t)&ir, td);
456 printf("nfs_mountroot: SIOCSIFMTU: %d", error);
461 * If the gateway field is filled in, set it as the default route.
462 * Note that pxeboot will set a default route of 0 if the route
463 * is not set by the DHCP server. Check also for a value of 0
464 * to avoid panicking inappropriately in that situation.
466 if (nd->mygateway.sin_len != 0 &&
467 nd->mygateway.sin_addr.s_addr != 0) {
468 struct sockaddr_in mask, sin;
470 bzero((caddr_t)&mask, sizeof(mask));
472 sin.sin_family = AF_INET;
473 sin.sin_len = sizeof(sin);
474 /* XXX MRT use table 0 for this sort of thing */
475 CURVNET_SET(TD_TO_VNET(td));
476 error = rtrequest_fib(RTM_ADD, (struct sockaddr *)&sin,
477 (struct sockaddr *)&nd->mygateway,
478 (struct sockaddr *)&mask,
479 RTF_UP | RTF_GATEWAY, NULL, RT_DEFAULT_FIB);
482 panic("nfs_mountroot: RTM_ADD: %d", error);
486 * Create the rootfs mount point.
488 nd->root_args.fh = nd->root_fh;
489 nd->root_args.fhsize = nd->root_fhsize;
490 l = ntohl(nd->root_saddr.sin_addr.s_addr);
491 snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
492 (l >> 24) & 0xff, (l >> 16) & 0xff,
493 (l >> 8) & 0xff, (l >> 0) & 0xff, nd->root_hostnam);
494 printf("NFS ROOT: %s\n", buf);
495 nd->root_args.hostname = buf;
496 if ((error = nfs_mountdiskless(buf,
497 &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) {
502 * This is not really an nfs issue, but it is much easier to
503 * set hostname here and then let the "/etc/rc.xxx" files
504 * mount the right /var based upon its preset value.
506 mtx_lock(&prison0.pr_mtx);
507 strlcpy(prison0.pr_hostname, nd->my_hostnam,
508 sizeof(prison0.pr_hostname));
509 mtx_unlock(&prison0.pr_mtx);
510 inittodr(ntohl(nd->root_time));
515 * Internal version of mount system call for diskless setup.
518 nfs_mountdiskless(char *path,
519 struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
520 struct vnode **vpp, struct mount *mp)
522 struct sockaddr *nam;
527 * Find the directory path in "path", which also has the server's
528 * name/ip address in it.
530 dirpath = strchr(path, ':');
532 dirlen = strlen(++dirpath);
535 nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
536 if ((error = mountnfs(args, mp, nam, path, NULL, 0, dirpath, dirlen,
537 NULL, 0, vpp, td->td_ucred, td, NFS_DEFAULT_NAMETIMEO,
538 NFS_DEFAULT_NEGNAMETIMEO, 0)) != 0) {
539 printf("nfs_mountroot: mount %s on /: %d\n", path, error);
546 nfs_sec_name(char *sec, int *flagsp)
548 if (!strcmp(sec, "krb5"))
549 *flagsp |= NFSMNT_KERB;
550 else if (!strcmp(sec, "krb5i"))
551 *flagsp |= (NFSMNT_KERB | NFSMNT_INTEGRITY);
552 else if (!strcmp(sec, "krb5p"))
553 *flagsp |= (NFSMNT_KERB | NFSMNT_PRIVACY);
557 nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
558 const char *hostname, struct ucred *cred, struct thread *td)
564 * Set read-only flag if requested; otherwise, clear it if this is
565 * an update. If this is not an update, then either the read-only
566 * flag is already clear, or this is a root mount and it was set
567 * intentionally at some previous point.
569 if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) {
571 mp->mnt_flag |= MNT_RDONLY;
573 } else if (mp->mnt_flag & MNT_UPDATE) {
575 mp->mnt_flag &= ~MNT_RDONLY;
580 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
581 * no sense in that context. Also, set up appropriate retransmit
582 * and soft timeout behavior.
584 if (argp->sotype == SOCK_STREAM) {
585 nmp->nm_flag &= ~NFSMNT_NOCONN;
586 nmp->nm_timeo = NFS_MAXTIMEO;
587 if ((argp->flags & NFSMNT_NFSV4) != 0)
588 nmp->nm_retry = INT_MAX;
590 nmp->nm_retry = NFS_RETRANS_TCP;
593 /* Also clear RDIRPLUS if NFSv2, it crashes some servers */
594 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
595 argp->flags &= ~NFSMNT_RDIRPLUS;
596 nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
599 /* Clear ONEOPENOWN for NFSv2, 3 and 4.0. */
600 if (nmp->nm_minorvers == 0) {
601 argp->flags &= ~NFSMNT_ONEOPENOWN;
602 nmp->nm_flag &= ~NFSMNT_ONEOPENOWN;
605 /* Re-bind if rsrvd port requested and wasn't on one */
606 adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
607 && (argp->flags & NFSMNT_RESVPORT);
608 /* Also re-bind if we're switching to/from a connected UDP socket */
609 adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
610 (argp->flags & NFSMNT_NOCONN));
612 /* Update flags atomically. Don't change the lock bits. */
613 nmp->nm_flag = argp->flags | nmp->nm_flag;
615 if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
616 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
617 if (nmp->nm_timeo < NFS_MINTIMEO)
618 nmp->nm_timeo = NFS_MINTIMEO;
619 else if (nmp->nm_timeo > NFS_MAXTIMEO)
620 nmp->nm_timeo = NFS_MAXTIMEO;
623 if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
624 nmp->nm_retry = argp->retrans;
625 if (nmp->nm_retry > NFS_MAXREXMIT)
626 nmp->nm_retry = NFS_MAXREXMIT;
629 if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
630 nmp->nm_wsize = argp->wsize;
632 * Clip at the power of 2 below the size. There is an
633 * issue (not isolated) that causes intermittent page
634 * faults if this is not done.
636 if (nmp->nm_wsize > NFS_FABLKSIZE)
637 nmp->nm_wsize = 1 << (fls(nmp->nm_wsize) - 1);
639 nmp->nm_wsize = NFS_FABLKSIZE;
642 if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
643 nmp->nm_rsize = argp->rsize;
645 * Clip at the power of 2 below the size. There is an
646 * issue (not isolated) that causes intermittent page
647 * faults if this is not done.
649 if (nmp->nm_rsize > NFS_FABLKSIZE)
650 nmp->nm_rsize = 1 << (fls(nmp->nm_rsize) - 1);
652 nmp->nm_rsize = NFS_FABLKSIZE;
655 if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
656 nmp->nm_readdirsize = argp->readdirsize;
659 if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
660 nmp->nm_acregmin = argp->acregmin;
662 nmp->nm_acregmin = NFS_MINATTRTIMO;
663 if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
664 nmp->nm_acregmax = argp->acregmax;
666 nmp->nm_acregmax = NFS_MAXATTRTIMO;
667 if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
668 nmp->nm_acdirmin = argp->acdirmin;
670 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
671 if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
672 nmp->nm_acdirmax = argp->acdirmax;
674 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
675 if (nmp->nm_acdirmin > nmp->nm_acdirmax)
676 nmp->nm_acdirmin = nmp->nm_acdirmax;
677 if (nmp->nm_acregmin > nmp->nm_acregmax)
678 nmp->nm_acregmin = nmp->nm_acregmax;
680 if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
681 if (argp->readahead <= NFS_MAXRAHEAD)
682 nmp->nm_readahead = argp->readahead;
684 nmp->nm_readahead = NFS_MAXRAHEAD;
686 if ((argp->flags & NFSMNT_WCOMMITSIZE) && argp->wcommitsize >= 0) {
687 if (argp->wcommitsize < nmp->nm_wsize)
688 nmp->nm_wcommitsize = nmp->nm_wsize;
690 nmp->nm_wcommitsize = argp->wcommitsize;
693 adjsock |= ((nmp->nm_sotype != argp->sotype) ||
694 (nmp->nm_soproto != argp->proto));
696 if (nmp->nm_client != NULL && adjsock) {
697 int haslock = 0, error = 0;
699 if (nmp->nm_sotype == SOCK_STREAM) {
700 error = newnfs_sndlock(&nmp->nm_sockreq.nr_lock);
705 newnfs_disconnect(&nmp->nm_sockreq);
707 newnfs_sndunlock(&nmp->nm_sockreq.nr_lock);
708 nmp->nm_sotype = argp->sotype;
709 nmp->nm_soproto = argp->proto;
710 if (nmp->nm_sotype == SOCK_DGRAM)
711 while (newnfs_connect(nmp, &nmp->nm_sockreq,
713 printf("newnfs_args: retrying connect\n");
714 (void) nfs_catnap(PSOCK, 0, "nfscon");
718 nmp->nm_sotype = argp->sotype;
719 nmp->nm_soproto = argp->proto;
722 if (hostname != NULL) {
723 strlcpy(nmp->nm_hostname, hostname,
724 sizeof(nmp->nm_hostname));
725 p = strchr(nmp->nm_hostname, ':');
731 static const char *nfs_opts[] = { "from", "nfs_args",
732 "noac", "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
733 "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
734 "async", "noconn", "nolockd", "conn", "lockd", "intr", "rdirplus",
735 "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize",
736 "retrans", "actimeo", "acregmin", "acregmax", "acdirmin", "acdirmax",
737 "resvport", "readahead", "hostname", "timeo", "timeout", "addr", "fh",
738 "nfsv3", "sec", "principal", "nfsv4", "gssname", "allgssname", "dirpath",
739 "minorversion", "nametimeo", "negnametimeo", "nocto", "noncontigwr",
740 "pnfs", "wcommitsize", "oneopenown",
744 * Parse the "from" mountarg, passed by the generic mount(8) program
745 * or the mountroot code. This is used when rerooting into NFS.
747 * Note that the "hostname" is actually a "hostname:/share/path" string.
750 nfs_mount_parse_from(struct vfsoptlist *opts, char **hostnamep,
751 struct sockaddr_in **sinp, char *dirpath, size_t dirpathsize, int *dirlenp)
753 char *nam, *delimp, *hostp, *spec;
754 int error, have_bracket = 0, offset, rv, speclen;
755 struct sockaddr_in *sin;
758 error = vfs_getopt(opts, "from", (void **)&spec, &speclen);
761 nam = malloc(MNAMELEN + 1, M_TEMP, M_WAITOK);
764 * This part comes from sbin/mount_nfs/mount_nfs.c:getnfsargs().
766 if (*spec == '[' && (delimp = strchr(spec + 1, ']')) != NULL &&
767 *(delimp + 1) == ':') {
771 } else if ((delimp = strrchr(spec, ':')) != NULL) {
774 } else if ((delimp = strrchr(spec, '@')) != NULL) {
775 printf("%s: path@server syntax is deprecated, "
776 "use server:path\n", __func__);
779 printf("%s: no <host>:<dirpath> nfs-name\n", __func__);
786 * If there has been a trailing slash at mounttime it seems
787 * that some mountd implementations fail to remove the mount
788 * entries from their mountlist while unmounting.
790 for (speclen = strlen(spec);
791 speclen > 1 && spec[speclen - 1] == '/';
793 spec[speclen - 1] = '\0';
794 if (strlen(hostp) + strlen(spec) + 1 > MNAMELEN) {
795 printf("%s: %s:%s: name too long", __func__, hostp, spec);
799 /* Make both '@' and ':' notations equal */
800 if (*hostp != '\0') {
805 memmove(nam + offset, hostp, len);
807 nam[len + offset++] = ']';
808 nam[len + offset++] = ':';
809 memmove(nam + len + offset, spec, speclen);
810 nam[len + speclen + offset] = '\0';
817 sin = malloc(sizeof(*sin), M_SONAME, M_WAITOK);
818 rv = inet_pton(AF_INET, hostp, &sin->sin_addr);
820 printf("%s: cannot parse '%s', inet_pton() returned %d\n",
821 __func__, hostp, rv);
827 sin->sin_len = sizeof(*sin);
828 sin->sin_family = AF_INET;
830 * XXX: hardcoded port number.
832 sin->sin_port = htons(2049);
834 *hostnamep = strdup(nam, M_NEWNFSMNT);
836 strlcpy(dirpath, spec, dirpathsize);
837 *dirlenp = strlen(dirpath);
847 * It seems a bit dumb to copyinstr() the host and path here and then
848 * bcopy() them in mountnfs(), but I wanted to detect errors before
849 * doing the getsockaddr() call because getsockaddr() allocates an mbuf and
850 * an error after that means that I have to release the mbuf.
854 nfs_mount(struct mount *mp)
856 struct nfs_args args = {
857 .version = NFS_ARGSVERSION,
859 .addrlen = sizeof (struct sockaddr_in),
860 .sotype = SOCK_STREAM,
864 .flags = NFSMNT_RESVPORT,
867 .readdirsize = NFS_READDIRSIZE,
869 .retrans = NFS_RETRANS,
870 .readahead = NFS_DEFRAHEAD,
871 .wcommitsize = 0, /* was: NQ_DEFLEASE */
873 .acregmin = NFS_MINATTRTIMO,
874 .acregmax = NFS_MAXATTRTIMO,
875 .acdirmin = NFS_MINDIRATTRTIMO,
876 .acdirmax = NFS_MAXDIRATTRTIMO,
878 int error = 0, ret, len;
879 struct sockaddr *nam = NULL;
883 u_char nfh[NFSX_FHMAX], krbname[100], dirpath[100], srvkrbname[100];
884 char *cp, *opt, *name, *secname;
885 int nametimeo = NFS_DEFAULT_NAMETIMEO;
886 int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
888 int dirlen, has_nfs_args_opt, has_nfs_from_opt,
889 krbnamelen, srvkrbnamelen;
892 has_nfs_args_opt = 0;
893 has_nfs_from_opt = 0;
894 hst = malloc(MNAMELEN, M_TEMP, M_WAITOK);
895 if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
901 if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS &&
902 nfs_diskless_valid != 0) {
903 error = nfs_mountroot(mp);
910 * The old mount_nfs program passed the struct nfs_args
911 * from userspace to kernel. The new mount_nfs program
912 * passes string options via nmount() from userspace to kernel
913 * and we populate the struct nfs_args in the kernel.
915 if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
916 error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
921 if (args.version != NFS_ARGSVERSION) {
922 error = EPROGMISMATCH;
925 has_nfs_args_opt = 1;
928 /* Handle the new style options. */
929 if (vfs_getopt(mp->mnt_optnew, "noac", NULL, NULL) == 0) {
930 args.acdirmin = args.acdirmax =
931 args.acregmin = args.acregmax = 0;
932 args.flags |= NFSMNT_ACDIRMIN | NFSMNT_ACDIRMAX |
933 NFSMNT_ACREGMIN | NFSMNT_ACREGMAX;
935 if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
936 args.flags |= NFSMNT_NOCONN;
937 if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
938 args.flags &= ~NFSMNT_NOCONN;
939 if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
940 args.flags |= NFSMNT_NOLOCKD;
941 if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
942 args.flags &= ~NFSMNT_NOLOCKD;
943 if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
944 args.flags |= NFSMNT_INT;
945 if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
946 args.flags |= NFSMNT_RDIRPLUS;
947 if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
948 args.flags |= NFSMNT_RESVPORT;
949 if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
950 args.flags &= ~NFSMNT_RESVPORT;
951 if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
952 args.flags |= NFSMNT_SOFT;
953 if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
954 args.flags &= ~NFSMNT_SOFT;
955 if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
956 args.sotype = SOCK_DGRAM;
957 if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
958 args.sotype = SOCK_DGRAM;
959 if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
960 args.sotype = SOCK_STREAM;
961 if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
962 args.flags |= NFSMNT_NFSV3;
963 if (vfs_getopt(mp->mnt_optnew, "nfsv4", NULL, NULL) == 0) {
964 args.flags |= NFSMNT_NFSV4;
965 args.sotype = SOCK_STREAM;
967 if (vfs_getopt(mp->mnt_optnew, "allgssname", NULL, NULL) == 0)
968 args.flags |= NFSMNT_ALLGSSNAME;
969 if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0)
970 args.flags |= NFSMNT_NOCTO;
971 if (vfs_getopt(mp->mnt_optnew, "noncontigwr", NULL, NULL) == 0)
972 args.flags |= NFSMNT_NONCONTIGWR;
973 if (vfs_getopt(mp->mnt_optnew, "pnfs", NULL, NULL) == 0)
974 args.flags |= NFSMNT_PNFS;
975 if (vfs_getopt(mp->mnt_optnew, "oneopenown", NULL, NULL) == 0)
976 args.flags |= NFSMNT_ONEOPENOWN;
977 if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
979 vfs_mount_error(mp, "illegal readdirsize");
983 ret = sscanf(opt, "%d", &args.readdirsize);
984 if (ret != 1 || args.readdirsize <= 0) {
985 vfs_mount_error(mp, "illegal readdirsize: %s",
990 args.flags |= NFSMNT_READDIRSIZE;
992 if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
994 vfs_mount_error(mp, "illegal readahead");
998 ret = sscanf(opt, "%d", &args.readahead);
999 if (ret != 1 || args.readahead <= 0) {
1000 vfs_mount_error(mp, "illegal readahead: %s",
1005 args.flags |= NFSMNT_READAHEAD;
1007 if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
1009 vfs_mount_error(mp, "illegal wsize");
1013 ret = sscanf(opt, "%d", &args.wsize);
1014 if (ret != 1 || args.wsize <= 0) {
1015 vfs_mount_error(mp, "illegal wsize: %s",
1020 args.flags |= NFSMNT_WSIZE;
1022 if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
1024 vfs_mount_error(mp, "illegal rsize");
1028 ret = sscanf(opt, "%d", &args.rsize);
1029 if (ret != 1 || args.rsize <= 0) {
1030 vfs_mount_error(mp, "illegal wsize: %s",
1035 args.flags |= NFSMNT_RSIZE;
1037 if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
1039 vfs_mount_error(mp, "illegal retrans");
1043 ret = sscanf(opt, "%d", &args.retrans);
1044 if (ret != 1 || args.retrans <= 0) {
1045 vfs_mount_error(mp, "illegal retrans: %s",
1050 args.flags |= NFSMNT_RETRANS;
1052 if (vfs_getopt(mp->mnt_optnew, "actimeo", (void **)&opt, NULL) == 0) {
1053 ret = sscanf(opt, "%d", &args.acregmin);
1054 if (ret != 1 || args.acregmin < 0) {
1055 vfs_mount_error(mp, "illegal actimeo: %s",
1060 args.acdirmin = args.acdirmax = args.acregmax = args.acregmin;
1061 args.flags |= NFSMNT_ACDIRMIN | NFSMNT_ACDIRMAX |
1062 NFSMNT_ACREGMIN | NFSMNT_ACREGMAX;
1064 if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
1065 ret = sscanf(opt, "%d", &args.acregmin);
1066 if (ret != 1 || args.acregmin < 0) {
1067 vfs_mount_error(mp, "illegal acregmin: %s",
1072 args.flags |= NFSMNT_ACREGMIN;
1074 if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
1075 ret = sscanf(opt, "%d", &args.acregmax);
1076 if (ret != 1 || args.acregmax < 0) {
1077 vfs_mount_error(mp, "illegal acregmax: %s",
1082 args.flags |= NFSMNT_ACREGMAX;
1084 if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
1085 ret = sscanf(opt, "%d", &args.acdirmin);
1086 if (ret != 1 || args.acdirmin < 0) {
1087 vfs_mount_error(mp, "illegal acdirmin: %s",
1092 args.flags |= NFSMNT_ACDIRMIN;
1094 if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
1095 ret = sscanf(opt, "%d", &args.acdirmax);
1096 if (ret != 1 || args.acdirmax < 0) {
1097 vfs_mount_error(mp, "illegal acdirmax: %s",
1102 args.flags |= NFSMNT_ACDIRMAX;
1104 if (vfs_getopt(mp->mnt_optnew, "wcommitsize", (void **)&opt, NULL) == 0) {
1105 ret = sscanf(opt, "%d", &args.wcommitsize);
1106 if (ret != 1 || args.wcommitsize < 0) {
1107 vfs_mount_error(mp, "illegal wcommitsize: %s", opt);
1111 args.flags |= NFSMNT_WCOMMITSIZE;
1113 if (vfs_getopt(mp->mnt_optnew, "timeo", (void **)&opt, NULL) == 0) {
1114 ret = sscanf(opt, "%d", &args.timeo);
1115 if (ret != 1 || args.timeo <= 0) {
1116 vfs_mount_error(mp, "illegal timeo: %s",
1121 args.flags |= NFSMNT_TIMEO;
1123 if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
1124 ret = sscanf(opt, "%d", &args.timeo);
1125 if (ret != 1 || args.timeo <= 0) {
1126 vfs_mount_error(mp, "illegal timeout: %s",
1131 args.flags |= NFSMNT_TIMEO;
1133 if (vfs_getopt(mp->mnt_optnew, "nametimeo", (void **)&opt, NULL) == 0) {
1134 ret = sscanf(opt, "%d", &nametimeo);
1135 if (ret != 1 || nametimeo < 0) {
1136 vfs_mount_error(mp, "illegal nametimeo: %s", opt);
1141 if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
1143 ret = sscanf(opt, "%d", &negnametimeo);
1144 if (ret != 1 || negnametimeo < 0) {
1145 vfs_mount_error(mp, "illegal negnametimeo: %s",
1151 if (vfs_getopt(mp->mnt_optnew, "minorversion", (void **)&opt, NULL) ==
1153 ret = sscanf(opt, "%d", &minvers);
1154 if (ret != 1 || minvers < 0 || minvers > 2 ||
1155 (args.flags & NFSMNT_NFSV4) == 0) {
1156 vfs_mount_error(mp, "illegal minorversion: %s", opt);
1161 if (vfs_getopt(mp->mnt_optnew, "sec",
1162 (void **) &secname, NULL) == 0)
1163 nfs_sec_name(secname, &args.flags);
1165 if (mp->mnt_flag & MNT_UPDATE) {
1166 struct nfsmount *nmp = VFSTONFS(mp);
1174 * If a change from TCP->UDP is done and there are thread(s)
1175 * that have I/O RPC(s) in progress with a transfer size
1176 * greater than NFS_MAXDGRAMDATA, those thread(s) will be
1177 * hung, retrying the RPC(s) forever. Usually these threads
1178 * will be seen doing an uninterruptible sleep on wait channel
1181 if (args.sotype == SOCK_DGRAM && nmp->nm_sotype == SOCK_STREAM)
1182 tprintf(td->td_proc, LOG_WARNING,
1183 "Warning: mount -u that changes TCP->UDP can result in hung threads\n");
1186 * When doing an update, we can't change version,
1187 * security, switch lockd strategies, change cookie
1188 * translation or switch oneopenown.
1190 args.flags = (args.flags &
1197 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
1205 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
1206 nfs_decode_args(mp, nmp, &args, NULL, td->td_ucred, td);
1211 * Make the nfs_ip_paranoia sysctl serve as the default connection
1212 * or no-connection mode for those protocols that support
1213 * no-connection mode (the flag will be cleared later for protocols
1214 * that do not support no-connection mode). This will allow a client
1215 * to receive replies from a different IP then the request was
1216 * sent to. Note: default value for nfs_ip_paranoia is 1 (paranoid),
1219 if (nfs_ip_paranoia == 0)
1220 args.flags |= NFSMNT_NOCONN;
1222 if (has_nfs_args_opt != 0) {
1224 * In the 'nfs_args' case, the pointers in the args
1225 * structure are in userland - we copy them in here.
1227 if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
1228 vfs_mount_error(mp, "Bad file handle");
1232 error = copyin((caddr_t)args.fh, (caddr_t)nfh,
1236 error = copyinstr(args.hostname, hst, MNAMELEN - 1, &hstlen);
1239 bzero(&hst[hstlen], MNAMELEN - hstlen);
1240 args.hostname = hst;
1241 /* getsockaddr() call must be after above copyin() calls */
1242 error = getsockaddr(&nam, args.addr, args.addrlen);
1245 } else if (nfs_mount_parse_from(mp->mnt_optnew,
1246 &args.hostname, (struct sockaddr_in **)&nam, dirpath,
1247 sizeof(dirpath), &dirlen) == 0) {
1248 has_nfs_from_opt = 1;
1249 bcopy(args.hostname, hst, MNAMELEN);
1250 hst[MNAMELEN - 1] = '\0';
1253 * This only works with NFSv4 for now.
1256 args.flags |= NFSMNT_NFSV4;
1257 args.sotype = SOCK_STREAM;
1259 if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
1260 &args.fhsize) == 0) {
1261 if (args.fhsize < 0 || args.fhsize > NFSX_FHMAX) {
1262 vfs_mount_error(mp, "Bad file handle");
1266 bcopy(args.fh, nfh, args.fhsize);
1270 (void) vfs_getopt(mp->mnt_optnew, "hostname",
1271 (void **)&args.hostname, &len);
1272 if (args.hostname == NULL) {
1273 vfs_mount_error(mp, "Invalid hostname");
1277 if (len >= MNAMELEN) {
1278 vfs_mount_error(mp, "Hostname too long");
1282 bcopy(args.hostname, hst, len);
1286 if (vfs_getopt(mp->mnt_optnew, "principal", (void **)&name, NULL) == 0)
1287 strlcpy(srvkrbname, name, sizeof (srvkrbname));
1289 snprintf(srvkrbname, sizeof (srvkrbname), "nfs@%s", hst);
1290 cp = strchr(srvkrbname, ':');
1294 srvkrbnamelen = strlen(srvkrbname);
1296 if (vfs_getopt(mp->mnt_optnew, "gssname", (void **)&name, NULL) == 0)
1297 strlcpy(krbname, name, sizeof (krbname));
1300 krbnamelen = strlen(krbname);
1302 if (has_nfs_from_opt == 0) {
1303 if (vfs_getopt(mp->mnt_optnew,
1304 "dirpath", (void **)&name, NULL) == 0)
1305 strlcpy(dirpath, name, sizeof (dirpath));
1308 dirlen = strlen(dirpath);
1311 if (has_nfs_args_opt == 0 && has_nfs_from_opt == 0) {
1312 if (vfs_getopt(mp->mnt_optnew, "addr",
1313 (void **)&args.addr, &args.addrlen) == 0) {
1314 if (args.addrlen > SOCK_MAXADDRLEN) {
1315 error = ENAMETOOLONG;
1318 nam = malloc(args.addrlen, M_SONAME, M_WAITOK);
1319 bcopy(args.addr, nam, args.addrlen);
1320 nam->sa_len = args.addrlen;
1322 vfs_mount_error(mp, "No server address");
1329 error = mountnfs(&args, mp, nam, hst, krbname, krbnamelen, dirpath,
1330 dirlen, srvkrbname, srvkrbnamelen, &vp, td->td_ucred, td,
1331 nametimeo, negnametimeo, minvers);
1335 mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED | MNTK_NO_IOPF |
1337 if ((VFSTONFS(mp)->nm_flag & NFSMNT_NFSV4) != 0)
1338 mp->mnt_kern_flag |= MNTK_NULL_NOCACHE;
1350 * It seems a bit dumb to copyinstr() the host and path here and then
1351 * bcopy() them in mountnfs(), but I wanted to detect errors before
1352 * doing the getsockaddr() call because getsockaddr() allocates an mbuf and
1353 * an error after that means that I have to release the mbuf.
1357 nfs_cmount(struct mntarg *ma, void *data, uint64_t flags)
1360 struct nfs_args args;
1362 error = copyin(data, &args, sizeof (struct nfs_args));
1366 ma = mount_arg(ma, "nfs_args", &args, sizeof args);
1368 error = kernel_mount(ma, flags);
1373 * Common code for mount and mountroot
1376 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
1377 char *hst, u_char *krbname, int krbnamelen, u_char *dirpath, int dirlen,
1378 u_char *srvkrbname, int srvkrbnamelen, struct vnode **vpp,
1379 struct ucred *cred, struct thread *td, int nametimeo, int negnametimeo,
1382 struct nfsmount *nmp;
1384 int error, trycnt, ret;
1385 struct nfsvattr nfsva;
1386 struct nfsclclient *clp;
1387 struct nfsclds *dsp, *tdsp;
1389 static u_int64_t clval = 0;
1391 NFSCL_DEBUG(3, "in mnt\n");
1393 if (mp->mnt_flag & MNT_UPDATE) {
1395 printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
1396 free(nam, M_SONAME);
1399 nmp = malloc(sizeof (struct nfsmount) +
1400 krbnamelen + dirlen + srvkrbnamelen + 2,
1401 M_NEWNFSMNT, M_WAITOK | M_ZERO);
1402 TAILQ_INIT(&nmp->nm_bufq);
1403 TAILQ_INIT(&nmp->nm_sess);
1405 clval = (u_int64_t)nfsboottime.tv_sec;
1406 nmp->nm_clval = clval++;
1407 nmp->nm_krbnamelen = krbnamelen;
1408 nmp->nm_dirpathlen = dirlen;
1409 nmp->nm_srvkrbnamelen = srvkrbnamelen;
1410 if (td->td_ucred->cr_uid != (uid_t)0) {
1412 * nm_uid is used to get KerberosV credentials for
1413 * the nfsv4 state handling operations if there is
1414 * no host based principal set. Use the uid of
1415 * this user if not root, since they are doing the
1416 * mount. I don't think setting this for root will
1417 * work, since root normally does not have user
1418 * credentials in a credentials cache.
1420 nmp->nm_uid = td->td_ucred->cr_uid;
1423 * Just set to -1, so it won't be used.
1425 nmp->nm_uid = (uid_t)-1;
1428 /* Copy and null terminate all the names */
1429 if (nmp->nm_krbnamelen > 0) {
1430 bcopy(krbname, nmp->nm_krbname, nmp->nm_krbnamelen);
1431 nmp->nm_name[nmp->nm_krbnamelen] = '\0';
1433 if (nmp->nm_dirpathlen > 0) {
1434 bcopy(dirpath, NFSMNT_DIRPATH(nmp),
1435 nmp->nm_dirpathlen);
1436 nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1439 if (nmp->nm_srvkrbnamelen > 0) {
1440 bcopy(srvkrbname, NFSMNT_SRVKRBNAME(nmp),
1441 nmp->nm_srvkrbnamelen);
1442 nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1443 + nmp->nm_srvkrbnamelen + 2] = '\0';
1445 nmp->nm_sockreq.nr_cred = crhold(cred);
1446 mtx_init(&nmp->nm_sockreq.nr_mtx, "nfssock", NULL, MTX_DEF);
1448 nmp->nm_getinfo = nfs_getnlminfo;
1449 nmp->nm_vinvalbuf = ncl_vinvalbuf;
1452 nmp->nm_mountp = mp;
1453 mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF | MTX_DUPOK);
1456 * Since nfs_decode_args() might optionally set them, these
1457 * need to be set to defaults before the call, so that the
1458 * optional settings aren't overwritten.
1460 nmp->nm_nametimeo = nametimeo;
1461 nmp->nm_negnametimeo = negnametimeo;
1462 nmp->nm_timeo = NFS_TIMEO;
1463 nmp->nm_retry = NFS_RETRANS;
1464 nmp->nm_readahead = NFS_DEFRAHEAD;
1466 /* This is empirical approximation of sqrt(hibufspace) * 256. */
1467 nmp->nm_wcommitsize = NFS_MAXBSIZE / 256;
1468 while ((long)nmp->nm_wcommitsize * nmp->nm_wcommitsize < hibufspace)
1469 nmp->nm_wcommitsize *= 2;
1470 nmp->nm_wcommitsize *= 256;
1472 if ((argp->flags & NFSMNT_NFSV4) != 0)
1473 nmp->nm_minorvers = minvers;
1475 nmp->nm_minorvers = 0;
1477 nfs_decode_args(mp, nmp, argp, hst, cred, td);
1480 * V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too
1481 * high, depending on whether we end up with negative offsets in
1482 * the client or server somewhere. 2GB-1 may be safer.
1484 * For V3, ncl_fsinfo will adjust this as necessary. Assume maximum
1485 * that we can handle until we find out otherwise.
1487 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0)
1488 nmp->nm_maxfilesize = 0xffffffffLL;
1490 nmp->nm_maxfilesize = OFF_MAX;
1492 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
1493 nmp->nm_wsize = NFS_WSIZE;
1494 nmp->nm_rsize = NFS_RSIZE;
1495 nmp->nm_readdirsize = NFS_READDIRSIZE;
1497 nmp->nm_numgrps = NFS_MAXGRPS;
1498 nmp->nm_tprintf_delay = nfs_tprintf_delay;
1499 if (nmp->nm_tprintf_delay < 0)
1500 nmp->nm_tprintf_delay = 0;
1501 nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
1502 if (nmp->nm_tprintf_initial_delay < 0)
1503 nmp->nm_tprintf_initial_delay = 0;
1504 nmp->nm_fhsize = argp->fhsize;
1505 if (nmp->nm_fhsize > 0)
1506 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
1507 bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
1509 /* Set up the sockets and per-host congestion */
1510 nmp->nm_sotype = argp->sotype;
1511 nmp->nm_soproto = argp->proto;
1512 nmp->nm_sockreq.nr_prog = NFS_PROG;
1513 if ((argp->flags & NFSMNT_NFSV4))
1514 nmp->nm_sockreq.nr_vers = NFS_VER4;
1515 else if ((argp->flags & NFSMNT_NFSV3))
1516 nmp->nm_sockreq.nr_vers = NFS_VER3;
1518 nmp->nm_sockreq.nr_vers = NFS_VER2;
1521 if ((error = newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0)))
1523 /* For NFSv4.1, get the clientid now. */
1524 if (nmp->nm_minorvers > 0) {
1525 NFSCL_DEBUG(3, "at getcl\n");
1526 error = nfscl_getcl(mp, cred, td, 0, &clp);
1527 NFSCL_DEBUG(3, "aft getcl=%d\n", error);
1532 if (nmp->nm_fhsize == 0 && (nmp->nm_flag & NFSMNT_NFSV4) &&
1533 nmp->nm_dirpathlen > 0) {
1534 NFSCL_DEBUG(3, "in dirp\n");
1536 * If the fhsize on the mount point == 0 for V4, the mount
1537 * path needs to be looked up.
1541 error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp),
1543 NFSCL_DEBUG(3, "aft dirp=%d\n", error);
1545 (void) nfs_catnap(PZERO, error, "nfsgetdirp");
1546 } while (error && --trycnt > 0);
1548 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
1554 * A reference count is needed on the nfsnode representing the
1555 * remote root. If this object is not persistent, then backward
1556 * traversals of the mount point (i.e. "..") will not work if
1557 * the nfsnode gets flushed out of the cache. Ufs does not have
1558 * this problem, because one can identify root inodes by their
1559 * number == UFS_ROOTINO (2).
1561 if (nmp->nm_fhsize > 0) {
1563 * Set f_iosize to NFS_DIRBLKSIZ so that bo_bsize gets set
1564 * non-zero for the root vnode. f_iosize will be set correctly
1565 * by nfs_statfs() before any I/O occurs.
1567 mp->mnt_stat.f_iosize = NFS_DIRBLKSIZ;
1568 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np,
1575 * Get file attributes and transfer parameters for the
1576 * mountpoint. This has the side effect of filling in
1577 * (*vpp)->v_type with the correct value.
1579 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
1580 cred, td, &nfsva, NULL, &lease);
1583 * Just set default values to get things going.
1585 NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
1586 nfsva.na_vattr.va_type = VDIR;
1587 nfsva.na_vattr.va_mode = 0777;
1588 nfsva.na_vattr.va_nlink = 100;
1589 nfsva.na_vattr.va_uid = (uid_t)0;
1590 nfsva.na_vattr.va_gid = (gid_t)0;
1591 nfsva.na_vattr.va_fileid = 2;
1592 nfsva.na_vattr.va_gen = 1;
1593 nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
1594 nfsva.na_vattr.va_size = 512 * 1024;
1597 (void) nfscl_loadattrcache(vpp, &nfsva, NULL, NULL, 0, 1);
1598 if (nmp->nm_minorvers > 0) {
1599 NFSCL_DEBUG(3, "lease=%d\n", (int)lease);
1601 clp->nfsc_renew = NFSCL_RENEW(lease);
1602 clp->nfsc_expire = NFSD_MONOSEC + clp->nfsc_renew;
1603 clp->nfsc_clientidrev++;
1604 if (clp->nfsc_clientidrev == 0)
1605 clp->nfsc_clientidrev++;
1608 * Mount will succeed, so the renew thread can be
1611 nfscl_start_renewthread(clp);
1612 nfscl_clientrelease(clp);
1614 if (argp->flags & NFSMNT_NFSV3)
1615 ncl_fsinfo(nmp, *vpp, cred, td);
1617 /* Mark if the mount point supports NFSv4 ACLs. */
1618 if ((argp->flags & NFSMNT_NFSV4) != 0 && nfsrv_useacl != 0 &&
1620 NFSISSET_ATTRBIT(&nfsva.na_suppattr, NFSATTRBIT_ACL)) {
1622 mp->mnt_flag |= MNT_NFS4ACLS;
1627 * Lose the lock but keep the ref.
1629 NFSVOPUNLOCK(*vpp, 0);
1630 vfs_cache_root_set(mp, *vpp);
1637 nfscl_clientrelease(clp);
1638 newnfs_disconnect(&nmp->nm_sockreq);
1639 crfree(nmp->nm_sockreq.nr_cred);
1640 if (nmp->nm_sockreq.nr_auth != NULL)
1641 AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
1642 mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1643 mtx_destroy(&nmp->nm_mtx);
1644 if (nmp->nm_clp != NULL) {
1646 LIST_REMOVE(nmp->nm_clp, nfsc_list);
1648 free(nmp->nm_clp, M_NFSCLCLIENT);
1650 TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp) {
1651 if (dsp != TAILQ_FIRST(&nmp->nm_sess) &&
1652 dsp->nfsclds_sockp != NULL)
1653 newnfs_disconnect(dsp->nfsclds_sockp);
1654 nfscl_freenfsclds(dsp);
1656 free(nmp, M_NEWNFSMNT);
1657 free(nam, M_SONAME);
1662 * unmount system call
1665 nfs_unmount(struct mount *mp, int mntflags)
1668 struct nfsmount *nmp;
1669 int error, flags = 0, i, trycnt = 0;
1670 struct nfsclds *dsp, *tdsp;
1674 if (mntflags & MNT_FORCE)
1675 flags |= FORCECLOSE;
1679 * Goes something like this..
1680 * - Call vflush() to clear out vnodes for this filesystem
1681 * - Close the socket
1682 * - Free up the data structures
1684 /* In the forced case, cancel any outstanding requests. */
1685 if (mntflags & MNT_FORCE) {
1687 if (nfsv4_findmirror(nmp) != NULL)
1692 error = newnfs_nmcancelreqs(nmp);
1695 /* For a forced close, get rid of the renew thread now */
1696 nfscl_umount(nmp, td);
1698 /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
1700 error = vflush(mp, 1, flags, td);
1701 if ((mntflags & MNT_FORCE) && error != 0 && ++trycnt < 30)
1702 (void) nfs_catnap(PSOCK, error, "newndm");
1703 } while ((mntflags & MNT_FORCE) && error != 0 && trycnt < 30);
1708 * We are now committed to the unmount.
1710 if ((mntflags & MNT_FORCE) == 0)
1711 nfscl_umount(nmp, td);
1713 mtx_lock(&nmp->nm_mtx);
1714 nmp->nm_privflag |= NFSMNTP_FORCEDISM;
1715 mtx_unlock(&nmp->nm_mtx);
1717 /* Make sure no nfsiods are assigned to this mount. */
1719 for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
1720 if (ncl_iodmount[i] == nmp) {
1721 ncl_iodwant[i] = NFSIOD_AVAILABLE;
1722 ncl_iodmount[i] = NULL;
1727 * We can now set mnt_data to NULL and wait for
1728 * nfssvc(NFSSVC_FORCEDISM) to complete.
1730 mtx_lock(&mountlist_mtx);
1731 mtx_lock(&nmp->nm_mtx);
1732 mp->mnt_data = NULL;
1733 mtx_unlock(&mountlist_mtx);
1734 while ((nmp->nm_privflag & NFSMNTP_CANCELRPCS) != 0)
1735 msleep(nmp, &nmp->nm_mtx, PVFS, "nfsfdism", 0);
1736 mtx_unlock(&nmp->nm_mtx);
1738 newnfs_disconnect(&nmp->nm_sockreq);
1739 crfree(nmp->nm_sockreq.nr_cred);
1740 free(nmp->nm_nam, M_SONAME);
1741 if (nmp->nm_sockreq.nr_auth != NULL)
1742 AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
1743 mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1744 mtx_destroy(&nmp->nm_mtx);
1745 TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp) {
1746 if (dsp != TAILQ_FIRST(&nmp->nm_sess) &&
1747 dsp->nfsclds_sockp != NULL)
1748 newnfs_disconnect(dsp->nfsclds_sockp);
1749 nfscl_freenfsclds(dsp);
1751 free(nmp, M_NEWNFSMNT);
1757 * Return root of a filesystem
1760 nfs_root(struct mount *mp, int flags, struct vnode **vpp)
1763 struct nfsmount *nmp;
1768 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, flags);
1773 * Get transfer parameters and attributes for root vnode once.
1775 mtx_lock(&nmp->nm_mtx);
1776 if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
1777 mtx_unlock(&nmp->nm_mtx);
1778 ncl_fsinfo(nmp, vp, curthread->td_ucred, curthread);
1780 mtx_unlock(&nmp->nm_mtx);
1781 if (vp->v_type == VNON)
1783 vp->v_vflag |= VV_ROOT;
1789 * Flush out the buffer cache
1793 nfs_sync(struct mount *mp, int waitfor)
1795 struct vnode *vp, *mvp;
1797 int error, allerror = 0;
1803 * If a forced dismount is in progress, return from here so that
1804 * the umount(2) syscall doesn't get stuck in VFS_SYNC() before
1805 * calling VFS_UNMOUNT().
1807 if (NFSCL_FORCEDISM(mp)) {
1814 * Force stale buffer cache information to be flushed.
1817 MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
1818 /* XXX Racy bv_cnt check. */
1819 if (NFSVOPISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
1820 waitfor == MNT_LAZY) {
1824 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
1825 MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
1828 error = VOP_FSYNC(vp, waitfor, td);
1831 NFSVOPUNLOCK(vp, 0);
1838 nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
1840 struct nfsmount *nmp = VFSTONFS(mp);
1844 bzero(&vq, sizeof(vq));
1847 case VFS_CTL_NOLOCKS:
1848 val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
1849 if (req->oldptr != NULL) {
1850 error = SYSCTL_OUT(req, &val, sizeof(val));
1854 if (req->newptr != NULL) {
1855 error = SYSCTL_IN(req, &val, sizeof(val));
1859 nmp->nm_flag |= NFSMNT_NOLOCKS;
1861 nmp->nm_flag &= ~NFSMNT_NOLOCKS;
1866 mtx_lock(&nmp->nm_mtx);
1867 if (nmp->nm_state & NFSSTA_TIMEO)
1868 vq.vq_flags |= VQ_NOTRESP;
1869 mtx_unlock(&nmp->nm_mtx);
1871 if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
1872 (nmp->nm_state & NFSSTA_LOCKTIMEO))
1873 vq.vq_flags |= VQ_NOTRESPLOCK;
1875 error = SYSCTL_OUT(req, &vq, sizeof(vq));
1878 if (req->oldptr != NULL) {
1879 error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
1880 sizeof(nmp->nm_tprintf_initial_delay));
1884 if (req->newptr != NULL) {
1885 error = vfs_suser(mp, req->td);
1888 error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
1889 sizeof(nmp->nm_tprintf_initial_delay));
1892 if (nmp->nm_tprintf_initial_delay < 0)
1893 nmp->nm_tprintf_initial_delay = 0;
1903 * Purge any RPCs in progress, so that they will all return errors.
1904 * This allows dounmount() to continue as far as VFS_UNMOUNT() for a
1908 nfs_purge(struct mount *mp)
1910 struct nfsmount *nmp = VFSTONFS(mp);
1912 newnfs_nmcancelreqs(nmp);
1916 * Extract the information needed by the nlm from the nfs vnode.
1919 nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp,
1920 struct sockaddr_storage *sp, int *is_v3p, off_t *sizep,
1921 struct timeval *timeop)
1923 struct nfsmount *nmp;
1924 struct nfsnode *np = VTONFS(vp);
1926 nmp = VFSTONFS(vp->v_mount);
1928 *fhlenp = (size_t)np->n_fhp->nfh_len;
1930 bcopy(np->n_fhp->nfh_fh, fhp, np->n_fhp->nfh_len);
1932 bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp)));
1934 *is_v3p = NFS_ISV3(vp);
1936 *sizep = np->n_size;
1937 if (timeop != NULL) {
1938 timeop->tv_sec = nmp->nm_timeo / NFS_HZ;
1939 timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ);
1944 * This function prints out an option name, based on the conditional
1947 static __inline void nfscl_printopt(struct nfsmount *nmp, int testval,
1948 char *opt, char **buf, size_t *blen)
1952 if (testval != 0 && *blen > strlen(opt)) {
1953 len = snprintf(*buf, *blen, "%s", opt);
1954 if (len != strlen(opt))
1962 * This function printf out an options integer value.
1964 static __inline void nfscl_printoptval(struct nfsmount *nmp, int optval,
1965 char *opt, char **buf, size_t *blen)
1969 if (*blen > strlen(opt) + 1) {
1970 /* Could result in truncated output string. */
1971 len = snprintf(*buf, *blen, "%s=%d", opt, optval);
1980 * Load the option flags and values into the buffer.
1982 void nfscl_retopts(struct nfsmount *nmp, char *buffer, size_t buflen)
1989 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV4) != 0, "nfsv4", &buf,
1991 if ((nmp->nm_flag & NFSMNT_NFSV4) != 0) {
1992 nfscl_printoptval(nmp, nmp->nm_minorvers, ",minorversion", &buf,
1994 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_PNFS) != 0, ",pnfs",
1996 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_ONEOPENOWN) != 0 &&
1997 nmp->nm_minorvers > 0, ",oneopenown", &buf, &blen);
1999 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV3) != 0, "nfsv3", &buf,
2001 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0,
2002 "nfsv2", &buf, &blen);
2003 nfscl_printopt(nmp, nmp->nm_sotype == SOCK_STREAM, ",tcp", &buf, &blen);
2004 nfscl_printopt(nmp, nmp->nm_sotype != SOCK_STREAM, ",udp", &buf, &blen);
2005 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RESVPORT) != 0, ",resvport",
2007 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCONN) != 0, ",noconn",
2009 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) == 0, ",hard", &buf,
2011 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) != 0, ",soft", &buf,
2013 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_INT) != 0, ",intr", &buf,
2015 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) == 0, ",cto", &buf,
2017 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) != 0, ",nocto", &buf,
2019 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NONCONTIGWR) != 0,
2020 ",noncontigwr", &buf, &blen);
2021 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
2022 0, ",lockd", &buf, &blen);
2023 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
2024 NFSMNT_NOLOCKD, ",nolockd", &buf, &blen);
2025 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RDIRPLUS) != 0, ",rdirplus",
2027 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_KERB) == 0, ",sec=sys",
2029 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
2030 NFSMNT_PRIVACY)) == NFSMNT_KERB, ",sec=krb5", &buf, &blen);
2031 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
2032 NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_INTEGRITY), ",sec=krb5i",
2034 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
2035 NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_PRIVACY), ",sec=krb5p",
2037 nfscl_printoptval(nmp, nmp->nm_acdirmin, ",acdirmin", &buf, &blen);
2038 nfscl_printoptval(nmp, nmp->nm_acdirmax, ",acdirmax", &buf, &blen);
2039 nfscl_printoptval(nmp, nmp->nm_acregmin, ",acregmin", &buf, &blen);
2040 nfscl_printoptval(nmp, nmp->nm_acregmax, ",acregmax", &buf, &blen);
2041 nfscl_printoptval(nmp, nmp->nm_nametimeo, ",nametimeo", &buf, &blen);
2042 nfscl_printoptval(nmp, nmp->nm_negnametimeo, ",negnametimeo", &buf,
2044 nfscl_printoptval(nmp, nmp->nm_rsize, ",rsize", &buf, &blen);
2045 nfscl_printoptval(nmp, nmp->nm_wsize, ",wsize", &buf, &blen);
2046 nfscl_printoptval(nmp, nmp->nm_readdirsize, ",readdirsize", &buf,
2048 nfscl_printoptval(nmp, nmp->nm_readahead, ",readahead", &buf, &blen);
2049 nfscl_printoptval(nmp, nmp->nm_wcommitsize, ",wcommitsize", &buf,
2051 nfscl_printoptval(nmp, nmp->nm_timeo, ",timeout", &buf, &blen);
2052 nfscl_printoptval(nmp, nmp->nm_retry, ",retrans", &buf, &blen);