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"
43 #include "opt_kern_tls.h"
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
50 #include <sys/clock.h>
52 #include <sys/limits.h>
54 #include <sys/malloc.h>
56 #include <sys/module.h>
57 #include <sys/mount.h>
59 #include <sys/socket.h>
60 #include <sys/socketvar.h>
61 #include <sys/sockio.h>
62 #include <sys/sysctl.h>
63 #include <sys/vnode.h>
64 #include <sys/signalvar.h>
67 #include <vm/vm_extern.h>
71 #include <net/route.h>
72 #include <net/route/route_ctl.h>
73 #include <netinet/in.h>
75 #include <fs/nfs/nfsport.h>
76 #include <fs/nfsclient/nfsnode.h>
77 #include <fs/nfsclient/nfsmount.h>
78 #include <fs/nfsclient/nfs.h>
79 #include <nfs/nfsdiskless.h>
81 #include <rpc/rpcsec_tls.h>
83 FEATURE(nfscl, "NFSv4 client");
85 extern int nfscl_ticks;
86 extern struct timeval nfsboottime;
87 extern int nfsrv_useacl;
88 extern int nfscl_debuglevel;
89 extern enum nfsiod_state ncl_iodwant[NFS_MAXASYNCDAEMON];
90 extern struct nfsmount *ncl_iodmount[NFS_MAXASYNCDAEMON];
91 extern struct mtx ncl_iod_mutex;
93 extern struct mtx nfsrv_dslock_mtx;
95 MALLOC_DEFINE(M_NEWNFSREQ, "newnfsclient_req", "NFS request header");
96 MALLOC_DEFINE(M_NEWNFSMNT, "newnfsmnt", "NFS mount struct");
98 SYSCTL_DECL(_vfs_nfs);
99 static int nfs_ip_paranoia = 1;
100 SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW,
101 &nfs_ip_paranoia, 0, "");
102 static int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
103 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_INITIAL_DELAY,
104 downdelayinitial, CTLFLAG_RW, &nfs_tprintf_initial_delay, 0, "");
105 /* how long between console messages "nfs server foo not responding" */
106 static int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
107 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_DELAY,
108 downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0, "");
111 SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0,
112 "Toggle debug flag");
115 static int nfs_mountroot(struct mount *);
116 static void nfs_sec_name(char *, int *);
117 static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp,
118 struct nfs_args *argp, const char *, struct ucred *,
120 static int mountnfs(struct nfs_args *, struct mount *,
121 struct sockaddr *, char *, u_char *, int, u_char *, int,
122 u_char *, int, struct vnode **, struct ucred *,
123 struct thread *, int, int, int, uint32_t);
124 static void nfs_getnlminfo(struct vnode *, uint8_t *, size_t *,
125 struct sockaddr_storage *, int *, off_t *,
127 static vfs_mount_t nfs_mount;
128 static vfs_cmount_t nfs_cmount;
129 static vfs_unmount_t nfs_unmount;
130 static vfs_root_t nfs_root;
131 static vfs_statfs_t nfs_statfs;
132 static vfs_sync_t nfs_sync;
133 static vfs_sysctl_t nfs_sysctl;
134 static vfs_purge_t nfs_purge;
137 * nfs vfs operations.
139 static struct vfsops nfs_vfsops = {
140 .vfs_init = ncl_init,
141 .vfs_mount = nfs_mount,
142 .vfs_cmount = nfs_cmount,
143 .vfs_root = vfs_cache_root,
144 .vfs_cachedroot = nfs_root,
145 .vfs_statfs = nfs_statfs,
146 .vfs_sync = nfs_sync,
147 .vfs_uninit = ncl_uninit,
148 .vfs_unmount = nfs_unmount,
149 .vfs_sysctl = nfs_sysctl,
150 .vfs_purge = nfs_purge,
152 VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK | VFCF_SBDRY);
154 /* So that loader and kldload(2) can find us, wherever we are.. */
155 MODULE_VERSION(nfs, 1);
156 MODULE_DEPEND(nfs, nfscommon, 1, 1, 1);
157 MODULE_DEPEND(nfs, krpc, 1, 1, 1);
158 MODULE_DEPEND(nfs, nfssvc, 1, 1, 1);
161 * This structure is now defined in sys/nfs/nfs_diskless.c so that it
162 * can be shared by both NFS clients. It is declared here so that it
163 * will be defined for kernels built without NFS_ROOT, although it
164 * isn't used in that case.
166 #if !defined(NFS_ROOT)
167 struct nfs_diskless nfs_diskless = { { { 0 } } };
168 struct nfsv3_diskless nfsv3_diskless = { { { 0 } } };
169 int nfs_diskless_valid = 0;
172 SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
173 &nfs_diskless_valid, 0,
174 "Has the diskless struct been filled correctly");
176 SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
177 nfsv3_diskless.root_hostnam, 0, "Path to nfs root");
179 SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
180 &nfsv3_diskless.root_saddr, sizeof(nfsv3_diskless.root_saddr),
181 "%Ssockaddr_in", "Diskless root nfs address");
184 void newnfsargs_ntoh(struct nfs_args *);
185 static int nfs_mountdiskless(char *,
186 struct sockaddr_in *, struct nfs_args *,
187 struct thread *, struct vnode **, struct mount *);
188 static void nfs_convert_diskless(void);
189 static void nfs_convert_oargs(struct nfs_args *args,
190 struct onfs_args *oargs);
193 newnfs_iosize(struct nfsmount *nmp)
197 /* First, set the upper limit for iosize */
198 if (nmp->nm_flag & NFSMNT_NFSV4) {
199 maxio = NFS_MAXBSIZE;
200 } else if (nmp->nm_flag & NFSMNT_NFSV3) {
201 if (nmp->nm_sotype == SOCK_DGRAM)
202 maxio = NFS_MAXDGRAMDATA;
204 maxio = NFS_MAXBSIZE;
206 maxio = NFS_V2MAXDATA;
208 if (nmp->nm_rsize > maxio || nmp->nm_rsize == 0)
209 nmp->nm_rsize = maxio;
210 if (nmp->nm_rsize > NFS_MAXBSIZE)
211 nmp->nm_rsize = NFS_MAXBSIZE;
212 if (nmp->nm_readdirsize > maxio || nmp->nm_readdirsize == 0)
213 nmp->nm_readdirsize = maxio;
214 if (nmp->nm_readdirsize > nmp->nm_rsize)
215 nmp->nm_readdirsize = nmp->nm_rsize;
216 if (nmp->nm_wsize > maxio || nmp->nm_wsize == 0)
217 nmp->nm_wsize = maxio;
218 if (nmp->nm_wsize > NFS_MAXBSIZE)
219 nmp->nm_wsize = NFS_MAXBSIZE;
222 * Calculate the size used for io buffers. Use the larger
223 * of the two sizes to minimise nfs requests but make sure
224 * that it is at least one VM page to avoid wasting buffer
225 * space. It must also be at least NFS_DIRBLKSIZ, since
226 * that is the buffer size used for directories.
228 iosize = imax(nmp->nm_rsize, nmp->nm_wsize);
229 iosize = imax(iosize, PAGE_SIZE);
230 iosize = imax(iosize, NFS_DIRBLKSIZ);
231 nmp->nm_mountp->mnt_stat.f_iosize = iosize;
236 nfs_convert_oargs(struct nfs_args *args, struct onfs_args *oargs)
239 args->version = NFS_ARGSVERSION;
240 args->addr = oargs->addr;
241 args->addrlen = oargs->addrlen;
242 args->sotype = oargs->sotype;
243 args->proto = oargs->proto;
244 args->fh = oargs->fh;
245 args->fhsize = oargs->fhsize;
246 args->flags = oargs->flags;
247 args->wsize = oargs->wsize;
248 args->rsize = oargs->rsize;
249 args->readdirsize = oargs->readdirsize;
250 args->timeo = oargs->timeo;
251 args->retrans = oargs->retrans;
252 args->readahead = oargs->readahead;
253 args->hostname = oargs->hostname;
257 nfs_convert_diskless(void)
260 bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
261 sizeof(struct ifaliasreq));
262 bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
263 sizeof(struct sockaddr_in));
264 nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
265 if (nfsv3_diskless.root_args.flags & NFSMNT_NFSV3) {
266 nfsv3_diskless.root_fhsize = NFSX_MYFH;
267 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_MYFH);
269 nfsv3_diskless.root_fhsize = NFSX_V2FH;
270 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
272 bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
273 sizeof(struct sockaddr_in));
274 bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN);
275 nfsv3_diskless.root_time = nfs_diskless.root_time;
276 bcopy(nfs_diskless.my_hostnam, nfsv3_diskless.my_hostnam,
278 nfs_diskless_valid = 3;
285 nfs_statfs(struct mount *mp, struct statfs *sbp)
289 struct nfsmount *nmp = VFSTONFS(mp);
290 struct nfsvattr nfsva;
293 int error = 0, attrflag, gotfsinfo = 0, ret;
298 error = vfs_busy(mp, MBF_NOWAIT);
301 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
307 mtx_lock(&nmp->nm_mtx);
308 if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
309 mtx_unlock(&nmp->nm_mtx);
310 error = nfsrpc_fsinfo(vp, &fs, td->td_ucred, td, &nfsva,
315 mtx_unlock(&nmp->nm_mtx);
317 error = nfsrpc_statfs(vp, &sb, &fs, td->td_ucred, td, &nfsva,
320 NFSCL_DEBUG(2, "statfs=%d\n", error);
322 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
323 td->td_ucred, td, &nfsva, NULL, NULL);
326 * Just set default values to get things going.
328 NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
329 nfsva.na_vattr.va_type = VDIR;
330 nfsva.na_vattr.va_mode = 0777;
331 nfsva.na_vattr.va_nlink = 100;
332 nfsva.na_vattr.va_uid = (uid_t)0;
333 nfsva.na_vattr.va_gid = (gid_t)0;
334 nfsva.na_vattr.va_fileid = 2;
335 nfsva.na_vattr.va_gen = 1;
336 nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
337 nfsva.na_vattr.va_size = 512 * 1024;
340 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
342 mtx_lock(&nmp->nm_mtx);
343 if (gotfsinfo || (nmp->nm_flag & NFSMNT_NFSV4))
344 nfscl_loadfsinfo(nmp, &fs);
345 nfscl_loadsbinfo(nmp, &sb, sbp);
346 sbp->f_iosize = newnfs_iosize(nmp);
347 mtx_unlock(&nmp->nm_mtx);
348 if (sbp != &mp->mnt_stat) {
349 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
350 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
352 strncpy(&sbp->f_fstypename[0], mp->mnt_vfc->vfc_name, MFSNAMELEN);
353 } else if (NFS_ISV4(vp)) {
354 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
362 * nfs version 3 fsinfo rpc call
365 ncl_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred,
369 struct nfsvattr nfsva;
372 error = nfsrpc_fsinfo(vp, &fs, cred, td, &nfsva, &attrflag, NULL);
375 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0,
377 mtx_lock(&nmp->nm_mtx);
378 nfscl_loadfsinfo(nmp, &fs);
379 mtx_unlock(&nmp->nm_mtx);
385 * Mount a remote root fs via. nfs. This depends on the info in the
386 * nfs_diskless structure that has been filled in properly by some primary
388 * It goes something like this:
389 * - do enough of "ifconfig" by calling ifioctl() so that the system
390 * can talk to the server
391 * - If nfs_diskless.mygateway is filled in, use that address as
393 * - build the rootfs mount point and call mountnfs() to do the rest.
395 * It is assumed to be safe to read, modify, and write the nfsv3_diskless
396 * structure, as well as other global NFS client variables here, as
397 * nfs_mountroot() will be called once in the boot before any other NFS
398 * client activity occurs.
401 nfs_mountroot(struct mount *mp)
403 struct thread *td = curthread;
404 struct nfsv3_diskless *nd = &nfsv3_diskless;
413 #if defined(BOOTP_NFSROOT) && defined(BOOTP)
414 bootpc_init(); /* use bootp to get nfs_diskless filled in */
415 #elif defined(NFS_ROOT)
416 nfs_setup_diskless();
419 if (nfs_diskless_valid == 0)
421 if (nfs_diskless_valid == 1)
422 nfs_convert_diskless();
425 * Do enough of ifconfig(8) so that the critical net interface can
426 * talk to the server.
428 error = socreate(nd->myif.ifra_addr.sa_family, &so, nd->root_args.sotype, 0,
431 panic("nfs_mountroot: socreate(%04x): %d",
432 nd->myif.ifra_addr.sa_family, error);
434 #if 0 /* XXX Bad idea */
436 * We might not have been told the right interface, so we pass
437 * over the first ten interfaces of the same kind, until we get
438 * one of them configured.
441 for (i = strlen(nd->myif.ifra_name) - 1;
442 nd->myif.ifra_name[i] >= '0' &&
443 nd->myif.ifra_name[i] <= '9';
444 nd->myif.ifra_name[i] ++) {
445 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
450 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
452 panic("nfs_mountroot: SIOCAIFADDR: %d", error);
453 if ((cp = kern_getenv("boot.netif.mtu")) != NULL) {
454 ir.ifr_mtu = strtol(cp, NULL, 10);
455 bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ);
457 error = ifioctl(so, SIOCSIFMTU, (caddr_t)&ir, td);
459 printf("nfs_mountroot: SIOCSIFMTU: %d", error);
464 * If the gateway field is filled in, set it as the default route.
465 * Note that pxeboot will set a default route of 0 if the route
466 * is not set by the DHCP server. Check also for a value of 0
467 * to avoid panicking inappropriately in that situation.
469 if (nd->mygateway.sin_len != 0 &&
470 nd->mygateway.sin_addr.s_addr != 0) {
471 struct sockaddr_in mask, sin;
472 struct epoch_tracker et;
473 struct rt_addrinfo info;
474 struct rib_cmd_info rc;
476 bzero((caddr_t)&mask, sizeof(mask));
478 sin.sin_family = AF_INET;
479 sin.sin_len = sizeof(sin);
480 /* XXX MRT use table 0 for this sort of thing */
482 CURVNET_SET(TD_TO_VNET(td));
484 bzero((caddr_t)&info, sizeof(info));
485 info.rti_flags = RTF_UP | RTF_GATEWAY;
486 info.rti_info[RTAX_DST] = (struct sockaddr *)&sin;
487 info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&nd->mygateway;
488 info.rti_info[RTAX_NETMASK] = (struct sockaddr *)&mask;
490 error = rib_action(RT_DEFAULT_FIB, RTM_ADD, &info, &rc);
494 panic("nfs_mountroot: RTM_ADD: %d", error);
498 * Create the rootfs mount point.
500 nd->root_args.fh = nd->root_fh;
501 nd->root_args.fhsize = nd->root_fhsize;
502 l = ntohl(nd->root_saddr.sin_addr.s_addr);
503 snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
504 (l >> 24) & 0xff, (l >> 16) & 0xff,
505 (l >> 8) & 0xff, (l >> 0) & 0xff, nd->root_hostnam);
506 printf("NFS ROOT: %s\n", buf);
507 nd->root_args.hostname = buf;
508 if ((error = nfs_mountdiskless(buf,
509 &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) {
514 * This is not really an nfs issue, but it is much easier to
515 * set hostname here and then let the "/etc/rc.xxx" files
516 * mount the right /var based upon its preset value.
518 mtx_lock(&prison0.pr_mtx);
519 strlcpy(prison0.pr_hostname, nd->my_hostnam,
520 sizeof(prison0.pr_hostname));
521 mtx_unlock(&prison0.pr_mtx);
522 inittodr(ntohl(nd->root_time));
527 * Internal version of mount system call for diskless setup.
530 nfs_mountdiskless(char *path,
531 struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
532 struct vnode **vpp, struct mount *mp)
534 struct sockaddr *nam;
539 * Find the directory path in "path", which also has the server's
540 * name/ip address in it.
542 dirpath = strchr(path, ':');
544 dirlen = strlen(++dirpath);
547 nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
548 if ((error = mountnfs(args, mp, nam, path, NULL, 0, dirpath, dirlen,
549 NULL, 0, vpp, td->td_ucred, td, NFS_DEFAULT_NAMETIMEO,
550 NFS_DEFAULT_NEGNAMETIMEO, 0, 0)) != 0) {
551 printf("nfs_mountroot: mount %s on /: %d\n", path, error);
558 nfs_sec_name(char *sec, int *flagsp)
560 if (!strcmp(sec, "krb5"))
561 *flagsp |= NFSMNT_KERB;
562 else if (!strcmp(sec, "krb5i"))
563 *flagsp |= (NFSMNT_KERB | NFSMNT_INTEGRITY);
564 else if (!strcmp(sec, "krb5p"))
565 *flagsp |= (NFSMNT_KERB | NFSMNT_PRIVACY);
569 nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
570 const char *hostname, struct ucred *cred, struct thread *td)
576 * Set read-only flag if requested; otherwise, clear it if this is
577 * an update. If this is not an update, then either the read-only
578 * flag is already clear, or this is a root mount and it was set
579 * intentionally at some previous point.
581 if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) {
583 mp->mnt_flag |= MNT_RDONLY;
585 } else if (mp->mnt_flag & MNT_UPDATE) {
587 mp->mnt_flag &= ~MNT_RDONLY;
592 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
593 * no sense in that context. Also, set up appropriate retransmit
594 * and soft timeout behavior.
596 if (argp->sotype == SOCK_STREAM) {
597 nmp->nm_flag &= ~NFSMNT_NOCONN;
598 nmp->nm_timeo = NFS_MAXTIMEO;
599 if ((argp->flags & NFSMNT_NFSV4) != 0)
600 nmp->nm_retry = INT_MAX;
602 nmp->nm_retry = NFS_RETRANS_TCP;
605 /* Also clear RDIRPLUS if NFSv2, it crashes some servers */
606 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
607 argp->flags &= ~NFSMNT_RDIRPLUS;
608 nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
611 /* Clear ONEOPENOWN for NFSv2, 3 and 4.0. */
612 if (nmp->nm_minorvers == 0) {
613 argp->flags &= ~NFSMNT_ONEOPENOWN;
614 nmp->nm_flag &= ~NFSMNT_ONEOPENOWN;
617 /* Re-bind if rsrvd port requested and wasn't on one */
618 adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
619 && (argp->flags & NFSMNT_RESVPORT);
620 /* Also re-bind if we're switching to/from a connected UDP socket */
621 adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
622 (argp->flags & NFSMNT_NOCONN));
624 /* Update flags atomically. Don't change the lock bits. */
625 nmp->nm_flag = argp->flags | nmp->nm_flag;
627 if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
628 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
629 if (nmp->nm_timeo < NFS_MINTIMEO)
630 nmp->nm_timeo = NFS_MINTIMEO;
631 else if (nmp->nm_timeo > NFS_MAXTIMEO)
632 nmp->nm_timeo = NFS_MAXTIMEO;
635 if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
636 nmp->nm_retry = argp->retrans;
637 if (nmp->nm_retry > NFS_MAXREXMIT)
638 nmp->nm_retry = NFS_MAXREXMIT;
641 if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
642 nmp->nm_wsize = argp->wsize;
644 * Clip at the power of 2 below the size. There is an
645 * issue (not isolated) that causes intermittent page
646 * faults if this is not done.
648 if (nmp->nm_wsize > NFS_FABLKSIZE)
649 nmp->nm_wsize = 1 << (fls(nmp->nm_wsize) - 1);
651 nmp->nm_wsize = NFS_FABLKSIZE;
654 if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
655 nmp->nm_rsize = argp->rsize;
657 * Clip at the power of 2 below the size. There is an
658 * issue (not isolated) that causes intermittent page
659 * faults if this is not done.
661 if (nmp->nm_rsize > NFS_FABLKSIZE)
662 nmp->nm_rsize = 1 << (fls(nmp->nm_rsize) - 1);
664 nmp->nm_rsize = NFS_FABLKSIZE;
667 if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
668 nmp->nm_readdirsize = argp->readdirsize;
671 if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
672 nmp->nm_acregmin = argp->acregmin;
674 nmp->nm_acregmin = NFS_MINATTRTIMO;
675 if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
676 nmp->nm_acregmax = argp->acregmax;
678 nmp->nm_acregmax = NFS_MAXATTRTIMO;
679 if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
680 nmp->nm_acdirmin = argp->acdirmin;
682 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
683 if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
684 nmp->nm_acdirmax = argp->acdirmax;
686 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
687 if (nmp->nm_acdirmin > nmp->nm_acdirmax)
688 nmp->nm_acdirmin = nmp->nm_acdirmax;
689 if (nmp->nm_acregmin > nmp->nm_acregmax)
690 nmp->nm_acregmin = nmp->nm_acregmax;
692 if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
693 if (argp->readahead <= NFS_MAXRAHEAD)
694 nmp->nm_readahead = argp->readahead;
696 nmp->nm_readahead = NFS_MAXRAHEAD;
698 if ((argp->flags & NFSMNT_WCOMMITSIZE) && argp->wcommitsize >= 0) {
699 if (argp->wcommitsize < nmp->nm_wsize)
700 nmp->nm_wcommitsize = nmp->nm_wsize;
702 nmp->nm_wcommitsize = argp->wcommitsize;
705 adjsock |= ((nmp->nm_sotype != argp->sotype) ||
706 (nmp->nm_soproto != argp->proto));
708 if (nmp->nm_client != NULL && adjsock) {
709 int haslock = 0, error = 0;
711 if (nmp->nm_sotype == SOCK_STREAM) {
712 error = newnfs_sndlock(&nmp->nm_sockreq.nr_lock);
717 newnfs_disconnect(&nmp->nm_sockreq);
719 newnfs_sndunlock(&nmp->nm_sockreq.nr_lock);
720 nmp->nm_sotype = argp->sotype;
721 nmp->nm_soproto = argp->proto;
722 if (nmp->nm_sotype == SOCK_DGRAM)
723 while (newnfs_connect(nmp, &nmp->nm_sockreq,
724 cred, td, 0, false)) {
725 printf("newnfs_args: retrying connect\n");
726 (void) nfs_catnap(PSOCK, 0, "nfscon");
730 nmp->nm_sotype = argp->sotype;
731 nmp->nm_soproto = argp->proto;
734 if (hostname != NULL) {
735 strlcpy(nmp->nm_hostname, hostname,
736 sizeof(nmp->nm_hostname));
737 p = strchr(nmp->nm_hostname, ':');
743 static const char *nfs_opts[] = { "from", "nfs_args",
744 "noac", "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
745 "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
746 "async", "noconn", "nolockd", "conn", "lockd", "intr", "rdirplus",
747 "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize",
748 "retrans", "actimeo", "acregmin", "acregmax", "acdirmin", "acdirmax",
749 "resvport", "readahead", "hostname", "timeo", "timeout", "addr", "fh",
750 "nfsv3", "sec", "principal", "nfsv4", "gssname", "allgssname", "dirpath",
751 "minorversion", "nametimeo", "negnametimeo", "nocto", "noncontigwr",
752 "pnfs", "wcommitsize", "oneopenown", "tls",
756 * Parse the "from" mountarg, passed by the generic mount(8) program
757 * or the mountroot code. This is used when rerooting into NFS.
759 * Note that the "hostname" is actually a "hostname:/share/path" string.
762 nfs_mount_parse_from(struct vfsoptlist *opts, char **hostnamep,
763 struct sockaddr_in **sinp, char *dirpath, size_t dirpathsize, int *dirlenp)
765 char *nam, *delimp, *hostp, *spec;
766 int error, have_bracket = 0, offset, rv, speclen;
767 struct sockaddr_in *sin;
770 error = vfs_getopt(opts, "from", (void **)&spec, &speclen);
773 nam = malloc(MNAMELEN + 1, M_TEMP, M_WAITOK);
776 * This part comes from sbin/mount_nfs/mount_nfs.c:getnfsargs().
778 if (*spec == '[' && (delimp = strchr(spec + 1, ']')) != NULL &&
779 *(delimp + 1) == ':') {
783 } else if ((delimp = strrchr(spec, ':')) != NULL) {
786 } else if ((delimp = strrchr(spec, '@')) != NULL) {
787 printf("%s: path@server syntax is deprecated, "
788 "use server:path\n", __func__);
791 printf("%s: no <host>:<dirpath> nfs-name\n", __func__);
798 * If there has been a trailing slash at mounttime it seems
799 * that some mountd implementations fail to remove the mount
800 * entries from their mountlist while unmounting.
802 for (speclen = strlen(spec);
803 speclen > 1 && spec[speclen - 1] == '/';
805 spec[speclen - 1] = '\0';
806 if (strlen(hostp) + strlen(spec) + 1 > MNAMELEN) {
807 printf("%s: %s:%s: name too long", __func__, hostp, spec);
811 /* Make both '@' and ':' notations equal */
812 if (*hostp != '\0') {
817 memmove(nam + offset, hostp, len);
819 nam[len + offset++] = ']';
820 nam[len + offset++] = ':';
821 memmove(nam + len + offset, spec, speclen);
822 nam[len + speclen + offset] = '\0';
829 sin = malloc(sizeof(*sin), M_SONAME, M_WAITOK);
830 rv = inet_pton(AF_INET, hostp, &sin->sin_addr);
832 printf("%s: cannot parse '%s', inet_pton() returned %d\n",
833 __func__, hostp, rv);
839 sin->sin_len = sizeof(*sin);
840 sin->sin_family = AF_INET;
842 * XXX: hardcoded port number.
844 sin->sin_port = htons(2049);
846 *hostnamep = strdup(nam, M_NEWNFSMNT);
848 strlcpy(dirpath, spec, dirpathsize);
849 *dirlenp = strlen(dirpath);
859 * It seems a bit dumb to copyinstr() the host and path here and then
860 * bcopy() them in mountnfs(), but I wanted to detect errors before
861 * doing the getsockaddr() call because getsockaddr() allocates an mbuf and
862 * an error after that means that I have to release the mbuf.
866 nfs_mount(struct mount *mp)
868 struct nfs_args args = {
869 .version = NFS_ARGSVERSION,
871 .addrlen = sizeof (struct sockaddr_in),
872 .sotype = SOCK_STREAM,
876 .flags = NFSMNT_RESVPORT,
879 .readdirsize = NFS_READDIRSIZE,
881 .retrans = NFS_RETRANS,
882 .readahead = NFS_DEFRAHEAD,
883 .wcommitsize = 0, /* was: NQ_DEFLEASE */
885 .acregmin = NFS_MINATTRTIMO,
886 .acregmax = NFS_MAXATTRTIMO,
887 .acdirmin = NFS_MINDIRATTRTIMO,
888 .acdirmax = NFS_MAXDIRATTRTIMO,
890 int error = 0, ret, len;
891 struct sockaddr *nam = NULL;
895 u_char nfh[NFSX_FHMAX], krbname[100], dirpath[100], srvkrbname[100];
896 char *cp, *opt, *name, *secname;
897 int nametimeo = NFS_DEFAULT_NAMETIMEO;
898 int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
900 int dirlen, has_nfs_args_opt, has_nfs_from_opt,
901 krbnamelen, srvkrbnamelen;
905 has_nfs_args_opt = 0;
906 has_nfs_from_opt = 0;
908 hst = malloc(MNAMELEN, M_TEMP, M_WAITOK);
909 if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
915 if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS &&
916 nfs_diskless_valid != 0) {
917 error = nfs_mountroot(mp);
924 * The old mount_nfs program passed the struct nfs_args
925 * from userspace to kernel. The new mount_nfs program
926 * passes string options via nmount() from userspace to kernel
927 * and we populate the struct nfs_args in the kernel.
929 if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
930 error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
935 if (args.version != NFS_ARGSVERSION) {
936 error = EPROGMISMATCH;
939 has_nfs_args_opt = 1;
942 /* Handle the new style options. */
943 if (vfs_getopt(mp->mnt_optnew, "noac", NULL, NULL) == 0) {
944 args.acdirmin = args.acdirmax =
945 args.acregmin = args.acregmax = 0;
946 args.flags |= NFSMNT_ACDIRMIN | NFSMNT_ACDIRMAX |
947 NFSMNT_ACREGMIN | NFSMNT_ACREGMAX;
949 if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
950 args.flags |= NFSMNT_NOCONN;
951 if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
952 args.flags &= ~NFSMNT_NOCONN;
953 if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
954 args.flags |= NFSMNT_NOLOCKD;
955 if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
956 args.flags &= ~NFSMNT_NOLOCKD;
957 if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
958 args.flags |= NFSMNT_INT;
959 if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
960 args.flags |= NFSMNT_RDIRPLUS;
961 if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
962 args.flags |= NFSMNT_RESVPORT;
963 if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
964 args.flags &= ~NFSMNT_RESVPORT;
965 if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
966 args.flags |= NFSMNT_SOFT;
967 if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
968 args.flags &= ~NFSMNT_SOFT;
969 if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
970 args.sotype = SOCK_DGRAM;
971 if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
972 args.sotype = SOCK_DGRAM;
973 if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
974 args.sotype = SOCK_STREAM;
975 if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
976 args.flags |= NFSMNT_NFSV3;
977 if (vfs_getopt(mp->mnt_optnew, "nfsv4", NULL, NULL) == 0) {
978 args.flags |= NFSMNT_NFSV4;
979 args.sotype = SOCK_STREAM;
981 if (vfs_getopt(mp->mnt_optnew, "allgssname", NULL, NULL) == 0)
982 args.flags |= NFSMNT_ALLGSSNAME;
983 if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0)
984 args.flags |= NFSMNT_NOCTO;
985 if (vfs_getopt(mp->mnt_optnew, "noncontigwr", NULL, NULL) == 0)
986 args.flags |= NFSMNT_NONCONTIGWR;
987 if (vfs_getopt(mp->mnt_optnew, "pnfs", NULL, NULL) == 0)
988 args.flags |= NFSMNT_PNFS;
989 if (vfs_getopt(mp->mnt_optnew, "oneopenown", NULL, NULL) == 0)
990 args.flags |= NFSMNT_ONEOPENOWN;
991 if (vfs_getopt(mp->mnt_optnew, "tls", NULL, NULL) == 0)
992 newflag |= NFSMNT_TLS;
993 if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
995 vfs_mount_error(mp, "illegal readdirsize");
999 ret = sscanf(opt, "%d", &args.readdirsize);
1000 if (ret != 1 || args.readdirsize <= 0) {
1001 vfs_mount_error(mp, "illegal readdirsize: %s",
1006 args.flags |= NFSMNT_READDIRSIZE;
1008 if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
1010 vfs_mount_error(mp, "illegal readahead");
1014 ret = sscanf(opt, "%d", &args.readahead);
1015 if (ret != 1 || args.readahead <= 0) {
1016 vfs_mount_error(mp, "illegal readahead: %s",
1021 args.flags |= NFSMNT_READAHEAD;
1023 if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
1025 vfs_mount_error(mp, "illegal wsize");
1029 ret = sscanf(opt, "%d", &args.wsize);
1030 if (ret != 1 || args.wsize <= 0) {
1031 vfs_mount_error(mp, "illegal wsize: %s",
1036 args.flags |= NFSMNT_WSIZE;
1038 if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
1040 vfs_mount_error(mp, "illegal rsize");
1044 ret = sscanf(opt, "%d", &args.rsize);
1045 if (ret != 1 || args.rsize <= 0) {
1046 vfs_mount_error(mp, "illegal wsize: %s",
1051 args.flags |= NFSMNT_RSIZE;
1053 if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
1055 vfs_mount_error(mp, "illegal retrans");
1059 ret = sscanf(opt, "%d", &args.retrans);
1060 if (ret != 1 || args.retrans <= 0) {
1061 vfs_mount_error(mp, "illegal retrans: %s",
1066 args.flags |= NFSMNT_RETRANS;
1068 if (vfs_getopt(mp->mnt_optnew, "actimeo", (void **)&opt, NULL) == 0) {
1069 ret = sscanf(opt, "%d", &args.acregmin);
1070 if (ret != 1 || args.acregmin < 0) {
1071 vfs_mount_error(mp, "illegal actimeo: %s",
1076 args.acdirmin = args.acdirmax = args.acregmax = args.acregmin;
1077 args.flags |= NFSMNT_ACDIRMIN | NFSMNT_ACDIRMAX |
1078 NFSMNT_ACREGMIN | NFSMNT_ACREGMAX;
1080 if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
1081 ret = sscanf(opt, "%d", &args.acregmin);
1082 if (ret != 1 || args.acregmin < 0) {
1083 vfs_mount_error(mp, "illegal acregmin: %s",
1088 args.flags |= NFSMNT_ACREGMIN;
1090 if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
1091 ret = sscanf(opt, "%d", &args.acregmax);
1092 if (ret != 1 || args.acregmax < 0) {
1093 vfs_mount_error(mp, "illegal acregmax: %s",
1098 args.flags |= NFSMNT_ACREGMAX;
1100 if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
1101 ret = sscanf(opt, "%d", &args.acdirmin);
1102 if (ret != 1 || args.acdirmin < 0) {
1103 vfs_mount_error(mp, "illegal acdirmin: %s",
1108 args.flags |= NFSMNT_ACDIRMIN;
1110 if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
1111 ret = sscanf(opt, "%d", &args.acdirmax);
1112 if (ret != 1 || args.acdirmax < 0) {
1113 vfs_mount_error(mp, "illegal acdirmax: %s",
1118 args.flags |= NFSMNT_ACDIRMAX;
1120 if (vfs_getopt(mp->mnt_optnew, "wcommitsize", (void **)&opt, NULL) == 0) {
1121 ret = sscanf(opt, "%d", &args.wcommitsize);
1122 if (ret != 1 || args.wcommitsize < 0) {
1123 vfs_mount_error(mp, "illegal wcommitsize: %s", opt);
1127 args.flags |= NFSMNT_WCOMMITSIZE;
1129 if (vfs_getopt(mp->mnt_optnew, "timeo", (void **)&opt, NULL) == 0) {
1130 ret = sscanf(opt, "%d", &args.timeo);
1131 if (ret != 1 || args.timeo <= 0) {
1132 vfs_mount_error(mp, "illegal timeo: %s",
1137 args.flags |= NFSMNT_TIMEO;
1139 if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
1140 ret = sscanf(opt, "%d", &args.timeo);
1141 if (ret != 1 || args.timeo <= 0) {
1142 vfs_mount_error(mp, "illegal timeout: %s",
1147 args.flags |= NFSMNT_TIMEO;
1149 if (vfs_getopt(mp->mnt_optnew, "nametimeo", (void **)&opt, NULL) == 0) {
1150 ret = sscanf(opt, "%d", &nametimeo);
1151 if (ret != 1 || nametimeo < 0) {
1152 vfs_mount_error(mp, "illegal nametimeo: %s", opt);
1157 if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
1159 ret = sscanf(opt, "%d", &negnametimeo);
1160 if (ret != 1 || negnametimeo < 0) {
1161 vfs_mount_error(mp, "illegal negnametimeo: %s",
1167 if (vfs_getopt(mp->mnt_optnew, "minorversion", (void **)&opt, NULL) ==
1169 ret = sscanf(opt, "%d", &minvers);
1170 if (ret != 1 || minvers < 0 || minvers > 2 ||
1171 (args.flags & NFSMNT_NFSV4) == 0) {
1172 vfs_mount_error(mp, "illegal minorversion: %s", opt);
1177 if (vfs_getopt(mp->mnt_optnew, "sec",
1178 (void **) &secname, NULL) == 0)
1179 nfs_sec_name(secname, &args.flags);
1181 if (mp->mnt_flag & MNT_UPDATE) {
1182 struct nfsmount *nmp = VFSTONFS(mp);
1190 * If a change from TCP->UDP is done and there are thread(s)
1191 * that have I/O RPC(s) in progress with a transfer size
1192 * greater than NFS_MAXDGRAMDATA, those thread(s) will be
1193 * hung, retrying the RPC(s) forever. Usually these threads
1194 * will be seen doing an uninterruptible sleep on wait channel
1197 if (args.sotype == SOCK_DGRAM && nmp->nm_sotype == SOCK_STREAM)
1198 tprintf(td->td_proc, LOG_WARNING,
1199 "Warning: mount -u that changes TCP->UDP can result in hung threads\n");
1202 * When doing an update, we can't change version,
1203 * security, switch lockd strategies, change cookie
1204 * translation or switch oneopenown.
1206 args.flags = (args.flags &
1213 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
1221 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
1222 nfs_decode_args(mp, nmp, &args, NULL, td->td_ucred, td);
1227 * Make the nfs_ip_paranoia sysctl serve as the default connection
1228 * or no-connection mode for those protocols that support
1229 * no-connection mode (the flag will be cleared later for protocols
1230 * that do not support no-connection mode). This will allow a client
1231 * to receive replies from a different IP then the request was
1232 * sent to. Note: default value for nfs_ip_paranoia is 1 (paranoid),
1235 if (nfs_ip_paranoia == 0)
1236 args.flags |= NFSMNT_NOCONN;
1238 if (has_nfs_args_opt != 0) {
1240 * In the 'nfs_args' case, the pointers in the args
1241 * structure are in userland - we copy them in here.
1243 if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
1244 vfs_mount_error(mp, "Bad file handle");
1248 error = copyin((caddr_t)args.fh, (caddr_t)nfh,
1252 error = copyinstr(args.hostname, hst, MNAMELEN - 1, &hstlen);
1255 bzero(&hst[hstlen], MNAMELEN - hstlen);
1256 args.hostname = hst;
1257 /* getsockaddr() call must be after above copyin() calls */
1258 error = getsockaddr(&nam, args.addr, args.addrlen);
1261 } else if (nfs_mount_parse_from(mp->mnt_optnew,
1262 &args.hostname, (struct sockaddr_in **)&nam, dirpath,
1263 sizeof(dirpath), &dirlen) == 0) {
1264 has_nfs_from_opt = 1;
1265 bcopy(args.hostname, hst, MNAMELEN);
1266 hst[MNAMELEN - 1] = '\0';
1269 * This only works with NFSv4 for now.
1272 args.flags |= NFSMNT_NFSV4;
1273 args.sotype = SOCK_STREAM;
1275 if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
1276 &args.fhsize) == 0) {
1277 if (args.fhsize < 0 || args.fhsize > NFSX_FHMAX) {
1278 vfs_mount_error(mp, "Bad file handle");
1282 bcopy(args.fh, nfh, args.fhsize);
1286 (void) vfs_getopt(mp->mnt_optnew, "hostname",
1287 (void **)&args.hostname, &len);
1288 if (args.hostname == NULL) {
1289 vfs_mount_error(mp, "Invalid hostname");
1293 if (len >= MNAMELEN) {
1294 vfs_mount_error(mp, "Hostname too long");
1298 bcopy(args.hostname, hst, len);
1302 if (vfs_getopt(mp->mnt_optnew, "principal", (void **)&name, NULL) == 0)
1303 strlcpy(srvkrbname, name, sizeof (srvkrbname));
1305 snprintf(srvkrbname, sizeof (srvkrbname), "nfs@%s", hst);
1306 cp = strchr(srvkrbname, ':');
1310 srvkrbnamelen = strlen(srvkrbname);
1312 if (vfs_getopt(mp->mnt_optnew, "gssname", (void **)&name, NULL) == 0)
1313 strlcpy(krbname, name, sizeof (krbname));
1316 krbnamelen = strlen(krbname);
1318 if (has_nfs_from_opt == 0) {
1319 if (vfs_getopt(mp->mnt_optnew,
1320 "dirpath", (void **)&name, NULL) == 0)
1321 strlcpy(dirpath, name, sizeof (dirpath));
1324 dirlen = strlen(dirpath);
1327 if (has_nfs_args_opt == 0 && has_nfs_from_opt == 0) {
1328 if (vfs_getopt(mp->mnt_optnew, "addr",
1329 (void **)&args.addr, &args.addrlen) == 0) {
1330 if (args.addrlen > SOCK_MAXADDRLEN) {
1331 error = ENAMETOOLONG;
1334 nam = malloc(args.addrlen, M_SONAME, M_WAITOK);
1335 bcopy(args.addr, nam, args.addrlen);
1336 nam->sa_len = args.addrlen;
1338 vfs_mount_error(mp, "No server address");
1345 error = mountnfs(&args, mp, nam, hst, krbname, krbnamelen, dirpath,
1346 dirlen, srvkrbname, srvkrbnamelen, &vp, td->td_ucred, td,
1347 nametimeo, negnametimeo, minvers, newflag);
1351 mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED | MNTK_NO_IOPF |
1353 if ((VFSTONFS(mp)->nm_flag & NFSMNT_NFSV4) != 0)
1354 mp->mnt_kern_flag |= MNTK_NULL_NOCACHE;
1366 * It seems a bit dumb to copyinstr() the host and path here and then
1367 * bcopy() them in mountnfs(), but I wanted to detect errors before
1368 * doing the getsockaddr() call because getsockaddr() allocates an mbuf and
1369 * an error after that means that I have to release the mbuf.
1373 nfs_cmount(struct mntarg *ma, void *data, uint64_t flags)
1376 struct nfs_args args;
1378 error = copyin(data, &args, sizeof (struct nfs_args));
1382 ma = mount_arg(ma, "nfs_args", &args, sizeof args);
1384 error = kernel_mount(ma, flags);
1389 * Common code for mount and mountroot
1392 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
1393 char *hst, u_char *krbname, int krbnamelen, u_char *dirpath, int dirlen,
1394 u_char *srvkrbname, int srvkrbnamelen, struct vnode **vpp,
1395 struct ucred *cred, struct thread *td, int nametimeo, int negnametimeo,
1396 int minvers, uint32_t newflag)
1398 struct nfsmount *nmp;
1400 int error, trycnt, ret;
1401 struct nfsvattr nfsva;
1402 struct nfsclclient *clp;
1403 struct nfsclds *dsp, *tdsp;
1405 static u_int64_t clval = 0;
1410 NFSCL_DEBUG(3, "in mnt\n");
1412 if (mp->mnt_flag & MNT_UPDATE) {
1414 printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
1415 free(nam, M_SONAME);
1418 /* NFS-over-TLS requires that rpctls be functioning. */
1419 if ((newflag & NFSMNT_TLS) != 0) {
1422 if (rpctls_getinfo(&maxlen, true, false))
1426 free(nam, M_SONAME);
1430 nmp = malloc(sizeof (struct nfsmount) +
1431 krbnamelen + dirlen + srvkrbnamelen + 2,
1432 M_NEWNFSMNT, M_WAITOK | M_ZERO);
1433 nmp->nm_newflag = newflag;
1434 TAILQ_INIT(&nmp->nm_bufq);
1435 TAILQ_INIT(&nmp->nm_sess);
1437 clval = (u_int64_t)nfsboottime.tv_sec;
1438 nmp->nm_clval = clval++;
1439 nmp->nm_krbnamelen = krbnamelen;
1440 nmp->nm_dirpathlen = dirlen;
1441 nmp->nm_srvkrbnamelen = srvkrbnamelen;
1442 if (td->td_ucred->cr_uid != (uid_t)0) {
1444 * nm_uid is used to get KerberosV credentials for
1445 * the nfsv4 state handling operations if there is
1446 * no host based principal set. Use the uid of
1447 * this user if not root, since they are doing the
1448 * mount. I don't think setting this for root will
1449 * work, since root normally does not have user
1450 * credentials in a credentials cache.
1452 nmp->nm_uid = td->td_ucred->cr_uid;
1455 * Just set to -1, so it won't be used.
1457 nmp->nm_uid = (uid_t)-1;
1460 /* Copy and null terminate all the names */
1461 if (nmp->nm_krbnamelen > 0) {
1462 bcopy(krbname, nmp->nm_krbname, nmp->nm_krbnamelen);
1463 nmp->nm_name[nmp->nm_krbnamelen] = '\0';
1465 if (nmp->nm_dirpathlen > 0) {
1466 bcopy(dirpath, NFSMNT_DIRPATH(nmp),
1467 nmp->nm_dirpathlen);
1468 nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1471 if (nmp->nm_srvkrbnamelen > 0) {
1472 bcopy(srvkrbname, NFSMNT_SRVKRBNAME(nmp),
1473 nmp->nm_srvkrbnamelen);
1474 nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1475 + nmp->nm_srvkrbnamelen + 2] = '\0';
1477 nmp->nm_sockreq.nr_cred = crhold(cred);
1478 mtx_init(&nmp->nm_sockreq.nr_mtx, "nfssock", NULL, MTX_DEF);
1480 nmp->nm_getinfo = nfs_getnlminfo;
1481 nmp->nm_vinvalbuf = ncl_vinvalbuf;
1484 nmp->nm_mountp = mp;
1485 mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF | MTX_DUPOK);
1488 * Since nfs_decode_args() might optionally set them, these
1489 * need to be set to defaults before the call, so that the
1490 * optional settings aren't overwritten.
1492 nmp->nm_nametimeo = nametimeo;
1493 nmp->nm_negnametimeo = negnametimeo;
1494 nmp->nm_timeo = NFS_TIMEO;
1495 nmp->nm_retry = NFS_RETRANS;
1496 nmp->nm_readahead = NFS_DEFRAHEAD;
1498 /* This is empirical approximation of sqrt(hibufspace) * 256. */
1499 nmp->nm_wcommitsize = NFS_MAXBSIZE / 256;
1500 while ((long)nmp->nm_wcommitsize * nmp->nm_wcommitsize < hibufspace)
1501 nmp->nm_wcommitsize *= 2;
1502 nmp->nm_wcommitsize *= 256;
1504 if ((argp->flags & NFSMNT_NFSV4) != 0)
1505 nmp->nm_minorvers = minvers;
1507 nmp->nm_minorvers = 0;
1509 nfs_decode_args(mp, nmp, argp, hst, cred, td);
1512 * V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too
1513 * high, depending on whether we end up with negative offsets in
1514 * the client or server somewhere. 2GB-1 may be safer.
1516 * For V3, ncl_fsinfo will adjust this as necessary. Assume maximum
1517 * that we can handle until we find out otherwise.
1519 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0)
1520 nmp->nm_maxfilesize = 0xffffffffLL;
1522 nmp->nm_maxfilesize = OFF_MAX;
1524 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
1525 nmp->nm_wsize = NFS_WSIZE;
1526 nmp->nm_rsize = NFS_RSIZE;
1527 nmp->nm_readdirsize = NFS_READDIRSIZE;
1529 nmp->nm_numgrps = NFS_MAXGRPS;
1530 nmp->nm_tprintf_delay = nfs_tprintf_delay;
1531 if (nmp->nm_tprintf_delay < 0)
1532 nmp->nm_tprintf_delay = 0;
1533 nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
1534 if (nmp->nm_tprintf_initial_delay < 0)
1535 nmp->nm_tprintf_initial_delay = 0;
1536 nmp->nm_fhsize = argp->fhsize;
1537 if (nmp->nm_fhsize > 0)
1538 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
1539 bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
1541 /* Set up the sockets and per-host congestion */
1542 nmp->nm_sotype = argp->sotype;
1543 nmp->nm_soproto = argp->proto;
1544 nmp->nm_sockreq.nr_prog = NFS_PROG;
1545 if ((argp->flags & NFSMNT_NFSV4))
1546 nmp->nm_sockreq.nr_vers = NFS_VER4;
1547 else if ((argp->flags & NFSMNT_NFSV3))
1548 nmp->nm_sockreq.nr_vers = NFS_VER3;
1550 nmp->nm_sockreq.nr_vers = NFS_VER2;
1553 if ((error = newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0, false)))
1555 /* For NFSv4.1, get the clientid now. */
1556 if (nmp->nm_minorvers > 0) {
1557 NFSCL_DEBUG(3, "at getcl\n");
1558 error = nfscl_getcl(mp, cred, td, 0, &clp);
1559 NFSCL_DEBUG(3, "aft getcl=%d\n", error);
1564 if (nmp->nm_fhsize == 0 && (nmp->nm_flag & NFSMNT_NFSV4) &&
1565 nmp->nm_dirpathlen > 0) {
1566 NFSCL_DEBUG(3, "in dirp\n");
1568 * If the fhsize on the mount point == 0 for V4, the mount
1569 * path needs to be looked up.
1573 error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp),
1575 NFSCL_DEBUG(3, "aft dirp=%d\n", error);
1577 (void) nfs_catnap(PZERO, error, "nfsgetdirp");
1578 } while (error && --trycnt > 0);
1584 * A reference count is needed on the nfsnode representing the
1585 * remote root. If this object is not persistent, then backward
1586 * traversals of the mount point (i.e. "..") will not work if
1587 * the nfsnode gets flushed out of the cache. Ufs does not have
1588 * this problem, because one can identify root inodes by their
1589 * number == UFS_ROOTINO (2).
1591 if (nmp->nm_fhsize > 0) {
1593 * Set f_iosize to NFS_DIRBLKSIZ so that bo_bsize gets set
1594 * non-zero for the root vnode. f_iosize will be set correctly
1595 * by nfs_statfs() before any I/O occurs.
1597 mp->mnt_stat.f_iosize = NFS_DIRBLKSIZ;
1598 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np,
1605 * Get file attributes and transfer parameters for the
1606 * mountpoint. This has the side effect of filling in
1607 * (*vpp)->v_type with the correct value.
1609 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
1610 cred, td, &nfsva, NULL, &lease);
1613 * Just set default values to get things going.
1615 NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
1616 nfsva.na_vattr.va_type = VDIR;
1617 nfsva.na_vattr.va_mode = 0777;
1618 nfsva.na_vattr.va_nlink = 100;
1619 nfsva.na_vattr.va_uid = (uid_t)0;
1620 nfsva.na_vattr.va_gid = (gid_t)0;
1621 nfsva.na_vattr.va_fileid = 2;
1622 nfsva.na_vattr.va_gen = 1;
1623 nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
1624 nfsva.na_vattr.va_size = 512 * 1024;
1627 (void) nfscl_loadattrcache(vpp, &nfsva, NULL, NULL, 0, 1);
1628 if (nmp->nm_minorvers > 0) {
1629 NFSCL_DEBUG(3, "lease=%d\n", (int)lease);
1631 clp->nfsc_renew = NFSCL_RENEW(lease);
1632 clp->nfsc_expire = NFSD_MONOSEC + clp->nfsc_renew;
1633 clp->nfsc_clientidrev++;
1634 if (clp->nfsc_clientidrev == 0)
1635 clp->nfsc_clientidrev++;
1638 * Mount will succeed, so the renew thread can be
1641 nfscl_start_renewthread(clp);
1642 nfscl_clientrelease(clp);
1644 if (argp->flags & NFSMNT_NFSV3)
1645 ncl_fsinfo(nmp, *vpp, cred, td);
1647 /* Mark if the mount point supports NFSv4 ACLs. */
1648 if ((argp->flags & NFSMNT_NFSV4) != 0 && nfsrv_useacl != 0 &&
1650 NFSISSET_ATTRBIT(&nfsva.na_suppattr, NFSATTRBIT_ACL)) {
1652 mp->mnt_flag |= MNT_NFS4ACLS;
1657 * Lose the lock but keep the ref.
1660 vfs_cache_root_set(mp, *vpp);
1667 nfscl_clientrelease(clp);
1668 newnfs_disconnect(&nmp->nm_sockreq);
1669 crfree(nmp->nm_sockreq.nr_cred);
1670 if (nmp->nm_sockreq.nr_auth != NULL)
1671 AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
1672 mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1673 mtx_destroy(&nmp->nm_mtx);
1674 if (nmp->nm_clp != NULL) {
1676 LIST_REMOVE(nmp->nm_clp, nfsc_list);
1678 free(nmp->nm_clp, M_NFSCLCLIENT);
1680 TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp) {
1681 if (dsp != TAILQ_FIRST(&nmp->nm_sess) &&
1682 dsp->nfsclds_sockp != NULL)
1683 newnfs_disconnect(dsp->nfsclds_sockp);
1684 nfscl_freenfsclds(dsp);
1686 free(nmp, M_NEWNFSMNT);
1687 free(nam, M_SONAME);
1692 * unmount system call
1695 nfs_unmount(struct mount *mp, int mntflags)
1698 struct nfsmount *nmp;
1699 int error, flags = 0, i, trycnt = 0;
1700 struct nfsclds *dsp, *tdsp;
1704 if (mntflags & MNT_FORCE)
1705 flags |= FORCECLOSE;
1709 * Goes something like this..
1710 * - Call vflush() to clear out vnodes for this filesystem
1711 * - Close the socket
1712 * - Free up the data structures
1714 /* In the forced case, cancel any outstanding requests. */
1715 if (mntflags & MNT_FORCE) {
1717 if (nfsv4_findmirror(nmp) != NULL)
1722 error = newnfs_nmcancelreqs(nmp);
1725 /* For a forced close, get rid of the renew thread now */
1726 nfscl_umount(nmp, td);
1728 /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
1730 error = vflush(mp, 1, flags, td);
1731 if ((mntflags & MNT_FORCE) && error != 0 && ++trycnt < 30)
1732 (void) nfs_catnap(PSOCK, error, "newndm");
1733 } while ((mntflags & MNT_FORCE) && error != 0 && trycnt < 30);
1738 * We are now committed to the unmount.
1740 if ((mntflags & MNT_FORCE) == 0)
1741 nfscl_umount(nmp, td);
1743 mtx_lock(&nmp->nm_mtx);
1744 nmp->nm_privflag |= NFSMNTP_FORCEDISM;
1745 mtx_unlock(&nmp->nm_mtx);
1747 /* Make sure no nfsiods are assigned to this mount. */
1749 for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
1750 if (ncl_iodmount[i] == nmp) {
1751 ncl_iodwant[i] = NFSIOD_AVAILABLE;
1752 ncl_iodmount[i] = NULL;
1757 * We can now set mnt_data to NULL and wait for
1758 * nfssvc(NFSSVC_FORCEDISM) to complete.
1760 mtx_lock(&mountlist_mtx);
1761 mtx_lock(&nmp->nm_mtx);
1762 mp->mnt_data = NULL;
1763 mtx_unlock(&mountlist_mtx);
1764 while ((nmp->nm_privflag & NFSMNTP_CANCELRPCS) != 0)
1765 msleep(nmp, &nmp->nm_mtx, PVFS, "nfsfdism", 0);
1766 mtx_unlock(&nmp->nm_mtx);
1768 newnfs_disconnect(&nmp->nm_sockreq);
1769 crfree(nmp->nm_sockreq.nr_cred);
1770 free(nmp->nm_nam, M_SONAME);
1771 if (nmp->nm_sockreq.nr_auth != NULL)
1772 AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
1773 mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1774 mtx_destroy(&nmp->nm_mtx);
1775 TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp) {
1776 if (dsp != TAILQ_FIRST(&nmp->nm_sess) &&
1777 dsp->nfsclds_sockp != NULL)
1778 newnfs_disconnect(dsp->nfsclds_sockp);
1779 nfscl_freenfsclds(dsp);
1781 free(nmp, M_NEWNFSMNT);
1787 * Return root of a filesystem
1790 nfs_root(struct mount *mp, int flags, struct vnode **vpp)
1793 struct nfsmount *nmp;
1798 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, flags);
1803 * Get transfer parameters and attributes for root vnode once.
1805 mtx_lock(&nmp->nm_mtx);
1806 if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
1807 mtx_unlock(&nmp->nm_mtx);
1808 ncl_fsinfo(nmp, vp, curthread->td_ucred, curthread);
1810 mtx_unlock(&nmp->nm_mtx);
1811 if (vp->v_type == VNON)
1813 vp->v_vflag |= VV_ROOT;
1819 * Flush out the buffer cache
1823 nfs_sync(struct mount *mp, int waitfor)
1825 struct vnode *vp, *mvp;
1827 int error, allerror = 0;
1833 * If a forced dismount is in progress, return from here so that
1834 * the umount(2) syscall doesn't get stuck in VFS_SYNC() before
1835 * calling VFS_UNMOUNT().
1837 if (NFSCL_FORCEDISM(mp)) {
1844 * Force stale buffer cache information to be flushed.
1847 MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
1848 /* XXX Racy bv_cnt check. */
1849 if (NFSVOPISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
1850 waitfor == MNT_LAZY) {
1854 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK)) {
1855 MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
1858 error = VOP_FSYNC(vp, waitfor, td);
1868 nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
1870 struct nfsmount *nmp = VFSTONFS(mp);
1874 bzero(&vq, sizeof(vq));
1877 case VFS_CTL_NOLOCKS:
1878 val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
1879 if (req->oldptr != NULL) {
1880 error = SYSCTL_OUT(req, &val, sizeof(val));
1884 if (req->newptr != NULL) {
1885 error = SYSCTL_IN(req, &val, sizeof(val));
1889 nmp->nm_flag |= NFSMNT_NOLOCKS;
1891 nmp->nm_flag &= ~NFSMNT_NOLOCKS;
1896 mtx_lock(&nmp->nm_mtx);
1897 if (nmp->nm_state & NFSSTA_TIMEO)
1898 vq.vq_flags |= VQ_NOTRESP;
1899 mtx_unlock(&nmp->nm_mtx);
1901 if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
1902 (nmp->nm_state & NFSSTA_LOCKTIMEO))
1903 vq.vq_flags |= VQ_NOTRESPLOCK;
1905 error = SYSCTL_OUT(req, &vq, sizeof(vq));
1908 if (req->oldptr != NULL) {
1909 error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
1910 sizeof(nmp->nm_tprintf_initial_delay));
1914 if (req->newptr != NULL) {
1915 error = vfs_suser(mp, req->td);
1918 error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
1919 sizeof(nmp->nm_tprintf_initial_delay));
1922 if (nmp->nm_tprintf_initial_delay < 0)
1923 nmp->nm_tprintf_initial_delay = 0;
1933 * Purge any RPCs in progress, so that they will all return errors.
1934 * This allows dounmount() to continue as far as VFS_UNMOUNT() for a
1938 nfs_purge(struct mount *mp)
1940 struct nfsmount *nmp = VFSTONFS(mp);
1942 newnfs_nmcancelreqs(nmp);
1946 * Extract the information needed by the nlm from the nfs vnode.
1949 nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp,
1950 struct sockaddr_storage *sp, int *is_v3p, off_t *sizep,
1951 struct timeval *timeop)
1953 struct nfsmount *nmp;
1954 struct nfsnode *np = VTONFS(vp);
1956 nmp = VFSTONFS(vp->v_mount);
1958 *fhlenp = (size_t)np->n_fhp->nfh_len;
1960 bcopy(np->n_fhp->nfh_fh, fhp, np->n_fhp->nfh_len);
1962 bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp)));
1964 *is_v3p = NFS_ISV3(vp);
1966 *sizep = np->n_size;
1967 if (timeop != NULL) {
1968 timeop->tv_sec = nmp->nm_timeo / NFS_HZ;
1969 timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ);
1974 * This function prints out an option name, based on the conditional
1977 static __inline void nfscl_printopt(struct nfsmount *nmp, int testval,
1978 char *opt, char **buf, size_t *blen)
1982 if (testval != 0 && *blen > strlen(opt)) {
1983 len = snprintf(*buf, *blen, "%s", opt);
1984 if (len != strlen(opt))
1992 * This function printf out an options integer value.
1994 static __inline void nfscl_printoptval(struct nfsmount *nmp, int optval,
1995 char *opt, char **buf, size_t *blen)
1999 if (*blen > strlen(opt) + 1) {
2000 /* Could result in truncated output string. */
2001 len = snprintf(*buf, *blen, "%s=%d", opt, optval);
2010 * Load the option flags and values into the buffer.
2012 void nfscl_retopts(struct nfsmount *nmp, char *buffer, size_t buflen)
2019 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV4) != 0, "nfsv4", &buf,
2021 if ((nmp->nm_flag & NFSMNT_NFSV4) != 0) {
2022 nfscl_printoptval(nmp, nmp->nm_minorvers, ",minorversion", &buf,
2024 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_PNFS) != 0, ",pnfs",
2026 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_ONEOPENOWN) != 0 &&
2027 nmp->nm_minorvers > 0, ",oneopenown", &buf, &blen);
2029 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV3) != 0, "nfsv3", &buf,
2031 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0,
2032 "nfsv2", &buf, &blen);
2033 nfscl_printopt(nmp, nmp->nm_sotype == SOCK_STREAM, ",tcp", &buf, &blen);
2034 nfscl_printopt(nmp, nmp->nm_sotype != SOCK_STREAM, ",udp", &buf, &blen);
2035 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RESVPORT) != 0, ",resvport",
2037 nfscl_printopt(nmp, (nmp->nm_newflag & NFSMNT_TLS) != 0, ",tls", &buf,
2039 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCONN) != 0, ",noconn",
2041 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) == 0, ",hard", &buf,
2043 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) != 0, ",soft", &buf,
2045 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_INT) != 0, ",intr", &buf,
2047 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) == 0, ",cto", &buf,
2049 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) != 0, ",nocto", &buf,
2051 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NONCONTIGWR) != 0,
2052 ",noncontigwr", &buf, &blen);
2053 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
2054 0, ",lockd", &buf, &blen);
2055 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
2056 NFSMNT_NOLOCKD, ",nolockd", &buf, &blen);
2057 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RDIRPLUS) != 0, ",rdirplus",
2059 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_KERB) == 0, ",sec=sys",
2061 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
2062 NFSMNT_PRIVACY)) == NFSMNT_KERB, ",sec=krb5", &buf, &blen);
2063 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
2064 NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_INTEGRITY), ",sec=krb5i",
2066 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
2067 NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_PRIVACY), ",sec=krb5p",
2069 nfscl_printoptval(nmp, nmp->nm_acdirmin, ",acdirmin", &buf, &blen);
2070 nfscl_printoptval(nmp, nmp->nm_acdirmax, ",acdirmax", &buf, &blen);
2071 nfscl_printoptval(nmp, nmp->nm_acregmin, ",acregmin", &buf, &blen);
2072 nfscl_printoptval(nmp, nmp->nm_acregmax, ",acregmax", &buf, &blen);
2073 nfscl_printoptval(nmp, nmp->nm_nametimeo, ",nametimeo", &buf, &blen);
2074 nfscl_printoptval(nmp, nmp->nm_negnametimeo, ",negnametimeo", &buf,
2076 nfscl_printoptval(nmp, nmp->nm_rsize, ",rsize", &buf, &blen);
2077 nfscl_printoptval(nmp, nmp->nm_wsize, ",wsize", &buf, &blen);
2078 nfscl_printoptval(nmp, nmp->nm_readdirsize, ",readdirsize", &buf,
2080 nfscl_printoptval(nmp, nmp->nm_readahead, ",readahead", &buf, &blen);
2081 nfscl_printoptval(nmp, nmp->nm_wcommitsize, ",wcommitsize", &buf,
2083 nfscl_printoptval(nmp, nmp->nm_timeo, ",timeout", &buf, &blen);
2084 nfscl_printoptval(nmp, nmp->nm_retry, ",retrans", &buf, &blen);