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 <net/route/route_ctl.h>
72 #include <netinet/in.h>
74 #include <fs/nfs/nfsport.h>
75 #include <fs/nfsclient/nfsnode.h>
76 #include <fs/nfsclient/nfsmount.h>
77 #include <fs/nfsclient/nfs.h>
78 #include <nfs/nfsdiskless.h>
80 FEATURE(nfscl, "NFSv4 client");
82 extern int nfscl_ticks;
83 extern struct timeval nfsboottime;
84 extern int nfsrv_useacl;
85 extern int nfscl_debuglevel;
86 extern enum nfsiod_state ncl_iodwant[NFS_MAXASYNCDAEMON];
87 extern struct nfsmount *ncl_iodmount[NFS_MAXASYNCDAEMON];
88 extern struct mtx ncl_iod_mutex;
90 extern struct mtx nfsrv_dslock_mtx;
92 MALLOC_DEFINE(M_NEWNFSREQ, "newnfsclient_req", "NFS request header");
93 MALLOC_DEFINE(M_NEWNFSMNT, "newnfsmnt", "NFS mount struct");
95 SYSCTL_DECL(_vfs_nfs);
96 static int nfs_ip_paranoia = 1;
97 SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW,
98 &nfs_ip_paranoia, 0, "");
99 static int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
100 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_INITIAL_DELAY,
101 downdelayinitial, CTLFLAG_RW, &nfs_tprintf_initial_delay, 0, "");
102 /* how long between console messages "nfs server foo not responding" */
103 static int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
104 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_DELAY,
105 downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0, "");
108 SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0,
109 "Toggle debug flag");
112 static int nfs_mountroot(struct mount *);
113 static void nfs_sec_name(char *, int *);
114 static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp,
115 struct nfs_args *argp, const char *, struct ucred *,
117 static int mountnfs(struct nfs_args *, struct mount *,
118 struct sockaddr *, char *, u_char *, int, u_char *, int,
119 u_char *, int, struct vnode **, struct ucred *,
120 struct thread *, int, int, int);
121 static void nfs_getnlminfo(struct vnode *, uint8_t *, size_t *,
122 struct sockaddr_storage *, int *, off_t *,
124 static vfs_mount_t nfs_mount;
125 static vfs_cmount_t nfs_cmount;
126 static vfs_unmount_t nfs_unmount;
127 static vfs_root_t nfs_root;
128 static vfs_statfs_t nfs_statfs;
129 static vfs_sync_t nfs_sync;
130 static vfs_sysctl_t nfs_sysctl;
131 static vfs_purge_t nfs_purge;
134 * nfs vfs operations.
136 static struct vfsops nfs_vfsops = {
137 .vfs_init = ncl_init,
138 .vfs_mount = nfs_mount,
139 .vfs_cmount = nfs_cmount,
140 .vfs_root = vfs_cache_root,
141 .vfs_cachedroot = nfs_root,
142 .vfs_statfs = nfs_statfs,
143 .vfs_sync = nfs_sync,
144 .vfs_uninit = ncl_uninit,
145 .vfs_unmount = nfs_unmount,
146 .vfs_sysctl = nfs_sysctl,
147 .vfs_purge = nfs_purge,
149 VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK | VFCF_SBDRY);
151 /* So that loader and kldload(2) can find us, wherever we are.. */
152 MODULE_VERSION(nfs, 1);
153 MODULE_DEPEND(nfs, nfscommon, 1, 1, 1);
154 MODULE_DEPEND(nfs, krpc, 1, 1, 1);
155 MODULE_DEPEND(nfs, nfssvc, 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;
469 struct epoch_tracker et;
470 struct rt_addrinfo info;
471 struct rib_cmd_info rc;
473 bzero((caddr_t)&mask, sizeof(mask));
475 sin.sin_family = AF_INET;
476 sin.sin_len = sizeof(sin);
477 /* XXX MRT use table 0 for this sort of thing */
479 CURVNET_SET(TD_TO_VNET(td));
481 bzero((caddr_t)&info, sizeof(info));
482 info.rti_flags = RTF_UP | RTF_GATEWAY;
483 info.rti_info[RTAX_DST] = (struct sockaddr *)&sin;
484 info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&nd->mygateway;
485 info.rti_info[RTAX_NETMASK] = (struct sockaddr *)&mask;
487 error = rib_action(RT_DEFAULT_FIB, RTM_ADD, &info, &rc);
491 panic("nfs_mountroot: RTM_ADD: %d", error);
495 * Create the rootfs mount point.
497 nd->root_args.fh = nd->root_fh;
498 nd->root_args.fhsize = nd->root_fhsize;
499 l = ntohl(nd->root_saddr.sin_addr.s_addr);
500 snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
501 (l >> 24) & 0xff, (l >> 16) & 0xff,
502 (l >> 8) & 0xff, (l >> 0) & 0xff, nd->root_hostnam);
503 printf("NFS ROOT: %s\n", buf);
504 nd->root_args.hostname = buf;
505 if ((error = nfs_mountdiskless(buf,
506 &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) {
511 * This is not really an nfs issue, but it is much easier to
512 * set hostname here and then let the "/etc/rc.xxx" files
513 * mount the right /var based upon its preset value.
515 mtx_lock(&prison0.pr_mtx);
516 strlcpy(prison0.pr_hostname, nd->my_hostnam,
517 sizeof(prison0.pr_hostname));
518 mtx_unlock(&prison0.pr_mtx);
519 inittodr(ntohl(nd->root_time));
524 * Internal version of mount system call for diskless setup.
527 nfs_mountdiskless(char *path,
528 struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
529 struct vnode **vpp, struct mount *mp)
531 struct sockaddr *nam;
536 * Find the directory path in "path", which also has the server's
537 * name/ip address in it.
539 dirpath = strchr(path, ':');
541 dirlen = strlen(++dirpath);
544 nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
545 if ((error = mountnfs(args, mp, nam, path, NULL, 0, dirpath, dirlen,
546 NULL, 0, vpp, td->td_ucred, td, NFS_DEFAULT_NAMETIMEO,
547 NFS_DEFAULT_NEGNAMETIMEO, 0)) != 0) {
548 printf("nfs_mountroot: mount %s on /: %d\n", path, error);
555 nfs_sec_name(char *sec, int *flagsp)
557 if (!strcmp(sec, "krb5"))
558 *flagsp |= NFSMNT_KERB;
559 else if (!strcmp(sec, "krb5i"))
560 *flagsp |= (NFSMNT_KERB | NFSMNT_INTEGRITY);
561 else if (!strcmp(sec, "krb5p"))
562 *flagsp |= (NFSMNT_KERB | NFSMNT_PRIVACY);
566 nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
567 const char *hostname, struct ucred *cred, struct thread *td)
573 * Set read-only flag if requested; otherwise, clear it if this is
574 * an update. If this is not an update, then either the read-only
575 * flag is already clear, or this is a root mount and it was set
576 * intentionally at some previous point.
578 if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) {
580 mp->mnt_flag |= MNT_RDONLY;
582 } else if (mp->mnt_flag & MNT_UPDATE) {
584 mp->mnt_flag &= ~MNT_RDONLY;
589 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
590 * no sense in that context. Also, set up appropriate retransmit
591 * and soft timeout behavior.
593 if (argp->sotype == SOCK_STREAM) {
594 nmp->nm_flag &= ~NFSMNT_NOCONN;
595 nmp->nm_timeo = NFS_MAXTIMEO;
596 if ((argp->flags & NFSMNT_NFSV4) != 0)
597 nmp->nm_retry = INT_MAX;
599 nmp->nm_retry = NFS_RETRANS_TCP;
602 /* Also clear RDIRPLUS if NFSv2, it crashes some servers */
603 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
604 argp->flags &= ~NFSMNT_RDIRPLUS;
605 nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
608 /* Clear ONEOPENOWN for NFSv2, 3 and 4.0. */
609 if (nmp->nm_minorvers == 0) {
610 argp->flags &= ~NFSMNT_ONEOPENOWN;
611 nmp->nm_flag &= ~NFSMNT_ONEOPENOWN;
614 /* Re-bind if rsrvd port requested and wasn't on one */
615 adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
616 && (argp->flags & NFSMNT_RESVPORT);
617 /* Also re-bind if we're switching to/from a connected UDP socket */
618 adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
619 (argp->flags & NFSMNT_NOCONN));
621 /* Update flags atomically. Don't change the lock bits. */
622 nmp->nm_flag = argp->flags | nmp->nm_flag;
624 if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
625 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
626 if (nmp->nm_timeo < NFS_MINTIMEO)
627 nmp->nm_timeo = NFS_MINTIMEO;
628 else if (nmp->nm_timeo > NFS_MAXTIMEO)
629 nmp->nm_timeo = NFS_MAXTIMEO;
632 if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
633 nmp->nm_retry = argp->retrans;
634 if (nmp->nm_retry > NFS_MAXREXMIT)
635 nmp->nm_retry = NFS_MAXREXMIT;
638 if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
639 nmp->nm_wsize = argp->wsize;
641 * Clip at the power of 2 below the size. There is an
642 * issue (not isolated) that causes intermittent page
643 * faults if this is not done.
645 if (nmp->nm_wsize > NFS_FABLKSIZE)
646 nmp->nm_wsize = 1 << (fls(nmp->nm_wsize) - 1);
648 nmp->nm_wsize = NFS_FABLKSIZE;
651 if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
652 nmp->nm_rsize = argp->rsize;
654 * Clip at the power of 2 below the size. There is an
655 * issue (not isolated) that causes intermittent page
656 * faults if this is not done.
658 if (nmp->nm_rsize > NFS_FABLKSIZE)
659 nmp->nm_rsize = 1 << (fls(nmp->nm_rsize) - 1);
661 nmp->nm_rsize = NFS_FABLKSIZE;
664 if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
665 nmp->nm_readdirsize = argp->readdirsize;
668 if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
669 nmp->nm_acregmin = argp->acregmin;
671 nmp->nm_acregmin = NFS_MINATTRTIMO;
672 if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
673 nmp->nm_acregmax = argp->acregmax;
675 nmp->nm_acregmax = NFS_MAXATTRTIMO;
676 if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
677 nmp->nm_acdirmin = argp->acdirmin;
679 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
680 if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
681 nmp->nm_acdirmax = argp->acdirmax;
683 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
684 if (nmp->nm_acdirmin > nmp->nm_acdirmax)
685 nmp->nm_acdirmin = nmp->nm_acdirmax;
686 if (nmp->nm_acregmin > nmp->nm_acregmax)
687 nmp->nm_acregmin = nmp->nm_acregmax;
689 if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
690 if (argp->readahead <= NFS_MAXRAHEAD)
691 nmp->nm_readahead = argp->readahead;
693 nmp->nm_readahead = NFS_MAXRAHEAD;
695 if ((argp->flags & NFSMNT_WCOMMITSIZE) && argp->wcommitsize >= 0) {
696 if (argp->wcommitsize < nmp->nm_wsize)
697 nmp->nm_wcommitsize = nmp->nm_wsize;
699 nmp->nm_wcommitsize = argp->wcommitsize;
702 adjsock |= ((nmp->nm_sotype != argp->sotype) ||
703 (nmp->nm_soproto != argp->proto));
705 if (nmp->nm_client != NULL && adjsock) {
706 int haslock = 0, error = 0;
708 if (nmp->nm_sotype == SOCK_STREAM) {
709 error = newnfs_sndlock(&nmp->nm_sockreq.nr_lock);
714 newnfs_disconnect(&nmp->nm_sockreq);
716 newnfs_sndunlock(&nmp->nm_sockreq.nr_lock);
717 nmp->nm_sotype = argp->sotype;
718 nmp->nm_soproto = argp->proto;
719 if (nmp->nm_sotype == SOCK_DGRAM)
720 while (newnfs_connect(nmp, &nmp->nm_sockreq,
722 printf("newnfs_args: retrying connect\n");
723 (void) nfs_catnap(PSOCK, 0, "nfscon");
727 nmp->nm_sotype = argp->sotype;
728 nmp->nm_soproto = argp->proto;
731 if (hostname != NULL) {
732 strlcpy(nmp->nm_hostname, hostname,
733 sizeof(nmp->nm_hostname));
734 p = strchr(nmp->nm_hostname, ':');
740 static const char *nfs_opts[] = { "from", "nfs_args",
741 "noac", "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
742 "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
743 "async", "noconn", "nolockd", "conn", "lockd", "intr", "rdirplus",
744 "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize",
745 "retrans", "actimeo", "acregmin", "acregmax", "acdirmin", "acdirmax",
746 "resvport", "readahead", "hostname", "timeo", "timeout", "addr", "fh",
747 "nfsv3", "sec", "principal", "nfsv4", "gssname", "allgssname", "dirpath",
748 "minorversion", "nametimeo", "negnametimeo", "nocto", "noncontigwr",
749 "pnfs", "wcommitsize", "oneopenown",
753 * Parse the "from" mountarg, passed by the generic mount(8) program
754 * or the mountroot code. This is used when rerooting into NFS.
756 * Note that the "hostname" is actually a "hostname:/share/path" string.
759 nfs_mount_parse_from(struct vfsoptlist *opts, char **hostnamep,
760 struct sockaddr_in **sinp, char *dirpath, size_t dirpathsize, int *dirlenp)
762 char *nam, *delimp, *hostp, *spec;
763 int error, have_bracket = 0, offset, rv, speclen;
764 struct sockaddr_in *sin;
767 error = vfs_getopt(opts, "from", (void **)&spec, &speclen);
770 nam = malloc(MNAMELEN + 1, M_TEMP, M_WAITOK);
773 * This part comes from sbin/mount_nfs/mount_nfs.c:getnfsargs().
775 if (*spec == '[' && (delimp = strchr(spec + 1, ']')) != NULL &&
776 *(delimp + 1) == ':') {
780 } else if ((delimp = strrchr(spec, ':')) != NULL) {
783 } else if ((delimp = strrchr(spec, '@')) != NULL) {
784 printf("%s: path@server syntax is deprecated, "
785 "use server:path\n", __func__);
788 printf("%s: no <host>:<dirpath> nfs-name\n", __func__);
795 * If there has been a trailing slash at mounttime it seems
796 * that some mountd implementations fail to remove the mount
797 * entries from their mountlist while unmounting.
799 for (speclen = strlen(spec);
800 speclen > 1 && spec[speclen - 1] == '/';
802 spec[speclen - 1] = '\0';
803 if (strlen(hostp) + strlen(spec) + 1 > MNAMELEN) {
804 printf("%s: %s:%s: name too long", __func__, hostp, spec);
808 /* Make both '@' and ':' notations equal */
809 if (*hostp != '\0') {
814 memmove(nam + offset, hostp, len);
816 nam[len + offset++] = ']';
817 nam[len + offset++] = ':';
818 memmove(nam + len + offset, spec, speclen);
819 nam[len + speclen + offset] = '\0';
826 sin = malloc(sizeof(*sin), M_SONAME, M_WAITOK);
827 rv = inet_pton(AF_INET, hostp, &sin->sin_addr);
829 printf("%s: cannot parse '%s', inet_pton() returned %d\n",
830 __func__, hostp, rv);
836 sin->sin_len = sizeof(*sin);
837 sin->sin_family = AF_INET;
839 * XXX: hardcoded port number.
841 sin->sin_port = htons(2049);
843 *hostnamep = strdup(nam, M_NEWNFSMNT);
845 strlcpy(dirpath, spec, dirpathsize);
846 *dirlenp = strlen(dirpath);
856 * It seems a bit dumb to copyinstr() the host and path here and then
857 * bcopy() them in mountnfs(), but I wanted to detect errors before
858 * doing the getsockaddr() call because getsockaddr() allocates an mbuf and
859 * an error after that means that I have to release the mbuf.
863 nfs_mount(struct mount *mp)
865 struct nfs_args args = {
866 .version = NFS_ARGSVERSION,
868 .addrlen = sizeof (struct sockaddr_in),
869 .sotype = SOCK_STREAM,
873 .flags = NFSMNT_RESVPORT,
876 .readdirsize = NFS_READDIRSIZE,
878 .retrans = NFS_RETRANS,
879 .readahead = NFS_DEFRAHEAD,
880 .wcommitsize = 0, /* was: NQ_DEFLEASE */
882 .acregmin = NFS_MINATTRTIMO,
883 .acregmax = NFS_MAXATTRTIMO,
884 .acdirmin = NFS_MINDIRATTRTIMO,
885 .acdirmax = NFS_MAXDIRATTRTIMO,
887 int error = 0, ret, len;
888 struct sockaddr *nam = NULL;
892 u_char nfh[NFSX_FHMAX], krbname[100], dirpath[100], srvkrbname[100];
893 char *cp, *opt, *name, *secname;
894 int nametimeo = NFS_DEFAULT_NAMETIMEO;
895 int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
897 int dirlen, has_nfs_args_opt, has_nfs_from_opt,
898 krbnamelen, srvkrbnamelen;
901 has_nfs_args_opt = 0;
902 has_nfs_from_opt = 0;
903 hst = malloc(MNAMELEN, M_TEMP, M_WAITOK);
904 if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
910 if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS &&
911 nfs_diskless_valid != 0) {
912 error = nfs_mountroot(mp);
919 * The old mount_nfs program passed the struct nfs_args
920 * from userspace to kernel. The new mount_nfs program
921 * passes string options via nmount() from userspace to kernel
922 * and we populate the struct nfs_args in the kernel.
924 if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
925 error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
930 if (args.version != NFS_ARGSVERSION) {
931 error = EPROGMISMATCH;
934 has_nfs_args_opt = 1;
937 /* Handle the new style options. */
938 if (vfs_getopt(mp->mnt_optnew, "noac", NULL, NULL) == 0) {
939 args.acdirmin = args.acdirmax =
940 args.acregmin = args.acregmax = 0;
941 args.flags |= NFSMNT_ACDIRMIN | NFSMNT_ACDIRMAX |
942 NFSMNT_ACREGMIN | NFSMNT_ACREGMAX;
944 if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
945 args.flags |= NFSMNT_NOCONN;
946 if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
947 args.flags &= ~NFSMNT_NOCONN;
948 if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
949 args.flags |= NFSMNT_NOLOCKD;
950 if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
951 args.flags &= ~NFSMNT_NOLOCKD;
952 if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
953 args.flags |= NFSMNT_INT;
954 if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
955 args.flags |= NFSMNT_RDIRPLUS;
956 if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
957 args.flags |= NFSMNT_RESVPORT;
958 if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
959 args.flags &= ~NFSMNT_RESVPORT;
960 if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
961 args.flags |= NFSMNT_SOFT;
962 if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
963 args.flags &= ~NFSMNT_SOFT;
964 if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
965 args.sotype = SOCK_DGRAM;
966 if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
967 args.sotype = SOCK_DGRAM;
968 if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
969 args.sotype = SOCK_STREAM;
970 if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
971 args.flags |= NFSMNT_NFSV3;
972 if (vfs_getopt(mp->mnt_optnew, "nfsv4", NULL, NULL) == 0) {
973 args.flags |= NFSMNT_NFSV4;
974 args.sotype = SOCK_STREAM;
976 if (vfs_getopt(mp->mnt_optnew, "allgssname", NULL, NULL) == 0)
977 args.flags |= NFSMNT_ALLGSSNAME;
978 if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0)
979 args.flags |= NFSMNT_NOCTO;
980 if (vfs_getopt(mp->mnt_optnew, "noncontigwr", NULL, NULL) == 0)
981 args.flags |= NFSMNT_NONCONTIGWR;
982 if (vfs_getopt(mp->mnt_optnew, "pnfs", NULL, NULL) == 0)
983 args.flags |= NFSMNT_PNFS;
984 if (vfs_getopt(mp->mnt_optnew, "oneopenown", NULL, NULL) == 0)
985 args.flags |= NFSMNT_ONEOPENOWN;
986 if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
988 vfs_mount_error(mp, "illegal readdirsize");
992 ret = sscanf(opt, "%d", &args.readdirsize);
993 if (ret != 1 || args.readdirsize <= 0) {
994 vfs_mount_error(mp, "illegal readdirsize: %s",
999 args.flags |= NFSMNT_READDIRSIZE;
1001 if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
1003 vfs_mount_error(mp, "illegal readahead");
1007 ret = sscanf(opt, "%d", &args.readahead);
1008 if (ret != 1 || args.readahead <= 0) {
1009 vfs_mount_error(mp, "illegal readahead: %s",
1014 args.flags |= NFSMNT_READAHEAD;
1016 if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
1018 vfs_mount_error(mp, "illegal wsize");
1022 ret = sscanf(opt, "%d", &args.wsize);
1023 if (ret != 1 || args.wsize <= 0) {
1024 vfs_mount_error(mp, "illegal wsize: %s",
1029 args.flags |= NFSMNT_WSIZE;
1031 if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
1033 vfs_mount_error(mp, "illegal rsize");
1037 ret = sscanf(opt, "%d", &args.rsize);
1038 if (ret != 1 || args.rsize <= 0) {
1039 vfs_mount_error(mp, "illegal wsize: %s",
1044 args.flags |= NFSMNT_RSIZE;
1046 if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
1048 vfs_mount_error(mp, "illegal retrans");
1052 ret = sscanf(opt, "%d", &args.retrans);
1053 if (ret != 1 || args.retrans <= 0) {
1054 vfs_mount_error(mp, "illegal retrans: %s",
1059 args.flags |= NFSMNT_RETRANS;
1061 if (vfs_getopt(mp->mnt_optnew, "actimeo", (void **)&opt, NULL) == 0) {
1062 ret = sscanf(opt, "%d", &args.acregmin);
1063 if (ret != 1 || args.acregmin < 0) {
1064 vfs_mount_error(mp, "illegal actimeo: %s",
1069 args.acdirmin = args.acdirmax = args.acregmax = args.acregmin;
1070 args.flags |= NFSMNT_ACDIRMIN | NFSMNT_ACDIRMAX |
1071 NFSMNT_ACREGMIN | NFSMNT_ACREGMAX;
1073 if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
1074 ret = sscanf(opt, "%d", &args.acregmin);
1075 if (ret != 1 || args.acregmin < 0) {
1076 vfs_mount_error(mp, "illegal acregmin: %s",
1081 args.flags |= NFSMNT_ACREGMIN;
1083 if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
1084 ret = sscanf(opt, "%d", &args.acregmax);
1085 if (ret != 1 || args.acregmax < 0) {
1086 vfs_mount_error(mp, "illegal acregmax: %s",
1091 args.flags |= NFSMNT_ACREGMAX;
1093 if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
1094 ret = sscanf(opt, "%d", &args.acdirmin);
1095 if (ret != 1 || args.acdirmin < 0) {
1096 vfs_mount_error(mp, "illegal acdirmin: %s",
1101 args.flags |= NFSMNT_ACDIRMIN;
1103 if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
1104 ret = sscanf(opt, "%d", &args.acdirmax);
1105 if (ret != 1 || args.acdirmax < 0) {
1106 vfs_mount_error(mp, "illegal acdirmax: %s",
1111 args.flags |= NFSMNT_ACDIRMAX;
1113 if (vfs_getopt(mp->mnt_optnew, "wcommitsize", (void **)&opt, NULL) == 0) {
1114 ret = sscanf(opt, "%d", &args.wcommitsize);
1115 if (ret != 1 || args.wcommitsize < 0) {
1116 vfs_mount_error(mp, "illegal wcommitsize: %s", opt);
1120 args.flags |= NFSMNT_WCOMMITSIZE;
1122 if (vfs_getopt(mp->mnt_optnew, "timeo", (void **)&opt, NULL) == 0) {
1123 ret = sscanf(opt, "%d", &args.timeo);
1124 if (ret != 1 || args.timeo <= 0) {
1125 vfs_mount_error(mp, "illegal timeo: %s",
1130 args.flags |= NFSMNT_TIMEO;
1132 if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
1133 ret = sscanf(opt, "%d", &args.timeo);
1134 if (ret != 1 || args.timeo <= 0) {
1135 vfs_mount_error(mp, "illegal timeout: %s",
1140 args.flags |= NFSMNT_TIMEO;
1142 if (vfs_getopt(mp->mnt_optnew, "nametimeo", (void **)&opt, NULL) == 0) {
1143 ret = sscanf(opt, "%d", &nametimeo);
1144 if (ret != 1 || nametimeo < 0) {
1145 vfs_mount_error(mp, "illegal nametimeo: %s", opt);
1150 if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
1152 ret = sscanf(opt, "%d", &negnametimeo);
1153 if (ret != 1 || negnametimeo < 0) {
1154 vfs_mount_error(mp, "illegal negnametimeo: %s",
1160 if (vfs_getopt(mp->mnt_optnew, "minorversion", (void **)&opt, NULL) ==
1162 ret = sscanf(opt, "%d", &minvers);
1163 if (ret != 1 || minvers < 0 || minvers > 2 ||
1164 (args.flags & NFSMNT_NFSV4) == 0) {
1165 vfs_mount_error(mp, "illegal minorversion: %s", opt);
1170 if (vfs_getopt(mp->mnt_optnew, "sec",
1171 (void **) &secname, NULL) == 0)
1172 nfs_sec_name(secname, &args.flags);
1174 if (mp->mnt_flag & MNT_UPDATE) {
1175 struct nfsmount *nmp = VFSTONFS(mp);
1183 * If a change from TCP->UDP is done and there are thread(s)
1184 * that have I/O RPC(s) in progress with a transfer size
1185 * greater than NFS_MAXDGRAMDATA, those thread(s) will be
1186 * hung, retrying the RPC(s) forever. Usually these threads
1187 * will be seen doing an uninterruptible sleep on wait channel
1190 if (args.sotype == SOCK_DGRAM && nmp->nm_sotype == SOCK_STREAM)
1191 tprintf(td->td_proc, LOG_WARNING,
1192 "Warning: mount -u that changes TCP->UDP can result in hung threads\n");
1195 * When doing an update, we can't change version,
1196 * security, switch lockd strategies, change cookie
1197 * translation or switch oneopenown.
1199 args.flags = (args.flags &
1206 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
1214 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
1215 nfs_decode_args(mp, nmp, &args, NULL, td->td_ucred, td);
1220 * Make the nfs_ip_paranoia sysctl serve as the default connection
1221 * or no-connection mode for those protocols that support
1222 * no-connection mode (the flag will be cleared later for protocols
1223 * that do not support no-connection mode). This will allow a client
1224 * to receive replies from a different IP then the request was
1225 * sent to. Note: default value for nfs_ip_paranoia is 1 (paranoid),
1228 if (nfs_ip_paranoia == 0)
1229 args.flags |= NFSMNT_NOCONN;
1231 if (has_nfs_args_opt != 0) {
1233 * In the 'nfs_args' case, the pointers in the args
1234 * structure are in userland - we copy them in here.
1236 if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
1237 vfs_mount_error(mp, "Bad file handle");
1241 error = copyin((caddr_t)args.fh, (caddr_t)nfh,
1245 error = copyinstr(args.hostname, hst, MNAMELEN - 1, &hstlen);
1248 bzero(&hst[hstlen], MNAMELEN - hstlen);
1249 args.hostname = hst;
1250 /* getsockaddr() call must be after above copyin() calls */
1251 error = getsockaddr(&nam, args.addr, args.addrlen);
1254 } else if (nfs_mount_parse_from(mp->mnt_optnew,
1255 &args.hostname, (struct sockaddr_in **)&nam, dirpath,
1256 sizeof(dirpath), &dirlen) == 0) {
1257 has_nfs_from_opt = 1;
1258 bcopy(args.hostname, hst, MNAMELEN);
1259 hst[MNAMELEN - 1] = '\0';
1262 * This only works with NFSv4 for now.
1265 args.flags |= NFSMNT_NFSV4;
1266 args.sotype = SOCK_STREAM;
1268 if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
1269 &args.fhsize) == 0) {
1270 if (args.fhsize < 0 || args.fhsize > NFSX_FHMAX) {
1271 vfs_mount_error(mp, "Bad file handle");
1275 bcopy(args.fh, nfh, args.fhsize);
1279 (void) vfs_getopt(mp->mnt_optnew, "hostname",
1280 (void **)&args.hostname, &len);
1281 if (args.hostname == NULL) {
1282 vfs_mount_error(mp, "Invalid hostname");
1286 if (len >= MNAMELEN) {
1287 vfs_mount_error(mp, "Hostname too long");
1291 bcopy(args.hostname, hst, len);
1295 if (vfs_getopt(mp->mnt_optnew, "principal", (void **)&name, NULL) == 0)
1296 strlcpy(srvkrbname, name, sizeof (srvkrbname));
1298 snprintf(srvkrbname, sizeof (srvkrbname), "nfs@%s", hst);
1299 cp = strchr(srvkrbname, ':');
1303 srvkrbnamelen = strlen(srvkrbname);
1305 if (vfs_getopt(mp->mnt_optnew, "gssname", (void **)&name, NULL) == 0)
1306 strlcpy(krbname, name, sizeof (krbname));
1309 krbnamelen = strlen(krbname);
1311 if (has_nfs_from_opt == 0) {
1312 if (vfs_getopt(mp->mnt_optnew,
1313 "dirpath", (void **)&name, NULL) == 0)
1314 strlcpy(dirpath, name, sizeof (dirpath));
1317 dirlen = strlen(dirpath);
1320 if (has_nfs_args_opt == 0 && has_nfs_from_opt == 0) {
1321 if (vfs_getopt(mp->mnt_optnew, "addr",
1322 (void **)&args.addr, &args.addrlen) == 0) {
1323 if (args.addrlen > SOCK_MAXADDRLEN) {
1324 error = ENAMETOOLONG;
1327 nam = malloc(args.addrlen, M_SONAME, M_WAITOK);
1328 bcopy(args.addr, nam, args.addrlen);
1329 nam->sa_len = args.addrlen;
1331 vfs_mount_error(mp, "No server address");
1338 error = mountnfs(&args, mp, nam, hst, krbname, krbnamelen, dirpath,
1339 dirlen, srvkrbname, srvkrbnamelen, &vp, td->td_ucred, td,
1340 nametimeo, negnametimeo, minvers);
1344 mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED | MNTK_NO_IOPF |
1346 if ((VFSTONFS(mp)->nm_flag & NFSMNT_NFSV4) != 0)
1347 mp->mnt_kern_flag |= MNTK_NULL_NOCACHE;
1359 * It seems a bit dumb to copyinstr() the host and path here and then
1360 * bcopy() them in mountnfs(), but I wanted to detect errors before
1361 * doing the getsockaddr() call because getsockaddr() allocates an mbuf and
1362 * an error after that means that I have to release the mbuf.
1366 nfs_cmount(struct mntarg *ma, void *data, uint64_t flags)
1369 struct nfs_args args;
1371 error = copyin(data, &args, sizeof (struct nfs_args));
1375 ma = mount_arg(ma, "nfs_args", &args, sizeof args);
1377 error = kernel_mount(ma, flags);
1382 * Common code for mount and mountroot
1385 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
1386 char *hst, u_char *krbname, int krbnamelen, u_char *dirpath, int dirlen,
1387 u_char *srvkrbname, int srvkrbnamelen, struct vnode **vpp,
1388 struct ucred *cred, struct thread *td, int nametimeo, int negnametimeo,
1391 struct nfsmount *nmp;
1393 int error, trycnt, ret;
1394 struct nfsvattr nfsva;
1395 struct nfsclclient *clp;
1396 struct nfsclds *dsp, *tdsp;
1398 static u_int64_t clval = 0;
1400 NFSCL_DEBUG(3, "in mnt\n");
1402 if (mp->mnt_flag & MNT_UPDATE) {
1404 printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
1405 free(nam, M_SONAME);
1408 nmp = malloc(sizeof (struct nfsmount) +
1409 krbnamelen + dirlen + srvkrbnamelen + 2,
1410 M_NEWNFSMNT, M_WAITOK | M_ZERO);
1411 TAILQ_INIT(&nmp->nm_bufq);
1412 TAILQ_INIT(&nmp->nm_sess);
1414 clval = (u_int64_t)nfsboottime.tv_sec;
1415 nmp->nm_clval = clval++;
1416 nmp->nm_krbnamelen = krbnamelen;
1417 nmp->nm_dirpathlen = dirlen;
1418 nmp->nm_srvkrbnamelen = srvkrbnamelen;
1419 if (td->td_ucred->cr_uid != (uid_t)0) {
1421 * nm_uid is used to get KerberosV credentials for
1422 * the nfsv4 state handling operations if there is
1423 * no host based principal set. Use the uid of
1424 * this user if not root, since they are doing the
1425 * mount. I don't think setting this for root will
1426 * work, since root normally does not have user
1427 * credentials in a credentials cache.
1429 nmp->nm_uid = td->td_ucred->cr_uid;
1432 * Just set to -1, so it won't be used.
1434 nmp->nm_uid = (uid_t)-1;
1437 /* Copy and null terminate all the names */
1438 if (nmp->nm_krbnamelen > 0) {
1439 bcopy(krbname, nmp->nm_krbname, nmp->nm_krbnamelen);
1440 nmp->nm_name[nmp->nm_krbnamelen] = '\0';
1442 if (nmp->nm_dirpathlen > 0) {
1443 bcopy(dirpath, NFSMNT_DIRPATH(nmp),
1444 nmp->nm_dirpathlen);
1445 nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1448 if (nmp->nm_srvkrbnamelen > 0) {
1449 bcopy(srvkrbname, NFSMNT_SRVKRBNAME(nmp),
1450 nmp->nm_srvkrbnamelen);
1451 nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1452 + nmp->nm_srvkrbnamelen + 2] = '\0';
1454 nmp->nm_sockreq.nr_cred = crhold(cred);
1455 mtx_init(&nmp->nm_sockreq.nr_mtx, "nfssock", NULL, MTX_DEF);
1457 nmp->nm_getinfo = nfs_getnlminfo;
1458 nmp->nm_vinvalbuf = ncl_vinvalbuf;
1461 nmp->nm_mountp = mp;
1462 mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF | MTX_DUPOK);
1465 * Since nfs_decode_args() might optionally set them, these
1466 * need to be set to defaults before the call, so that the
1467 * optional settings aren't overwritten.
1469 nmp->nm_nametimeo = nametimeo;
1470 nmp->nm_negnametimeo = negnametimeo;
1471 nmp->nm_timeo = NFS_TIMEO;
1472 nmp->nm_retry = NFS_RETRANS;
1473 nmp->nm_readahead = NFS_DEFRAHEAD;
1475 /* This is empirical approximation of sqrt(hibufspace) * 256. */
1476 nmp->nm_wcommitsize = NFS_MAXBSIZE / 256;
1477 while ((long)nmp->nm_wcommitsize * nmp->nm_wcommitsize < hibufspace)
1478 nmp->nm_wcommitsize *= 2;
1479 nmp->nm_wcommitsize *= 256;
1481 if ((argp->flags & NFSMNT_NFSV4) != 0)
1482 nmp->nm_minorvers = minvers;
1484 nmp->nm_minorvers = 0;
1486 nfs_decode_args(mp, nmp, argp, hst, cred, td);
1489 * V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too
1490 * high, depending on whether we end up with negative offsets in
1491 * the client or server somewhere. 2GB-1 may be safer.
1493 * For V3, ncl_fsinfo will adjust this as necessary. Assume maximum
1494 * that we can handle until we find out otherwise.
1496 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0)
1497 nmp->nm_maxfilesize = 0xffffffffLL;
1499 nmp->nm_maxfilesize = OFF_MAX;
1501 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
1502 nmp->nm_wsize = NFS_WSIZE;
1503 nmp->nm_rsize = NFS_RSIZE;
1504 nmp->nm_readdirsize = NFS_READDIRSIZE;
1506 nmp->nm_numgrps = NFS_MAXGRPS;
1507 nmp->nm_tprintf_delay = nfs_tprintf_delay;
1508 if (nmp->nm_tprintf_delay < 0)
1509 nmp->nm_tprintf_delay = 0;
1510 nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
1511 if (nmp->nm_tprintf_initial_delay < 0)
1512 nmp->nm_tprintf_initial_delay = 0;
1513 nmp->nm_fhsize = argp->fhsize;
1514 if (nmp->nm_fhsize > 0)
1515 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
1516 bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
1518 /* Set up the sockets and per-host congestion */
1519 nmp->nm_sotype = argp->sotype;
1520 nmp->nm_soproto = argp->proto;
1521 nmp->nm_sockreq.nr_prog = NFS_PROG;
1522 if ((argp->flags & NFSMNT_NFSV4))
1523 nmp->nm_sockreq.nr_vers = NFS_VER4;
1524 else if ((argp->flags & NFSMNT_NFSV3))
1525 nmp->nm_sockreq.nr_vers = NFS_VER3;
1527 nmp->nm_sockreq.nr_vers = NFS_VER2;
1530 if ((error = newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0)))
1532 /* For NFSv4.1, get the clientid now. */
1533 if (nmp->nm_minorvers > 0) {
1534 NFSCL_DEBUG(3, "at getcl\n");
1535 error = nfscl_getcl(mp, cred, td, 0, &clp);
1536 NFSCL_DEBUG(3, "aft getcl=%d\n", error);
1541 if (nmp->nm_fhsize == 0 && (nmp->nm_flag & NFSMNT_NFSV4) &&
1542 nmp->nm_dirpathlen > 0) {
1543 NFSCL_DEBUG(3, "in dirp\n");
1545 * If the fhsize on the mount point == 0 for V4, the mount
1546 * path needs to be looked up.
1550 error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp),
1552 NFSCL_DEBUG(3, "aft dirp=%d\n", error);
1554 (void) nfs_catnap(PZERO, error, "nfsgetdirp");
1555 } while (error && --trycnt > 0);
1561 * A reference count is needed on the nfsnode representing the
1562 * remote root. If this object is not persistent, then backward
1563 * traversals of the mount point (i.e. "..") will not work if
1564 * the nfsnode gets flushed out of the cache. Ufs does not have
1565 * this problem, because one can identify root inodes by their
1566 * number == UFS_ROOTINO (2).
1568 if (nmp->nm_fhsize > 0) {
1570 * Set f_iosize to NFS_DIRBLKSIZ so that bo_bsize gets set
1571 * non-zero for the root vnode. f_iosize will be set correctly
1572 * by nfs_statfs() before any I/O occurs.
1574 mp->mnt_stat.f_iosize = NFS_DIRBLKSIZ;
1575 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np,
1582 * Get file attributes and transfer parameters for the
1583 * mountpoint. This has the side effect of filling in
1584 * (*vpp)->v_type with the correct value.
1586 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
1587 cred, td, &nfsva, NULL, &lease);
1590 * Just set default values to get things going.
1592 NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
1593 nfsva.na_vattr.va_type = VDIR;
1594 nfsva.na_vattr.va_mode = 0777;
1595 nfsva.na_vattr.va_nlink = 100;
1596 nfsva.na_vattr.va_uid = (uid_t)0;
1597 nfsva.na_vattr.va_gid = (gid_t)0;
1598 nfsva.na_vattr.va_fileid = 2;
1599 nfsva.na_vattr.va_gen = 1;
1600 nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
1601 nfsva.na_vattr.va_size = 512 * 1024;
1604 (void) nfscl_loadattrcache(vpp, &nfsva, NULL, NULL, 0, 1);
1605 if (nmp->nm_minorvers > 0) {
1606 NFSCL_DEBUG(3, "lease=%d\n", (int)lease);
1608 clp->nfsc_renew = NFSCL_RENEW(lease);
1609 clp->nfsc_expire = NFSD_MONOSEC + clp->nfsc_renew;
1610 clp->nfsc_clientidrev++;
1611 if (clp->nfsc_clientidrev == 0)
1612 clp->nfsc_clientidrev++;
1615 * Mount will succeed, so the renew thread can be
1618 nfscl_start_renewthread(clp);
1619 nfscl_clientrelease(clp);
1621 if (argp->flags & NFSMNT_NFSV3)
1622 ncl_fsinfo(nmp, *vpp, cred, td);
1624 /* Mark if the mount point supports NFSv4 ACLs. */
1625 if ((argp->flags & NFSMNT_NFSV4) != 0 && nfsrv_useacl != 0 &&
1627 NFSISSET_ATTRBIT(&nfsva.na_suppattr, NFSATTRBIT_ACL)) {
1629 mp->mnt_flag |= MNT_NFS4ACLS;
1634 * Lose the lock but keep the ref.
1637 vfs_cache_root_set(mp, *vpp);
1644 nfscl_clientrelease(clp);
1645 newnfs_disconnect(&nmp->nm_sockreq);
1646 crfree(nmp->nm_sockreq.nr_cred);
1647 if (nmp->nm_sockreq.nr_auth != NULL)
1648 AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
1649 mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1650 mtx_destroy(&nmp->nm_mtx);
1651 if (nmp->nm_clp != NULL) {
1653 LIST_REMOVE(nmp->nm_clp, nfsc_list);
1655 free(nmp->nm_clp, M_NFSCLCLIENT);
1657 TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp) {
1658 if (dsp != TAILQ_FIRST(&nmp->nm_sess) &&
1659 dsp->nfsclds_sockp != NULL)
1660 newnfs_disconnect(dsp->nfsclds_sockp);
1661 nfscl_freenfsclds(dsp);
1663 free(nmp, M_NEWNFSMNT);
1664 free(nam, M_SONAME);
1669 * unmount system call
1672 nfs_unmount(struct mount *mp, int mntflags)
1675 struct nfsmount *nmp;
1676 int error, flags = 0, i, trycnt = 0;
1677 struct nfsclds *dsp, *tdsp;
1681 if (mntflags & MNT_FORCE)
1682 flags |= FORCECLOSE;
1686 * Goes something like this..
1687 * - Call vflush() to clear out vnodes for this filesystem
1688 * - Close the socket
1689 * - Free up the data structures
1691 /* In the forced case, cancel any outstanding requests. */
1692 if (mntflags & MNT_FORCE) {
1694 if (nfsv4_findmirror(nmp) != NULL)
1699 error = newnfs_nmcancelreqs(nmp);
1702 /* For a forced close, get rid of the renew thread now */
1703 nfscl_umount(nmp, td);
1705 /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
1707 error = vflush(mp, 1, flags, td);
1708 if ((mntflags & MNT_FORCE) && error != 0 && ++trycnt < 30)
1709 (void) nfs_catnap(PSOCK, error, "newndm");
1710 } while ((mntflags & MNT_FORCE) && error != 0 && trycnt < 30);
1715 * We are now committed to the unmount.
1717 if ((mntflags & MNT_FORCE) == 0)
1718 nfscl_umount(nmp, td);
1720 mtx_lock(&nmp->nm_mtx);
1721 nmp->nm_privflag |= NFSMNTP_FORCEDISM;
1722 mtx_unlock(&nmp->nm_mtx);
1724 /* Make sure no nfsiods are assigned to this mount. */
1726 for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
1727 if (ncl_iodmount[i] == nmp) {
1728 ncl_iodwant[i] = NFSIOD_AVAILABLE;
1729 ncl_iodmount[i] = NULL;
1734 * We can now set mnt_data to NULL and wait for
1735 * nfssvc(NFSSVC_FORCEDISM) to complete.
1737 mtx_lock(&mountlist_mtx);
1738 mtx_lock(&nmp->nm_mtx);
1739 mp->mnt_data = NULL;
1740 mtx_unlock(&mountlist_mtx);
1741 while ((nmp->nm_privflag & NFSMNTP_CANCELRPCS) != 0)
1742 msleep(nmp, &nmp->nm_mtx, PVFS, "nfsfdism", 0);
1743 mtx_unlock(&nmp->nm_mtx);
1745 newnfs_disconnect(&nmp->nm_sockreq);
1746 crfree(nmp->nm_sockreq.nr_cred);
1747 free(nmp->nm_nam, M_SONAME);
1748 if (nmp->nm_sockreq.nr_auth != NULL)
1749 AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
1750 mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1751 mtx_destroy(&nmp->nm_mtx);
1752 TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp) {
1753 if (dsp != TAILQ_FIRST(&nmp->nm_sess) &&
1754 dsp->nfsclds_sockp != NULL)
1755 newnfs_disconnect(dsp->nfsclds_sockp);
1756 nfscl_freenfsclds(dsp);
1758 free(nmp, M_NEWNFSMNT);
1764 * Return root of a filesystem
1767 nfs_root(struct mount *mp, int flags, struct vnode **vpp)
1770 struct nfsmount *nmp;
1775 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, flags);
1780 * Get transfer parameters and attributes for root vnode once.
1782 mtx_lock(&nmp->nm_mtx);
1783 if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
1784 mtx_unlock(&nmp->nm_mtx);
1785 ncl_fsinfo(nmp, vp, curthread->td_ucred, curthread);
1787 mtx_unlock(&nmp->nm_mtx);
1788 if (vp->v_type == VNON)
1790 vp->v_vflag |= VV_ROOT;
1796 * Flush out the buffer cache
1800 nfs_sync(struct mount *mp, int waitfor)
1802 struct vnode *vp, *mvp;
1804 int error, allerror = 0;
1810 * If a forced dismount is in progress, return from here so that
1811 * the umount(2) syscall doesn't get stuck in VFS_SYNC() before
1812 * calling VFS_UNMOUNT().
1814 if (NFSCL_FORCEDISM(mp)) {
1821 * Force stale buffer cache information to be flushed.
1824 MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
1825 /* XXX Racy bv_cnt check. */
1826 if (NFSVOPISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
1827 waitfor == MNT_LAZY) {
1831 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
1832 MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
1835 error = VOP_FSYNC(vp, waitfor, td);
1845 nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
1847 struct nfsmount *nmp = VFSTONFS(mp);
1851 bzero(&vq, sizeof(vq));
1854 case VFS_CTL_NOLOCKS:
1855 val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
1856 if (req->oldptr != NULL) {
1857 error = SYSCTL_OUT(req, &val, sizeof(val));
1861 if (req->newptr != NULL) {
1862 error = SYSCTL_IN(req, &val, sizeof(val));
1866 nmp->nm_flag |= NFSMNT_NOLOCKS;
1868 nmp->nm_flag &= ~NFSMNT_NOLOCKS;
1873 mtx_lock(&nmp->nm_mtx);
1874 if (nmp->nm_state & NFSSTA_TIMEO)
1875 vq.vq_flags |= VQ_NOTRESP;
1876 mtx_unlock(&nmp->nm_mtx);
1878 if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
1879 (nmp->nm_state & NFSSTA_LOCKTIMEO))
1880 vq.vq_flags |= VQ_NOTRESPLOCK;
1882 error = SYSCTL_OUT(req, &vq, sizeof(vq));
1885 if (req->oldptr != NULL) {
1886 error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
1887 sizeof(nmp->nm_tprintf_initial_delay));
1891 if (req->newptr != NULL) {
1892 error = vfs_suser(mp, req->td);
1895 error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
1896 sizeof(nmp->nm_tprintf_initial_delay));
1899 if (nmp->nm_tprintf_initial_delay < 0)
1900 nmp->nm_tprintf_initial_delay = 0;
1910 * Purge any RPCs in progress, so that they will all return errors.
1911 * This allows dounmount() to continue as far as VFS_UNMOUNT() for a
1915 nfs_purge(struct mount *mp)
1917 struct nfsmount *nmp = VFSTONFS(mp);
1919 newnfs_nmcancelreqs(nmp);
1923 * Extract the information needed by the nlm from the nfs vnode.
1926 nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp,
1927 struct sockaddr_storage *sp, int *is_v3p, off_t *sizep,
1928 struct timeval *timeop)
1930 struct nfsmount *nmp;
1931 struct nfsnode *np = VTONFS(vp);
1933 nmp = VFSTONFS(vp->v_mount);
1935 *fhlenp = (size_t)np->n_fhp->nfh_len;
1937 bcopy(np->n_fhp->nfh_fh, fhp, np->n_fhp->nfh_len);
1939 bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp)));
1941 *is_v3p = NFS_ISV3(vp);
1943 *sizep = np->n_size;
1944 if (timeop != NULL) {
1945 timeop->tv_sec = nmp->nm_timeo / NFS_HZ;
1946 timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ);
1951 * This function prints out an option name, based on the conditional
1954 static __inline void nfscl_printopt(struct nfsmount *nmp, int testval,
1955 char *opt, char **buf, size_t *blen)
1959 if (testval != 0 && *blen > strlen(opt)) {
1960 len = snprintf(*buf, *blen, "%s", opt);
1961 if (len != strlen(opt))
1969 * This function printf out an options integer value.
1971 static __inline void nfscl_printoptval(struct nfsmount *nmp, int optval,
1972 char *opt, char **buf, size_t *blen)
1976 if (*blen > strlen(opt) + 1) {
1977 /* Could result in truncated output string. */
1978 len = snprintf(*buf, *blen, "%s=%d", opt, optval);
1987 * Load the option flags and values into the buffer.
1989 void nfscl_retopts(struct nfsmount *nmp, char *buffer, size_t buflen)
1996 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV4) != 0, "nfsv4", &buf,
1998 if ((nmp->nm_flag & NFSMNT_NFSV4) != 0) {
1999 nfscl_printoptval(nmp, nmp->nm_minorvers, ",minorversion", &buf,
2001 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_PNFS) != 0, ",pnfs",
2003 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_ONEOPENOWN) != 0 &&
2004 nmp->nm_minorvers > 0, ",oneopenown", &buf, &blen);
2006 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV3) != 0, "nfsv3", &buf,
2008 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0,
2009 "nfsv2", &buf, &blen);
2010 nfscl_printopt(nmp, nmp->nm_sotype == SOCK_STREAM, ",tcp", &buf, &blen);
2011 nfscl_printopt(nmp, nmp->nm_sotype != SOCK_STREAM, ",udp", &buf, &blen);
2012 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RESVPORT) != 0, ",resvport",
2014 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCONN) != 0, ",noconn",
2016 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) == 0, ",hard", &buf,
2018 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) != 0, ",soft", &buf,
2020 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_INT) != 0, ",intr", &buf,
2022 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) == 0, ",cto", &buf,
2024 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) != 0, ",nocto", &buf,
2026 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NONCONTIGWR) != 0,
2027 ",noncontigwr", &buf, &blen);
2028 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
2029 0, ",lockd", &buf, &blen);
2030 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
2031 NFSMNT_NOLOCKD, ",nolockd", &buf, &blen);
2032 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RDIRPLUS) != 0, ",rdirplus",
2034 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_KERB) == 0, ",sec=sys",
2036 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
2037 NFSMNT_PRIVACY)) == NFSMNT_KERB, ",sec=krb5", &buf, &blen);
2038 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
2039 NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_INTEGRITY), ",sec=krb5i",
2041 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
2042 NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_PRIVACY), ",sec=krb5p",
2044 nfscl_printoptval(nmp, nmp->nm_acdirmin, ",acdirmin", &buf, &blen);
2045 nfscl_printoptval(nmp, nmp->nm_acdirmax, ",acdirmax", &buf, &blen);
2046 nfscl_printoptval(nmp, nmp->nm_acregmin, ",acregmin", &buf, &blen);
2047 nfscl_printoptval(nmp, nmp->nm_acregmax, ",acregmax", &buf, &blen);
2048 nfscl_printoptval(nmp, nmp->nm_nametimeo, ",nametimeo", &buf, &blen);
2049 nfscl_printoptval(nmp, nmp->nm_negnametimeo, ",negnametimeo", &buf,
2051 nfscl_printoptval(nmp, nmp->nm_rsize, ",rsize", &buf, &blen);
2052 nfscl_printoptval(nmp, nmp->nm_wsize, ",wsize", &buf, &blen);
2053 nfscl_printoptval(nmp, nmp->nm_readdirsize, ",readdirsize", &buf,
2055 nfscl_printoptval(nmp, nmp->nm_readahead, ",readahead", &buf, &blen);
2056 nfscl_printoptval(nmp, nmp->nm_wcommitsize, ",wcommitsize", &buf,
2058 nfscl_printoptval(nmp, nmp->nm_timeo, ",timeout", &buf, &blen);
2059 nfscl_printoptval(nmp, nmp->nm_retry, ",retrans", &buf, &blen);