2 * Copyright (c) 1989, 1993, 1995
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 4. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * from nfs_vfsops.c 8.12 (Berkeley) 5/20/95
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
39 #include "opt_bootp.h"
40 #include "opt_nfsroot.h"
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
47 #include <sys/clock.h>
49 #include <sys/limits.h>
51 #include <sys/malloc.h>
53 #include <sys/module.h>
54 #include <sys/mount.h>
56 #include <sys/socket.h>
57 #include <sys/socketvar.h>
58 #include <sys/sockio.h>
59 #include <sys/sysctl.h>
60 #include <sys/vnode.h>
61 #include <sys/signalvar.h>
64 #include <vm/vm_extern.h>
68 #include <net/route.h>
69 #include <netinet/in.h>
71 #include <fs/nfs/nfsport.h>
72 #include <fs/nfsclient/nfsnode.h>
73 #include <fs/nfsclient/nfsmount.h>
74 #include <fs/nfsclient/nfs.h>
75 #include <nfs/nfsdiskless.h>
77 FEATURE(nfscl, "NFSv4 client");
79 extern int nfscl_ticks;
80 extern struct timeval nfsboottime;
81 extern struct nfsstats newnfsstats;
82 extern int nfsrv_useacl;
83 extern int nfscl_debuglevel;
86 MALLOC_DEFINE(M_NEWNFSREQ, "newnfsclient_req", "New NFS request header");
87 MALLOC_DEFINE(M_NEWNFSMNT, "newnfsmnt", "New NFS mount struct");
89 SYSCTL_DECL(_vfs_nfs);
90 static int nfs_ip_paranoia = 1;
91 SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW,
92 &nfs_ip_paranoia, 0, "");
93 static int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
94 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_INITIAL_DELAY,
95 downdelayinitial, CTLFLAG_RW, &nfs_tprintf_initial_delay, 0, "");
96 /* how long between console messages "nfs server foo not responding" */
97 static int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
98 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_DELAY,
99 downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0, "");
101 static int nfs_mountroot(struct mount *);
102 static void nfs_sec_name(char *, int *);
103 static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp,
104 struct nfs_args *argp, const char *, struct ucred *,
106 static int mountnfs(struct nfs_args *, struct mount *,
107 struct sockaddr *, char *, u_char *, int, u_char *, int,
108 u_char *, int, struct vnode **, struct ucred *,
109 struct thread *, int, int, int);
110 static void nfs_getnlminfo(struct vnode *, uint8_t *, size_t *,
111 struct sockaddr_storage *, int *, off_t *,
113 static vfs_mount_t nfs_mount;
114 static vfs_cmount_t nfs_cmount;
115 static vfs_unmount_t nfs_unmount;
116 static vfs_root_t nfs_root;
117 static vfs_statfs_t nfs_statfs;
118 static vfs_sync_t nfs_sync;
119 static vfs_sysctl_t nfs_sysctl;
122 * nfs vfs operations.
124 static struct vfsops nfs_vfsops = {
125 .vfs_init = ncl_init,
126 .vfs_mount = nfs_mount,
127 .vfs_cmount = nfs_cmount,
128 .vfs_root = nfs_root,
129 .vfs_statfs = nfs_statfs,
130 .vfs_sync = nfs_sync,
131 .vfs_uninit = ncl_uninit,
132 .vfs_unmount = nfs_unmount,
133 .vfs_sysctl = nfs_sysctl,
135 VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK | VFCF_SBDRY);
137 /* So that loader and kldload(2) can find us, wherever we are.. */
138 MODULE_VERSION(nfs, 1);
139 MODULE_DEPEND(nfs, nfscommon, 1, 1, 1);
140 MODULE_DEPEND(nfs, krpc, 1, 1, 1);
141 MODULE_DEPEND(nfs, nfssvc, 1, 1, 1);
142 MODULE_DEPEND(nfs, nfslock, 1, 1, 1);
145 * This structure is now defined in sys/nfs/nfs_diskless.c so that it
146 * can be shared by both NFS clients. It is declared here so that it
147 * will be defined for kernels built without NFS_ROOT, although it
148 * isn't used in that case.
150 #if !defined(NFS_ROOT) && !defined(NFSCLIENT)
151 struct nfs_diskless nfs_diskless = { { { 0 } } };
152 struct nfsv3_diskless nfsv3_diskless = { { { 0 } } };
153 int nfs_diskless_valid = 0;
156 SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
157 &nfs_diskless_valid, 0,
158 "Has the diskless struct been filled correctly");
160 SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
161 nfsv3_diskless.root_hostnam, 0, "Path to nfs root");
163 SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
164 &nfsv3_diskless.root_saddr, sizeof(nfsv3_diskless.root_saddr),
165 "%Ssockaddr_in", "Diskless root nfs address");
168 void newnfsargs_ntoh(struct nfs_args *);
169 static int nfs_mountdiskless(char *,
170 struct sockaddr_in *, struct nfs_args *,
171 struct thread *, struct vnode **, struct mount *);
172 static void nfs_convert_diskless(void);
173 static void nfs_convert_oargs(struct nfs_args *args,
174 struct onfs_args *oargs);
177 newnfs_iosize(struct nfsmount *nmp)
181 /* First, set the upper limit for iosize */
182 if (nmp->nm_flag & NFSMNT_NFSV4) {
183 maxio = NFS_MAXBSIZE;
184 } else if (nmp->nm_flag & NFSMNT_NFSV3) {
185 if (nmp->nm_sotype == SOCK_DGRAM)
186 maxio = NFS_MAXDGRAMDATA;
188 maxio = NFS_MAXBSIZE;
190 maxio = NFS_V2MAXDATA;
192 if (nmp->nm_rsize > maxio || nmp->nm_rsize == 0)
193 nmp->nm_rsize = maxio;
194 if (nmp->nm_rsize > MAXBSIZE)
195 nmp->nm_rsize = MAXBSIZE;
196 if (nmp->nm_readdirsize > maxio || nmp->nm_readdirsize == 0)
197 nmp->nm_readdirsize = maxio;
198 if (nmp->nm_readdirsize > nmp->nm_rsize)
199 nmp->nm_readdirsize = nmp->nm_rsize;
200 if (nmp->nm_wsize > maxio || nmp->nm_wsize == 0)
201 nmp->nm_wsize = maxio;
202 if (nmp->nm_wsize > MAXBSIZE)
203 nmp->nm_wsize = MAXBSIZE;
206 * Calculate the size used for io buffers. Use the larger
207 * of the two sizes to minimise nfs requests but make sure
208 * that it is at least one VM page to avoid wasting buffer
211 iosize = imax(nmp->nm_rsize, nmp->nm_wsize);
212 iosize = imax(iosize, PAGE_SIZE);
213 nmp->nm_mountp->mnt_stat.f_iosize = iosize;
218 nfs_convert_oargs(struct nfs_args *args, struct onfs_args *oargs)
221 args->version = NFS_ARGSVERSION;
222 args->addr = oargs->addr;
223 args->addrlen = oargs->addrlen;
224 args->sotype = oargs->sotype;
225 args->proto = oargs->proto;
226 args->fh = oargs->fh;
227 args->fhsize = oargs->fhsize;
228 args->flags = oargs->flags;
229 args->wsize = oargs->wsize;
230 args->rsize = oargs->rsize;
231 args->readdirsize = oargs->readdirsize;
232 args->timeo = oargs->timeo;
233 args->retrans = oargs->retrans;
234 args->readahead = oargs->readahead;
235 args->hostname = oargs->hostname;
239 nfs_convert_diskless(void)
242 bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
243 sizeof(struct ifaliasreq));
244 bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
245 sizeof(struct sockaddr_in));
246 nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
247 if (nfsv3_diskless.root_args.flags & NFSMNT_NFSV3) {
248 nfsv3_diskless.root_fhsize = NFSX_MYFH;
249 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_MYFH);
251 nfsv3_diskless.root_fhsize = NFSX_V2FH;
252 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
254 bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
255 sizeof(struct sockaddr_in));
256 bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN);
257 nfsv3_diskless.root_time = nfs_diskless.root_time;
258 bcopy(nfs_diskless.my_hostnam, nfsv3_diskless.my_hostnam,
260 nfs_diskless_valid = 3;
267 nfs_statfs(struct mount *mp, struct statfs *sbp)
271 struct nfsmount *nmp = VFSTONFS(mp);
272 struct nfsvattr nfsva;
275 int error = 0, attrflag, gotfsinfo = 0, ret;
280 error = vfs_busy(mp, MBF_NOWAIT);
283 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
289 mtx_lock(&nmp->nm_mtx);
290 if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
291 mtx_unlock(&nmp->nm_mtx);
292 error = nfsrpc_fsinfo(vp, &fs, td->td_ucred, td, &nfsva,
297 mtx_unlock(&nmp->nm_mtx);
299 error = nfsrpc_statfs(vp, &sb, &fs, td->td_ucred, td, &nfsva,
302 NFSCL_DEBUG(2, "statfs=%d\n", error);
304 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
305 td->td_ucred, td, &nfsva, NULL, NULL);
308 * Just set default values to get things going.
310 NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
311 nfsva.na_vattr.va_type = VDIR;
312 nfsva.na_vattr.va_mode = 0777;
313 nfsva.na_vattr.va_nlink = 100;
314 nfsva.na_vattr.va_uid = (uid_t)0;
315 nfsva.na_vattr.va_gid = (gid_t)0;
316 nfsva.na_vattr.va_fileid = 2;
317 nfsva.na_vattr.va_gen = 1;
318 nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
319 nfsva.na_vattr.va_size = 512 * 1024;
322 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
324 mtx_lock(&nmp->nm_mtx);
325 if (gotfsinfo || (nmp->nm_flag & NFSMNT_NFSV4))
326 nfscl_loadfsinfo(nmp, &fs);
327 nfscl_loadsbinfo(nmp, &sb, sbp);
328 sbp->f_iosize = newnfs_iosize(nmp);
329 mtx_unlock(&nmp->nm_mtx);
330 if (sbp != &mp->mnt_stat) {
331 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
332 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
334 strncpy(&sbp->f_fstypename[0], mp->mnt_vfc->vfc_name, MFSNAMELEN);
335 } else if (NFS_ISV4(vp)) {
336 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
344 * nfs version 3 fsinfo rpc call
347 ncl_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred,
351 struct nfsvattr nfsva;
354 error = nfsrpc_fsinfo(vp, &fs, cred, td, &nfsva, &attrflag, NULL);
357 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0,
359 mtx_lock(&nmp->nm_mtx);
360 nfscl_loadfsinfo(nmp, &fs);
361 mtx_unlock(&nmp->nm_mtx);
367 * Mount a remote root fs via. nfs. This depends on the info in the
368 * nfs_diskless structure that has been filled in properly by some primary
370 * It goes something like this:
371 * - do enough of "ifconfig" by calling ifioctl() so that the system
372 * can talk to the server
373 * - If nfs_diskless.mygateway is filled in, use that address as
375 * - build the rootfs mount point and call mountnfs() to do the rest.
377 * It is assumed to be safe to read, modify, and write the nfsv3_diskless
378 * structure, as well as other global NFS client variables here, as
379 * nfs_mountroot() will be called once in the boot before any other NFS
380 * client activity occurs.
383 nfs_mountroot(struct mount *mp)
385 struct thread *td = curthread;
386 struct nfsv3_diskless *nd = &nfsv3_diskless;
395 #if defined(BOOTP_NFSROOT) && defined(BOOTP)
396 bootpc_init(); /* use bootp to get nfs_diskless filled in */
397 #elif defined(NFS_ROOT)
398 nfs_setup_diskless();
401 if (nfs_diskless_valid == 0)
403 if (nfs_diskless_valid == 1)
404 nfs_convert_diskless();
407 * XXX splnet, so networks will receive...
412 * Do enough of ifconfig(8) so that the critical net interface can
413 * talk to the server.
415 error = socreate(nd->myif.ifra_addr.sa_family, &so, nd->root_args.sotype, 0,
418 panic("nfs_mountroot: socreate(%04x): %d",
419 nd->myif.ifra_addr.sa_family, error);
421 #if 0 /* XXX Bad idea */
423 * We might not have been told the right interface, so we pass
424 * over the first ten interfaces of the same kind, until we get
425 * one of them configured.
428 for (i = strlen(nd->myif.ifra_name) - 1;
429 nd->myif.ifra_name[i] >= '0' &&
430 nd->myif.ifra_name[i] <= '9';
431 nd->myif.ifra_name[i] ++) {
432 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
437 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
439 panic("nfs_mountroot: SIOCAIFADDR: %d", error);
440 if ((cp = getenv("boot.netif.mtu")) != NULL) {
441 ir.ifr_mtu = strtol(cp, NULL, 10);
442 bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ);
444 error = ifioctl(so, SIOCSIFMTU, (caddr_t)&ir, td);
446 printf("nfs_mountroot: SIOCSIFMTU: %d", error);
451 * If the gateway field is filled in, set it as the default route.
452 * Note that pxeboot will set a default route of 0 if the route
453 * is not set by the DHCP server. Check also for a value of 0
454 * to avoid panicking inappropriately in that situation.
456 if (nd->mygateway.sin_len != 0 &&
457 nd->mygateway.sin_addr.s_addr != 0) {
458 struct sockaddr_in mask, sin;
460 bzero((caddr_t)&mask, sizeof(mask));
462 sin.sin_family = AF_INET;
463 sin.sin_len = sizeof(sin);
464 /* XXX MRT use table 0 for this sort of thing */
465 CURVNET_SET(TD_TO_VNET(td));
466 error = rtrequest_fib(RTM_ADD, (struct sockaddr *)&sin,
467 (struct sockaddr *)&nd->mygateway,
468 (struct sockaddr *)&mask,
469 RTF_UP | RTF_GATEWAY, NULL, RT_DEFAULT_FIB);
472 panic("nfs_mountroot: RTM_ADD: %d", error);
476 * Create the rootfs mount point.
478 nd->root_args.fh = nd->root_fh;
479 nd->root_args.fhsize = nd->root_fhsize;
480 l = ntohl(nd->root_saddr.sin_addr.s_addr);
481 snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
482 (l >> 24) & 0xff, (l >> 16) & 0xff,
483 (l >> 8) & 0xff, (l >> 0) & 0xff, nd->root_hostnam);
484 printf("NFS ROOT: %s\n", buf);
485 nd->root_args.hostname = buf;
486 if ((error = nfs_mountdiskless(buf,
487 &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) {
492 * This is not really an nfs issue, but it is much easier to
493 * set hostname here and then let the "/etc/rc.xxx" files
494 * mount the right /var based upon its preset value.
496 mtx_lock(&prison0.pr_mtx);
497 strlcpy(prison0.pr_hostname, nd->my_hostnam,
498 sizeof(prison0.pr_hostname));
499 mtx_unlock(&prison0.pr_mtx);
500 inittodr(ntohl(nd->root_time));
505 * Internal version of mount system call for diskless setup.
508 nfs_mountdiskless(char *path,
509 struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
510 struct vnode **vpp, struct mount *mp)
512 struct sockaddr *nam;
517 * Find the directory path in "path", which also has the server's
518 * name/ip address in it.
520 dirpath = strchr(path, ':');
522 dirlen = strlen(++dirpath);
525 nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
526 if ((error = mountnfs(args, mp, nam, path, NULL, 0, dirpath, dirlen,
527 NULL, 0, vpp, td->td_ucred, td, NFS_DEFAULT_NAMETIMEO,
528 NFS_DEFAULT_NEGNAMETIMEO, 0)) != 0) {
529 printf("nfs_mountroot: mount %s on /: %d\n", path, error);
536 nfs_sec_name(char *sec, int *flagsp)
538 if (!strcmp(sec, "krb5"))
539 *flagsp |= NFSMNT_KERB;
540 else if (!strcmp(sec, "krb5i"))
541 *flagsp |= (NFSMNT_KERB | NFSMNT_INTEGRITY);
542 else if (!strcmp(sec, "krb5p"))
543 *flagsp |= (NFSMNT_KERB | NFSMNT_PRIVACY);
547 nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
548 const char *hostname, struct ucred *cred, struct thread *td)
557 * Set read-only flag if requested; otherwise, clear it if this is
558 * an update. If this is not an update, then either the read-only
559 * flag is already clear, or this is a root mount and it was set
560 * intentionally at some previous point.
562 if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) {
564 mp->mnt_flag |= MNT_RDONLY;
566 } else if (mp->mnt_flag & MNT_UPDATE) {
568 mp->mnt_flag &= ~MNT_RDONLY;
573 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
574 * no sense in that context. Also, set up appropriate retransmit
575 * and soft timeout behavior.
577 if (argp->sotype == SOCK_STREAM) {
578 nmp->nm_flag &= ~NFSMNT_NOCONN;
579 nmp->nm_timeo = NFS_MAXTIMEO;
580 if ((argp->flags & NFSMNT_NFSV4) != 0)
581 nmp->nm_retry = INT_MAX;
583 nmp->nm_retry = NFS_RETRANS_TCP;
586 /* Also clear RDIRPLUS if NFSv2, it crashes some servers */
587 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
588 argp->flags &= ~NFSMNT_RDIRPLUS;
589 nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
592 /* Clear NFSMNT_RESVPORT for NFSv4, since it is not required. */
593 if ((argp->flags & NFSMNT_NFSV4) != 0) {
594 argp->flags &= ~NFSMNT_RESVPORT;
595 nmp->nm_flag &= ~NFSMNT_RESVPORT;
598 /* Re-bind if rsrvd port requested and wasn't on one */
599 adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
600 && (argp->flags & NFSMNT_RESVPORT);
601 /* Also re-bind if we're switching to/from a connected UDP socket */
602 adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
603 (argp->flags & NFSMNT_NOCONN));
605 /* Update flags atomically. Don't change the lock bits. */
606 nmp->nm_flag = argp->flags | nmp->nm_flag;
609 if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
610 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
611 if (nmp->nm_timeo < NFS_MINTIMEO)
612 nmp->nm_timeo = NFS_MINTIMEO;
613 else if (nmp->nm_timeo > NFS_MAXTIMEO)
614 nmp->nm_timeo = NFS_MAXTIMEO;
617 if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
618 nmp->nm_retry = argp->retrans;
619 if (nmp->nm_retry > NFS_MAXREXMIT)
620 nmp->nm_retry = NFS_MAXREXMIT;
623 if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
624 nmp->nm_wsize = argp->wsize;
625 /* Round down to multiple of blocksize */
626 nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
627 if (nmp->nm_wsize <= 0)
628 nmp->nm_wsize = NFS_FABLKSIZE;
631 if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
632 nmp->nm_rsize = argp->rsize;
633 /* Round down to multiple of blocksize */
634 nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
635 if (nmp->nm_rsize <= 0)
636 nmp->nm_rsize = NFS_FABLKSIZE;
639 if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
640 nmp->nm_readdirsize = argp->readdirsize;
643 if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
644 nmp->nm_acregmin = argp->acregmin;
646 nmp->nm_acregmin = NFS_MINATTRTIMO;
647 if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
648 nmp->nm_acregmax = argp->acregmax;
650 nmp->nm_acregmax = NFS_MAXATTRTIMO;
651 if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
652 nmp->nm_acdirmin = argp->acdirmin;
654 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
655 if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
656 nmp->nm_acdirmax = argp->acdirmax;
658 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
659 if (nmp->nm_acdirmin > nmp->nm_acdirmax)
660 nmp->nm_acdirmin = nmp->nm_acdirmax;
661 if (nmp->nm_acregmin > nmp->nm_acregmax)
662 nmp->nm_acregmin = nmp->nm_acregmax;
664 if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
665 if (argp->readahead <= NFS_MAXRAHEAD)
666 nmp->nm_readahead = argp->readahead;
668 nmp->nm_readahead = NFS_MAXRAHEAD;
670 if ((argp->flags & NFSMNT_WCOMMITSIZE) && argp->wcommitsize >= 0) {
671 if (argp->wcommitsize < nmp->nm_wsize)
672 nmp->nm_wcommitsize = nmp->nm_wsize;
674 nmp->nm_wcommitsize = argp->wcommitsize;
677 adjsock |= ((nmp->nm_sotype != argp->sotype) ||
678 (nmp->nm_soproto != argp->proto));
680 if (nmp->nm_client != NULL && adjsock) {
681 int haslock = 0, error = 0;
683 if (nmp->nm_sotype == SOCK_STREAM) {
684 error = newnfs_sndlock(&nmp->nm_sockreq.nr_lock);
689 newnfs_disconnect(&nmp->nm_sockreq);
691 newnfs_sndunlock(&nmp->nm_sockreq.nr_lock);
692 nmp->nm_sotype = argp->sotype;
693 nmp->nm_soproto = argp->proto;
694 if (nmp->nm_sotype == SOCK_DGRAM)
695 while (newnfs_connect(nmp, &nmp->nm_sockreq,
697 printf("newnfs_args: retrying connect\n");
698 (void) nfs_catnap(PSOCK, 0, "newnfscon");
702 nmp->nm_sotype = argp->sotype;
703 nmp->nm_soproto = argp->proto;
706 if (hostname != NULL) {
707 strlcpy(nmp->nm_hostname, hostname,
708 sizeof(nmp->nm_hostname));
709 p = strchr(nmp->nm_hostname, ':');
715 static const char *nfs_opts[] = { "from", "nfs_args",
716 "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
717 "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
718 "async", "noconn", "nolockd", "conn", "lockd", "intr", "rdirplus",
719 "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize",
720 "retrans", "acregmin", "acregmax", "acdirmin", "acdirmax", "resvport",
721 "readahead", "hostname", "timeout", "addr", "fh", "nfsv3", "sec",
722 "principal", "nfsv4", "gssname", "allgssname", "dirpath", "minorversion",
723 "nametimeo", "negnametimeo", "nocto", "pnfs", "wcommitsize",
730 * It seems a bit dumb to copyinstr() the host and path here and then
731 * bcopy() them in mountnfs(), but I wanted to detect errors before
732 * doing the sockargs() call because sockargs() allocates an mbuf and
733 * an error after that means that I have to release the mbuf.
737 nfs_mount(struct mount *mp)
739 struct nfs_args args = {
740 .version = NFS_ARGSVERSION,
742 .addrlen = sizeof (struct sockaddr_in),
743 .sotype = SOCK_STREAM,
747 .flags = NFSMNT_RESVPORT,
750 .readdirsize = NFS_READDIRSIZE,
752 .retrans = NFS_RETRANS,
753 .readahead = NFS_DEFRAHEAD,
754 .wcommitsize = 0, /* was: NQ_DEFLEASE */
756 .acregmin = NFS_MINATTRTIMO,
757 .acregmax = NFS_MAXATTRTIMO,
758 .acdirmin = NFS_MINDIRATTRTIMO,
759 .acdirmax = NFS_MAXDIRATTRTIMO,
761 int error = 0, ret, len;
762 struct sockaddr *nam = NULL;
766 u_char nfh[NFSX_FHMAX], krbname[100], dirpath[100], srvkrbname[100];
767 char *opt, *name, *secname;
768 int nametimeo = NFS_DEFAULT_NAMETIMEO;
769 int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
771 int dirlen, has_nfs_args_opt, krbnamelen, srvkrbnamelen;
774 has_nfs_args_opt = 0;
775 if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
781 if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS) {
782 error = nfs_mountroot(mp);
789 * The old mount_nfs program passed the struct nfs_args
790 * from userspace to kernel. The new mount_nfs program
791 * passes string options via nmount() from userspace to kernel
792 * and we populate the struct nfs_args in the kernel.
794 if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
795 error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
800 if (args.version != NFS_ARGSVERSION) {
801 error = EPROGMISMATCH;
804 has_nfs_args_opt = 1;
807 /* Handle the new style options. */
808 if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
809 args.flags |= NFSMNT_NOCONN;
810 if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
811 args.flags |= NFSMNT_NOCONN;
812 if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
813 args.flags |= NFSMNT_NOLOCKD;
814 if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
815 args.flags &= ~NFSMNT_NOLOCKD;
816 if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
817 args.flags |= NFSMNT_INT;
818 if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
819 args.flags |= NFSMNT_RDIRPLUS;
820 if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
821 args.flags |= NFSMNT_RESVPORT;
822 if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
823 args.flags &= ~NFSMNT_RESVPORT;
824 if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
825 args.flags |= NFSMNT_SOFT;
826 if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
827 args.flags &= ~NFSMNT_SOFT;
828 if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
829 args.sotype = SOCK_DGRAM;
830 if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
831 args.sotype = SOCK_DGRAM;
832 if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
833 args.sotype = SOCK_STREAM;
834 if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
835 args.flags |= NFSMNT_NFSV3;
836 if (vfs_getopt(mp->mnt_optnew, "nfsv4", NULL, NULL) == 0) {
837 args.flags |= NFSMNT_NFSV4;
838 args.sotype = SOCK_STREAM;
840 if (vfs_getopt(mp->mnt_optnew, "allgssname", NULL, NULL) == 0)
841 args.flags |= NFSMNT_ALLGSSNAME;
842 if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0)
843 args.flags |= NFSMNT_NOCTO;
844 if (vfs_getopt(mp->mnt_optnew, "pnfs", NULL, NULL) == 0)
845 args.flags |= NFSMNT_PNFS;
846 if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
848 vfs_mount_error(mp, "illegal readdirsize");
852 ret = sscanf(opt, "%d", &args.readdirsize);
853 if (ret != 1 || args.readdirsize <= 0) {
854 vfs_mount_error(mp, "illegal readdirsize: %s",
859 args.flags |= NFSMNT_READDIRSIZE;
861 if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
863 vfs_mount_error(mp, "illegal readahead");
867 ret = sscanf(opt, "%d", &args.readahead);
868 if (ret != 1 || args.readahead <= 0) {
869 vfs_mount_error(mp, "illegal readahead: %s",
874 args.flags |= NFSMNT_READAHEAD;
876 if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
878 vfs_mount_error(mp, "illegal wsize");
882 ret = sscanf(opt, "%d", &args.wsize);
883 if (ret != 1 || args.wsize <= 0) {
884 vfs_mount_error(mp, "illegal wsize: %s",
889 args.flags |= NFSMNT_WSIZE;
891 if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
893 vfs_mount_error(mp, "illegal rsize");
897 ret = sscanf(opt, "%d", &args.rsize);
898 if (ret != 1 || args.rsize <= 0) {
899 vfs_mount_error(mp, "illegal wsize: %s",
904 args.flags |= NFSMNT_RSIZE;
906 if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
908 vfs_mount_error(mp, "illegal retrans");
912 ret = sscanf(opt, "%d", &args.retrans);
913 if (ret != 1 || args.retrans <= 0) {
914 vfs_mount_error(mp, "illegal retrans: %s",
919 args.flags |= NFSMNT_RETRANS;
921 if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
922 ret = sscanf(opt, "%d", &args.acregmin);
923 if (ret != 1 || args.acregmin < 0) {
924 vfs_mount_error(mp, "illegal acregmin: %s",
929 args.flags |= NFSMNT_ACREGMIN;
931 if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
932 ret = sscanf(opt, "%d", &args.acregmax);
933 if (ret != 1 || args.acregmax < 0) {
934 vfs_mount_error(mp, "illegal acregmax: %s",
939 args.flags |= NFSMNT_ACREGMAX;
941 if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
942 ret = sscanf(opt, "%d", &args.acdirmin);
943 if (ret != 1 || args.acdirmin < 0) {
944 vfs_mount_error(mp, "illegal acdirmin: %s",
949 args.flags |= NFSMNT_ACDIRMIN;
951 if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
952 ret = sscanf(opt, "%d", &args.acdirmax);
953 if (ret != 1 || args.acdirmax < 0) {
954 vfs_mount_error(mp, "illegal acdirmax: %s",
959 args.flags |= NFSMNT_ACDIRMAX;
961 if (vfs_getopt(mp->mnt_optnew, "wcommitsize", (void **)&opt, NULL) == 0) {
962 ret = sscanf(opt, "%d", &args.wcommitsize);
963 if (ret != 1 || args.wcommitsize < 0) {
964 vfs_mount_error(mp, "illegal wcommitsize: %s", opt);
968 args.flags |= NFSMNT_WCOMMITSIZE;
970 if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
971 ret = sscanf(opt, "%d", &args.timeo);
972 if (ret != 1 || args.timeo <= 0) {
973 vfs_mount_error(mp, "illegal timeout: %s",
978 args.flags |= NFSMNT_TIMEO;
980 if (vfs_getopt(mp->mnt_optnew, "nametimeo", (void **)&opt, NULL) == 0) {
981 ret = sscanf(opt, "%d", &nametimeo);
982 if (ret != 1 || nametimeo < 0) {
983 vfs_mount_error(mp, "illegal nametimeo: %s", opt);
988 if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
990 ret = sscanf(opt, "%d", &negnametimeo);
991 if (ret != 1 || negnametimeo < 0) {
992 vfs_mount_error(mp, "illegal negnametimeo: %s",
998 if (vfs_getopt(mp->mnt_optnew, "minorversion", (void **)&opt, NULL) ==
1000 ret = sscanf(opt, "%d", &minvers);
1001 if (ret != 1 || minvers < 0 || minvers > 1 ||
1002 (args.flags & NFSMNT_NFSV4) == 0) {
1003 vfs_mount_error(mp, "illegal minorversion: %s", opt);
1008 if (vfs_getopt(mp->mnt_optnew, "sec",
1009 (void **) &secname, NULL) == 0)
1010 nfs_sec_name(secname, &args.flags);
1012 if (mp->mnt_flag & MNT_UPDATE) {
1013 struct nfsmount *nmp = VFSTONFS(mp);
1021 * If a change from TCP->UDP is done and there are thread(s)
1022 * that have I/O RPC(s) in progress with a tranfer size
1023 * greater than NFS_MAXDGRAMDATA, those thread(s) will be
1024 * hung, retrying the RPC(s) forever. Usually these threads
1025 * will be seen doing an uninterruptible sleep on wait channel
1026 * "newnfsreq" (truncated to "newnfsre" by procstat).
1028 if (args.sotype == SOCK_DGRAM && nmp->nm_sotype == SOCK_STREAM)
1029 tprintf(td->td_proc, LOG_WARNING,
1030 "Warning: mount -u that changes TCP->UDP can result in hung threads\n");
1033 * When doing an update, we can't change version,
1034 * security, switch lockd strategies or change cookie
1037 args.flags = (args.flags &
1043 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
1050 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
1051 nfs_decode_args(mp, nmp, &args, NULL, td->td_ucred, td);
1056 * Make the nfs_ip_paranoia sysctl serve as the default connection
1057 * or no-connection mode for those protocols that support
1058 * no-connection mode (the flag will be cleared later for protocols
1059 * that do not support no-connection mode). This will allow a client
1060 * to receive replies from a different IP then the request was
1061 * sent to. Note: default value for nfs_ip_paranoia is 1 (paranoid),
1064 if (nfs_ip_paranoia == 0)
1065 args.flags |= NFSMNT_NOCONN;
1067 if (has_nfs_args_opt != 0) {
1069 * In the 'nfs_args' case, the pointers in the args
1070 * structure are in userland - we copy them in here.
1072 if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
1073 vfs_mount_error(mp, "Bad file handle");
1077 error = copyin((caddr_t)args.fh, (caddr_t)nfh,
1081 error = copyinstr(args.hostname, hst, MNAMELEN - 1, &hstlen);
1084 bzero(&hst[hstlen], MNAMELEN - hstlen);
1085 args.hostname = hst;
1086 /* sockargs() call must be after above copyin() calls */
1087 error = getsockaddr(&nam, (caddr_t)args.addr,
1092 if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
1093 &args.fhsize) == 0) {
1094 if (args.fhsize < 0 || args.fhsize > NFSX_FHMAX) {
1095 vfs_mount_error(mp, "Bad file handle");
1099 bcopy(args.fh, nfh, args.fhsize);
1103 (void) vfs_getopt(mp->mnt_optnew, "hostname",
1104 (void **)&args.hostname, &len);
1105 if (args.hostname == NULL) {
1106 vfs_mount_error(mp, "Invalid hostname");
1110 bcopy(args.hostname, hst, MNAMELEN);
1111 hst[MNAMELEN - 1] = '\0';
1114 if (vfs_getopt(mp->mnt_optnew, "principal", (void **)&name, NULL) == 0)
1115 strlcpy(srvkrbname, name, sizeof (srvkrbname));
1117 snprintf(srvkrbname, sizeof (srvkrbname), "nfs@%s", hst);
1118 srvkrbnamelen = strlen(srvkrbname);
1120 if (vfs_getopt(mp->mnt_optnew, "gssname", (void **)&name, NULL) == 0)
1121 strlcpy(krbname, name, sizeof (krbname));
1124 krbnamelen = strlen(krbname);
1126 if (vfs_getopt(mp->mnt_optnew, "dirpath", (void **)&name, NULL) == 0)
1127 strlcpy(dirpath, name, sizeof (dirpath));
1130 dirlen = strlen(dirpath);
1132 if (has_nfs_args_opt == 0) {
1133 if (vfs_getopt(mp->mnt_optnew, "addr",
1134 (void **)&args.addr, &args.addrlen) == 0) {
1135 if (args.addrlen > SOCK_MAXADDRLEN) {
1136 error = ENAMETOOLONG;
1139 nam = malloc(args.addrlen, M_SONAME, M_WAITOK);
1140 bcopy(args.addr, nam, args.addrlen);
1141 nam->sa_len = args.addrlen;
1143 vfs_mount_error(mp, "No server address");
1150 error = mountnfs(&args, mp, nam, hst, krbname, krbnamelen, dirpath,
1151 dirlen, srvkrbname, srvkrbnamelen, &vp, td->td_ucred, td,
1152 nametimeo, negnametimeo, minvers);
1156 mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED | MNTK_NO_IOPF;
1167 * It seems a bit dumb to copyinstr() the host and path here and then
1168 * bcopy() them in mountnfs(), but I wanted to detect errors before
1169 * doing the sockargs() call because sockargs() allocates an mbuf and
1170 * an error after that means that I have to release the mbuf.
1174 nfs_cmount(struct mntarg *ma, void *data, uint64_t flags)
1177 struct nfs_args args;
1179 error = copyin(data, &args, sizeof (struct nfs_args));
1183 ma = mount_arg(ma, "nfs_args", &args, sizeof args);
1185 error = kernel_mount(ma, flags);
1190 * Common code for mount and mountroot
1193 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
1194 char *hst, u_char *krbname, int krbnamelen, u_char *dirpath, int dirlen,
1195 u_char *srvkrbname, int srvkrbnamelen, struct vnode **vpp,
1196 struct ucred *cred, struct thread *td, int nametimeo, int negnametimeo,
1199 struct nfsmount *nmp;
1201 int error, trycnt, ret;
1202 struct nfsvattr nfsva;
1203 struct nfsclclient *clp;
1204 struct nfsclds *dsp, *tdsp;
1206 static u_int64_t clval = 0;
1208 NFSCL_DEBUG(3, "in mnt\n");
1210 if (mp->mnt_flag & MNT_UPDATE) {
1212 printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
1213 FREE(nam, M_SONAME);
1216 MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount) +
1217 krbnamelen + dirlen + srvkrbnamelen + 2,
1218 M_NEWNFSMNT, M_WAITOK | M_ZERO);
1219 TAILQ_INIT(&nmp->nm_bufq);
1221 clval = (u_int64_t)nfsboottime.tv_sec;
1222 nmp->nm_clval = clval++;
1223 nmp->nm_krbnamelen = krbnamelen;
1224 nmp->nm_dirpathlen = dirlen;
1225 nmp->nm_srvkrbnamelen = srvkrbnamelen;
1226 if (td->td_ucred->cr_uid != (uid_t)0) {
1228 * nm_uid is used to get KerberosV credentials for
1229 * the nfsv4 state handling operations if there is
1230 * no host based principal set. Use the uid of
1231 * this user if not root, since they are doing the
1232 * mount. I don't think setting this for root will
1233 * work, since root normally does not have user
1234 * credentials in a credentials cache.
1236 nmp->nm_uid = td->td_ucred->cr_uid;
1239 * Just set to -1, so it won't be used.
1241 nmp->nm_uid = (uid_t)-1;
1244 /* Copy and null terminate all the names */
1245 if (nmp->nm_krbnamelen > 0) {
1246 bcopy(krbname, nmp->nm_krbname, nmp->nm_krbnamelen);
1247 nmp->nm_name[nmp->nm_krbnamelen] = '\0';
1249 if (nmp->nm_dirpathlen > 0) {
1250 bcopy(dirpath, NFSMNT_DIRPATH(nmp),
1251 nmp->nm_dirpathlen);
1252 nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1255 if (nmp->nm_srvkrbnamelen > 0) {
1256 bcopy(srvkrbname, NFSMNT_SRVKRBNAME(nmp),
1257 nmp->nm_srvkrbnamelen);
1258 nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1259 + nmp->nm_srvkrbnamelen + 2] = '\0';
1261 nmp->nm_sockreq.nr_cred = crhold(cred);
1262 mtx_init(&nmp->nm_sockreq.nr_mtx, "nfssock", NULL, MTX_DEF);
1264 nmp->nm_getinfo = nfs_getnlminfo;
1265 nmp->nm_vinvalbuf = ncl_vinvalbuf;
1268 nmp->nm_mountp = mp;
1269 mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF | MTX_DUPOK);
1272 * Since nfs_decode_args() might optionally set them, these
1273 * need to be set to defaults before the call, so that the
1274 * optional settings aren't overwritten.
1276 nmp->nm_nametimeo = nametimeo;
1277 nmp->nm_negnametimeo = negnametimeo;
1278 nmp->nm_timeo = NFS_TIMEO;
1279 nmp->nm_retry = NFS_RETRANS;
1280 nmp->nm_readahead = NFS_DEFRAHEAD;
1281 if (desiredvnodes >= 11000)
1282 nmp->nm_wcommitsize = hibufspace / (desiredvnodes / 1000);
1284 nmp->nm_wcommitsize = hibufspace / 10;
1285 if ((argp->flags & NFSMNT_NFSV4) != 0)
1286 nmp->nm_minorvers = minvers;
1288 nmp->nm_minorvers = 0;
1290 nfs_decode_args(mp, nmp, argp, hst, cred, td);
1293 * V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too
1294 * high, depending on whether we end up with negative offsets in
1295 * the client or server somewhere. 2GB-1 may be safer.
1297 * For V3, ncl_fsinfo will adjust this as necessary. Assume maximum
1298 * that we can handle until we find out otherwise.
1300 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0)
1301 nmp->nm_maxfilesize = 0xffffffffLL;
1303 nmp->nm_maxfilesize = OFF_MAX;
1305 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
1306 nmp->nm_wsize = NFS_WSIZE;
1307 nmp->nm_rsize = NFS_RSIZE;
1308 nmp->nm_readdirsize = NFS_READDIRSIZE;
1310 nmp->nm_numgrps = NFS_MAXGRPS;
1311 nmp->nm_tprintf_delay = nfs_tprintf_delay;
1312 if (nmp->nm_tprintf_delay < 0)
1313 nmp->nm_tprintf_delay = 0;
1314 nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
1315 if (nmp->nm_tprintf_initial_delay < 0)
1316 nmp->nm_tprintf_initial_delay = 0;
1317 nmp->nm_fhsize = argp->fhsize;
1318 if (nmp->nm_fhsize > 0)
1319 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
1320 bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
1322 /* Set up the sockets and per-host congestion */
1323 nmp->nm_sotype = argp->sotype;
1324 nmp->nm_soproto = argp->proto;
1325 nmp->nm_sockreq.nr_prog = NFS_PROG;
1326 if ((argp->flags & NFSMNT_NFSV4))
1327 nmp->nm_sockreq.nr_vers = NFS_VER4;
1328 else if ((argp->flags & NFSMNT_NFSV3))
1329 nmp->nm_sockreq.nr_vers = NFS_VER3;
1331 nmp->nm_sockreq.nr_vers = NFS_VER2;
1334 if ((error = newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0)))
1336 /* For NFSv4.1, get the clientid now. */
1337 if (nmp->nm_minorvers > 0) {
1338 NFSCL_DEBUG(3, "at getcl\n");
1339 error = nfscl_getcl(mp, cred, td, 0, &clp);
1340 NFSCL_DEBUG(3, "aft getcl=%d\n", error);
1345 if (nmp->nm_fhsize == 0 && (nmp->nm_flag & NFSMNT_NFSV4) &&
1346 nmp->nm_dirpathlen > 0) {
1347 NFSCL_DEBUG(3, "in dirp\n");
1349 * If the fhsize on the mount point == 0 for V4, the mount
1350 * path needs to be looked up.
1354 error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp),
1356 NFSCL_DEBUG(3, "aft dirp=%d\n", error);
1358 (void) nfs_catnap(PZERO, error, "nfsgetdirp");
1359 } while (error && --trycnt > 0);
1361 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
1367 * A reference count is needed on the nfsnode representing the
1368 * remote root. If this object is not persistent, then backward
1369 * traversals of the mount point (i.e. "..") will not work if
1370 * the nfsnode gets flushed out of the cache. Ufs does not have
1371 * this problem, because one can identify root inodes by their
1372 * number == ROOTINO (2).
1374 if (nmp->nm_fhsize > 0) {
1376 * Set f_iosize to NFS_DIRBLKSIZ so that bo_bsize gets set
1377 * non-zero for the root vnode. f_iosize will be set correctly
1378 * by nfs_statfs() before any I/O occurs.
1380 mp->mnt_stat.f_iosize = NFS_DIRBLKSIZ;
1381 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np,
1388 * Get file attributes and transfer parameters for the
1389 * mountpoint. This has the side effect of filling in
1390 * (*vpp)->v_type with the correct value.
1392 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
1393 cred, td, &nfsva, NULL, &lease);
1396 * Just set default values to get things going.
1398 NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
1399 nfsva.na_vattr.va_type = VDIR;
1400 nfsva.na_vattr.va_mode = 0777;
1401 nfsva.na_vattr.va_nlink = 100;
1402 nfsva.na_vattr.va_uid = (uid_t)0;
1403 nfsva.na_vattr.va_gid = (gid_t)0;
1404 nfsva.na_vattr.va_fileid = 2;
1405 nfsva.na_vattr.va_gen = 1;
1406 nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
1407 nfsva.na_vattr.va_size = 512 * 1024;
1410 (void) nfscl_loadattrcache(vpp, &nfsva, NULL, NULL, 0, 1);
1411 if (nmp->nm_minorvers > 0) {
1412 NFSCL_DEBUG(3, "lease=%d\n", (int)lease);
1414 clp->nfsc_renew = NFSCL_RENEW(lease);
1415 clp->nfsc_expire = NFSD_MONOSEC + clp->nfsc_renew;
1416 clp->nfsc_clientidrev++;
1417 if (clp->nfsc_clientidrev == 0)
1418 clp->nfsc_clientidrev++;
1421 * Mount will succeed, so the renew thread can be
1424 nfscl_start_renewthread(clp);
1425 nfscl_clientrelease(clp);
1427 if (argp->flags & NFSMNT_NFSV3)
1428 ncl_fsinfo(nmp, *vpp, cred, td);
1430 /* Mark if the mount point supports NFSv4 ACLs. */
1431 if ((argp->flags & NFSMNT_NFSV4) != 0 && nfsrv_useacl != 0 &&
1433 NFSISSET_ATTRBIT(&nfsva.na_suppattr, NFSATTRBIT_ACL)) {
1435 mp->mnt_flag |= MNT_NFS4ACLS;
1440 * Lose the lock but keep the ref.
1442 NFSVOPUNLOCK(*vpp, 0);
1449 nfscl_clientrelease(clp);
1450 newnfs_disconnect(&nmp->nm_sockreq);
1451 crfree(nmp->nm_sockreq.nr_cred);
1452 mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1453 mtx_destroy(&nmp->nm_mtx);
1454 if (nmp->nm_clp != NULL) {
1456 LIST_REMOVE(nmp->nm_clp, nfsc_list);
1458 free(nmp->nm_clp, M_NFSCLCLIENT);
1460 TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp)
1461 nfscl_freenfsclds(dsp);
1462 FREE(nmp, M_NEWNFSMNT);
1463 FREE(nam, M_SONAME);
1468 * unmount system call
1471 nfs_unmount(struct mount *mp, int mntflags)
1474 struct nfsmount *nmp;
1475 int error, flags = 0, trycnt = 0;
1476 struct nfsclds *dsp, *tdsp;
1480 if (mntflags & MNT_FORCE)
1481 flags |= FORCECLOSE;
1484 * Goes something like this..
1485 * - Call vflush() to clear out vnodes for this filesystem
1486 * - Close the socket
1487 * - Free up the data structures
1489 /* In the forced case, cancel any outstanding requests. */
1490 if (mntflags & MNT_FORCE) {
1491 error = newnfs_nmcancelreqs(nmp);
1494 /* For a forced close, get rid of the renew thread now */
1495 nfscl_umount(nmp, td);
1497 /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
1499 error = vflush(mp, 1, flags, td);
1500 if ((mntflags & MNT_FORCE) && error != 0 && ++trycnt < 30)
1501 (void) nfs_catnap(PSOCK, error, "newndm");
1502 } while ((mntflags & MNT_FORCE) && error != 0 && trycnt < 30);
1507 * We are now committed to the unmount.
1509 if ((mntflags & MNT_FORCE) == 0)
1510 nfscl_umount(nmp, td);
1511 newnfs_disconnect(&nmp->nm_sockreq);
1512 crfree(nmp->nm_sockreq.nr_cred);
1513 FREE(nmp->nm_nam, M_SONAME);
1515 mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1516 mtx_destroy(&nmp->nm_mtx);
1517 TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp)
1518 nfscl_freenfsclds(dsp);
1519 FREE(nmp, M_NEWNFSMNT);
1525 * Return root of a filesystem
1528 nfs_root(struct mount *mp, int flags, struct vnode **vpp)
1531 struct nfsmount *nmp;
1536 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, flags);
1541 * Get transfer parameters and attributes for root vnode once.
1543 mtx_lock(&nmp->nm_mtx);
1544 if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
1545 mtx_unlock(&nmp->nm_mtx);
1546 ncl_fsinfo(nmp, vp, curthread->td_ucred, curthread);
1548 mtx_unlock(&nmp->nm_mtx);
1549 if (vp->v_type == VNON)
1551 vp->v_vflag |= VV_ROOT;
1557 * Flush out the buffer cache
1561 nfs_sync(struct mount *mp, int waitfor)
1563 struct vnode *vp, *mvp;
1565 int error, allerror = 0;
1571 * If a forced dismount is in progress, return from here so that
1572 * the umount(2) syscall doesn't get stuck in VFS_SYNC() before
1573 * calling VFS_UNMOUNT().
1575 if ((mp->mnt_kern_flag & MNTK_UNMOUNTF) != 0) {
1582 * Force stale buffer cache information to be flushed.
1585 MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
1586 /* XXX Racy bv_cnt check. */
1587 if (NFSVOPISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
1588 waitfor == MNT_LAZY) {
1592 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
1593 MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
1596 error = VOP_FSYNC(vp, waitfor, td);
1599 NFSVOPUNLOCK(vp, 0);
1606 nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
1608 struct nfsmount *nmp = VFSTONFS(mp);
1612 bzero(&vq, sizeof(vq));
1615 case VFS_CTL_NOLOCKS:
1616 val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
1617 if (req->oldptr != NULL) {
1618 error = SYSCTL_OUT(req, &val, sizeof(val));
1622 if (req->newptr != NULL) {
1623 error = SYSCTL_IN(req, &val, sizeof(val));
1627 nmp->nm_flag |= NFSMNT_NOLOCKS;
1629 nmp->nm_flag &= ~NFSMNT_NOLOCKS;
1634 mtx_lock(&nmp->nm_mtx);
1635 if (nmp->nm_state & NFSSTA_TIMEO)
1636 vq.vq_flags |= VQ_NOTRESP;
1637 mtx_unlock(&nmp->nm_mtx);
1639 if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
1640 (nmp->nm_state & NFSSTA_LOCKTIMEO))
1641 vq.vq_flags |= VQ_NOTRESPLOCK;
1643 error = SYSCTL_OUT(req, &vq, sizeof(vq));
1646 if (req->oldptr != NULL) {
1647 error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
1648 sizeof(nmp->nm_tprintf_initial_delay));
1652 if (req->newptr != NULL) {
1653 error = vfs_suser(mp, req->td);
1656 error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
1657 sizeof(nmp->nm_tprintf_initial_delay));
1660 if (nmp->nm_tprintf_initial_delay < 0)
1661 nmp->nm_tprintf_initial_delay = 0;
1671 * Extract the information needed by the nlm from the nfs vnode.
1674 nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp,
1675 struct sockaddr_storage *sp, int *is_v3p, off_t *sizep,
1676 struct timeval *timeop)
1678 struct nfsmount *nmp;
1679 struct nfsnode *np = VTONFS(vp);
1681 nmp = VFSTONFS(vp->v_mount);
1683 *fhlenp = (size_t)np->n_fhp->nfh_len;
1685 bcopy(np->n_fhp->nfh_fh, fhp, np->n_fhp->nfh_len);
1687 bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp)));
1689 *is_v3p = NFS_ISV3(vp);
1691 *sizep = np->n_size;
1692 if (timeop != NULL) {
1693 timeop->tv_sec = nmp->nm_timeo / NFS_HZ;
1694 timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ);
1699 * This function prints out an option name, based on the conditional
1702 static __inline void nfscl_printopt(struct nfsmount *nmp, int testval,
1703 char *opt, char **buf, size_t *blen)
1707 if (testval != 0 && *blen > strlen(opt)) {
1708 len = snprintf(*buf, *blen, "%s", opt);
1709 if (len != strlen(opt))
1717 * This function printf out an options integer value.
1719 static __inline void nfscl_printoptval(struct nfsmount *nmp, int optval,
1720 char *opt, char **buf, size_t *blen)
1724 if (*blen > strlen(opt) + 1) {
1725 /* Could result in truncated output string. */
1726 len = snprintf(*buf, *blen, "%s=%d", opt, optval);
1735 * Load the option flags and values into the buffer.
1737 void nfscl_retopts(struct nfsmount *nmp, char *buffer, size_t buflen)
1744 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV4) != 0, "nfsv4", &buf,
1746 if ((nmp->nm_flag & NFSMNT_NFSV4) != 0) {
1747 nfscl_printoptval(nmp, nmp->nm_minorvers, ",minorversion", &buf,
1749 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_PNFS) != 0, ",pnfs",
1752 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV3) != 0, "nfsv3", &buf,
1754 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0,
1755 "nfsv2", &buf, &blen);
1756 nfscl_printopt(nmp, nmp->nm_sotype == SOCK_STREAM, ",tcp", &buf, &blen);
1757 nfscl_printopt(nmp, nmp->nm_sotype != SOCK_STREAM, ",udp", &buf, &blen);
1758 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RESVPORT) != 0, ",resvport",
1760 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCONN) != 0, ",noconn",
1762 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) == 0, ",hard", &buf,
1764 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) != 0, ",soft", &buf,
1766 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_INT) != 0, ",intr", &buf,
1768 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) == 0, ",cto", &buf,
1770 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) != 0, ",nocto", &buf,
1772 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
1773 0, ",lockd", &buf, &blen);
1774 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
1775 NFSMNT_NOLOCKD, ",nolockd", &buf, &blen);
1776 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RDIRPLUS) != 0, ",rdirplus",
1778 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_KERB) == 0, ",sec=sys",
1780 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
1781 NFSMNT_PRIVACY)) == NFSMNT_KERB, ",sec=krb5", &buf, &blen);
1782 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
1783 NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_INTEGRITY), ",sec=krb5i",
1785 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
1786 NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_PRIVACY), ",sec=krb5p",
1788 nfscl_printoptval(nmp, nmp->nm_acdirmin, ",acdirmin", &buf, &blen);
1789 nfscl_printoptval(nmp, nmp->nm_acdirmax, ",acdirmax", &buf, &blen);
1790 nfscl_printoptval(nmp, nmp->nm_acregmin, ",acregmin", &buf, &blen);
1791 nfscl_printoptval(nmp, nmp->nm_acregmax, ",acregmax", &buf, &blen);
1792 nfscl_printoptval(nmp, nmp->nm_nametimeo, ",nametimeo", &buf, &blen);
1793 nfscl_printoptval(nmp, nmp->nm_negnametimeo, ",negnametimeo", &buf,
1795 nfscl_printoptval(nmp, nmp->nm_rsize, ",rsize", &buf, &blen);
1796 nfscl_printoptval(nmp, nmp->nm_wsize, ",wsize", &buf, &blen);
1797 nfscl_printoptval(nmp, nmp->nm_readdirsize, ",readdirsize", &buf,
1799 nfscl_printoptval(nmp, nmp->nm_readahead, ",readahead", &buf, &blen);
1800 nfscl_printoptval(nmp, nmp->nm_wcommitsize, ",wcommitsize", &buf,
1802 nfscl_printoptval(nmp, nmp->nm_timeo, ",timeout", &buf, &blen);
1803 nfscl_printoptval(nmp, nmp->nm_retry, ",retrans", &buf, &blen);