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 * @(#)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>
48 #include <sys/limits.h>
50 #include <sys/malloc.h>
52 #include <sys/module.h>
53 #include <sys/mount.h>
55 #include <sys/socket.h>
56 #include <sys/socketvar.h>
57 #include <sys/sockio.h>
58 #include <sys/sysctl.h>
59 #include <sys/syslog.h>
60 #include <sys/vnode.h>
61 #include <sys/signalvar.h>
64 #include <vm/vm_extern.h>
68 #include <net/route.h>
71 #include <netinet/in.h>
75 #include <nfs/nfsproto.h>
76 #include <nfsclient/nfs.h>
77 #include <nfsclient/nfsnode.h>
78 #include <nfsclient/nfsmount.h>
79 #include <nfs/xdr_subs.h>
80 #include <nfsclient/nfsm_subs.h>
81 #include <nfs/nfsdiskless.h>
83 FEATURE(nfsclient, "NFS client");
85 MALLOC_DEFINE(M_NFSREQ, "nfsclient_req", "NFS request header");
86 MALLOC_DEFINE(M_NFSBIGFH, "nfsclient_bigfh", "NFS version 3 file handle");
87 MALLOC_DEFINE(M_NFSDIROFF, "nfsclient_diroff", "NFS directory offset data");
88 MALLOC_DEFINE(M_NFSHASH, "nfsclient_hash", "NFS hash tables");
89 MALLOC_DEFINE(M_NFSDIRECTIO, "nfsclient_directio", "NFS Direct IO async write state");
91 uma_zone_t nfsmount_zone;
93 struct nfsstats nfsstats;
95 SYSCTL_NODE(_vfs, OID_AUTO, oldnfs, CTLFLAG_RW, 0, "Old NFS filesystem");
96 SYSCTL_STRUCT(_vfs_oldnfs, NFS_NFSSTATS, nfsstats, CTLFLAG_RW,
97 &nfsstats, nfsstats, "S,nfsstats");
98 static int nfs_ip_paranoia = 1;
99 SYSCTL_INT(_vfs_oldnfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW,
101 "Disallow accepting replies from IPs which differ from those sent");
104 SYSCTL_INT(_vfs_oldnfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0,
105 "Toggle debug flag");
107 static int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
108 SYSCTL_INT(_vfs_oldnfs, NFS_TPRINTF_INITIAL_DELAY,
109 downdelayinitial, CTLFLAG_RW, &nfs_tprintf_initial_delay, 0,
110 "Delay before printing \"nfs server not responding\" messages");
111 /* how long between console messages "nfs server foo not responding" */
112 static int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
113 SYSCTL_INT(_vfs_oldnfs, NFS_TPRINTF_DELAY,
114 downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0,
115 "Delay between printing \"nfs server not responding\" messages");
117 static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp,
118 struct nfs_args *argp, const char *hostname);
119 static int mountnfs(struct nfs_args *, struct mount *,
120 struct sockaddr *, char *, struct vnode **,
121 struct ucred *cred, int);
122 static void nfs_getnlminfo(struct vnode *, uint8_t *, size_t *,
123 struct sockaddr_storage *, int *, off_t *,
125 static vfs_mount_t nfs_mount;
126 static vfs_cmount_t nfs_cmount;
127 static vfs_unmount_t nfs_unmount;
128 static vfs_root_t nfs_root;
129 static vfs_statfs_t nfs_statfs;
130 static vfs_sync_t nfs_sync;
131 static vfs_sysctl_t nfs_sysctl;
133 static int fake_wchan;
136 * nfs vfs operations.
138 static struct vfsops nfs_vfsops = {
139 .vfs_init = nfs_init,
140 .vfs_mount = nfs_mount,
141 .vfs_cmount = nfs_cmount,
142 .vfs_root = nfs_root,
143 .vfs_statfs = nfs_statfs,
144 .vfs_sync = nfs_sync,
145 .vfs_uninit = nfs_uninit,
146 .vfs_unmount = nfs_unmount,
147 .vfs_sysctl = nfs_sysctl,
149 VFS_SET(nfs_vfsops, oldnfs, VFCF_NETWORK);
151 /* So that loader and kldload(2) can find us, wherever we are.. */
152 MODULE_VERSION(oldnfs, 1);
153 MODULE_DEPEND(oldnfs, krpc, 1, 1, 1);
155 MODULE_DEPEND(oldnfs, kgssapi, 1, 1, 1);
157 MODULE_DEPEND(oldnfs, nfs_common, 1, 1, 1);
158 MODULE_DEPEND(oldnfs, nfslock, 1, 1, 1);
160 static struct nfs_rpcops nfs_rpcops = {
170 * This structure is now defined in sys/nfs/nfs_diskless.c so that it
171 * can be shared by both NFS clients. It is declared here so that it
172 * will be defined for kernels built without NFS_ROOT, although it
173 * isn't used in that case.
176 struct nfs_diskless nfs_diskless = { { { 0 } } };
177 struct nfsv3_diskless nfsv3_diskless = { { { 0 } } };
178 int nfs_diskless_valid = 0;
181 SYSCTL_INT(_vfs_oldnfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
182 &nfs_diskless_valid, 0,
183 "Has the diskless struct been filled correctly");
185 SYSCTL_STRING(_vfs_oldnfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
186 nfsv3_diskless.root_hostnam, 0, "Path to nfs root");
188 SYSCTL_OPAQUE(_vfs_oldnfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
189 &nfsv3_diskless.root_saddr, sizeof nfsv3_diskless.root_saddr,
190 "%Ssockaddr_in", "Diskless root nfs address");
193 void nfsargs_ntoh(struct nfs_args *);
194 static int nfs_mountdiskless(char *,
195 struct sockaddr_in *, struct nfs_args *,
196 struct thread *, struct vnode **, struct mount *);
197 static void nfs_convert_diskless(void);
198 static void nfs_convert_oargs(struct nfs_args *args,
199 struct onfs_args *oargs);
202 nfs_iosize(struct nfsmount *nmp)
207 * Calculate the size used for io buffers. Use the larger
208 * of the two sizes to minimise nfs requests but make sure
209 * that it is at least one VM page to avoid wasting buffer
212 iosize = imax(nmp->nm_rsize, nmp->nm_wsize);
213 iosize = imax(iosize, PAGE_SIZE);
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->maxgrouplist = oargs->maxgrouplist;
235 args->readahead = oargs->readahead;
236 args->deadthresh = oargs->deadthresh;
237 args->hostname = oargs->hostname;
241 nfs_convert_diskless(void)
244 bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
245 sizeof(struct ifaliasreq));
246 bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
247 sizeof(struct sockaddr_in));
248 nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
249 if (nfsv3_diskless.root_args.flags & NFSMNT_NFSV3) {
250 nfsv3_diskless.root_fhsize = NFSX_V3FH;
251 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V3FH);
253 nfsv3_diskless.root_fhsize = NFSX_V2FH;
254 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
256 bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
257 sizeof(struct sockaddr_in));
258 bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN);
259 nfsv3_diskless.root_time = nfs_diskless.root_time;
260 bcopy(nfs_diskless.my_hostnam, nfsv3_diskless.my_hostnam,
262 nfs_diskless_valid = 3;
269 nfs_statfs(struct mount *mp, struct statfs *sbp)
273 struct nfs_statfs *sfp;
275 struct nfsmount *nmp = VFSTONFS(mp);
276 int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr;
277 struct mbuf *mreq, *mrep, *md, *mb;
285 error = vfs_busy(mp, MBF_NOWAIT);
288 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
294 mtx_lock(&nmp->nm_mtx);
295 if (v3 && (nmp->nm_state & NFSSTA_GOTFSINFO) == 0) {
296 mtx_unlock(&nmp->nm_mtx);
297 (void)nfs_fsinfo(nmp, vp, td->td_ucred, td);
299 mtx_unlock(&nmp->nm_mtx);
300 nfsstats.rpccnt[NFSPROC_FSSTAT]++;
301 mreq = nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3));
303 bpos = mtod(mb, caddr_t);
305 nfsm_request(vp, NFSPROC_FSSTAT, td, td->td_ucred);
307 nfsm_postop_attr(vp, retattr);
313 sfp = nfsm_dissect(struct nfs_statfs *, NFSX_STATFS(v3));
314 mtx_lock(&nmp->nm_mtx);
315 sbp->f_iosize = nfs_iosize(nmp);
316 mtx_unlock(&nmp->nm_mtx);
318 sbp->f_bsize = NFS_FABLKSIZE;
319 tquad = fxdr_hyper(&sfp->sf_tbytes);
320 sbp->f_blocks = tquad / NFS_FABLKSIZE;
321 tquad = fxdr_hyper(&sfp->sf_fbytes);
322 sbp->f_bfree = tquad / NFS_FABLKSIZE;
323 tquad = fxdr_hyper(&sfp->sf_abytes);
324 sbp->f_bavail = tquad / NFS_FABLKSIZE;
325 sbp->f_files = (fxdr_unsigned(int32_t,
326 sfp->sf_tfiles.nfsuquad[1]) & 0x7fffffff);
327 sbp->f_ffree = (fxdr_unsigned(int32_t,
328 sfp->sf_ffiles.nfsuquad[1]) & 0x7fffffff);
330 sbp->f_bsize = fxdr_unsigned(int32_t, sfp->sf_bsize);
331 sbp->f_blocks = fxdr_unsigned(int32_t, sfp->sf_blocks);
332 sbp->f_bfree = fxdr_unsigned(int32_t, sfp->sf_bfree);
333 sbp->f_bavail = fxdr_unsigned(int32_t, sfp->sf_bavail);
345 * nfs version 3 fsinfo rpc call
348 nfs_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred,
351 struct nfsv3_fsinfo *fsp;
354 int error = 0, retattr;
355 struct mbuf *mreq, *mrep, *md, *mb;
358 nfsstats.rpccnt[NFSPROC_FSINFO]++;
359 mreq = nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1));
361 bpos = mtod(mb, caddr_t);
363 nfsm_request(vp, NFSPROC_FSINFO, td, cred);
364 nfsm_postop_attr(vp, retattr);
366 fsp = nfsm_dissect(struct nfsv3_fsinfo *, NFSX_V3FSINFO);
367 pref = fxdr_unsigned(u_int32_t, fsp->fs_wtpref);
368 mtx_lock(&nmp->nm_mtx);
369 if (pref < nmp->nm_wsize && pref >= NFS_FABLKSIZE)
370 nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) &
371 ~(NFS_FABLKSIZE - 1);
372 max = fxdr_unsigned(u_int32_t, fsp->fs_wtmax);
373 if (max < nmp->nm_wsize && max > 0) {
374 nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1);
375 if (nmp->nm_wsize == 0)
378 pref = fxdr_unsigned(u_int32_t, fsp->fs_rtpref);
379 if (pref < nmp->nm_rsize && pref >= NFS_FABLKSIZE)
380 nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) &
381 ~(NFS_FABLKSIZE - 1);
382 max = fxdr_unsigned(u_int32_t, fsp->fs_rtmax);
383 if (max < nmp->nm_rsize && max > 0) {
384 nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1);
385 if (nmp->nm_rsize == 0)
388 pref = fxdr_unsigned(u_int32_t, fsp->fs_dtpref);
389 if (pref < nmp->nm_readdirsize && pref >= NFS_DIRBLKSIZ)
390 nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ - 1) &
391 ~(NFS_DIRBLKSIZ - 1);
392 if (max < nmp->nm_readdirsize && max > 0) {
393 nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1);
394 if (nmp->nm_readdirsize == 0)
395 nmp->nm_readdirsize = max;
397 maxfsize = fxdr_hyper(&fsp->fs_maxfilesize);
398 if (maxfsize > 0 && maxfsize < nmp->nm_maxfilesize)
399 nmp->nm_maxfilesize = maxfsize;
400 nmp->nm_mountp->mnt_stat.f_iosize = nfs_iosize(nmp);
401 nmp->nm_state |= NFSSTA_GOTFSINFO;
402 mtx_unlock(&nmp->nm_mtx);
410 * Mount a remote root fs via. nfs. This depends on the info in the
411 * nfs_diskless structure that has been filled in properly by some primary
413 * It goes something like this:
414 * - do enough of "ifconfig" by calling ifioctl() so that the system
415 * can talk to the server
416 * - If nfs_diskless.mygateway is filled in, use that address as
418 * - build the rootfs mount point and call mountnfs() to do the rest.
420 * It is assumed to be safe to read, modify, and write the nfsv3_diskless
421 * structure, as well as other global NFS client variables here, as
422 * nfs_mountroot() will be called once in the boot before any other NFS
423 * client activity occurs.
426 nfs_mountroot(struct mount *mp)
428 struct thread *td = curthread;
429 struct nfsv3_diskless *nd = &nfsv3_diskless;
439 #if defined(BOOTP_NFSROOT) && defined(BOOTP)
440 bootpc_init(); /* use bootp to get nfs_diskless filled in */
441 #elif defined(NFS_ROOT)
442 nfs_setup_diskless();
445 if (nfs_diskless_valid == 0) {
448 if (nfs_diskless_valid == 1)
449 nfs_convert_diskless();
452 * XXX splnet, so networks will receive...
457 * Do enough of ifconfig(8) so that the critical net interface can
458 * talk to the server.
460 error = socreate(nd->myif.ifra_addr.sa_family, &so, nd->root_args.sotype, 0,
463 panic("nfs_mountroot: socreate(%04x): %d",
464 nd->myif.ifra_addr.sa_family, error);
466 #if 0 /* XXX Bad idea */
468 * We might not have been told the right interface, so we pass
469 * over the first ten interfaces of the same kind, until we get
470 * one of them configured.
473 for (i = strlen(nd->myif.ifra_name) - 1;
474 nd->myif.ifra_name[i] >= '0' &&
475 nd->myif.ifra_name[i] <= '9';
476 nd->myif.ifra_name[i] ++) {
477 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
483 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
485 panic("nfs_mountroot: SIOCAIFADDR: %d", error);
487 if ((cp = getenv("boot.netif.mtu")) != NULL) {
488 ir.ifr_mtu = strtol(cp, NULL, 10);
489 bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ);
491 error = ifioctl(so, SIOCSIFMTU, (caddr_t)&ir, td);
493 printf("nfs_mountroot: SIOCSIFMTU: %d", error);
498 * If the gateway field is filled in, set it as the default route.
499 * Note that pxeboot will set a default route of 0 if the route
500 * is not set by the DHCP server. Check also for a value of 0
501 * to avoid panicking inappropriately in that situation.
503 if (nd->mygateway.sin_len != 0 &&
504 nd->mygateway.sin_addr.s_addr != 0) {
505 struct sockaddr_in mask, sin;
507 bzero((caddr_t)&mask, sizeof(mask));
509 sin.sin_family = AF_INET;
510 sin.sin_len = sizeof(sin);
511 /* XXX MRT use table 0 for this sort of thing */
512 CURVNET_SET(TD_TO_VNET(td));
513 error = rtrequest_fib(RTM_ADD, (struct sockaddr *)&sin,
514 (struct sockaddr *)&nd->mygateway,
515 (struct sockaddr *)&mask,
516 RTF_UP | RTF_GATEWAY, NULL, RT_DEFAULT_FIB);
519 panic("nfs_mountroot: RTM_ADD: %d", error);
523 * Create the rootfs mount point.
525 nd->root_args.fh = nd->root_fh;
526 nd->root_args.fhsize = nd->root_fhsize;
527 l = ntohl(nd->root_saddr.sin_addr.s_addr);
528 snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
529 (l >> 24) & 0xff, (l >> 16) & 0xff,
530 (l >> 8) & 0xff, (l >> 0) & 0xff, nd->root_hostnam);
531 printf("NFS ROOT: %s\n", buf);
532 nd->root_args.hostname = buf;
533 if ((error = nfs_mountdiskless(buf,
534 &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) {
539 * This is not really an nfs issue, but it is much easier to
540 * set hostname here and then let the "/etc/rc.xxx" files
541 * mount the right /var based upon its preset value.
543 mtx_lock(&prison0.pr_mtx);
544 strlcpy(prison0.pr_hostname, nd->my_hostnam,
545 sizeof (prison0.pr_hostname));
546 mtx_unlock(&prison0.pr_mtx);
547 inittodr(ntohl(nd->root_time));
552 * Internal version of mount system call for diskless setup.
555 nfs_mountdiskless(char *path,
556 struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
557 struct vnode **vpp, struct mount *mp)
559 struct sockaddr *nam;
562 nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
563 if ((error = mountnfs(args, mp, nam, path, vpp,
564 td->td_ucred, NFS_DEFAULT_NEGNAMETIMEO)) != 0) {
565 printf("nfs_mountroot: mount %s on /: %d\n", path, error);
572 nfs_sec_name_to_num(char *sec)
574 if (!strcmp(sec, "krb5"))
575 return (RPCSEC_GSS_KRB5);
576 if (!strcmp(sec, "krb5i"))
577 return (RPCSEC_GSS_KRB5I);
578 if (!strcmp(sec, "krb5p"))
579 return (RPCSEC_GSS_KRB5P);
580 if (!strcmp(sec, "sys"))
583 * Userland should validate the string but we will try and
584 * cope with unexpected values.
590 nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
591 const char *hostname)
603 * Set read-only flag if requested; otherwise, clear it if this is
604 * an update. If this is not an update, then either the read-only
605 * flag is already clear, or this is a root mount and it was set
606 * intentionally at some previous point.
608 if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) {
610 mp->mnt_flag |= MNT_RDONLY;
612 } else if (mp->mnt_flag & MNT_UPDATE) {
614 mp->mnt_flag &= ~MNT_RDONLY;
619 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
620 * no sense in that context. Also, set up appropriate retransmit
621 * and soft timeout behavior.
623 if (argp->sotype == SOCK_STREAM) {
624 nmp->nm_flag &= ~NFSMNT_NOCONN;
625 nmp->nm_flag |= NFSMNT_DUMBTIMR;
626 nmp->nm_timeo = NFS_MAXTIMEO;
627 nmp->nm_retry = NFS_RETRANS_TCP;
630 /* Also clear RDIRPLUS if not NFSv3, it crashes some servers */
631 if ((argp->flags & NFSMNT_NFSV3) == 0)
632 nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
634 /* Re-bind if rsrvd port requested and wasn't on one */
635 adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
636 && (argp->flags & NFSMNT_RESVPORT);
637 /* Also re-bind if we're switching to/from a connected UDP socket */
638 adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
639 (argp->flags & NFSMNT_NOCONN));
641 /* Update flags atomically. Don't change the lock bits. */
642 nmp->nm_flag = argp->flags | nmp->nm_flag;
645 if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
646 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
647 if (nmp->nm_timeo < NFS_MINTIMEO)
648 nmp->nm_timeo = NFS_MINTIMEO;
649 else if (nmp->nm_timeo > NFS_MAXTIMEO)
650 nmp->nm_timeo = NFS_MAXTIMEO;
653 if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
654 nmp->nm_retry = argp->retrans;
655 if (nmp->nm_retry > NFS_MAXREXMIT)
656 nmp->nm_retry = NFS_MAXREXMIT;
659 if (argp->flags & NFSMNT_NFSV3) {
660 if (argp->sotype == SOCK_DGRAM)
661 maxio = NFS_MAXDGRAMDATA;
665 maxio = NFS_V2MAXDATA;
667 if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
668 nmp->nm_wsize = argp->wsize;
669 /* Round down to multiple of blocksize */
670 nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
671 if (nmp->nm_wsize <= 0)
672 nmp->nm_wsize = NFS_FABLKSIZE;
674 if (nmp->nm_wsize > maxio)
675 nmp->nm_wsize = maxio;
676 if (nmp->nm_wsize > MAXBSIZE)
677 nmp->nm_wsize = MAXBSIZE;
679 if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
680 nmp->nm_rsize = argp->rsize;
681 /* Round down to multiple of blocksize */
682 nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
683 if (nmp->nm_rsize <= 0)
684 nmp->nm_rsize = NFS_FABLKSIZE;
686 if (nmp->nm_rsize > maxio)
687 nmp->nm_rsize = maxio;
688 if (nmp->nm_rsize > MAXBSIZE)
689 nmp->nm_rsize = MAXBSIZE;
691 if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
692 nmp->nm_readdirsize = argp->readdirsize;
694 if (nmp->nm_readdirsize > maxio)
695 nmp->nm_readdirsize = maxio;
696 if (nmp->nm_readdirsize > nmp->nm_rsize)
697 nmp->nm_readdirsize = nmp->nm_rsize;
699 if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
700 nmp->nm_acregmin = argp->acregmin;
702 nmp->nm_acregmin = NFS_MINATTRTIMO;
703 if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
704 nmp->nm_acregmax = argp->acregmax;
706 nmp->nm_acregmax = NFS_MAXATTRTIMO;
707 if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
708 nmp->nm_acdirmin = argp->acdirmin;
710 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
711 if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
712 nmp->nm_acdirmax = argp->acdirmax;
714 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
715 if (nmp->nm_acdirmin > nmp->nm_acdirmax)
716 nmp->nm_acdirmin = nmp->nm_acdirmax;
717 if (nmp->nm_acregmin > nmp->nm_acregmax)
718 nmp->nm_acregmin = nmp->nm_acregmax;
720 if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0) {
721 if (argp->maxgrouplist <= NFS_MAXGRPS)
722 nmp->nm_numgrps = argp->maxgrouplist;
724 nmp->nm_numgrps = NFS_MAXGRPS;
726 if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
727 if (argp->readahead <= NFS_MAXRAHEAD)
728 nmp->nm_readahead = argp->readahead;
730 nmp->nm_readahead = NFS_MAXRAHEAD;
732 if ((argp->flags & NFSMNT_WCOMMITSIZE) && argp->wcommitsize >= 0) {
733 if (argp->wcommitsize < nmp->nm_wsize)
734 nmp->nm_wcommitsize = nmp->nm_wsize;
736 nmp->nm_wcommitsize = argp->wcommitsize;
738 if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 0) {
739 if (argp->deadthresh <= NFS_MAXDEADTHRESH)
740 nmp->nm_deadthresh = argp->deadthresh;
742 nmp->nm_deadthresh = NFS_MAXDEADTHRESH;
745 adjsock |= ((nmp->nm_sotype != argp->sotype) ||
746 (nmp->nm_soproto != argp->proto));
747 nmp->nm_sotype = argp->sotype;
748 nmp->nm_soproto = argp->proto;
750 if (nmp->nm_client && adjsock) {
751 nfs_safedisconnect(nmp);
752 if (nmp->nm_sotype == SOCK_DGRAM)
753 while (nfs_connect(nmp)) {
754 printf("nfs_args: retrying connect\n");
755 (void) tsleep(&fake_wchan, PSOCK, "nfscon", hz);
760 strlcpy(nmp->nm_hostname, hostname,
761 sizeof(nmp->nm_hostname));
762 p = strchr(nmp->nm_hostname, ':');
767 if (vfs_getopt(mp->mnt_optnew, "sec",
768 (void **) &secname, NULL) == 0) {
769 nmp->nm_secflavor = nfs_sec_name_to_num(secname);
771 nmp->nm_secflavor = AUTH_SYS;
774 if (vfs_getopt(mp->mnt_optnew, "principal",
775 (void **) &principal, NULL) == 0) {
776 strlcpy(nmp->nm_principal, principal,
777 sizeof(nmp->nm_principal));
779 snprintf(nmp->nm_principal, sizeof(nmp->nm_principal),
780 "nfs@%s", nmp->nm_hostname);
784 static const char *nfs_opts[] = { "from", "nfs_args",
785 "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
786 "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
787 "async", "dumbtimer", "noconn", "nolockd", "intr", "rdirplus", "resvport",
788 "readahead", "readdirsize", "soft", "hard", "mntudp", "tcp", "udp",
789 "wsize", "rsize", "retrans", "acregmin", "acregmax", "acdirmin",
790 "acdirmax", "deadthresh", "hostname", "timeout", "addr", "fh", "nfsv3",
791 "sec", "maxgroups", "principal", "negnametimeo", "nocto", "wcommitsize",
798 * It seems a bit dumb to copyinstr() the host and path here and then
799 * bcopy() them in mountnfs(), but I wanted to detect errors before
800 * doing the sockargs() call because sockargs() allocates an mbuf and
801 * an error after that means that I have to release the mbuf.
805 nfs_mount(struct mount *mp)
807 struct nfs_args args = {
808 .version = NFS_ARGSVERSION,
810 .addrlen = sizeof (struct sockaddr_in),
811 .sotype = SOCK_STREAM,
815 .flags = NFSMNT_RESVPORT,
818 .readdirsize = NFS_READDIRSIZE,
820 .retrans = NFS_RETRANS,
821 .maxgrouplist = NFS_MAXGRPS,
822 .readahead = NFS_DEFRAHEAD,
823 .wcommitsize = 0, /* was: NQ_DEFLEASE */
824 .deadthresh = NFS_MAXDEADTHRESH, /* was: NQ_DEADTHRESH */
827 .acregmin = NFS_MINATTRTIMO,
828 .acregmax = NFS_MAXATTRTIMO,
829 .acdirmin = NFS_MINDIRATTRTIMO,
830 .acdirmax = NFS_MAXDIRATTRTIMO,
832 int error, ret, has_nfs_args_opt;
833 int has_addr_opt, has_fh_opt, has_hostname_opt;
834 struct sockaddr *nam;
838 u_char nfh[NFSX_V3FHMAX];
840 int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
842 has_nfs_args_opt = 0;
845 has_hostname_opt = 0;
847 if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
852 if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS) {
853 error = nfs_mountroot(mp);
858 * The old mount_nfs program passed the struct nfs_args
859 * from userspace to kernel. The new mount_nfs program
860 * passes string options via nmount() from userspace to kernel
861 * and we populate the struct nfs_args in the kernel.
863 if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
864 error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
869 if (args.version != NFS_ARGSVERSION) {
870 error = EPROGMISMATCH;
873 has_nfs_args_opt = 1;
876 if (vfs_getopt(mp->mnt_optnew, "dumbtimer", NULL, NULL) == 0)
877 args.flags |= NFSMNT_DUMBTIMR;
878 if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
879 args.flags |= NFSMNT_NOCONN;
880 if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
881 args.flags |= NFSMNT_NOCONN;
882 if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
883 args.flags |= NFSMNT_NOLOCKD;
884 if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
885 args.flags &= ~NFSMNT_NOLOCKD;
886 if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
887 args.flags |= NFSMNT_INT;
888 if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
889 args.flags |= NFSMNT_RDIRPLUS;
890 if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
891 args.flags |= NFSMNT_RESVPORT;
892 if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
893 args.flags &= ~NFSMNT_RESVPORT;
894 if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
895 args.flags |= NFSMNT_SOFT;
896 if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
897 args.flags &= ~NFSMNT_SOFT;
898 if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
899 args.sotype = SOCK_DGRAM;
900 if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
901 args.sotype = SOCK_DGRAM;
902 if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
903 args.sotype = SOCK_STREAM;
904 if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
905 args.flags |= NFSMNT_NFSV3;
906 if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0)
907 args.flags |= NFSMNT_NOCTO;
908 if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
910 vfs_mount_error(mp, "illegal readdirsize");
914 ret = sscanf(opt, "%d", &args.readdirsize);
915 if (ret != 1 || args.readdirsize <= 0) {
916 vfs_mount_error(mp, "illegal readdirsize: %s",
921 args.flags |= NFSMNT_READDIRSIZE;
923 if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
925 vfs_mount_error(mp, "illegal readahead");
929 ret = sscanf(opt, "%d", &args.readahead);
930 if (ret != 1 || args.readahead <= 0) {
931 vfs_mount_error(mp, "illegal readahead: %s",
936 args.flags |= NFSMNT_READAHEAD;
938 if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
940 vfs_mount_error(mp, "illegal wsize");
944 ret = sscanf(opt, "%d", &args.wsize);
945 if (ret != 1 || args.wsize <= 0) {
946 vfs_mount_error(mp, "illegal wsize: %s",
951 args.flags |= NFSMNT_WSIZE;
953 if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
955 vfs_mount_error(mp, "illegal rsize");
959 ret = sscanf(opt, "%d", &args.rsize);
960 if (ret != 1 || args.rsize <= 0) {
961 vfs_mount_error(mp, "illegal wsize: %s",
966 args.flags |= NFSMNT_RSIZE;
968 if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
970 vfs_mount_error(mp, "illegal retrans");
974 ret = sscanf(opt, "%d", &args.retrans);
975 if (ret != 1 || args.retrans <= 0) {
976 vfs_mount_error(mp, "illegal retrans: %s",
981 args.flags |= NFSMNT_RETRANS;
983 if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
984 ret = sscanf(opt, "%d", &args.acregmin);
985 if (ret != 1 || args.acregmin < 0) {
986 vfs_mount_error(mp, "illegal acregmin: %s",
991 args.flags |= NFSMNT_ACREGMIN;
993 if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
994 ret = sscanf(opt, "%d", &args.acregmax);
995 if (ret != 1 || args.acregmax < 0) {
996 vfs_mount_error(mp, "illegal acregmax: %s",
1001 args.flags |= NFSMNT_ACREGMAX;
1003 if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
1004 ret = sscanf(opt, "%d", &args.acdirmin);
1005 if (ret != 1 || args.acdirmin < 0) {
1006 vfs_mount_error(mp, "illegal acdirmin: %s",
1011 args.flags |= NFSMNT_ACDIRMIN;
1013 if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
1014 ret = sscanf(opt, "%d", &args.acdirmax);
1015 if (ret != 1 || args.acdirmax < 0) {
1016 vfs_mount_error(mp, "illegal acdirmax: %s",
1021 args.flags |= NFSMNT_ACDIRMAX;
1023 if (vfs_getopt(mp->mnt_optnew, "wcommitsize", (void **)&opt, NULL) == 0) {
1024 ret = sscanf(opt, "%d", &args.wcommitsize);
1025 if (ret != 1 || args.wcommitsize < 0) {
1026 vfs_mount_error(mp, "illegal wcommitsize: %s", opt);
1030 args.flags |= NFSMNT_WCOMMITSIZE;
1032 if (vfs_getopt(mp->mnt_optnew, "deadthresh", (void **)&opt, NULL) == 0) {
1033 ret = sscanf(opt, "%d", &args.deadthresh);
1034 if (ret != 1 || args.deadthresh <= 0) {
1035 vfs_mount_error(mp, "illegal deadthresh: %s",
1040 args.flags |= NFSMNT_DEADTHRESH;
1042 if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
1043 ret = sscanf(opt, "%d", &args.timeo);
1044 if (ret != 1 || args.timeo <= 0) {
1045 vfs_mount_error(mp, "illegal timeout: %s",
1050 args.flags |= NFSMNT_TIMEO;
1052 if (vfs_getopt(mp->mnt_optnew, "maxgroups", (void **)&opt, NULL) == 0) {
1053 ret = sscanf(opt, "%d", &args.maxgrouplist);
1054 if (ret != 1 || args.maxgrouplist <= 0) {
1055 vfs_mount_error(mp, "illegal maxgroups: %s",
1060 args.flags |= NFSMNT_MAXGRPS;
1062 if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
1064 ret = sscanf(opt, "%d", &negnametimeo);
1065 if (ret != 1 || negnametimeo < 0) {
1066 vfs_mount_error(mp, "illegal negnametimeo: %s",
1072 if (vfs_getopt(mp->mnt_optnew, "addr", (void **)&args.addr,
1073 &args.addrlen) == 0) {
1075 if (args.addrlen > SOCK_MAXADDRLEN) {
1076 error = ENAMETOOLONG;
1079 nam = malloc(args.addrlen, M_SONAME,
1081 bcopy(args.addr, nam, args.addrlen);
1082 nam->sa_len = args.addrlen;
1084 if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
1085 &args.fhsize) == 0) {
1088 if (vfs_getopt(mp->mnt_optnew, "hostname", (void **)&args.hostname,
1090 has_hostname_opt = 1;
1092 if (args.hostname == NULL) {
1093 vfs_mount_error(mp, "Invalid hostname");
1097 if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
1098 vfs_mount_error(mp, "Bad file handle");
1103 if (mp->mnt_flag & MNT_UPDATE) {
1104 struct nfsmount *nmp = VFSTONFS(mp);
1112 * If a change from TCP->UDP is done and there are thread(s)
1113 * that have I/O RPC(s) in progress with a tranfer size
1114 * greater than NFS_MAXDGRAMDATA, those thread(s) will be
1115 * hung, retrying the RPC(s) forever. Usually these threads
1116 * will be seen doing an uninterruptible sleep on wait channel
1117 * "newnfsreq" (truncated to "newnfsre" by procstat).
1119 if (args.sotype == SOCK_DGRAM && nmp->nm_sotype == SOCK_STREAM)
1120 tprintf(curthread->td_proc, LOG_WARNING,
1121 "Warning: mount -u that changes TCP->UDP can result in hung threads\n");
1124 * When doing an update, we can't change from or to
1125 * v3, switch lockd strategies or change cookie translation
1127 args.flags = (args.flags &
1128 ~(NFSMNT_NFSV3 | NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
1130 (NFSMNT_NFSV3 | NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
1131 nfs_decode_args(mp, nmp, &args, NULL);
1136 * Make the nfs_ip_paranoia sysctl serve as the default connection
1137 * or no-connection mode for those protocols that support
1138 * no-connection mode (the flag will be cleared later for protocols
1139 * that do not support no-connection mode). This will allow a client
1140 * to receive replies from a different IP then the request was
1141 * sent to. Note: default value for nfs_ip_paranoia is 1 (paranoid),
1144 if (nfs_ip_paranoia == 0)
1145 args.flags |= NFSMNT_NOCONN;
1147 if (has_nfs_args_opt) {
1149 * In the 'nfs_args' case, the pointers in the args
1150 * structure are in userland - we copy them in here.
1153 error = copyin((caddr_t)args.fh, (caddr_t)nfh,
1160 if (!has_hostname_opt) {
1161 error = copyinstr(args.hostname, hst, MNAMELEN-1, &len);
1165 bzero(&hst[len], MNAMELEN - len);
1166 args.hostname = hst;
1168 if (!has_addr_opt) {
1169 /* sockargs() call must be after above copyin() calls */
1170 error = getsockaddr(&nam, (caddr_t)args.addr,
1176 } else if (has_addr_opt == 0) {
1177 vfs_mount_error(mp, "No server address");
1181 error = mountnfs(&args, mp, nam, args.hostname, &vp,
1182 curthread->td_ucred, negnametimeo);
1186 mp->mnt_kern_flag |= (MNTK_MPSAFE|MNTK_LOOKUP_SHARED);
1197 * It seems a bit dumb to copyinstr() the host and path here and then
1198 * bcopy() them in mountnfs(), but I wanted to detect errors before
1199 * doing the sockargs() call because sockargs() allocates an mbuf and
1200 * an error after that means that I have to release the mbuf.
1204 nfs_cmount(struct mntarg *ma, void *data, uint64_t flags)
1207 struct nfs_args args;
1209 error = copyin(data, &args, sizeof (struct nfs_args));
1213 ma = mount_arg(ma, "nfs_args", &args, sizeof args);
1215 error = kernel_mount(ma, flags);
1220 * Common code for mount and mountroot
1223 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
1224 char *hst, struct vnode **vpp, struct ucred *cred, int negnametimeo)
1226 struct nfsmount *nmp;
1231 if (mp->mnt_flag & MNT_UPDATE) {
1233 printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
1234 free(nam, M_SONAME);
1237 nmp = uma_zalloc(nfsmount_zone, M_WAITOK);
1238 bzero((caddr_t)nmp, sizeof (struct nfsmount));
1239 TAILQ_INIT(&nmp->nm_bufq);
1241 nmp->nm_getinfo = nfs_getnlminfo;
1242 nmp->nm_vinvalbuf = nfs_vinvalbuf;
1245 nmp->nm_mountp = mp;
1246 mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF);
1249 * V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too
1250 * high, depending on whether we end up with negative offsets in
1251 * the client or server somewhere. 2GB-1 may be safer.
1253 * For V3, nfs_fsinfo will adjust this as necessary. Assume maximum
1254 * that we can handle until we find out otherwise.
1256 if ((argp->flags & NFSMNT_NFSV3) == 0)
1257 nmp->nm_maxfilesize = 0xffffffffLL;
1259 nmp->nm_maxfilesize = OFF_MAX;
1261 nmp->nm_timeo = NFS_TIMEO;
1262 nmp->nm_retry = NFS_RETRANS;
1263 if ((argp->flags & NFSMNT_NFSV3) && argp->sotype == SOCK_STREAM) {
1264 nmp->nm_wsize = nmp->nm_rsize = NFS_MAXDATA;
1266 nmp->nm_wsize = NFS_WSIZE;
1267 nmp->nm_rsize = NFS_RSIZE;
1269 nmp->nm_wcommitsize = hibufspace / (desiredvnodes / 1000);
1270 nmp->nm_readdirsize = NFS_READDIRSIZE;
1271 nmp->nm_numgrps = NFS_MAXGRPS;
1272 nmp->nm_readahead = NFS_DEFRAHEAD;
1273 nmp->nm_deadthresh = NFS_MAXDEADTHRESH;
1274 nmp->nm_negnametimeo = negnametimeo;
1275 nmp->nm_tprintf_delay = nfs_tprintf_delay;
1276 if (nmp->nm_tprintf_delay < 0)
1277 nmp->nm_tprintf_delay = 0;
1278 nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
1279 if (nmp->nm_tprintf_initial_delay < 0)
1280 nmp->nm_tprintf_initial_delay = 0;
1281 nmp->nm_fhsize = argp->fhsize;
1282 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
1283 bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
1285 /* Set up the sockets and per-host congestion */
1286 nmp->nm_sotype = argp->sotype;
1287 nmp->nm_soproto = argp->proto;
1288 nmp->nm_rpcops = &nfs_rpcops;
1290 nfs_decode_args(mp, nmp, argp, hst);
1293 * For Connection based sockets (TCP,...) defer the connect until
1294 * the first request, in case the server is not responding.
1296 if (nmp->nm_sotype == SOCK_DGRAM &&
1297 (error = nfs_connect(nmp)))
1301 * This is silly, but it has to be set so that vinifod() works.
1302 * We do not want to do an nfs_statfs() here since we can get
1303 * stuck on a dead server and we are holding a lock on the mount
1306 mtx_lock(&nmp->nm_mtx);
1307 mp->mnt_stat.f_iosize = nfs_iosize(nmp);
1308 mtx_unlock(&nmp->nm_mtx);
1310 * A reference count is needed on the nfsnode representing the
1311 * remote root. If this object is not persistent, then backward
1312 * traversals of the mount point (i.e. "..") will not work if
1313 * the nfsnode gets flushed out of the cache. Ufs does not have
1314 * this problem, because one can identify root inodes by their
1315 * number == ROOTINO (2).
1317 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
1323 * Get file attributes and transfer parameters for the
1324 * mountpoint. This has the side effect of filling in
1325 * (*vpp)->v_type with the correct value.
1327 if (argp->flags & NFSMNT_NFSV3)
1328 nfs_fsinfo(nmp, *vpp, curthread->td_ucred, curthread);
1330 VOP_GETATTR(*vpp, &attrs, curthread->td_ucred);
1333 * Lose the lock but keep the ref.
1335 VOP_UNLOCK(*vpp, 0);
1339 nfs_disconnect(nmp);
1340 mtx_destroy(&nmp->nm_mtx);
1341 uma_zfree(nfsmount_zone, nmp);
1342 free(nam, M_SONAME);
1347 * unmount system call
1350 nfs_unmount(struct mount *mp, int mntflags)
1352 struct nfsmount *nmp;
1353 int error, flags = 0;
1355 if (mntflags & MNT_FORCE)
1356 flags |= FORCECLOSE;
1359 * Goes something like this..
1360 * - Call vflush() to clear out vnodes for this filesystem
1361 * - Close the socket
1362 * - Free up the data structures
1364 /* In the forced case, cancel any outstanding requests. */
1365 if (flags & FORCECLOSE) {
1366 error = nfs_nmcancelreqs(nmp);
1370 /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
1371 error = vflush(mp, 1, flags, curthread);
1376 * We are now committed to the unmount.
1378 nfs_disconnect(nmp);
1379 free(nmp->nm_nam, M_SONAME);
1381 mtx_destroy(&nmp->nm_mtx);
1382 uma_zfree(nfsmount_zone, nmp);
1388 * Return root of a filesystem
1391 nfs_root(struct mount *mp, int flags, struct vnode **vpp)
1394 struct nfsmount *nmp;
1399 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, flags);
1404 * Get transfer parameters and attributes for root vnode once.
1406 mtx_lock(&nmp->nm_mtx);
1407 if ((nmp->nm_state & NFSSTA_GOTFSINFO) == 0 &&
1408 (nmp->nm_flag & NFSMNT_NFSV3)) {
1409 mtx_unlock(&nmp->nm_mtx);
1410 nfs_fsinfo(nmp, vp, curthread->td_ucred, curthread);
1412 mtx_unlock(&nmp->nm_mtx);
1413 if (vp->v_type == VNON)
1415 vp->v_vflag |= VV_ROOT;
1421 * Flush out the buffer cache
1425 nfs_sync(struct mount *mp, int waitfor)
1427 struct vnode *vp, *mvp;
1429 int error, allerror = 0;
1435 * If a forced dismount is in progress, return from here so that
1436 * the umount(2) syscall doesn't get stuck in VFS_SYNC() before
1437 * calling VFS_UNMOUNT().
1439 if ((mp->mnt_kern_flag & MNTK_UNMOUNTF) != 0) {
1445 * Force stale buffer cache information to be flushed.
1448 MNT_VNODE_FOREACH(vp, mp, mvp) {
1451 /* XXX Racy bv_cnt check. */
1452 if (VOP_ISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
1453 waitfor == MNT_LAZY) {
1458 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
1460 MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp);
1463 error = VOP_FSYNC(vp, waitfor, td);
1476 nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
1478 struct nfsmount *nmp = VFSTONFS(mp);
1482 bzero(&vq, sizeof(vq));
1485 case VFS_CTL_NOLOCKS:
1486 val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
1487 if (req->oldptr != NULL) {
1488 error = SYSCTL_OUT(req, &val, sizeof(val));
1492 if (req->newptr != NULL) {
1493 error = SYSCTL_IN(req, &val, sizeof(val));
1497 nmp->nm_flag |= NFSMNT_NOLOCKS;
1499 nmp->nm_flag &= ~NFSMNT_NOLOCKS;
1504 mtx_lock(&nmp->nm_mtx);
1505 if (nmp->nm_state & NFSSTA_TIMEO)
1506 vq.vq_flags |= VQ_NOTRESP;
1507 mtx_unlock(&nmp->nm_mtx);
1509 if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
1510 (nmp->nm_state & NFSSTA_LOCKTIMEO))
1511 vq.vq_flags |= VQ_NOTRESPLOCK;
1513 error = SYSCTL_OUT(req, &vq, sizeof(vq));
1516 if (req->oldptr != NULL) {
1517 error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
1518 sizeof(nmp->nm_tprintf_initial_delay));
1522 if (req->newptr != NULL) {
1523 error = vfs_suser(mp, req->td);
1526 error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
1527 sizeof(nmp->nm_tprintf_initial_delay));
1530 if (nmp->nm_tprintf_initial_delay < 0)
1531 nmp->nm_tprintf_initial_delay = 0;
1541 * Extract the information needed by the nlm from the nfs vnode.
1544 nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp,
1545 struct sockaddr_storage *sp, int *is_v3p, off_t *sizep,
1546 struct timeval *timeop)
1548 struct nfsmount *nmp;
1549 struct nfsnode *np = VTONFS(vp);
1551 nmp = VFSTONFS(vp->v_mount);
1553 *fhlenp = (size_t)np->n_fhsize;
1555 bcopy(np->n_fhp, fhp, np->n_fhsize);
1557 bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp)));
1559 *is_v3p = NFS_ISV3(vp);
1561 *sizep = np->n_size;
1562 if (timeop != NULL) {
1563 timeop->tv_sec = nmp->nm_timeo / NFS_HZ;
1564 timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ);