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/vnode.h>
60 #include <sys/signalvar.h>
63 #include <vm/vm_extern.h>
67 #include <net/route.h>
70 #include <netinet/in.h>
74 #include <nfs/nfsproto.h>
75 #include <nfsclient/nfs.h>
76 #include <nfsclient/nfsnode.h>
77 #include <nfsclient/nfsmount.h>
78 #include <nfs/xdr_subs.h>
79 #include <nfsclient/nfsm_subs.h>
80 #include <nfs/nfsdiskless.h>
82 MALLOC_DEFINE(M_NFSREQ, "nfsclient_req", "NFS request header");
83 MALLOC_DEFINE(M_NFSBIGFH, "nfsclient_bigfh", "NFS version 3 file handle");
84 MALLOC_DEFINE(M_NFSDIROFF, "nfsclient_diroff", "NFS directory offset data");
85 MALLOC_DEFINE(M_NFSHASH, "nfsclient_hash", "NFS hash tables");
86 MALLOC_DEFINE(M_NFSDIRECTIO, "nfsclient_directio", "NFS Direct IO async write state");
88 uma_zone_t nfsmount_zone;
90 struct nfsstats nfsstats;
92 SYSCTL_NODE(_vfs, OID_AUTO, nfs, CTLFLAG_RW, 0, "NFS filesystem");
93 SYSCTL_STRUCT(_vfs_nfs, NFS_NFSSTATS, nfsstats, CTLFLAG_RW,
94 &nfsstats, nfsstats, "S,nfsstats");
95 static int nfs_ip_paranoia = 1;
96 SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW,
98 "Disallow accepting replies from IPs which differ from those sent");
101 SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0,
102 "Toggle debug flag");
104 static int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
105 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_INITIAL_DELAY,
106 downdelayinitial, CTLFLAG_RW, &nfs_tprintf_initial_delay, 0,
107 "Delay before printing \"nfs server not responding\" messages");
108 /* how long between console messages "nfs server foo not responding" */
109 static int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
110 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_DELAY,
111 downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0,
112 "Delay between printing \"nfs server not responding\" messages");
114 static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp,
115 struct nfs_args *argp, const char *hostname);
116 static int mountnfs(struct nfs_args *, struct mount *,
117 struct sockaddr *, char *, struct vnode **,
118 struct ucred *cred, int);
119 static void nfs_getnlminfo(struct vnode *, uint8_t *, size_t *,
120 struct sockaddr_storage *, int *, off_t *,
122 static vfs_mount_t nfs_mount;
123 static vfs_cmount_t nfs_cmount;
124 static vfs_unmount_t nfs_unmount;
125 static vfs_root_t nfs_root;
126 static vfs_statfs_t nfs_statfs;
127 static vfs_sync_t nfs_sync;
128 static vfs_sysctl_t nfs_sysctl;
130 static int fake_wchan;
133 * nfs vfs operations.
135 static struct vfsops nfs_vfsops = {
136 .vfs_init = nfs_init,
137 .vfs_mount = nfs_mount,
138 .vfs_cmount = nfs_cmount,
139 .vfs_root = nfs_root,
140 .vfs_statfs = nfs_statfs,
141 .vfs_sync = nfs_sync,
142 .vfs_uninit = nfs_uninit,
143 .vfs_unmount = nfs_unmount,
144 .vfs_sysctl = nfs_sysctl,
146 VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK);
148 /* So that loader and kldload(2) can find us, wherever we are.. */
149 MODULE_VERSION(nfs, 1);
150 MODULE_DEPEND(nfs, krpc, 1, 1, 1);
152 MODULE_DEPEND(nfs, kgssapi, 1, 1, 1);
154 MODULE_DEPEND(nfs, nfs_common, 1, 1, 1);
155 MODULE_DEPEND(nfs, nfslock, 1, 1, 1);
157 static struct nfs_rpcops nfs_rpcops = {
167 * This structure is now defined in sys/nfs/nfs_diskless.c so that it
168 * can be shared by both NFS clients. It is declared here so that it
169 * will be defined for kernels built without NFS_ROOT, although it
170 * isn't used in that case.
173 struct nfs_diskless nfs_diskless = { { { 0 } } };
174 struct nfsv3_diskless nfsv3_diskless = { { { 0 } } };
175 int nfs_diskless_valid = 0;
178 SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
179 &nfs_diskless_valid, 0,
180 "Has the diskless struct been filled correctly");
182 SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
183 nfsv3_diskless.root_hostnam, 0, "Path to nfs root");
185 SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
186 &nfsv3_diskless.root_saddr, sizeof nfsv3_diskless.root_saddr,
187 "%Ssockaddr_in", "Diskless root nfs address");
190 void nfsargs_ntoh(struct nfs_args *);
191 static int nfs_mountdiskless(char *,
192 struct sockaddr_in *, struct nfs_args *,
193 struct thread *, struct vnode **, struct mount *);
194 static void nfs_convert_diskless(void);
195 static void nfs_convert_oargs(struct nfs_args *args,
196 struct onfs_args *oargs);
199 nfs_iosize(struct nfsmount *nmp)
204 * Calculate the size used for io buffers. Use the larger
205 * of the two sizes to minimise nfs requests but make sure
206 * that it is at least one VM page to avoid wasting buffer
209 iosize = imax(nmp->nm_rsize, nmp->nm_wsize);
210 iosize = imax(iosize, PAGE_SIZE);
215 nfs_convert_oargs(struct nfs_args *args, struct onfs_args *oargs)
218 args->version = NFS_ARGSVERSION;
219 args->addr = oargs->addr;
220 args->addrlen = oargs->addrlen;
221 args->sotype = oargs->sotype;
222 args->proto = oargs->proto;
223 args->fh = oargs->fh;
224 args->fhsize = oargs->fhsize;
225 args->flags = oargs->flags;
226 args->wsize = oargs->wsize;
227 args->rsize = oargs->rsize;
228 args->readdirsize = oargs->readdirsize;
229 args->timeo = oargs->timeo;
230 args->retrans = oargs->retrans;
231 args->maxgrouplist = oargs->maxgrouplist;
232 args->readahead = oargs->readahead;
233 args->deadthresh = oargs->deadthresh;
234 args->hostname = oargs->hostname;
238 nfs_convert_diskless(void)
241 bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
242 sizeof(struct ifaliasreq));
243 bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
244 sizeof(struct sockaddr_in));
245 nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
246 if (nfsv3_diskless.root_args.flags & NFSMNT_NFSV3) {
247 nfsv3_diskless.root_fhsize = NFSX_V3FH;
248 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V3FH);
250 nfsv3_diskless.root_fhsize = NFSX_V2FH;
251 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
253 bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
254 sizeof(struct sockaddr_in));
255 bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN);
256 nfsv3_diskless.root_time = nfs_diskless.root_time;
257 bcopy(nfs_diskless.my_hostnam, nfsv3_diskless.my_hostnam,
259 nfs_diskless_valid = 3;
266 nfs_statfs(struct mount *mp, struct statfs *sbp)
270 struct nfs_statfs *sfp;
272 struct nfsmount *nmp = VFSTONFS(mp);
273 int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr;
274 struct mbuf *mreq, *mrep, *md, *mb;
282 error = vfs_busy(mp, MBF_NOWAIT);
285 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
291 mtx_lock(&nmp->nm_mtx);
292 if (v3 && (nmp->nm_state & NFSSTA_GOTFSINFO) == 0) {
293 mtx_unlock(&nmp->nm_mtx);
294 (void)nfs_fsinfo(nmp, vp, td->td_ucred, td);
296 mtx_unlock(&nmp->nm_mtx);
297 nfsstats.rpccnt[NFSPROC_FSSTAT]++;
298 mreq = nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3));
300 bpos = mtod(mb, caddr_t);
302 nfsm_request(vp, NFSPROC_FSSTAT, td, td->td_ucred);
304 nfsm_postop_attr(vp, retattr);
310 sfp = nfsm_dissect(struct nfs_statfs *, NFSX_STATFS(v3));
311 mtx_lock(&nmp->nm_mtx);
312 sbp->f_iosize = nfs_iosize(nmp);
313 mtx_unlock(&nmp->nm_mtx);
315 sbp->f_bsize = NFS_FABLKSIZE;
316 tquad = fxdr_hyper(&sfp->sf_tbytes);
317 sbp->f_blocks = tquad / NFS_FABLKSIZE;
318 tquad = fxdr_hyper(&sfp->sf_fbytes);
319 sbp->f_bfree = tquad / NFS_FABLKSIZE;
320 tquad = fxdr_hyper(&sfp->sf_abytes);
321 sbp->f_bavail = tquad / NFS_FABLKSIZE;
322 sbp->f_files = (fxdr_unsigned(int32_t,
323 sfp->sf_tfiles.nfsuquad[1]) & 0x7fffffff);
324 sbp->f_ffree = (fxdr_unsigned(int32_t,
325 sfp->sf_ffiles.nfsuquad[1]) & 0x7fffffff);
327 sbp->f_bsize = fxdr_unsigned(int32_t, sfp->sf_bsize);
328 sbp->f_blocks = fxdr_unsigned(int32_t, sfp->sf_blocks);
329 sbp->f_bfree = fxdr_unsigned(int32_t, sfp->sf_bfree);
330 sbp->f_bavail = fxdr_unsigned(int32_t, sfp->sf_bavail);
342 * nfs version 3 fsinfo rpc call
345 nfs_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred,
348 struct nfsv3_fsinfo *fsp;
351 int error = 0, retattr;
352 struct mbuf *mreq, *mrep, *md, *mb;
355 nfsstats.rpccnt[NFSPROC_FSINFO]++;
356 mreq = nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1));
358 bpos = mtod(mb, caddr_t);
360 nfsm_request(vp, NFSPROC_FSINFO, td, cred);
361 nfsm_postop_attr(vp, retattr);
363 fsp = nfsm_dissect(struct nfsv3_fsinfo *, NFSX_V3FSINFO);
364 pref = fxdr_unsigned(u_int32_t, fsp->fs_wtpref);
365 mtx_lock(&nmp->nm_mtx);
366 if (pref < nmp->nm_wsize && pref >= NFS_FABLKSIZE)
367 nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) &
368 ~(NFS_FABLKSIZE - 1);
369 max = fxdr_unsigned(u_int32_t, fsp->fs_wtmax);
370 if (max < nmp->nm_wsize && max > 0) {
371 nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1);
372 if (nmp->nm_wsize == 0)
375 pref = fxdr_unsigned(u_int32_t, fsp->fs_rtpref);
376 if (pref < nmp->nm_rsize && pref >= NFS_FABLKSIZE)
377 nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) &
378 ~(NFS_FABLKSIZE - 1);
379 max = fxdr_unsigned(u_int32_t, fsp->fs_rtmax);
380 if (max < nmp->nm_rsize && max > 0) {
381 nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1);
382 if (nmp->nm_rsize == 0)
385 pref = fxdr_unsigned(u_int32_t, fsp->fs_dtpref);
386 if (pref < nmp->nm_readdirsize && pref >= NFS_DIRBLKSIZ)
387 nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ - 1) &
388 ~(NFS_DIRBLKSIZ - 1);
389 if (max < nmp->nm_readdirsize && max > 0) {
390 nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1);
391 if (nmp->nm_readdirsize == 0)
392 nmp->nm_readdirsize = max;
394 maxfsize = fxdr_hyper(&fsp->fs_maxfilesize);
395 if (maxfsize > 0 && maxfsize < nmp->nm_maxfilesize)
396 nmp->nm_maxfilesize = maxfsize;
397 nmp->nm_mountp->mnt_stat.f_iosize = nfs_iosize(nmp);
398 nmp->nm_state |= NFSSTA_GOTFSINFO;
399 mtx_unlock(&nmp->nm_mtx);
407 * Mount a remote root fs via. nfs. This depends on the info in the
408 * nfs_diskless structure that has been filled in properly by some primary
410 * It goes something like this:
411 * - do enough of "ifconfig" by calling ifioctl() so that the system
412 * can talk to the server
413 * - If nfs_diskless.mygateway is filled in, use that address as
415 * - build the rootfs mount point and call mountnfs() to do the rest.
417 * It is assumed to be safe to read, modify, and write the nfsv3_diskless
418 * structure, as well as other global NFS client variables here, as
419 * nfs_mountroot() will be called once in the boot before any other NFS
420 * client activity occurs.
423 nfs_mountroot(struct mount *mp)
425 struct thread *td = curthread;
426 struct nfsv3_diskless *nd = &nfsv3_diskless;
436 #if defined(BOOTP_NFSROOT) && defined(BOOTP)
437 bootpc_init(); /* use bootp to get nfs_diskless filled in */
438 #elif defined(NFS_ROOT)
439 nfs_setup_diskless();
442 if (nfs_diskless_valid == 0) {
445 if (nfs_diskless_valid == 1)
446 nfs_convert_diskless();
449 * XXX splnet, so networks will receive...
454 * Do enough of ifconfig(8) so that the critical net interface can
455 * talk to the server.
457 error = socreate(nd->myif.ifra_addr.sa_family, &so, nd->root_args.sotype, 0,
460 panic("nfs_mountroot: socreate(%04x): %d",
461 nd->myif.ifra_addr.sa_family, error);
463 #if 0 /* XXX Bad idea */
465 * We might not have been told the right interface, so we pass
466 * over the first ten interfaces of the same kind, until we get
467 * one of them configured.
470 for (i = strlen(nd->myif.ifra_name) - 1;
471 nd->myif.ifra_name[i] >= '0' &&
472 nd->myif.ifra_name[i] <= '9';
473 nd->myif.ifra_name[i] ++) {
474 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
480 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
482 panic("nfs_mountroot: SIOCAIFADDR: %d", error);
484 if ((cp = getenv("boot.netif.mtu")) != NULL) {
485 ir.ifr_mtu = strtol(cp, NULL, 10);
486 bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ);
488 error = ifioctl(so, SIOCSIFMTU, (caddr_t)&ir, td);
490 printf("nfs_mountroot: SIOCSIFMTU: %d", error);
495 * If the gateway field is filled in, set it as the default route.
496 * Note that pxeboot will set a default route of 0 if the route
497 * is not set by the DHCP server. Check also for a value of 0
498 * to avoid panicking inappropriately in that situation.
500 if (nd->mygateway.sin_len != 0 &&
501 nd->mygateway.sin_addr.s_addr != 0) {
502 struct sockaddr_in mask, sin;
504 bzero((caddr_t)&mask, sizeof(mask));
506 sin.sin_family = AF_INET;
507 sin.sin_len = sizeof(sin);
508 /* XXX MRT use table 0 for this sort of thing */
509 CURVNET_SET(TD_TO_VNET(td));
510 error = rtrequest(RTM_ADD, (struct sockaddr *)&sin,
511 (struct sockaddr *)&nd->mygateway,
512 (struct sockaddr *)&mask,
513 RTF_UP | RTF_GATEWAY, NULL);
516 panic("nfs_mountroot: RTM_ADD: %d", error);
520 * Create the rootfs mount point.
522 nd->root_args.fh = nd->root_fh;
523 nd->root_args.fhsize = nd->root_fhsize;
524 l = ntohl(nd->root_saddr.sin_addr.s_addr);
525 snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
526 (l >> 24) & 0xff, (l >> 16) & 0xff,
527 (l >> 8) & 0xff, (l >> 0) & 0xff, nd->root_hostnam);
528 printf("NFS ROOT: %s\n", buf);
529 nd->root_args.hostname = buf;
530 if ((error = nfs_mountdiskless(buf,
531 &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) {
536 * This is not really an nfs issue, but it is much easier to
537 * set hostname here and then let the "/etc/rc.xxx" files
538 * mount the right /var based upon its preset value.
540 mtx_lock(&prison0.pr_mtx);
541 strlcpy(prison0.pr_hostname, nd->my_hostnam,
542 sizeof (prison0.pr_hostname));
543 mtx_unlock(&prison0.pr_mtx);
544 inittodr(ntohl(nd->root_time));
549 * Internal version of mount system call for diskless setup.
552 nfs_mountdiskless(char *path,
553 struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
554 struct vnode **vpp, struct mount *mp)
556 struct sockaddr *nam;
559 nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
560 if ((error = mountnfs(args, mp, nam, path, vpp,
561 td->td_ucred, NFS_DEFAULT_NEGNAMETIMEO)) != 0) {
562 printf("nfs_mountroot: mount %s on /: %d\n", path, error);
569 nfs_sec_name_to_num(char *sec)
571 if (!strcmp(sec, "krb5"))
572 return (RPCSEC_GSS_KRB5);
573 if (!strcmp(sec, "krb5i"))
574 return (RPCSEC_GSS_KRB5I);
575 if (!strcmp(sec, "krb5p"))
576 return (RPCSEC_GSS_KRB5P);
577 if (!strcmp(sec, "sys"))
580 * Userland should validate the string but we will try and
581 * cope with unexpected values.
587 nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
588 const char *hostname)
600 * Set read-only flag if requested; otherwise, clear it if this is
601 * an update. If this is not an update, then either the read-only
602 * flag is already clear, or this is a root mount and it was set
603 * intentionally at some previous point.
605 if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) {
607 mp->mnt_flag |= MNT_RDONLY;
609 } else if (mp->mnt_flag & MNT_UPDATE) {
611 mp->mnt_flag &= ~MNT_RDONLY;
616 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
617 * no sense in that context. Also, set up appropriate retransmit
618 * and soft timeout behavior.
620 if (argp->sotype == SOCK_STREAM) {
621 nmp->nm_flag &= ~NFSMNT_NOCONN;
622 nmp->nm_flag |= NFSMNT_DUMBTIMR;
623 nmp->nm_timeo = NFS_MAXTIMEO;
624 nmp->nm_retry = NFS_RETRANS_TCP;
627 /* Also clear RDIRPLUS if not NFSv3, it crashes some servers */
628 if ((argp->flags & NFSMNT_NFSV3) == 0)
629 nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
631 /* Re-bind if rsrvd port requested and wasn't on one */
632 adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
633 && (argp->flags & NFSMNT_RESVPORT);
634 /* Also re-bind if we're switching to/from a connected UDP socket */
635 adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
636 (argp->flags & NFSMNT_NOCONN));
638 /* Update flags atomically. Don't change the lock bits. */
639 nmp->nm_flag = argp->flags | nmp->nm_flag;
642 if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
643 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
644 if (nmp->nm_timeo < NFS_MINTIMEO)
645 nmp->nm_timeo = NFS_MINTIMEO;
646 else if (nmp->nm_timeo > NFS_MAXTIMEO)
647 nmp->nm_timeo = NFS_MAXTIMEO;
650 if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
651 nmp->nm_retry = argp->retrans;
652 if (nmp->nm_retry > NFS_MAXREXMIT)
653 nmp->nm_retry = NFS_MAXREXMIT;
656 if (argp->flags & NFSMNT_NFSV3) {
657 if (argp->sotype == SOCK_DGRAM)
658 maxio = NFS_MAXDGRAMDATA;
662 maxio = NFS_V2MAXDATA;
664 if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
665 nmp->nm_wsize = argp->wsize;
666 /* Round down to multiple of blocksize */
667 nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
668 if (nmp->nm_wsize <= 0)
669 nmp->nm_wsize = NFS_FABLKSIZE;
671 if (nmp->nm_wsize > maxio)
672 nmp->nm_wsize = maxio;
673 if (nmp->nm_wsize > MAXBSIZE)
674 nmp->nm_wsize = MAXBSIZE;
676 if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
677 nmp->nm_rsize = argp->rsize;
678 /* Round down to multiple of blocksize */
679 nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
680 if (nmp->nm_rsize <= 0)
681 nmp->nm_rsize = NFS_FABLKSIZE;
683 if (nmp->nm_rsize > maxio)
684 nmp->nm_rsize = maxio;
685 if (nmp->nm_rsize > MAXBSIZE)
686 nmp->nm_rsize = MAXBSIZE;
688 if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
689 nmp->nm_readdirsize = argp->readdirsize;
691 if (nmp->nm_readdirsize > maxio)
692 nmp->nm_readdirsize = maxio;
693 if (nmp->nm_readdirsize > nmp->nm_rsize)
694 nmp->nm_readdirsize = nmp->nm_rsize;
696 if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
697 nmp->nm_acregmin = argp->acregmin;
699 nmp->nm_acregmin = NFS_MINATTRTIMO;
700 if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
701 nmp->nm_acregmax = argp->acregmax;
703 nmp->nm_acregmax = NFS_MAXATTRTIMO;
704 if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
705 nmp->nm_acdirmin = argp->acdirmin;
707 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
708 if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
709 nmp->nm_acdirmax = argp->acdirmax;
711 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
712 if (nmp->nm_acdirmin > nmp->nm_acdirmax)
713 nmp->nm_acdirmin = nmp->nm_acdirmax;
714 if (nmp->nm_acregmin > nmp->nm_acregmax)
715 nmp->nm_acregmin = nmp->nm_acregmax;
717 if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0) {
718 if (argp->maxgrouplist <= NFS_MAXGRPS)
719 nmp->nm_numgrps = argp->maxgrouplist;
721 nmp->nm_numgrps = NFS_MAXGRPS;
723 if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
724 if (argp->readahead <= NFS_MAXRAHEAD)
725 nmp->nm_readahead = argp->readahead;
727 nmp->nm_readahead = NFS_MAXRAHEAD;
729 if ((argp->flags & NFSMNT_WCOMMITSIZE) && argp->wcommitsize >= 0) {
730 if (argp->wcommitsize < nmp->nm_wsize)
731 nmp->nm_wcommitsize = nmp->nm_wsize;
733 nmp->nm_wcommitsize = argp->wcommitsize;
735 if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 0) {
736 if (argp->deadthresh <= NFS_MAXDEADTHRESH)
737 nmp->nm_deadthresh = argp->deadthresh;
739 nmp->nm_deadthresh = NFS_MAXDEADTHRESH;
742 adjsock |= ((nmp->nm_sotype != argp->sotype) ||
743 (nmp->nm_soproto != argp->proto));
744 nmp->nm_sotype = argp->sotype;
745 nmp->nm_soproto = argp->proto;
747 if (nmp->nm_client && adjsock) {
748 nfs_safedisconnect(nmp);
749 if (nmp->nm_sotype == SOCK_DGRAM)
750 while (nfs_connect(nmp)) {
751 printf("nfs_args: retrying connect\n");
752 (void) tsleep(&fake_wchan, PSOCK, "nfscon", hz);
757 strlcpy(nmp->nm_hostname, hostname,
758 sizeof(nmp->nm_hostname));
759 p = strchr(nmp->nm_hostname, ':');
764 if (vfs_getopt(mp->mnt_optnew, "sec",
765 (void **) &secname, NULL) == 0) {
766 nmp->nm_secflavor = nfs_sec_name_to_num(secname);
768 nmp->nm_secflavor = AUTH_SYS;
771 if (vfs_getopt(mp->mnt_optnew, "principal",
772 (void **) &principal, NULL) == 0) {
773 strlcpy(nmp->nm_principal, principal,
774 sizeof(nmp->nm_principal));
776 snprintf(nmp->nm_principal, sizeof(nmp->nm_principal),
777 "nfs@%s", nmp->nm_hostname);
781 static const char *nfs_opts[] = { "from", "nfs_args",
782 "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
783 "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
784 "async", "dumbtimer", "noconn", "nolockd", "intr", "rdirplus", "resvport",
785 "readahead", "readdirsize", "soft", "hard", "mntudp", "tcp", "udp",
786 "wsize", "rsize", "retrans", "acregmin", "acregmax", "acdirmin",
787 "acdirmax", "deadthresh", "hostname", "timeout", "addr", "fh", "nfsv3",
788 "sec", "maxgroups", "principal", "negnametimeo", "nocto",
795 * It seems a bit dumb to copyinstr() the host and path here and then
796 * bcopy() them in mountnfs(), but I wanted to detect errors before
797 * doing the sockargs() call because sockargs() allocates an mbuf and
798 * an error after that means that I have to release the mbuf.
802 nfs_mount(struct mount *mp)
804 struct nfs_args args = {
805 .version = NFS_ARGSVERSION,
807 .addrlen = sizeof (struct sockaddr_in),
808 .sotype = SOCK_STREAM,
812 .flags = NFSMNT_RESVPORT,
815 .readdirsize = NFS_READDIRSIZE,
817 .retrans = NFS_RETRANS,
818 .maxgrouplist = NFS_MAXGRPS,
819 .readahead = NFS_DEFRAHEAD,
820 .wcommitsize = 0, /* was: NQ_DEFLEASE */
821 .deadthresh = NFS_MAXDEADTHRESH, /* was: NQ_DEADTHRESH */
824 .acregmin = NFS_MINATTRTIMO,
825 .acregmax = NFS_MAXATTRTIMO,
826 .acdirmin = NFS_MINDIRATTRTIMO,
827 .acdirmax = NFS_MAXDIRATTRTIMO,
829 int error, ret, has_nfs_args_opt;
830 int has_addr_opt, has_fh_opt, has_hostname_opt;
831 struct sockaddr *nam;
835 u_char nfh[NFSX_V3FHMAX];
837 int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
839 has_nfs_args_opt = 0;
842 has_hostname_opt = 0;
844 if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
849 if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS) {
850 error = nfs_mountroot(mp);
855 * The old mount_nfs program passed the struct nfs_args
856 * from userspace to kernel. The new mount_nfs program
857 * passes string options via nmount() from userspace to kernel
858 * and we populate the struct nfs_args in the kernel.
860 if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
861 error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
866 if (args.version != NFS_ARGSVERSION) {
867 error = EPROGMISMATCH;
870 has_nfs_args_opt = 1;
873 if (vfs_getopt(mp->mnt_optnew, "dumbtimer", NULL, NULL) == 0)
874 args.flags |= NFSMNT_DUMBTIMR;
875 if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
876 args.flags |= NFSMNT_NOCONN;
877 if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
878 args.flags |= NFSMNT_NOCONN;
879 if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
880 args.flags |= NFSMNT_NOLOCKD;
881 if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
882 args.flags &= ~NFSMNT_NOLOCKD;
883 if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
884 args.flags |= NFSMNT_INT;
885 if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
886 args.flags |= NFSMNT_RDIRPLUS;
887 if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
888 args.flags |= NFSMNT_RESVPORT;
889 if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
890 args.flags &= ~NFSMNT_RESVPORT;
891 if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
892 args.flags |= NFSMNT_SOFT;
893 if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
894 args.flags &= ~NFSMNT_SOFT;
895 if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
896 args.sotype = SOCK_DGRAM;
897 if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
898 args.sotype = SOCK_DGRAM;
899 if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
900 args.sotype = SOCK_STREAM;
901 if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
902 args.flags |= NFSMNT_NFSV3;
903 if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0)
904 args.flags |= NFSMNT_NOCTO;
905 if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
907 vfs_mount_error(mp, "illegal readdirsize");
911 ret = sscanf(opt, "%d", &args.readdirsize);
912 if (ret != 1 || args.readdirsize <= 0) {
913 vfs_mount_error(mp, "illegal readdirsize: %s",
918 args.flags |= NFSMNT_READDIRSIZE;
920 if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
922 vfs_mount_error(mp, "illegal readahead");
926 ret = sscanf(opt, "%d", &args.readahead);
927 if (ret != 1 || args.readahead <= 0) {
928 vfs_mount_error(mp, "illegal readahead: %s",
933 args.flags |= NFSMNT_READAHEAD;
935 if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
937 vfs_mount_error(mp, "illegal wsize");
941 ret = sscanf(opt, "%d", &args.wsize);
942 if (ret != 1 || args.wsize <= 0) {
943 vfs_mount_error(mp, "illegal wsize: %s",
948 args.flags |= NFSMNT_WSIZE;
950 if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
952 vfs_mount_error(mp, "illegal rsize");
956 ret = sscanf(opt, "%d", &args.rsize);
957 if (ret != 1 || args.rsize <= 0) {
958 vfs_mount_error(mp, "illegal wsize: %s",
963 args.flags |= NFSMNT_RSIZE;
965 if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
967 vfs_mount_error(mp, "illegal retrans");
971 ret = sscanf(opt, "%d", &args.retrans);
972 if (ret != 1 || args.retrans <= 0) {
973 vfs_mount_error(mp, "illegal retrans: %s",
978 args.flags |= NFSMNT_RETRANS;
980 if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
981 ret = sscanf(opt, "%d", &args.acregmin);
982 if (ret != 1 || args.acregmin < 0) {
983 vfs_mount_error(mp, "illegal acregmin: %s",
988 args.flags |= NFSMNT_ACREGMIN;
990 if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
991 ret = sscanf(opt, "%d", &args.acregmax);
992 if (ret != 1 || args.acregmax < 0) {
993 vfs_mount_error(mp, "illegal acregmax: %s",
998 args.flags |= NFSMNT_ACREGMAX;
1000 if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
1001 ret = sscanf(opt, "%d", &args.acdirmin);
1002 if (ret != 1 || args.acdirmin < 0) {
1003 vfs_mount_error(mp, "illegal acdirmin: %s",
1008 args.flags |= NFSMNT_ACDIRMIN;
1010 if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
1011 ret = sscanf(opt, "%d", &args.acdirmax);
1012 if (ret != 1 || args.acdirmax < 0) {
1013 vfs_mount_error(mp, "illegal acdirmax: %s",
1018 args.flags |= NFSMNT_ACDIRMAX;
1020 if (vfs_getopt(mp->mnt_optnew, "deadthresh", (void **)&opt, NULL) == 0) {
1021 ret = sscanf(opt, "%d", &args.deadthresh);
1022 if (ret != 1 || args.deadthresh <= 0) {
1023 vfs_mount_error(mp, "illegal deadthresh: %s",
1028 args.flags |= NFSMNT_DEADTHRESH;
1030 if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
1031 ret = sscanf(opt, "%d", &args.timeo);
1032 if (ret != 1 || args.timeo <= 0) {
1033 vfs_mount_error(mp, "illegal timeout: %s",
1038 args.flags |= NFSMNT_TIMEO;
1040 if (vfs_getopt(mp->mnt_optnew, "maxgroups", (void **)&opt, NULL) == 0) {
1041 ret = sscanf(opt, "%d", &args.maxgrouplist);
1042 if (ret != 1 || args.maxgrouplist <= 0) {
1043 vfs_mount_error(mp, "illegal maxgroups: %s",
1048 args.flags |= NFSMNT_MAXGRPS;
1050 if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
1052 ret = sscanf(opt, "%d", &negnametimeo);
1053 if (ret != 1 || negnametimeo < 0) {
1054 vfs_mount_error(mp, "illegal negnametimeo: %s",
1060 if (vfs_getopt(mp->mnt_optnew, "addr", (void **)&args.addr,
1061 &args.addrlen) == 0) {
1063 if (args.addrlen > SOCK_MAXADDRLEN) {
1064 error = ENAMETOOLONG;
1067 nam = malloc(args.addrlen, M_SONAME,
1069 bcopy(args.addr, nam, args.addrlen);
1070 nam->sa_len = args.addrlen;
1072 if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
1073 &args.fhsize) == 0) {
1076 if (vfs_getopt(mp->mnt_optnew, "hostname", (void **)&args.hostname,
1078 has_hostname_opt = 1;
1080 if (args.hostname == NULL) {
1081 vfs_mount_error(mp, "Invalid hostname");
1085 if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
1086 vfs_mount_error(mp, "Bad file handle");
1091 if (mp->mnt_flag & MNT_UPDATE) {
1092 struct nfsmount *nmp = VFSTONFS(mp);
1099 * When doing an update, we can't change from or to
1100 * v3, switch lockd strategies or change cookie translation
1102 args.flags = (args.flags &
1103 ~(NFSMNT_NFSV3 | NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
1105 (NFSMNT_NFSV3 | NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
1106 nfs_decode_args(mp, nmp, &args, NULL);
1111 * Make the nfs_ip_paranoia sysctl serve as the default connection
1112 * or no-connection mode for those protocols that support
1113 * no-connection mode (the flag will be cleared later for protocols
1114 * that do not support no-connection mode). This will allow a client
1115 * to receive replies from a different IP then the request was
1116 * sent to. Note: default value for nfs_ip_paranoia is 1 (paranoid),
1119 if (nfs_ip_paranoia == 0)
1120 args.flags |= NFSMNT_NOCONN;
1122 if (has_nfs_args_opt) {
1124 * In the 'nfs_args' case, the pointers in the args
1125 * structure are in userland - we copy them in here.
1128 error = copyin((caddr_t)args.fh, (caddr_t)nfh,
1135 if (!has_hostname_opt) {
1136 error = copyinstr(args.hostname, hst, MNAMELEN-1, &len);
1140 bzero(&hst[len], MNAMELEN - len);
1141 args.hostname = hst;
1143 if (!has_addr_opt) {
1144 /* sockargs() call must be after above copyin() calls */
1145 error = getsockaddr(&nam, (caddr_t)args.addr,
1151 } else if (has_addr_opt == 0) {
1152 vfs_mount_error(mp, "No server address");
1156 error = mountnfs(&args, mp, nam, args.hostname, &vp,
1157 curthread->td_ucred, negnametimeo);
1161 mp->mnt_kern_flag |= (MNTK_MPSAFE|MNTK_LOOKUP_SHARED);
1172 * It seems a bit dumb to copyinstr() the host and path here and then
1173 * bcopy() them in mountnfs(), but I wanted to detect errors before
1174 * doing the sockargs() call because sockargs() allocates an mbuf and
1175 * an error after that means that I have to release the mbuf.
1179 nfs_cmount(struct mntarg *ma, void *data, int flags)
1182 struct nfs_args args;
1184 error = copyin(data, &args, sizeof (struct nfs_args));
1188 ma = mount_arg(ma, "nfs_args", &args, sizeof args);
1190 error = kernel_mount(ma, flags);
1195 * Common code for mount and mountroot
1198 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
1199 char *hst, struct vnode **vpp, struct ucred *cred, int negnametimeo)
1201 struct nfsmount *nmp;
1206 if (mp->mnt_flag & MNT_UPDATE) {
1208 printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
1209 free(nam, M_SONAME);
1212 nmp = uma_zalloc(nfsmount_zone, M_WAITOK);
1213 bzero((caddr_t)nmp, sizeof (struct nfsmount));
1214 TAILQ_INIT(&nmp->nm_bufq);
1216 nmp->nm_getinfo = nfs_getnlminfo;
1217 nmp->nm_vinvalbuf = nfs_vinvalbuf;
1220 nmp->nm_mountp = mp;
1221 mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF);
1224 * V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too
1225 * high, depending on whether we end up with negative offsets in
1226 * the client or server somewhere. 2GB-1 may be safer.
1228 * For V3, nfs_fsinfo will adjust this as necessary. Assume maximum
1229 * that we can handle until we find out otherwise.
1231 if ((argp->flags & NFSMNT_NFSV3) == 0)
1232 nmp->nm_maxfilesize = 0xffffffffLL;
1234 nmp->nm_maxfilesize = OFF_MAX;
1236 nmp->nm_timeo = NFS_TIMEO;
1237 nmp->nm_retry = NFS_RETRANS;
1238 if ((argp->flags & NFSMNT_NFSV3) && argp->sotype == SOCK_STREAM) {
1239 nmp->nm_wsize = nmp->nm_rsize = NFS_MAXDATA;
1241 nmp->nm_wsize = NFS_WSIZE;
1242 nmp->nm_rsize = NFS_RSIZE;
1244 nmp->nm_wcommitsize = hibufspace / (desiredvnodes / 1000);
1245 nmp->nm_readdirsize = NFS_READDIRSIZE;
1246 nmp->nm_numgrps = NFS_MAXGRPS;
1247 nmp->nm_readahead = NFS_DEFRAHEAD;
1248 nmp->nm_deadthresh = NFS_MAXDEADTHRESH;
1249 nmp->nm_negnametimeo = negnametimeo;
1250 nmp->nm_tprintf_delay = nfs_tprintf_delay;
1251 if (nmp->nm_tprintf_delay < 0)
1252 nmp->nm_tprintf_delay = 0;
1253 nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
1254 if (nmp->nm_tprintf_initial_delay < 0)
1255 nmp->nm_tprintf_initial_delay = 0;
1256 nmp->nm_fhsize = argp->fhsize;
1257 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
1258 bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
1260 /* Set up the sockets and per-host congestion */
1261 nmp->nm_sotype = argp->sotype;
1262 nmp->nm_soproto = argp->proto;
1263 nmp->nm_rpcops = &nfs_rpcops;
1265 nfs_decode_args(mp, nmp, argp, hst);
1268 * For Connection based sockets (TCP,...) defer the connect until
1269 * the first request, in case the server is not responding.
1271 if (nmp->nm_sotype == SOCK_DGRAM &&
1272 (error = nfs_connect(nmp)))
1276 * This is silly, but it has to be set so that vinifod() works.
1277 * We do not want to do an nfs_statfs() here since we can get
1278 * stuck on a dead server and we are holding a lock on the mount
1281 mtx_lock(&nmp->nm_mtx);
1282 mp->mnt_stat.f_iosize = nfs_iosize(nmp);
1283 mtx_unlock(&nmp->nm_mtx);
1285 * A reference count is needed on the nfsnode representing the
1286 * remote root. If this object is not persistent, then backward
1287 * traversals of the mount point (i.e. "..") will not work if
1288 * the nfsnode gets flushed out of the cache. Ufs does not have
1289 * this problem, because one can identify root inodes by their
1290 * number == ROOTINO (2).
1292 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
1298 * Get file attributes and transfer parameters for the
1299 * mountpoint. This has the side effect of filling in
1300 * (*vpp)->v_type with the correct value.
1302 if (argp->flags & NFSMNT_NFSV3)
1303 nfs_fsinfo(nmp, *vpp, curthread->td_ucred, curthread);
1305 VOP_GETATTR(*vpp, &attrs, curthread->td_ucred);
1308 * Lose the lock but keep the ref.
1310 VOP_UNLOCK(*vpp, 0);
1314 nfs_disconnect(nmp);
1315 mtx_destroy(&nmp->nm_mtx);
1316 uma_zfree(nfsmount_zone, nmp);
1317 free(nam, M_SONAME);
1322 * unmount system call
1325 nfs_unmount(struct mount *mp, int mntflags)
1327 struct nfsmount *nmp;
1328 int error, flags = 0;
1330 if (mntflags & MNT_FORCE)
1331 flags |= FORCECLOSE;
1334 * Goes something like this..
1335 * - Call vflush() to clear out vnodes for this filesystem
1336 * - Close the socket
1337 * - Free up the data structures
1339 /* In the forced case, cancel any outstanding requests. */
1340 if (flags & FORCECLOSE) {
1341 error = nfs_nmcancelreqs(nmp);
1345 /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
1346 error = vflush(mp, 1, flags, curthread);
1351 * We are now committed to the unmount.
1353 nfs_disconnect(nmp);
1354 free(nmp->nm_nam, M_SONAME);
1356 mtx_destroy(&nmp->nm_mtx);
1357 uma_zfree(nfsmount_zone, nmp);
1363 * Return root of a filesystem
1366 nfs_root(struct mount *mp, int flags, struct vnode **vpp)
1369 struct nfsmount *nmp;
1374 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, flags);
1379 * Get transfer parameters and attributes for root vnode once.
1381 mtx_lock(&nmp->nm_mtx);
1382 if ((nmp->nm_state & NFSSTA_GOTFSINFO) == 0 &&
1383 (nmp->nm_flag & NFSMNT_NFSV3)) {
1384 mtx_unlock(&nmp->nm_mtx);
1385 nfs_fsinfo(nmp, vp, curthread->td_ucred, curthread);
1387 mtx_unlock(&nmp->nm_mtx);
1388 if (vp->v_type == VNON)
1390 vp->v_vflag |= VV_ROOT;
1396 * Flush out the buffer cache
1400 nfs_sync(struct mount *mp, int waitfor)
1402 struct vnode *vp, *mvp;
1404 int error, allerror = 0;
1410 * If a forced dismount is in progress, return from here so that
1411 * the umount(2) syscall doesn't get stuck in VFS_SYNC() before
1412 * calling VFS_UNMOUNT().
1414 if ((mp->mnt_kern_flag & MNTK_UNMOUNTF) != 0) {
1420 * Force stale buffer cache information to be flushed.
1423 MNT_VNODE_FOREACH(vp, mp, mvp) {
1426 /* XXX Racy bv_cnt check. */
1427 if (VOP_ISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
1428 waitfor == MNT_LAZY) {
1433 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
1435 MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp);
1438 error = VOP_FSYNC(vp, waitfor, td);
1451 nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
1453 struct nfsmount *nmp = VFSTONFS(mp);
1457 bzero(&vq, sizeof(vq));
1460 case VFS_CTL_NOLOCKS:
1461 val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
1462 if (req->oldptr != NULL) {
1463 error = SYSCTL_OUT(req, &val, sizeof(val));
1467 if (req->newptr != NULL) {
1468 error = SYSCTL_IN(req, &val, sizeof(val));
1472 nmp->nm_flag |= NFSMNT_NOLOCKS;
1474 nmp->nm_flag &= ~NFSMNT_NOLOCKS;
1479 mtx_lock(&nmp->nm_mtx);
1480 if (nmp->nm_state & NFSSTA_TIMEO)
1481 vq.vq_flags |= VQ_NOTRESP;
1482 mtx_unlock(&nmp->nm_mtx);
1484 if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
1485 (nmp->nm_state & NFSSTA_LOCKTIMEO))
1486 vq.vq_flags |= VQ_NOTRESPLOCK;
1488 error = SYSCTL_OUT(req, &vq, sizeof(vq));
1491 if (req->oldptr != NULL) {
1492 error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
1493 sizeof(nmp->nm_tprintf_initial_delay));
1497 if (req->newptr != NULL) {
1498 error = vfs_suser(mp, req->td);
1501 error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
1502 sizeof(nmp->nm_tprintf_initial_delay));
1505 if (nmp->nm_tprintf_initial_delay < 0)
1506 nmp->nm_tprintf_initial_delay = 0;
1516 * Extract the information needed by the nlm from the nfs vnode.
1519 nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp,
1520 struct sockaddr_storage *sp, int *is_v3p, off_t *sizep,
1521 struct timeval *timeop)
1523 struct nfsmount *nmp;
1524 struct nfsnode *np = VTONFS(vp);
1526 nmp = VFSTONFS(vp->v_mount);
1528 *fhlenp = (size_t)np->n_fhsize;
1530 bcopy(np->n_fhp, fhp, np->n_fhsize);
1532 bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp)));
1534 *is_v3p = NFS_ISV3(vp);
1536 *sizep = np->n_size;
1537 if (timeop != NULL) {
1538 timeop->tv_sec = nmp->nm_timeo / NFS_HZ;
1539 timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ);