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, char *);
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, NULL)) != 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", "tlscertname",
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, *tlscertname;
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;
907 hst = malloc(MNAMELEN, M_TEMP, M_WAITOK);
908 if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
914 if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS &&
915 nfs_diskless_valid != 0) {
916 error = nfs_mountroot(mp);
923 * The old mount_nfs program passed the struct nfs_args
924 * from userspace to kernel. The new mount_nfs program
925 * passes string options via nmount() from userspace to kernel
926 * and we populate the struct nfs_args in the kernel.
928 if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
929 error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
934 if (args.version != NFS_ARGSVERSION) {
935 error = EPROGMISMATCH;
938 has_nfs_args_opt = 1;
941 /* Handle the new style options. */
942 if (vfs_getopt(mp->mnt_optnew, "noac", NULL, NULL) == 0) {
943 args.acdirmin = args.acdirmax =
944 args.acregmin = args.acregmax = 0;
945 args.flags |= NFSMNT_ACDIRMIN | NFSMNT_ACDIRMAX |
946 NFSMNT_ACREGMIN | NFSMNT_ACREGMAX;
948 if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
949 args.flags |= NFSMNT_NOCONN;
950 if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
951 args.flags &= ~NFSMNT_NOCONN;
952 if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
953 args.flags |= NFSMNT_NOLOCKD;
954 if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
955 args.flags &= ~NFSMNT_NOLOCKD;
956 if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
957 args.flags |= NFSMNT_INT;
958 if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
959 args.flags |= NFSMNT_RDIRPLUS;
960 if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
961 args.flags |= NFSMNT_RESVPORT;
962 if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
963 args.flags &= ~NFSMNT_RESVPORT;
964 if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
965 args.flags |= NFSMNT_SOFT;
966 if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
967 args.flags &= ~NFSMNT_SOFT;
968 if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
969 args.sotype = SOCK_DGRAM;
970 if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
971 args.sotype = SOCK_DGRAM;
972 if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
973 args.sotype = SOCK_STREAM;
974 if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
975 args.flags |= NFSMNT_NFSV3;
976 if (vfs_getopt(mp->mnt_optnew, "nfsv4", NULL, NULL) == 0) {
977 args.flags |= NFSMNT_NFSV4;
978 args.sotype = SOCK_STREAM;
980 if (vfs_getopt(mp->mnt_optnew, "allgssname", NULL, NULL) == 0)
981 args.flags |= NFSMNT_ALLGSSNAME;
982 if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0)
983 args.flags |= NFSMNT_NOCTO;
984 if (vfs_getopt(mp->mnt_optnew, "noncontigwr", NULL, NULL) == 0)
985 args.flags |= NFSMNT_NONCONTIGWR;
986 if (vfs_getopt(mp->mnt_optnew, "pnfs", NULL, NULL) == 0)
987 args.flags |= NFSMNT_PNFS;
988 if (vfs_getopt(mp->mnt_optnew, "oneopenown", NULL, NULL) == 0)
989 args.flags |= NFSMNT_ONEOPENOWN;
990 if (vfs_getopt(mp->mnt_optnew, "tls", NULL, NULL) == 0)
991 newflag |= NFSMNT_TLS;
992 if (vfs_getopt(mp->mnt_optnew, "tlscertname", (void **)&opt, &len) ==
995 * tlscertname with "key.pem" appended to it forms a file
996 * name. As such, the maximum allowable strlen(tlscertname) is
997 * NAME_MAX - 7. However, "len" includes the nul termination
998 * byte so it can be up to NAME_MAX - 6.
1000 if (opt == NULL || len <= 1 || len > NAME_MAX - 6) {
1001 vfs_mount_error(mp, "invalid tlscertname");
1005 tlscertname = malloc(len, M_NEWNFSMNT, M_WAITOK);
1006 strlcpy(tlscertname, opt, len);
1008 if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
1010 vfs_mount_error(mp, "illegal readdirsize");
1014 ret = sscanf(opt, "%d", &args.readdirsize);
1015 if (ret != 1 || args.readdirsize <= 0) {
1016 vfs_mount_error(mp, "illegal readdirsize: %s",
1021 args.flags |= NFSMNT_READDIRSIZE;
1023 if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
1025 vfs_mount_error(mp, "illegal readahead");
1029 ret = sscanf(opt, "%d", &args.readahead);
1030 if (ret != 1 || args.readahead <= 0) {
1031 vfs_mount_error(mp, "illegal readahead: %s",
1036 args.flags |= NFSMNT_READAHEAD;
1038 if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
1040 vfs_mount_error(mp, "illegal wsize");
1044 ret = sscanf(opt, "%d", &args.wsize);
1045 if (ret != 1 || args.wsize <= 0) {
1046 vfs_mount_error(mp, "illegal wsize: %s",
1051 args.flags |= NFSMNT_WSIZE;
1053 if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
1055 vfs_mount_error(mp, "illegal rsize");
1059 ret = sscanf(opt, "%d", &args.rsize);
1060 if (ret != 1 || args.rsize <= 0) {
1061 vfs_mount_error(mp, "illegal wsize: %s",
1066 args.flags |= NFSMNT_RSIZE;
1068 if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
1070 vfs_mount_error(mp, "illegal retrans");
1074 ret = sscanf(opt, "%d", &args.retrans);
1075 if (ret != 1 || args.retrans <= 0) {
1076 vfs_mount_error(mp, "illegal retrans: %s",
1081 args.flags |= NFSMNT_RETRANS;
1083 if (vfs_getopt(mp->mnt_optnew, "actimeo", (void **)&opt, NULL) == 0) {
1084 ret = sscanf(opt, "%d", &args.acregmin);
1085 if (ret != 1 || args.acregmin < 0) {
1086 vfs_mount_error(mp, "illegal actimeo: %s",
1091 args.acdirmin = args.acdirmax = args.acregmax = args.acregmin;
1092 args.flags |= NFSMNT_ACDIRMIN | NFSMNT_ACDIRMAX |
1093 NFSMNT_ACREGMIN | NFSMNT_ACREGMAX;
1095 if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
1096 ret = sscanf(opt, "%d", &args.acregmin);
1097 if (ret != 1 || args.acregmin < 0) {
1098 vfs_mount_error(mp, "illegal acregmin: %s",
1103 args.flags |= NFSMNT_ACREGMIN;
1105 if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
1106 ret = sscanf(opt, "%d", &args.acregmax);
1107 if (ret != 1 || args.acregmax < 0) {
1108 vfs_mount_error(mp, "illegal acregmax: %s",
1113 args.flags |= NFSMNT_ACREGMAX;
1115 if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
1116 ret = sscanf(opt, "%d", &args.acdirmin);
1117 if (ret != 1 || args.acdirmin < 0) {
1118 vfs_mount_error(mp, "illegal acdirmin: %s",
1123 args.flags |= NFSMNT_ACDIRMIN;
1125 if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
1126 ret = sscanf(opt, "%d", &args.acdirmax);
1127 if (ret != 1 || args.acdirmax < 0) {
1128 vfs_mount_error(mp, "illegal acdirmax: %s",
1133 args.flags |= NFSMNT_ACDIRMAX;
1135 if (vfs_getopt(mp->mnt_optnew, "wcommitsize", (void **)&opt, NULL) == 0) {
1136 ret = sscanf(opt, "%d", &args.wcommitsize);
1137 if (ret != 1 || args.wcommitsize < 0) {
1138 vfs_mount_error(mp, "illegal wcommitsize: %s", opt);
1142 args.flags |= NFSMNT_WCOMMITSIZE;
1144 if (vfs_getopt(mp->mnt_optnew, "timeo", (void **)&opt, NULL) == 0) {
1145 ret = sscanf(opt, "%d", &args.timeo);
1146 if (ret != 1 || args.timeo <= 0) {
1147 vfs_mount_error(mp, "illegal timeo: %s",
1152 args.flags |= NFSMNT_TIMEO;
1154 if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
1155 ret = sscanf(opt, "%d", &args.timeo);
1156 if (ret != 1 || args.timeo <= 0) {
1157 vfs_mount_error(mp, "illegal timeout: %s",
1162 args.flags |= NFSMNT_TIMEO;
1164 if (vfs_getopt(mp->mnt_optnew, "nametimeo", (void **)&opt, NULL) == 0) {
1165 ret = sscanf(opt, "%d", &nametimeo);
1166 if (ret != 1 || nametimeo < 0) {
1167 vfs_mount_error(mp, "illegal nametimeo: %s", opt);
1172 if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
1174 ret = sscanf(opt, "%d", &negnametimeo);
1175 if (ret != 1 || negnametimeo < 0) {
1176 vfs_mount_error(mp, "illegal negnametimeo: %s",
1182 if (vfs_getopt(mp->mnt_optnew, "minorversion", (void **)&opt, NULL) ==
1184 ret = sscanf(opt, "%d", &minvers);
1185 if (ret != 1 || minvers < 0 || minvers > 2 ||
1186 (args.flags & NFSMNT_NFSV4) == 0) {
1187 vfs_mount_error(mp, "illegal minorversion: %s", opt);
1192 if (vfs_getopt(mp->mnt_optnew, "sec",
1193 (void **) &secname, NULL) == 0)
1194 nfs_sec_name(secname, &args.flags);
1196 if (mp->mnt_flag & MNT_UPDATE) {
1197 struct nfsmount *nmp = VFSTONFS(mp);
1205 * If a change from TCP->UDP is done and there are thread(s)
1206 * that have I/O RPC(s) in progress with a transfer size
1207 * greater than NFS_MAXDGRAMDATA, those thread(s) will be
1208 * hung, retrying the RPC(s) forever. Usually these threads
1209 * will be seen doing an uninterruptible sleep on wait channel
1212 if (args.sotype == SOCK_DGRAM && nmp->nm_sotype == SOCK_STREAM)
1213 tprintf(td->td_proc, LOG_WARNING,
1214 "Warning: mount -u that changes TCP->UDP can result in hung threads\n");
1217 * When doing an update, we can't change version,
1218 * security, switch lockd strategies, change cookie
1219 * translation or switch oneopenown.
1221 args.flags = (args.flags &
1228 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
1236 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
1237 nfs_decode_args(mp, nmp, &args, NULL, td->td_ucred, td);
1242 * Make the nfs_ip_paranoia sysctl serve as the default connection
1243 * or no-connection mode for those protocols that support
1244 * no-connection mode (the flag will be cleared later for protocols
1245 * that do not support no-connection mode). This will allow a client
1246 * to receive replies from a different IP then the request was
1247 * sent to. Note: default value for nfs_ip_paranoia is 1 (paranoid),
1250 if (nfs_ip_paranoia == 0)
1251 args.flags |= NFSMNT_NOCONN;
1253 if (has_nfs_args_opt != 0) {
1255 * In the 'nfs_args' case, the pointers in the args
1256 * structure are in userland - we copy them in here.
1258 if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
1259 vfs_mount_error(mp, "Bad file handle");
1263 error = copyin((caddr_t)args.fh, (caddr_t)nfh,
1267 error = copyinstr(args.hostname, hst, MNAMELEN - 1, &hstlen);
1270 bzero(&hst[hstlen], MNAMELEN - hstlen);
1271 args.hostname = hst;
1272 /* getsockaddr() call must be after above copyin() calls */
1273 error = getsockaddr(&nam, args.addr, args.addrlen);
1276 } else if (nfs_mount_parse_from(mp->mnt_optnew,
1277 &args.hostname, (struct sockaddr_in **)&nam, dirpath,
1278 sizeof(dirpath), &dirlen) == 0) {
1279 has_nfs_from_opt = 1;
1280 bcopy(args.hostname, hst, MNAMELEN);
1281 hst[MNAMELEN - 1] = '\0';
1284 * This only works with NFSv4 for now.
1287 args.flags |= NFSMNT_NFSV4;
1288 args.sotype = SOCK_STREAM;
1290 if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
1291 &args.fhsize) == 0) {
1292 if (args.fhsize < 0 || args.fhsize > NFSX_FHMAX) {
1293 vfs_mount_error(mp, "Bad file handle");
1297 bcopy(args.fh, nfh, args.fhsize);
1301 (void) vfs_getopt(mp->mnt_optnew, "hostname",
1302 (void **)&args.hostname, &len);
1303 if (args.hostname == NULL) {
1304 vfs_mount_error(mp, "Invalid hostname");
1308 if (len >= MNAMELEN) {
1309 vfs_mount_error(mp, "Hostname too long");
1313 bcopy(args.hostname, hst, len);
1317 if (vfs_getopt(mp->mnt_optnew, "principal", (void **)&name, NULL) == 0)
1318 strlcpy(srvkrbname, name, sizeof (srvkrbname));
1320 snprintf(srvkrbname, sizeof (srvkrbname), "nfs@%s", hst);
1321 cp = strchr(srvkrbname, ':');
1325 srvkrbnamelen = strlen(srvkrbname);
1327 if (vfs_getopt(mp->mnt_optnew, "gssname", (void **)&name, NULL) == 0)
1328 strlcpy(krbname, name, sizeof (krbname));
1331 krbnamelen = strlen(krbname);
1333 if (has_nfs_from_opt == 0) {
1334 if (vfs_getopt(mp->mnt_optnew,
1335 "dirpath", (void **)&name, NULL) == 0)
1336 strlcpy(dirpath, name, sizeof (dirpath));
1339 dirlen = strlen(dirpath);
1342 if (has_nfs_args_opt == 0 && has_nfs_from_opt == 0) {
1343 if (vfs_getopt(mp->mnt_optnew, "addr",
1344 (void **)&args.addr, &args.addrlen) == 0) {
1345 if (args.addrlen > SOCK_MAXADDRLEN) {
1346 error = ENAMETOOLONG;
1349 nam = malloc(args.addrlen, M_SONAME, M_WAITOK);
1350 bcopy(args.addr, nam, args.addrlen);
1351 nam->sa_len = args.addrlen;
1353 vfs_mount_error(mp, "No server address");
1360 error = mountnfs(&args, mp, nam, hst, krbname, krbnamelen, dirpath,
1361 dirlen, srvkrbname, srvkrbnamelen, &vp, td->td_ucred, td,
1362 nametimeo, negnametimeo, minvers, newflag, tlscertname);
1366 mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED | MNTK_NO_IOPF |
1368 if ((VFSTONFS(mp)->nm_flag & NFSMNT_NFSV4) != 0)
1369 mp->mnt_kern_flag |= MNTK_NULL_NOCACHE;
1380 * It seems a bit dumb to copyinstr() the host and path here and then
1381 * bcopy() them in mountnfs(), but I wanted to detect errors before
1382 * doing the getsockaddr() call because getsockaddr() allocates an mbuf and
1383 * an error after that means that I have to release the mbuf.
1387 nfs_cmount(struct mntarg *ma, void *data, uint64_t flags)
1390 struct nfs_args args;
1392 error = copyin(data, &args, sizeof (struct nfs_args));
1396 ma = mount_arg(ma, "nfs_args", &args, sizeof args);
1398 error = kernel_mount(ma, flags);
1403 * Common code for mount and mountroot
1406 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
1407 char *hst, u_char *krbname, int krbnamelen, u_char *dirpath, int dirlen,
1408 u_char *srvkrbname, int srvkrbnamelen, struct vnode **vpp,
1409 struct ucred *cred, struct thread *td, int nametimeo, int negnametimeo,
1410 int minvers, uint32_t newflag, char *tlscertname)
1412 struct nfsmount *nmp;
1414 int error, trycnt, ret;
1415 struct nfsvattr nfsva;
1416 struct nfsclclient *clp;
1417 struct nfsclds *dsp, *tdsp;
1419 static u_int64_t clval = 0;
1424 NFSCL_DEBUG(3, "in mnt\n");
1426 if (mp->mnt_flag & MNT_UPDATE) {
1428 printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
1429 free(nam, M_SONAME);
1430 free(tlscertname, M_NEWNFSMNT);
1433 /* NFS-over-TLS requires that rpctls be functioning. */
1434 if ((newflag & NFSMNT_TLS) != 0) {
1437 /* KERN_TLS is only supported for TCP. */
1438 if (argp->sotype == SOCK_STREAM &&
1439 rpctls_getinfo(&maxlen, true, false))
1443 free(nam, M_SONAME);
1444 free(tlscertname, M_NEWNFSMNT);
1448 nmp = malloc(sizeof (struct nfsmount) +
1449 krbnamelen + dirlen + srvkrbnamelen + 2,
1450 M_NEWNFSMNT, M_WAITOK | M_ZERO);
1451 nmp->nm_tlscertname = tlscertname;
1452 nmp->nm_newflag = newflag;
1453 TAILQ_INIT(&nmp->nm_bufq);
1454 TAILQ_INIT(&nmp->nm_sess);
1456 clval = (u_int64_t)nfsboottime.tv_sec;
1457 nmp->nm_clval = clval++;
1458 nmp->nm_krbnamelen = krbnamelen;
1459 nmp->nm_dirpathlen = dirlen;
1460 nmp->nm_srvkrbnamelen = srvkrbnamelen;
1461 if (td->td_ucred->cr_uid != (uid_t)0) {
1463 * nm_uid is used to get KerberosV credentials for
1464 * the nfsv4 state handling operations if there is
1465 * no host based principal set. Use the uid of
1466 * this user if not root, since they are doing the
1467 * mount. I don't think setting this for root will
1468 * work, since root normally does not have user
1469 * credentials in a credentials cache.
1471 nmp->nm_uid = td->td_ucred->cr_uid;
1474 * Just set to -1, so it won't be used.
1476 nmp->nm_uid = (uid_t)-1;
1479 /* Copy and null terminate all the names */
1480 if (nmp->nm_krbnamelen > 0) {
1481 bcopy(krbname, nmp->nm_krbname, nmp->nm_krbnamelen);
1482 nmp->nm_name[nmp->nm_krbnamelen] = '\0';
1484 if (nmp->nm_dirpathlen > 0) {
1485 bcopy(dirpath, NFSMNT_DIRPATH(nmp),
1486 nmp->nm_dirpathlen);
1487 nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1490 if (nmp->nm_srvkrbnamelen > 0) {
1491 bcopy(srvkrbname, NFSMNT_SRVKRBNAME(nmp),
1492 nmp->nm_srvkrbnamelen);
1493 nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1494 + nmp->nm_srvkrbnamelen + 2] = '\0';
1496 nmp->nm_sockreq.nr_cred = crhold(cred);
1497 mtx_init(&nmp->nm_sockreq.nr_mtx, "nfssock", NULL, MTX_DEF);
1499 nmp->nm_getinfo = nfs_getnlminfo;
1500 nmp->nm_vinvalbuf = ncl_vinvalbuf;
1503 nmp->nm_mountp = mp;
1504 mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF | MTX_DUPOK);
1507 * Since nfs_decode_args() might optionally set them, these
1508 * need to be set to defaults before the call, so that the
1509 * optional settings aren't overwritten.
1511 nmp->nm_nametimeo = nametimeo;
1512 nmp->nm_negnametimeo = negnametimeo;
1513 nmp->nm_timeo = NFS_TIMEO;
1514 nmp->nm_retry = NFS_RETRANS;
1515 nmp->nm_readahead = NFS_DEFRAHEAD;
1517 /* This is empirical approximation of sqrt(hibufspace) * 256. */
1518 nmp->nm_wcommitsize = NFS_MAXBSIZE / 256;
1519 while ((long)nmp->nm_wcommitsize * nmp->nm_wcommitsize < hibufspace)
1520 nmp->nm_wcommitsize *= 2;
1521 nmp->nm_wcommitsize *= 256;
1523 if ((argp->flags & NFSMNT_NFSV4) != 0)
1524 nmp->nm_minorvers = minvers;
1526 nmp->nm_minorvers = 0;
1528 nfs_decode_args(mp, nmp, argp, hst, cred, td);
1531 * V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too
1532 * high, depending on whether we end up with negative offsets in
1533 * the client or server somewhere. 2GB-1 may be safer.
1535 * For V3, ncl_fsinfo will adjust this as necessary. Assume maximum
1536 * that we can handle until we find out otherwise.
1538 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0)
1539 nmp->nm_maxfilesize = 0xffffffffLL;
1541 nmp->nm_maxfilesize = OFF_MAX;
1543 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
1544 nmp->nm_wsize = NFS_WSIZE;
1545 nmp->nm_rsize = NFS_RSIZE;
1546 nmp->nm_readdirsize = NFS_READDIRSIZE;
1548 nmp->nm_numgrps = NFS_MAXGRPS;
1549 nmp->nm_tprintf_delay = nfs_tprintf_delay;
1550 if (nmp->nm_tprintf_delay < 0)
1551 nmp->nm_tprintf_delay = 0;
1552 nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
1553 if (nmp->nm_tprintf_initial_delay < 0)
1554 nmp->nm_tprintf_initial_delay = 0;
1555 nmp->nm_fhsize = argp->fhsize;
1556 if (nmp->nm_fhsize > 0)
1557 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
1558 bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
1560 /* Set up the sockets and per-host congestion */
1561 nmp->nm_sotype = argp->sotype;
1562 nmp->nm_soproto = argp->proto;
1563 nmp->nm_sockreq.nr_prog = NFS_PROG;
1564 if ((argp->flags & NFSMNT_NFSV4))
1565 nmp->nm_sockreq.nr_vers = NFS_VER4;
1566 else if ((argp->flags & NFSMNT_NFSV3))
1567 nmp->nm_sockreq.nr_vers = NFS_VER3;
1569 nmp->nm_sockreq.nr_vers = NFS_VER2;
1571 if ((error = newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0, false)))
1573 /* For NFSv4.1, get the clientid now. */
1574 if (nmp->nm_minorvers > 0) {
1575 NFSCL_DEBUG(3, "at getcl\n");
1576 error = nfscl_getcl(mp, cred, td, 0, &clp);
1577 NFSCL_DEBUG(3, "aft getcl=%d\n", error);
1582 if (nmp->nm_fhsize == 0 && (nmp->nm_flag & NFSMNT_NFSV4) &&
1583 nmp->nm_dirpathlen > 0) {
1584 NFSCL_DEBUG(3, "in dirp\n");
1586 * If the fhsize on the mount point == 0 for V4, the mount
1587 * path needs to be looked up.
1591 error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp),
1593 NFSCL_DEBUG(3, "aft dirp=%d\n", error);
1595 (void) nfs_catnap(PZERO, error, "nfsgetdirp");
1596 } while (error && --trycnt > 0);
1602 * A reference count is needed on the nfsnode representing the
1603 * remote root. If this object is not persistent, then backward
1604 * traversals of the mount point (i.e. "..") will not work if
1605 * the nfsnode gets flushed out of the cache. Ufs does not have
1606 * this problem, because one can identify root inodes by their
1607 * number == UFS_ROOTINO (2).
1609 if (nmp->nm_fhsize > 0) {
1611 * Set f_iosize to NFS_DIRBLKSIZ so that bo_bsize gets set
1612 * non-zero for the root vnode. f_iosize will be set correctly
1613 * by nfs_statfs() before any I/O occurs.
1615 mp->mnt_stat.f_iosize = NFS_DIRBLKSIZ;
1616 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np,
1623 * Get file attributes and transfer parameters for the
1624 * mountpoint. This has the side effect of filling in
1625 * (*vpp)->v_type with the correct value.
1627 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
1628 cred, td, &nfsva, NULL, &lease);
1631 * Just set default values to get things going.
1633 NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
1634 nfsva.na_vattr.va_type = VDIR;
1635 nfsva.na_vattr.va_mode = 0777;
1636 nfsva.na_vattr.va_nlink = 100;
1637 nfsva.na_vattr.va_uid = (uid_t)0;
1638 nfsva.na_vattr.va_gid = (gid_t)0;
1639 nfsva.na_vattr.va_fileid = 2;
1640 nfsva.na_vattr.va_gen = 1;
1641 nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
1642 nfsva.na_vattr.va_size = 512 * 1024;
1645 (void) nfscl_loadattrcache(vpp, &nfsva, NULL, NULL, 0, 1);
1646 if (nmp->nm_minorvers > 0) {
1647 NFSCL_DEBUG(3, "lease=%d\n", (int)lease);
1649 clp->nfsc_renew = NFSCL_RENEW(lease);
1650 clp->nfsc_expire = NFSD_MONOSEC + clp->nfsc_renew;
1651 clp->nfsc_clientidrev++;
1652 if (clp->nfsc_clientidrev == 0)
1653 clp->nfsc_clientidrev++;
1656 * Mount will succeed, so the renew thread can be
1659 nfscl_start_renewthread(clp);
1660 nfscl_clientrelease(clp);
1662 if (argp->flags & NFSMNT_NFSV3)
1663 ncl_fsinfo(nmp, *vpp, cred, td);
1665 /* Mark if the mount point supports NFSv4 ACLs. */
1666 if ((argp->flags & NFSMNT_NFSV4) != 0 && nfsrv_useacl != 0 &&
1668 NFSISSET_ATTRBIT(&nfsva.na_suppattr, NFSATTRBIT_ACL)) {
1670 mp->mnt_flag |= MNT_NFS4ACLS;
1675 * Lose the lock but keep the ref.
1678 vfs_cache_root_set(mp, *vpp);
1685 nfscl_clientrelease(clp);
1686 newnfs_disconnect(&nmp->nm_sockreq);
1687 crfree(nmp->nm_sockreq.nr_cred);
1688 if (nmp->nm_sockreq.nr_auth != NULL)
1689 AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
1690 mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1691 mtx_destroy(&nmp->nm_mtx);
1692 if (nmp->nm_clp != NULL) {
1694 LIST_REMOVE(nmp->nm_clp, nfsc_list);
1696 free(nmp->nm_clp, M_NFSCLCLIENT);
1698 TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp) {
1699 if (dsp != TAILQ_FIRST(&nmp->nm_sess) &&
1700 dsp->nfsclds_sockp != NULL)
1701 newnfs_disconnect(dsp->nfsclds_sockp);
1702 nfscl_freenfsclds(dsp);
1704 free(nmp->nm_tlscertname, M_NEWNFSMNT);
1705 free(nmp, M_NEWNFSMNT);
1706 free(nam, M_SONAME);
1711 * unmount system call
1714 nfs_unmount(struct mount *mp, int mntflags)
1717 struct nfsmount *nmp;
1718 int error, flags = 0, i, trycnt = 0;
1719 struct nfsclds *dsp, *tdsp;
1723 if (mntflags & MNT_FORCE)
1724 flags |= FORCECLOSE;
1728 * Goes something like this..
1729 * - Call vflush() to clear out vnodes for this filesystem
1730 * - Close the socket
1731 * - Free up the data structures
1733 /* In the forced case, cancel any outstanding requests. */
1734 if (mntflags & MNT_FORCE) {
1736 if (nfsv4_findmirror(nmp) != NULL)
1741 error = newnfs_nmcancelreqs(nmp);
1744 /* For a forced close, get rid of the renew thread now */
1745 nfscl_umount(nmp, td);
1747 /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
1749 error = vflush(mp, 1, flags, td);
1750 if ((mntflags & MNT_FORCE) && error != 0 && ++trycnt < 30)
1751 (void) nfs_catnap(PSOCK, error, "newndm");
1752 } while ((mntflags & MNT_FORCE) && error != 0 && trycnt < 30);
1757 * We are now committed to the unmount.
1759 if ((mntflags & MNT_FORCE) == 0)
1760 nfscl_umount(nmp, td);
1762 mtx_lock(&nmp->nm_mtx);
1763 nmp->nm_privflag |= NFSMNTP_FORCEDISM;
1764 mtx_unlock(&nmp->nm_mtx);
1766 /* Make sure no nfsiods are assigned to this mount. */
1768 for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
1769 if (ncl_iodmount[i] == nmp) {
1770 ncl_iodwant[i] = NFSIOD_AVAILABLE;
1771 ncl_iodmount[i] = NULL;
1776 * We can now set mnt_data to NULL and wait for
1777 * nfssvc(NFSSVC_FORCEDISM) to complete.
1779 mtx_lock(&mountlist_mtx);
1780 mtx_lock(&nmp->nm_mtx);
1781 mp->mnt_data = NULL;
1782 mtx_unlock(&mountlist_mtx);
1783 while ((nmp->nm_privflag & NFSMNTP_CANCELRPCS) != 0)
1784 msleep(nmp, &nmp->nm_mtx, PVFS, "nfsfdism", 0);
1785 mtx_unlock(&nmp->nm_mtx);
1787 newnfs_disconnect(&nmp->nm_sockreq);
1788 crfree(nmp->nm_sockreq.nr_cred);
1789 free(nmp->nm_nam, M_SONAME);
1790 if (nmp->nm_sockreq.nr_auth != NULL)
1791 AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
1792 mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1793 mtx_destroy(&nmp->nm_mtx);
1794 TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp) {
1795 if (dsp != TAILQ_FIRST(&nmp->nm_sess) &&
1796 dsp->nfsclds_sockp != NULL)
1797 newnfs_disconnect(dsp->nfsclds_sockp);
1798 nfscl_freenfsclds(dsp);
1800 free(nmp->nm_tlscertname, M_NEWNFSMNT);
1801 free(nmp, M_NEWNFSMNT);
1807 * Return root of a filesystem
1810 nfs_root(struct mount *mp, int flags, struct vnode **vpp)
1813 struct nfsmount *nmp;
1818 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, flags);
1823 * Get transfer parameters and attributes for root vnode once.
1825 mtx_lock(&nmp->nm_mtx);
1826 if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
1827 mtx_unlock(&nmp->nm_mtx);
1828 ncl_fsinfo(nmp, vp, curthread->td_ucred, curthread);
1830 mtx_unlock(&nmp->nm_mtx);
1831 if (vp->v_type == VNON)
1833 vp->v_vflag |= VV_ROOT;
1839 * Flush out the buffer cache
1843 nfs_sync(struct mount *mp, int waitfor)
1845 struct vnode *vp, *mvp;
1847 int error, allerror = 0;
1853 * If a forced dismount is in progress, return from here so that
1854 * the umount(2) syscall doesn't get stuck in VFS_SYNC() before
1855 * calling VFS_UNMOUNT().
1857 if (NFSCL_FORCEDISM(mp)) {
1864 * Force stale buffer cache information to be flushed.
1867 MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
1868 /* XXX Racy bv_cnt check. */
1869 if (NFSVOPISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
1870 waitfor == MNT_LAZY) {
1874 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK)) {
1875 MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
1878 error = VOP_FSYNC(vp, waitfor, td);
1888 nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
1890 struct nfsmount *nmp = VFSTONFS(mp);
1894 bzero(&vq, sizeof(vq));
1897 case VFS_CTL_NOLOCKS:
1898 val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
1899 if (req->oldptr != NULL) {
1900 error = SYSCTL_OUT(req, &val, sizeof(val));
1904 if (req->newptr != NULL) {
1905 error = SYSCTL_IN(req, &val, sizeof(val));
1909 nmp->nm_flag |= NFSMNT_NOLOCKS;
1911 nmp->nm_flag &= ~NFSMNT_NOLOCKS;
1916 mtx_lock(&nmp->nm_mtx);
1917 if (nmp->nm_state & NFSSTA_TIMEO)
1918 vq.vq_flags |= VQ_NOTRESP;
1919 mtx_unlock(&nmp->nm_mtx);
1921 if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
1922 (nmp->nm_state & NFSSTA_LOCKTIMEO))
1923 vq.vq_flags |= VQ_NOTRESPLOCK;
1925 error = SYSCTL_OUT(req, &vq, sizeof(vq));
1928 if (req->oldptr != NULL) {
1929 error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
1930 sizeof(nmp->nm_tprintf_initial_delay));
1934 if (req->newptr != NULL) {
1935 error = vfs_suser(mp, req->td);
1938 error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
1939 sizeof(nmp->nm_tprintf_initial_delay));
1942 if (nmp->nm_tprintf_initial_delay < 0)
1943 nmp->nm_tprintf_initial_delay = 0;
1953 * Purge any RPCs in progress, so that they will all return errors.
1954 * This allows dounmount() to continue as far as VFS_UNMOUNT() for a
1958 nfs_purge(struct mount *mp)
1960 struct nfsmount *nmp = VFSTONFS(mp);
1962 newnfs_nmcancelreqs(nmp);
1966 * Extract the information needed by the nlm from the nfs vnode.
1969 nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp,
1970 struct sockaddr_storage *sp, int *is_v3p, off_t *sizep,
1971 struct timeval *timeop)
1973 struct nfsmount *nmp;
1974 struct nfsnode *np = VTONFS(vp);
1976 nmp = VFSTONFS(vp->v_mount);
1978 *fhlenp = (size_t)np->n_fhp->nfh_len;
1980 bcopy(np->n_fhp->nfh_fh, fhp, np->n_fhp->nfh_len);
1982 bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp)));
1984 *is_v3p = NFS_ISV3(vp);
1986 *sizep = np->n_size;
1987 if (timeop != NULL) {
1988 timeop->tv_sec = nmp->nm_timeo / NFS_HZ;
1989 timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ);
1994 * This function prints out an option name, based on the conditional
1997 static __inline void nfscl_printopt(struct nfsmount *nmp, int testval,
1998 char *opt, char **buf, size_t *blen)
2002 if (testval != 0 && *blen > strlen(opt)) {
2003 len = snprintf(*buf, *blen, "%s", opt);
2004 if (len != strlen(opt))
2012 * This function printf out an options integer value.
2014 static __inline void nfscl_printoptval(struct nfsmount *nmp, int optval,
2015 char *opt, char **buf, size_t *blen)
2019 if (*blen > strlen(opt) + 1) {
2020 /* Could result in truncated output string. */
2021 len = snprintf(*buf, *blen, "%s=%d", opt, optval);
2030 * Load the option flags and values into the buffer.
2032 void nfscl_retopts(struct nfsmount *nmp, char *buffer, size_t buflen)
2039 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV4) != 0, "nfsv4", &buf,
2041 if ((nmp->nm_flag & NFSMNT_NFSV4) != 0) {
2042 nfscl_printoptval(nmp, nmp->nm_minorvers, ",minorversion", &buf,
2044 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_PNFS) != 0, ",pnfs",
2046 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_ONEOPENOWN) != 0 &&
2047 nmp->nm_minorvers > 0, ",oneopenown", &buf, &blen);
2049 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV3) != 0, "nfsv3", &buf,
2051 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0,
2052 "nfsv2", &buf, &blen);
2053 nfscl_printopt(nmp, nmp->nm_sotype == SOCK_STREAM, ",tcp", &buf, &blen);
2054 nfscl_printopt(nmp, nmp->nm_sotype != SOCK_STREAM, ",udp", &buf, &blen);
2055 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RESVPORT) != 0, ",resvport",
2057 nfscl_printopt(nmp, (nmp->nm_newflag & NFSMNT_TLS) != 0, ",tls", &buf,
2059 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCONN) != 0, ",noconn",
2061 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) == 0, ",hard", &buf,
2063 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) != 0, ",soft", &buf,
2065 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_INT) != 0, ",intr", &buf,
2067 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) == 0, ",cto", &buf,
2069 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) != 0, ",nocto", &buf,
2071 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NONCONTIGWR) != 0,
2072 ",noncontigwr", &buf, &blen);
2073 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
2074 0, ",lockd", &buf, &blen);
2075 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
2076 NFSMNT_NOLOCKD, ",nolockd", &buf, &blen);
2077 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RDIRPLUS) != 0, ",rdirplus",
2079 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_KERB) == 0, ",sec=sys",
2081 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
2082 NFSMNT_PRIVACY)) == NFSMNT_KERB, ",sec=krb5", &buf, &blen);
2083 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
2084 NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_INTEGRITY), ",sec=krb5i",
2086 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
2087 NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_PRIVACY), ",sec=krb5p",
2089 nfscl_printoptval(nmp, nmp->nm_acdirmin, ",acdirmin", &buf, &blen);
2090 nfscl_printoptval(nmp, nmp->nm_acdirmax, ",acdirmax", &buf, &blen);
2091 nfscl_printoptval(nmp, nmp->nm_acregmin, ",acregmin", &buf, &blen);
2092 nfscl_printoptval(nmp, nmp->nm_acregmax, ",acregmax", &buf, &blen);
2093 nfscl_printoptval(nmp, nmp->nm_nametimeo, ",nametimeo", &buf, &blen);
2094 nfscl_printoptval(nmp, nmp->nm_negnametimeo, ",negnametimeo", &buf,
2096 nfscl_printoptval(nmp, nmp->nm_rsize, ",rsize", &buf, &blen);
2097 nfscl_printoptval(nmp, nmp->nm_wsize, ",wsize", &buf, &blen);
2098 nfscl_printoptval(nmp, nmp->nm_readdirsize, ",readdirsize", &buf,
2100 nfscl_printoptval(nmp, nmp->nm_readahead, ",readahead", &buf, &blen);
2101 nfscl_printoptval(nmp, nmp->nm_wcommitsize, ",wcommitsize", &buf,
2103 nfscl_printoptval(nmp, nmp->nm_timeo, ",timeout", &buf, &blen);
2104 nfscl_printoptval(nmp, nmp->nm_retry, ",retrans", &buf, &blen);