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;
90 MALLOC_DEFINE(M_NEWNFSREQ, "newnfsclient_req", "NFS request header");
91 MALLOC_DEFINE(M_NEWNFSMNT, "newnfsmnt", "NFS mount struct");
93 SYSCTL_DECL(_vfs_nfs);
94 static int nfs_ip_paranoia = 1;
95 SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW,
96 &nfs_ip_paranoia, 0, "");
97 static int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
98 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_INITIAL_DELAY,
99 downdelayinitial, CTLFLAG_RW, &nfs_tprintf_initial_delay, 0, "");
100 /* how long between console messages "nfs server foo not responding" */
101 static int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
102 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_DELAY,
103 downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0, "");
106 SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0,
107 "Toggle debug flag");
110 static int nfs_mountroot(struct mount *);
111 static void nfs_sec_name(char *, int *);
112 static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp,
113 struct nfs_args *argp, const char *, struct ucred *,
115 static int mountnfs(struct nfs_args *, struct mount *,
116 struct sockaddr *, char *, u_char *, int, u_char *, int,
117 u_char *, int, struct vnode **, struct ucred *,
118 struct thread *, int, int, int);
119 static void nfs_getnlminfo(struct vnode *, uint8_t *, size_t *,
120 struct sockaddr_storage *, int *, off_t *,
122 static vfs_mount_t nfs_mount;
123 static vfs_cmount_t nfs_cmount;
124 static vfs_unmount_t nfs_unmount;
125 static vfs_root_t nfs_root;
126 static vfs_statfs_t nfs_statfs;
127 static vfs_sync_t nfs_sync;
128 static vfs_sysctl_t nfs_sysctl;
129 static vfs_purge_t nfs_purge;
132 * nfs vfs operations.
134 static struct vfsops nfs_vfsops = {
135 .vfs_init = ncl_init,
136 .vfs_mount = nfs_mount,
137 .vfs_cmount = nfs_cmount,
138 .vfs_root = nfs_root,
139 .vfs_statfs = nfs_statfs,
140 .vfs_sync = nfs_sync,
141 .vfs_uninit = ncl_uninit,
142 .vfs_unmount = nfs_unmount,
143 .vfs_sysctl = nfs_sysctl,
144 .vfs_purge = nfs_purge,
146 VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK | VFCF_SBDRY);
148 /* So that loader and kldload(2) can find us, wherever we are.. */
149 MODULE_VERSION(nfs, 1);
150 MODULE_DEPEND(nfs, nfscommon, 1, 1, 1);
151 MODULE_DEPEND(nfs, krpc, 1, 1, 1);
152 MODULE_DEPEND(nfs, nfssvc, 1, 1, 1);
153 MODULE_DEPEND(nfs, nfslock, 1, 1, 1);
156 * This structure is now defined in sys/nfs/nfs_diskless.c so that it
157 * can be shared by both NFS clients. It is declared here so that it
158 * will be defined for kernels built without NFS_ROOT, although it
159 * isn't used in that case.
161 #if !defined(NFS_ROOT)
162 struct nfs_diskless nfs_diskless = { { { 0 } } };
163 struct nfsv3_diskless nfsv3_diskless = { { { 0 } } };
164 int nfs_diskless_valid = 0;
167 SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
168 &nfs_diskless_valid, 0,
169 "Has the diskless struct been filled correctly");
171 SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
172 nfsv3_diskless.root_hostnam, 0, "Path to nfs root");
174 SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
175 &nfsv3_diskless.root_saddr, sizeof(nfsv3_diskless.root_saddr),
176 "%Ssockaddr_in", "Diskless root nfs address");
179 void newnfsargs_ntoh(struct nfs_args *);
180 static int nfs_mountdiskless(char *,
181 struct sockaddr_in *, struct nfs_args *,
182 struct thread *, struct vnode **, struct mount *);
183 static void nfs_convert_diskless(void);
184 static void nfs_convert_oargs(struct nfs_args *args,
185 struct onfs_args *oargs);
188 newnfs_iosize(struct nfsmount *nmp)
192 /* First, set the upper limit for iosize */
193 if (nmp->nm_flag & NFSMNT_NFSV4) {
194 maxio = NFS_MAXBSIZE;
195 } else if (nmp->nm_flag & NFSMNT_NFSV3) {
196 if (nmp->nm_sotype == SOCK_DGRAM)
197 maxio = NFS_MAXDGRAMDATA;
199 maxio = NFS_MAXBSIZE;
201 maxio = NFS_V2MAXDATA;
203 if (nmp->nm_rsize > maxio || nmp->nm_rsize == 0)
204 nmp->nm_rsize = maxio;
205 if (nmp->nm_rsize > NFS_MAXBSIZE)
206 nmp->nm_rsize = NFS_MAXBSIZE;
207 if (nmp->nm_readdirsize > maxio || nmp->nm_readdirsize == 0)
208 nmp->nm_readdirsize = maxio;
209 if (nmp->nm_readdirsize > nmp->nm_rsize)
210 nmp->nm_readdirsize = nmp->nm_rsize;
211 if (nmp->nm_wsize > maxio || nmp->nm_wsize == 0)
212 nmp->nm_wsize = maxio;
213 if (nmp->nm_wsize > NFS_MAXBSIZE)
214 nmp->nm_wsize = NFS_MAXBSIZE;
217 * Calculate the size used for io buffers. Use the larger
218 * of the two sizes to minimise nfs requests but make sure
219 * that it is at least one VM page to avoid wasting buffer
220 * space. It must also be at least NFS_DIRBLKSIZ, since
221 * that is the buffer size used for directories.
223 iosize = imax(nmp->nm_rsize, nmp->nm_wsize);
224 iosize = imax(iosize, PAGE_SIZE);
225 iosize = imax(iosize, NFS_DIRBLKSIZ);
226 nmp->nm_mountp->mnt_stat.f_iosize = iosize;
231 nfs_convert_oargs(struct nfs_args *args, struct onfs_args *oargs)
234 args->version = NFS_ARGSVERSION;
235 args->addr = oargs->addr;
236 args->addrlen = oargs->addrlen;
237 args->sotype = oargs->sotype;
238 args->proto = oargs->proto;
239 args->fh = oargs->fh;
240 args->fhsize = oargs->fhsize;
241 args->flags = oargs->flags;
242 args->wsize = oargs->wsize;
243 args->rsize = oargs->rsize;
244 args->readdirsize = oargs->readdirsize;
245 args->timeo = oargs->timeo;
246 args->retrans = oargs->retrans;
247 args->readahead = oargs->readahead;
248 args->hostname = oargs->hostname;
252 nfs_convert_diskless(void)
255 bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
256 sizeof(struct ifaliasreq));
257 bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
258 sizeof(struct sockaddr_in));
259 nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
260 if (nfsv3_diskless.root_args.flags & NFSMNT_NFSV3) {
261 nfsv3_diskless.root_fhsize = NFSX_MYFH;
262 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_MYFH);
264 nfsv3_diskless.root_fhsize = NFSX_V2FH;
265 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
267 bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
268 sizeof(struct sockaddr_in));
269 bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN);
270 nfsv3_diskless.root_time = nfs_diskless.root_time;
271 bcopy(nfs_diskless.my_hostnam, nfsv3_diskless.my_hostnam,
273 nfs_diskless_valid = 3;
280 nfs_statfs(struct mount *mp, struct statfs *sbp)
284 struct nfsmount *nmp = VFSTONFS(mp);
285 struct nfsvattr nfsva;
288 int error = 0, attrflag, gotfsinfo = 0, ret;
293 error = vfs_busy(mp, MBF_NOWAIT);
296 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
302 mtx_lock(&nmp->nm_mtx);
303 if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
304 mtx_unlock(&nmp->nm_mtx);
305 error = nfsrpc_fsinfo(vp, &fs, td->td_ucred, td, &nfsva,
310 mtx_unlock(&nmp->nm_mtx);
312 error = nfsrpc_statfs(vp, &sb, &fs, td->td_ucred, td, &nfsva,
315 NFSCL_DEBUG(2, "statfs=%d\n", error);
317 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
318 td->td_ucred, td, &nfsva, NULL, NULL);
321 * Just set default values to get things going.
323 NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
324 nfsva.na_vattr.va_type = VDIR;
325 nfsva.na_vattr.va_mode = 0777;
326 nfsva.na_vattr.va_nlink = 100;
327 nfsva.na_vattr.va_uid = (uid_t)0;
328 nfsva.na_vattr.va_gid = (gid_t)0;
329 nfsva.na_vattr.va_fileid = 2;
330 nfsva.na_vattr.va_gen = 1;
331 nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
332 nfsva.na_vattr.va_size = 512 * 1024;
335 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
337 mtx_lock(&nmp->nm_mtx);
338 if (gotfsinfo || (nmp->nm_flag & NFSMNT_NFSV4))
339 nfscl_loadfsinfo(nmp, &fs);
340 nfscl_loadsbinfo(nmp, &sb, sbp);
341 sbp->f_iosize = newnfs_iosize(nmp);
342 mtx_unlock(&nmp->nm_mtx);
343 if (sbp != &mp->mnt_stat) {
344 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
345 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
347 strncpy(&sbp->f_fstypename[0], mp->mnt_vfc->vfc_name, MFSNAMELEN);
348 } else if (NFS_ISV4(vp)) {
349 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
357 * nfs version 3 fsinfo rpc call
360 ncl_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred,
364 struct nfsvattr nfsva;
367 error = nfsrpc_fsinfo(vp, &fs, cred, td, &nfsva, &attrflag, NULL);
370 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0,
372 mtx_lock(&nmp->nm_mtx);
373 nfscl_loadfsinfo(nmp, &fs);
374 mtx_unlock(&nmp->nm_mtx);
380 * Mount a remote root fs via. nfs. This depends on the info in the
381 * nfs_diskless structure that has been filled in properly by some primary
383 * It goes something like this:
384 * - do enough of "ifconfig" by calling ifioctl() so that the system
385 * can talk to the server
386 * - If nfs_diskless.mygateway is filled in, use that address as
388 * - build the rootfs mount point and call mountnfs() to do the rest.
390 * It is assumed to be safe to read, modify, and write the nfsv3_diskless
391 * structure, as well as other global NFS client variables here, as
392 * nfs_mountroot() will be called once in the boot before any other NFS
393 * client activity occurs.
396 nfs_mountroot(struct mount *mp)
398 struct thread *td = curthread;
399 struct nfsv3_diskless *nd = &nfsv3_diskless;
408 #if defined(BOOTP_NFSROOT) && defined(BOOTP)
409 bootpc_init(); /* use bootp to get nfs_diskless filled in */
410 #elif defined(NFS_ROOT)
411 nfs_setup_diskless();
414 if (nfs_diskless_valid == 0)
416 if (nfs_diskless_valid == 1)
417 nfs_convert_diskless();
420 * Do enough of ifconfig(8) so that the critical net interface can
421 * talk to the server.
423 error = socreate(nd->myif.ifra_addr.sa_family, &so, nd->root_args.sotype, 0,
426 panic("nfs_mountroot: socreate(%04x): %d",
427 nd->myif.ifra_addr.sa_family, error);
429 #if 0 /* XXX Bad idea */
431 * We might not have been told the right interface, so we pass
432 * over the first ten interfaces of the same kind, until we get
433 * one of them configured.
436 for (i = strlen(nd->myif.ifra_name) - 1;
437 nd->myif.ifra_name[i] >= '0' &&
438 nd->myif.ifra_name[i] <= '9';
439 nd->myif.ifra_name[i] ++) {
440 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
445 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
447 panic("nfs_mountroot: SIOCAIFADDR: %d", error);
448 if ((cp = kern_getenv("boot.netif.mtu")) != NULL) {
449 ir.ifr_mtu = strtol(cp, NULL, 10);
450 bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ);
452 error = ifioctl(so, SIOCSIFMTU, (caddr_t)&ir, td);
454 printf("nfs_mountroot: SIOCSIFMTU: %d", error);
459 * If the gateway field is filled in, set it as the default route.
460 * Note that pxeboot will set a default route of 0 if the route
461 * is not set by the DHCP server. Check also for a value of 0
462 * to avoid panicking inappropriately in that situation.
464 if (nd->mygateway.sin_len != 0 &&
465 nd->mygateway.sin_addr.s_addr != 0) {
466 struct sockaddr_in mask, sin;
468 bzero((caddr_t)&mask, sizeof(mask));
470 sin.sin_family = AF_INET;
471 sin.sin_len = sizeof(sin);
472 /* XXX MRT use table 0 for this sort of thing */
473 CURVNET_SET(TD_TO_VNET(td));
474 error = rtrequest_fib(RTM_ADD, (struct sockaddr *)&sin,
475 (struct sockaddr *)&nd->mygateway,
476 (struct sockaddr *)&mask,
477 RTF_UP | RTF_GATEWAY, NULL, RT_DEFAULT_FIB);
480 panic("nfs_mountroot: RTM_ADD: %d", error);
484 * Create the rootfs mount point.
486 nd->root_args.fh = nd->root_fh;
487 nd->root_args.fhsize = nd->root_fhsize;
488 l = ntohl(nd->root_saddr.sin_addr.s_addr);
489 snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
490 (l >> 24) & 0xff, (l >> 16) & 0xff,
491 (l >> 8) & 0xff, (l >> 0) & 0xff, nd->root_hostnam);
492 printf("NFS ROOT: %s\n", buf);
493 nd->root_args.hostname = buf;
494 if ((error = nfs_mountdiskless(buf,
495 &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) {
500 * This is not really an nfs issue, but it is much easier to
501 * set hostname here and then let the "/etc/rc.xxx" files
502 * mount the right /var based upon its preset value.
504 mtx_lock(&prison0.pr_mtx);
505 strlcpy(prison0.pr_hostname, nd->my_hostnam,
506 sizeof(prison0.pr_hostname));
507 mtx_unlock(&prison0.pr_mtx);
508 inittodr(ntohl(nd->root_time));
513 * Internal version of mount system call for diskless setup.
516 nfs_mountdiskless(char *path,
517 struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
518 struct vnode **vpp, struct mount *mp)
520 struct sockaddr *nam;
525 * Find the directory path in "path", which also has the server's
526 * name/ip address in it.
528 dirpath = strchr(path, ':');
530 dirlen = strlen(++dirpath);
533 nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
534 if ((error = mountnfs(args, mp, nam, path, NULL, 0, dirpath, dirlen,
535 NULL, 0, vpp, td->td_ucred, td, NFS_DEFAULT_NAMETIMEO,
536 NFS_DEFAULT_NEGNAMETIMEO, 0)) != 0) {
537 printf("nfs_mountroot: mount %s on /: %d\n", path, error);
544 nfs_sec_name(char *sec, int *flagsp)
546 if (!strcmp(sec, "krb5"))
547 *flagsp |= NFSMNT_KERB;
548 else if (!strcmp(sec, "krb5i"))
549 *flagsp |= (NFSMNT_KERB | NFSMNT_INTEGRITY);
550 else if (!strcmp(sec, "krb5p"))
551 *flagsp |= (NFSMNT_KERB | NFSMNT_PRIVACY);
555 nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
556 const char *hostname, struct ucred *cred, struct thread *td)
562 * Set read-only flag if requested; otherwise, clear it if this is
563 * an update. If this is not an update, then either the read-only
564 * flag is already clear, or this is a root mount and it was set
565 * intentionally at some previous point.
567 if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) {
569 mp->mnt_flag |= MNT_RDONLY;
571 } else if (mp->mnt_flag & MNT_UPDATE) {
573 mp->mnt_flag &= ~MNT_RDONLY;
578 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
579 * no sense in that context. Also, set up appropriate retransmit
580 * and soft timeout behavior.
582 if (argp->sotype == SOCK_STREAM) {
583 nmp->nm_flag &= ~NFSMNT_NOCONN;
584 nmp->nm_timeo = NFS_MAXTIMEO;
585 if ((argp->flags & NFSMNT_NFSV4) != 0)
586 nmp->nm_retry = INT_MAX;
588 nmp->nm_retry = NFS_RETRANS_TCP;
591 /* Also clear RDIRPLUS if NFSv2, it crashes some servers */
592 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
593 argp->flags &= ~NFSMNT_RDIRPLUS;
594 nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
597 /* Clear ONEOPENOWN for NFSv2, 3 and 4.0. */
598 if (nmp->nm_minorvers == 0) {
599 argp->flags &= ~NFSMNT_ONEOPENOWN;
600 nmp->nm_flag &= ~NFSMNT_ONEOPENOWN;
603 /* Re-bind if rsrvd port requested and wasn't on one */
604 adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
605 && (argp->flags & NFSMNT_RESVPORT);
606 /* Also re-bind if we're switching to/from a connected UDP socket */
607 adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
608 (argp->flags & NFSMNT_NOCONN));
610 /* Update flags atomically. Don't change the lock bits. */
611 nmp->nm_flag = argp->flags | nmp->nm_flag;
613 if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
614 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
615 if (nmp->nm_timeo < NFS_MINTIMEO)
616 nmp->nm_timeo = NFS_MINTIMEO;
617 else if (nmp->nm_timeo > NFS_MAXTIMEO)
618 nmp->nm_timeo = NFS_MAXTIMEO;
621 if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
622 nmp->nm_retry = argp->retrans;
623 if (nmp->nm_retry > NFS_MAXREXMIT)
624 nmp->nm_retry = NFS_MAXREXMIT;
627 if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
628 nmp->nm_wsize = argp->wsize;
630 * Clip at the power of 2 below the size. There is an
631 * issue (not isolated) that causes intermittent page
632 * faults if this is not done.
634 if (nmp->nm_wsize > NFS_FABLKSIZE)
635 nmp->nm_wsize = 1 << (fls(nmp->nm_wsize) - 1);
637 nmp->nm_wsize = NFS_FABLKSIZE;
640 if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
641 nmp->nm_rsize = argp->rsize;
643 * Clip at the power of 2 below the size. There is an
644 * issue (not isolated) that causes intermittent page
645 * faults if this is not done.
647 if (nmp->nm_rsize > NFS_FABLKSIZE)
648 nmp->nm_rsize = 1 << (fls(nmp->nm_rsize) - 1);
650 nmp->nm_rsize = NFS_FABLKSIZE;
653 if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
654 nmp->nm_readdirsize = argp->readdirsize;
657 if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
658 nmp->nm_acregmin = argp->acregmin;
660 nmp->nm_acregmin = NFS_MINATTRTIMO;
661 if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
662 nmp->nm_acregmax = argp->acregmax;
664 nmp->nm_acregmax = NFS_MAXATTRTIMO;
665 if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
666 nmp->nm_acdirmin = argp->acdirmin;
668 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
669 if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
670 nmp->nm_acdirmax = argp->acdirmax;
672 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
673 if (nmp->nm_acdirmin > nmp->nm_acdirmax)
674 nmp->nm_acdirmin = nmp->nm_acdirmax;
675 if (nmp->nm_acregmin > nmp->nm_acregmax)
676 nmp->nm_acregmin = nmp->nm_acregmax;
678 if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
679 if (argp->readahead <= NFS_MAXRAHEAD)
680 nmp->nm_readahead = argp->readahead;
682 nmp->nm_readahead = NFS_MAXRAHEAD;
684 if ((argp->flags & NFSMNT_WCOMMITSIZE) && argp->wcommitsize >= 0) {
685 if (argp->wcommitsize < nmp->nm_wsize)
686 nmp->nm_wcommitsize = nmp->nm_wsize;
688 nmp->nm_wcommitsize = argp->wcommitsize;
691 adjsock |= ((nmp->nm_sotype != argp->sotype) ||
692 (nmp->nm_soproto != argp->proto));
694 if (nmp->nm_client != NULL && adjsock) {
695 int haslock = 0, error = 0;
697 if (nmp->nm_sotype == SOCK_STREAM) {
698 error = newnfs_sndlock(&nmp->nm_sockreq.nr_lock);
703 newnfs_disconnect(&nmp->nm_sockreq);
705 newnfs_sndunlock(&nmp->nm_sockreq.nr_lock);
706 nmp->nm_sotype = argp->sotype;
707 nmp->nm_soproto = argp->proto;
708 if (nmp->nm_sotype == SOCK_DGRAM)
709 while (newnfs_connect(nmp, &nmp->nm_sockreq,
711 printf("newnfs_args: retrying connect\n");
712 (void) nfs_catnap(PSOCK, 0, "nfscon");
716 nmp->nm_sotype = argp->sotype;
717 nmp->nm_soproto = argp->proto;
720 if (hostname != NULL) {
721 strlcpy(nmp->nm_hostname, hostname,
722 sizeof(nmp->nm_hostname));
723 p = strchr(nmp->nm_hostname, ':');
729 static const char *nfs_opts[] = { "from", "nfs_args",
730 "noac", "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
731 "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
732 "async", "noconn", "nolockd", "conn", "lockd", "intr", "rdirplus",
733 "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize",
734 "retrans", "actimeo", "acregmin", "acregmax", "acdirmin", "acdirmax",
735 "resvport", "readahead", "hostname", "timeo", "timeout", "addr", "fh",
736 "nfsv3", "sec", "principal", "nfsv4", "gssname", "allgssname", "dirpath",
737 "minorversion", "nametimeo", "negnametimeo", "nocto", "noncontigwr",
738 "pnfs", "wcommitsize", "oneopenown",
742 * Parse the "from" mountarg, passed by the generic mount(8) program
743 * or the mountroot code. This is used when rerooting into NFS.
745 * Note that the "hostname" is actually a "hostname:/share/path" string.
748 nfs_mount_parse_from(struct vfsoptlist *opts, char **hostnamep,
749 struct sockaddr_in **sinp, char *dirpath, size_t dirpathsize, int *dirlenp)
751 char *nam, *delimp, *hostp, *spec;
752 int error, have_bracket = 0, offset, rv, speclen;
753 struct sockaddr_in *sin;
756 error = vfs_getopt(opts, "from", (void **)&spec, &speclen);
759 nam = malloc(MNAMELEN + 1, M_TEMP, M_WAITOK);
762 * This part comes from sbin/mount_nfs/mount_nfs.c:getnfsargs().
764 if (*spec == '[' && (delimp = strchr(spec + 1, ']')) != NULL &&
765 *(delimp + 1) == ':') {
769 } else if ((delimp = strrchr(spec, ':')) != NULL) {
772 } else if ((delimp = strrchr(spec, '@')) != NULL) {
773 printf("%s: path@server syntax is deprecated, "
774 "use server:path\n", __func__);
777 printf("%s: no <host>:<dirpath> nfs-name\n", __func__);
784 * If there has been a trailing slash at mounttime it seems
785 * that some mountd implementations fail to remove the mount
786 * entries from their mountlist while unmounting.
788 for (speclen = strlen(spec);
789 speclen > 1 && spec[speclen - 1] == '/';
791 spec[speclen - 1] = '\0';
792 if (strlen(hostp) + strlen(spec) + 1 > MNAMELEN) {
793 printf("%s: %s:%s: name too long", __func__, hostp, spec);
797 /* Make both '@' and ':' notations equal */
798 if (*hostp != '\0') {
803 memmove(nam + offset, hostp, len);
805 nam[len + offset++] = ']';
806 nam[len + offset++] = ':';
807 memmove(nam + len + offset, spec, speclen);
808 nam[len + speclen + offset] = '\0';
815 sin = malloc(sizeof(*sin), M_SONAME, M_WAITOK);
816 rv = inet_pton(AF_INET, hostp, &sin->sin_addr);
818 printf("%s: cannot parse '%s', inet_pton() returned %d\n",
819 __func__, hostp, rv);
825 sin->sin_len = sizeof(*sin);
826 sin->sin_family = AF_INET;
828 * XXX: hardcoded port number.
830 sin->sin_port = htons(2049);
832 *hostnamep = strdup(nam, M_NEWNFSMNT);
834 strlcpy(dirpath, spec, dirpathsize);
835 *dirlenp = strlen(dirpath);
845 * It seems a bit dumb to copyinstr() the host and path here and then
846 * bcopy() them in mountnfs(), but I wanted to detect errors before
847 * doing the getsockaddr() call because getsockaddr() allocates an mbuf and
848 * an error after that means that I have to release the mbuf.
852 nfs_mount(struct mount *mp)
854 struct nfs_args args = {
855 .version = NFS_ARGSVERSION,
857 .addrlen = sizeof (struct sockaddr_in),
858 .sotype = SOCK_STREAM,
862 .flags = NFSMNT_RESVPORT,
865 .readdirsize = NFS_READDIRSIZE,
867 .retrans = NFS_RETRANS,
868 .readahead = NFS_DEFRAHEAD,
869 .wcommitsize = 0, /* was: NQ_DEFLEASE */
871 .acregmin = NFS_MINATTRTIMO,
872 .acregmax = NFS_MAXATTRTIMO,
873 .acdirmin = NFS_MINDIRATTRTIMO,
874 .acdirmax = NFS_MAXDIRATTRTIMO,
876 int error = 0, ret, len;
877 struct sockaddr *nam = NULL;
881 u_char nfh[NFSX_FHMAX], krbname[100], dirpath[100], srvkrbname[100];
882 char *cp, *opt, *name, *secname;
883 int nametimeo = NFS_DEFAULT_NAMETIMEO;
884 int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
886 int dirlen, has_nfs_args_opt, has_nfs_from_opt,
887 krbnamelen, srvkrbnamelen;
890 has_nfs_args_opt = 0;
891 has_nfs_from_opt = 0;
892 hst = malloc(MNAMELEN, M_TEMP, M_WAITOK);
893 if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
899 if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS &&
900 nfs_diskless_valid != 0) {
901 error = nfs_mountroot(mp);
908 * The old mount_nfs program passed the struct nfs_args
909 * from userspace to kernel. The new mount_nfs program
910 * passes string options via nmount() from userspace to kernel
911 * and we populate the struct nfs_args in the kernel.
913 if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
914 error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
919 if (args.version != NFS_ARGSVERSION) {
920 error = EPROGMISMATCH;
923 has_nfs_args_opt = 1;
926 /* Handle the new style options. */
927 if (vfs_getopt(mp->mnt_optnew, "noac", NULL, NULL) == 0) {
928 args.acdirmin = args.acdirmax =
929 args.acregmin = args.acregmax = 0;
930 args.flags |= NFSMNT_ACDIRMIN | NFSMNT_ACDIRMAX |
931 NFSMNT_ACREGMIN | NFSMNT_ACREGMAX;
933 if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
934 args.flags |= NFSMNT_NOCONN;
935 if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
936 args.flags &= ~NFSMNT_NOCONN;
937 if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
938 args.flags |= NFSMNT_NOLOCKD;
939 if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
940 args.flags &= ~NFSMNT_NOLOCKD;
941 if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
942 args.flags |= NFSMNT_INT;
943 if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
944 args.flags |= NFSMNT_RDIRPLUS;
945 if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
946 args.flags |= NFSMNT_RESVPORT;
947 if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
948 args.flags &= ~NFSMNT_RESVPORT;
949 if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
950 args.flags |= NFSMNT_SOFT;
951 if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
952 args.flags &= ~NFSMNT_SOFT;
953 if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
954 args.sotype = SOCK_DGRAM;
955 if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
956 args.sotype = SOCK_DGRAM;
957 if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
958 args.sotype = SOCK_STREAM;
959 if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
960 args.flags |= NFSMNT_NFSV3;
961 if (vfs_getopt(mp->mnt_optnew, "nfsv4", NULL, NULL) == 0) {
962 args.flags |= NFSMNT_NFSV4;
963 args.sotype = SOCK_STREAM;
965 if (vfs_getopt(mp->mnt_optnew, "allgssname", NULL, NULL) == 0)
966 args.flags |= NFSMNT_ALLGSSNAME;
967 if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0)
968 args.flags |= NFSMNT_NOCTO;
969 if (vfs_getopt(mp->mnt_optnew, "noncontigwr", NULL, NULL) == 0)
970 args.flags |= NFSMNT_NONCONTIGWR;
971 if (vfs_getopt(mp->mnt_optnew, "pnfs", NULL, NULL) == 0)
972 args.flags |= NFSMNT_PNFS;
973 if (vfs_getopt(mp->mnt_optnew, "oneopenown", NULL, NULL) == 0)
974 args.flags |= NFSMNT_ONEOPENOWN;
975 if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
977 vfs_mount_error(mp, "illegal readdirsize");
981 ret = sscanf(opt, "%d", &args.readdirsize);
982 if (ret != 1 || args.readdirsize <= 0) {
983 vfs_mount_error(mp, "illegal readdirsize: %s",
988 args.flags |= NFSMNT_READDIRSIZE;
990 if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
992 vfs_mount_error(mp, "illegal readahead");
996 ret = sscanf(opt, "%d", &args.readahead);
997 if (ret != 1 || args.readahead <= 0) {
998 vfs_mount_error(mp, "illegal readahead: %s",
1003 args.flags |= NFSMNT_READAHEAD;
1005 if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
1007 vfs_mount_error(mp, "illegal wsize");
1011 ret = sscanf(opt, "%d", &args.wsize);
1012 if (ret != 1 || args.wsize <= 0) {
1013 vfs_mount_error(mp, "illegal wsize: %s",
1018 args.flags |= NFSMNT_WSIZE;
1020 if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
1022 vfs_mount_error(mp, "illegal rsize");
1026 ret = sscanf(opt, "%d", &args.rsize);
1027 if (ret != 1 || args.rsize <= 0) {
1028 vfs_mount_error(mp, "illegal wsize: %s",
1033 args.flags |= NFSMNT_RSIZE;
1035 if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
1037 vfs_mount_error(mp, "illegal retrans");
1041 ret = sscanf(opt, "%d", &args.retrans);
1042 if (ret != 1 || args.retrans <= 0) {
1043 vfs_mount_error(mp, "illegal retrans: %s",
1048 args.flags |= NFSMNT_RETRANS;
1050 if (vfs_getopt(mp->mnt_optnew, "actimeo", (void **)&opt, NULL) == 0) {
1051 ret = sscanf(opt, "%d", &args.acregmin);
1052 if (ret != 1 || args.acregmin < 0) {
1053 vfs_mount_error(mp, "illegal actimeo: %s",
1058 args.acdirmin = args.acdirmax = args.acregmax = args.acregmin;
1059 args.flags |= NFSMNT_ACDIRMIN | NFSMNT_ACDIRMAX |
1060 NFSMNT_ACREGMIN | NFSMNT_ACREGMAX;
1062 if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
1063 ret = sscanf(opt, "%d", &args.acregmin);
1064 if (ret != 1 || args.acregmin < 0) {
1065 vfs_mount_error(mp, "illegal acregmin: %s",
1070 args.flags |= NFSMNT_ACREGMIN;
1072 if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
1073 ret = sscanf(opt, "%d", &args.acregmax);
1074 if (ret != 1 || args.acregmax < 0) {
1075 vfs_mount_error(mp, "illegal acregmax: %s",
1080 args.flags |= NFSMNT_ACREGMAX;
1082 if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
1083 ret = sscanf(opt, "%d", &args.acdirmin);
1084 if (ret != 1 || args.acdirmin < 0) {
1085 vfs_mount_error(mp, "illegal acdirmin: %s",
1090 args.flags |= NFSMNT_ACDIRMIN;
1092 if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
1093 ret = sscanf(opt, "%d", &args.acdirmax);
1094 if (ret != 1 || args.acdirmax < 0) {
1095 vfs_mount_error(mp, "illegal acdirmax: %s",
1100 args.flags |= NFSMNT_ACDIRMAX;
1102 if (vfs_getopt(mp->mnt_optnew, "wcommitsize", (void **)&opt, NULL) == 0) {
1103 ret = sscanf(opt, "%d", &args.wcommitsize);
1104 if (ret != 1 || args.wcommitsize < 0) {
1105 vfs_mount_error(mp, "illegal wcommitsize: %s", opt);
1109 args.flags |= NFSMNT_WCOMMITSIZE;
1111 if (vfs_getopt(mp->mnt_optnew, "timeo", (void **)&opt, NULL) == 0) {
1112 ret = sscanf(opt, "%d", &args.timeo);
1113 if (ret != 1 || args.timeo <= 0) {
1114 vfs_mount_error(mp, "illegal timeo: %s",
1119 args.flags |= NFSMNT_TIMEO;
1121 if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
1122 ret = sscanf(opt, "%d", &args.timeo);
1123 if (ret != 1 || args.timeo <= 0) {
1124 vfs_mount_error(mp, "illegal timeout: %s",
1129 args.flags |= NFSMNT_TIMEO;
1131 if (vfs_getopt(mp->mnt_optnew, "nametimeo", (void **)&opt, NULL) == 0) {
1132 ret = sscanf(opt, "%d", &nametimeo);
1133 if (ret != 1 || nametimeo < 0) {
1134 vfs_mount_error(mp, "illegal nametimeo: %s", opt);
1139 if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
1141 ret = sscanf(opt, "%d", &negnametimeo);
1142 if (ret != 1 || negnametimeo < 0) {
1143 vfs_mount_error(mp, "illegal negnametimeo: %s",
1149 if (vfs_getopt(mp->mnt_optnew, "minorversion", (void **)&opt, NULL) ==
1151 ret = sscanf(opt, "%d", &minvers);
1152 if (ret != 1 || minvers < 0 || minvers > 1 ||
1153 (args.flags & NFSMNT_NFSV4) == 0) {
1154 vfs_mount_error(mp, "illegal minorversion: %s", opt);
1159 if (vfs_getopt(mp->mnt_optnew, "sec",
1160 (void **) &secname, NULL) == 0)
1161 nfs_sec_name(secname, &args.flags);
1163 if (mp->mnt_flag & MNT_UPDATE) {
1164 struct nfsmount *nmp = VFSTONFS(mp);
1172 * If a change from TCP->UDP is done and there are thread(s)
1173 * that have I/O RPC(s) in progress with a transfer size
1174 * greater than NFS_MAXDGRAMDATA, those thread(s) will be
1175 * hung, retrying the RPC(s) forever. Usually these threads
1176 * will be seen doing an uninterruptible sleep on wait channel
1179 if (args.sotype == SOCK_DGRAM && nmp->nm_sotype == SOCK_STREAM)
1180 tprintf(td->td_proc, LOG_WARNING,
1181 "Warning: mount -u that changes TCP->UDP can result in hung threads\n");
1184 * When doing an update, we can't change version,
1185 * security, switch lockd strategies, change cookie
1186 * translation or switch oneopenown.
1188 args.flags = (args.flags &
1195 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
1203 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
1204 nfs_decode_args(mp, nmp, &args, NULL, td->td_ucred, td);
1209 * Make the nfs_ip_paranoia sysctl serve as the default connection
1210 * or no-connection mode for those protocols that support
1211 * no-connection mode (the flag will be cleared later for protocols
1212 * that do not support no-connection mode). This will allow a client
1213 * to receive replies from a different IP then the request was
1214 * sent to. Note: default value for nfs_ip_paranoia is 1 (paranoid),
1217 if (nfs_ip_paranoia == 0)
1218 args.flags |= NFSMNT_NOCONN;
1220 if (has_nfs_args_opt != 0) {
1222 * In the 'nfs_args' case, the pointers in the args
1223 * structure are in userland - we copy them in here.
1225 if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
1226 vfs_mount_error(mp, "Bad file handle");
1230 error = copyin((caddr_t)args.fh, (caddr_t)nfh,
1234 error = copyinstr(args.hostname, hst, MNAMELEN - 1, &hstlen);
1237 bzero(&hst[hstlen], MNAMELEN - hstlen);
1238 args.hostname = hst;
1239 /* getsockaddr() call must be after above copyin() calls */
1240 error = getsockaddr(&nam, (caddr_t)args.addr,
1244 } else if (nfs_mount_parse_from(mp->mnt_optnew,
1245 &args.hostname, (struct sockaddr_in **)&nam, dirpath,
1246 sizeof(dirpath), &dirlen) == 0) {
1247 has_nfs_from_opt = 1;
1248 bcopy(args.hostname, hst, MNAMELEN);
1249 hst[MNAMELEN - 1] = '\0';
1252 * This only works with NFSv4 for now.
1255 args.flags |= NFSMNT_NFSV4;
1256 args.sotype = SOCK_STREAM;
1258 if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
1259 &args.fhsize) == 0) {
1260 if (args.fhsize < 0 || args.fhsize > NFSX_FHMAX) {
1261 vfs_mount_error(mp, "Bad file handle");
1265 bcopy(args.fh, nfh, args.fhsize);
1269 (void) vfs_getopt(mp->mnt_optnew, "hostname",
1270 (void **)&args.hostname, &len);
1271 if (args.hostname == NULL) {
1272 vfs_mount_error(mp, "Invalid hostname");
1276 if (len >= MNAMELEN) {
1277 vfs_mount_error(mp, "Hostname too long");
1281 bcopy(args.hostname, hst, len);
1285 if (vfs_getopt(mp->mnt_optnew, "principal", (void **)&name, NULL) == 0)
1286 strlcpy(srvkrbname, name, sizeof (srvkrbname));
1288 snprintf(srvkrbname, sizeof (srvkrbname), "nfs@%s", hst);
1289 cp = strchr(srvkrbname, ':');
1293 srvkrbnamelen = strlen(srvkrbname);
1295 if (vfs_getopt(mp->mnt_optnew, "gssname", (void **)&name, NULL) == 0)
1296 strlcpy(krbname, name, sizeof (krbname));
1299 krbnamelen = strlen(krbname);
1301 if (has_nfs_from_opt == 0) {
1302 if (vfs_getopt(mp->mnt_optnew,
1303 "dirpath", (void **)&name, NULL) == 0)
1304 strlcpy(dirpath, name, sizeof (dirpath));
1307 dirlen = strlen(dirpath);
1310 if (has_nfs_args_opt == 0 && has_nfs_from_opt == 0) {
1311 if (vfs_getopt(mp->mnt_optnew, "addr",
1312 (void **)&args.addr, &args.addrlen) == 0) {
1313 if (args.addrlen > SOCK_MAXADDRLEN) {
1314 error = ENAMETOOLONG;
1317 nam = malloc(args.addrlen, M_SONAME, M_WAITOK);
1318 bcopy(args.addr, nam, args.addrlen);
1319 nam->sa_len = args.addrlen;
1321 vfs_mount_error(mp, "No server address");
1328 error = mountnfs(&args, mp, nam, hst, krbname, krbnamelen, dirpath,
1329 dirlen, srvkrbname, srvkrbnamelen, &vp, td->td_ucred, td,
1330 nametimeo, negnametimeo, minvers);
1334 mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED | MNTK_NO_IOPF |
1336 if ((VFSTONFS(mp)->nm_flag & NFSMNT_NFSV4) != 0)
1337 mp->mnt_kern_flag |= MNTK_NULL_NOCACHE;
1349 * It seems a bit dumb to copyinstr() the host and path here and then
1350 * bcopy() them in mountnfs(), but I wanted to detect errors before
1351 * doing the getsockaddr() call because getsockaddr() allocates an mbuf and
1352 * an error after that means that I have to release the mbuf.
1356 nfs_cmount(struct mntarg *ma, void *data, uint64_t flags)
1359 struct nfs_args args;
1361 error = copyin(data, &args, sizeof (struct nfs_args));
1365 ma = mount_arg(ma, "nfs_args", &args, sizeof args);
1367 error = kernel_mount(ma, flags);
1372 * Common code for mount and mountroot
1375 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
1376 char *hst, u_char *krbname, int krbnamelen, u_char *dirpath, int dirlen,
1377 u_char *srvkrbname, int srvkrbnamelen, struct vnode **vpp,
1378 struct ucred *cred, struct thread *td, int nametimeo, int negnametimeo,
1381 struct nfsmount *nmp;
1383 int error, trycnt, ret;
1384 struct nfsvattr nfsva;
1385 struct nfsclclient *clp;
1386 struct nfsclds *dsp, *tdsp;
1388 static u_int64_t clval = 0;
1390 NFSCL_DEBUG(3, "in mnt\n");
1392 if (mp->mnt_flag & MNT_UPDATE) {
1394 printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
1395 free(nam, M_SONAME);
1398 nmp = malloc(sizeof (struct nfsmount) +
1399 krbnamelen + dirlen + srvkrbnamelen + 2,
1400 M_NEWNFSMNT, M_WAITOK | M_ZERO);
1401 TAILQ_INIT(&nmp->nm_bufq);
1402 TAILQ_INIT(&nmp->nm_sess);
1404 clval = (u_int64_t)nfsboottime.tv_sec;
1405 nmp->nm_clval = clval++;
1406 nmp->nm_krbnamelen = krbnamelen;
1407 nmp->nm_dirpathlen = dirlen;
1408 nmp->nm_srvkrbnamelen = srvkrbnamelen;
1409 if (td->td_ucred->cr_uid != (uid_t)0) {
1411 * nm_uid is used to get KerberosV credentials for
1412 * the nfsv4 state handling operations if there is
1413 * no host based principal set. Use the uid of
1414 * this user if not root, since they are doing the
1415 * mount. I don't think setting this for root will
1416 * work, since root normally does not have user
1417 * credentials in a credentials cache.
1419 nmp->nm_uid = td->td_ucred->cr_uid;
1422 * Just set to -1, so it won't be used.
1424 nmp->nm_uid = (uid_t)-1;
1427 /* Copy and null terminate all the names */
1428 if (nmp->nm_krbnamelen > 0) {
1429 bcopy(krbname, nmp->nm_krbname, nmp->nm_krbnamelen);
1430 nmp->nm_name[nmp->nm_krbnamelen] = '\0';
1432 if (nmp->nm_dirpathlen > 0) {
1433 bcopy(dirpath, NFSMNT_DIRPATH(nmp),
1434 nmp->nm_dirpathlen);
1435 nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1438 if (nmp->nm_srvkrbnamelen > 0) {
1439 bcopy(srvkrbname, NFSMNT_SRVKRBNAME(nmp),
1440 nmp->nm_srvkrbnamelen);
1441 nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1442 + nmp->nm_srvkrbnamelen + 2] = '\0';
1444 nmp->nm_sockreq.nr_cred = crhold(cred);
1445 mtx_init(&nmp->nm_sockreq.nr_mtx, "nfssock", NULL, MTX_DEF);
1447 nmp->nm_getinfo = nfs_getnlminfo;
1448 nmp->nm_vinvalbuf = ncl_vinvalbuf;
1451 nmp->nm_mountp = mp;
1452 mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF | MTX_DUPOK);
1455 * Since nfs_decode_args() might optionally set them, these
1456 * need to be set to defaults before the call, so that the
1457 * optional settings aren't overwritten.
1459 nmp->nm_nametimeo = nametimeo;
1460 nmp->nm_negnametimeo = negnametimeo;
1461 nmp->nm_timeo = NFS_TIMEO;
1462 nmp->nm_retry = NFS_RETRANS;
1463 nmp->nm_readahead = NFS_DEFRAHEAD;
1465 /* This is empirical approximation of sqrt(hibufspace) * 256. */
1466 nmp->nm_wcommitsize = NFS_MAXBSIZE / 256;
1467 while ((long)nmp->nm_wcommitsize * nmp->nm_wcommitsize < hibufspace)
1468 nmp->nm_wcommitsize *= 2;
1469 nmp->nm_wcommitsize *= 256;
1471 if ((argp->flags & NFSMNT_NFSV4) != 0)
1472 nmp->nm_minorvers = minvers;
1474 nmp->nm_minorvers = 0;
1476 nfs_decode_args(mp, nmp, argp, hst, cred, td);
1479 * V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too
1480 * high, depending on whether we end up with negative offsets in
1481 * the client or server somewhere. 2GB-1 may be safer.
1483 * For V3, ncl_fsinfo will adjust this as necessary. Assume maximum
1484 * that we can handle until we find out otherwise.
1486 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0)
1487 nmp->nm_maxfilesize = 0xffffffffLL;
1489 nmp->nm_maxfilesize = OFF_MAX;
1491 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
1492 nmp->nm_wsize = NFS_WSIZE;
1493 nmp->nm_rsize = NFS_RSIZE;
1494 nmp->nm_readdirsize = NFS_READDIRSIZE;
1496 nmp->nm_numgrps = NFS_MAXGRPS;
1497 nmp->nm_tprintf_delay = nfs_tprintf_delay;
1498 if (nmp->nm_tprintf_delay < 0)
1499 nmp->nm_tprintf_delay = 0;
1500 nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
1501 if (nmp->nm_tprintf_initial_delay < 0)
1502 nmp->nm_tprintf_initial_delay = 0;
1503 nmp->nm_fhsize = argp->fhsize;
1504 if (nmp->nm_fhsize > 0)
1505 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
1506 bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
1508 /* Set up the sockets and per-host congestion */
1509 nmp->nm_sotype = argp->sotype;
1510 nmp->nm_soproto = argp->proto;
1511 nmp->nm_sockreq.nr_prog = NFS_PROG;
1512 if ((argp->flags & NFSMNT_NFSV4))
1513 nmp->nm_sockreq.nr_vers = NFS_VER4;
1514 else if ((argp->flags & NFSMNT_NFSV3))
1515 nmp->nm_sockreq.nr_vers = NFS_VER3;
1517 nmp->nm_sockreq.nr_vers = NFS_VER2;
1520 if ((error = newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0)))
1522 /* For NFSv4.1, get the clientid now. */
1523 if (nmp->nm_minorvers > 0) {
1524 NFSCL_DEBUG(3, "at getcl\n");
1525 error = nfscl_getcl(mp, cred, td, 0, &clp);
1526 NFSCL_DEBUG(3, "aft getcl=%d\n", error);
1531 if (nmp->nm_fhsize == 0 && (nmp->nm_flag & NFSMNT_NFSV4) &&
1532 nmp->nm_dirpathlen > 0) {
1533 NFSCL_DEBUG(3, "in dirp\n");
1535 * If the fhsize on the mount point == 0 for V4, the mount
1536 * path needs to be looked up.
1540 error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp),
1542 NFSCL_DEBUG(3, "aft dirp=%d\n", error);
1544 (void) nfs_catnap(PZERO, error, "nfsgetdirp");
1545 } while (error && --trycnt > 0);
1547 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
1553 * A reference count is needed on the nfsnode representing the
1554 * remote root. If this object is not persistent, then backward
1555 * traversals of the mount point (i.e. "..") will not work if
1556 * the nfsnode gets flushed out of the cache. Ufs does not have
1557 * this problem, because one can identify root inodes by their
1558 * number == UFS_ROOTINO (2).
1560 if (nmp->nm_fhsize > 0) {
1562 * Set f_iosize to NFS_DIRBLKSIZ so that bo_bsize gets set
1563 * non-zero for the root vnode. f_iosize will be set correctly
1564 * by nfs_statfs() before any I/O occurs.
1566 mp->mnt_stat.f_iosize = NFS_DIRBLKSIZ;
1567 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np,
1574 * Get file attributes and transfer parameters for the
1575 * mountpoint. This has the side effect of filling in
1576 * (*vpp)->v_type with the correct value.
1578 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
1579 cred, td, &nfsva, NULL, &lease);
1582 * Just set default values to get things going.
1584 NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
1585 nfsva.na_vattr.va_type = VDIR;
1586 nfsva.na_vattr.va_mode = 0777;
1587 nfsva.na_vattr.va_nlink = 100;
1588 nfsva.na_vattr.va_uid = (uid_t)0;
1589 nfsva.na_vattr.va_gid = (gid_t)0;
1590 nfsva.na_vattr.va_fileid = 2;
1591 nfsva.na_vattr.va_gen = 1;
1592 nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
1593 nfsva.na_vattr.va_size = 512 * 1024;
1596 (void) nfscl_loadattrcache(vpp, &nfsva, NULL, NULL, 0, 1);
1597 if (nmp->nm_minorvers > 0) {
1598 NFSCL_DEBUG(3, "lease=%d\n", (int)lease);
1600 clp->nfsc_renew = NFSCL_RENEW(lease);
1601 clp->nfsc_expire = NFSD_MONOSEC + clp->nfsc_renew;
1602 clp->nfsc_clientidrev++;
1603 if (clp->nfsc_clientidrev == 0)
1604 clp->nfsc_clientidrev++;
1607 * Mount will succeed, so the renew thread can be
1610 nfscl_start_renewthread(clp);
1611 nfscl_clientrelease(clp);
1613 if (argp->flags & NFSMNT_NFSV3)
1614 ncl_fsinfo(nmp, *vpp, cred, td);
1616 /* Mark if the mount point supports NFSv4 ACLs. */
1617 if ((argp->flags & NFSMNT_NFSV4) != 0 && nfsrv_useacl != 0 &&
1619 NFSISSET_ATTRBIT(&nfsva.na_suppattr, NFSATTRBIT_ACL)) {
1621 mp->mnt_flag |= MNT_NFS4ACLS;
1626 * Lose the lock but keep the ref.
1628 NFSVOPUNLOCK(*vpp, 0);
1635 nfscl_clientrelease(clp);
1636 newnfs_disconnect(&nmp->nm_sockreq);
1637 crfree(nmp->nm_sockreq.nr_cred);
1638 if (nmp->nm_sockreq.nr_auth != NULL)
1639 AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
1640 mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1641 mtx_destroy(&nmp->nm_mtx);
1642 if (nmp->nm_clp != NULL) {
1644 LIST_REMOVE(nmp->nm_clp, nfsc_list);
1646 free(nmp->nm_clp, M_NFSCLCLIENT);
1648 TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp) {
1649 if (dsp != TAILQ_FIRST(&nmp->nm_sess) &&
1650 dsp->nfsclds_sockp != NULL)
1651 newnfs_disconnect(dsp->nfsclds_sockp);
1652 nfscl_freenfsclds(dsp);
1654 free(nmp, M_NEWNFSMNT);
1655 free(nam, M_SONAME);
1660 * unmount system call
1663 nfs_unmount(struct mount *mp, int mntflags)
1666 struct nfsmount *nmp;
1667 int error, flags = 0, i, trycnt = 0;
1668 struct nfsclds *dsp, *tdsp;
1672 if (mntflags & MNT_FORCE)
1673 flags |= FORCECLOSE;
1676 * Goes something like this..
1677 * - Call vflush() to clear out vnodes for this filesystem
1678 * - Close the socket
1679 * - Free up the data structures
1681 /* In the forced case, cancel any outstanding requests. */
1682 if (mntflags & MNT_FORCE) {
1683 error = newnfs_nmcancelreqs(nmp);
1686 /* For a forced close, get rid of the renew thread now */
1687 nfscl_umount(nmp, td);
1689 /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
1691 error = vflush(mp, 1, flags, td);
1692 if ((mntflags & MNT_FORCE) && error != 0 && ++trycnt < 30)
1693 (void) nfs_catnap(PSOCK, error, "newndm");
1694 } while ((mntflags & MNT_FORCE) && error != 0 && trycnt < 30);
1699 * We are now committed to the unmount.
1701 if ((mntflags & MNT_FORCE) == 0)
1702 nfscl_umount(nmp, td);
1704 mtx_lock(&nmp->nm_mtx);
1705 nmp->nm_privflag |= NFSMNTP_FORCEDISM;
1706 mtx_unlock(&nmp->nm_mtx);
1708 /* Make sure no nfsiods are assigned to this mount. */
1709 mtx_lock(&ncl_iod_mutex);
1710 for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
1711 if (ncl_iodmount[i] == nmp) {
1712 ncl_iodwant[i] = NFSIOD_AVAILABLE;
1713 ncl_iodmount[i] = NULL;
1715 mtx_unlock(&ncl_iod_mutex);
1718 * We can now set mnt_data to NULL and wait for
1719 * nfssvc(NFSSVC_FORCEDISM) to complete.
1721 mtx_lock(&mountlist_mtx);
1722 mtx_lock(&nmp->nm_mtx);
1723 mp->mnt_data = NULL;
1724 mtx_unlock(&mountlist_mtx);
1725 while ((nmp->nm_privflag & NFSMNTP_CANCELRPCS) != 0)
1726 msleep(nmp, &nmp->nm_mtx, PVFS, "nfsfdism", 0);
1727 mtx_unlock(&nmp->nm_mtx);
1729 newnfs_disconnect(&nmp->nm_sockreq);
1730 crfree(nmp->nm_sockreq.nr_cred);
1731 free(nmp->nm_nam, M_SONAME);
1732 if (nmp->nm_sockreq.nr_auth != NULL)
1733 AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
1734 mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1735 mtx_destroy(&nmp->nm_mtx);
1736 TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp) {
1737 if (dsp != TAILQ_FIRST(&nmp->nm_sess) &&
1738 dsp->nfsclds_sockp != NULL)
1739 newnfs_disconnect(dsp->nfsclds_sockp);
1740 nfscl_freenfsclds(dsp);
1742 free(nmp, M_NEWNFSMNT);
1748 * Return root of a filesystem
1751 nfs_root(struct mount *mp, int flags, struct vnode **vpp)
1754 struct nfsmount *nmp;
1759 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, flags);
1764 * Get transfer parameters and attributes for root vnode once.
1766 mtx_lock(&nmp->nm_mtx);
1767 if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
1768 mtx_unlock(&nmp->nm_mtx);
1769 ncl_fsinfo(nmp, vp, curthread->td_ucred, curthread);
1771 mtx_unlock(&nmp->nm_mtx);
1772 if (vp->v_type == VNON)
1774 vp->v_vflag |= VV_ROOT;
1780 * Flush out the buffer cache
1784 nfs_sync(struct mount *mp, int waitfor)
1786 struct vnode *vp, *mvp;
1788 int error, allerror = 0;
1794 * If a forced dismount is in progress, return from here so that
1795 * the umount(2) syscall doesn't get stuck in VFS_SYNC() before
1796 * calling VFS_UNMOUNT().
1798 if (NFSCL_FORCEDISM(mp)) {
1805 * Force stale buffer cache information to be flushed.
1808 MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
1809 /* XXX Racy bv_cnt check. */
1810 if (NFSVOPISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
1811 waitfor == MNT_LAZY) {
1815 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
1816 MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
1819 error = VOP_FSYNC(vp, waitfor, td);
1822 NFSVOPUNLOCK(vp, 0);
1829 nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
1831 struct nfsmount *nmp = VFSTONFS(mp);
1835 bzero(&vq, sizeof(vq));
1838 case VFS_CTL_NOLOCKS:
1839 val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
1840 if (req->oldptr != NULL) {
1841 error = SYSCTL_OUT(req, &val, sizeof(val));
1845 if (req->newptr != NULL) {
1846 error = SYSCTL_IN(req, &val, sizeof(val));
1850 nmp->nm_flag |= NFSMNT_NOLOCKS;
1852 nmp->nm_flag &= ~NFSMNT_NOLOCKS;
1857 mtx_lock(&nmp->nm_mtx);
1858 if (nmp->nm_state & NFSSTA_TIMEO)
1859 vq.vq_flags |= VQ_NOTRESP;
1860 mtx_unlock(&nmp->nm_mtx);
1862 if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
1863 (nmp->nm_state & NFSSTA_LOCKTIMEO))
1864 vq.vq_flags |= VQ_NOTRESPLOCK;
1866 error = SYSCTL_OUT(req, &vq, sizeof(vq));
1869 if (req->oldptr != NULL) {
1870 error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
1871 sizeof(nmp->nm_tprintf_initial_delay));
1875 if (req->newptr != NULL) {
1876 error = vfs_suser(mp, req->td);
1879 error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
1880 sizeof(nmp->nm_tprintf_initial_delay));
1883 if (nmp->nm_tprintf_initial_delay < 0)
1884 nmp->nm_tprintf_initial_delay = 0;
1894 * Purge any RPCs in progress, so that they will all return errors.
1895 * This allows dounmount() to continue as far as VFS_UNMOUNT() for a
1899 nfs_purge(struct mount *mp)
1901 struct nfsmount *nmp = VFSTONFS(mp);
1903 newnfs_nmcancelreqs(nmp);
1907 * Extract the information needed by the nlm from the nfs vnode.
1910 nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp,
1911 struct sockaddr_storage *sp, int *is_v3p, off_t *sizep,
1912 struct timeval *timeop)
1914 struct nfsmount *nmp;
1915 struct nfsnode *np = VTONFS(vp);
1917 nmp = VFSTONFS(vp->v_mount);
1919 *fhlenp = (size_t)np->n_fhp->nfh_len;
1921 bcopy(np->n_fhp->nfh_fh, fhp, np->n_fhp->nfh_len);
1923 bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp)));
1925 *is_v3p = NFS_ISV3(vp);
1927 *sizep = np->n_size;
1928 if (timeop != NULL) {
1929 timeop->tv_sec = nmp->nm_timeo / NFS_HZ;
1930 timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ);
1935 * This function prints out an option name, based on the conditional
1938 static __inline void nfscl_printopt(struct nfsmount *nmp, int testval,
1939 char *opt, char **buf, size_t *blen)
1943 if (testval != 0 && *blen > strlen(opt)) {
1944 len = snprintf(*buf, *blen, "%s", opt);
1945 if (len != strlen(opt))
1953 * This function printf out an options integer value.
1955 static __inline void nfscl_printoptval(struct nfsmount *nmp, int optval,
1956 char *opt, char **buf, size_t *blen)
1960 if (*blen > strlen(opt) + 1) {
1961 /* Could result in truncated output string. */
1962 len = snprintf(*buf, *blen, "%s=%d", opt, optval);
1971 * Load the option flags and values into the buffer.
1973 void nfscl_retopts(struct nfsmount *nmp, char *buffer, size_t buflen)
1980 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV4) != 0, "nfsv4", &buf,
1982 if ((nmp->nm_flag & NFSMNT_NFSV4) != 0) {
1983 nfscl_printoptval(nmp, nmp->nm_minorvers, ",minorversion", &buf,
1985 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_PNFS) != 0, ",pnfs",
1987 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_ONEOPENOWN) != 0 &&
1988 nmp->nm_minorvers > 0, ",oneopenown", &buf, &blen);
1990 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV3) != 0, "nfsv3", &buf,
1992 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0,
1993 "nfsv2", &buf, &blen);
1994 nfscl_printopt(nmp, nmp->nm_sotype == SOCK_STREAM, ",tcp", &buf, &blen);
1995 nfscl_printopt(nmp, nmp->nm_sotype != SOCK_STREAM, ",udp", &buf, &blen);
1996 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RESVPORT) != 0, ",resvport",
1998 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCONN) != 0, ",noconn",
2000 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) == 0, ",hard", &buf,
2002 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) != 0, ",soft", &buf,
2004 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_INT) != 0, ",intr", &buf,
2006 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) == 0, ",cto", &buf,
2008 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) != 0, ",nocto", &buf,
2010 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NONCONTIGWR) != 0,
2011 ",noncontigwr", &buf, &blen);
2012 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
2013 0, ",lockd", &buf, &blen);
2014 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
2015 NFSMNT_NOLOCKD, ",nolockd", &buf, &blen);
2016 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RDIRPLUS) != 0, ",rdirplus",
2018 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_KERB) == 0, ",sec=sys",
2020 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
2021 NFSMNT_PRIVACY)) == NFSMNT_KERB, ",sec=krb5", &buf, &blen);
2022 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
2023 NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_INTEGRITY), ",sec=krb5i",
2025 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
2026 NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_PRIVACY), ",sec=krb5p",
2028 nfscl_printoptval(nmp, nmp->nm_acdirmin, ",acdirmin", &buf, &blen);
2029 nfscl_printoptval(nmp, nmp->nm_acdirmax, ",acdirmax", &buf, &blen);
2030 nfscl_printoptval(nmp, nmp->nm_acregmin, ",acregmin", &buf, &blen);
2031 nfscl_printoptval(nmp, nmp->nm_acregmax, ",acregmax", &buf, &blen);
2032 nfscl_printoptval(nmp, nmp->nm_nametimeo, ",nametimeo", &buf, &blen);
2033 nfscl_printoptval(nmp, nmp->nm_negnametimeo, ",negnametimeo", &buf,
2035 nfscl_printoptval(nmp, nmp->nm_rsize, ",rsize", &buf, &blen);
2036 nfscl_printoptval(nmp, nmp->nm_wsize, ",wsize", &buf, &blen);
2037 nfscl_printoptval(nmp, nmp->nm_readdirsize, ",readdirsize", &buf,
2039 nfscl_printoptval(nmp, nmp->nm_readahead, ",readahead", &buf, &blen);
2040 nfscl_printoptval(nmp, nmp->nm_wcommitsize, ",wcommitsize", &buf,
2042 nfscl_printoptval(nmp, nmp->nm_timeo, ",timeout", &buf, &blen);
2043 nfscl_printoptval(nmp, nmp->nm_retry, ",retrans", &buf, &blen);