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 FEATURE(nfsclient, "NFS client");
84 MALLOC_DEFINE(M_NFSREQ, "nfsclient_req", "NFS request header");
85 MALLOC_DEFINE(M_NFSBIGFH, "nfsclient_bigfh", "NFS version 3 file handle");
86 MALLOC_DEFINE(M_NFSDIROFF, "nfsclient_diroff", "NFS directory offset data");
87 MALLOC_DEFINE(M_NFSHASH, "nfsclient_hash", "NFS hash tables");
88 MALLOC_DEFINE(M_NFSDIRECTIO, "nfsclient_directio", "NFS Direct IO async write state");
90 uma_zone_t nfsmount_zone;
92 struct nfsstats nfsstats;
94 SYSCTL_NODE(_vfs, OID_AUTO, oldnfs, CTLFLAG_RW, 0, "Old NFS filesystem");
95 SYSCTL_STRUCT(_vfs_oldnfs, NFS_NFSSTATS, nfsstats, CTLFLAG_RW,
96 &nfsstats, nfsstats, "S,nfsstats");
97 static int nfs_ip_paranoia = 1;
98 SYSCTL_INT(_vfs_oldnfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW,
100 "Disallow accepting replies from IPs which differ from those sent");
103 SYSCTL_INT(_vfs_oldnfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0,
104 "Toggle debug flag");
106 static int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
107 SYSCTL_INT(_vfs_oldnfs, NFS_TPRINTF_INITIAL_DELAY,
108 downdelayinitial, CTLFLAG_RW, &nfs_tprintf_initial_delay, 0,
109 "Delay before printing \"nfs server not responding\" messages");
110 /* how long between console messages "nfs server foo not responding" */
111 static int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
112 SYSCTL_INT(_vfs_oldnfs, NFS_TPRINTF_DELAY,
113 downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0,
114 "Delay between printing \"nfs server not responding\" messages");
116 static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp,
117 struct nfs_args *argp, const char *hostname);
118 static int mountnfs(struct nfs_args *, struct mount *,
119 struct sockaddr *, char *, struct vnode **,
120 struct ucred *cred, int);
121 static void nfs_getnlminfo(struct vnode *, uint8_t *, size_t *,
122 struct sockaddr_storage *, int *, off_t *,
124 static vfs_mount_t nfs_mount;
125 static vfs_cmount_t nfs_cmount;
126 static vfs_unmount_t nfs_unmount;
127 static vfs_root_t nfs_root;
128 static vfs_statfs_t nfs_statfs;
129 static vfs_sync_t nfs_sync;
130 static vfs_sysctl_t nfs_sysctl;
132 static int fake_wchan;
135 * nfs vfs operations.
137 static struct vfsops nfs_vfsops = {
138 .vfs_init = nfs_init,
139 .vfs_mount = nfs_mount,
140 .vfs_cmount = nfs_cmount,
141 .vfs_root = nfs_root,
142 .vfs_statfs = nfs_statfs,
143 .vfs_sync = nfs_sync,
144 .vfs_uninit = nfs_uninit,
145 .vfs_unmount = nfs_unmount,
146 .vfs_sysctl = nfs_sysctl,
148 VFS_SET(nfs_vfsops, oldnfs, VFCF_NETWORK);
150 /* So that loader and kldload(2) can find us, wherever we are.. */
151 MODULE_VERSION(oldnfs, 1);
152 MODULE_DEPEND(oldnfs, krpc, 1, 1, 1);
154 MODULE_DEPEND(oldnfs, kgssapi, 1, 1, 1);
156 MODULE_DEPEND(oldnfs, nfs_common, 1, 1, 1);
157 MODULE_DEPEND(oldnfs, nfslock, 1, 1, 1);
159 static struct nfs_rpcops nfs_rpcops = {
169 * This structure is now defined in sys/nfs/nfs_diskless.c so that it
170 * can be shared by both NFS clients. It is declared here so that it
171 * will be defined for kernels built without NFS_ROOT, although it
172 * isn't used in that case.
175 struct nfs_diskless nfs_diskless = { { { 0 } } };
176 struct nfsv3_diskless nfsv3_diskless = { { { 0 } } };
177 int nfs_diskless_valid = 0;
180 SYSCTL_INT(_vfs_oldnfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
181 &nfs_diskless_valid, 0,
182 "Has the diskless struct been filled correctly");
184 SYSCTL_STRING(_vfs_oldnfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
185 nfsv3_diskless.root_hostnam, 0, "Path to nfs root");
187 SYSCTL_OPAQUE(_vfs_oldnfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
188 &nfsv3_diskless.root_saddr, sizeof nfsv3_diskless.root_saddr,
189 "%Ssockaddr_in", "Diskless root nfs address");
192 void nfsargs_ntoh(struct nfs_args *);
193 static int nfs_mountdiskless(char *,
194 struct sockaddr_in *, struct nfs_args *,
195 struct thread *, struct vnode **, struct mount *);
196 static void nfs_convert_diskless(void);
197 static void nfs_convert_oargs(struct nfs_args *args,
198 struct onfs_args *oargs);
201 nfs_iosize(struct nfsmount *nmp)
206 * Calculate the size used for io buffers. Use the larger
207 * of the two sizes to minimise nfs requests but make sure
208 * that it is at least one VM page to avoid wasting buffer
211 iosize = imax(nmp->nm_rsize, nmp->nm_wsize);
212 iosize = imax(iosize, PAGE_SIZE);
217 nfs_convert_oargs(struct nfs_args *args, struct onfs_args *oargs)
220 args->version = NFS_ARGSVERSION;
221 args->addr = oargs->addr;
222 args->addrlen = oargs->addrlen;
223 args->sotype = oargs->sotype;
224 args->proto = oargs->proto;
225 args->fh = oargs->fh;
226 args->fhsize = oargs->fhsize;
227 args->flags = oargs->flags;
228 args->wsize = oargs->wsize;
229 args->rsize = oargs->rsize;
230 args->readdirsize = oargs->readdirsize;
231 args->timeo = oargs->timeo;
232 args->retrans = oargs->retrans;
233 args->maxgrouplist = oargs->maxgrouplist;
234 args->readahead = oargs->readahead;
235 args->deadthresh = oargs->deadthresh;
236 args->hostname = oargs->hostname;
240 nfs_convert_diskless(void)
243 bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
244 sizeof(struct ifaliasreq));
245 bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
246 sizeof(struct sockaddr_in));
247 nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
248 if (nfsv3_diskless.root_args.flags & NFSMNT_NFSV3) {
249 nfsv3_diskless.root_fhsize = NFSX_V3FH;
250 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V3FH);
252 nfsv3_diskless.root_fhsize = NFSX_V2FH;
253 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
255 bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
256 sizeof(struct sockaddr_in));
257 bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN);
258 nfsv3_diskless.root_time = nfs_diskless.root_time;
259 bcopy(nfs_diskless.my_hostnam, nfsv3_diskless.my_hostnam,
261 nfs_diskless_valid = 3;
268 nfs_statfs(struct mount *mp, struct statfs *sbp)
272 struct nfs_statfs *sfp;
274 struct nfsmount *nmp = VFSTONFS(mp);
275 int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr;
276 struct mbuf *mreq, *mrep, *md, *mb;
284 error = vfs_busy(mp, MBF_NOWAIT);
287 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
293 mtx_lock(&nmp->nm_mtx);
294 if (v3 && (nmp->nm_state & NFSSTA_GOTFSINFO) == 0) {
295 mtx_unlock(&nmp->nm_mtx);
296 (void)nfs_fsinfo(nmp, vp, td->td_ucred, td);
298 mtx_unlock(&nmp->nm_mtx);
299 nfsstats.rpccnt[NFSPROC_FSSTAT]++;
300 mreq = nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3));
302 bpos = mtod(mb, caddr_t);
304 nfsm_request(vp, NFSPROC_FSSTAT, td, td->td_ucred);
306 nfsm_postop_attr(vp, retattr);
312 sfp = nfsm_dissect(struct nfs_statfs *, NFSX_STATFS(v3));
313 mtx_lock(&nmp->nm_mtx);
314 sbp->f_iosize = nfs_iosize(nmp);
315 mtx_unlock(&nmp->nm_mtx);
317 sbp->f_bsize = NFS_FABLKSIZE;
318 tquad = fxdr_hyper(&sfp->sf_tbytes);
319 sbp->f_blocks = tquad / NFS_FABLKSIZE;
320 tquad = fxdr_hyper(&sfp->sf_fbytes);
321 sbp->f_bfree = tquad / NFS_FABLKSIZE;
322 tquad = fxdr_hyper(&sfp->sf_abytes);
323 sbp->f_bavail = tquad / NFS_FABLKSIZE;
324 sbp->f_files = (fxdr_unsigned(int32_t,
325 sfp->sf_tfiles.nfsuquad[1]) & 0x7fffffff);
326 sbp->f_ffree = (fxdr_unsigned(int32_t,
327 sfp->sf_ffiles.nfsuquad[1]) & 0x7fffffff);
329 sbp->f_bsize = fxdr_unsigned(int32_t, sfp->sf_bsize);
330 sbp->f_blocks = fxdr_unsigned(int32_t, sfp->sf_blocks);
331 sbp->f_bfree = fxdr_unsigned(int32_t, sfp->sf_bfree);
332 sbp->f_bavail = fxdr_unsigned(int32_t, sfp->sf_bavail);
344 * nfs version 3 fsinfo rpc call
347 nfs_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred,
350 struct nfsv3_fsinfo *fsp;
353 int error = 0, retattr;
354 struct mbuf *mreq, *mrep, *md, *mb;
357 nfsstats.rpccnt[NFSPROC_FSINFO]++;
358 mreq = nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1));
360 bpos = mtod(mb, caddr_t);
362 nfsm_request(vp, NFSPROC_FSINFO, td, cred);
363 nfsm_postop_attr(vp, retattr);
365 fsp = nfsm_dissect(struct nfsv3_fsinfo *, NFSX_V3FSINFO);
366 pref = fxdr_unsigned(u_int32_t, fsp->fs_wtpref);
367 mtx_lock(&nmp->nm_mtx);
368 if (pref < nmp->nm_wsize && pref >= NFS_FABLKSIZE)
369 nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) &
370 ~(NFS_FABLKSIZE - 1);
371 max = fxdr_unsigned(u_int32_t, fsp->fs_wtmax);
372 if (max < nmp->nm_wsize && max > 0) {
373 nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1);
374 if (nmp->nm_wsize == 0)
377 pref = fxdr_unsigned(u_int32_t, fsp->fs_rtpref);
378 if (pref < nmp->nm_rsize && pref >= NFS_FABLKSIZE)
379 nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) &
380 ~(NFS_FABLKSIZE - 1);
381 max = fxdr_unsigned(u_int32_t, fsp->fs_rtmax);
382 if (max < nmp->nm_rsize && max > 0) {
383 nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1);
384 if (nmp->nm_rsize == 0)
387 pref = fxdr_unsigned(u_int32_t, fsp->fs_dtpref);
388 if (pref < nmp->nm_readdirsize && pref >= NFS_DIRBLKSIZ)
389 nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ - 1) &
390 ~(NFS_DIRBLKSIZ - 1);
391 if (max < nmp->nm_readdirsize && max > 0) {
392 nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1);
393 if (nmp->nm_readdirsize == 0)
394 nmp->nm_readdirsize = max;
396 maxfsize = fxdr_hyper(&fsp->fs_maxfilesize);
397 if (maxfsize > 0 && maxfsize < nmp->nm_maxfilesize)
398 nmp->nm_maxfilesize = maxfsize;
399 nmp->nm_mountp->mnt_stat.f_iosize = nfs_iosize(nmp);
400 nmp->nm_state |= NFSSTA_GOTFSINFO;
401 mtx_unlock(&nmp->nm_mtx);
409 * Mount a remote root fs via. nfs. This depends on the info in the
410 * nfs_diskless structure that has been filled in properly by some primary
412 * It goes something like this:
413 * - do enough of "ifconfig" by calling ifioctl() so that the system
414 * can talk to the server
415 * - If nfs_diskless.mygateway is filled in, use that address as
417 * - build the rootfs mount point and call mountnfs() to do the rest.
419 * It is assumed to be safe to read, modify, and write the nfsv3_diskless
420 * structure, as well as other global NFS client variables here, as
421 * nfs_mountroot() will be called once in the boot before any other NFS
422 * client activity occurs.
425 nfs_mountroot(struct mount *mp)
427 struct thread *td = curthread;
428 struct nfsv3_diskless *nd = &nfsv3_diskless;
438 #if defined(BOOTP_NFSROOT) && defined(BOOTP)
439 bootpc_init(); /* use bootp to get nfs_diskless filled in */
440 #elif defined(NFS_ROOT)
441 nfs_setup_diskless();
444 if (nfs_diskless_valid == 0) {
447 if (nfs_diskless_valid == 1)
448 nfs_convert_diskless();
451 * XXX splnet, so networks will receive...
456 * Do enough of ifconfig(8) so that the critical net interface can
457 * talk to the server.
459 error = socreate(nd->myif.ifra_addr.sa_family, &so, nd->root_args.sotype, 0,
462 panic("nfs_mountroot: socreate(%04x): %d",
463 nd->myif.ifra_addr.sa_family, error);
465 #if 0 /* XXX Bad idea */
467 * We might not have been told the right interface, so we pass
468 * over the first ten interfaces of the same kind, until we get
469 * one of them configured.
472 for (i = strlen(nd->myif.ifra_name) - 1;
473 nd->myif.ifra_name[i] >= '0' &&
474 nd->myif.ifra_name[i] <= '9';
475 nd->myif.ifra_name[i] ++) {
476 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
482 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
484 panic("nfs_mountroot: SIOCAIFADDR: %d", error);
486 if ((cp = getenv("boot.netif.mtu")) != NULL) {
487 ir.ifr_mtu = strtol(cp, NULL, 10);
488 bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ);
490 error = ifioctl(so, SIOCSIFMTU, (caddr_t)&ir, td);
492 printf("nfs_mountroot: SIOCSIFMTU: %d", error);
497 * If the gateway field is filled in, set it as the default route.
498 * Note that pxeboot will set a default route of 0 if the route
499 * is not set by the DHCP server. Check also for a value of 0
500 * to avoid panicking inappropriately in that situation.
502 if (nd->mygateway.sin_len != 0 &&
503 nd->mygateway.sin_addr.s_addr != 0) {
504 struct sockaddr_in mask, sin;
506 bzero((caddr_t)&mask, sizeof(mask));
508 sin.sin_family = AF_INET;
509 sin.sin_len = sizeof(sin);
510 /* XXX MRT use table 0 for this sort of thing */
511 CURVNET_SET(TD_TO_VNET(td));
512 error = rtrequest(RTM_ADD, (struct sockaddr *)&sin,
513 (struct sockaddr *)&nd->mygateway,
514 (struct sockaddr *)&mask,
515 RTF_UP | RTF_GATEWAY, NULL);
518 panic("nfs_mountroot: RTM_ADD: %d", error);
522 * Create the rootfs mount point.
524 nd->root_args.fh = nd->root_fh;
525 nd->root_args.fhsize = nd->root_fhsize;
526 l = ntohl(nd->root_saddr.sin_addr.s_addr);
527 snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
528 (l >> 24) & 0xff, (l >> 16) & 0xff,
529 (l >> 8) & 0xff, (l >> 0) & 0xff, nd->root_hostnam);
530 printf("NFS ROOT: %s\n", buf);
531 nd->root_args.hostname = buf;
532 if ((error = nfs_mountdiskless(buf,
533 &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) {
538 * This is not really an nfs issue, but it is much easier to
539 * set hostname here and then let the "/etc/rc.xxx" files
540 * mount the right /var based upon its preset value.
542 mtx_lock(&prison0.pr_mtx);
543 strlcpy(prison0.pr_hostname, nd->my_hostnam,
544 sizeof (prison0.pr_hostname));
545 mtx_unlock(&prison0.pr_mtx);
546 inittodr(ntohl(nd->root_time));
551 * Internal version of mount system call for diskless setup.
554 nfs_mountdiskless(char *path,
555 struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
556 struct vnode **vpp, struct mount *mp)
558 struct sockaddr *nam;
561 nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
562 if ((error = mountnfs(args, mp, nam, path, vpp,
563 td->td_ucred, NFS_DEFAULT_NEGNAMETIMEO)) != 0) {
564 printf("nfs_mountroot: mount %s on /: %d\n", path, error);
571 nfs_sec_name_to_num(char *sec)
573 if (!strcmp(sec, "krb5"))
574 return (RPCSEC_GSS_KRB5);
575 if (!strcmp(sec, "krb5i"))
576 return (RPCSEC_GSS_KRB5I);
577 if (!strcmp(sec, "krb5p"))
578 return (RPCSEC_GSS_KRB5P);
579 if (!strcmp(sec, "sys"))
582 * Userland should validate the string but we will try and
583 * cope with unexpected values.
589 nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
590 const char *hostname)
602 * Set read-only flag if requested; otherwise, clear it if this is
603 * an update. If this is not an update, then either the read-only
604 * flag is already clear, or this is a root mount and it was set
605 * intentionally at some previous point.
607 if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) {
609 mp->mnt_flag |= MNT_RDONLY;
611 } else if (mp->mnt_flag & MNT_UPDATE) {
613 mp->mnt_flag &= ~MNT_RDONLY;
618 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
619 * no sense in that context. Also, set up appropriate retransmit
620 * and soft timeout behavior.
622 if (argp->sotype == SOCK_STREAM) {
623 nmp->nm_flag &= ~NFSMNT_NOCONN;
624 nmp->nm_flag |= NFSMNT_DUMBTIMR;
625 nmp->nm_timeo = NFS_MAXTIMEO;
626 nmp->nm_retry = NFS_RETRANS_TCP;
629 /* Also clear RDIRPLUS if not NFSv3, it crashes some servers */
630 if ((argp->flags & NFSMNT_NFSV3) == 0)
631 nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
633 /* Re-bind if rsrvd port requested and wasn't on one */
634 adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
635 && (argp->flags & NFSMNT_RESVPORT);
636 /* Also re-bind if we're switching to/from a connected UDP socket */
637 adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
638 (argp->flags & NFSMNT_NOCONN));
640 /* Update flags atomically. Don't change the lock bits. */
641 nmp->nm_flag = argp->flags | nmp->nm_flag;
644 if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
645 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
646 if (nmp->nm_timeo < NFS_MINTIMEO)
647 nmp->nm_timeo = NFS_MINTIMEO;
648 else if (nmp->nm_timeo > NFS_MAXTIMEO)
649 nmp->nm_timeo = NFS_MAXTIMEO;
652 if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
653 nmp->nm_retry = argp->retrans;
654 if (nmp->nm_retry > NFS_MAXREXMIT)
655 nmp->nm_retry = NFS_MAXREXMIT;
658 if (argp->flags & NFSMNT_NFSV3) {
659 if (argp->sotype == SOCK_DGRAM)
660 maxio = NFS_MAXDGRAMDATA;
664 maxio = NFS_V2MAXDATA;
666 if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
667 nmp->nm_wsize = argp->wsize;
668 /* Round down to multiple of blocksize */
669 nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
670 if (nmp->nm_wsize <= 0)
671 nmp->nm_wsize = NFS_FABLKSIZE;
673 if (nmp->nm_wsize > maxio)
674 nmp->nm_wsize = maxio;
675 if (nmp->nm_wsize > MAXBSIZE)
676 nmp->nm_wsize = MAXBSIZE;
678 if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
679 nmp->nm_rsize = argp->rsize;
680 /* Round down to multiple of blocksize */
681 nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
682 if (nmp->nm_rsize <= 0)
683 nmp->nm_rsize = NFS_FABLKSIZE;
685 if (nmp->nm_rsize > maxio)
686 nmp->nm_rsize = maxio;
687 if (nmp->nm_rsize > MAXBSIZE)
688 nmp->nm_rsize = MAXBSIZE;
690 if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
691 nmp->nm_readdirsize = argp->readdirsize;
693 if (nmp->nm_readdirsize > maxio)
694 nmp->nm_readdirsize = maxio;
695 if (nmp->nm_readdirsize > nmp->nm_rsize)
696 nmp->nm_readdirsize = nmp->nm_rsize;
698 if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
699 nmp->nm_acregmin = argp->acregmin;
701 nmp->nm_acregmin = NFS_MINATTRTIMO;
702 if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
703 nmp->nm_acregmax = argp->acregmax;
705 nmp->nm_acregmax = NFS_MAXATTRTIMO;
706 if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
707 nmp->nm_acdirmin = argp->acdirmin;
709 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
710 if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
711 nmp->nm_acdirmax = argp->acdirmax;
713 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
714 if (nmp->nm_acdirmin > nmp->nm_acdirmax)
715 nmp->nm_acdirmin = nmp->nm_acdirmax;
716 if (nmp->nm_acregmin > nmp->nm_acregmax)
717 nmp->nm_acregmin = nmp->nm_acregmax;
719 if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0) {
720 if (argp->maxgrouplist <= NFS_MAXGRPS)
721 nmp->nm_numgrps = argp->maxgrouplist;
723 nmp->nm_numgrps = NFS_MAXGRPS;
725 if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
726 if (argp->readahead <= NFS_MAXRAHEAD)
727 nmp->nm_readahead = argp->readahead;
729 nmp->nm_readahead = NFS_MAXRAHEAD;
731 if ((argp->flags & NFSMNT_WCOMMITSIZE) && argp->wcommitsize >= 0) {
732 if (argp->wcommitsize < nmp->nm_wsize)
733 nmp->nm_wcommitsize = nmp->nm_wsize;
735 nmp->nm_wcommitsize = argp->wcommitsize;
737 if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 0) {
738 if (argp->deadthresh <= NFS_MAXDEADTHRESH)
739 nmp->nm_deadthresh = argp->deadthresh;
741 nmp->nm_deadthresh = NFS_MAXDEADTHRESH;
744 adjsock |= ((nmp->nm_sotype != argp->sotype) ||
745 (nmp->nm_soproto != argp->proto));
746 nmp->nm_sotype = argp->sotype;
747 nmp->nm_soproto = argp->proto;
749 if (nmp->nm_client && adjsock) {
750 nfs_safedisconnect(nmp);
751 if (nmp->nm_sotype == SOCK_DGRAM)
752 while (nfs_connect(nmp)) {
753 printf("nfs_args: retrying connect\n");
754 (void) tsleep(&fake_wchan, PSOCK, "nfscon", hz);
759 strlcpy(nmp->nm_hostname, hostname,
760 sizeof(nmp->nm_hostname));
761 p = strchr(nmp->nm_hostname, ':');
766 if (vfs_getopt(mp->mnt_optnew, "sec",
767 (void **) &secname, NULL) == 0) {
768 nmp->nm_secflavor = nfs_sec_name_to_num(secname);
770 nmp->nm_secflavor = AUTH_SYS;
773 if (vfs_getopt(mp->mnt_optnew, "principal",
774 (void **) &principal, NULL) == 0) {
775 strlcpy(nmp->nm_principal, principal,
776 sizeof(nmp->nm_principal));
778 snprintf(nmp->nm_principal, sizeof(nmp->nm_principal),
779 "nfs@%s", nmp->nm_hostname);
783 static const char *nfs_opts[] = { "from", "nfs_args",
784 "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
785 "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
786 "async", "dumbtimer", "noconn", "nolockd", "intr", "rdirplus", "resvport",
787 "readahead", "readdirsize", "soft", "hard", "mntudp", "tcp", "udp",
788 "wsize", "rsize", "retrans", "acregmin", "acregmax", "acdirmin",
789 "acdirmax", "deadthresh", "hostname", "timeout", "addr", "fh", "nfsv3",
790 "sec", "maxgroups", "principal", "negnametimeo", "nocto",
797 * It seems a bit dumb to copyinstr() the host and path here and then
798 * bcopy() them in mountnfs(), but I wanted to detect errors before
799 * doing the sockargs() call because sockargs() allocates an mbuf and
800 * an error after that means that I have to release the mbuf.
804 nfs_mount(struct mount *mp)
806 struct nfs_args args = {
807 .version = NFS_ARGSVERSION,
809 .addrlen = sizeof (struct sockaddr_in),
810 .sotype = SOCK_STREAM,
814 .flags = NFSMNT_RESVPORT,
817 .readdirsize = NFS_READDIRSIZE,
819 .retrans = NFS_RETRANS,
820 .maxgrouplist = NFS_MAXGRPS,
821 .readahead = NFS_DEFRAHEAD,
822 .wcommitsize = 0, /* was: NQ_DEFLEASE */
823 .deadthresh = NFS_MAXDEADTHRESH, /* was: NQ_DEADTHRESH */
826 .acregmin = NFS_MINATTRTIMO,
827 .acregmax = NFS_MAXATTRTIMO,
828 .acdirmin = NFS_MINDIRATTRTIMO,
829 .acdirmax = NFS_MAXDIRATTRTIMO,
831 int error, ret, has_nfs_args_opt;
832 int has_addr_opt, has_fh_opt, has_hostname_opt;
833 struct sockaddr *nam;
837 u_char nfh[NFSX_V3FHMAX];
839 int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
841 has_nfs_args_opt = 0;
844 has_hostname_opt = 0;
846 if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
851 if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS) {
852 error = nfs_mountroot(mp);
857 * The old mount_nfs program passed the struct nfs_args
858 * from userspace to kernel. The new mount_nfs program
859 * passes string options via nmount() from userspace to kernel
860 * and we populate the struct nfs_args in the kernel.
862 if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
863 error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
868 if (args.version != NFS_ARGSVERSION) {
869 error = EPROGMISMATCH;
872 has_nfs_args_opt = 1;
875 if (vfs_getopt(mp->mnt_optnew, "dumbtimer", NULL, NULL) == 0)
876 args.flags |= NFSMNT_DUMBTIMR;
877 if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
878 args.flags |= NFSMNT_NOCONN;
879 if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
880 args.flags |= NFSMNT_NOCONN;
881 if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
882 args.flags |= NFSMNT_NOLOCKD;
883 if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
884 args.flags &= ~NFSMNT_NOLOCKD;
885 if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
886 args.flags |= NFSMNT_INT;
887 if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
888 args.flags |= NFSMNT_RDIRPLUS;
889 if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
890 args.flags |= NFSMNT_RESVPORT;
891 if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
892 args.flags &= ~NFSMNT_RESVPORT;
893 if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
894 args.flags |= NFSMNT_SOFT;
895 if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
896 args.flags &= ~NFSMNT_SOFT;
897 if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
898 args.sotype = SOCK_DGRAM;
899 if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
900 args.sotype = SOCK_DGRAM;
901 if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
902 args.sotype = SOCK_STREAM;
903 if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
904 args.flags |= NFSMNT_NFSV3;
905 if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0)
906 args.flags |= NFSMNT_NOCTO;
907 if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
909 vfs_mount_error(mp, "illegal readdirsize");
913 ret = sscanf(opt, "%d", &args.readdirsize);
914 if (ret != 1 || args.readdirsize <= 0) {
915 vfs_mount_error(mp, "illegal readdirsize: %s",
920 args.flags |= NFSMNT_READDIRSIZE;
922 if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
924 vfs_mount_error(mp, "illegal readahead");
928 ret = sscanf(opt, "%d", &args.readahead);
929 if (ret != 1 || args.readahead <= 0) {
930 vfs_mount_error(mp, "illegal readahead: %s",
935 args.flags |= NFSMNT_READAHEAD;
937 if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
939 vfs_mount_error(mp, "illegal wsize");
943 ret = sscanf(opt, "%d", &args.wsize);
944 if (ret != 1 || args.wsize <= 0) {
945 vfs_mount_error(mp, "illegal wsize: %s",
950 args.flags |= NFSMNT_WSIZE;
952 if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
954 vfs_mount_error(mp, "illegal rsize");
958 ret = sscanf(opt, "%d", &args.rsize);
959 if (ret != 1 || args.rsize <= 0) {
960 vfs_mount_error(mp, "illegal wsize: %s",
965 args.flags |= NFSMNT_RSIZE;
967 if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
969 vfs_mount_error(mp, "illegal retrans");
973 ret = sscanf(opt, "%d", &args.retrans);
974 if (ret != 1 || args.retrans <= 0) {
975 vfs_mount_error(mp, "illegal retrans: %s",
980 args.flags |= NFSMNT_RETRANS;
982 if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
983 ret = sscanf(opt, "%d", &args.acregmin);
984 if (ret != 1 || args.acregmin < 0) {
985 vfs_mount_error(mp, "illegal acregmin: %s",
990 args.flags |= NFSMNT_ACREGMIN;
992 if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
993 ret = sscanf(opt, "%d", &args.acregmax);
994 if (ret != 1 || args.acregmax < 0) {
995 vfs_mount_error(mp, "illegal acregmax: %s",
1000 args.flags |= NFSMNT_ACREGMAX;
1002 if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
1003 ret = sscanf(opt, "%d", &args.acdirmin);
1004 if (ret != 1 || args.acdirmin < 0) {
1005 vfs_mount_error(mp, "illegal acdirmin: %s",
1010 args.flags |= NFSMNT_ACDIRMIN;
1012 if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
1013 ret = sscanf(opt, "%d", &args.acdirmax);
1014 if (ret != 1 || args.acdirmax < 0) {
1015 vfs_mount_error(mp, "illegal acdirmax: %s",
1020 args.flags |= NFSMNT_ACDIRMAX;
1022 if (vfs_getopt(mp->mnt_optnew, "deadthresh", (void **)&opt, NULL) == 0) {
1023 ret = sscanf(opt, "%d", &args.deadthresh);
1024 if (ret != 1 || args.deadthresh <= 0) {
1025 vfs_mount_error(mp, "illegal deadthresh: %s",
1030 args.flags |= NFSMNT_DEADTHRESH;
1032 if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
1033 ret = sscanf(opt, "%d", &args.timeo);
1034 if (ret != 1 || args.timeo <= 0) {
1035 vfs_mount_error(mp, "illegal timeout: %s",
1040 args.flags |= NFSMNT_TIMEO;
1042 if (vfs_getopt(mp->mnt_optnew, "maxgroups", (void **)&opt, NULL) == 0) {
1043 ret = sscanf(opt, "%d", &args.maxgrouplist);
1044 if (ret != 1 || args.maxgrouplist <= 0) {
1045 vfs_mount_error(mp, "illegal maxgroups: %s",
1050 args.flags |= NFSMNT_MAXGRPS;
1052 if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
1054 ret = sscanf(opt, "%d", &negnametimeo);
1055 if (ret != 1 || negnametimeo < 0) {
1056 vfs_mount_error(mp, "illegal negnametimeo: %s",
1062 if (vfs_getopt(mp->mnt_optnew, "addr", (void **)&args.addr,
1063 &args.addrlen) == 0) {
1065 if (args.addrlen > SOCK_MAXADDRLEN) {
1066 error = ENAMETOOLONG;
1069 nam = malloc(args.addrlen, M_SONAME,
1071 bcopy(args.addr, nam, args.addrlen);
1072 nam->sa_len = args.addrlen;
1074 if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
1075 &args.fhsize) == 0) {
1078 if (vfs_getopt(mp->mnt_optnew, "hostname", (void **)&args.hostname,
1080 has_hostname_opt = 1;
1082 if (args.hostname == NULL) {
1083 vfs_mount_error(mp, "Invalid hostname");
1087 if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
1088 vfs_mount_error(mp, "Bad file handle");
1093 if (mp->mnt_flag & MNT_UPDATE) {
1094 struct nfsmount *nmp = VFSTONFS(mp);
1101 * When doing an update, we can't change from or to
1102 * v3, switch lockd strategies or change cookie translation
1104 args.flags = (args.flags &
1105 ~(NFSMNT_NFSV3 | NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
1107 (NFSMNT_NFSV3 | NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
1108 nfs_decode_args(mp, nmp, &args, NULL);
1113 * Make the nfs_ip_paranoia sysctl serve as the default connection
1114 * or no-connection mode for those protocols that support
1115 * no-connection mode (the flag will be cleared later for protocols
1116 * that do not support no-connection mode). This will allow a client
1117 * to receive replies from a different IP then the request was
1118 * sent to. Note: default value for nfs_ip_paranoia is 1 (paranoid),
1121 if (nfs_ip_paranoia == 0)
1122 args.flags |= NFSMNT_NOCONN;
1124 if (has_nfs_args_opt) {
1126 * In the 'nfs_args' case, the pointers in the args
1127 * structure are in userland - we copy them in here.
1130 error = copyin((caddr_t)args.fh, (caddr_t)nfh,
1137 if (!has_hostname_opt) {
1138 error = copyinstr(args.hostname, hst, MNAMELEN-1, &len);
1142 bzero(&hst[len], MNAMELEN - len);
1143 args.hostname = hst;
1145 if (!has_addr_opt) {
1146 /* sockargs() call must be after above copyin() calls */
1147 error = getsockaddr(&nam, (caddr_t)args.addr,
1153 } else if (has_addr_opt == 0) {
1154 vfs_mount_error(mp, "No server address");
1158 error = mountnfs(&args, mp, nam, args.hostname, &vp,
1159 curthread->td_ucred, negnametimeo);
1163 mp->mnt_kern_flag |= (MNTK_MPSAFE|MNTK_LOOKUP_SHARED);
1174 * It seems a bit dumb to copyinstr() the host and path here and then
1175 * bcopy() them in mountnfs(), but I wanted to detect errors before
1176 * doing the sockargs() call because sockargs() allocates an mbuf and
1177 * an error after that means that I have to release the mbuf.
1181 nfs_cmount(struct mntarg *ma, void *data, int flags)
1184 struct nfs_args args;
1186 error = copyin(data, &args, sizeof (struct nfs_args));
1190 ma = mount_arg(ma, "nfs_args", &args, sizeof args);
1192 error = kernel_mount(ma, flags);
1197 * Common code for mount and mountroot
1200 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
1201 char *hst, struct vnode **vpp, struct ucred *cred, int negnametimeo)
1203 struct nfsmount *nmp;
1208 if (mp->mnt_flag & MNT_UPDATE) {
1210 printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
1211 free(nam, M_SONAME);
1214 nmp = uma_zalloc(nfsmount_zone, M_WAITOK);
1215 bzero((caddr_t)nmp, sizeof (struct nfsmount));
1216 TAILQ_INIT(&nmp->nm_bufq);
1218 nmp->nm_getinfo = nfs_getnlminfo;
1219 nmp->nm_vinvalbuf = nfs_vinvalbuf;
1222 nmp->nm_mountp = mp;
1223 mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF);
1226 * V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too
1227 * high, depending on whether we end up with negative offsets in
1228 * the client or server somewhere. 2GB-1 may be safer.
1230 * For V3, nfs_fsinfo will adjust this as necessary. Assume maximum
1231 * that we can handle until we find out otherwise.
1233 if ((argp->flags & NFSMNT_NFSV3) == 0)
1234 nmp->nm_maxfilesize = 0xffffffffLL;
1236 nmp->nm_maxfilesize = OFF_MAX;
1238 nmp->nm_timeo = NFS_TIMEO;
1239 nmp->nm_retry = NFS_RETRANS;
1240 if ((argp->flags & NFSMNT_NFSV3) && argp->sotype == SOCK_STREAM) {
1241 nmp->nm_wsize = nmp->nm_rsize = NFS_MAXDATA;
1243 nmp->nm_wsize = NFS_WSIZE;
1244 nmp->nm_rsize = NFS_RSIZE;
1246 nmp->nm_wcommitsize = hibufspace / (desiredvnodes / 1000);
1247 nmp->nm_readdirsize = NFS_READDIRSIZE;
1248 nmp->nm_numgrps = NFS_MAXGRPS;
1249 nmp->nm_readahead = NFS_DEFRAHEAD;
1250 nmp->nm_deadthresh = NFS_MAXDEADTHRESH;
1251 nmp->nm_negnametimeo = negnametimeo;
1252 nmp->nm_tprintf_delay = nfs_tprintf_delay;
1253 if (nmp->nm_tprintf_delay < 0)
1254 nmp->nm_tprintf_delay = 0;
1255 nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
1256 if (nmp->nm_tprintf_initial_delay < 0)
1257 nmp->nm_tprintf_initial_delay = 0;
1258 nmp->nm_fhsize = argp->fhsize;
1259 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
1260 bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
1262 /* Set up the sockets and per-host congestion */
1263 nmp->nm_sotype = argp->sotype;
1264 nmp->nm_soproto = argp->proto;
1265 nmp->nm_rpcops = &nfs_rpcops;
1267 nfs_decode_args(mp, nmp, argp, hst);
1270 * For Connection based sockets (TCP,...) defer the connect until
1271 * the first request, in case the server is not responding.
1273 if (nmp->nm_sotype == SOCK_DGRAM &&
1274 (error = nfs_connect(nmp)))
1278 * This is silly, but it has to be set so that vinifod() works.
1279 * We do not want to do an nfs_statfs() here since we can get
1280 * stuck on a dead server and we are holding a lock on the mount
1283 mtx_lock(&nmp->nm_mtx);
1284 mp->mnt_stat.f_iosize = nfs_iosize(nmp);
1285 mtx_unlock(&nmp->nm_mtx);
1287 * A reference count is needed on the nfsnode representing the
1288 * remote root. If this object is not persistent, then backward
1289 * traversals of the mount point (i.e. "..") will not work if
1290 * the nfsnode gets flushed out of the cache. Ufs does not have
1291 * this problem, because one can identify root inodes by their
1292 * number == ROOTINO (2).
1294 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
1300 * Get file attributes and transfer parameters for the
1301 * mountpoint. This has the side effect of filling in
1302 * (*vpp)->v_type with the correct value.
1304 if (argp->flags & NFSMNT_NFSV3)
1305 nfs_fsinfo(nmp, *vpp, curthread->td_ucred, curthread);
1307 VOP_GETATTR(*vpp, &attrs, curthread->td_ucred);
1310 * Lose the lock but keep the ref.
1312 VOP_UNLOCK(*vpp, 0);
1316 nfs_disconnect(nmp);
1317 mtx_destroy(&nmp->nm_mtx);
1318 uma_zfree(nfsmount_zone, nmp);
1319 free(nam, M_SONAME);
1324 * unmount system call
1327 nfs_unmount(struct mount *mp, int mntflags)
1329 struct nfsmount *nmp;
1330 int error, flags = 0;
1332 if (mntflags & MNT_FORCE)
1333 flags |= FORCECLOSE;
1336 * Goes something like this..
1337 * - Call vflush() to clear out vnodes for this filesystem
1338 * - Close the socket
1339 * - Free up the data structures
1341 /* In the forced case, cancel any outstanding requests. */
1342 if (flags & FORCECLOSE) {
1343 error = nfs_nmcancelreqs(nmp);
1347 /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
1348 error = vflush(mp, 1, flags, curthread);
1353 * We are now committed to the unmount.
1355 nfs_disconnect(nmp);
1356 free(nmp->nm_nam, M_SONAME);
1358 mtx_destroy(&nmp->nm_mtx);
1359 uma_zfree(nfsmount_zone, nmp);
1365 * Return root of a filesystem
1368 nfs_root(struct mount *mp, int flags, struct vnode **vpp)
1371 struct nfsmount *nmp;
1376 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, flags);
1381 * Get transfer parameters and attributes for root vnode once.
1383 mtx_lock(&nmp->nm_mtx);
1384 if ((nmp->nm_state & NFSSTA_GOTFSINFO) == 0 &&
1385 (nmp->nm_flag & NFSMNT_NFSV3)) {
1386 mtx_unlock(&nmp->nm_mtx);
1387 nfs_fsinfo(nmp, vp, curthread->td_ucred, curthread);
1389 mtx_unlock(&nmp->nm_mtx);
1390 if (vp->v_type == VNON)
1392 vp->v_vflag |= VV_ROOT;
1398 * Flush out the buffer cache
1402 nfs_sync(struct mount *mp, int waitfor)
1404 struct vnode *vp, *mvp;
1406 int error, allerror = 0;
1412 * If a forced dismount is in progress, return from here so that
1413 * the umount(2) syscall doesn't get stuck in VFS_SYNC() before
1414 * calling VFS_UNMOUNT().
1416 if ((mp->mnt_kern_flag & MNTK_UNMOUNTF) != 0) {
1422 * Force stale buffer cache information to be flushed.
1425 MNT_VNODE_FOREACH(vp, mp, mvp) {
1428 /* XXX Racy bv_cnt check. */
1429 if (VOP_ISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
1430 waitfor == MNT_LAZY) {
1435 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
1437 MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp);
1440 error = VOP_FSYNC(vp, waitfor, td);
1453 nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
1455 struct nfsmount *nmp = VFSTONFS(mp);
1459 bzero(&vq, sizeof(vq));
1462 case VFS_CTL_NOLOCKS:
1463 val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
1464 if (req->oldptr != NULL) {
1465 error = SYSCTL_OUT(req, &val, sizeof(val));
1469 if (req->newptr != NULL) {
1470 error = SYSCTL_IN(req, &val, sizeof(val));
1474 nmp->nm_flag |= NFSMNT_NOLOCKS;
1476 nmp->nm_flag &= ~NFSMNT_NOLOCKS;
1481 mtx_lock(&nmp->nm_mtx);
1482 if (nmp->nm_state & NFSSTA_TIMEO)
1483 vq.vq_flags |= VQ_NOTRESP;
1484 mtx_unlock(&nmp->nm_mtx);
1486 if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
1487 (nmp->nm_state & NFSSTA_LOCKTIMEO))
1488 vq.vq_flags |= VQ_NOTRESPLOCK;
1490 error = SYSCTL_OUT(req, &vq, sizeof(vq));
1493 if (req->oldptr != NULL) {
1494 error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
1495 sizeof(nmp->nm_tprintf_initial_delay));
1499 if (req->newptr != NULL) {
1500 error = vfs_suser(mp, req->td);
1503 error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
1504 sizeof(nmp->nm_tprintf_initial_delay));
1507 if (nmp->nm_tprintf_initial_delay < 0)
1508 nmp->nm_tprintf_initial_delay = 0;
1518 * Extract the information needed by the nlm from the nfs vnode.
1521 nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp,
1522 struct sockaddr_storage *sp, int *is_v3p, off_t *sizep,
1523 struct timeval *timeop)
1525 struct nfsmount *nmp;
1526 struct nfsnode *np = VTONFS(vp);
1528 nmp = VFSTONFS(vp->v_mount);
1530 *fhlenp = (size_t)np->n_fhsize;
1532 bcopy(np->n_fhp, fhp, np->n_fhsize);
1534 bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp)));
1536 *is_v3p = NFS_ISV3(vp);
1538 *sizep = np->n_size;
1539 if (timeop != NULL) {
1540 timeop->tv_sec = nmp->nm_timeo / NFS_HZ;
1541 timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ);