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$");
40 #include "opt_bootp.h"
41 #include "opt_nfsroot.h"
42 #include "opt_kern_tls.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 #include <rpc/rpcsec_tls.h>
82 FEATURE(nfscl, "NFSv4 client");
84 extern int nfscl_ticks;
85 extern struct timeval nfsboottime;
86 extern int nfsrv_useacl;
87 extern int nfscl_debuglevel;
88 extern enum nfsiod_state ncl_iodwant[NFS_MAXASYNCDAEMON];
89 extern struct nfsmount *ncl_iodmount[NFS_MAXASYNCDAEMON];
90 extern struct mtx ncl_iod_mutex;
92 extern struct mtx nfsrv_dslock_mtx;
94 MALLOC_DEFINE(M_NEWNFSREQ, "newnfsclient_req", "NFS request header");
95 MALLOC_DEFINE(M_NEWNFSMNT, "newnfsmnt", "NFS mount struct");
97 SYSCTL_DECL(_vfs_nfs);
98 static int nfs_ip_paranoia = 1;
99 SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW,
100 &nfs_ip_paranoia, 0, "");
101 static int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
102 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_INITIAL_DELAY,
103 downdelayinitial, CTLFLAG_RW, &nfs_tprintf_initial_delay, 0, "");
104 /* how long between console messages "nfs server foo not responding" */
105 static int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
106 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_DELAY,
107 downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0, "");
110 SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0,
111 "Toggle debug flag");
114 static int nfs_mountroot(struct mount *);
115 static void nfs_sec_name(char *, int *);
116 static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp,
117 struct nfs_args *argp, const char *, struct ucred *,
119 static int mountnfs(struct nfs_args *, struct mount *,
120 struct sockaddr *, char *, u_char *, int, u_char *, int,
121 u_char *, int, struct vnode **, struct ucred *,
122 struct thread *, int, int, int, uint32_t);
123 static void nfs_getnlminfo(struct vnode *, uint8_t *, size_t *,
124 struct sockaddr_storage *, int *, off_t *,
126 static vfs_mount_t nfs_mount;
127 static vfs_cmount_t nfs_cmount;
128 static vfs_unmount_t nfs_unmount;
129 static vfs_root_t nfs_root;
130 static vfs_statfs_t nfs_statfs;
131 static vfs_sync_t nfs_sync;
132 static vfs_sysctl_t nfs_sysctl;
133 static vfs_purge_t nfs_purge;
136 * nfs vfs operations.
138 static struct vfsops nfs_vfsops = {
139 .vfs_init = ncl_init,
140 .vfs_mount = nfs_mount,
141 .vfs_cmount = nfs_cmount,
142 .vfs_root = vfs_cache_root,
143 .vfs_cachedroot = nfs_root,
144 .vfs_statfs = nfs_statfs,
145 .vfs_sync = nfs_sync,
146 .vfs_uninit = ncl_uninit,
147 .vfs_unmount = nfs_unmount,
148 .vfs_sysctl = nfs_sysctl,
149 .vfs_purge = nfs_purge,
151 VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK | VFCF_SBDRY);
153 /* So that loader and kldload(2) can find us, wherever we are.. */
154 MODULE_VERSION(nfs, 1);
155 MODULE_DEPEND(nfs, nfscommon, 1, 1, 1);
156 MODULE_DEPEND(nfs, krpc, 1, 1, 1);
157 MODULE_DEPEND(nfs, nfssvc, 1, 1, 1);
160 * This structure is now defined in sys/nfs/nfs_diskless.c so that it
161 * can be shared by both NFS clients. It is declared here so that it
162 * will be defined for kernels built without NFS_ROOT, although it
163 * isn't used in that case.
165 #if !defined(NFS_ROOT)
166 struct nfs_diskless nfs_diskless = { { { 0 } } };
167 struct nfsv3_diskless nfsv3_diskless = { { { 0 } } };
168 int nfs_diskless_valid = 0;
171 SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
172 &nfs_diskless_valid, 0,
173 "Has the diskless struct been filled correctly");
175 SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
176 nfsv3_diskless.root_hostnam, 0, "Path to nfs root");
178 SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
179 &nfsv3_diskless.root_saddr, sizeof(nfsv3_diskless.root_saddr),
180 "%Ssockaddr_in", "Diskless root nfs address");
182 void newnfsargs_ntoh(struct nfs_args *);
183 static int nfs_mountdiskless(char *,
184 struct sockaddr_in *, struct nfs_args *,
185 struct thread *, struct vnode **, struct mount *);
186 static void nfs_convert_diskless(void);
187 static void nfs_convert_oargs(struct nfs_args *args,
188 struct onfs_args *oargs);
191 newnfs_iosize(struct nfsmount *nmp)
195 /* First, set the upper limit for iosize */
196 if (nmp->nm_flag & NFSMNT_NFSV4) {
197 maxio = NFS_MAXBSIZE;
198 } else if (nmp->nm_flag & NFSMNT_NFSV3) {
199 if (nmp->nm_sotype == SOCK_DGRAM)
200 maxio = NFS_MAXDGRAMDATA;
202 maxio = NFS_MAXBSIZE;
204 maxio = NFS_V2MAXDATA;
206 if (nmp->nm_rsize > maxio || nmp->nm_rsize == 0)
207 nmp->nm_rsize = maxio;
208 if (nmp->nm_rsize > NFS_MAXBSIZE)
209 nmp->nm_rsize = NFS_MAXBSIZE;
210 if (nmp->nm_readdirsize > maxio || nmp->nm_readdirsize == 0)
211 nmp->nm_readdirsize = maxio;
212 if (nmp->nm_readdirsize > nmp->nm_rsize)
213 nmp->nm_readdirsize = nmp->nm_rsize;
214 if (nmp->nm_wsize > maxio || nmp->nm_wsize == 0)
215 nmp->nm_wsize = maxio;
216 if (nmp->nm_wsize > NFS_MAXBSIZE)
217 nmp->nm_wsize = NFS_MAXBSIZE;
220 * Calculate the size used for io buffers. Use the larger
221 * of the two sizes to minimise nfs requests but make sure
222 * that it is at least one VM page to avoid wasting buffer
223 * space. It must also be at least NFS_DIRBLKSIZ, since
224 * that is the buffer size used for directories.
226 iosize = imax(nmp->nm_rsize, nmp->nm_wsize);
227 iosize = imax(iosize, PAGE_SIZE);
228 iosize = imax(iosize, NFS_DIRBLKSIZ);
229 nmp->nm_mountp->mnt_stat.f_iosize = iosize;
234 nfs_convert_oargs(struct nfs_args *args, struct onfs_args *oargs)
237 args->version = NFS_ARGSVERSION;
238 args->addr = oargs->addr;
239 args->addrlen = oargs->addrlen;
240 args->sotype = oargs->sotype;
241 args->proto = oargs->proto;
242 args->fh = oargs->fh;
243 args->fhsize = oargs->fhsize;
244 args->flags = oargs->flags;
245 args->wsize = oargs->wsize;
246 args->rsize = oargs->rsize;
247 args->readdirsize = oargs->readdirsize;
248 args->timeo = oargs->timeo;
249 args->retrans = oargs->retrans;
250 args->readahead = oargs->readahead;
251 args->hostname = oargs->hostname;
255 nfs_convert_diskless(void)
258 bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
259 sizeof(struct ifaliasreq));
260 bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
261 sizeof(struct sockaddr_in));
262 nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
263 if (nfsv3_diskless.root_args.flags & NFSMNT_NFSV3) {
264 nfsv3_diskless.root_fhsize = NFSX_MYFH;
265 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_MYFH);
267 nfsv3_diskless.root_fhsize = NFSX_V2FH;
268 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
270 bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
271 sizeof(struct sockaddr_in));
272 bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN);
273 nfsv3_diskless.root_time = nfs_diskless.root_time;
274 bcopy(nfs_diskless.my_hostnam, nfsv3_diskless.my_hostnam,
276 nfs_diskless_valid = 3;
283 nfs_statfs(struct mount *mp, struct statfs *sbp)
287 struct nfsmount *nmp = VFSTONFS(mp);
288 struct nfsvattr nfsva;
291 int error = 0, attrflag, gotfsinfo = 0, ret;
296 error = vfs_busy(mp, MBF_NOWAIT);
299 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
305 mtx_lock(&nmp->nm_mtx);
306 if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
307 mtx_unlock(&nmp->nm_mtx);
308 error = nfsrpc_fsinfo(vp, &fs, td->td_ucred, td, &nfsva,
313 mtx_unlock(&nmp->nm_mtx);
315 error = nfsrpc_statfs(vp, &sb, &fs, td->td_ucred, td, &nfsva,
318 NFSCL_DEBUG(2, "statfs=%d\n", error);
320 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
321 td->td_ucred, td, &nfsva, NULL, NULL);
324 * Just set default values to get things going.
326 NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
327 nfsva.na_vattr.va_type = VDIR;
328 nfsva.na_vattr.va_mode = 0777;
329 nfsva.na_vattr.va_nlink = 100;
330 nfsva.na_vattr.va_uid = (uid_t)0;
331 nfsva.na_vattr.va_gid = (gid_t)0;
332 nfsva.na_vattr.va_fileid = 2;
333 nfsva.na_vattr.va_gen = 1;
334 nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
335 nfsva.na_vattr.va_size = 512 * 1024;
338 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
340 mtx_lock(&nmp->nm_mtx);
341 if (gotfsinfo || (nmp->nm_flag & NFSMNT_NFSV4))
342 nfscl_loadfsinfo(nmp, &fs);
343 nfscl_loadsbinfo(nmp, &sb, sbp);
344 sbp->f_iosize = newnfs_iosize(nmp);
345 mtx_unlock(&nmp->nm_mtx);
346 if (sbp != &mp->mnt_stat) {
347 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
348 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
350 strncpy(&sbp->f_fstypename[0], mp->mnt_vfc->vfc_name, MFSNAMELEN);
351 } else if (NFS_ISV4(vp)) {
352 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
360 * nfs version 3 fsinfo rpc call
363 ncl_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred,
367 struct nfsvattr nfsva;
370 error = nfsrpc_fsinfo(vp, &fs, cred, td, &nfsva, &attrflag, NULL);
373 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0,
375 mtx_lock(&nmp->nm_mtx);
376 nfscl_loadfsinfo(nmp, &fs);
377 mtx_unlock(&nmp->nm_mtx);
383 * Mount a remote root fs via. nfs. This depends on the info in the
384 * nfs_diskless structure that has been filled in properly by some primary
386 * It goes something like this:
387 * - do enough of "ifconfig" by calling ifioctl() so that the system
388 * can talk to the server
389 * - If nfs_diskless.mygateway is filled in, use that address as
391 * - build the rootfs mount point and call mountnfs() to do the rest.
393 * It is assumed to be safe to read, modify, and write the nfsv3_diskless
394 * structure, as well as other global NFS client variables here, as
395 * nfs_mountroot() will be called once in the boot before any other NFS
396 * client activity occurs.
399 nfs_mountroot(struct mount *mp)
401 struct thread *td = curthread;
402 struct nfsv3_diskless *nd = &nfsv3_diskless;
411 #if defined(BOOTP_NFSROOT) && defined(BOOTP)
412 bootpc_init(); /* use bootp to get nfs_diskless filled in */
413 #elif defined(NFS_ROOT)
414 nfs_setup_diskless();
417 if (nfs_diskless_valid == 0)
419 if (nfs_diskless_valid == 1)
420 nfs_convert_diskless();
423 * Do enough of ifconfig(8) so that the critical net interface can
424 * talk to the server.
426 error = socreate(nd->myif.ifra_addr.sa_family, &so, nd->root_args.sotype, 0,
429 panic("nfs_mountroot: socreate(%04x): %d",
430 nd->myif.ifra_addr.sa_family, error);
432 #if 0 /* XXX Bad idea */
434 * We might not have been told the right interface, so we pass
435 * over the first ten interfaces of the same kind, until we get
436 * one of them configured.
439 for (i = strlen(nd->myif.ifra_name) - 1;
440 nd->myif.ifra_name[i] >= '0' &&
441 nd->myif.ifra_name[i] <= '9';
442 nd->myif.ifra_name[i] ++) {
443 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
448 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
450 panic("nfs_mountroot: SIOCAIFADDR: %d", error);
451 if ((cp = kern_getenv("boot.netif.mtu")) != NULL) {
452 ir.ifr_mtu = strtol(cp, NULL, 10);
453 bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ);
455 error = ifioctl(so, SIOCSIFMTU, (caddr_t)&ir, td);
457 printf("nfs_mountroot: SIOCSIFMTU: %d", error);
462 * If the gateway field is filled in, set it as the default route.
463 * Note that pxeboot will set a default route of 0 if the route
464 * is not set by the DHCP server. Check also for a value of 0
465 * to avoid panicking inappropriately in that situation.
467 if (nd->mygateway.sin_len != 0 &&
468 nd->mygateway.sin_addr.s_addr != 0) {
469 struct sockaddr_in mask, sin;
470 struct epoch_tracker et;
471 struct rt_addrinfo info;
472 struct rib_cmd_info rc;
474 bzero((caddr_t)&mask, sizeof(mask));
476 sin.sin_family = AF_INET;
477 sin.sin_len = sizeof(sin);
478 /* XXX MRT use table 0 for this sort of thing */
480 CURVNET_SET(TD_TO_VNET(td));
482 bzero((caddr_t)&info, sizeof(info));
483 info.rti_flags = RTF_UP | RTF_GATEWAY;
484 info.rti_info[RTAX_DST] = (struct sockaddr *)&sin;
485 info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&nd->mygateway;
486 info.rti_info[RTAX_NETMASK] = (struct sockaddr *)&mask;
488 error = rib_action(RT_DEFAULT_FIB, RTM_ADD, &info, &rc);
492 panic("nfs_mountroot: RTM_ADD: %d", error);
496 * Create the rootfs mount point.
498 nd->root_args.fh = nd->root_fh;
499 nd->root_args.fhsize = nd->root_fhsize;
500 l = ntohl(nd->root_saddr.sin_addr.s_addr);
501 snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
502 (l >> 24) & 0xff, (l >> 16) & 0xff,
503 (l >> 8) & 0xff, (l >> 0) & 0xff, nd->root_hostnam);
504 printf("NFS ROOT: %s\n", buf);
505 nd->root_args.hostname = buf;
506 if ((error = nfs_mountdiskless(buf,
507 &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) {
512 * This is not really an nfs issue, but it is much easier to
513 * set hostname here and then let the "/etc/rc.xxx" files
514 * mount the right /var based upon its preset value.
516 mtx_lock(&prison0.pr_mtx);
517 strlcpy(prison0.pr_hostname, nd->my_hostnam,
518 sizeof(prison0.pr_hostname));
519 mtx_unlock(&prison0.pr_mtx);
520 inittodr(ntohl(nd->root_time));
525 * Internal version of mount system call for diskless setup.
528 nfs_mountdiskless(char *path,
529 struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
530 struct vnode **vpp, struct mount *mp)
532 struct sockaddr *nam;
537 * Find the directory path in "path", which also has the server's
538 * name/ip address in it.
540 dirpath = strchr(path, ':');
542 dirlen = strlen(++dirpath);
545 nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
546 if ((error = mountnfs(args, mp, nam, path, NULL, 0, dirpath, dirlen,
547 NULL, 0, vpp, td->td_ucred, td, NFS_DEFAULT_NAMETIMEO,
548 NFS_DEFAULT_NEGNAMETIMEO, 0, 0)) != 0) {
549 printf("nfs_mountroot: mount %s on /: %d\n", path, error);
556 nfs_sec_name(char *sec, int *flagsp)
558 if (!strcmp(sec, "krb5"))
559 *flagsp |= NFSMNT_KERB;
560 else if (!strcmp(sec, "krb5i"))
561 *flagsp |= (NFSMNT_KERB | NFSMNT_INTEGRITY);
562 else if (!strcmp(sec, "krb5p"))
563 *flagsp |= (NFSMNT_KERB | NFSMNT_PRIVACY);
567 nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
568 const char *hostname, struct ucred *cred, struct thread *td)
574 * Set read-only flag if requested; otherwise, clear it if this is
575 * an update. If this is not an update, then either the read-only
576 * flag is already clear, or this is a root mount and it was set
577 * intentionally at some previous point.
579 if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) {
581 mp->mnt_flag |= MNT_RDONLY;
583 } else if (mp->mnt_flag & MNT_UPDATE) {
585 mp->mnt_flag &= ~MNT_RDONLY;
590 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
591 * no sense in that context. Also, set up appropriate retransmit
592 * and soft timeout behavior.
594 if (argp->sotype == SOCK_STREAM) {
595 nmp->nm_flag &= ~NFSMNT_NOCONN;
596 nmp->nm_timeo = NFS_MAXTIMEO;
597 if ((argp->flags & NFSMNT_NFSV4) != 0)
598 nmp->nm_retry = INT_MAX;
600 nmp->nm_retry = NFS_RETRANS_TCP;
603 /* Also clear RDIRPLUS if NFSv2, it crashes some servers */
604 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
605 argp->flags &= ~NFSMNT_RDIRPLUS;
606 nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
609 /* Clear ONEOPENOWN for NFSv2, 3 and 4.0. */
610 if (nmp->nm_minorvers == 0) {
611 argp->flags &= ~NFSMNT_ONEOPENOWN;
612 nmp->nm_flag &= ~NFSMNT_ONEOPENOWN;
615 /* Re-bind if rsrvd port requested and wasn't on one */
616 adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
617 && (argp->flags & NFSMNT_RESVPORT);
618 /* Also re-bind if we're switching to/from a connected UDP socket */
619 adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
620 (argp->flags & NFSMNT_NOCONN));
622 /* Update flags atomically. Don't change the lock bits. */
623 nmp->nm_flag = argp->flags | nmp->nm_flag;
625 if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
626 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
627 if (nmp->nm_timeo < NFS_MINTIMEO)
628 nmp->nm_timeo = NFS_MINTIMEO;
629 else if (nmp->nm_timeo > NFS_MAXTIMEO)
630 nmp->nm_timeo = NFS_MAXTIMEO;
633 if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
634 nmp->nm_retry = argp->retrans;
635 if (nmp->nm_retry > NFS_MAXREXMIT)
636 nmp->nm_retry = NFS_MAXREXMIT;
639 if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
640 nmp->nm_wsize = argp->wsize;
642 * Clip at the power of 2 below the size. There is an
643 * issue (not isolated) that causes intermittent page
644 * faults if this is not done.
646 if (nmp->nm_wsize > NFS_FABLKSIZE)
647 nmp->nm_wsize = 1 << (fls(nmp->nm_wsize) - 1);
649 nmp->nm_wsize = NFS_FABLKSIZE;
652 if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
653 nmp->nm_rsize = argp->rsize;
655 * Clip at the power of 2 below the size. There is an
656 * issue (not isolated) that causes intermittent page
657 * faults if this is not done.
659 if (nmp->nm_rsize > NFS_FABLKSIZE)
660 nmp->nm_rsize = 1 << (fls(nmp->nm_rsize) - 1);
662 nmp->nm_rsize = NFS_FABLKSIZE;
665 if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
666 nmp->nm_readdirsize = argp->readdirsize;
669 if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
670 nmp->nm_acregmin = argp->acregmin;
672 nmp->nm_acregmin = NFS_MINATTRTIMO;
673 if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
674 nmp->nm_acregmax = argp->acregmax;
676 nmp->nm_acregmax = NFS_MAXATTRTIMO;
677 if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
678 nmp->nm_acdirmin = argp->acdirmin;
680 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
681 if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
682 nmp->nm_acdirmax = argp->acdirmax;
684 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
685 if (nmp->nm_acdirmin > nmp->nm_acdirmax)
686 nmp->nm_acdirmin = nmp->nm_acdirmax;
687 if (nmp->nm_acregmin > nmp->nm_acregmax)
688 nmp->nm_acregmin = nmp->nm_acregmax;
690 if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
691 if (argp->readahead <= NFS_MAXRAHEAD)
692 nmp->nm_readahead = argp->readahead;
694 nmp->nm_readahead = NFS_MAXRAHEAD;
696 if ((argp->flags & NFSMNT_WCOMMITSIZE) && argp->wcommitsize >= 0) {
697 if (argp->wcommitsize < nmp->nm_wsize)
698 nmp->nm_wcommitsize = nmp->nm_wsize;
700 nmp->nm_wcommitsize = argp->wcommitsize;
703 adjsock |= ((nmp->nm_sotype != argp->sotype) ||
704 (nmp->nm_soproto != argp->proto));
706 if (nmp->nm_client != NULL && adjsock) {
707 int haslock = 0, error = 0;
709 if (nmp->nm_sotype == SOCK_STREAM) {
710 error = newnfs_sndlock(&nmp->nm_sockreq.nr_lock);
715 newnfs_disconnect(&nmp->nm_sockreq);
717 newnfs_sndunlock(&nmp->nm_sockreq.nr_lock);
718 nmp->nm_sotype = argp->sotype;
719 nmp->nm_soproto = argp->proto;
720 if (nmp->nm_sotype == SOCK_DGRAM)
721 while (newnfs_connect(nmp, &nmp->nm_sockreq,
722 cred, td, 0, false)) {
723 printf("newnfs_args: retrying connect\n");
724 (void) nfs_catnap(PSOCK, 0, "nfscon");
728 nmp->nm_sotype = argp->sotype;
729 nmp->nm_soproto = argp->proto;
732 if (hostname != NULL) {
733 strlcpy(nmp->nm_hostname, hostname,
734 sizeof(nmp->nm_hostname));
735 p = strchr(nmp->nm_hostname, ':');
741 static const char *nfs_opts[] = { "from", "nfs_args",
742 "noac", "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
743 "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
744 "async", "noconn", "nolockd", "conn", "lockd", "intr", "rdirplus",
745 "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize",
746 "retrans", "actimeo", "acregmin", "acregmax", "acdirmin", "acdirmax",
747 "resvport", "readahead", "hostname", "timeo", "timeout", "addr", "fh",
748 "nfsv3", "sec", "principal", "nfsv4", "gssname", "allgssname", "dirpath",
749 "minorversion", "nametimeo", "negnametimeo", "nocto", "noncontigwr",
750 "pnfs", "wcommitsize", "oneopenown", "tls",
754 * Parse the "from" mountarg, passed by the generic mount(8) program
755 * or the mountroot code. This is used when rerooting into NFS.
757 * Note that the "hostname" is actually a "hostname:/share/path" string.
760 nfs_mount_parse_from(struct vfsoptlist *opts, char **hostnamep,
761 struct sockaddr_in **sinp, char *dirpath, size_t dirpathsize, int *dirlenp)
763 char *nam, *delimp, *hostp, *spec;
764 int error, have_bracket = 0, offset, rv, speclen;
765 struct sockaddr_in *sin;
768 error = vfs_getopt(opts, "from", (void **)&spec, &speclen);
771 nam = malloc(MNAMELEN + 1, M_TEMP, M_WAITOK);
774 * This part comes from sbin/mount_nfs/mount_nfs.c:getnfsargs().
776 if (*spec == '[' && (delimp = strchr(spec + 1, ']')) != NULL &&
777 *(delimp + 1) == ':') {
781 } else if ((delimp = strrchr(spec, ':')) != NULL) {
784 } else if ((delimp = strrchr(spec, '@')) != NULL) {
785 printf("%s: path@server syntax is deprecated, "
786 "use server:path\n", __func__);
789 printf("%s: no <host>:<dirpath> nfs-name\n", __func__);
796 * If there has been a trailing slash at mounttime it seems
797 * that some mountd implementations fail to remove the mount
798 * entries from their mountlist while unmounting.
800 for (speclen = strlen(spec);
801 speclen > 1 && spec[speclen - 1] == '/';
803 spec[speclen - 1] = '\0';
804 if (strlen(hostp) + strlen(spec) + 1 > MNAMELEN) {
805 printf("%s: %s:%s: name too long", __func__, hostp, spec);
809 /* Make both '@' and ':' notations equal */
810 if (*hostp != '\0') {
815 memmove(nam + offset, hostp, len);
817 nam[len + offset++] = ']';
818 nam[len + offset++] = ':';
819 memmove(nam + len + offset, spec, speclen);
820 nam[len + speclen + offset] = '\0';
827 sin = malloc(sizeof(*sin), M_SONAME, M_WAITOK);
828 rv = inet_pton(AF_INET, hostp, &sin->sin_addr);
830 printf("%s: cannot parse '%s', inet_pton() returned %d\n",
831 __func__, hostp, rv);
837 sin->sin_len = sizeof(*sin);
838 sin->sin_family = AF_INET;
840 * XXX: hardcoded port number.
842 sin->sin_port = htons(2049);
844 *hostnamep = strdup(nam, M_NEWNFSMNT);
846 strlcpy(dirpath, spec, dirpathsize);
847 *dirlenp = strlen(dirpath);
857 * It seems a bit dumb to copyinstr() the host and path here and then
858 * bcopy() them in mountnfs(), but I wanted to detect errors before
859 * doing the getsockaddr() call because getsockaddr() allocates an mbuf and
860 * an error after that means that I have to release the mbuf.
864 nfs_mount(struct mount *mp)
866 struct nfs_args args = {
867 .version = NFS_ARGSVERSION,
869 .addrlen = sizeof (struct sockaddr_in),
870 .sotype = SOCK_STREAM,
874 .flags = NFSMNT_RESVPORT,
877 .readdirsize = NFS_READDIRSIZE,
879 .retrans = NFS_RETRANS,
880 .readahead = NFS_DEFRAHEAD,
881 .wcommitsize = 0, /* was: NQ_DEFLEASE */
883 .acregmin = NFS_MINATTRTIMO,
884 .acregmax = NFS_MAXATTRTIMO,
885 .acdirmin = NFS_MINDIRATTRTIMO,
886 .acdirmax = NFS_MAXDIRATTRTIMO,
888 int error = 0, ret, len;
889 struct sockaddr *nam = NULL;
893 u_char nfh[NFSX_FHMAX], krbname[100], dirpath[100], srvkrbname[100];
894 char *cp, *opt, *name, *secname;
895 int nametimeo = NFS_DEFAULT_NAMETIMEO;
896 int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
898 int dirlen, has_nfs_args_opt, has_nfs_from_opt,
899 krbnamelen, srvkrbnamelen;
903 has_nfs_args_opt = 0;
904 has_nfs_from_opt = 0;
906 hst = malloc(MNAMELEN, M_TEMP, M_WAITOK);
907 if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
913 if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS &&
914 nfs_diskless_valid != 0) {
915 error = nfs_mountroot(mp);
922 * The old mount_nfs program passed the struct nfs_args
923 * from userspace to kernel. The new mount_nfs program
924 * passes string options via nmount() from userspace to kernel
925 * and we populate the struct nfs_args in the kernel.
927 if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
928 error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
933 if (args.version != NFS_ARGSVERSION) {
934 error = EPROGMISMATCH;
937 has_nfs_args_opt = 1;
940 /* Handle the new style options. */
941 if (vfs_getopt(mp->mnt_optnew, "noac", NULL, NULL) == 0) {
942 args.acdirmin = args.acdirmax =
943 args.acregmin = args.acregmax = 0;
944 args.flags |= NFSMNT_ACDIRMIN | NFSMNT_ACDIRMAX |
945 NFSMNT_ACREGMIN | NFSMNT_ACREGMAX;
947 if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
948 args.flags |= NFSMNT_NOCONN;
949 if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
950 args.flags &= ~NFSMNT_NOCONN;
951 if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
952 args.flags |= NFSMNT_NOLOCKD;
953 if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
954 args.flags &= ~NFSMNT_NOLOCKD;
955 if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
956 args.flags |= NFSMNT_INT;
957 if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
958 args.flags |= NFSMNT_RDIRPLUS;
959 if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
960 args.flags |= NFSMNT_RESVPORT;
961 if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
962 args.flags &= ~NFSMNT_RESVPORT;
963 if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
964 args.flags |= NFSMNT_SOFT;
965 if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
966 args.flags &= ~NFSMNT_SOFT;
967 if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
968 args.sotype = SOCK_DGRAM;
969 if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
970 args.sotype = SOCK_DGRAM;
971 if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
972 args.sotype = SOCK_STREAM;
973 if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
974 args.flags |= NFSMNT_NFSV3;
975 if (vfs_getopt(mp->mnt_optnew, "nfsv4", NULL, NULL) == 0) {
976 args.flags |= NFSMNT_NFSV4;
977 args.sotype = SOCK_STREAM;
979 if (vfs_getopt(mp->mnt_optnew, "allgssname", NULL, NULL) == 0)
980 args.flags |= NFSMNT_ALLGSSNAME;
981 if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0)
982 args.flags |= NFSMNT_NOCTO;
983 if (vfs_getopt(mp->mnt_optnew, "noncontigwr", NULL, NULL) == 0)
984 args.flags |= NFSMNT_NONCONTIGWR;
985 if (vfs_getopt(mp->mnt_optnew, "pnfs", NULL, NULL) == 0)
986 args.flags |= NFSMNT_PNFS;
987 if (vfs_getopt(mp->mnt_optnew, "oneopenown", NULL, NULL) == 0)
988 args.flags |= NFSMNT_ONEOPENOWN;
989 if (vfs_getopt(mp->mnt_optnew, "tls", NULL, NULL) == 0)
990 newflag |= NFSMNT_TLS;
991 if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
993 vfs_mount_error(mp, "illegal readdirsize");
997 ret = sscanf(opt, "%d", &args.readdirsize);
998 if (ret != 1 || args.readdirsize <= 0) {
999 vfs_mount_error(mp, "illegal readdirsize: %s",
1004 args.flags |= NFSMNT_READDIRSIZE;
1006 if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
1008 vfs_mount_error(mp, "illegal readahead");
1012 ret = sscanf(opt, "%d", &args.readahead);
1013 if (ret != 1 || args.readahead <= 0) {
1014 vfs_mount_error(mp, "illegal readahead: %s",
1019 args.flags |= NFSMNT_READAHEAD;
1021 if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
1023 vfs_mount_error(mp, "illegal wsize");
1027 ret = sscanf(opt, "%d", &args.wsize);
1028 if (ret != 1 || args.wsize <= 0) {
1029 vfs_mount_error(mp, "illegal wsize: %s",
1034 args.flags |= NFSMNT_WSIZE;
1036 if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
1038 vfs_mount_error(mp, "illegal rsize");
1042 ret = sscanf(opt, "%d", &args.rsize);
1043 if (ret != 1 || args.rsize <= 0) {
1044 vfs_mount_error(mp, "illegal wsize: %s",
1049 args.flags |= NFSMNT_RSIZE;
1051 if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
1053 vfs_mount_error(mp, "illegal retrans");
1057 ret = sscanf(opt, "%d", &args.retrans);
1058 if (ret != 1 || args.retrans <= 0) {
1059 vfs_mount_error(mp, "illegal retrans: %s",
1064 args.flags |= NFSMNT_RETRANS;
1066 if (vfs_getopt(mp->mnt_optnew, "actimeo", (void **)&opt, NULL) == 0) {
1067 ret = sscanf(opt, "%d", &args.acregmin);
1068 if (ret != 1 || args.acregmin < 0) {
1069 vfs_mount_error(mp, "illegal actimeo: %s",
1074 args.acdirmin = args.acdirmax = args.acregmax = args.acregmin;
1075 args.flags |= NFSMNT_ACDIRMIN | NFSMNT_ACDIRMAX |
1076 NFSMNT_ACREGMIN | NFSMNT_ACREGMAX;
1078 if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
1079 ret = sscanf(opt, "%d", &args.acregmin);
1080 if (ret != 1 || args.acregmin < 0) {
1081 vfs_mount_error(mp, "illegal acregmin: %s",
1086 args.flags |= NFSMNT_ACREGMIN;
1088 if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
1089 ret = sscanf(opt, "%d", &args.acregmax);
1090 if (ret != 1 || args.acregmax < 0) {
1091 vfs_mount_error(mp, "illegal acregmax: %s",
1096 args.flags |= NFSMNT_ACREGMAX;
1098 if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
1099 ret = sscanf(opt, "%d", &args.acdirmin);
1100 if (ret != 1 || args.acdirmin < 0) {
1101 vfs_mount_error(mp, "illegal acdirmin: %s",
1106 args.flags |= NFSMNT_ACDIRMIN;
1108 if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
1109 ret = sscanf(opt, "%d", &args.acdirmax);
1110 if (ret != 1 || args.acdirmax < 0) {
1111 vfs_mount_error(mp, "illegal acdirmax: %s",
1116 args.flags |= NFSMNT_ACDIRMAX;
1118 if (vfs_getopt(mp->mnt_optnew, "wcommitsize", (void **)&opt, NULL) == 0) {
1119 ret = sscanf(opt, "%d", &args.wcommitsize);
1120 if (ret != 1 || args.wcommitsize < 0) {
1121 vfs_mount_error(mp, "illegal wcommitsize: %s", opt);
1125 args.flags |= NFSMNT_WCOMMITSIZE;
1127 if (vfs_getopt(mp->mnt_optnew, "timeo", (void **)&opt, NULL) == 0) {
1128 ret = sscanf(opt, "%d", &args.timeo);
1129 if (ret != 1 || args.timeo <= 0) {
1130 vfs_mount_error(mp, "illegal timeo: %s",
1135 args.flags |= NFSMNT_TIMEO;
1137 if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
1138 ret = sscanf(opt, "%d", &args.timeo);
1139 if (ret != 1 || args.timeo <= 0) {
1140 vfs_mount_error(mp, "illegal timeout: %s",
1145 args.flags |= NFSMNT_TIMEO;
1147 if (vfs_getopt(mp->mnt_optnew, "nametimeo", (void **)&opt, NULL) == 0) {
1148 ret = sscanf(opt, "%d", &nametimeo);
1149 if (ret != 1 || nametimeo < 0) {
1150 vfs_mount_error(mp, "illegal nametimeo: %s", opt);
1155 if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
1157 ret = sscanf(opt, "%d", &negnametimeo);
1158 if (ret != 1 || negnametimeo < 0) {
1159 vfs_mount_error(mp, "illegal negnametimeo: %s",
1165 if (vfs_getopt(mp->mnt_optnew, "minorversion", (void **)&opt, NULL) ==
1167 ret = sscanf(opt, "%d", &minvers);
1168 if (ret != 1 || minvers < 0 || minvers > 2 ||
1169 (args.flags & NFSMNT_NFSV4) == 0) {
1170 vfs_mount_error(mp, "illegal minorversion: %s", opt);
1175 if (vfs_getopt(mp->mnt_optnew, "sec",
1176 (void **) &secname, NULL) == 0)
1177 nfs_sec_name(secname, &args.flags);
1179 if (mp->mnt_flag & MNT_UPDATE) {
1180 struct nfsmount *nmp = VFSTONFS(mp);
1188 * If a change from TCP->UDP is done and there are thread(s)
1189 * that have I/O RPC(s) in progress with a transfer size
1190 * greater than NFS_MAXDGRAMDATA, those thread(s) will be
1191 * hung, retrying the RPC(s) forever. Usually these threads
1192 * will be seen doing an uninterruptible sleep on wait channel
1195 if (args.sotype == SOCK_DGRAM && nmp->nm_sotype == SOCK_STREAM)
1196 tprintf(td->td_proc, LOG_WARNING,
1197 "Warning: mount -u that changes TCP->UDP can result in hung threads\n");
1200 * When doing an update, we can't change version,
1201 * security, switch lockd strategies, change cookie
1202 * translation or switch oneopenown.
1204 args.flags = (args.flags &
1211 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
1219 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
1220 nfs_decode_args(mp, nmp, &args, NULL, td->td_ucred, td);
1225 * Make the nfs_ip_paranoia sysctl serve as the default connection
1226 * or no-connection mode for those protocols that support
1227 * no-connection mode (the flag will be cleared later for protocols
1228 * that do not support no-connection mode). This will allow a client
1229 * to receive replies from a different IP then the request was
1230 * sent to. Note: default value for nfs_ip_paranoia is 1 (paranoid),
1233 if (nfs_ip_paranoia == 0)
1234 args.flags |= NFSMNT_NOCONN;
1236 if (has_nfs_args_opt != 0) {
1238 * In the 'nfs_args' case, the pointers in the args
1239 * structure are in userland - we copy them in here.
1241 if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
1242 vfs_mount_error(mp, "Bad file handle");
1246 error = copyin((caddr_t)args.fh, (caddr_t)nfh,
1250 error = copyinstr(args.hostname, hst, MNAMELEN - 1, &hstlen);
1253 bzero(&hst[hstlen], MNAMELEN - hstlen);
1254 args.hostname = hst;
1255 /* getsockaddr() call must be after above copyin() calls */
1256 error = getsockaddr(&nam, args.addr, args.addrlen);
1259 } else if (nfs_mount_parse_from(mp->mnt_optnew,
1260 &args.hostname, (struct sockaddr_in **)&nam, dirpath,
1261 sizeof(dirpath), &dirlen) == 0) {
1262 has_nfs_from_opt = 1;
1263 bcopy(args.hostname, hst, MNAMELEN);
1264 hst[MNAMELEN - 1] = '\0';
1267 * This only works with NFSv4 for now.
1270 args.flags |= NFSMNT_NFSV4;
1271 args.sotype = SOCK_STREAM;
1273 if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
1274 &args.fhsize) == 0) {
1275 if (args.fhsize < 0 || args.fhsize > NFSX_FHMAX) {
1276 vfs_mount_error(mp, "Bad file handle");
1280 bcopy(args.fh, nfh, args.fhsize);
1284 (void) vfs_getopt(mp->mnt_optnew, "hostname",
1285 (void **)&args.hostname, &len);
1286 if (args.hostname == NULL) {
1287 vfs_mount_error(mp, "Invalid hostname");
1291 if (len >= MNAMELEN) {
1292 vfs_mount_error(mp, "Hostname too long");
1296 bcopy(args.hostname, hst, len);
1300 if (vfs_getopt(mp->mnt_optnew, "principal", (void **)&name, NULL) == 0)
1301 strlcpy(srvkrbname, name, sizeof (srvkrbname));
1303 snprintf(srvkrbname, sizeof (srvkrbname), "nfs@%s", hst);
1304 cp = strchr(srvkrbname, ':');
1308 srvkrbnamelen = strlen(srvkrbname);
1310 if (vfs_getopt(mp->mnt_optnew, "gssname", (void **)&name, NULL) == 0)
1311 strlcpy(krbname, name, sizeof (krbname));
1314 krbnamelen = strlen(krbname);
1316 if (has_nfs_from_opt == 0) {
1317 if (vfs_getopt(mp->mnt_optnew,
1318 "dirpath", (void **)&name, NULL) == 0)
1319 strlcpy(dirpath, name, sizeof (dirpath));
1322 dirlen = strlen(dirpath);
1325 if (has_nfs_args_opt == 0 && has_nfs_from_opt == 0) {
1326 if (vfs_getopt(mp->mnt_optnew, "addr",
1327 (void **)&args.addr, &args.addrlen) == 0) {
1328 if (args.addrlen > SOCK_MAXADDRLEN) {
1329 error = ENAMETOOLONG;
1332 nam = malloc(args.addrlen, M_SONAME, M_WAITOK);
1333 bcopy(args.addr, nam, args.addrlen);
1334 nam->sa_len = args.addrlen;
1336 vfs_mount_error(mp, "No server address");
1343 error = mountnfs(&args, mp, nam, hst, krbname, krbnamelen, dirpath,
1344 dirlen, srvkrbname, srvkrbnamelen, &vp, td->td_ucred, td,
1345 nametimeo, negnametimeo, minvers, newflag);
1349 mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED | MNTK_NO_IOPF |
1351 if ((VFSTONFS(mp)->nm_flag & NFSMNT_NFSV4) != 0)
1352 mp->mnt_kern_flag |= MNTK_NULL_NOCACHE;
1363 * It seems a bit dumb to copyinstr() the host and path here and then
1364 * bcopy() them in mountnfs(), but I wanted to detect errors before
1365 * doing the getsockaddr() call because getsockaddr() allocates an mbuf and
1366 * an error after that means that I have to release the mbuf.
1370 nfs_cmount(struct mntarg *ma, void *data, uint64_t flags)
1373 struct nfs_args args;
1375 error = copyin(data, &args, sizeof (struct nfs_args));
1379 ma = mount_arg(ma, "nfs_args", &args, sizeof args);
1381 error = kernel_mount(ma, flags);
1386 * Common code for mount and mountroot
1389 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
1390 char *hst, u_char *krbname, int krbnamelen, u_char *dirpath, int dirlen,
1391 u_char *srvkrbname, int srvkrbnamelen, struct vnode **vpp,
1392 struct ucred *cred, struct thread *td, int nametimeo, int negnametimeo,
1393 int minvers, uint32_t newflag)
1395 struct nfsmount *nmp;
1397 int error, trycnt, ret;
1398 struct nfsvattr nfsva;
1399 struct nfsclclient *clp;
1400 struct nfsclds *dsp, *tdsp;
1402 static u_int64_t clval = 0;
1407 NFSCL_DEBUG(3, "in mnt\n");
1409 if (mp->mnt_flag & MNT_UPDATE) {
1411 printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
1412 free(nam, M_SONAME);
1415 /* NFS-over-TLS requires that rpctls be functioning. */
1416 if ((newflag & NFSMNT_TLS) != 0) {
1419 /* KERN_TLS is only supported for TCP. */
1420 if (argp->sotype == SOCK_STREAM &&
1421 rpctls_getinfo(&maxlen, true, false))
1425 free(nam, M_SONAME);
1429 nmp = malloc(sizeof (struct nfsmount) +
1430 krbnamelen + dirlen + srvkrbnamelen + 2,
1431 M_NEWNFSMNT, M_WAITOK | M_ZERO);
1432 nmp->nm_newflag = newflag;
1433 TAILQ_INIT(&nmp->nm_bufq);
1434 TAILQ_INIT(&nmp->nm_sess);
1436 clval = (u_int64_t)nfsboottime.tv_sec;
1437 nmp->nm_clval = clval++;
1438 nmp->nm_krbnamelen = krbnamelen;
1439 nmp->nm_dirpathlen = dirlen;
1440 nmp->nm_srvkrbnamelen = srvkrbnamelen;
1441 if (td->td_ucred->cr_uid != (uid_t)0) {
1443 * nm_uid is used to get KerberosV credentials for
1444 * the nfsv4 state handling operations if there is
1445 * no host based principal set. Use the uid of
1446 * this user if not root, since they are doing the
1447 * mount. I don't think setting this for root will
1448 * work, since root normally does not have user
1449 * credentials in a credentials cache.
1451 nmp->nm_uid = td->td_ucred->cr_uid;
1454 * Just set to -1, so it won't be used.
1456 nmp->nm_uid = (uid_t)-1;
1459 /* Copy and null terminate all the names */
1460 if (nmp->nm_krbnamelen > 0) {
1461 bcopy(krbname, nmp->nm_krbname, nmp->nm_krbnamelen);
1462 nmp->nm_name[nmp->nm_krbnamelen] = '\0';
1464 if (nmp->nm_dirpathlen > 0) {
1465 bcopy(dirpath, NFSMNT_DIRPATH(nmp),
1466 nmp->nm_dirpathlen);
1467 nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1470 if (nmp->nm_srvkrbnamelen > 0) {
1471 bcopy(srvkrbname, NFSMNT_SRVKRBNAME(nmp),
1472 nmp->nm_srvkrbnamelen);
1473 nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1474 + nmp->nm_srvkrbnamelen + 2] = '\0';
1476 nmp->nm_sockreq.nr_cred = crhold(cred);
1477 mtx_init(&nmp->nm_sockreq.nr_mtx, "nfssock", NULL, MTX_DEF);
1479 nmp->nm_getinfo = nfs_getnlminfo;
1480 nmp->nm_vinvalbuf = ncl_vinvalbuf;
1483 nmp->nm_mountp = mp;
1484 mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF | MTX_DUPOK);
1487 * Since nfs_decode_args() might optionally set them, these
1488 * need to be set to defaults before the call, so that the
1489 * optional settings aren't overwritten.
1491 nmp->nm_nametimeo = nametimeo;
1492 nmp->nm_negnametimeo = negnametimeo;
1493 nmp->nm_timeo = NFS_TIMEO;
1494 nmp->nm_retry = NFS_RETRANS;
1495 nmp->nm_readahead = NFS_DEFRAHEAD;
1497 /* This is empirical approximation of sqrt(hibufspace) * 256. */
1498 nmp->nm_wcommitsize = NFS_MAXBSIZE / 256;
1499 while ((long)nmp->nm_wcommitsize * nmp->nm_wcommitsize < hibufspace)
1500 nmp->nm_wcommitsize *= 2;
1501 nmp->nm_wcommitsize *= 256;
1503 if ((argp->flags & NFSMNT_NFSV4) != 0)
1504 nmp->nm_minorvers = minvers;
1506 nmp->nm_minorvers = 0;
1508 nfs_decode_args(mp, nmp, argp, hst, cred, td);
1511 * V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too
1512 * high, depending on whether we end up with negative offsets in
1513 * the client or server somewhere. 2GB-1 may be safer.
1515 * For V3, ncl_fsinfo will adjust this as necessary. Assume maximum
1516 * that we can handle until we find out otherwise.
1518 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0)
1519 nmp->nm_maxfilesize = 0xffffffffLL;
1521 nmp->nm_maxfilesize = OFF_MAX;
1523 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
1524 nmp->nm_wsize = NFS_WSIZE;
1525 nmp->nm_rsize = NFS_RSIZE;
1526 nmp->nm_readdirsize = NFS_READDIRSIZE;
1528 nmp->nm_numgrps = NFS_MAXGRPS;
1529 nmp->nm_tprintf_delay = nfs_tprintf_delay;
1530 if (nmp->nm_tprintf_delay < 0)
1531 nmp->nm_tprintf_delay = 0;
1532 nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
1533 if (nmp->nm_tprintf_initial_delay < 0)
1534 nmp->nm_tprintf_initial_delay = 0;
1535 nmp->nm_fhsize = argp->fhsize;
1536 if (nmp->nm_fhsize > 0)
1537 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
1538 bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
1540 /* Set up the sockets and per-host congestion */
1541 nmp->nm_sotype = argp->sotype;
1542 nmp->nm_soproto = argp->proto;
1543 nmp->nm_sockreq.nr_prog = NFS_PROG;
1544 if ((argp->flags & NFSMNT_NFSV4))
1545 nmp->nm_sockreq.nr_vers = NFS_VER4;
1546 else if ((argp->flags & NFSMNT_NFSV3))
1547 nmp->nm_sockreq.nr_vers = NFS_VER3;
1549 nmp->nm_sockreq.nr_vers = NFS_VER2;
1551 if ((error = newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0, false)))
1553 /* For NFSv4.1, get the clientid now. */
1554 if (nmp->nm_minorvers > 0) {
1555 NFSCL_DEBUG(3, "at getcl\n");
1556 error = nfscl_getcl(mp, cred, td, 0, &clp);
1557 NFSCL_DEBUG(3, "aft getcl=%d\n", error);
1562 if (nmp->nm_fhsize == 0 && (nmp->nm_flag & NFSMNT_NFSV4) &&
1563 nmp->nm_dirpathlen > 0) {
1564 NFSCL_DEBUG(3, "in dirp\n");
1566 * If the fhsize on the mount point == 0 for V4, the mount
1567 * path needs to be looked up.
1571 error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp),
1573 NFSCL_DEBUG(3, "aft dirp=%d\n", error);
1575 (void) nfs_catnap(PZERO, error, "nfsgetdirp");
1576 } while (error && --trycnt > 0);
1582 * A reference count is needed on the nfsnode representing the
1583 * remote root. If this object is not persistent, then backward
1584 * traversals of the mount point (i.e. "..") will not work if
1585 * the nfsnode gets flushed out of the cache. Ufs does not have
1586 * this problem, because one can identify root inodes by their
1587 * number == UFS_ROOTINO (2).
1589 if (nmp->nm_fhsize > 0) {
1591 * Set f_iosize to NFS_DIRBLKSIZ so that bo_bsize gets set
1592 * non-zero for the root vnode. f_iosize will be set correctly
1593 * by nfs_statfs() before any I/O occurs.
1595 mp->mnt_stat.f_iosize = NFS_DIRBLKSIZ;
1596 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np,
1603 * Get file attributes and transfer parameters for the
1604 * mountpoint. This has the side effect of filling in
1605 * (*vpp)->v_type with the correct value.
1607 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
1608 cred, td, &nfsva, NULL, &lease);
1611 * Just set default values to get things going.
1613 NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
1614 nfsva.na_vattr.va_type = VDIR;
1615 nfsva.na_vattr.va_mode = 0777;
1616 nfsva.na_vattr.va_nlink = 100;
1617 nfsva.na_vattr.va_uid = (uid_t)0;
1618 nfsva.na_vattr.va_gid = (gid_t)0;
1619 nfsva.na_vattr.va_fileid = 2;
1620 nfsva.na_vattr.va_gen = 1;
1621 nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
1622 nfsva.na_vattr.va_size = 512 * 1024;
1625 (void) nfscl_loadattrcache(vpp, &nfsva, NULL, NULL, 0, 1);
1626 if (nmp->nm_minorvers > 0) {
1627 NFSCL_DEBUG(3, "lease=%d\n", (int)lease);
1629 clp->nfsc_renew = NFSCL_RENEW(lease);
1630 clp->nfsc_expire = NFSD_MONOSEC + clp->nfsc_renew;
1631 clp->nfsc_clientidrev++;
1632 if (clp->nfsc_clientidrev == 0)
1633 clp->nfsc_clientidrev++;
1636 * Mount will succeed, so the renew thread can be
1639 nfscl_start_renewthread(clp);
1640 nfscl_clientrelease(clp);
1642 if (argp->flags & NFSMNT_NFSV3)
1643 ncl_fsinfo(nmp, *vpp, cred, td);
1645 /* Mark if the mount point supports NFSv4 ACLs. */
1646 if ((argp->flags & NFSMNT_NFSV4) != 0 && nfsrv_useacl != 0 &&
1648 NFSISSET_ATTRBIT(&nfsva.na_suppattr, NFSATTRBIT_ACL)) {
1650 mp->mnt_flag |= MNT_NFS4ACLS;
1655 * Lose the lock but keep the ref.
1658 vfs_cache_root_set(mp, *vpp);
1665 nfscl_clientrelease(clp);
1666 newnfs_disconnect(&nmp->nm_sockreq);
1667 crfree(nmp->nm_sockreq.nr_cred);
1668 if (nmp->nm_sockreq.nr_auth != NULL)
1669 AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
1670 mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1671 mtx_destroy(&nmp->nm_mtx);
1672 if (nmp->nm_clp != NULL) {
1674 LIST_REMOVE(nmp->nm_clp, nfsc_list);
1676 free(nmp->nm_clp, M_NFSCLCLIENT);
1678 TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp) {
1679 if (dsp != TAILQ_FIRST(&nmp->nm_sess) &&
1680 dsp->nfsclds_sockp != NULL)
1681 newnfs_disconnect(dsp->nfsclds_sockp);
1682 nfscl_freenfsclds(dsp);
1684 free(nmp, M_NEWNFSMNT);
1685 free(nam, M_SONAME);
1690 * unmount system call
1693 nfs_unmount(struct mount *mp, int mntflags)
1696 struct nfsmount *nmp;
1697 int error, flags = 0, i, trycnt = 0;
1698 struct nfsclds *dsp, *tdsp;
1702 if (mntflags & MNT_FORCE)
1703 flags |= FORCECLOSE;
1707 * Goes something like this..
1708 * - Call vflush() to clear out vnodes for this filesystem
1709 * - Close the socket
1710 * - Free up the data structures
1712 /* In the forced case, cancel any outstanding requests. */
1713 if (mntflags & MNT_FORCE) {
1715 if (nfsv4_findmirror(nmp) != NULL)
1720 error = newnfs_nmcancelreqs(nmp);
1723 /* For a forced close, get rid of the renew thread now */
1724 nfscl_umount(nmp, td);
1726 /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
1728 error = vflush(mp, 1, flags, td);
1729 if ((mntflags & MNT_FORCE) && error != 0 && ++trycnt < 30)
1730 (void) nfs_catnap(PSOCK, error, "newndm");
1731 } while ((mntflags & MNT_FORCE) && error != 0 && trycnt < 30);
1736 * We are now committed to the unmount.
1738 if ((mntflags & MNT_FORCE) == 0)
1739 nfscl_umount(nmp, td);
1741 mtx_lock(&nmp->nm_mtx);
1742 nmp->nm_privflag |= NFSMNTP_FORCEDISM;
1743 mtx_unlock(&nmp->nm_mtx);
1745 /* Make sure no nfsiods are assigned to this mount. */
1747 for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
1748 if (ncl_iodmount[i] == nmp) {
1749 ncl_iodwant[i] = NFSIOD_AVAILABLE;
1750 ncl_iodmount[i] = NULL;
1755 * We can now set mnt_data to NULL and wait for
1756 * nfssvc(NFSSVC_FORCEDISM) to complete.
1758 mtx_lock(&mountlist_mtx);
1759 mtx_lock(&nmp->nm_mtx);
1760 mp->mnt_data = NULL;
1761 mtx_unlock(&mountlist_mtx);
1762 while ((nmp->nm_privflag & NFSMNTP_CANCELRPCS) != 0)
1763 msleep(nmp, &nmp->nm_mtx, PVFS, "nfsfdism", 0);
1764 mtx_unlock(&nmp->nm_mtx);
1766 newnfs_disconnect(&nmp->nm_sockreq);
1767 crfree(nmp->nm_sockreq.nr_cred);
1768 free(nmp->nm_nam, M_SONAME);
1769 if (nmp->nm_sockreq.nr_auth != NULL)
1770 AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
1771 mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1772 mtx_destroy(&nmp->nm_mtx);
1773 TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp) {
1774 if (dsp != TAILQ_FIRST(&nmp->nm_sess) &&
1775 dsp->nfsclds_sockp != NULL)
1776 newnfs_disconnect(dsp->nfsclds_sockp);
1777 nfscl_freenfsclds(dsp);
1779 free(nmp, M_NEWNFSMNT);
1785 * Return root of a filesystem
1788 nfs_root(struct mount *mp, int flags, struct vnode **vpp)
1791 struct nfsmount *nmp;
1796 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, flags);
1801 * Get transfer parameters and attributes for root vnode once.
1803 mtx_lock(&nmp->nm_mtx);
1804 if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
1805 mtx_unlock(&nmp->nm_mtx);
1806 ncl_fsinfo(nmp, vp, curthread->td_ucred, curthread);
1808 mtx_unlock(&nmp->nm_mtx);
1809 if (vp->v_type == VNON)
1811 vp->v_vflag |= VV_ROOT;
1817 * Flush out the buffer cache
1821 nfs_sync(struct mount *mp, int waitfor)
1823 struct vnode *vp, *mvp;
1825 int error, allerror = 0;
1831 * If a forced dismount is in progress, return from here so that
1832 * the umount(2) syscall doesn't get stuck in VFS_SYNC() before
1833 * calling VFS_UNMOUNT().
1835 if (NFSCL_FORCEDISM(mp)) {
1842 * Force stale buffer cache information to be flushed.
1845 MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
1846 /* XXX Racy bv_cnt check. */
1847 if (NFSVOPISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
1848 waitfor == MNT_LAZY) {
1852 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK)) {
1853 MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
1856 error = VOP_FSYNC(vp, waitfor, td);
1866 nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
1868 struct nfsmount *nmp = VFSTONFS(mp);
1872 bzero(&vq, sizeof(vq));
1875 case VFS_CTL_NOLOCKS:
1876 val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
1877 if (req->oldptr != NULL) {
1878 error = SYSCTL_OUT(req, &val, sizeof(val));
1882 if (req->newptr != NULL) {
1883 error = SYSCTL_IN(req, &val, sizeof(val));
1887 nmp->nm_flag |= NFSMNT_NOLOCKS;
1889 nmp->nm_flag &= ~NFSMNT_NOLOCKS;
1894 mtx_lock(&nmp->nm_mtx);
1895 if (nmp->nm_state & NFSSTA_TIMEO)
1896 vq.vq_flags |= VQ_NOTRESP;
1897 mtx_unlock(&nmp->nm_mtx);
1899 if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
1900 (nmp->nm_state & NFSSTA_LOCKTIMEO))
1901 vq.vq_flags |= VQ_NOTRESPLOCK;
1903 error = SYSCTL_OUT(req, &vq, sizeof(vq));
1906 if (req->oldptr != NULL) {
1907 error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
1908 sizeof(nmp->nm_tprintf_initial_delay));
1912 if (req->newptr != NULL) {
1913 error = vfs_suser(mp, req->td);
1916 error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
1917 sizeof(nmp->nm_tprintf_initial_delay));
1920 if (nmp->nm_tprintf_initial_delay < 0)
1921 nmp->nm_tprintf_initial_delay = 0;
1931 * Purge any RPCs in progress, so that they will all return errors.
1932 * This allows dounmount() to continue as far as VFS_UNMOUNT() for a
1936 nfs_purge(struct mount *mp)
1938 struct nfsmount *nmp = VFSTONFS(mp);
1940 newnfs_nmcancelreqs(nmp);
1944 * Extract the information needed by the nlm from the nfs vnode.
1947 nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp,
1948 struct sockaddr_storage *sp, int *is_v3p, off_t *sizep,
1949 struct timeval *timeop)
1951 struct nfsmount *nmp;
1952 struct nfsnode *np = VTONFS(vp);
1954 nmp = VFSTONFS(vp->v_mount);
1956 *fhlenp = (size_t)np->n_fhp->nfh_len;
1958 bcopy(np->n_fhp->nfh_fh, fhp, np->n_fhp->nfh_len);
1960 bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp)));
1962 *is_v3p = NFS_ISV3(vp);
1964 *sizep = np->n_size;
1965 if (timeop != NULL) {
1966 timeop->tv_sec = nmp->nm_timeo / NFS_HZ;
1967 timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ);
1972 * This function prints out an option name, based on the conditional
1975 static __inline void nfscl_printopt(struct nfsmount *nmp, int testval,
1976 char *opt, char **buf, size_t *blen)
1980 if (testval != 0 && *blen > strlen(opt)) {
1981 len = snprintf(*buf, *blen, "%s", opt);
1982 if (len != strlen(opt))
1990 * This function printf out an options integer value.
1992 static __inline void nfscl_printoptval(struct nfsmount *nmp, int optval,
1993 char *opt, char **buf, size_t *blen)
1997 if (*blen > strlen(opt) + 1) {
1998 /* Could result in truncated output string. */
1999 len = snprintf(*buf, *blen, "%s=%d", opt, optval);
2008 * Load the option flags and values into the buffer.
2010 void nfscl_retopts(struct nfsmount *nmp, char *buffer, size_t buflen)
2017 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV4) != 0, "nfsv4", &buf,
2019 if ((nmp->nm_flag & NFSMNT_NFSV4) != 0) {
2020 nfscl_printoptval(nmp, nmp->nm_minorvers, ",minorversion", &buf,
2022 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_PNFS) != 0, ",pnfs",
2024 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_ONEOPENOWN) != 0 &&
2025 nmp->nm_minorvers > 0, ",oneopenown", &buf, &blen);
2027 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV3) != 0, "nfsv3", &buf,
2029 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0,
2030 "nfsv2", &buf, &blen);
2031 nfscl_printopt(nmp, nmp->nm_sotype == SOCK_STREAM, ",tcp", &buf, &blen);
2032 nfscl_printopt(nmp, nmp->nm_sotype != SOCK_STREAM, ",udp", &buf, &blen);
2033 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RESVPORT) != 0, ",resvport",
2035 nfscl_printopt(nmp, (nmp->nm_newflag & NFSMNT_TLS) != 0, ",tls", &buf,
2037 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCONN) != 0, ",noconn",
2039 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) == 0, ",hard", &buf,
2041 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) != 0, ",soft", &buf,
2043 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_INT) != 0, ",intr", &buf,
2045 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) == 0, ",cto", &buf,
2047 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) != 0, ",nocto", &buf,
2049 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NONCONTIGWR) != 0,
2050 ",noncontigwr", &buf, &blen);
2051 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
2052 0, ",lockd", &buf, &blen);
2053 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
2054 NFSMNT_NOLOCKD, ",nolockd", &buf, &blen);
2055 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RDIRPLUS) != 0, ",rdirplus",
2057 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_KERB) == 0, ",sec=sys",
2059 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
2060 NFSMNT_PRIVACY)) == NFSMNT_KERB, ",sec=krb5", &buf, &blen);
2061 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
2062 NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_INTEGRITY), ",sec=krb5i",
2064 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
2065 NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_PRIVACY), ",sec=krb5p",
2067 nfscl_printoptval(nmp, nmp->nm_acdirmin, ",acdirmin", &buf, &blen);
2068 nfscl_printoptval(nmp, nmp->nm_acdirmax, ",acdirmax", &buf, &blen);
2069 nfscl_printoptval(nmp, nmp->nm_acregmin, ",acregmin", &buf, &blen);
2070 nfscl_printoptval(nmp, nmp->nm_acregmax, ",acregmax", &buf, &blen);
2071 nfscl_printoptval(nmp, nmp->nm_nametimeo, ",nametimeo", &buf, &blen);
2072 nfscl_printoptval(nmp, nmp->nm_negnametimeo, ",negnametimeo", &buf,
2074 nfscl_printoptval(nmp, nmp->nm_rsize, ",rsize", &buf, &blen);
2075 nfscl_printoptval(nmp, nmp->nm_wsize, ",wsize", &buf, &blen);
2076 nfscl_printoptval(nmp, nmp->nm_readdirsize, ",readdirsize", &buf,
2078 nfscl_printoptval(nmp, nmp->nm_readahead, ",readahead", &buf, &blen);
2079 nfscl_printoptval(nmp, nmp->nm_wcommitsize, ",wcommitsize", &buf,
2081 nfscl_printoptval(nmp, nmp->nm_timeo, ",timeout", &buf, &blen);
2082 nfscl_printoptval(nmp, nmp->nm_retry, ",retrans", &buf, &blen);