2 * Copyright (c) 1989, 1993, 1995
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 4. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * @(#)nfs_vfsops.c 8.12 (Berkeley) 5/20/95
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
39 #include "opt_bootp.h"
40 #include "opt_nfsroot.h"
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
48 #include <sys/limits.h>
50 #include <sys/malloc.h>
52 #include <sys/module.h>
53 #include <sys/mount.h>
55 #include <sys/socket.h>
56 #include <sys/socketvar.h>
57 #include <sys/sockio.h>
58 #include <sys/sysctl.h>
59 #include <sys/syslog.h>
60 #include <sys/vnode.h>
61 #include <sys/signalvar.h>
64 #include <vm/vm_extern.h>
68 #include <net/if_var.h>
69 #include <net/route.h>
72 #include <netinet/in.h>
76 #include <nfs/nfsproto.h>
77 #include <nfsclient/nfs.h>
78 #include <nfsclient/nfsnode.h>
79 #include <nfsclient/nfsmount.h>
80 #include <nfs/xdr_subs.h>
81 #include <nfsclient/nfsm_subs.h>
82 #include <nfs/nfsdiskless.h>
84 FEATURE(nfsclient, "NFS client");
86 MALLOC_DEFINE(M_NFSREQ, "nfsclient_req", "NFS request header");
87 MALLOC_DEFINE(M_NFSBIGFH, "nfsclient_bigfh", "NFS version 3 file handle");
88 MALLOC_DEFINE(M_NFSDIROFF, "nfsclient_diroff", "NFS directory offset data");
89 MALLOC_DEFINE(M_NFSHASH, "nfsclient_hash", "NFS hash tables");
90 MALLOC_DEFINE(M_NFSDIRECTIO, "nfsclient_directio", "NFS Direct IO async write state");
92 uma_zone_t nfsmount_zone;
94 struct nfsstats nfsstats;
96 SYSCTL_NODE(_vfs, OID_AUTO, oldnfs, CTLFLAG_RW, 0, "Old NFS filesystem");
97 SYSCTL_STRUCT(_vfs_oldnfs, NFS_NFSSTATS, nfsstats, CTLFLAG_RW,
98 &nfsstats, nfsstats, "S,nfsstats");
99 static int nfs_ip_paranoia = 1;
100 SYSCTL_INT(_vfs_oldnfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW,
102 "Disallow accepting replies from IPs which differ from those sent");
105 SYSCTL_INT(_vfs_oldnfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0,
106 "Toggle debug flag");
108 static int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
109 SYSCTL_INT(_vfs_oldnfs, NFS_TPRINTF_INITIAL_DELAY,
110 downdelayinitial, CTLFLAG_RW, &nfs_tprintf_initial_delay, 0,
111 "Delay before printing \"nfs server not responding\" messages");
112 /* how long between console messages "nfs server foo not responding" */
113 static int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
114 SYSCTL_INT(_vfs_oldnfs, NFS_TPRINTF_DELAY,
115 downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0,
116 "Delay between printing \"nfs server not responding\" messages");
118 static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp,
119 struct nfs_args *argp, const char *hostname);
120 static int mountnfs(struct nfs_args *, struct mount *,
121 struct sockaddr *, char *, struct vnode **,
122 struct ucred *cred, int, int);
123 static void nfs_getnlminfo(struct vnode *, uint8_t *, size_t *,
124 struct sockaddr_storage *, int *, off_t *,
126 static vfs_mount_t nfs_mount;
127 static vfs_cmount_t nfs_cmount;
128 static vfs_unmount_t nfs_unmount;
129 static vfs_root_t nfs_root;
130 static vfs_statfs_t nfs_statfs;
131 static vfs_sync_t nfs_sync;
132 static vfs_sysctl_t nfs_sysctl;
134 static int fake_wchan;
137 * nfs vfs operations.
139 static struct vfsops nfs_vfsops = {
140 .vfs_init = nfs_init,
141 .vfs_mount = nfs_mount,
142 .vfs_cmount = nfs_cmount,
143 .vfs_root = nfs_root,
144 .vfs_statfs = nfs_statfs,
145 .vfs_sync = nfs_sync,
146 .vfs_uninit = nfs_uninit,
147 .vfs_unmount = nfs_unmount,
148 .vfs_sysctl = nfs_sysctl,
150 VFS_SET(nfs_vfsops, oldnfs, VFCF_NETWORK | VFCF_SBDRY);
152 /* So that loader and kldload(2) can find us, wherever we are.. */
153 MODULE_VERSION(oldnfs, 1);
154 MODULE_DEPEND(oldnfs, krpc, 1, 1, 1);
156 MODULE_DEPEND(oldnfs, kgssapi, 1, 1, 1);
158 MODULE_DEPEND(oldnfs, nfs_common, 1, 1, 1);
159 MODULE_DEPEND(oldnfs, nfslock, 1, 1, 1);
161 static struct nfs_rpcops nfs_rpcops = {
171 * This structure is now defined in sys/nfs/nfs_diskless.c so that it
172 * can be shared by both NFS clients. It is declared here so that it
173 * will be defined for kernels built without NFS_ROOT, although it
174 * isn't used in that case.
177 struct nfs_diskless nfs_diskless = { { { 0 } } };
178 struct nfsv3_diskless nfsv3_diskless = { { { 0 } } };
179 int nfs_diskless_valid = 0;
182 SYSCTL_INT(_vfs_oldnfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
183 &nfs_diskless_valid, 0,
184 "Has the diskless struct been filled correctly");
186 SYSCTL_STRING(_vfs_oldnfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
187 nfsv3_diskless.root_hostnam, 0, "Path to nfs root");
189 SYSCTL_OPAQUE(_vfs_oldnfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
190 &nfsv3_diskless.root_saddr, sizeof nfsv3_diskless.root_saddr,
191 "%Ssockaddr_in", "Diskless root nfs address");
194 void nfsargs_ntoh(struct nfs_args *);
195 static int nfs_mountdiskless(char *,
196 struct sockaddr_in *, struct nfs_args *,
197 struct thread *, struct vnode **, struct mount *);
198 static void nfs_convert_diskless(void);
199 static void nfs_convert_oargs(struct nfs_args *args,
200 struct onfs_args *oargs);
203 nfs_iosize(struct nfsmount *nmp)
208 * Calculate the size used for io buffers. Use the larger
209 * of the two sizes to minimise nfs requests but make sure
210 * that it is at least one VM page to avoid wasting buffer
213 iosize = imax(nmp->nm_rsize, nmp->nm_wsize);
214 iosize = imax(iosize, PAGE_SIZE);
219 nfs_convert_oargs(struct nfs_args *args, struct onfs_args *oargs)
222 args->version = NFS_ARGSVERSION;
223 args->addr = oargs->addr;
224 args->addrlen = oargs->addrlen;
225 args->sotype = oargs->sotype;
226 args->proto = oargs->proto;
227 args->fh = oargs->fh;
228 args->fhsize = oargs->fhsize;
229 args->flags = oargs->flags;
230 args->wsize = oargs->wsize;
231 args->rsize = oargs->rsize;
232 args->readdirsize = oargs->readdirsize;
233 args->timeo = oargs->timeo;
234 args->retrans = oargs->retrans;
235 args->maxgrouplist = oargs->maxgrouplist;
236 args->readahead = oargs->readahead;
237 args->deadthresh = oargs->deadthresh;
238 args->hostname = oargs->hostname;
242 nfs_convert_diskless(void)
245 bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
246 sizeof(struct ifaliasreq));
247 bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
248 sizeof(struct sockaddr_in));
249 nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
250 if (nfsv3_diskless.root_args.flags & NFSMNT_NFSV3) {
251 nfsv3_diskless.root_fhsize = NFSX_V3FH;
252 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V3FH);
254 nfsv3_diskless.root_fhsize = NFSX_V2FH;
255 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
257 bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
258 sizeof(struct sockaddr_in));
259 bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN);
260 nfsv3_diskless.root_time = nfs_diskless.root_time;
261 bcopy(nfs_diskless.my_hostnam, nfsv3_diskless.my_hostnam,
263 nfs_diskless_valid = 3;
270 nfs_statfs(struct mount *mp, struct statfs *sbp)
274 struct nfs_statfs *sfp;
276 struct nfsmount *nmp = VFSTONFS(mp);
277 int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr;
278 struct mbuf *mreq, *mrep, *md, *mb;
286 error = vfs_busy(mp, MBF_NOWAIT);
289 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
295 mtx_lock(&nmp->nm_mtx);
296 if (v3 && (nmp->nm_state & NFSSTA_GOTFSINFO) == 0) {
297 mtx_unlock(&nmp->nm_mtx);
298 (void)nfs_fsinfo(nmp, vp, td->td_ucred, td);
300 mtx_unlock(&nmp->nm_mtx);
301 nfsstats.rpccnt[NFSPROC_FSSTAT]++;
302 mreq = m_get2(NFSX_FH(v3), M_WAITOK, MT_DATA, 0);
304 bpos = mtod(mb, caddr_t);
306 nfsm_request(vp, NFSPROC_FSSTAT, td, td->td_ucred);
308 nfsm_postop_attr(vp, retattr);
314 sfp = nfsm_dissect(struct nfs_statfs *, NFSX_STATFS(v3));
315 mtx_lock(&nmp->nm_mtx);
316 sbp->f_iosize = nfs_iosize(nmp);
317 mtx_unlock(&nmp->nm_mtx);
319 sbp->f_bsize = NFS_FABLKSIZE;
320 tquad = fxdr_hyper(&sfp->sf_tbytes);
321 sbp->f_blocks = tquad / NFS_FABLKSIZE;
322 tquad = fxdr_hyper(&sfp->sf_fbytes);
323 sbp->f_bfree = tquad / NFS_FABLKSIZE;
324 tquad = fxdr_hyper(&sfp->sf_abytes);
325 sbp->f_bavail = tquad / NFS_FABLKSIZE;
326 sbp->f_files = (fxdr_unsigned(int32_t,
327 sfp->sf_tfiles.nfsuquad[1]) & 0x7fffffff);
328 sbp->f_ffree = (fxdr_unsigned(int32_t,
329 sfp->sf_ffiles.nfsuquad[1]) & 0x7fffffff);
331 sbp->f_bsize = fxdr_unsigned(int32_t, sfp->sf_bsize);
332 sbp->f_blocks = fxdr_unsigned(int32_t, sfp->sf_blocks);
333 sbp->f_bfree = fxdr_unsigned(int32_t, sfp->sf_bfree);
334 sbp->f_bavail = fxdr_unsigned(int32_t, sfp->sf_bavail);
346 * nfs version 3 fsinfo rpc call
349 nfs_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred,
352 struct nfsv3_fsinfo *fsp;
355 int error = 0, retattr;
356 struct mbuf *mreq, *mrep, *md, *mb;
359 nfsstats.rpccnt[NFSPROC_FSINFO]++;
360 mreq = m_get2(NFSX_FH(1), M_WAITOK, MT_DATA, 0);
362 bpos = mtod(mb, caddr_t);
364 nfsm_request(vp, NFSPROC_FSINFO, td, cred);
365 nfsm_postop_attr(vp, retattr);
367 fsp = nfsm_dissect(struct nfsv3_fsinfo *, NFSX_V3FSINFO);
368 pref = fxdr_unsigned(u_int32_t, fsp->fs_wtpref);
369 mtx_lock(&nmp->nm_mtx);
370 if (pref < nmp->nm_wsize && pref >= NFS_FABLKSIZE)
371 nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) &
372 ~(NFS_FABLKSIZE - 1);
373 max = fxdr_unsigned(u_int32_t, fsp->fs_wtmax);
374 if (max < nmp->nm_wsize && max > 0) {
375 nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1);
376 if (nmp->nm_wsize == 0)
379 pref = fxdr_unsigned(u_int32_t, fsp->fs_rtpref);
380 if (pref < nmp->nm_rsize && pref >= NFS_FABLKSIZE)
381 nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) &
382 ~(NFS_FABLKSIZE - 1);
383 max = fxdr_unsigned(u_int32_t, fsp->fs_rtmax);
384 if (max < nmp->nm_rsize && max > 0) {
385 nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1);
386 if (nmp->nm_rsize == 0)
389 pref = fxdr_unsigned(u_int32_t, fsp->fs_dtpref);
390 if (pref < nmp->nm_readdirsize && pref >= NFS_DIRBLKSIZ)
391 nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ - 1) &
392 ~(NFS_DIRBLKSIZ - 1);
393 if (max < nmp->nm_readdirsize && max > 0) {
394 nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1);
395 if (nmp->nm_readdirsize == 0)
396 nmp->nm_readdirsize = max;
398 maxfsize = fxdr_hyper(&fsp->fs_maxfilesize);
399 if (maxfsize > 0 && maxfsize < nmp->nm_maxfilesize)
400 nmp->nm_maxfilesize = maxfsize;
401 nmp->nm_mountp->mnt_stat.f_iosize = nfs_iosize(nmp);
402 nmp->nm_state |= NFSSTA_GOTFSINFO;
403 mtx_unlock(&nmp->nm_mtx);
411 * Mount a remote root fs via. nfs. This depends on the info in the
412 * nfs_diskless structure that has been filled in properly by some primary
414 * It goes something like this:
415 * - do enough of "ifconfig" by calling ifioctl() so that the system
416 * can talk to the server
417 * - If nfs_diskless.mygateway is filled in, use that address as
419 * - build the rootfs mount point and call mountnfs() to do the rest.
421 * It is assumed to be safe to read, modify, and write the nfsv3_diskless
422 * structure, as well as other global NFS client variables here, as
423 * nfs_mountroot() will be called once in the boot before any other NFS
424 * client activity occurs.
427 nfs_mountroot(struct mount *mp)
429 struct thread *td = curthread;
430 struct nfsv3_diskless *nd = &nfsv3_diskless;
440 #if defined(BOOTP_NFSROOT) && defined(BOOTP)
441 bootpc_init(); /* use bootp to get nfs_diskless filled in */
442 #elif defined(NFS_ROOT)
443 nfs_setup_diskless();
446 if (nfs_diskless_valid == 0) {
449 if (nfs_diskless_valid == 1)
450 nfs_convert_diskless();
453 * XXX splnet, so networks will receive...
458 * Do enough of ifconfig(8) so that the critical net interface can
459 * talk to the server.
461 error = socreate(nd->myif.ifra_addr.sa_family, &so, nd->root_args.sotype, 0,
464 panic("nfs_mountroot: socreate(%04x): %d",
465 nd->myif.ifra_addr.sa_family, error);
467 #if 0 /* XXX Bad idea */
469 * We might not have been told the right interface, so we pass
470 * over the first ten interfaces of the same kind, until we get
471 * one of them configured.
474 for (i = strlen(nd->myif.ifra_name) - 1;
475 nd->myif.ifra_name[i] >= '0' &&
476 nd->myif.ifra_name[i] <= '9';
477 nd->myif.ifra_name[i] ++) {
478 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
484 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
486 panic("nfs_mountroot: SIOCAIFADDR: %d", error);
488 if ((cp = getenv("boot.netif.mtu")) != NULL) {
489 ir.ifr_mtu = strtol(cp, NULL, 10);
490 bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ);
492 error = ifioctl(so, SIOCSIFMTU, (caddr_t)&ir, td);
494 printf("nfs_mountroot: SIOCSIFMTU: %d", error);
499 * If the gateway field is filled in, set it as the default route.
500 * Note that pxeboot will set a default route of 0 if the route
501 * is not set by the DHCP server. Check also for a value of 0
502 * to avoid panicking inappropriately in that situation.
504 if (nd->mygateway.sin_len != 0 &&
505 nd->mygateway.sin_addr.s_addr != 0) {
506 struct sockaddr_in mask, sin;
508 bzero((caddr_t)&mask, sizeof(mask));
510 sin.sin_family = AF_INET;
511 sin.sin_len = sizeof(sin);
512 /* XXX MRT use table 0 for this sort of thing */
513 CURVNET_SET(TD_TO_VNET(td));
514 error = rtrequest_fib(RTM_ADD, (struct sockaddr *)&sin,
515 (struct sockaddr *)&nd->mygateway,
516 (struct sockaddr *)&mask,
517 RTF_UP | RTF_GATEWAY, NULL, RT_DEFAULT_FIB);
520 panic("nfs_mountroot: RTM_ADD: %d", error);
524 * Create the rootfs mount point.
526 nd->root_args.fh = nd->root_fh;
527 nd->root_args.fhsize = nd->root_fhsize;
528 l = ntohl(nd->root_saddr.sin_addr.s_addr);
529 snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
530 (l >> 24) & 0xff, (l >> 16) & 0xff,
531 (l >> 8) & 0xff, (l >> 0) & 0xff, nd->root_hostnam);
532 printf("NFS ROOT: %s\n", buf);
533 nd->root_args.hostname = buf;
534 if ((error = nfs_mountdiskless(buf,
535 &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) {
540 * This is not really an nfs issue, but it is much easier to
541 * set hostname here and then let the "/etc/rc.xxx" files
542 * mount the right /var based upon its preset value.
544 mtx_lock(&prison0.pr_mtx);
545 strlcpy(prison0.pr_hostname, nd->my_hostnam,
546 sizeof (prison0.pr_hostname));
547 mtx_unlock(&prison0.pr_mtx);
548 inittodr(ntohl(nd->root_time));
553 * Internal version of mount system call for diskless setup.
556 nfs_mountdiskless(char *path,
557 struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
558 struct vnode **vpp, struct mount *mp)
560 struct sockaddr *nam;
563 nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
564 if ((error = mountnfs(args, mp, nam, path, vpp, td->td_ucred,
565 NFS_DEFAULT_NAMETIMEO, NFS_DEFAULT_NEGNAMETIMEO)) != 0) {
566 printf("nfs_mountroot: mount %s on /: %d\n", path, error);
573 nfs_sec_name_to_num(char *sec)
575 if (!strcmp(sec, "krb5"))
576 return (RPCSEC_GSS_KRB5);
577 if (!strcmp(sec, "krb5i"))
578 return (RPCSEC_GSS_KRB5I);
579 if (!strcmp(sec, "krb5p"))
580 return (RPCSEC_GSS_KRB5P);
581 if (!strcmp(sec, "sys"))
584 * Userland should validate the string but we will try and
585 * cope with unexpected values.
591 nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
592 const char *hostname)
604 * Set read-only flag if requested; otherwise, clear it if this is
605 * an update. If this is not an update, then either the read-only
606 * flag is already clear, or this is a root mount and it was set
607 * intentionally at some previous point.
609 if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) {
611 mp->mnt_flag |= MNT_RDONLY;
613 } else if (mp->mnt_flag & MNT_UPDATE) {
615 mp->mnt_flag &= ~MNT_RDONLY;
620 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
621 * no sense in that context. Also, set up appropriate retransmit
622 * and soft timeout behavior.
624 if (argp->sotype == SOCK_STREAM) {
625 nmp->nm_flag &= ~NFSMNT_NOCONN;
626 nmp->nm_flag |= NFSMNT_DUMBTIMR;
627 nmp->nm_timeo = NFS_MAXTIMEO;
628 nmp->nm_retry = NFS_RETRANS_TCP;
631 /* Also clear RDIRPLUS if not NFSv3, it crashes some servers */
632 if ((argp->flags & NFSMNT_NFSV3) == 0)
633 nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
635 /* Re-bind if rsrvd port requested and wasn't on one */
636 adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
637 && (argp->flags & NFSMNT_RESVPORT);
638 /* Also re-bind if we're switching to/from a connected UDP socket */
639 adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
640 (argp->flags & NFSMNT_NOCONN));
642 /* Update flags atomically. Don't change the lock bits. */
643 nmp->nm_flag = argp->flags | nmp->nm_flag;
646 if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
647 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
648 if (nmp->nm_timeo < NFS_MINTIMEO)
649 nmp->nm_timeo = NFS_MINTIMEO;
650 else if (nmp->nm_timeo > NFS_MAXTIMEO)
651 nmp->nm_timeo = NFS_MAXTIMEO;
654 if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
655 nmp->nm_retry = argp->retrans;
656 if (nmp->nm_retry > NFS_MAXREXMIT)
657 nmp->nm_retry = NFS_MAXREXMIT;
660 if (argp->flags & NFSMNT_NFSV3) {
661 if (argp->sotype == SOCK_DGRAM)
662 maxio = NFS_MAXDGRAMDATA;
666 maxio = NFS_V2MAXDATA;
668 if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
669 nmp->nm_wsize = argp->wsize;
670 /* Round down to multiple of blocksize */
671 nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
672 if (nmp->nm_wsize <= 0)
673 nmp->nm_wsize = NFS_FABLKSIZE;
675 if (nmp->nm_wsize > maxio)
676 nmp->nm_wsize = maxio;
677 if (nmp->nm_wsize > MAXBSIZE)
678 nmp->nm_wsize = MAXBSIZE;
680 if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
681 nmp->nm_rsize = argp->rsize;
682 /* Round down to multiple of blocksize */
683 nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
684 if (nmp->nm_rsize <= 0)
685 nmp->nm_rsize = NFS_FABLKSIZE;
687 if (nmp->nm_rsize > maxio)
688 nmp->nm_rsize = maxio;
689 if (nmp->nm_rsize > MAXBSIZE)
690 nmp->nm_rsize = MAXBSIZE;
692 if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
693 nmp->nm_readdirsize = argp->readdirsize;
695 if (nmp->nm_readdirsize > maxio)
696 nmp->nm_readdirsize = maxio;
697 if (nmp->nm_readdirsize > nmp->nm_rsize)
698 nmp->nm_readdirsize = nmp->nm_rsize;
700 if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
701 nmp->nm_acregmin = argp->acregmin;
703 nmp->nm_acregmin = NFS_MINATTRTIMO;
704 if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
705 nmp->nm_acregmax = argp->acregmax;
707 nmp->nm_acregmax = NFS_MAXATTRTIMO;
708 if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
709 nmp->nm_acdirmin = argp->acdirmin;
711 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
712 if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
713 nmp->nm_acdirmax = argp->acdirmax;
715 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
716 if (nmp->nm_acdirmin > nmp->nm_acdirmax)
717 nmp->nm_acdirmin = nmp->nm_acdirmax;
718 if (nmp->nm_acregmin > nmp->nm_acregmax)
719 nmp->nm_acregmin = nmp->nm_acregmax;
721 if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0) {
722 if (argp->maxgrouplist <= NFS_MAXGRPS)
723 nmp->nm_numgrps = argp->maxgrouplist;
725 nmp->nm_numgrps = NFS_MAXGRPS;
727 if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
728 if (argp->readahead <= NFS_MAXRAHEAD)
729 nmp->nm_readahead = argp->readahead;
731 nmp->nm_readahead = NFS_MAXRAHEAD;
733 if ((argp->flags & NFSMNT_WCOMMITSIZE) && argp->wcommitsize >= 0) {
734 if (argp->wcommitsize < nmp->nm_wsize)
735 nmp->nm_wcommitsize = nmp->nm_wsize;
737 nmp->nm_wcommitsize = argp->wcommitsize;
739 if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 0) {
740 if (argp->deadthresh <= NFS_MAXDEADTHRESH)
741 nmp->nm_deadthresh = argp->deadthresh;
743 nmp->nm_deadthresh = NFS_MAXDEADTHRESH;
746 adjsock |= ((nmp->nm_sotype != argp->sotype) ||
747 (nmp->nm_soproto != argp->proto));
748 nmp->nm_sotype = argp->sotype;
749 nmp->nm_soproto = argp->proto;
751 if (nmp->nm_client && adjsock) {
752 nfs_safedisconnect(nmp);
753 if (nmp->nm_sotype == SOCK_DGRAM)
754 while (nfs_connect(nmp)) {
755 printf("nfs_args: retrying connect\n");
756 (void) tsleep(&fake_wchan, PSOCK, "nfscon", hz);
761 strlcpy(nmp->nm_hostname, hostname,
762 sizeof(nmp->nm_hostname));
763 p = strchr(nmp->nm_hostname, ':');
768 if (vfs_getopt(mp->mnt_optnew, "sec",
769 (void **) &secname, NULL) == 0) {
770 nmp->nm_secflavor = nfs_sec_name_to_num(secname);
772 nmp->nm_secflavor = AUTH_SYS;
775 if (vfs_getopt(mp->mnt_optnew, "principal",
776 (void **) &principal, NULL) == 0) {
777 strlcpy(nmp->nm_principal, principal,
778 sizeof(nmp->nm_principal));
780 snprintf(nmp->nm_principal, sizeof(nmp->nm_principal),
781 "nfs@%s", nmp->nm_hostname);
785 static const char *nfs_opts[] = { "from", "nfs_args",
786 "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
787 "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
788 "async", "dumbtimer", "noconn", "nolockd", "intr", "rdirplus", "resvport",
789 "readahead", "readdirsize", "soft", "hard", "mntudp", "tcp", "udp",
790 "wsize", "rsize", "retrans", "acregmin", "acregmax", "acdirmin",
791 "acdirmax", "deadthresh", "hostname", "timeout", "addr", "fh", "nfsv3",
792 "sec", "maxgroups", "principal", "negnametimeo", "nocto", "wcommitsize",
800 * It seems a bit dumb to copyinstr() the host and path here and then
801 * bcopy() them in mountnfs(), but I wanted to detect errors before
802 * doing the sockargs() call because sockargs() allocates an mbuf and
803 * an error after that means that I have to release the mbuf.
807 nfs_mount(struct mount *mp)
809 struct nfs_args args = {
810 .version = NFS_ARGSVERSION,
812 .addrlen = sizeof (struct sockaddr_in),
813 .sotype = SOCK_STREAM,
817 .flags = NFSMNT_RESVPORT,
820 .readdirsize = NFS_READDIRSIZE,
822 .retrans = NFS_RETRANS,
823 .maxgrouplist = NFS_MAXGRPS,
824 .readahead = NFS_DEFRAHEAD,
825 .wcommitsize = 0, /* was: NQ_DEFLEASE */
826 .deadthresh = NFS_MAXDEADTHRESH, /* was: NQ_DEADTHRESH */
829 .acregmin = NFS_MINATTRTIMO,
830 .acregmax = NFS_MAXATTRTIMO,
831 .acdirmin = NFS_MINDIRATTRTIMO,
832 .acdirmax = NFS_MAXDIRATTRTIMO,
834 int error, ret, has_nfs_args_opt;
835 int has_addr_opt, has_fh_opt, has_hostname_opt;
836 struct sockaddr *nam;
840 u_char nfh[NFSX_V3FHMAX];
842 int nametimeo = NFS_DEFAULT_NAMETIMEO;
843 int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
845 has_nfs_args_opt = 0;
848 has_hostname_opt = 0;
850 if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
855 if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS) {
856 error = nfs_mountroot(mp);
861 * The old mount_nfs program passed the struct nfs_args
862 * from userspace to kernel. The new mount_nfs program
863 * passes string options via nmount() from userspace to kernel
864 * and we populate the struct nfs_args in the kernel.
866 if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
867 error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
872 if (args.version != NFS_ARGSVERSION) {
873 error = EPROGMISMATCH;
876 has_nfs_args_opt = 1;
879 if (vfs_getopt(mp->mnt_optnew, "dumbtimer", NULL, NULL) == 0)
880 args.flags |= NFSMNT_DUMBTIMR;
881 if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
882 args.flags |= NFSMNT_NOCONN;
883 if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
884 args.flags |= NFSMNT_NOCONN;
885 if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
886 args.flags |= NFSMNT_NOLOCKD;
887 if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
888 args.flags &= ~NFSMNT_NOLOCKD;
889 if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
890 args.flags |= NFSMNT_INT;
891 if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
892 args.flags |= NFSMNT_RDIRPLUS;
893 if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
894 args.flags |= NFSMNT_RESVPORT;
895 if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
896 args.flags &= ~NFSMNT_RESVPORT;
897 if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
898 args.flags |= NFSMNT_SOFT;
899 if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
900 args.flags &= ~NFSMNT_SOFT;
901 if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
902 args.sotype = SOCK_DGRAM;
903 if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
904 args.sotype = SOCK_DGRAM;
905 if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
906 args.sotype = SOCK_STREAM;
907 if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
908 args.flags |= NFSMNT_NFSV3;
909 if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0)
910 args.flags |= NFSMNT_NOCTO;
911 if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
913 vfs_mount_error(mp, "illegal readdirsize");
917 ret = sscanf(opt, "%d", &args.readdirsize);
918 if (ret != 1 || args.readdirsize <= 0) {
919 vfs_mount_error(mp, "illegal readdirsize: %s",
924 args.flags |= NFSMNT_READDIRSIZE;
926 if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
928 vfs_mount_error(mp, "illegal readahead");
932 ret = sscanf(opt, "%d", &args.readahead);
933 if (ret != 1 || args.readahead <= 0) {
934 vfs_mount_error(mp, "illegal readahead: %s",
939 args.flags |= NFSMNT_READAHEAD;
941 if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
943 vfs_mount_error(mp, "illegal wsize");
947 ret = sscanf(opt, "%d", &args.wsize);
948 if (ret != 1 || args.wsize <= 0) {
949 vfs_mount_error(mp, "illegal wsize: %s",
954 args.flags |= NFSMNT_WSIZE;
956 if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
958 vfs_mount_error(mp, "illegal rsize");
962 ret = sscanf(opt, "%d", &args.rsize);
963 if (ret != 1 || args.rsize <= 0) {
964 vfs_mount_error(mp, "illegal wsize: %s",
969 args.flags |= NFSMNT_RSIZE;
971 if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
973 vfs_mount_error(mp, "illegal retrans");
977 ret = sscanf(opt, "%d", &args.retrans);
978 if (ret != 1 || args.retrans <= 0) {
979 vfs_mount_error(mp, "illegal retrans: %s",
984 args.flags |= NFSMNT_RETRANS;
986 if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
987 ret = sscanf(opt, "%d", &args.acregmin);
988 if (ret != 1 || args.acregmin < 0) {
989 vfs_mount_error(mp, "illegal acregmin: %s",
994 args.flags |= NFSMNT_ACREGMIN;
996 if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
997 ret = sscanf(opt, "%d", &args.acregmax);
998 if (ret != 1 || args.acregmax < 0) {
999 vfs_mount_error(mp, "illegal acregmax: %s",
1004 args.flags |= NFSMNT_ACREGMAX;
1006 if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
1007 ret = sscanf(opt, "%d", &args.acdirmin);
1008 if (ret != 1 || args.acdirmin < 0) {
1009 vfs_mount_error(mp, "illegal acdirmin: %s",
1014 args.flags |= NFSMNT_ACDIRMIN;
1016 if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
1017 ret = sscanf(opt, "%d", &args.acdirmax);
1018 if (ret != 1 || args.acdirmax < 0) {
1019 vfs_mount_error(mp, "illegal acdirmax: %s",
1024 args.flags |= NFSMNT_ACDIRMAX;
1026 if (vfs_getopt(mp->mnt_optnew, "wcommitsize", (void **)&opt, NULL) == 0) {
1027 ret = sscanf(opt, "%d", &args.wcommitsize);
1028 if (ret != 1 || args.wcommitsize < 0) {
1029 vfs_mount_error(mp, "illegal wcommitsize: %s", opt);
1033 args.flags |= NFSMNT_WCOMMITSIZE;
1035 if (vfs_getopt(mp->mnt_optnew, "deadthresh", (void **)&opt, NULL) == 0) {
1036 ret = sscanf(opt, "%d", &args.deadthresh);
1037 if (ret != 1 || args.deadthresh <= 0) {
1038 vfs_mount_error(mp, "illegal deadthresh: %s",
1043 args.flags |= NFSMNT_DEADTHRESH;
1045 if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
1046 ret = sscanf(opt, "%d", &args.timeo);
1047 if (ret != 1 || args.timeo <= 0) {
1048 vfs_mount_error(mp, "illegal timeout: %s",
1053 args.flags |= NFSMNT_TIMEO;
1055 if (vfs_getopt(mp->mnt_optnew, "maxgroups", (void **)&opt, NULL) == 0) {
1056 ret = sscanf(opt, "%d", &args.maxgrouplist);
1057 if (ret != 1 || args.maxgrouplist <= 0) {
1058 vfs_mount_error(mp, "illegal maxgroups: %s",
1063 args.flags |= NFSMNT_MAXGRPS;
1065 if (vfs_getopt(mp->mnt_optnew, "nametimeo", (void **)&opt, NULL) == 0) {
1066 ret = sscanf(opt, "%d", &nametimeo);
1067 if (ret != 1 || nametimeo < 0) {
1068 vfs_mount_error(mp, "illegal nametimeo: %s", opt);
1073 if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
1075 ret = sscanf(opt, "%d", &negnametimeo);
1076 if (ret != 1 || negnametimeo < 0) {
1077 vfs_mount_error(mp, "illegal negnametimeo: %s",
1083 if (vfs_getopt(mp->mnt_optnew, "addr", (void **)&args.addr,
1084 &args.addrlen) == 0) {
1086 if (args.addrlen > SOCK_MAXADDRLEN) {
1087 error = ENAMETOOLONG;
1090 nam = malloc(args.addrlen, M_SONAME,
1092 bcopy(args.addr, nam, args.addrlen);
1093 nam->sa_len = args.addrlen;
1095 if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
1096 &args.fhsize) == 0) {
1099 if (vfs_getopt(mp->mnt_optnew, "hostname", (void **)&args.hostname,
1101 has_hostname_opt = 1;
1103 if (args.hostname == NULL) {
1104 vfs_mount_error(mp, "Invalid hostname");
1108 if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
1109 vfs_mount_error(mp, "Bad file handle");
1114 if (mp->mnt_flag & MNT_UPDATE) {
1115 struct nfsmount *nmp = VFSTONFS(mp);
1123 * If a change from TCP->UDP is done and there are thread(s)
1124 * that have I/O RPC(s) in progress with a tranfer size
1125 * greater than NFS_MAXDGRAMDATA, those thread(s) will be
1126 * hung, retrying the RPC(s) forever. Usually these threads
1127 * will be seen doing an uninterruptible sleep on wait channel
1128 * "newnfsreq" (truncated to "newnfsre" by procstat).
1130 if (args.sotype == SOCK_DGRAM && nmp->nm_sotype == SOCK_STREAM)
1131 tprintf(curthread->td_proc, LOG_WARNING,
1132 "Warning: mount -u that changes TCP->UDP can result in hung threads\n");
1135 * When doing an update, we can't change from or to
1136 * v3, switch lockd strategies or change cookie translation
1138 args.flags = (args.flags &
1139 ~(NFSMNT_NFSV3 | NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
1141 (NFSMNT_NFSV3 | NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
1142 nfs_decode_args(mp, nmp, &args, NULL);
1147 * Make the nfs_ip_paranoia sysctl serve as the default connection
1148 * or no-connection mode for those protocols that support
1149 * no-connection mode (the flag will be cleared later for protocols
1150 * that do not support no-connection mode). This will allow a client
1151 * to receive replies from a different IP then the request was
1152 * sent to. Note: default value for nfs_ip_paranoia is 1 (paranoid),
1155 if (nfs_ip_paranoia == 0)
1156 args.flags |= NFSMNT_NOCONN;
1158 if (has_nfs_args_opt) {
1160 * In the 'nfs_args' case, the pointers in the args
1161 * structure are in userland - we copy them in here.
1164 error = copyin((caddr_t)args.fh, (caddr_t)nfh,
1171 if (!has_hostname_opt) {
1172 error = copyinstr(args.hostname, hst, MNAMELEN-1, &len);
1176 bzero(&hst[len], MNAMELEN - len);
1177 args.hostname = hst;
1179 if (!has_addr_opt) {
1180 /* sockargs() call must be after above copyin() calls */
1181 error = getsockaddr(&nam, (caddr_t)args.addr,
1187 } else if (has_addr_opt == 0) {
1188 vfs_mount_error(mp, "No server address");
1192 error = mountnfs(&args, mp, nam, args.hostname, &vp,
1193 curthread->td_ucred, nametimeo, negnametimeo);
1197 mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED;
1208 * It seems a bit dumb to copyinstr() the host and path here and then
1209 * bcopy() them in mountnfs(), but I wanted to detect errors before
1210 * doing the sockargs() call because sockargs() allocates an mbuf and
1211 * an error after that means that I have to release the mbuf.
1215 nfs_cmount(struct mntarg *ma, void *data, uint64_t flags)
1218 struct nfs_args args;
1220 error = copyin(data, &args, sizeof (struct nfs_args));
1224 ma = mount_arg(ma, "nfs_args", &args, sizeof args);
1226 error = kernel_mount(ma, flags);
1231 * Common code for mount and mountroot
1234 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
1235 char *hst, struct vnode **vpp, struct ucred *cred, int nametimeo,
1238 struct nfsmount *nmp;
1243 if (mp->mnt_flag & MNT_UPDATE) {
1245 printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
1246 free(nam, M_SONAME);
1249 nmp = uma_zalloc(nfsmount_zone, M_WAITOK);
1250 bzero((caddr_t)nmp, sizeof (struct nfsmount));
1251 TAILQ_INIT(&nmp->nm_bufq);
1253 nmp->nm_getinfo = nfs_getnlminfo;
1254 nmp->nm_vinvalbuf = nfs_vinvalbuf;
1257 nmp->nm_mountp = mp;
1258 mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF);
1261 * V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too
1262 * high, depending on whether we end up with negative offsets in
1263 * the client or server somewhere. 2GB-1 may be safer.
1265 * For V3, nfs_fsinfo will adjust this as necessary. Assume maximum
1266 * that we can handle until we find out otherwise.
1268 if ((argp->flags & NFSMNT_NFSV3) == 0)
1269 nmp->nm_maxfilesize = 0xffffffffLL;
1271 nmp->nm_maxfilesize = OFF_MAX;
1273 nmp->nm_timeo = NFS_TIMEO;
1274 nmp->nm_retry = NFS_RETRANS;
1275 if ((argp->flags & NFSMNT_NFSV3) && argp->sotype == SOCK_STREAM) {
1276 nmp->nm_wsize = nmp->nm_rsize = NFS_MAXDATA;
1278 nmp->nm_wsize = NFS_WSIZE;
1279 nmp->nm_rsize = NFS_RSIZE;
1281 nmp->nm_wcommitsize = hibufspace / (desiredvnodes / 1000);
1282 nmp->nm_readdirsize = NFS_READDIRSIZE;
1283 nmp->nm_numgrps = NFS_MAXGRPS;
1284 nmp->nm_readahead = NFS_DEFRAHEAD;
1285 nmp->nm_deadthresh = NFS_MAXDEADTHRESH;
1286 nmp->nm_nametimeo = nametimeo;
1287 nmp->nm_negnametimeo = negnametimeo;
1288 nmp->nm_tprintf_delay = nfs_tprintf_delay;
1289 if (nmp->nm_tprintf_delay < 0)
1290 nmp->nm_tprintf_delay = 0;
1291 nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
1292 if (nmp->nm_tprintf_initial_delay < 0)
1293 nmp->nm_tprintf_initial_delay = 0;
1294 nmp->nm_fhsize = argp->fhsize;
1295 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
1296 bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
1298 /* Set up the sockets and per-host congestion */
1299 nmp->nm_sotype = argp->sotype;
1300 nmp->nm_soproto = argp->proto;
1301 nmp->nm_rpcops = &nfs_rpcops;
1303 nfs_decode_args(mp, nmp, argp, hst);
1306 * For Connection based sockets (TCP,...) defer the connect until
1307 * the first request, in case the server is not responding.
1309 if (nmp->nm_sotype == SOCK_DGRAM &&
1310 (error = nfs_connect(nmp)))
1314 * This is silly, but it has to be set so that vinifod() works.
1315 * We do not want to do an nfs_statfs() here since we can get
1316 * stuck on a dead server and we are holding a lock on the mount
1319 mtx_lock(&nmp->nm_mtx);
1320 mp->mnt_stat.f_iosize = nfs_iosize(nmp);
1321 mtx_unlock(&nmp->nm_mtx);
1323 * A reference count is needed on the nfsnode representing the
1324 * remote root. If this object is not persistent, then backward
1325 * traversals of the mount point (i.e. "..") will not work if
1326 * the nfsnode gets flushed out of the cache. Ufs does not have
1327 * this problem, because one can identify root inodes by their
1328 * number == ROOTINO (2).
1330 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
1336 * Get file attributes and transfer parameters for the
1337 * mountpoint. This has the side effect of filling in
1338 * (*vpp)->v_type with the correct value.
1340 if (argp->flags & NFSMNT_NFSV3)
1341 nfs_fsinfo(nmp, *vpp, curthread->td_ucred, curthread);
1343 VOP_GETATTR(*vpp, &attrs, curthread->td_ucred);
1346 * Lose the lock but keep the ref.
1348 VOP_UNLOCK(*vpp, 0);
1352 nfs_disconnect(nmp);
1353 mtx_destroy(&nmp->nm_mtx);
1354 uma_zfree(nfsmount_zone, nmp);
1355 free(nam, M_SONAME);
1360 * unmount system call
1363 nfs_unmount(struct mount *mp, int mntflags)
1365 struct nfsmount *nmp;
1366 int error, flags = 0, i;
1368 if (mntflags & MNT_FORCE)
1369 flags |= FORCECLOSE;
1372 * Goes something like this..
1373 * - Call vflush() to clear out vnodes for this filesystem
1374 * - Close the socket
1375 * - Free up the data structures
1377 /* In the forced case, cancel any outstanding requests. */
1378 if (flags & FORCECLOSE) {
1379 error = nfs_nmcancelreqs(nmp);
1383 /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
1384 error = vflush(mp, 1, flags, curthread);
1389 * We are now committed to the unmount.
1391 /* Make sure no nfsiods are assigned to this mount. */
1392 mtx_lock(&nfs_iod_mtx);
1393 for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
1394 if (nfs_iodmount[i] == nmp) {
1395 nfs_iodwant[i] = NFSIOD_AVAILABLE;
1396 nfs_iodmount[i] = NULL;
1398 mtx_unlock(&nfs_iod_mtx);
1399 nfs_disconnect(nmp);
1400 free(nmp->nm_nam, M_SONAME);
1402 mtx_destroy(&nmp->nm_mtx);
1403 uma_zfree(nfsmount_zone, nmp);
1409 * Return root of a filesystem
1412 nfs_root(struct mount *mp, int flags, struct vnode **vpp)
1415 struct nfsmount *nmp;
1420 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, flags);
1425 * Get transfer parameters and attributes for root vnode once.
1427 mtx_lock(&nmp->nm_mtx);
1428 if ((nmp->nm_state & NFSSTA_GOTFSINFO) == 0 &&
1429 (nmp->nm_flag & NFSMNT_NFSV3)) {
1430 mtx_unlock(&nmp->nm_mtx);
1431 nfs_fsinfo(nmp, vp, curthread->td_ucred, curthread);
1433 mtx_unlock(&nmp->nm_mtx);
1434 if (vp->v_type == VNON)
1436 vp->v_vflag |= VV_ROOT;
1442 * Flush out the buffer cache
1446 nfs_sync(struct mount *mp, int waitfor)
1448 struct vnode *vp, *mvp;
1450 int error, allerror = 0;
1456 * If a forced dismount is in progress, return from here so that
1457 * the umount(2) syscall doesn't get stuck in VFS_SYNC() before
1458 * calling VFS_UNMOUNT().
1460 if ((mp->mnt_kern_flag & MNTK_UNMOUNTF) != 0) {
1467 * Force stale buffer cache information to be flushed.
1470 MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
1471 /* XXX Racy bv_cnt check. */
1472 if (VOP_ISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
1473 waitfor == MNT_LAZY) {
1477 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
1478 MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
1481 error = VOP_FSYNC(vp, waitfor, td);
1491 nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
1493 struct nfsmount *nmp = VFSTONFS(mp);
1497 bzero(&vq, sizeof(vq));
1500 case VFS_CTL_NOLOCKS:
1501 val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
1502 if (req->oldptr != NULL) {
1503 error = SYSCTL_OUT(req, &val, sizeof(val));
1507 if (req->newptr != NULL) {
1508 error = SYSCTL_IN(req, &val, sizeof(val));
1512 nmp->nm_flag |= NFSMNT_NOLOCKS;
1514 nmp->nm_flag &= ~NFSMNT_NOLOCKS;
1519 mtx_lock(&nmp->nm_mtx);
1520 if (nmp->nm_state & NFSSTA_TIMEO)
1521 vq.vq_flags |= VQ_NOTRESP;
1522 mtx_unlock(&nmp->nm_mtx);
1524 if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
1525 (nmp->nm_state & NFSSTA_LOCKTIMEO))
1526 vq.vq_flags |= VQ_NOTRESPLOCK;
1528 error = SYSCTL_OUT(req, &vq, sizeof(vq));
1531 if (req->oldptr != NULL) {
1532 error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
1533 sizeof(nmp->nm_tprintf_initial_delay));
1537 if (req->newptr != NULL) {
1538 error = vfs_suser(mp, req->td);
1541 error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
1542 sizeof(nmp->nm_tprintf_initial_delay));
1545 if (nmp->nm_tprintf_initial_delay < 0)
1546 nmp->nm_tprintf_initial_delay = 0;
1556 * Extract the information needed by the nlm from the nfs vnode.
1559 nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp,
1560 struct sockaddr_storage *sp, int *is_v3p, off_t *sizep,
1561 struct timeval *timeop)
1563 struct nfsmount *nmp;
1564 struct nfsnode *np = VTONFS(vp);
1566 nmp = VFSTONFS(vp->v_mount);
1568 *fhlenp = (size_t)np->n_fhsize;
1570 bcopy(np->n_fhp, fhp, np->n_fhsize);
1572 bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp)));
1574 *is_v3p = NFS_ISV3(vp);
1576 *sizep = np->n_size;
1577 if (timeop != NULL) {
1578 timeop->tv_sec = nmp->nm_timeo / NFS_HZ;
1579 timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ);