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>
49 #include <sys/malloc.h>
51 #include <sys/module.h>
52 #include <sys/mount.h>
54 #include <sys/socket.h>
55 #include <sys/socketvar.h>
56 #include <sys/sockio.h>
57 #include <sys/sysctl.h>
58 #include <sys/vnode.h>
59 #include <sys/signalvar.h>
62 #include <vm/vm_extern.h>
66 #include <net/route.h>
69 #include <netinet/in.h>
73 #include <nfs/nfsproto.h>
74 #include <nfsclient/nfs.h>
75 #include <nfsclient/nfsnode.h>
76 #include <nfsclient/nfsmount.h>
77 #include <nfs/xdr_subs.h>
78 #include <nfsclient/nfsm_subs.h>
79 #include <nfsclient/nfsdiskless.h>
81 MALLOC_DEFINE(M_NFSREQ, "nfsclient_req", "NFS request header");
82 MALLOC_DEFINE(M_NFSBIGFH, "nfsclient_bigfh", "NFS version 3 file handle");
83 MALLOC_DEFINE(M_NFSDIROFF, "nfsclient_diroff", "NFS directory offset data");
84 MALLOC_DEFINE(M_NFSHASH, "nfsclient_hash", "NFS hash tables");
85 MALLOC_DEFINE(M_NFSDIRECTIO, "nfsclient_directio", "NFS Direct IO async write state");
87 uma_zone_t nfsmount_zone;
89 struct nfsstats nfsstats;
91 SYSCTL_NODE(_vfs, OID_AUTO, nfs, CTLFLAG_RW, 0, "NFS filesystem");
92 SYSCTL_STRUCT(_vfs_nfs, NFS_NFSSTATS, nfsstats, CTLFLAG_RW,
93 &nfsstats, nfsstats, "S,nfsstats");
94 static int nfs_ip_paranoia = 1;
95 SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW,
97 "Disallow accepting replies from IPs which differ from those sent");
100 SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0,
101 "Toggle debug flag");
103 static int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
104 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_INITIAL_DELAY,
105 downdelayinitial, CTLFLAG_RW, &nfs_tprintf_initial_delay, 0,
106 "Delay before printing \"nfs server not responding\" messages");
107 /* how long between console messages "nfs server foo not responding" */
108 static int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
109 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_DELAY,
110 downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0,
111 "Delay between printing \"nfs server not responding\" messages");
113 static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp,
114 struct nfs_args *argp, const char *hostname);
115 static int mountnfs(struct nfs_args *, struct mount *,
116 struct sockaddr *, char *, struct vnode **,
117 struct ucred *cred, int);
118 static vfs_mount_t nfs_mount;
119 static vfs_cmount_t nfs_cmount;
120 static vfs_unmount_t nfs_unmount;
121 static vfs_root_t nfs_root;
122 static vfs_statfs_t nfs_statfs;
123 static vfs_sync_t nfs_sync;
124 static vfs_sysctl_t nfs_sysctl;
126 static int fake_wchan;
129 * nfs vfs operations.
131 static struct vfsops nfs_vfsops = {
132 .vfs_init = nfs_init,
133 .vfs_mount = nfs_mount,
134 .vfs_cmount = nfs_cmount,
135 .vfs_root = nfs_root,
136 .vfs_statfs = nfs_statfs,
137 .vfs_sync = nfs_sync,
138 .vfs_uninit = nfs_uninit,
139 .vfs_unmount = nfs_unmount,
140 .vfs_sysctl = nfs_sysctl,
142 VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK);
144 /* So that loader and kldload(2) can find us, wherever we are.. */
145 MODULE_VERSION(nfs, 1);
146 MODULE_DEPEND(nfs, krpc, 1, 1, 1);
148 MODULE_DEPEND(nfs, kgssapi, 1, 1, 1);
150 MODULE_DEPEND(nfs, nfs_common, 1, 1, 1);
152 static struct nfs_rpcops nfs_rpcops = {
162 * This structure must be filled in by a primary bootstrap or bootstrap
163 * server for a diskless/dataless machine. It is initialized below just
164 * to ensure that it is allocated to initialized data (.data not .bss).
166 struct nfs_diskless nfs_diskless = { { { 0 } } };
167 struct nfsv3_diskless nfsv3_diskless = { { { 0 } } };
168 int nfs_diskless_valid = 0;
170 SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
171 &nfs_diskless_valid, 0,
172 "Has the diskless struct been filled correctly");
174 SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
175 nfsv3_diskless.root_hostnam, 0, "Path to nfs root");
177 SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
178 &nfsv3_diskless.root_saddr, sizeof nfsv3_diskless.root_saddr,
179 "%Ssockaddr_in", "Diskless root nfs address");
182 void nfsargs_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 nfs_iosize(struct nfsmount *nmp)
196 * Calculate the size used for io buffers. Use the larger
197 * of the two sizes to minimise nfs requests but make sure
198 * that it is at least one VM page to avoid wasting buffer
201 iosize = imax(nmp->nm_rsize, nmp->nm_wsize);
202 iosize = imax(iosize, PAGE_SIZE);
207 nfs_convert_oargs(struct nfs_args *args, struct onfs_args *oargs)
210 args->version = NFS_ARGSVERSION;
211 args->addr = oargs->addr;
212 args->addrlen = oargs->addrlen;
213 args->sotype = oargs->sotype;
214 args->proto = oargs->proto;
215 args->fh = oargs->fh;
216 args->fhsize = oargs->fhsize;
217 args->flags = oargs->flags;
218 args->wsize = oargs->wsize;
219 args->rsize = oargs->rsize;
220 args->readdirsize = oargs->readdirsize;
221 args->timeo = oargs->timeo;
222 args->retrans = oargs->retrans;
223 args->maxgrouplist = oargs->maxgrouplist;
224 args->readahead = oargs->readahead;
225 args->deadthresh = oargs->deadthresh;
226 args->hostname = oargs->hostname;
230 nfs_convert_diskless(void)
233 bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
234 sizeof(struct ifaliasreq));
235 bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
236 sizeof(struct sockaddr_in));
237 nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
238 if (nfsv3_diskless.root_args.flags & NFSMNT_NFSV3) {
239 nfsv3_diskless.root_fhsize = NFSX_V3FH;
240 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V3FH);
242 nfsv3_diskless.root_fhsize = NFSX_V2FH;
243 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
245 bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
246 sizeof(struct sockaddr_in));
247 bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN);
248 nfsv3_diskless.root_time = nfs_diskless.root_time;
249 bcopy(nfs_diskless.my_hostnam, nfsv3_diskless.my_hostnam,
251 nfs_diskless_valid = 3;
258 nfs_statfs(struct mount *mp, struct statfs *sbp)
262 struct nfs_statfs *sfp;
264 struct nfsmount *nmp = VFSTONFS(mp);
265 int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr;
266 struct mbuf *mreq, *mrep, *md, *mb;
274 error = vfs_busy(mp, MBF_NOWAIT);
277 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
283 mtx_lock(&nmp->nm_mtx);
284 if (v3 && (nmp->nm_state & NFSSTA_GOTFSINFO) == 0) {
285 mtx_unlock(&nmp->nm_mtx);
286 (void)nfs_fsinfo(nmp, vp, td->td_ucred, td);
288 mtx_unlock(&nmp->nm_mtx);
289 nfsstats.rpccnt[NFSPROC_FSSTAT]++;
290 mreq = nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3));
292 bpos = mtod(mb, caddr_t);
294 nfsm_request(vp, NFSPROC_FSSTAT, td, td->td_ucred);
296 nfsm_postop_attr(vp, retattr);
302 sfp = nfsm_dissect(struct nfs_statfs *, NFSX_STATFS(v3));
303 mtx_lock(&nmp->nm_mtx);
304 sbp->f_iosize = nfs_iosize(nmp);
305 mtx_unlock(&nmp->nm_mtx);
307 sbp->f_bsize = NFS_FABLKSIZE;
308 tquad = fxdr_hyper(&sfp->sf_tbytes);
309 sbp->f_blocks = tquad / NFS_FABLKSIZE;
310 tquad = fxdr_hyper(&sfp->sf_fbytes);
311 sbp->f_bfree = tquad / NFS_FABLKSIZE;
312 tquad = fxdr_hyper(&sfp->sf_abytes);
313 sbp->f_bavail = tquad / NFS_FABLKSIZE;
314 sbp->f_files = (fxdr_unsigned(int32_t,
315 sfp->sf_tfiles.nfsuquad[1]) & 0x7fffffff);
316 sbp->f_ffree = (fxdr_unsigned(int32_t,
317 sfp->sf_ffiles.nfsuquad[1]) & 0x7fffffff);
319 sbp->f_bsize = fxdr_unsigned(int32_t, sfp->sf_bsize);
320 sbp->f_blocks = fxdr_unsigned(int32_t, sfp->sf_blocks);
321 sbp->f_bfree = fxdr_unsigned(int32_t, sfp->sf_bfree);
322 sbp->f_bavail = fxdr_unsigned(int32_t, sfp->sf_bavail);
334 * nfs version 3 fsinfo rpc call
337 nfs_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred,
340 struct nfsv3_fsinfo *fsp;
343 int error = 0, retattr;
344 struct mbuf *mreq, *mrep, *md, *mb;
347 nfsstats.rpccnt[NFSPROC_FSINFO]++;
348 mreq = nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1));
350 bpos = mtod(mb, caddr_t);
352 nfsm_request(vp, NFSPROC_FSINFO, td, cred);
353 nfsm_postop_attr(vp, retattr);
355 fsp = nfsm_dissect(struct nfsv3_fsinfo *, NFSX_V3FSINFO);
356 pref = fxdr_unsigned(u_int32_t, fsp->fs_wtpref);
357 mtx_lock(&nmp->nm_mtx);
358 if (pref < nmp->nm_wsize && pref >= NFS_FABLKSIZE)
359 nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) &
360 ~(NFS_FABLKSIZE - 1);
361 max = fxdr_unsigned(u_int32_t, fsp->fs_wtmax);
362 if (max < nmp->nm_wsize && max > 0) {
363 nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1);
364 if (nmp->nm_wsize == 0)
367 pref = fxdr_unsigned(u_int32_t, fsp->fs_rtpref);
368 if (pref < nmp->nm_rsize && pref >= NFS_FABLKSIZE)
369 nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) &
370 ~(NFS_FABLKSIZE - 1);
371 max = fxdr_unsigned(u_int32_t, fsp->fs_rtmax);
372 if (max < nmp->nm_rsize && max > 0) {
373 nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1);
374 if (nmp->nm_rsize == 0)
377 pref = fxdr_unsigned(u_int32_t, fsp->fs_dtpref);
378 if (pref < nmp->nm_readdirsize && pref >= NFS_DIRBLKSIZ)
379 nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ - 1) &
380 ~(NFS_DIRBLKSIZ - 1);
381 if (max < nmp->nm_readdirsize && max > 0) {
382 nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1);
383 if (nmp->nm_readdirsize == 0)
384 nmp->nm_readdirsize = max;
386 maxfsize = fxdr_hyper(&fsp->fs_maxfilesize);
387 if (maxfsize > 0 && maxfsize < nmp->nm_maxfilesize)
388 nmp->nm_maxfilesize = maxfsize;
389 nmp->nm_mountp->mnt_stat.f_iosize = nfs_iosize(nmp);
390 nmp->nm_state |= NFSSTA_GOTFSINFO;
391 mtx_unlock(&nmp->nm_mtx);
399 * Mount a remote root fs via. nfs. This depends on the info in the
400 * nfs_diskless structure that has been filled in properly by some primary
402 * It goes something like this:
403 * - do enough of "ifconfig" by calling ifioctl() so that the system
404 * can talk to the server
405 * - If nfs_diskless.mygateway is filled in, use that address as
407 * - build the rootfs mount point and call mountnfs() to do the rest.
409 * It is assumed to be safe to read, modify, and write the nfsv3_diskless
410 * structure, as well as other global NFS client variables here, as
411 * nfs_mountroot() will be called once in the boot before any other NFS
412 * client activity occurs.
415 nfs_mountroot(struct mount *mp)
417 struct thread *td = curthread;
418 struct nfsv3_diskless *nd = &nfsv3_diskless;
427 CURVNET_SET(TD_TO_VNET(td));
429 #if defined(BOOTP_NFSROOT) && defined(BOOTP)
430 bootpc_init(); /* use bootp to get nfs_diskless filled in */
431 #elif defined(NFS_ROOT)
432 nfs_setup_diskless();
435 if (nfs_diskless_valid == 0) {
439 if (nfs_diskless_valid == 1)
440 nfs_convert_diskless();
443 * XXX splnet, so networks will receive...
448 * Do enough of ifconfig(8) so that the critical net interface can
449 * talk to the server.
451 error = socreate(nd->myif.ifra_addr.sa_family, &so, nd->root_args.sotype, 0,
454 panic("nfs_mountroot: socreate(%04x): %d",
455 nd->myif.ifra_addr.sa_family, error);
457 #if 0 /* XXX Bad idea */
459 * We might not have been told the right interface, so we pass
460 * over the first ten interfaces of the same kind, until we get
461 * one of them configured.
464 for (i = strlen(nd->myif.ifra_name) - 1;
465 nd->myif.ifra_name[i] >= '0' &&
466 nd->myif.ifra_name[i] <= '9';
467 nd->myif.ifra_name[i] ++) {
468 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
474 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
476 panic("nfs_mountroot: SIOCAIFADDR: %d", error);
478 if ((cp = getenv("boot.netif.mtu")) != NULL) {
479 ir.ifr_mtu = strtol(cp, NULL, 10);
480 bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ);
482 error = ifioctl(so, SIOCSIFMTU, (caddr_t)&ir, td);
484 printf("nfs_mountroot: SIOCSIFMTU: %d", error);
489 * If the gateway field is filled in, set it as the default route.
490 * Note that pxeboot will set a default route of 0 if the route
491 * is not set by the DHCP server. Check also for a value of 0
492 * to avoid panicking inappropriately in that situation.
494 if (nd->mygateway.sin_len != 0 &&
495 nd->mygateway.sin_addr.s_addr != 0) {
496 struct sockaddr_in mask, sin;
498 bzero((caddr_t)&mask, sizeof(mask));
500 sin.sin_family = AF_INET;
501 sin.sin_len = sizeof(sin);
502 /* XXX MRT use table 0 for this sort of thing */
503 error = rtrequest(RTM_ADD, (struct sockaddr *)&sin,
504 (struct sockaddr *)&nd->mygateway,
505 (struct sockaddr *)&mask,
506 RTF_UP | RTF_GATEWAY, NULL);
508 panic("nfs_mountroot: RTM_ADD: %d", error);
512 * Create the rootfs mount point.
514 nd->root_args.fh = nd->root_fh;
515 nd->root_args.fhsize = nd->root_fhsize;
516 l = ntohl(nd->root_saddr.sin_addr.s_addr);
517 snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
518 (l >> 24) & 0xff, (l >> 16) & 0xff,
519 (l >> 8) & 0xff, (l >> 0) & 0xff, nd->root_hostnam);
520 printf("NFS ROOT: %s\n", buf);
521 nd->root_args.hostname = buf;
522 if ((error = nfs_mountdiskless(buf,
523 &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) {
529 * This is not really an nfs issue, but it is much easier to
530 * set hostname here and then let the "/etc/rc.xxx" files
531 * mount the right /var based upon its preset value.
533 mtx_lock(&prison0.pr_mtx);
534 strlcpy(prison0.pr_hostname, nd->my_hostnam,
535 sizeof (prison0.pr_hostname));
536 mtx_unlock(&prison0.pr_mtx);
537 inittodr(ntohl(nd->root_time));
543 * Internal version of mount system call for diskless setup.
546 nfs_mountdiskless(char *path,
547 struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
548 struct vnode **vpp, struct mount *mp)
550 struct sockaddr *nam;
553 nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
554 if ((error = mountnfs(args, mp, nam, path, vpp,
555 td->td_ucred, NFS_DEFAULT_NEGNAMETIMEO)) != 0) {
556 printf("nfs_mountroot: mount %s on /: %d\n", path, error);
563 nfs_sec_name_to_num(char *sec)
565 if (!strcmp(sec, "krb5"))
566 return (RPCSEC_GSS_KRB5);
567 if (!strcmp(sec, "krb5i"))
568 return (RPCSEC_GSS_KRB5I);
569 if (!strcmp(sec, "krb5p"))
570 return (RPCSEC_GSS_KRB5P);
571 if (!strcmp(sec, "sys"))
574 * Userland should validate the string but we will try and
575 * cope with unexpected values.
581 nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
582 const char *hostname)
594 * Set read-only flag if requested; otherwise, clear it if this is
595 * an update. If this is not an update, then either the read-only
596 * flag is already clear, or this is a root mount and it was set
597 * intentionally at some previous point.
599 if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) {
601 mp->mnt_flag |= MNT_RDONLY;
603 } else if (mp->mnt_flag & MNT_UPDATE) {
605 mp->mnt_flag &= ~MNT_RDONLY;
610 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
611 * no sense in that context. Also, set up appropriate retransmit
612 * and soft timeout behavior.
614 if (argp->sotype == SOCK_STREAM) {
615 nmp->nm_flag &= ~NFSMNT_NOCONN;
616 nmp->nm_flag |= NFSMNT_DUMBTIMR;
617 nmp->nm_timeo = NFS_MAXTIMEO;
618 nmp->nm_retry = NFS_RETRANS_TCP;
621 /* Also clear RDIRPLUS if not NFSv3, it crashes some servers */
622 if ((argp->flags & NFSMNT_NFSV3) == 0)
623 nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
625 /* Re-bind if rsrvd port requested and wasn't on one */
626 adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
627 && (argp->flags & NFSMNT_RESVPORT);
628 /* Also re-bind if we're switching to/from a connected UDP socket */
629 adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
630 (argp->flags & NFSMNT_NOCONN));
632 /* Update flags atomically. Don't change the lock bits. */
633 nmp->nm_flag = argp->flags | nmp->nm_flag;
636 if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
637 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
638 if (nmp->nm_timeo < NFS_MINTIMEO)
639 nmp->nm_timeo = NFS_MINTIMEO;
640 else if (nmp->nm_timeo > NFS_MAXTIMEO)
641 nmp->nm_timeo = NFS_MAXTIMEO;
644 if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
645 nmp->nm_retry = argp->retrans;
646 if (nmp->nm_retry > NFS_MAXREXMIT)
647 nmp->nm_retry = NFS_MAXREXMIT;
650 if (argp->flags & NFSMNT_NFSV3) {
651 if (argp->sotype == SOCK_DGRAM)
652 maxio = NFS_MAXDGRAMDATA;
656 maxio = NFS_V2MAXDATA;
658 if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
659 nmp->nm_wsize = argp->wsize;
660 /* Round down to multiple of blocksize */
661 nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
662 if (nmp->nm_wsize <= 0)
663 nmp->nm_wsize = NFS_FABLKSIZE;
665 if (nmp->nm_wsize > maxio)
666 nmp->nm_wsize = maxio;
667 if (nmp->nm_wsize > MAXBSIZE)
668 nmp->nm_wsize = MAXBSIZE;
670 if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
671 nmp->nm_rsize = argp->rsize;
672 /* Round down to multiple of blocksize */
673 nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
674 if (nmp->nm_rsize <= 0)
675 nmp->nm_rsize = NFS_FABLKSIZE;
677 if (nmp->nm_rsize > maxio)
678 nmp->nm_rsize = maxio;
679 if (nmp->nm_rsize > MAXBSIZE)
680 nmp->nm_rsize = MAXBSIZE;
682 if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
683 nmp->nm_readdirsize = argp->readdirsize;
685 if (nmp->nm_readdirsize > maxio)
686 nmp->nm_readdirsize = maxio;
687 if (nmp->nm_readdirsize > nmp->nm_rsize)
688 nmp->nm_readdirsize = nmp->nm_rsize;
690 if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
691 nmp->nm_acregmin = argp->acregmin;
693 nmp->nm_acregmin = NFS_MINATTRTIMO;
694 if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
695 nmp->nm_acregmax = argp->acregmax;
697 nmp->nm_acregmax = NFS_MAXATTRTIMO;
698 if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
699 nmp->nm_acdirmin = argp->acdirmin;
701 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
702 if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
703 nmp->nm_acdirmax = argp->acdirmax;
705 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
706 if (nmp->nm_acdirmin > nmp->nm_acdirmax)
707 nmp->nm_acdirmin = nmp->nm_acdirmax;
708 if (nmp->nm_acregmin > nmp->nm_acregmax)
709 nmp->nm_acregmin = nmp->nm_acregmax;
711 if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0) {
712 if (argp->maxgrouplist <= NFS_MAXGRPS)
713 nmp->nm_numgrps = argp->maxgrouplist;
715 nmp->nm_numgrps = NFS_MAXGRPS;
717 if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
718 if (argp->readahead <= NFS_MAXRAHEAD)
719 nmp->nm_readahead = argp->readahead;
721 nmp->nm_readahead = NFS_MAXRAHEAD;
723 if ((argp->flags & NFSMNT_WCOMMITSIZE) && argp->wcommitsize >= 0) {
724 if (argp->wcommitsize < nmp->nm_wsize)
725 nmp->nm_wcommitsize = nmp->nm_wsize;
727 nmp->nm_wcommitsize = argp->wcommitsize;
729 if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 0) {
730 if (argp->deadthresh <= NFS_MAXDEADTHRESH)
731 nmp->nm_deadthresh = argp->deadthresh;
733 nmp->nm_deadthresh = NFS_MAXDEADTHRESH;
736 adjsock |= ((nmp->nm_sotype != argp->sotype) ||
737 (nmp->nm_soproto != argp->proto));
738 nmp->nm_sotype = argp->sotype;
739 nmp->nm_soproto = argp->proto;
741 if (nmp->nm_client && adjsock) {
742 nfs_safedisconnect(nmp);
743 if (nmp->nm_sotype == SOCK_DGRAM)
744 while (nfs_connect(nmp)) {
745 printf("nfs_args: retrying connect\n");
746 (void) tsleep(&fake_wchan, PSOCK, "nfscon", hz);
751 strlcpy(nmp->nm_hostname, hostname,
752 sizeof(nmp->nm_hostname));
753 p = strchr(nmp->nm_hostname, ':');
758 if (vfs_getopt(mp->mnt_optnew, "sec",
759 (void **) &secname, NULL) == 0) {
760 nmp->nm_secflavor = nfs_sec_name_to_num(secname);
762 nmp->nm_secflavor = AUTH_SYS;
765 if (vfs_getopt(mp->mnt_optnew, "principal",
766 (void **) &principal, NULL) == 0) {
767 strlcpy(nmp->nm_principal, principal,
768 sizeof(nmp->nm_principal));
770 snprintf(nmp->nm_principal, sizeof(nmp->nm_principal),
771 "nfs@%s", nmp->nm_hostname);
775 static const char *nfs_opts[] = { "from", "nfs_args",
776 "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
777 "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
778 "async", "dumbtimer", "noconn", "nolockd", "intr", "rdirplus", "resvport",
779 "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize",
780 "retrans", "acregmin", "acregmax", "acdirmin", "acdirmax",
781 "deadthresh", "hostname", "timeout", "addr", "fh", "nfsv3", "sec",
782 "maxgroups", "principal", "negnametimeo",
789 * It seems a bit dumb to copyinstr() the host and path here and then
790 * bcopy() them in mountnfs(), but I wanted to detect errors before
791 * doing the sockargs() call because sockargs() allocates an mbuf and
792 * an error after that means that I have to release the mbuf.
796 nfs_mount(struct mount *mp)
798 struct nfs_args args = {
799 .version = NFS_ARGSVERSION,
801 .addrlen = sizeof (struct sockaddr_in),
802 .sotype = SOCK_STREAM,
806 .flags = NFSMNT_RESVPORT,
809 .readdirsize = NFS_READDIRSIZE,
811 .retrans = NFS_RETRANS,
812 .maxgrouplist = NFS_MAXGRPS,
813 .readahead = NFS_DEFRAHEAD,
814 .wcommitsize = 0, /* was: NQ_DEFLEASE */
815 .deadthresh = NFS_MAXDEADTHRESH, /* was: NQ_DEADTHRESH */
818 .acregmin = NFS_MINATTRTIMO,
819 .acregmax = NFS_MAXATTRTIMO,
820 .acdirmin = NFS_MINDIRATTRTIMO,
821 .acdirmax = NFS_MAXDIRATTRTIMO,
823 int error, ret, has_nfs_args_opt;
824 int has_addr_opt, has_fh_opt, has_hostname_opt;
825 struct sockaddr *nam;
829 u_char nfh[NFSX_V3FHMAX];
831 int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
833 has_nfs_args_opt = 0;
836 has_hostname_opt = 0;
838 if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
843 if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS) {
844 error = nfs_mountroot(mp);
849 * The old mount_nfs program passed the struct nfs_args
850 * from userspace to kernel. The new mount_nfs program
851 * passes string options via nmount() from userspace to kernel
852 * and we populate the struct nfs_args in the kernel.
854 if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
855 error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
860 if (args.version != NFS_ARGSVERSION) {
861 error = EPROGMISMATCH;
864 has_nfs_args_opt = 1;
867 if (vfs_getopt(mp->mnt_optnew, "dumbtimer", NULL, NULL) == 0)
868 args.flags |= NFSMNT_DUMBTIMR;
869 if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
870 args.flags |= NFSMNT_NOCONN;
871 if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
872 args.flags |= NFSMNT_NOCONN;
873 if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
874 args.flags |= NFSMNT_NOLOCKD;
875 if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
876 args.flags &= ~NFSMNT_NOLOCKD;
877 if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
878 args.flags |= NFSMNT_INT;
879 if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
880 args.flags |= NFSMNT_RDIRPLUS;
881 if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
882 args.flags |= NFSMNT_RESVPORT;
883 if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
884 args.flags &= ~NFSMNT_RESVPORT;
885 if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
886 args.flags |= NFSMNT_SOFT;
887 if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
888 args.flags &= ~NFSMNT_SOFT;
889 if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
890 args.sotype = SOCK_DGRAM;
891 if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
892 args.sotype = SOCK_DGRAM;
893 if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
894 args.sotype = SOCK_STREAM;
895 if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
896 args.flags |= NFSMNT_NFSV3;
897 if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
899 vfs_mount_error(mp, "illegal readdirsize");
903 ret = sscanf(opt, "%d", &args.readdirsize);
904 if (ret != 1 || args.readdirsize <= 0) {
905 vfs_mount_error(mp, "illegal readdirsize: %s",
910 args.flags |= NFSMNT_READDIRSIZE;
912 if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
914 vfs_mount_error(mp, "illegal readahead");
918 ret = sscanf(opt, "%d", &args.readahead);
919 if (ret != 1 || args.readahead <= 0) {
920 vfs_mount_error(mp, "illegal readahead: %s",
925 args.flags |= NFSMNT_READAHEAD;
927 if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
929 vfs_mount_error(mp, "illegal wsize");
933 ret = sscanf(opt, "%d", &args.wsize);
934 if (ret != 1 || args.wsize <= 0) {
935 vfs_mount_error(mp, "illegal wsize: %s",
940 args.flags |= NFSMNT_WSIZE;
942 if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
944 vfs_mount_error(mp, "illegal rsize");
948 ret = sscanf(opt, "%d", &args.rsize);
949 if (ret != 1 || args.rsize <= 0) {
950 vfs_mount_error(mp, "illegal wsize: %s",
955 args.flags |= NFSMNT_RSIZE;
957 if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
959 vfs_mount_error(mp, "illegal retrans");
963 ret = sscanf(opt, "%d", &args.retrans);
964 if (ret != 1 || args.retrans <= 0) {
965 vfs_mount_error(mp, "illegal retrans: %s",
970 args.flags |= NFSMNT_RETRANS;
972 if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
973 ret = sscanf(opt, "%d", &args.acregmin);
974 if (ret != 1 || args.acregmin < 0) {
975 vfs_mount_error(mp, "illegal acregmin: %s",
980 args.flags |= NFSMNT_ACREGMIN;
982 if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
983 ret = sscanf(opt, "%d", &args.acregmax);
984 if (ret != 1 || args.acregmax < 0) {
985 vfs_mount_error(mp, "illegal acregmax: %s",
990 args.flags |= NFSMNT_ACREGMAX;
992 if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
993 ret = sscanf(opt, "%d", &args.acdirmin);
994 if (ret != 1 || args.acdirmin < 0) {
995 vfs_mount_error(mp, "illegal acdirmin: %s",
1000 args.flags |= NFSMNT_ACDIRMIN;
1002 if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
1003 ret = sscanf(opt, "%d", &args.acdirmax);
1004 if (ret != 1 || args.acdirmax < 0) {
1005 vfs_mount_error(mp, "illegal acdirmax: %s",
1010 args.flags |= NFSMNT_ACDIRMAX;
1012 if (vfs_getopt(mp->mnt_optnew, "deadthresh", (void **)&opt, NULL) == 0) {
1013 ret = sscanf(opt, "%d", &args.deadthresh);
1014 if (ret != 1 || args.deadthresh <= 0) {
1015 vfs_mount_error(mp, "illegal deadthresh: %s",
1020 args.flags |= NFSMNT_DEADTHRESH;
1022 if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
1023 ret = sscanf(opt, "%d", &args.timeo);
1024 if (ret != 1 || args.timeo <= 0) {
1025 vfs_mount_error(mp, "illegal timeout: %s",
1030 args.flags |= NFSMNT_TIMEO;
1032 if (vfs_getopt(mp->mnt_optnew, "maxgroups", (void **)&opt, NULL) == 0) {
1033 ret = sscanf(opt, "%d", &args.maxgrouplist);
1034 if (ret != 1 || args.maxgrouplist <= 0) {
1035 vfs_mount_error(mp, "illegal maxgroups: %s",
1040 args.flags |= NFSMNT_MAXGRPS;
1042 if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
1044 ret = sscanf(opt, "%d", &negnametimeo);
1045 if (ret != 1 || negnametimeo < 0) {
1046 vfs_mount_error(mp, "illegal negnametimeo: %s",
1052 if (vfs_getopt(mp->mnt_optnew, "addr", (void **)&args.addr,
1053 &args.addrlen) == 0) {
1055 if (args.addrlen > SOCK_MAXADDRLEN) {
1056 error = ENAMETOOLONG;
1059 nam = malloc(args.addrlen, M_SONAME,
1061 bcopy(args.addr, nam, args.addrlen);
1062 nam->sa_len = args.addrlen;
1064 if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
1065 &args.fhsize) == 0) {
1068 if (vfs_getopt(mp->mnt_optnew, "hostname", (void **)&args.hostname,
1070 has_hostname_opt = 1;
1072 if (args.hostname == NULL) {
1073 vfs_mount_error(mp, "Invalid hostname");
1078 if (mp->mnt_flag & MNT_UPDATE) {
1079 struct nfsmount *nmp = VFSTONFS(mp);
1086 * When doing an update, we can't change from or to
1087 * v3, switch lockd strategies or change cookie translation
1089 args.flags = (args.flags &
1090 ~(NFSMNT_NFSV3 | NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
1092 (NFSMNT_NFSV3 | NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
1093 nfs_decode_args(mp, nmp, &args, NULL);
1098 * Make the nfs_ip_paranoia sysctl serve as the default connection
1099 * or no-connection mode for those protocols that support
1100 * no-connection mode (the flag will be cleared later for protocols
1101 * that do not support no-connection mode). This will allow a client
1102 * to receive replies from a different IP then the request was
1103 * sent to. Note: default value for nfs_ip_paranoia is 1 (paranoid),
1106 if (nfs_ip_paranoia == 0)
1107 args.flags |= NFSMNT_NOCONN;
1109 if (has_nfs_args_opt) {
1111 * In the 'nfs_args' case, the pointers in the args
1112 * structure are in userland - we copy them in here.
1115 error = copyin((caddr_t)args.fh, (caddr_t)nfh,
1122 if (!has_hostname_opt) {
1123 error = copyinstr(args.hostname, hst, MNAMELEN-1, &len);
1127 bzero(&hst[len], MNAMELEN - len);
1128 args.hostname = hst;
1130 if (!has_addr_opt) {
1131 /* sockargs() call must be after above copyin() calls */
1132 error = getsockaddr(&nam, (caddr_t)args.addr,
1139 error = mountnfs(&args, mp, nam, args.hostname, &vp,
1140 curthread->td_ucred, negnametimeo);
1144 mp->mnt_kern_flag |= (MNTK_MPSAFE|MNTK_LOOKUP_SHARED);
1155 * It seems a bit dumb to copyinstr() the host and path here and then
1156 * bcopy() them in mountnfs(), but I wanted to detect errors before
1157 * doing the sockargs() call because sockargs() allocates an mbuf and
1158 * an error after that means that I have to release the mbuf.
1162 nfs_cmount(struct mntarg *ma, void *data, int flags)
1165 struct nfs_args args;
1167 error = copyin(data, &args, sizeof (struct nfs_args));
1171 ma = mount_arg(ma, "nfs_args", &args, sizeof args);
1173 error = kernel_mount(ma, flags);
1178 * Common code for mount and mountroot
1181 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
1182 char *hst, struct vnode **vpp, struct ucred *cred, int negnametimeo)
1184 struct nfsmount *nmp;
1189 if (mp->mnt_flag & MNT_UPDATE) {
1191 printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
1192 free(nam, M_SONAME);
1195 nmp = uma_zalloc(nfsmount_zone, M_WAITOK);
1196 bzero((caddr_t)nmp, sizeof (struct nfsmount));
1197 TAILQ_INIT(&nmp->nm_bufq);
1201 nmp->nm_mountp = mp;
1202 mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF);
1205 * V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too
1206 * high, depending on whether we end up with negative offsets in
1207 * the client or server somewhere. 2GB-1 may be safer.
1209 * For V3, nfs_fsinfo will adjust this as necessary. Assume maximum
1210 * that we can handle until we find out otherwise.
1211 * XXX Our "safe" limit on the client is what we can store in our
1212 * buffer cache using signed(!) block numbers.
1214 if ((argp->flags & NFSMNT_NFSV3) == 0)
1215 nmp->nm_maxfilesize = 0xffffffffLL;
1217 nmp->nm_maxfilesize = (u_int64_t)0x80000000 * DEV_BSIZE - 1;
1219 nmp->nm_timeo = NFS_TIMEO;
1220 nmp->nm_retry = NFS_RETRANS;
1221 if ((argp->flags & NFSMNT_NFSV3) && argp->sotype == SOCK_STREAM) {
1222 nmp->nm_wsize = nmp->nm_rsize = NFS_MAXDATA;
1224 nmp->nm_wsize = NFS_WSIZE;
1225 nmp->nm_rsize = NFS_RSIZE;
1227 nmp->nm_wcommitsize = hibufspace / (desiredvnodes / 1000);
1228 nmp->nm_readdirsize = NFS_READDIRSIZE;
1229 nmp->nm_numgrps = NFS_MAXGRPS;
1230 nmp->nm_readahead = NFS_DEFRAHEAD;
1231 nmp->nm_deadthresh = NFS_MAXDEADTHRESH;
1232 nmp->nm_negnametimeo = negnametimeo;
1233 nmp->nm_tprintf_delay = nfs_tprintf_delay;
1234 if (nmp->nm_tprintf_delay < 0)
1235 nmp->nm_tprintf_delay = 0;
1236 nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
1237 if (nmp->nm_tprintf_initial_delay < 0)
1238 nmp->nm_tprintf_initial_delay = 0;
1239 nmp->nm_fhsize = argp->fhsize;
1240 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
1241 bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
1243 /* Set up the sockets and per-host congestion */
1244 nmp->nm_sotype = argp->sotype;
1245 nmp->nm_soproto = argp->proto;
1246 nmp->nm_rpcops = &nfs_rpcops;
1248 nfs_decode_args(mp, nmp, argp, hst);
1251 * For Connection based sockets (TCP,...) defer the connect until
1252 * the first request, in case the server is not responding.
1254 if (nmp->nm_sotype == SOCK_DGRAM &&
1255 (error = nfs_connect(nmp)))
1259 * This is silly, but it has to be set so that vinifod() works.
1260 * We do not want to do an nfs_statfs() here since we can get
1261 * stuck on a dead server and we are holding a lock on the mount
1264 mtx_lock(&nmp->nm_mtx);
1265 mp->mnt_stat.f_iosize = nfs_iosize(nmp);
1266 mtx_unlock(&nmp->nm_mtx);
1268 * A reference count is needed on the nfsnode representing the
1269 * remote root. If this object is not persistent, then backward
1270 * traversals of the mount point (i.e. "..") will not work if
1271 * the nfsnode gets flushed out of the cache. Ufs does not have
1272 * this problem, because one can identify root inodes by their
1273 * number == ROOTINO (2).
1275 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
1281 * Get file attributes and transfer parameters for the
1282 * mountpoint. This has the side effect of filling in
1283 * (*vpp)->v_type with the correct value.
1285 if (argp->flags & NFSMNT_NFSV3)
1286 nfs_fsinfo(nmp, *vpp, curthread->td_ucred, curthread);
1288 VOP_GETATTR(*vpp, &attrs, curthread->td_ucred);
1291 * Lose the lock but keep the ref.
1293 VOP_UNLOCK(*vpp, 0);
1297 nfs_disconnect(nmp);
1298 mtx_destroy(&nmp->nm_mtx);
1299 uma_zfree(nfsmount_zone, nmp);
1300 free(nam, M_SONAME);
1305 * unmount system call
1308 nfs_unmount(struct mount *mp, int mntflags)
1310 struct nfsmount *nmp;
1311 int error, flags = 0;
1313 if (mntflags & MNT_FORCE)
1314 flags |= FORCECLOSE;
1317 * Goes something like this..
1318 * - Call vflush() to clear out vnodes for this filesystem
1319 * - Close the socket
1320 * - Free up the data structures
1322 /* In the forced case, cancel any outstanding requests. */
1323 if (flags & FORCECLOSE) {
1324 error = nfs_nmcancelreqs(nmp);
1328 /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
1329 error = vflush(mp, 1, flags, curthread);
1334 * We are now committed to the unmount.
1336 nfs_disconnect(nmp);
1337 free(nmp->nm_nam, M_SONAME);
1339 mtx_destroy(&nmp->nm_mtx);
1340 uma_zfree(nfsmount_zone, nmp);
1346 * Return root of a filesystem
1349 nfs_root(struct mount *mp, int flags, struct vnode **vpp)
1352 struct nfsmount *nmp;
1357 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, flags);
1362 * Get transfer parameters and attributes for root vnode once.
1364 mtx_lock(&nmp->nm_mtx);
1365 if ((nmp->nm_state & NFSSTA_GOTFSINFO) == 0 &&
1366 (nmp->nm_flag & NFSMNT_NFSV3)) {
1367 mtx_unlock(&nmp->nm_mtx);
1368 nfs_fsinfo(nmp, vp, curthread->td_ucred, curthread);
1370 mtx_unlock(&nmp->nm_mtx);
1371 if (vp->v_type == VNON)
1373 vp->v_vflag |= VV_ROOT;
1379 * Flush out the buffer cache
1383 nfs_sync(struct mount *mp, int waitfor)
1385 struct vnode *vp, *mvp;
1387 int error, allerror = 0;
1392 * Force stale buffer cache information to be flushed.
1396 MNT_VNODE_FOREACH(vp, mp, mvp) {
1399 /* XXX Racy bv_cnt check. */
1400 if (VOP_ISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
1401 waitfor == MNT_LAZY) {
1406 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
1408 MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp);
1411 error = VOP_FSYNC(vp, waitfor, td);
1424 nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
1426 struct nfsmount *nmp = VFSTONFS(mp);
1430 bzero(&vq, sizeof(vq));
1433 case VFS_CTL_NOLOCKS:
1434 val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
1435 if (req->oldptr != NULL) {
1436 error = SYSCTL_OUT(req, &val, sizeof(val));
1440 if (req->newptr != NULL) {
1441 error = SYSCTL_IN(req, &val, sizeof(val));
1445 nmp->nm_flag |= NFSMNT_NOLOCKS;
1447 nmp->nm_flag &= ~NFSMNT_NOLOCKS;
1452 mtx_lock(&nmp->nm_mtx);
1453 if (nmp->nm_state & NFSSTA_TIMEO)
1454 vq.vq_flags |= VQ_NOTRESP;
1455 mtx_unlock(&nmp->nm_mtx);
1457 if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
1458 (nmp->nm_state & NFSSTA_LOCKTIMEO))
1459 vq.vq_flags |= VQ_NOTRESPLOCK;
1461 error = SYSCTL_OUT(req, &vq, sizeof(vq));
1464 if (req->oldptr != NULL) {
1465 error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
1466 sizeof(nmp->nm_tprintf_initial_delay));
1470 if (req->newptr != NULL) {
1471 error = vfs_suser(mp, req->td);
1474 error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
1475 sizeof(nmp->nm_tprintf_initial_delay));
1478 if (nmp->nm_tprintf_initial_delay < 0)
1479 nmp->nm_tprintf_initial_delay = 0;