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 * from nfs_vfsops.c 8.12 (Berkeley) 5/20/95
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
39 #include "opt_bootp.h"
40 #include "opt_nfsroot.h"
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
47 #include <sys/clock.h>
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>
68 #include <netinet/in.h>
70 #include <fs/nfs/nfsport.h>
71 #include <fs/nfsclient/nfsnode.h>
72 #include <fs/nfsclient/nfsmount.h>
73 #include <fs/nfsclient/nfs.h>
74 #include <fs/nfsclient/nfsdiskless.h>
76 extern int nfscl_ticks;
77 extern struct timeval nfsboottime;
78 extern struct nfsstats newnfsstats;
80 MALLOC_DEFINE(M_NEWNFSREQ, "newnfsclient_req", "New NFS request header");
81 MALLOC_DEFINE(M_NEWNFSMNT, "newnfsmnt", "New NFS mount struct");
83 SYSCTL_DECL(_vfs_newnfs);
84 SYSCTL_STRUCT(_vfs_newnfs, NFS_NFSSTATS, nfsstats, CTLFLAG_RW,
85 &newnfsstats, nfsstats, "S,nfsstats");
86 static int nfs_ip_paranoia = 1;
87 SYSCTL_INT(_vfs_newnfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW,
88 &nfs_ip_paranoia, 0, "");
89 static int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
90 SYSCTL_INT(_vfs_newnfs, NFS_TPRINTF_INITIAL_DELAY,
91 downdelayinitial, CTLFLAG_RW, &nfs_tprintf_initial_delay, 0, "");
92 /* how long between console messages "nfs server foo not responding" */
93 static int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
94 SYSCTL_INT(_vfs_newnfs, NFS_TPRINTF_DELAY,
95 downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0, "");
97 static void nfs_sec_name(char *, int *);
98 static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp,
99 struct nfs_args *argp, const char *, struct ucred *,
101 static int mountnfs(struct nfs_args *, struct mount *,
102 struct sockaddr *, char *, u_char *, u_char *, u_char *,
103 struct vnode **, struct ucred *, struct thread *, int);
104 static void nfs_getnlminfo(struct vnode *, uint8_t *, size_t *,
105 struct sockaddr_storage *, int *, off_t *,
107 static vfs_mount_t nfs_mount;
108 static vfs_cmount_t nfs_cmount;
109 static vfs_unmount_t nfs_unmount;
110 static vfs_root_t nfs_root;
111 static vfs_statfs_t nfs_statfs;
112 static vfs_sync_t nfs_sync;
113 static vfs_sysctl_t nfs_sysctl;
116 * nfs vfs operations.
118 static struct vfsops nfs_vfsops = {
119 .vfs_init = ncl_init,
120 .vfs_mount = nfs_mount,
121 .vfs_cmount = nfs_cmount,
122 .vfs_root = nfs_root,
123 .vfs_statfs = nfs_statfs,
124 .vfs_sync = nfs_sync,
125 .vfs_uninit = ncl_uninit,
126 .vfs_unmount = nfs_unmount,
127 .vfs_sysctl = nfs_sysctl,
129 VFS_SET(nfs_vfsops, newnfs, VFCF_NETWORK);
131 /* So that loader and kldload(2) can find us, wherever we are.. */
132 MODULE_VERSION(newnfs, 1);
135 * This structure must be filled in by a primary bootstrap or bootstrap
136 * server for a diskless/dataless machine. It is initialized below just
137 * to ensure that it is allocated to initialized data (.data not .bss).
139 struct nfs_diskless newnfs_diskless = { { { 0 } } };
140 struct nfsv3_diskless newnfsv3_diskless = { { { 0 } } };
141 int newnfs_diskless_valid = 0;
143 SYSCTL_INT(_vfs_newnfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
144 &newnfs_diskless_valid, 0,
145 "Has the diskless struct been filled correctly");
147 SYSCTL_STRING(_vfs_newnfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
148 newnfsv3_diskless.root_hostnam, 0, "Path to nfs root");
150 SYSCTL_OPAQUE(_vfs_newnfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
151 &newnfsv3_diskless.root_saddr, sizeof newnfsv3_diskless.root_saddr,
152 "%Ssockaddr_in", "Diskless root nfs address");
155 void newnfsargs_ntoh(struct nfs_args *);
156 static int nfs_mountdiskless(char *,
157 struct sockaddr_in *, struct nfs_args *,
158 struct thread *, struct vnode **, struct mount *);
159 static void nfs_convert_diskless(void);
160 static void nfs_convert_oargs(struct nfs_args *args,
161 struct onfs_args *oargs);
164 newnfs_iosize(struct nfsmount *nmp)
168 /* First, set the upper limit for iosize */
169 if (nmp->nm_flag & NFSMNT_NFSV4) {
170 maxio = NFS_MAXBSIZE;
171 } else if (nmp->nm_flag & NFSMNT_NFSV3) {
172 if (nmp->nm_sotype == SOCK_DGRAM)
173 maxio = NFS_MAXDGRAMDATA;
175 maxio = NFS_MAXBSIZE;
177 maxio = NFS_V2MAXDATA;
179 if (nmp->nm_rsize > maxio || nmp->nm_rsize == 0)
180 nmp->nm_rsize = maxio;
181 if (nmp->nm_rsize > MAXBSIZE)
182 nmp->nm_rsize = MAXBSIZE;
183 if (nmp->nm_readdirsize > maxio || nmp->nm_readdirsize == 0)
184 nmp->nm_readdirsize = maxio;
185 if (nmp->nm_readdirsize > nmp->nm_rsize)
186 nmp->nm_readdirsize = nmp->nm_rsize;
187 if (nmp->nm_wsize > maxio || nmp->nm_wsize == 0)
188 nmp->nm_wsize = maxio;
189 if (nmp->nm_wsize > MAXBSIZE)
190 nmp->nm_wsize = MAXBSIZE;
193 * Calculate the size used for io buffers. Use the larger
194 * of the two sizes to minimise nfs requests but make sure
195 * that it is at least one VM page to avoid wasting buffer
198 iosize = imax(nmp->nm_rsize, nmp->nm_wsize);
199 iosize = imax(iosize, PAGE_SIZE);
200 nmp->nm_mountp->mnt_stat.f_iosize = iosize;
205 nfs_convert_oargs(struct nfs_args *args, struct onfs_args *oargs)
208 args->version = NFS_ARGSVERSION;
209 args->addr = oargs->addr;
210 args->addrlen = oargs->addrlen;
211 args->sotype = oargs->sotype;
212 args->proto = oargs->proto;
213 args->fh = oargs->fh;
214 args->fhsize = oargs->fhsize;
215 args->flags = oargs->flags;
216 args->wsize = oargs->wsize;
217 args->rsize = oargs->rsize;
218 args->readdirsize = oargs->readdirsize;
219 args->timeo = oargs->timeo;
220 args->retrans = oargs->retrans;
221 args->readahead = oargs->readahead;
222 args->hostname = oargs->hostname;
226 nfs_convert_diskless(void)
229 bcopy(&newnfs_diskless.myif, &newnfsv3_diskless.myif,
230 sizeof (struct ifaliasreq));
231 bcopy(&newnfs_diskless.mygateway, &newnfsv3_diskless.mygateway,
232 sizeof (struct sockaddr_in));
233 nfs_convert_oargs(&newnfsv3_diskless.root_args,
234 &newnfs_diskless.root_args);
235 if (newnfsv3_diskless.root_args.flags & NFSMNT_NFSV3) {
236 newnfsv3_diskless.root_fhsize = NFSX_MYFH;
237 bcopy(newnfs_diskless.root_fh, newnfsv3_diskless.root_fh,
240 newnfsv3_diskless.root_fhsize = NFSX_V2FH;
241 bcopy(newnfs_diskless.root_fh, newnfsv3_diskless.root_fh,
244 bcopy(&newnfs_diskless.root_saddr,&newnfsv3_diskless.root_saddr,
245 sizeof(struct sockaddr_in));
246 bcopy(newnfs_diskless.root_hostnam, newnfsv3_diskless.root_hostnam,
248 newnfsv3_diskless.root_time = newnfs_diskless.root_time;
249 bcopy(newnfs_diskless.my_hostnam, newnfsv3_diskless.my_hostnam,
251 newnfs_diskless_valid = 3;
258 nfs_statfs(struct mount *mp, struct statfs *sbp)
262 struct nfsmount *nmp = VFSTONFS(mp);
263 struct nfsvattr nfsva;
266 int error = 0, attrflag, gotfsinfo = 0, ret;
271 error = vfs_busy(mp, MBF_NOWAIT);
274 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np);
280 mtx_lock(&nmp->nm_mtx);
281 if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
282 mtx_unlock(&nmp->nm_mtx);
283 error = nfsrpc_fsinfo(vp, &fs, td->td_ucred, td, &nfsva,
288 mtx_unlock(&nmp->nm_mtx);
290 error = nfsrpc_statfs(vp, &sb, &fs, td->td_ucred, td, &nfsva,
293 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
294 td->td_ucred, td, &nfsva, NULL);
297 * Just set default values to get things going.
299 NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
300 nfsva.na_vattr.va_type = VDIR;
301 nfsva.na_vattr.va_mode = 0777;
302 nfsva.na_vattr.va_nlink = 100;
303 nfsva.na_vattr.va_uid = (uid_t)0;
304 nfsva.na_vattr.va_gid = (gid_t)0;
305 nfsva.na_vattr.va_fileid = 2;
306 nfsva.na_vattr.va_gen = 1;
307 nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
308 nfsva.na_vattr.va_size = 512 * 1024;
311 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
313 mtx_lock(&nmp->nm_mtx);
314 if (gotfsinfo || (nmp->nm_flag & NFSMNT_NFSV4))
315 nfscl_loadfsinfo(nmp, &fs);
316 nfscl_loadsbinfo(nmp, &sb, sbp);
317 sbp->f_flags = nmp->nm_flag;
318 sbp->f_iosize = newnfs_iosize(nmp);
319 mtx_unlock(&nmp->nm_mtx);
320 if (sbp != &mp->mnt_stat) {
321 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
322 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
324 strncpy(&sbp->f_fstypename[0], mp->mnt_vfc->vfc_name, MFSNAMELEN);
325 } else if (NFS_ISV4(vp)) {
326 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
334 * nfs version 3 fsinfo rpc call
337 ncl_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred,
341 struct nfsvattr nfsva;
344 error = nfsrpc_fsinfo(vp, &fs, cred, td, &nfsva, &attrflag, NULL);
347 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0,
349 mtx_lock(&nmp->nm_mtx);
350 nfscl_loadfsinfo(nmp, &fs);
351 mtx_unlock(&nmp->nm_mtx);
357 * Mount a remote root fs via. nfs. This depends on the info in the
358 * newnfs_diskless structure that has been filled in properly by some primary
360 * It goes something like this:
361 * - do enough of "ifconfig" by calling ifioctl() so that the system
362 * can talk to the server
363 * - If newnfs_diskless.mygateway is filled in, use that address as
365 * - build the rootfs mount point and call mountnfs() to do the rest.
367 * It is assumed to be safe to read, modify, and write the nfsv3_diskless
368 * structure, as well as other global NFS client variables here, as
369 * nfs_mountroot() will be called once in the boot before any other NFS
370 * client activity occurs.
373 ncl_mountroot(struct mount *mp)
375 struct thread *td = curthread;
376 struct nfsv3_diskless *nd = &newnfsv3_diskless;
385 #if defined(BOOTP_NFSROOT) && defined(BOOTP)
386 bootpc_init(); /* use bootp to get nfs_diskless filled in */
387 #elif defined(NFS_ROOT)
388 nfs_setup_diskless();
391 if (newnfs_diskless_valid == 0)
393 if (newnfs_diskless_valid == 1)
394 nfs_convert_diskless();
397 * XXX splnet, so networks will receive...
402 * Do enough of ifconfig(8) so that the critical net interface can
403 * talk to the server.
405 error = socreate(nd->myif.ifra_addr.sa_family, &so, nd->root_args.sotype, 0,
408 panic("nfs_mountroot: socreate(%04x): %d",
409 nd->myif.ifra_addr.sa_family, error);
411 #if 0 /* XXX Bad idea */
413 * We might not have been told the right interface, so we pass
414 * over the first ten interfaces of the same kind, until we get
415 * one of them configured.
418 for (i = strlen(nd->myif.ifra_name) - 1;
419 nd->myif.ifra_name[i] >= '0' &&
420 nd->myif.ifra_name[i] <= '9';
421 nd->myif.ifra_name[i] ++) {
422 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
427 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
429 panic("nfs_mountroot: SIOCAIFADDR: %d", error);
430 if ((cp = getenv("boot.netif.mtu")) != NULL) {
431 ir.ifr_mtu = strtol(cp, NULL, 10);
432 bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ);
434 error = ifioctl(so, SIOCSIFMTU, (caddr_t)&ir, td);
436 printf("nfs_mountroot: SIOCSIFMTU: %d", error);
441 * If the gateway field is filled in, set it as the default route.
442 * Note that pxeboot will set a default route of 0 if the route
443 * is not set by the DHCP server. Check also for a value of 0
444 * to avoid panicking inappropriately in that situation.
446 if (nd->mygateway.sin_len != 0 &&
447 nd->mygateway.sin_addr.s_addr != 0) {
448 struct sockaddr_in mask, sin;
450 bzero((caddr_t)&mask, sizeof(mask));
452 sin.sin_family = AF_INET;
453 sin.sin_len = sizeof(sin);
454 /* XXX MRT use table 0 for this sort of thing */
455 CURVNET_SET(TD_TO_VNET(td));
456 error = rtrequest(RTM_ADD, (struct sockaddr *)&sin,
457 (struct sockaddr *)&nd->mygateway,
458 (struct sockaddr *)&mask,
459 RTF_UP | RTF_GATEWAY, NULL);
462 panic("nfs_mountroot: RTM_ADD: %d", error);
466 * Create the rootfs mount point.
468 nd->root_args.fh = nd->root_fh;
469 nd->root_args.fhsize = nd->root_fhsize;
470 l = ntohl(nd->root_saddr.sin_addr.s_addr);
471 snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
472 (l >> 24) & 0xff, (l >> 16) & 0xff,
473 (l >> 8) & 0xff, (l >> 0) & 0xff, nd->root_hostnam);
474 printf("NFS ROOT: %s\n", buf);
475 nd->root_args.hostname = buf;
476 if ((error = nfs_mountdiskless(buf,
477 &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) {
482 * This is not really an nfs issue, but it is much easier to
483 * set hostname here and then let the "/etc/rc.xxx" files
484 * mount the right /var based upon its preset value.
486 mtx_lock(&prison0.pr_mtx);
487 strlcpy(prison0.pr_hostname, nd->my_hostnam,
488 sizeof(prison0.pr_hostname));
489 mtx_unlock(&prison0.pr_mtx);
490 inittodr(ntohl(nd->root_time));
495 * Internal version of mount system call for diskless setup.
498 nfs_mountdiskless(char *path,
499 struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
500 struct vnode **vpp, struct mount *mp)
502 struct sockaddr *nam;
505 nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
506 if ((error = mountnfs(args, mp, nam, path, NULL, NULL, NULL, vpp,
507 td->td_ucred, td, NFS_DEFAULT_NEGNAMETIMEO)) != 0) {
508 printf("nfs_mountroot: mount %s on /: %d\n", path, error);
515 nfs_sec_name(char *sec, int *flagsp)
517 if (!strcmp(sec, "krb5"))
518 *flagsp |= NFSMNT_KERB;
519 else if (!strcmp(sec, "krb5i"))
520 *flagsp |= (NFSMNT_KERB | NFSMNT_INTEGRITY);
521 else if (!strcmp(sec, "krb5p"))
522 *flagsp |= (NFSMNT_KERB | NFSMNT_PRIVACY);
526 nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
527 const char *hostname, struct ucred *cred, struct thread *td)
536 * Set read-only flag if requested; otherwise, clear it if this is
537 * an update. If this is not an update, then either the read-only
538 * flag is already clear, or this is a root mount and it was set
539 * intentionally at some previous point.
541 if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) {
543 mp->mnt_flag |= MNT_RDONLY;
545 } else if (mp->mnt_flag & MNT_UPDATE) {
547 mp->mnt_flag &= ~MNT_RDONLY;
552 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
553 * no sense in that context. Also, set up appropriate retransmit
554 * and soft timeout behavior.
556 if (argp->sotype == SOCK_STREAM) {
557 nmp->nm_flag &= ~NFSMNT_NOCONN;
558 nmp->nm_timeo = NFS_MAXTIMEO;
561 /* Also clear RDIRPLUS if not NFSv3, it crashes some servers */
562 if ((argp->flags & NFSMNT_NFSV3) == 0)
563 nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
565 /* Also re-bind if we're switching to/from a connected UDP socket */
566 adjsock = ((nmp->nm_flag & NFSMNT_NOCONN) !=
567 (argp->flags & NFSMNT_NOCONN));
569 /* Update flags atomically. Don't change the lock bits. */
570 nmp->nm_flag = argp->flags | nmp->nm_flag;
573 if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
574 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
575 if (nmp->nm_timeo < NFS_MINTIMEO)
576 nmp->nm_timeo = NFS_MINTIMEO;
577 else if (nmp->nm_timeo > NFS_MAXTIMEO)
578 nmp->nm_timeo = NFS_MAXTIMEO;
581 if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
582 nmp->nm_retry = argp->retrans;
583 if (nmp->nm_retry > NFS_MAXREXMIT)
584 nmp->nm_retry = NFS_MAXREXMIT;
587 if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
588 nmp->nm_wsize = argp->wsize;
589 /* Round down to multiple of blocksize */
590 nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
591 if (nmp->nm_wsize <= 0)
592 nmp->nm_wsize = NFS_FABLKSIZE;
595 if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
596 nmp->nm_rsize = argp->rsize;
597 /* Round down to multiple of blocksize */
598 nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
599 if (nmp->nm_rsize <= 0)
600 nmp->nm_rsize = NFS_FABLKSIZE;
603 if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
604 nmp->nm_readdirsize = argp->readdirsize;
607 if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
608 nmp->nm_acregmin = argp->acregmin;
610 nmp->nm_acregmin = NFS_MINATTRTIMO;
611 if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
612 nmp->nm_acregmax = argp->acregmax;
614 nmp->nm_acregmax = NFS_MAXATTRTIMO;
615 if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
616 nmp->nm_acdirmin = argp->acdirmin;
618 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
619 if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
620 nmp->nm_acdirmax = argp->acdirmax;
622 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
623 if (nmp->nm_acdirmin > nmp->nm_acdirmax)
624 nmp->nm_acdirmin = nmp->nm_acdirmax;
625 if (nmp->nm_acregmin > nmp->nm_acregmax)
626 nmp->nm_acregmin = nmp->nm_acregmax;
628 if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
629 if (argp->readahead <= NFS_MAXRAHEAD)
630 nmp->nm_readahead = argp->readahead;
632 nmp->nm_readahead = NFS_MAXRAHEAD;
634 if ((argp->flags & NFSMNT_WCOMMITSIZE) && argp->wcommitsize >= 0) {
635 if (argp->wcommitsize < nmp->nm_wsize)
636 nmp->nm_wcommitsize = nmp->nm_wsize;
638 nmp->nm_wcommitsize = argp->wcommitsize;
641 adjsock |= ((nmp->nm_sotype != argp->sotype) ||
642 (nmp->nm_soproto != argp->proto));
644 if (nmp->nm_client != NULL && adjsock) {
645 int haslock = 0, error = 0;
647 if (nmp->nm_sotype == SOCK_STREAM) {
648 error = newnfs_sndlock(&nmp->nm_sockreq.nr_lock);
653 newnfs_disconnect(&nmp->nm_sockreq);
655 newnfs_sndunlock(&nmp->nm_sockreq.nr_lock);
656 nmp->nm_sotype = argp->sotype;
657 nmp->nm_soproto = argp->proto;
658 if (nmp->nm_sotype == SOCK_DGRAM)
659 while (newnfs_connect(nmp, &nmp->nm_sockreq,
661 printf("newnfs_args: retrying connect\n");
662 (void) nfs_catnap(PSOCK, 0, "newnfscon");
666 nmp->nm_sotype = argp->sotype;
667 nmp->nm_soproto = argp->proto;
670 if (hostname != NULL) {
671 strlcpy(nmp->nm_hostname, hostname,
672 sizeof(nmp->nm_hostname));
673 p = strchr(nmp->nm_hostname, ':');
679 static const char *nfs_opts[] = { "from",
680 "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
681 "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
682 "async", "noconn", "nolockd", "conn", "lockd", "intr", "rdirplus",
683 "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize",
684 "retrans", "acregmin", "acregmax", "acdirmin", "acdirmax", "resvport",
685 "readahead", "hostname", "timeout", "addr", "fh", "nfsv3", "sec",
686 "principal", "nfsv4", "gssname", "allgssname", "dirpath",
694 * It seems a bit dumb to copyinstr() the host and path here and then
695 * bcopy() them in mountnfs(), but I wanted to detect errors before
696 * doing the sockargs() call because sockargs() allocates an mbuf and
697 * an error after that means that I have to release the mbuf.
701 nfs_mount(struct mount *mp)
703 struct nfs_args args = {
704 .version = NFS_ARGSVERSION,
706 .addrlen = sizeof (struct sockaddr_in),
707 .sotype = SOCK_STREAM,
714 .readdirsize = NFS_READDIRSIZE,
716 .retrans = NFS_RETRANS,
717 .readahead = NFS_DEFRAHEAD,
718 .wcommitsize = 0, /* was: NQ_DEFLEASE */
721 .acregmin = NFS_MINATTRTIMO,
722 .acregmax = NFS_MAXATTRTIMO,
723 .acdirmin = NFS_MINDIRATTRTIMO,
724 .acdirmax = NFS_MAXDIRATTRTIMO,
729 int error = 0, ret, len;
730 struct sockaddr *nam = NULL;
734 u_char nfh[NFSX_FHMAX], krbname[100], dirpath[100], srvkrbname[100];
735 char *opt, *name, *secname;
736 int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
738 if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
744 if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS) {
745 error = ncl_mountroot(mp);
751 /* Handle the new style options. */
752 if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
753 args.flags |= NFSMNT_NOCONN;
754 if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
755 args.flags |= NFSMNT_NOCONN;
756 if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
757 args.flags |= NFSMNT_NOLOCKD;
758 if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
759 args.flags &= ~NFSMNT_NOLOCKD;
760 if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
761 args.flags |= NFSMNT_INT;
762 if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
763 args.flags |= NFSMNT_RDIRPLUS;
764 if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
765 args.flags |= NFSMNT_RESVPORT;
766 if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
767 args.flags &= ~NFSMNT_RESVPORT;
768 if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
769 args.flags |= NFSMNT_SOFT;
770 if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
771 args.flags &= ~NFSMNT_SOFT;
772 if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
773 args.sotype = SOCK_DGRAM;
774 if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
775 args.sotype = SOCK_DGRAM;
776 if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
777 args.sotype = SOCK_STREAM;
778 if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
779 args.flags |= NFSMNT_NFSV3;
780 if (vfs_getopt(mp->mnt_optnew, "nfsv4", NULL, NULL) == 0) {
781 args.flags |= NFSMNT_NFSV4;
782 args.sotype = SOCK_STREAM;
784 if (vfs_getopt(mp->mnt_optnew, "allgssname", NULL, NULL) == 0)
785 args.flags |= NFSMNT_ALLGSSNAME;
786 if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
788 vfs_mount_error(mp, "illegal readdirsize");
792 ret = sscanf(opt, "%d", &args.readdirsize);
793 if (ret != 1 || args.readdirsize <= 0) {
794 vfs_mount_error(mp, "illegal readdirsize: %s",
799 args.flags |= NFSMNT_READDIRSIZE;
801 if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
803 vfs_mount_error(mp, "illegal readahead");
807 ret = sscanf(opt, "%d", &args.readahead);
808 if (ret != 1 || args.readahead <= 0) {
809 vfs_mount_error(mp, "illegal readahead: %s",
814 args.flags |= NFSMNT_READAHEAD;
816 if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
818 vfs_mount_error(mp, "illegal wsize");
822 ret = sscanf(opt, "%d", &args.wsize);
823 if (ret != 1 || args.wsize <= 0) {
824 vfs_mount_error(mp, "illegal wsize: %s",
829 args.flags |= NFSMNT_WSIZE;
831 if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
833 vfs_mount_error(mp, "illegal rsize");
837 ret = sscanf(opt, "%d", &args.rsize);
838 if (ret != 1 || args.rsize <= 0) {
839 vfs_mount_error(mp, "illegal wsize: %s",
844 args.flags |= NFSMNT_RSIZE;
846 if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
848 vfs_mount_error(mp, "illegal retrans");
852 ret = sscanf(opt, "%d", &args.retrans);
853 if (ret != 1 || args.retrans <= 0) {
854 vfs_mount_error(mp, "illegal retrans: %s",
859 args.flags |= NFSMNT_RETRANS;
861 if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
862 ret = sscanf(opt, "%d", &args.acregmin);
863 if (ret != 1 || args.acregmin < 0) {
864 vfs_mount_error(mp, "illegal acregmin: %s",
869 args.flags |= NFSMNT_ACREGMIN;
871 if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
872 ret = sscanf(opt, "%d", &args.acregmax);
873 if (ret != 1 || args.acregmax < 0) {
874 vfs_mount_error(mp, "illegal acregmax: %s",
879 args.flags |= NFSMNT_ACREGMAX;
881 if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
882 ret = sscanf(opt, "%d", &args.acdirmin);
883 if (ret != 1 || args.acdirmin < 0) {
884 vfs_mount_error(mp, "illegal acdirmin: %s",
889 args.flags |= NFSMNT_ACDIRMIN;
891 if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
892 ret = sscanf(opt, "%d", &args.acdirmax);
893 if (ret != 1 || args.acdirmax < 0) {
894 vfs_mount_error(mp, "illegal acdirmax: %s",
899 args.flags |= NFSMNT_ACDIRMAX;
901 if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
902 ret = sscanf(opt, "%d", &args.timeo);
903 if (ret != 1 || args.timeo <= 0) {
904 vfs_mount_error(mp, "illegal timeout: %s",
909 args.flags |= NFSMNT_TIMEO;
911 if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
913 ret = sscanf(opt, "%d", &negnametimeo);
914 if (ret != 1 || negnametimeo < 0) {
915 vfs_mount_error(mp, "illegal negnametimeo: %s",
921 if (vfs_getopt(mp->mnt_optnew, "sec",
922 (void **) &secname, NULL) == 0)
923 nfs_sec_name(secname, &args.flags);
925 if (mp->mnt_flag & MNT_UPDATE) {
926 struct nfsmount *nmp = VFSTONFS(mp);
933 * When doing an update, we can't change version,
934 * security, switch lockd strategies or change cookie
937 args.flags = (args.flags &
943 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
950 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
951 nfs_decode_args(mp, nmp, &args, NULL, td->td_ucred, td);
956 * Make the nfs_ip_paranoia sysctl serve as the default connection
957 * or no-connection mode for those protocols that support
958 * no-connection mode (the flag will be cleared later for protocols
959 * that do not support no-connection mode). This will allow a client
960 * to receive replies from a different IP then the request was
961 * sent to. Note: default value for nfs_ip_paranoia is 1 (paranoid),
964 if (nfs_ip_paranoia == 0)
965 args.flags |= NFSMNT_NOCONN;
967 if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
968 &args.fhsize) == 0) {
969 if (args.fhsize < 0 || args.fhsize > NFSX_FHMAX) {
970 vfs_mount_error(mp, "Bad file handle");
974 bcopy(args.fh, nfh, args.fhsize);
979 (void) vfs_getopt(mp->mnt_optnew, "hostname", (void **)&args.hostname,
981 if (args.hostname == NULL) {
982 vfs_mount_error(mp, "Invalid hostname");
986 bcopy(args.hostname, hst, MNAMELEN);
987 hst[MNAMELEN - 1] = '\0';
989 if (vfs_getopt(mp->mnt_optnew, "principal", (void **)&name, NULL) == 0)
990 strlcpy(srvkrbname, name, sizeof (srvkrbname));
992 snprintf(srvkrbname, sizeof (srvkrbname), "nfs@%s", hst);
993 args.srvkrbnamelen = strlen(srvkrbname);
995 if (vfs_getopt(mp->mnt_optnew, "gssname", (void **)&name, NULL) == 0)
996 strlcpy(krbname, name, sizeof (krbname));
999 args.krbnamelen = strlen(krbname);
1001 if (vfs_getopt(mp->mnt_optnew, "dirpath", (void **)&name, NULL) == 0)
1002 strlcpy(dirpath, name, sizeof (dirpath));
1005 args.dirlen = strlen(dirpath);
1007 if (vfs_getopt(mp->mnt_optnew, "addr", (void **)&args.addr,
1008 &args.addrlen) == 0) {
1009 if (args.addrlen > SOCK_MAXADDRLEN) {
1010 error = ENAMETOOLONG;
1013 nam = malloc(args.addrlen, M_SONAME, M_WAITOK);
1014 bcopy(args.addr, nam, args.addrlen);
1015 nam->sa_len = args.addrlen;
1019 error = mountnfs(&args, mp, nam, hst, krbname, dirpath, srvkrbname,
1020 &vp, td->td_ucred, td, negnametimeo);
1024 mp->mnt_kern_flag |= (MNTK_MPSAFE|MNTK_LOOKUP_SHARED);
1035 * It seems a bit dumb to copyinstr() the host and path here and then
1036 * bcopy() them in mountnfs(), but I wanted to detect errors before
1037 * doing the sockargs() call because sockargs() allocates an mbuf and
1038 * an error after that means that I have to release the mbuf.
1042 nfs_cmount(struct mntarg *ma, void *data, int flags)
1045 struct nfs_args args;
1047 error = copyin(data, &args, sizeof (struct nfs_args));
1051 ma = mount_arg(ma, "nfs_args", &args, sizeof args);
1053 error = kernel_mount(ma, flags);
1058 * Common code for mount and mountroot
1061 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
1062 char *hst, u_char *krbname, u_char *dirpath, u_char *srvkrbname,
1063 struct vnode **vpp, struct ucred *cred, struct thread *td,
1066 struct nfsmount *nmp;
1068 int error, trycnt, ret;
1069 struct nfsvattr nfsva;
1070 static u_int64_t clval = 0;
1072 if (mp->mnt_flag & MNT_UPDATE) {
1074 printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
1075 FREE(nam, M_SONAME);
1078 MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount) +
1079 argp->krbnamelen + argp->dirlen + argp->srvkrbnamelen + 2,
1080 M_NEWNFSMNT, M_WAITOK);
1081 bzero((caddr_t)nmp, sizeof (struct nfsmount) +
1082 argp->krbnamelen + argp->dirlen + argp->srvkrbnamelen + 2);
1083 TAILQ_INIT(&nmp->nm_bufq);
1085 clval = (u_int64_t)nfsboottime.tv_sec;
1086 nmp->nm_clval = clval++;
1087 nmp->nm_krbnamelen = argp->krbnamelen;
1088 nmp->nm_dirpathlen = argp->dirlen;
1089 nmp->nm_srvkrbnamelen = argp->srvkrbnamelen;
1090 if (td->td_ucred->cr_uid != (uid_t)0) {
1092 * nm_uid is used to get KerberosV credentials for
1093 * the nfsv4 state handling operations if there is
1094 * no host based principal set. Use the uid of
1095 * this user if not root, since they are doing the
1096 * mount. I don't think setting this for root will
1097 * work, since root normally does not have user
1098 * credentials in a credentials cache.
1100 nmp->nm_uid = td->td_ucred->cr_uid;
1103 * Just set to -1, so it won't be used.
1105 nmp->nm_uid = (uid_t)-1;
1108 /* Copy and null terminate all the names */
1109 if (nmp->nm_krbnamelen > 0) {
1110 bcopy(krbname, nmp->nm_krbname, nmp->nm_krbnamelen);
1111 nmp->nm_name[nmp->nm_krbnamelen] = '\0';
1113 if (nmp->nm_dirpathlen > 0) {
1114 bcopy(dirpath, NFSMNT_DIRPATH(nmp),
1115 nmp->nm_dirpathlen);
1116 nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1119 if (nmp->nm_srvkrbnamelen > 0) {
1120 bcopy(srvkrbname, NFSMNT_SRVKRBNAME(nmp),
1121 nmp->nm_srvkrbnamelen);
1122 nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1123 + nmp->nm_srvkrbnamelen + 2] = '\0';
1125 nmp->nm_sockreq.nr_cred = crhold(cred);
1126 mtx_init(&nmp->nm_sockreq.nr_mtx, "nfssock", NULL, MTX_DEF);
1128 nmp->nm_getinfo = nfs_getnlminfo;
1129 nmp->nm_vinvalbuf = ncl_vinvalbuf;
1132 nmp->nm_mountp = mp;
1133 mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF | MTX_DUPOK);
1134 nmp->nm_negnametimeo = negnametimeo;
1136 nfs_decode_args(mp, nmp, argp, hst, cred, td);
1139 * V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too
1140 * high, depending on whether we end up with negative offsets in
1141 * the client or server somewhere. 2GB-1 may be safer.
1143 * For V3, ncl_fsinfo will adjust this as necessary. Assume maximum
1144 * that we can handle until we find out otherwise.
1145 * XXX Our "safe" limit on the client is what we can store in our
1146 * buffer cache using signed(!) block numbers.
1148 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0)
1149 nmp->nm_maxfilesize = 0xffffffffLL;
1151 nmp->nm_maxfilesize = (u_int64_t)0x80000000 * DEV_BSIZE - 1;
1153 nmp->nm_timeo = NFS_TIMEO;
1154 nmp->nm_retry = NFS_RETRANS;
1155 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
1156 nmp->nm_wsize = NFS_WSIZE;
1157 nmp->nm_rsize = NFS_RSIZE;
1158 nmp->nm_readdirsize = NFS_READDIRSIZE;
1160 nmp->nm_wcommitsize = hibufspace / (desiredvnodes / 1000);
1161 nmp->nm_numgrps = NFS_MAXGRPS;
1162 nmp->nm_readahead = NFS_DEFRAHEAD;
1163 nmp->nm_tprintf_delay = nfs_tprintf_delay;
1164 if (nmp->nm_tprintf_delay < 0)
1165 nmp->nm_tprintf_delay = 0;
1166 nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
1167 if (nmp->nm_tprintf_initial_delay < 0)
1168 nmp->nm_tprintf_initial_delay = 0;
1169 nmp->nm_fhsize = argp->fhsize;
1170 if (nmp->nm_fhsize > 0)
1171 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
1172 bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
1174 /* Set up the sockets and per-host congestion */
1175 nmp->nm_sotype = argp->sotype;
1176 nmp->nm_soproto = argp->proto;
1177 nmp->nm_sockreq.nr_prog = NFS_PROG;
1178 if ((argp->flags & NFSMNT_NFSV4))
1179 nmp->nm_sockreq.nr_vers = NFS_VER4;
1180 else if ((argp->flags & NFSMNT_NFSV3))
1181 nmp->nm_sockreq.nr_vers = NFS_VER3;
1183 nmp->nm_sockreq.nr_vers = NFS_VER2;
1186 if ((error = newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0)))
1190 * A reference count is needed on the nfsnode representing the
1191 * remote root. If this object is not persistent, then backward
1192 * traversals of the mount point (i.e. "..") will not work if
1193 * the nfsnode gets flushed out of the cache. Ufs does not have
1194 * this problem, because one can identify root inodes by their
1195 * number == ROOTINO (2).
1197 if (nmp->nm_fhsize == 0 && (nmp->nm_flag & NFSMNT_NFSV4) &&
1198 nmp->nm_dirpathlen > 0) {
1200 * If the fhsize on the mount point == 0 for V4, the mount
1201 * path needs to be looked up.
1205 error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp),
1208 (void) nfs_catnap(PZERO, error, "nfsgetdirp");
1209 } while (error && --trycnt > 0);
1211 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
1215 if (nmp->nm_fhsize > 0) {
1217 * Set f_iosize to NFS_DIRBLKSIZ so that bo_bsize gets set
1218 * non-zero for the root vnode. f_iosize will be set correctly
1219 * by nfs_statfs() before any I/O occurs.
1221 mp->mnt_stat.f_iosize = NFS_DIRBLKSIZ;
1222 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np);
1228 * Get file attributes and transfer parameters for the
1229 * mountpoint. This has the side effect of filling in
1230 * (*vpp)->v_type with the correct value.
1232 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
1233 cred, td, &nfsva, NULL);
1236 * Just set default values to get things going.
1238 NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
1239 nfsva.na_vattr.va_type = VDIR;
1240 nfsva.na_vattr.va_mode = 0777;
1241 nfsva.na_vattr.va_nlink = 100;
1242 nfsva.na_vattr.va_uid = (uid_t)0;
1243 nfsva.na_vattr.va_gid = (gid_t)0;
1244 nfsva.na_vattr.va_fileid = 2;
1245 nfsva.na_vattr.va_gen = 1;
1246 nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
1247 nfsva.na_vattr.va_size = 512 * 1024;
1249 (void) nfscl_loadattrcache(vpp, &nfsva, NULL, NULL, 0, 1);
1250 if (argp->flags & NFSMNT_NFSV3)
1251 ncl_fsinfo(nmp, *vpp, cred, td);
1254 * Lose the lock but keep the ref.
1256 VOP_UNLOCK(*vpp, 0);
1262 newnfs_disconnect(&nmp->nm_sockreq);
1263 crfree(nmp->nm_sockreq.nr_cred);
1264 mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1265 mtx_destroy(&nmp->nm_mtx);
1266 FREE(nmp, M_NEWNFSMNT);
1267 FREE(nam, M_SONAME);
1272 * unmount system call
1275 nfs_unmount(struct mount *mp, int mntflags)
1278 struct nfsmount *nmp;
1279 int error, flags = 0, trycnt = 0;
1283 if (mntflags & MNT_FORCE)
1284 flags |= FORCECLOSE;
1287 * Goes something like this..
1288 * - Call vflush() to clear out vnodes for this filesystem
1289 * - Close the socket
1290 * - Free up the data structures
1292 /* In the forced case, cancel any outstanding requests. */
1293 if (mntflags & MNT_FORCE) {
1294 error = newnfs_nmcancelreqs(nmp);
1297 /* For a forced close, get rid of the renew thread now */
1298 nfscl_umount(nmp, td);
1300 /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
1302 error = vflush(mp, 1, flags, td);
1303 if ((mntflags & MNT_FORCE) && error != 0 && ++trycnt < 30)
1304 (void) nfs_catnap(PSOCK, error, "newndm");
1305 } while ((mntflags & MNT_FORCE) && error != 0 && trycnt < 30);
1310 * We are now committed to the unmount.
1312 if ((mntflags & MNT_FORCE) == 0)
1313 nfscl_umount(nmp, td);
1314 newnfs_disconnect(&nmp->nm_sockreq);
1315 crfree(nmp->nm_sockreq.nr_cred);
1316 FREE(nmp->nm_nam, M_SONAME);
1318 mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1319 mtx_destroy(&nmp->nm_mtx);
1320 FREE(nmp, M_NEWNFSMNT);
1326 * Return root of a filesystem
1329 nfs_root(struct mount *mp, int flags, struct vnode **vpp)
1332 struct nfsmount *nmp;
1337 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np);
1342 * Get transfer parameters and attributes for root vnode once.
1344 mtx_lock(&nmp->nm_mtx);
1345 if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
1346 mtx_unlock(&nmp->nm_mtx);
1347 ncl_fsinfo(nmp, vp, curthread->td_ucred, curthread);
1349 mtx_unlock(&nmp->nm_mtx);
1350 if (vp->v_type == VNON)
1352 vp->v_vflag |= VV_ROOT;
1358 * Flush out the buffer cache
1362 nfs_sync(struct mount *mp, int waitfor)
1364 struct vnode *vp, *mvp;
1366 int error, allerror = 0;
1371 * Force stale buffer cache information to be flushed.
1375 MNT_VNODE_FOREACH(vp, mp, mvp) {
1378 /* XXX Racy bv_cnt check. */
1379 if (VOP_ISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
1380 waitfor == MNT_LAZY) {
1385 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
1387 MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp);
1390 error = VOP_FSYNC(vp, waitfor, td);
1403 nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
1405 struct nfsmount *nmp = VFSTONFS(mp);
1409 bzero(&vq, sizeof(vq));
1412 case VFS_CTL_NOLOCKS:
1413 val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
1414 if (req->oldptr != NULL) {
1415 error = SYSCTL_OUT(req, &val, sizeof(val));
1419 if (req->newptr != NULL) {
1420 error = SYSCTL_IN(req, &val, sizeof(val));
1424 nmp->nm_flag |= NFSMNT_NOLOCKS;
1426 nmp->nm_flag &= ~NFSMNT_NOLOCKS;
1431 mtx_lock(&nmp->nm_mtx);
1432 if (nmp->nm_state & NFSSTA_TIMEO)
1433 vq.vq_flags |= VQ_NOTRESP;
1434 mtx_unlock(&nmp->nm_mtx);
1436 if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
1437 (nmp->nm_state & NFSSTA_LOCKTIMEO))
1438 vq.vq_flags |= VQ_NOTRESPLOCK;
1440 error = SYSCTL_OUT(req, &vq, sizeof(vq));
1443 if (req->oldptr != NULL) {
1444 error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
1445 sizeof(nmp->nm_tprintf_initial_delay));
1449 if (req->newptr != NULL) {
1450 error = vfs_suser(mp, req->td);
1453 error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
1454 sizeof(nmp->nm_tprintf_initial_delay));
1457 if (nmp->nm_tprintf_initial_delay < 0)
1458 nmp->nm_tprintf_initial_delay = 0;
1468 * Extract the information needed by the nlm from the nfs vnode.
1471 nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp,
1472 struct sockaddr_storage *sp, int *is_v3p, off_t *sizep,
1473 struct timeval *timeop)
1475 struct nfsmount *nmp;
1476 struct nfsnode *np = VTONFS(vp);
1478 nmp = VFSTONFS(vp->v_mount);
1480 *fhlenp = (size_t)np->n_fhp->nfh_len;
1482 bcopy(np->n_fhp->nfh_fh, fhp, np->n_fhp->nfh_len);
1484 bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp)));
1486 *is_v3p = NFS_ISV3(vp);
1488 *sizep = np->n_size;
1489 if (timeop != NULL) {
1490 timeop->tv_sec = nmp->nm_timeo / NFS_HZ;
1491 timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ);