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>
47 #include <sys/clock.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>
67 #include <netinet/in.h>
69 #include <rpc/rpcclnt.h>
71 #include <nfs/rpcv2.h>
72 #include <nfs/nfsproto.h>
73 #include <nfsclient/nfs.h>
74 #include <nfsclient/nfsnode.h>
75 #include <nfsclient/nfsmount.h>
76 #include <nfs/xdr_subs.h>
77 #include <nfsclient/nfsm_subs.h>
78 #include <nfsclient/nfsdiskless.h>
80 MALLOC_DEFINE(M_NFSREQ, "nfsclient_req", "NFS request header");
81 MALLOC_DEFINE(M_NFSBIGFH, "nfsclient_bigfh", "NFS version 3 file handle");
82 MALLOC_DEFINE(M_NFSDIROFF, "nfsclient_diroff", "NFS directory offset data");
83 MALLOC_DEFINE(M_NFSHASH, "nfsclient_hash", "NFS hash tables");
84 MALLOC_DEFINE(M_NFSDIRECTIO, "nfsclient_directio", "NFS Direct IO async write state");
86 uma_zone_t nfsmount_zone;
88 struct nfsstats nfsstats;
90 SYSCTL_NODE(_vfs, OID_AUTO, nfs, CTLFLAG_RW, 0, "NFS filesystem");
91 SYSCTL_STRUCT(_vfs_nfs, NFS_NFSSTATS, nfsstats, CTLFLAG_RW,
92 &nfsstats, nfsstats, "S,nfsstats");
93 static int nfs_ip_paranoia = 1;
94 SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW,
95 &nfs_ip_paranoia, 0, "");
98 SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0, "");
100 static int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
101 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_INITIAL_DELAY,
102 downdelayinitial, CTLFLAG_RW, &nfs_tprintf_initial_delay, 0, "");
103 /* how long between console messages "nfs server foo not responding" */
104 static int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
105 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_DELAY,
106 downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0, "");
108 static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp,
109 struct nfs_args *argp, const char *hostname);
110 static int mountnfs(struct nfs_args *, struct mount *,
111 struct sockaddr *, char *, struct vnode **,
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 = nfs_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 = nfs_uninit,
132 .vfs_unmount = nfs_unmount,
133 .vfs_sysctl = nfs_sysctl,
135 VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK);
137 /* So that loader and kldload(2) can find us, wherever we are.. */
138 MODULE_VERSION(nfs, 1);
140 static struct nfs_rpcops nfs_rpcops = {
150 * This structure must be filled in by a primary bootstrap or bootstrap
151 * server for a diskless/dataless machine. It is initialized below just
152 * to ensure that it is allocated to initialized data (.data not .bss).
154 struct nfs_diskless nfs_diskless = { { { 0 } } };
155 struct nfsv3_diskless nfsv3_diskless = { { { 0 } } };
156 int nfs_diskless_valid = 0;
158 SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
159 &nfs_diskless_valid, 0, "");
161 SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
162 nfsv3_diskless.root_hostnam, 0, "");
164 SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
165 &nfsv3_diskless.root_saddr, sizeof nfsv3_diskless.root_saddr,
166 "%Ssockaddr_in", "");
169 void nfsargs_ntoh(struct nfs_args *);
170 static int nfs_mountdiskless(char *, int,
171 struct sockaddr_in *, struct nfs_args *,
172 struct thread *, struct vnode **, struct mount *);
173 static void nfs_convert_diskless(void);
174 static void nfs_convert_oargs(struct nfs_args *args,
175 struct onfs_args *oargs);
178 nfs_iosize(struct nfsmount *nmp)
183 * Calculate the size used for io buffers. Use the larger
184 * of the two sizes to minimise nfs requests but make sure
185 * that it is at least one VM page to avoid wasting buffer
188 iosize = imax(nmp->nm_rsize, nmp->nm_wsize);
189 iosize = imax(iosize, PAGE_SIZE);
194 nfs_convert_oargs(struct nfs_args *args, struct onfs_args *oargs)
197 args->version = NFS_ARGSVERSION;
198 args->addr = oargs->addr;
199 args->addrlen = oargs->addrlen;
200 args->sotype = oargs->sotype;
201 args->proto = oargs->proto;
202 args->fh = oargs->fh;
203 args->fhsize = oargs->fhsize;
204 args->flags = oargs->flags;
205 args->wsize = oargs->wsize;
206 args->rsize = oargs->rsize;
207 args->readdirsize = oargs->readdirsize;
208 args->timeo = oargs->timeo;
209 args->retrans = oargs->retrans;
210 args->maxgrouplist = oargs->maxgrouplist;
211 args->readahead = oargs->readahead;
212 args->deadthresh = oargs->deadthresh;
213 args->hostname = oargs->hostname;
217 nfs_convert_diskless(void)
220 bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
221 sizeof(struct ifaliasreq));
222 bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
223 sizeof(struct sockaddr_in));
224 nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
225 if (nfsv3_diskless.root_args.flags & NFSMNT_NFSV3) {
226 nfsv3_diskless.root_fhsize = NFSX_V3FH;
227 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V3FH);
229 nfsv3_diskless.root_fhsize = NFSX_V2FH;
230 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
232 bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
233 sizeof(struct sockaddr_in));
234 bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN);
235 nfsv3_diskless.root_time = nfs_diskless.root_time;
236 bcopy(nfs_diskless.my_hostnam, nfsv3_diskless.my_hostnam,
238 nfs_diskless_valid = 3;
245 nfs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td)
248 struct nfs_statfs *sfp;
250 struct nfsmount *nmp = VFSTONFS(mp);
251 int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr;
252 struct mbuf *mreq, *mrep, *md, *mb;
259 error = vfs_busy(mp, 0, NULL, td);
262 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
268 mtx_lock(&nmp->nm_mtx);
269 if (v3 && (nmp->nm_state & NFSSTA_GOTFSINFO) == 0) {
270 mtx_unlock(&nmp->nm_mtx);
271 (void)nfs_fsinfo(nmp, vp, td->td_ucred, td);
273 mtx_unlock(&nmp->nm_mtx);
274 nfsstats.rpccnt[NFSPROC_FSSTAT]++;
275 mreq = nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3));
277 bpos = mtod(mb, caddr_t);
279 nfsm_request(vp, NFSPROC_FSSTAT, td, td->td_ucred);
281 nfsm_postop_attr(vp, retattr);
287 sfp = nfsm_dissect(struct nfs_statfs *, NFSX_STATFS(v3));
288 mtx_lock(&nmp->nm_mtx);
289 sbp->f_iosize = nfs_iosize(nmp);
290 mtx_unlock(&nmp->nm_mtx);
292 sbp->f_bsize = NFS_FABLKSIZE;
293 tquad = fxdr_hyper(&sfp->sf_tbytes);
294 sbp->f_blocks = tquad / NFS_FABLKSIZE;
295 tquad = fxdr_hyper(&sfp->sf_fbytes);
296 sbp->f_bfree = tquad / NFS_FABLKSIZE;
297 tquad = fxdr_hyper(&sfp->sf_abytes);
298 sbp->f_bavail = tquad / NFS_FABLKSIZE;
299 sbp->f_files = (fxdr_unsigned(int32_t,
300 sfp->sf_tfiles.nfsuquad[1]) & 0x7fffffff);
301 sbp->f_ffree = (fxdr_unsigned(int32_t,
302 sfp->sf_ffiles.nfsuquad[1]) & 0x7fffffff);
304 sbp->f_bsize = fxdr_unsigned(int32_t, sfp->sf_bsize);
305 sbp->f_blocks = fxdr_unsigned(int32_t, sfp->sf_blocks);
306 sbp->f_bfree = fxdr_unsigned(int32_t, sfp->sf_bfree);
307 sbp->f_bavail = fxdr_unsigned(int32_t, sfp->sf_bavail);
319 * nfs version 3 fsinfo rpc call
322 nfs_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred,
325 struct nfsv3_fsinfo *fsp;
328 int error = 0, retattr;
329 struct mbuf *mreq, *mrep, *md, *mb;
332 nfsstats.rpccnt[NFSPROC_FSINFO]++;
333 mreq = nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1));
335 bpos = mtod(mb, caddr_t);
337 nfsm_request(vp, NFSPROC_FSINFO, td, cred);
338 nfsm_postop_attr(vp, retattr);
340 fsp = nfsm_dissect(struct nfsv3_fsinfo *, NFSX_V3FSINFO);
341 pref = fxdr_unsigned(u_int32_t, fsp->fs_wtpref);
342 mtx_lock(&nmp->nm_mtx);
343 if (pref < nmp->nm_wsize && pref >= NFS_FABLKSIZE)
344 nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) &
345 ~(NFS_FABLKSIZE - 1);
346 max = fxdr_unsigned(u_int32_t, fsp->fs_wtmax);
347 if (max < nmp->nm_wsize && max > 0) {
348 nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1);
349 if (nmp->nm_wsize == 0)
352 pref = fxdr_unsigned(u_int32_t, fsp->fs_rtpref);
353 if (pref < nmp->nm_rsize && pref >= NFS_FABLKSIZE)
354 nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) &
355 ~(NFS_FABLKSIZE - 1);
356 max = fxdr_unsigned(u_int32_t, fsp->fs_rtmax);
357 if (max < nmp->nm_rsize && max > 0) {
358 nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1);
359 if (nmp->nm_rsize == 0)
362 pref = fxdr_unsigned(u_int32_t, fsp->fs_dtpref);
363 if (pref < nmp->nm_readdirsize && pref >= NFS_DIRBLKSIZ)
364 nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ - 1) &
365 ~(NFS_DIRBLKSIZ - 1);
366 if (max < nmp->nm_readdirsize && max > 0) {
367 nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1);
368 if (nmp->nm_readdirsize == 0)
369 nmp->nm_readdirsize = max;
371 maxfsize = fxdr_hyper(&fsp->fs_maxfilesize);
372 if (maxfsize > 0 && maxfsize < nmp->nm_maxfilesize)
373 nmp->nm_maxfilesize = maxfsize;
374 nmp->nm_mountp->mnt_stat.f_iosize = nfs_iosize(nmp);
375 nmp->nm_state |= NFSSTA_GOTFSINFO;
376 mtx_unlock(&nmp->nm_mtx);
384 * Mount a remote root fs via. nfs. This depends on the info in the
385 * nfs_diskless structure that has been filled in properly by some primary
387 * It goes something like this:
388 * - do enough of "ifconfig" by calling ifioctl() so that the system
389 * can talk to the server
390 * - If nfs_diskless.mygateway is filled in, use that address as
392 * - build the rootfs mount point and call mountnfs() to do the rest.
394 * It is assumed to be safe to read, modify, and write the nfsv3_diskless
395 * structure, as well as other global NFS client variables here, as
396 * nfs_mountroot() will be called once in the boot before any other NFS
397 * client activity occurs.
400 nfs_mountroot(struct mount *mp, struct thread *td)
402 struct nfsv3_diskless *nd = &nfsv3_diskless;
411 #if defined(BOOTP_NFSROOT) && defined(BOOTP)
412 bootpc_init(); /* use bootp to get nfs_diskless filled in */
413 #elif defined(NFS_ROOT)
414 nfs_setup_diskless();
417 if (nfs_diskless_valid == 0)
419 if (nfs_diskless_valid == 1)
420 nfs_convert_diskless();
423 * XXX splnet, so networks will receive...
428 * Do enough of ifconfig(8) so that the critical net interface can
429 * talk to the server.
431 error = socreate(nd->myif.ifra_addr.sa_family, &so, nd->root_args.sotype, 0,
434 panic("nfs_mountroot: socreate(%04x): %d",
435 nd->myif.ifra_addr.sa_family, error);
437 #if 0 /* XXX Bad idea */
439 * We might not have been told the right interface, so we pass
440 * over the first ten interfaces of the same kind, until we get
441 * one of them configured.
444 for (i = strlen(nd->myif.ifra_name) - 1;
445 nd->myif.ifra_name[i] >= '0' &&
446 nd->myif.ifra_name[i] <= '9';
447 nd->myif.ifra_name[i] ++) {
448 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
453 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
455 panic("nfs_mountroot: SIOCAIFADDR: %d", error);
456 if ((cp = getenv("boot.netif.mtu")) != NULL) {
457 ir.ifr_mtu = strtol(cp, NULL, 10);
458 bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ);
460 error = ifioctl(so, SIOCSIFMTU, (caddr_t)&ir, td);
462 printf("nfs_mountroot: SIOCSIFMTU: %d", error);
467 * If the gateway field is filled in, set it as the default route.
468 * Note that pxeboot will set a default route of 0 if the route
469 * is not set by the DHCP server. Check also for a value of 0
470 * to avoid panicking inappropriately in that situation.
472 if (nd->mygateway.sin_len != 0 &&
473 nd->mygateway.sin_addr.s_addr != 0) {
474 struct sockaddr_in mask, sin;
476 bzero((caddr_t)&mask, sizeof(mask));
478 sin.sin_family = AF_INET;
479 sin.sin_len = sizeof(sin);
480 /* XXX MRT use table 0 for this sort of thing */
481 error = rtrequest(RTM_ADD, (struct sockaddr *)&sin,
482 (struct sockaddr *)&nd->mygateway,
483 (struct sockaddr *)&mask,
484 RTF_UP | RTF_GATEWAY, NULL);
486 panic("nfs_mountroot: RTM_ADD: %d", error);
490 * Create the rootfs mount point.
492 nd->root_args.fh = nd->root_fh;
493 nd->root_args.fhsize = nd->root_fhsize;
494 l = ntohl(nd->root_saddr.sin_addr.s_addr);
495 snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
496 (l >> 24) & 0xff, (l >> 16) & 0xff,
497 (l >> 8) & 0xff, (l >> 0) & 0xff, nd->root_hostnam);
498 printf("NFS ROOT: %s\n", buf);
499 nd->root_args.hostname = buf;
500 if ((error = nfs_mountdiskless(buf, MNT_RDONLY,
501 &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) {
506 * This is not really an nfs issue, but it is much easier to
507 * set hostname here and then let the "/etc/rc.xxx" files
508 * mount the right /var based upon its preset value.
510 bcopy(nd->my_hostnam, hostname, MAXHOSTNAMELEN);
511 hostname[MAXHOSTNAMELEN - 1] = '\0';
512 for (i = 0; i < MAXHOSTNAMELEN; i++)
513 if (hostname[i] == '\0')
515 inittodr(ntohl(nd->root_time));
520 * Internal version of mount system call for diskless setup.
523 nfs_mountdiskless(char *path, int mountflag,
524 struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
525 struct vnode **vpp, struct mount *mp)
527 struct sockaddr *nam;
531 mp->mnt_kern_flag = 0;
532 mp->mnt_flag = mountflag;
534 nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
535 if ((error = mountnfs(args, mp, nam, path, vpp,
536 td->td_ucred)) != 0) {
537 printf("nfs_mountroot: mount %s on /: %d\n", path, error);
544 nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
545 const char *hostname)
555 * Set read-only flag if requested; otherwise, clear it if this is
556 * an update. If this is not an update, then either the read-only
557 * flag is already clear, or this is a root mount and it was set
558 * intentionally at some previous point.
560 if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) {
562 mp->mnt_flag |= MNT_RDONLY;
564 } else if (mp->mnt_flag & MNT_UPDATE) {
566 mp->mnt_flag &= ~MNT_RDONLY;
571 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
572 * no sense in that context. Also, set up appropriate retransmit
573 * and soft timeout behavior.
575 if (argp->sotype == SOCK_STREAM) {
576 nmp->nm_flag &= ~NFSMNT_NOCONN;
577 nmp->nm_flag |= NFSMNT_DUMBTIMR;
578 nmp->nm_timeo = NFS_MAXTIMEO;
579 nmp->nm_retry = NFS_RETRANS_TCP;
582 /* Also clear RDIRPLUS if not NFSv3, it crashes some servers */
583 if ((argp->flags & NFSMNT_NFSV3) == 0)
584 nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
586 /* Re-bind if rsrvd port requested and wasn't on one */
587 adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
588 && (argp->flags & NFSMNT_RESVPORT);
589 /* Also re-bind if we're switching to/from a connected UDP socket */
590 adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
591 (argp->flags & NFSMNT_NOCONN));
593 /* Update flags atomically. Don't change the lock bits. */
594 nmp->nm_flag = argp->flags | nmp->nm_flag;
597 if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
598 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
599 if (nmp->nm_timeo < NFS_MINTIMEO)
600 nmp->nm_timeo = NFS_MINTIMEO;
601 else if (nmp->nm_timeo > NFS_MAXTIMEO)
602 nmp->nm_timeo = NFS_MAXTIMEO;
605 if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
606 nmp->nm_retry = argp->retrans;
607 if (nmp->nm_retry > NFS_MAXREXMIT)
608 nmp->nm_retry = NFS_MAXREXMIT;
611 if (argp->flags & NFSMNT_NFSV3) {
612 if (argp->sotype == SOCK_DGRAM)
613 maxio = NFS_MAXDGRAMDATA;
617 maxio = NFS_V2MAXDATA;
619 if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
620 nmp->nm_wsize = argp->wsize;
621 /* Round down to multiple of blocksize */
622 nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
623 if (nmp->nm_wsize <= 0)
624 nmp->nm_wsize = NFS_FABLKSIZE;
626 if (nmp->nm_wsize > maxio)
627 nmp->nm_wsize = maxio;
628 if (nmp->nm_wsize > MAXBSIZE)
629 nmp->nm_wsize = MAXBSIZE;
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;
638 if (nmp->nm_rsize > maxio)
639 nmp->nm_rsize = maxio;
640 if (nmp->nm_rsize > MAXBSIZE)
641 nmp->nm_rsize = MAXBSIZE;
643 if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
644 nmp->nm_readdirsize = argp->readdirsize;
646 if (nmp->nm_readdirsize > maxio)
647 nmp->nm_readdirsize = maxio;
648 if (nmp->nm_readdirsize > nmp->nm_rsize)
649 nmp->nm_readdirsize = nmp->nm_rsize;
651 if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
652 nmp->nm_acregmin = argp->acregmin;
654 nmp->nm_acregmin = NFS_MINATTRTIMO;
655 if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
656 nmp->nm_acregmax = argp->acregmax;
658 nmp->nm_acregmax = NFS_MAXATTRTIMO;
659 if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
660 nmp->nm_acdirmin = argp->acdirmin;
662 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
663 if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
664 nmp->nm_acdirmax = argp->acdirmax;
666 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
667 if (nmp->nm_acdirmin > nmp->nm_acdirmax)
668 nmp->nm_acdirmin = nmp->nm_acdirmax;
669 if (nmp->nm_acregmin > nmp->nm_acregmax)
670 nmp->nm_acregmin = nmp->nm_acregmax;
672 if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0) {
673 if (argp->maxgrouplist <= NFS_MAXGRPS)
674 nmp->nm_numgrps = argp->maxgrouplist;
676 nmp->nm_numgrps = NFS_MAXGRPS;
678 if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
679 if (argp->readahead <= NFS_MAXRAHEAD)
680 nmp->nm_readahead = argp->readahead;
682 nmp->nm_readahead = NFS_MAXRAHEAD;
684 if ((argp->flags & NFSMNT_WCOMMITSIZE) && argp->wcommitsize >= 0) {
685 if (argp->wcommitsize < nmp->nm_wsize)
686 nmp->nm_wcommitsize = nmp->nm_wsize;
688 nmp->nm_wcommitsize = argp->wcommitsize;
690 if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 0) {
691 if (argp->deadthresh <= NFS_MAXDEADTHRESH)
692 nmp->nm_deadthresh = argp->deadthresh;
694 nmp->nm_deadthresh = NFS_MAXDEADTHRESH;
697 adjsock |= ((nmp->nm_sotype != argp->sotype) ||
698 (nmp->nm_soproto != argp->proto));
699 nmp->nm_sotype = argp->sotype;
700 nmp->nm_soproto = argp->proto;
702 if (nmp->nm_so && adjsock) {
703 nfs_safedisconnect(nmp);
704 if (nmp->nm_sotype == SOCK_DGRAM)
705 while (nfs_connect(nmp, NULL)) {
706 printf("nfs_args: retrying connect\n");
707 (void) tsleep((caddr_t)&lbolt, PSOCK, "nfscon", 0);
712 strlcpy(nmp->nm_hostname, hostname,
713 sizeof(nmp->nm_hostname));
714 p = strchr(nmp->nm_hostname, ':');
720 static const char *nfs_opts[] = { "from", "nfs_args",
721 "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
722 "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
723 "async", "dumbtimer", "noconn", "nolockd", "intr", "rdirplus", "resvport",
724 "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize",
725 "retrans", "acregmin", "acregmax", "acdirmin", "acdirmax",
726 "deadthresh", "hostname", "timeout", "addr", "fh", "nfsv3",
734 * It seems a bit dumb to copyinstr() the host and path here and then
735 * bcopy() them in mountnfs(), but I wanted to detect errors before
736 * doing the sockargs() call because sockargs() allocates an mbuf and
737 * an error after that means that I have to release the mbuf.
741 nfs_mount(struct mount *mp, struct thread *td)
743 int error, ret, has_nfs_args_opt;
744 int has_addr_opt, has_fh_opt, has_hostname_opt;
745 struct nfs_args args;
746 struct sockaddr *nam;
750 u_char nfh[NFSX_V3FHMAX];
753 has_nfs_args_opt = 0;
756 has_hostname_opt = 0;
758 if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
763 if (mp->mnt_flag & MNT_ROOTFS) {
764 error = nfs_mountroot(mp, td);
769 * The old mount_nfs program passed the struct nfs_args
770 * from userspace to kernel. The new mount_nfs program
771 * passes string options via nmount() from userspace to kernel
772 * and we populate the struct nfs_args in the kernel.
774 if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
775 error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
780 if (args.version != NFS_ARGSVERSION) {
781 error = EPROGMISMATCH;
784 has_nfs_args_opt = 1;
787 if (vfs_getopt(mp->mnt_optnew, "dumbtimer", NULL, NULL) == 0)
788 args.flags |= NFSMNT_DUMBTIMR;
789 if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
790 args.flags |= NFSMNT_NOCONN;
791 if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
792 args.flags |= NFSMNT_NOCONN;
793 if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
794 args.flags |= NFSMNT_NOLOCKD;
795 if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
796 args.flags &= ~NFSMNT_NOLOCKD;
797 if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
798 args.flags |= NFSMNT_INT;
799 if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
800 args.flags |= NFSMNT_RDIRPLUS;
801 if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
802 args.flags |= NFSMNT_RESVPORT;
803 if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
804 args.flags &= ~NFSMNT_RESVPORT;
805 if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
806 args.flags |= NFSMNT_SOFT;
807 if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
808 args.flags &= ~NFSMNT_SOFT;
809 if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
810 args.sotype = SOCK_DGRAM;
811 if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
812 args.sotype = SOCK_DGRAM;
813 if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
814 args.sotype = SOCK_STREAM;
815 if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
816 args.flags |= NFSMNT_NFSV3;
817 if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
819 vfs_mount_error(mp, "illegal readdirsize");
823 ret = sscanf(opt, "%d", &args.readdirsize);
824 if (ret != 1 || args.readdirsize <= 0) {
825 vfs_mount_error(mp, "illegal readdirsize: %s",
830 args.flags |= NFSMNT_READDIRSIZE;
832 if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
834 vfs_mount_error(mp, "illegal readahead");
838 ret = sscanf(opt, "%d", &args.readahead);
839 if (ret != 1 || args.readahead <= 0) {
840 vfs_mount_error(mp, "illegal readahead: %s",
845 args.flags |= NFSMNT_READAHEAD;
847 if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
849 vfs_mount_error(mp, "illegal wsize");
853 ret = sscanf(opt, "%d", &args.wsize);
854 if (ret != 1 || args.wsize <= 0) {
855 vfs_mount_error(mp, "illegal wsize: %s",
860 args.flags |= NFSMNT_WSIZE;
862 if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
864 vfs_mount_error(mp, "illegal rsize");
868 ret = sscanf(opt, "%d", &args.rsize);
869 if (ret != 1 || args.rsize <= 0) {
870 vfs_mount_error(mp, "illegal wsize: %s",
875 args.flags |= NFSMNT_RSIZE;
877 if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
879 vfs_mount_error(mp, "illegal retrans");
883 ret = sscanf(opt, "%d", &args.retrans);
884 if (ret != 1 || args.retrans <= 0) {
885 vfs_mount_error(mp, "illegal retrans: %s",
890 args.flags |= NFSMNT_RETRANS;
892 if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
893 ret = sscanf(opt, "%d", &args.acregmin);
894 if (ret != 1 || args.acregmin < 0) {
895 vfs_mount_error(mp, "illegal acregmin: %s",
900 args.flags |= NFSMNT_ACREGMIN;
902 if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
903 ret = sscanf(opt, "%d", &args.acregmax);
904 if (ret != 1 || args.acregmax < 0) {
905 vfs_mount_error(mp, "illegal acregmax: %s",
910 args.flags |= NFSMNT_ACREGMAX;
912 if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
913 ret = sscanf(opt, "%d", &args.acdirmin);
914 if (ret != 1 || args.acdirmin < 0) {
915 vfs_mount_error(mp, "illegal acdirmin: %s",
920 args.flags |= NFSMNT_ACDIRMIN;
922 if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
923 ret = sscanf(opt, "%d", &args.acdirmax);
924 if (ret != 1 || args.acdirmax < 0) {
925 vfs_mount_error(mp, "illegal acdirmax: %s",
930 args.flags |= NFSMNT_ACDIRMAX;
932 if (vfs_getopt(mp->mnt_optnew, "deadthresh", (void **)&opt, NULL) == 0) {
933 ret = sscanf(opt, "%d", &args.deadthresh);
934 if (ret != 1 || args.deadthresh <= 0) {
935 vfs_mount_error(mp, "illegal deadthresh: %s",
940 args.flags |= NFSMNT_DEADTHRESH;
942 if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
943 ret = sscanf(opt, "%d", &args.timeo);
944 if (ret != 1 || args.timeo <= 0) {
945 vfs_mount_error(mp, "illegal timeout: %s",
950 args.flags |= NFSMNT_TIMEO;
952 if (vfs_getopt(mp->mnt_optnew, "maxgroups", (void **)&opt, NULL) == 0) {
953 ret = sscanf(opt, "%d", &args.maxgrouplist);
954 if (ret != 1 || args.timeo <= 0) {
955 vfs_mount_error(mp, "illegal maxgroups: %s",
960 args.flags |= NFSMNT_MAXGRPS;
962 if (vfs_getopt(mp->mnt_optnew, "addr", (void **)&args.addr,
963 &args.addrlen) == 0) {
965 if (args.addrlen > SOCK_MAXADDRLEN) {
966 error = ENAMETOOLONG;
969 MALLOC(nam, struct sockaddr *, args.addrlen, M_SONAME,
971 bcopy(args.addr, nam, args.addrlen);
972 nam->sa_len = args.addrlen;
974 if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
975 &args.fhsize) == 0) {
978 if (vfs_getopt(mp->mnt_optnew, "hostname", (void **)&args.hostname,
980 has_hostname_opt = 1;
982 if (args.hostname == NULL) {
983 vfs_mount_error(mp, "Invalid hostname");
987 if (mp->mnt_flag & MNT_UPDATE) {
988 struct nfsmount *nmp = VFSTONFS(mp);
995 * When doing an update, we can't change from or to
996 * v3, switch lockd strategies or change cookie translation
998 args.flags = (args.flags &
999 ~(NFSMNT_NFSV3 | NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
1001 (NFSMNT_NFSV3 | NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
1002 nfs_decode_args(mp, nmp, &args, NULL);
1005 if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
1006 vfs_mount_error(mp, "Bad file handle");
1012 * Make the nfs_ip_paranoia sysctl serve as the default connection
1013 * or no-connection mode for those protocols that support
1014 * no-connection mode (the flag will be cleared later for protocols
1015 * that do not support no-connection mode). This will allow a client
1016 * to receive replies from a different IP then the request was
1017 * sent to. Note: default value for nfs_ip_paranoia is 1 (paranoid),
1020 if (nfs_ip_paranoia == 0)
1021 args.flags |= NFSMNT_NOCONN;
1023 if (has_nfs_args_opt) {
1025 * In the 'nfs_args' case, the pointers in the args
1026 * structure are in userland - we copy them in here.
1029 error = copyin((caddr_t)args.fh, (caddr_t)nfh,
1036 if (!has_hostname_opt) {
1037 error = copyinstr(args.hostname, hst, MNAMELEN-1, &len);
1041 bzero(&hst[len], MNAMELEN - len);
1042 args.hostname = hst;
1044 if (!has_addr_opt) {
1045 /* sockargs() call must be after above copyin() calls */
1046 error = getsockaddr(&nam, (caddr_t)args.addr,
1053 error = mountnfs(&args, mp, nam, args.hostname, &vp, td->td_ucred);
1057 mp->mnt_kern_flag |= (MNTK_MPSAFE|MNTK_LOOKUP_SHARED);
1068 * It seems a bit dumb to copyinstr() the host and path here and then
1069 * bcopy() them in mountnfs(), but I wanted to detect errors before
1070 * doing the sockargs() call because sockargs() allocates an mbuf and
1071 * an error after that means that I have to release the mbuf.
1075 nfs_cmount(struct mntarg *ma, void *data, int flags, struct thread *td)
1078 struct nfs_args args;
1080 error = copyin(data, &args, sizeof (struct nfs_args));
1084 ma = mount_arg(ma, "nfs_args", &args, sizeof args);
1086 error = kernel_mount(ma, flags);
1091 * Common code for mount and mountroot
1094 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
1095 char *hst, struct vnode **vpp, struct ucred *cred)
1097 struct nfsmount *nmp;
1102 if (mp->mnt_flag & MNT_UPDATE) {
1104 /* update paths, file handles, etc, here XXX */
1105 FREE(nam, M_SONAME);
1108 nmp = uma_zalloc(nfsmount_zone, M_WAITOK);
1109 bzero((caddr_t)nmp, sizeof (struct nfsmount));
1110 TAILQ_INIT(&nmp->nm_bufq);
1111 mp->mnt_data = (qaddr_t)nmp;
1114 nmp->nm_mountp = mp;
1115 mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF);
1118 * V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too
1119 * high, depending on whether we end up with negative offsets in
1120 * the client or server somewhere. 2GB-1 may be safer.
1122 * For V3, nfs_fsinfo will adjust this as necessary. Assume maximum
1123 * that we can handle until we find out otherwise.
1124 * XXX Our "safe" limit on the client is what we can store in our
1125 * buffer cache using signed(!) block numbers.
1127 if ((argp->flags & NFSMNT_NFSV3) == 0)
1128 nmp->nm_maxfilesize = 0xffffffffLL;
1130 nmp->nm_maxfilesize = (u_int64_t)0x80000000 * DEV_BSIZE - 1;
1132 nmp->nm_timeo = NFS_TIMEO;
1133 nmp->nm_retry = NFS_RETRANS;
1134 if ((argp->flags & NFSMNT_NFSV3) && argp->sotype == SOCK_STREAM) {
1135 nmp->nm_wsize = nmp->nm_rsize = NFS_MAXDATA;
1137 nmp->nm_wsize = NFS_WSIZE;
1138 nmp->nm_rsize = NFS_RSIZE;
1140 nmp->nm_wcommitsize = hibufspace / (desiredvnodes / 1000);
1141 nmp->nm_readdirsize = NFS_READDIRSIZE;
1142 nmp->nm_numgrps = NFS_MAXGRPS;
1143 nmp->nm_readahead = NFS_DEFRAHEAD;
1144 nmp->nm_deadthresh = NFS_MAXDEADTHRESH;
1145 nmp->nm_tprintf_delay = nfs_tprintf_delay;
1146 if (nmp->nm_tprintf_delay < 0)
1147 nmp->nm_tprintf_delay = 0;
1148 nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
1149 if (nmp->nm_tprintf_initial_delay < 0)
1150 nmp->nm_tprintf_initial_delay = 0;
1151 nmp->nm_fhsize = argp->fhsize;
1152 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
1153 bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
1155 /* Set up the sockets and per-host congestion */
1156 nmp->nm_sotype = argp->sotype;
1157 nmp->nm_soproto = argp->proto;
1158 nmp->nm_rpcops = &nfs_rpcops;
1160 nfs_decode_args(mp, nmp, argp, hst);
1163 * For Connection based sockets (TCP,...) defer the connect until
1164 * the first request, in case the server is not responding.
1166 if (nmp->nm_sotype == SOCK_DGRAM &&
1167 (error = nfs_connect(nmp, NULL)))
1171 * This is silly, but it has to be set so that vinifod() works.
1172 * We do not want to do an nfs_statfs() here since we can get
1173 * stuck on a dead server and we are holding a lock on the mount
1176 mtx_lock(&nmp->nm_mtx);
1177 mp->mnt_stat.f_iosize = nfs_iosize(nmp);
1178 mtx_unlock(&nmp->nm_mtx);
1180 * A reference count is needed on the nfsnode representing the
1181 * remote root. If this object is not persistent, then backward
1182 * traversals of the mount point (i.e. "..") will not work if
1183 * the nfsnode gets flushed out of the cache. Ufs does not have
1184 * this problem, because one can identify root inodes by their
1185 * number == ROOTINO (2).
1187 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
1193 * Get file attributes and transfer parameters for the
1194 * mountpoint. This has the side effect of filling in
1195 * (*vpp)->v_type with the correct value.
1197 if (argp->flags & NFSMNT_NFSV3)
1198 nfs_fsinfo(nmp, *vpp, curthread->td_ucred, curthread);
1200 VOP_GETATTR(*vpp, &attrs, curthread->td_ucred, curthread);
1203 * Lose the lock but keep the ref.
1205 VOP_UNLOCK(*vpp, 0, curthread);
1209 nfs_disconnect(nmp);
1210 mtx_destroy(&nmp->nm_mtx);
1211 uma_zfree(nfsmount_zone, nmp);
1212 FREE(nam, M_SONAME);
1217 * unmount system call
1220 nfs_unmount(struct mount *mp, int mntflags, struct thread *td)
1222 struct nfsmount *nmp;
1223 int error, flags = 0;
1225 if (mntflags & MNT_FORCE)
1226 flags |= FORCECLOSE;
1229 * Goes something like this..
1230 * - Call vflush() to clear out vnodes for this filesystem
1231 * - Close the socket
1232 * - Free up the data structures
1234 /* In the forced case, cancel any outstanding requests. */
1235 if (flags & FORCECLOSE) {
1236 error = nfs_nmcancelreqs(nmp);
1240 /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
1241 error = vflush(mp, 1, flags, td);
1246 * We are now committed to the unmount.
1248 nfs_disconnect(nmp);
1249 FREE(nmp->nm_nam, M_SONAME);
1251 mtx_destroy(&nmp->nm_mtx);
1252 uma_zfree(nfsmount_zone, nmp);
1258 * Return root of a filesystem
1261 nfs_root(struct mount *mp, int flags, struct vnode **vpp, struct thread *td)
1264 struct nfsmount *nmp;
1269 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, flags);
1274 * Get transfer parameters and attributes for root vnode once.
1276 mtx_lock(&nmp->nm_mtx);
1277 if ((nmp->nm_state & NFSSTA_GOTFSINFO) == 0 &&
1278 (nmp->nm_flag & NFSMNT_NFSV3)) {
1279 mtx_unlock(&nmp->nm_mtx);
1280 nfs_fsinfo(nmp, vp, curthread->td_ucred, curthread);
1282 mtx_unlock(&nmp->nm_mtx);
1283 if (vp->v_type == VNON)
1285 vp->v_vflag |= VV_ROOT;
1291 * Flush out the buffer cache
1295 nfs_sync(struct mount *mp, int waitfor, struct thread *td)
1297 struct vnode *vp, *mvp;
1298 int error, allerror = 0;
1301 * Force stale buffer cache information to be flushed.
1305 MNT_VNODE_FOREACH(vp, mp, mvp) {
1308 if (VOP_ISLOCKED(vp, NULL) ||
1309 vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
1310 waitfor == MNT_LAZY) {
1315 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
1317 MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp);
1320 error = VOP_FSYNC(vp, waitfor, td);
1323 VOP_UNLOCK(vp, 0, td);
1333 nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
1335 struct nfsmount *nmp = VFSTONFS(mp);
1339 bzero(&vq, sizeof(vq));
1342 case VFS_CTL_NOLOCKS:
1343 val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
1344 if (req->oldptr != NULL) {
1345 error = SYSCTL_OUT(req, &val, sizeof(val));
1349 if (req->newptr != NULL) {
1350 error = SYSCTL_IN(req, &val, sizeof(val));
1354 nmp->nm_flag |= NFSMNT_NOLOCKS;
1356 nmp->nm_flag &= ~NFSMNT_NOLOCKS;
1361 mtx_lock(&nmp->nm_mtx);
1362 if (nmp->nm_state & NFSSTA_TIMEO)
1363 vq.vq_flags |= VQ_NOTRESP;
1364 mtx_unlock(&nmp->nm_mtx);
1366 if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
1367 (nmp->nm_state & NFSSTA_LOCKTIMEO))
1368 vq.vq_flags |= VQ_NOTRESPLOCK;
1370 error = SYSCTL_OUT(req, &vq, sizeof(vq));
1373 if (req->oldptr != NULL) {
1374 error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
1375 sizeof(nmp->nm_tprintf_initial_delay));
1379 if (req->newptr != NULL) {
1380 error = vfs_suser(mp, req->td);
1383 error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
1384 sizeof(nmp->nm_tprintf_initial_delay));
1387 if (nmp->nm_tprintf_initial_delay < 0)
1388 nmp->nm_tprintf_initial_delay = 0;