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>
49 #include <sys/limits.h>
51 #include <sys/malloc.h>
53 #include <sys/module.h>
54 #include <sys/mount.h>
56 #include <sys/socket.h>
57 #include <sys/socketvar.h>
58 #include <sys/sockio.h>
59 #include <sys/sysctl.h>
60 #include <sys/vnode.h>
61 #include <sys/signalvar.h>
64 #include <vm/vm_extern.h>
68 #include <net/route.h>
69 #include <netinet/in.h>
71 #include <fs/nfs/nfsport.h>
72 #include <fs/nfsclient/nfsnode.h>
73 #include <fs/nfsclient/nfsmount.h>
74 #include <fs/nfsclient/nfs.h>
75 #include <fs/nfsclient/nfsdiskless.h>
77 extern int nfscl_ticks;
78 extern struct timeval nfsboottime;
79 extern struct nfsstats newnfsstats;
81 MALLOC_DEFINE(M_NEWNFSREQ, "newnfsclient_req", "New NFS request header");
82 MALLOC_DEFINE(M_NEWNFSMNT, "newnfsmnt", "New NFS mount struct");
84 SYSCTL_DECL(_vfs_newnfs);
85 SYSCTL_STRUCT(_vfs_newnfs, NFS_NFSSTATS, nfsstats, CTLFLAG_RW,
86 &newnfsstats, nfsstats, "S,nfsstats");
87 static int nfs_ip_paranoia = 1;
88 SYSCTL_INT(_vfs_newnfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW,
89 &nfs_ip_paranoia, 0, "");
90 static int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
91 SYSCTL_INT(_vfs_newnfs, NFS_TPRINTF_INITIAL_DELAY,
92 downdelayinitial, CTLFLAG_RW, &nfs_tprintf_initial_delay, 0, "");
93 /* how long between console messages "nfs server foo not responding" */
94 static int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
95 SYSCTL_INT(_vfs_newnfs, NFS_TPRINTF_DELAY,
96 downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0, "");
98 static void nfs_sec_name(char *, int *);
99 static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp,
100 struct nfs_args *argp, const char *, struct ucred *,
102 static int mountnfs(struct nfs_args *, struct mount *,
103 struct sockaddr *, char *, u_char *, u_char *, u_char *,
104 struct vnode **, struct ucred *, struct thread *, int);
105 static void nfs_getnlminfo(struct vnode *, uint8_t *, size_t *,
106 struct sockaddr_storage *, int *, off_t *,
108 static vfs_mount_t nfs_mount;
109 static vfs_cmount_t nfs_cmount;
110 static vfs_unmount_t nfs_unmount;
111 static vfs_root_t nfs_root;
112 static vfs_statfs_t nfs_statfs;
113 static vfs_sync_t nfs_sync;
114 static vfs_sysctl_t nfs_sysctl;
117 * nfs vfs operations.
119 static struct vfsops nfs_vfsops = {
120 .vfs_init = ncl_init,
121 .vfs_mount = nfs_mount,
122 .vfs_cmount = nfs_cmount,
123 .vfs_root = nfs_root,
124 .vfs_statfs = nfs_statfs,
125 .vfs_sync = nfs_sync,
126 .vfs_uninit = ncl_uninit,
127 .vfs_unmount = nfs_unmount,
128 .vfs_sysctl = nfs_sysctl,
130 VFS_SET(nfs_vfsops, newnfs, VFCF_NETWORK);
132 /* So that loader and kldload(2) can find us, wherever we are.. */
133 MODULE_VERSION(newnfs, 1);
136 * This structure must be filled in by a primary bootstrap or bootstrap
137 * server for a diskless/dataless machine. It is initialized below just
138 * to ensure that it is allocated to initialized data (.data not .bss).
140 struct nfs_diskless newnfs_diskless = { { { 0 } } };
141 struct nfsv3_diskless newnfsv3_diskless = { { { 0 } } };
142 int newnfs_diskless_valid = 0;
144 SYSCTL_INT(_vfs_newnfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
145 &newnfs_diskless_valid, 0,
146 "Has the diskless struct been filled correctly");
148 SYSCTL_STRING(_vfs_newnfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
149 newnfsv3_diskless.root_hostnam, 0, "Path to nfs root");
151 SYSCTL_OPAQUE(_vfs_newnfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
152 &newnfsv3_diskless.root_saddr, sizeof newnfsv3_diskless.root_saddr,
153 "%Ssockaddr_in", "Diskless root nfs address");
156 void newnfsargs_ntoh(struct nfs_args *);
157 static int nfs_mountdiskless(char *,
158 struct sockaddr_in *, struct nfs_args *,
159 struct thread *, struct vnode **, struct mount *);
160 static void nfs_convert_diskless(void);
161 static void nfs_convert_oargs(struct nfs_args *args,
162 struct onfs_args *oargs);
165 newnfs_iosize(struct nfsmount *nmp)
169 /* First, set the upper limit for iosize */
170 if (nmp->nm_flag & NFSMNT_NFSV4) {
171 maxio = NFS_MAXBSIZE;
172 } else if (nmp->nm_flag & NFSMNT_NFSV3) {
173 if (nmp->nm_sotype == SOCK_DGRAM)
174 maxio = NFS_MAXDGRAMDATA;
176 maxio = NFS_MAXBSIZE;
178 maxio = NFS_V2MAXDATA;
180 if (nmp->nm_rsize > maxio || nmp->nm_rsize == 0)
181 nmp->nm_rsize = maxio;
182 if (nmp->nm_rsize > MAXBSIZE)
183 nmp->nm_rsize = MAXBSIZE;
184 if (nmp->nm_readdirsize > maxio || nmp->nm_readdirsize == 0)
185 nmp->nm_readdirsize = maxio;
186 if (nmp->nm_readdirsize > nmp->nm_rsize)
187 nmp->nm_readdirsize = nmp->nm_rsize;
188 if (nmp->nm_wsize > maxio || nmp->nm_wsize == 0)
189 nmp->nm_wsize = maxio;
190 if (nmp->nm_wsize > MAXBSIZE)
191 nmp->nm_wsize = MAXBSIZE;
194 * Calculate the size used for io buffers. Use the larger
195 * of the two sizes to minimise nfs requests but make sure
196 * that it is at least one VM page to avoid wasting buffer
199 iosize = imax(nmp->nm_rsize, nmp->nm_wsize);
200 iosize = imax(iosize, PAGE_SIZE);
201 nmp->nm_mountp->mnt_stat.f_iosize = iosize;
206 nfs_convert_oargs(struct nfs_args *args, struct onfs_args *oargs)
209 args->version = NFS_ARGSVERSION;
210 args->addr = oargs->addr;
211 args->addrlen = oargs->addrlen;
212 args->sotype = oargs->sotype;
213 args->proto = oargs->proto;
214 args->fh = oargs->fh;
215 args->fhsize = oargs->fhsize;
216 args->flags = oargs->flags;
217 args->wsize = oargs->wsize;
218 args->rsize = oargs->rsize;
219 args->readdirsize = oargs->readdirsize;
220 args->timeo = oargs->timeo;
221 args->retrans = oargs->retrans;
222 args->readahead = oargs->readahead;
223 args->hostname = oargs->hostname;
227 nfs_convert_diskless(void)
230 bcopy(&newnfs_diskless.myif, &newnfsv3_diskless.myif,
231 sizeof (struct ifaliasreq));
232 bcopy(&newnfs_diskless.mygateway, &newnfsv3_diskless.mygateway,
233 sizeof (struct sockaddr_in));
234 nfs_convert_oargs(&newnfsv3_diskless.root_args,
235 &newnfs_diskless.root_args);
236 if (newnfsv3_diskless.root_args.flags & NFSMNT_NFSV3) {
237 newnfsv3_diskless.root_fhsize = NFSX_MYFH;
238 bcopy(newnfs_diskless.root_fh, newnfsv3_diskless.root_fh,
241 newnfsv3_diskless.root_fhsize = NFSX_V2FH;
242 bcopy(newnfs_diskless.root_fh, newnfsv3_diskless.root_fh,
245 bcopy(&newnfs_diskless.root_saddr,&newnfsv3_diskless.root_saddr,
246 sizeof(struct sockaddr_in));
247 bcopy(newnfs_diskless.root_hostnam, newnfsv3_diskless.root_hostnam,
249 newnfsv3_diskless.root_time = newnfs_diskless.root_time;
250 bcopy(newnfs_diskless.my_hostnam, newnfsv3_diskless.my_hostnam,
252 newnfs_diskless_valid = 3;
259 nfs_statfs(struct mount *mp, struct statfs *sbp)
263 struct nfsmount *nmp = VFSTONFS(mp);
264 struct nfsvattr nfsva;
267 int error = 0, attrflag, gotfsinfo = 0, ret;
272 error = vfs_busy(mp, MBF_NOWAIT);
275 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
281 mtx_lock(&nmp->nm_mtx);
282 if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
283 mtx_unlock(&nmp->nm_mtx);
284 error = nfsrpc_fsinfo(vp, &fs, td->td_ucred, td, &nfsva,
289 mtx_unlock(&nmp->nm_mtx);
291 error = nfsrpc_statfs(vp, &sb, &fs, td->td_ucred, td, &nfsva,
294 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
295 td->td_ucred, td, &nfsva, NULL);
298 * Just set default values to get things going.
300 NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
301 nfsva.na_vattr.va_type = VDIR;
302 nfsva.na_vattr.va_mode = 0777;
303 nfsva.na_vattr.va_nlink = 100;
304 nfsva.na_vattr.va_uid = (uid_t)0;
305 nfsva.na_vattr.va_gid = (gid_t)0;
306 nfsva.na_vattr.va_fileid = 2;
307 nfsva.na_vattr.va_gen = 1;
308 nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
309 nfsva.na_vattr.va_size = 512 * 1024;
312 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
314 mtx_lock(&nmp->nm_mtx);
315 if (gotfsinfo || (nmp->nm_flag & NFSMNT_NFSV4))
316 nfscl_loadfsinfo(nmp, &fs);
317 nfscl_loadsbinfo(nmp, &sb, sbp);
318 sbp->f_flags = nmp->nm_flag;
319 sbp->f_iosize = newnfs_iosize(nmp);
320 mtx_unlock(&nmp->nm_mtx);
321 if (sbp != &mp->mnt_stat) {
322 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
323 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
325 strncpy(&sbp->f_fstypename[0], mp->mnt_vfc->vfc_name, MFSNAMELEN);
326 } else if (NFS_ISV4(vp)) {
327 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
335 * nfs version 3 fsinfo rpc call
338 ncl_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred,
342 struct nfsvattr nfsva;
345 error = nfsrpc_fsinfo(vp, &fs, cred, td, &nfsva, &attrflag, NULL);
348 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0,
350 mtx_lock(&nmp->nm_mtx);
351 nfscl_loadfsinfo(nmp, &fs);
352 mtx_unlock(&nmp->nm_mtx);
358 * Mount a remote root fs via. nfs. This depends on the info in the
359 * newnfs_diskless structure that has been filled in properly by some primary
361 * It goes something like this:
362 * - do enough of "ifconfig" by calling ifioctl() so that the system
363 * can talk to the server
364 * - If newnfs_diskless.mygateway is filled in, use that address as
366 * - build the rootfs mount point and call mountnfs() to do the rest.
368 * It is assumed to be safe to read, modify, and write the nfsv3_diskless
369 * structure, as well as other global NFS client variables here, as
370 * nfs_mountroot() will be called once in the boot before any other NFS
371 * client activity occurs.
374 ncl_mountroot(struct mount *mp)
376 struct thread *td = curthread;
377 struct nfsv3_diskless *nd = &newnfsv3_diskless;
386 #if defined(BOOTP_NFSROOT) && defined(BOOTP)
387 bootpc_init(); /* use bootp to get nfs_diskless filled in */
388 #elif defined(NFS_ROOT)
389 nfs_setup_diskless();
392 if (newnfs_diskless_valid == 0)
394 if (newnfs_diskless_valid == 1)
395 nfs_convert_diskless();
398 * XXX splnet, so networks will receive...
403 * Do enough of ifconfig(8) so that the critical net interface can
404 * talk to the server.
406 error = socreate(nd->myif.ifra_addr.sa_family, &so, nd->root_args.sotype, 0,
409 panic("nfs_mountroot: socreate(%04x): %d",
410 nd->myif.ifra_addr.sa_family, error);
412 #if 0 /* XXX Bad idea */
414 * We might not have been told the right interface, so we pass
415 * over the first ten interfaces of the same kind, until we get
416 * one of them configured.
419 for (i = strlen(nd->myif.ifra_name) - 1;
420 nd->myif.ifra_name[i] >= '0' &&
421 nd->myif.ifra_name[i] <= '9';
422 nd->myif.ifra_name[i] ++) {
423 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
428 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
430 panic("nfs_mountroot: SIOCAIFADDR: %d", error);
431 if ((cp = getenv("boot.netif.mtu")) != NULL) {
432 ir.ifr_mtu = strtol(cp, NULL, 10);
433 bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ);
435 error = ifioctl(so, SIOCSIFMTU, (caddr_t)&ir, td);
437 printf("nfs_mountroot: SIOCSIFMTU: %d", error);
442 * If the gateway field is filled in, set it as the default route.
443 * Note that pxeboot will set a default route of 0 if the route
444 * is not set by the DHCP server. Check also for a value of 0
445 * to avoid panicking inappropriately in that situation.
447 if (nd->mygateway.sin_len != 0 &&
448 nd->mygateway.sin_addr.s_addr != 0) {
449 struct sockaddr_in mask, sin;
451 bzero((caddr_t)&mask, sizeof(mask));
453 sin.sin_family = AF_INET;
454 sin.sin_len = sizeof(sin);
455 /* XXX MRT use table 0 for this sort of thing */
456 CURVNET_SET(TD_TO_VNET(td));
457 error = rtrequest(RTM_ADD, (struct sockaddr *)&sin,
458 (struct sockaddr *)&nd->mygateway,
459 (struct sockaddr *)&mask,
460 RTF_UP | RTF_GATEWAY, NULL);
463 panic("nfs_mountroot: RTM_ADD: %d", error);
467 * Create the rootfs mount point.
469 nd->root_args.fh = nd->root_fh;
470 nd->root_args.fhsize = nd->root_fhsize;
471 l = ntohl(nd->root_saddr.sin_addr.s_addr);
472 snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
473 (l >> 24) & 0xff, (l >> 16) & 0xff,
474 (l >> 8) & 0xff, (l >> 0) & 0xff, nd->root_hostnam);
475 printf("NFS ROOT: %s\n", buf);
476 nd->root_args.hostname = buf;
477 if ((error = nfs_mountdiskless(buf,
478 &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) {
483 * This is not really an nfs issue, but it is much easier to
484 * set hostname here and then let the "/etc/rc.xxx" files
485 * mount the right /var based upon its preset value.
487 mtx_lock(&prison0.pr_mtx);
488 strlcpy(prison0.pr_hostname, nd->my_hostnam,
489 sizeof(prison0.pr_hostname));
490 mtx_unlock(&prison0.pr_mtx);
491 inittodr(ntohl(nd->root_time));
496 * Internal version of mount system call for diskless setup.
499 nfs_mountdiskless(char *path,
500 struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
501 struct vnode **vpp, struct mount *mp)
503 struct sockaddr *nam;
506 nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
507 if ((error = mountnfs(args, mp, nam, path, NULL, NULL, NULL, vpp,
508 td->td_ucred, td, NFS_DEFAULT_NEGNAMETIMEO)) != 0) {
509 printf("nfs_mountroot: mount %s on /: %d\n", path, error);
516 nfs_sec_name(char *sec, int *flagsp)
518 if (!strcmp(sec, "krb5"))
519 *flagsp |= NFSMNT_KERB;
520 else if (!strcmp(sec, "krb5i"))
521 *flagsp |= (NFSMNT_KERB | NFSMNT_INTEGRITY);
522 else if (!strcmp(sec, "krb5p"))
523 *flagsp |= (NFSMNT_KERB | NFSMNT_PRIVACY);
527 nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
528 const char *hostname, struct ucred *cred, struct thread *td)
537 * Set read-only flag if requested; otherwise, clear it if this is
538 * an update. If this is not an update, then either the read-only
539 * flag is already clear, or this is a root mount and it was set
540 * intentionally at some previous point.
542 if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) {
544 mp->mnt_flag |= MNT_RDONLY;
546 } else if (mp->mnt_flag & MNT_UPDATE) {
548 mp->mnt_flag &= ~MNT_RDONLY;
553 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
554 * no sense in that context. Also, set up appropriate retransmit
555 * and soft timeout behavior.
557 if (argp->sotype == SOCK_STREAM) {
558 nmp->nm_flag &= ~NFSMNT_NOCONN;
559 nmp->nm_timeo = NFS_MAXTIMEO;
560 if ((argp->flags & NFSMNT_NFSV4) != 0)
561 nmp->nm_retry = INT_MAX;
563 nmp->nm_retry = NFS_RETRANS_TCP;
566 /* Also clear RDIRPLUS if NFSv2, it crashes some servers */
567 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
568 argp->flags &= ~NFSMNT_RDIRPLUS;
569 nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
572 /* Clear NFSMNT_RESVPORT for NFSv4, since it is not required. */
573 if ((argp->flags & NFSMNT_NFSV4) != 0) {
574 argp->flags &= ~NFSMNT_RESVPORT;
575 nmp->nm_flag &= ~NFSMNT_RESVPORT;
578 /* Re-bind if rsrvd port requested and wasn't on one */
579 adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
580 && (argp->flags & NFSMNT_RESVPORT);
581 /* Also re-bind if we're switching to/from a connected UDP socket */
582 adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
583 (argp->flags & NFSMNT_NOCONN));
585 /* Update flags atomically. Don't change the lock bits. */
586 nmp->nm_flag = argp->flags | nmp->nm_flag;
589 if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
590 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
591 if (nmp->nm_timeo < NFS_MINTIMEO)
592 nmp->nm_timeo = NFS_MINTIMEO;
593 else if (nmp->nm_timeo > NFS_MAXTIMEO)
594 nmp->nm_timeo = NFS_MAXTIMEO;
597 if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
598 nmp->nm_retry = argp->retrans;
599 if (nmp->nm_retry > NFS_MAXREXMIT)
600 nmp->nm_retry = NFS_MAXREXMIT;
603 if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
604 nmp->nm_wsize = argp->wsize;
605 /* Round down to multiple of blocksize */
606 nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
607 if (nmp->nm_wsize <= 0)
608 nmp->nm_wsize = NFS_FABLKSIZE;
611 if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
612 nmp->nm_rsize = argp->rsize;
613 /* Round down to multiple of blocksize */
614 nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
615 if (nmp->nm_rsize <= 0)
616 nmp->nm_rsize = NFS_FABLKSIZE;
619 if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
620 nmp->nm_readdirsize = argp->readdirsize;
623 if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
624 nmp->nm_acregmin = argp->acregmin;
626 nmp->nm_acregmin = NFS_MINATTRTIMO;
627 if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
628 nmp->nm_acregmax = argp->acregmax;
630 nmp->nm_acregmax = NFS_MAXATTRTIMO;
631 if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
632 nmp->nm_acdirmin = argp->acdirmin;
634 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
635 if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
636 nmp->nm_acdirmax = argp->acdirmax;
638 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
639 if (nmp->nm_acdirmin > nmp->nm_acdirmax)
640 nmp->nm_acdirmin = nmp->nm_acdirmax;
641 if (nmp->nm_acregmin > nmp->nm_acregmax)
642 nmp->nm_acregmin = nmp->nm_acregmax;
644 if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
645 if (argp->readahead <= NFS_MAXRAHEAD)
646 nmp->nm_readahead = argp->readahead;
648 nmp->nm_readahead = NFS_MAXRAHEAD;
650 if ((argp->flags & NFSMNT_WCOMMITSIZE) && argp->wcommitsize >= 0) {
651 if (argp->wcommitsize < nmp->nm_wsize)
652 nmp->nm_wcommitsize = nmp->nm_wsize;
654 nmp->nm_wcommitsize = argp->wcommitsize;
657 adjsock |= ((nmp->nm_sotype != argp->sotype) ||
658 (nmp->nm_soproto != argp->proto));
660 if (nmp->nm_client != NULL && adjsock) {
661 int haslock = 0, error = 0;
663 if (nmp->nm_sotype == SOCK_STREAM) {
664 error = newnfs_sndlock(&nmp->nm_sockreq.nr_lock);
669 newnfs_disconnect(&nmp->nm_sockreq);
671 newnfs_sndunlock(&nmp->nm_sockreq.nr_lock);
672 nmp->nm_sotype = argp->sotype;
673 nmp->nm_soproto = argp->proto;
674 if (nmp->nm_sotype == SOCK_DGRAM)
675 while (newnfs_connect(nmp, &nmp->nm_sockreq,
677 printf("newnfs_args: retrying connect\n");
678 (void) nfs_catnap(PSOCK, 0, "newnfscon");
682 nmp->nm_sotype = argp->sotype;
683 nmp->nm_soproto = argp->proto;
686 if (hostname != NULL) {
687 strlcpy(nmp->nm_hostname, hostname,
688 sizeof(nmp->nm_hostname));
689 p = strchr(nmp->nm_hostname, ':');
695 static const char *nfs_opts[] = { "from",
696 "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
697 "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
698 "async", "noconn", "nolockd", "conn", "lockd", "intr", "rdirplus",
699 "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize",
700 "retrans", "acregmin", "acregmax", "acdirmin", "acdirmax", "resvport",
701 "readahead", "hostname", "timeout", "addr", "fh", "nfsv3", "sec",
702 "principal", "nfsv4", "gssname", "allgssname", "dirpath",
710 * It seems a bit dumb to copyinstr() the host and path here and then
711 * bcopy() them in mountnfs(), but I wanted to detect errors before
712 * doing the sockargs() call because sockargs() allocates an mbuf and
713 * an error after that means that I have to release the mbuf.
717 nfs_mount(struct mount *mp)
719 struct nfs_args args = {
720 .version = NFS_ARGSVERSION,
722 .addrlen = sizeof (struct sockaddr_in),
723 .sotype = SOCK_STREAM,
727 .flags = NFSMNT_RESVPORT,
730 .readdirsize = NFS_READDIRSIZE,
732 .retrans = NFS_RETRANS,
733 .readahead = NFS_DEFRAHEAD,
734 .wcommitsize = 0, /* was: NQ_DEFLEASE */
737 .acregmin = NFS_MINATTRTIMO,
738 .acregmax = NFS_MAXATTRTIMO,
739 .acdirmin = NFS_MINDIRATTRTIMO,
740 .acdirmax = NFS_MAXDIRATTRTIMO,
745 int error = 0, ret, len;
746 struct sockaddr *nam = NULL;
750 u_char nfh[NFSX_FHMAX], krbname[100], dirpath[100], srvkrbname[100];
751 char *opt, *name, *secname;
752 int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
754 if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
760 if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS) {
761 error = ncl_mountroot(mp);
767 /* Handle the new style options. */
768 if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
769 args.flags |= NFSMNT_NOCONN;
770 if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
771 args.flags |= NFSMNT_NOCONN;
772 if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
773 args.flags |= NFSMNT_NOLOCKD;
774 if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
775 args.flags &= ~NFSMNT_NOLOCKD;
776 if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
777 args.flags |= NFSMNT_INT;
778 if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
779 args.flags |= NFSMNT_RDIRPLUS;
780 if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
781 args.flags |= NFSMNT_RESVPORT;
782 if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
783 args.flags &= ~NFSMNT_RESVPORT;
784 if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
785 args.flags |= NFSMNT_SOFT;
786 if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
787 args.flags &= ~NFSMNT_SOFT;
788 if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
789 args.sotype = SOCK_DGRAM;
790 if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
791 args.sotype = SOCK_DGRAM;
792 if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
793 args.sotype = SOCK_STREAM;
794 if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
795 args.flags |= NFSMNT_NFSV3;
796 if (vfs_getopt(mp->mnt_optnew, "nfsv4", NULL, NULL) == 0) {
797 args.flags |= NFSMNT_NFSV4;
798 args.sotype = SOCK_STREAM;
800 if (vfs_getopt(mp->mnt_optnew, "allgssname", NULL, NULL) == 0)
801 args.flags |= NFSMNT_ALLGSSNAME;
802 if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
804 vfs_mount_error(mp, "illegal readdirsize");
808 ret = sscanf(opt, "%d", &args.readdirsize);
809 if (ret != 1 || args.readdirsize <= 0) {
810 vfs_mount_error(mp, "illegal readdirsize: %s",
815 args.flags |= NFSMNT_READDIRSIZE;
817 if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
819 vfs_mount_error(mp, "illegal readahead");
823 ret = sscanf(opt, "%d", &args.readahead);
824 if (ret != 1 || args.readahead <= 0) {
825 vfs_mount_error(mp, "illegal readahead: %s",
830 args.flags |= NFSMNT_READAHEAD;
832 if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
834 vfs_mount_error(mp, "illegal wsize");
838 ret = sscanf(opt, "%d", &args.wsize);
839 if (ret != 1 || args.wsize <= 0) {
840 vfs_mount_error(mp, "illegal wsize: %s",
845 args.flags |= NFSMNT_WSIZE;
847 if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
849 vfs_mount_error(mp, "illegal rsize");
853 ret = sscanf(opt, "%d", &args.rsize);
854 if (ret != 1 || args.rsize <= 0) {
855 vfs_mount_error(mp, "illegal wsize: %s",
860 args.flags |= NFSMNT_RSIZE;
862 if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
864 vfs_mount_error(mp, "illegal retrans");
868 ret = sscanf(opt, "%d", &args.retrans);
869 if (ret != 1 || args.retrans <= 0) {
870 vfs_mount_error(mp, "illegal retrans: %s",
875 args.flags |= NFSMNT_RETRANS;
877 if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
878 ret = sscanf(opt, "%d", &args.acregmin);
879 if (ret != 1 || args.acregmin < 0) {
880 vfs_mount_error(mp, "illegal acregmin: %s",
885 args.flags |= NFSMNT_ACREGMIN;
887 if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
888 ret = sscanf(opt, "%d", &args.acregmax);
889 if (ret != 1 || args.acregmax < 0) {
890 vfs_mount_error(mp, "illegal acregmax: %s",
895 args.flags |= NFSMNT_ACREGMAX;
897 if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
898 ret = sscanf(opt, "%d", &args.acdirmin);
899 if (ret != 1 || args.acdirmin < 0) {
900 vfs_mount_error(mp, "illegal acdirmin: %s",
905 args.flags |= NFSMNT_ACDIRMIN;
907 if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
908 ret = sscanf(opt, "%d", &args.acdirmax);
909 if (ret != 1 || args.acdirmax < 0) {
910 vfs_mount_error(mp, "illegal acdirmax: %s",
915 args.flags |= NFSMNT_ACDIRMAX;
917 if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
918 ret = sscanf(opt, "%d", &args.timeo);
919 if (ret != 1 || args.timeo <= 0) {
920 vfs_mount_error(mp, "illegal timeout: %s",
925 args.flags |= NFSMNT_TIMEO;
927 if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
929 ret = sscanf(opt, "%d", &negnametimeo);
930 if (ret != 1 || negnametimeo < 0) {
931 vfs_mount_error(mp, "illegal negnametimeo: %s",
937 if (vfs_getopt(mp->mnt_optnew, "sec",
938 (void **) &secname, NULL) == 0)
939 nfs_sec_name(secname, &args.flags);
941 if (mp->mnt_flag & MNT_UPDATE) {
942 struct nfsmount *nmp = VFSTONFS(mp);
949 * When doing an update, we can't change version,
950 * security, switch lockd strategies or change cookie
953 args.flags = (args.flags &
959 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
966 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
967 nfs_decode_args(mp, nmp, &args, NULL, td->td_ucred, td);
972 * Make the nfs_ip_paranoia sysctl serve as the default connection
973 * or no-connection mode for those protocols that support
974 * no-connection mode (the flag will be cleared later for protocols
975 * that do not support no-connection mode). This will allow a client
976 * to receive replies from a different IP then the request was
977 * sent to. Note: default value for nfs_ip_paranoia is 1 (paranoid),
980 if (nfs_ip_paranoia == 0)
981 args.flags |= NFSMNT_NOCONN;
983 if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
984 &args.fhsize) == 0) {
985 if (args.fhsize < 0 || args.fhsize > NFSX_FHMAX) {
986 vfs_mount_error(mp, "Bad file handle");
990 bcopy(args.fh, nfh, args.fhsize);
995 (void) vfs_getopt(mp->mnt_optnew, "hostname", (void **)&args.hostname,
997 if (args.hostname == NULL) {
998 vfs_mount_error(mp, "Invalid hostname");
1002 bcopy(args.hostname, hst, MNAMELEN);
1003 hst[MNAMELEN - 1] = '\0';
1005 if (vfs_getopt(mp->mnt_optnew, "principal", (void **)&name, NULL) == 0)
1006 strlcpy(srvkrbname, name, sizeof (srvkrbname));
1008 snprintf(srvkrbname, sizeof (srvkrbname), "nfs@%s", hst);
1009 args.srvkrbnamelen = strlen(srvkrbname);
1011 if (vfs_getopt(mp->mnt_optnew, "gssname", (void **)&name, NULL) == 0)
1012 strlcpy(krbname, name, sizeof (krbname));
1015 args.krbnamelen = strlen(krbname);
1017 if (vfs_getopt(mp->mnt_optnew, "dirpath", (void **)&name, NULL) == 0)
1018 strlcpy(dirpath, name, sizeof (dirpath));
1021 args.dirlen = strlen(dirpath);
1023 if (vfs_getopt(mp->mnt_optnew, "addr", (void **)&args.addr,
1024 &args.addrlen) == 0) {
1025 if (args.addrlen > SOCK_MAXADDRLEN) {
1026 error = ENAMETOOLONG;
1029 nam = malloc(args.addrlen, M_SONAME, M_WAITOK);
1030 bcopy(args.addr, nam, args.addrlen);
1031 nam->sa_len = args.addrlen;
1035 error = mountnfs(&args, mp, nam, hst, krbname, dirpath, srvkrbname,
1036 &vp, td->td_ucred, td, negnametimeo);
1040 mp->mnt_kern_flag |= (MNTK_MPSAFE|MNTK_LOOKUP_SHARED);
1051 * It seems a bit dumb to copyinstr() the host and path here and then
1052 * bcopy() them in mountnfs(), but I wanted to detect errors before
1053 * doing the sockargs() call because sockargs() allocates an mbuf and
1054 * an error after that means that I have to release the mbuf.
1058 nfs_cmount(struct mntarg *ma, void *data, int flags)
1061 struct nfs_args args;
1063 error = copyin(data, &args, sizeof (struct nfs_args));
1067 ma = mount_arg(ma, "nfs_args", &args, sizeof args);
1069 error = kernel_mount(ma, flags);
1074 * Common code for mount and mountroot
1077 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
1078 char *hst, u_char *krbname, u_char *dirpath, u_char *srvkrbname,
1079 struct vnode **vpp, struct ucred *cred, struct thread *td,
1082 struct nfsmount *nmp;
1084 int error, trycnt, ret;
1085 struct nfsvattr nfsva;
1086 static u_int64_t clval = 0;
1088 if (mp->mnt_flag & MNT_UPDATE) {
1090 printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
1091 FREE(nam, M_SONAME);
1094 MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount) +
1095 argp->krbnamelen + argp->dirlen + argp->srvkrbnamelen + 2,
1096 M_NEWNFSMNT, M_WAITOK);
1097 bzero((caddr_t)nmp, sizeof (struct nfsmount) +
1098 argp->krbnamelen + argp->dirlen + argp->srvkrbnamelen + 2);
1099 TAILQ_INIT(&nmp->nm_bufq);
1101 clval = (u_int64_t)nfsboottime.tv_sec;
1102 nmp->nm_clval = clval++;
1103 nmp->nm_krbnamelen = argp->krbnamelen;
1104 nmp->nm_dirpathlen = argp->dirlen;
1105 nmp->nm_srvkrbnamelen = argp->srvkrbnamelen;
1106 if (td->td_ucred->cr_uid != (uid_t)0) {
1108 * nm_uid is used to get KerberosV credentials for
1109 * the nfsv4 state handling operations if there is
1110 * no host based principal set. Use the uid of
1111 * this user if not root, since they are doing the
1112 * mount. I don't think setting this for root will
1113 * work, since root normally does not have user
1114 * credentials in a credentials cache.
1116 nmp->nm_uid = td->td_ucred->cr_uid;
1119 * Just set to -1, so it won't be used.
1121 nmp->nm_uid = (uid_t)-1;
1124 /* Copy and null terminate all the names */
1125 if (nmp->nm_krbnamelen > 0) {
1126 bcopy(krbname, nmp->nm_krbname, nmp->nm_krbnamelen);
1127 nmp->nm_name[nmp->nm_krbnamelen] = '\0';
1129 if (nmp->nm_dirpathlen > 0) {
1130 bcopy(dirpath, NFSMNT_DIRPATH(nmp),
1131 nmp->nm_dirpathlen);
1132 nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1135 if (nmp->nm_srvkrbnamelen > 0) {
1136 bcopy(srvkrbname, NFSMNT_SRVKRBNAME(nmp),
1137 nmp->nm_srvkrbnamelen);
1138 nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1139 + nmp->nm_srvkrbnamelen + 2] = '\0';
1141 nmp->nm_sockreq.nr_cred = crhold(cred);
1142 mtx_init(&nmp->nm_sockreq.nr_mtx, "nfssock", NULL, MTX_DEF);
1144 nmp->nm_getinfo = nfs_getnlminfo;
1145 nmp->nm_vinvalbuf = ncl_vinvalbuf;
1148 nmp->nm_mountp = mp;
1149 mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF | MTX_DUPOK);
1150 nmp->nm_negnametimeo = negnametimeo;
1152 nfs_decode_args(mp, nmp, argp, hst, cred, td);
1155 * V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too
1156 * high, depending on whether we end up with negative offsets in
1157 * the client or server somewhere. 2GB-1 may be safer.
1159 * For V3, ncl_fsinfo will adjust this as necessary. Assume maximum
1160 * that we can handle until we find out otherwise.
1161 * XXX Our "safe" limit on the client is what we can store in our
1162 * buffer cache using signed(!) block numbers.
1164 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0)
1165 nmp->nm_maxfilesize = 0xffffffffLL;
1167 nmp->nm_maxfilesize = (u_int64_t)0x80000000 * DEV_BSIZE - 1;
1169 nmp->nm_timeo = NFS_TIMEO;
1170 nmp->nm_retry = NFS_RETRANS;
1171 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
1172 nmp->nm_wsize = NFS_WSIZE;
1173 nmp->nm_rsize = NFS_RSIZE;
1174 nmp->nm_readdirsize = NFS_READDIRSIZE;
1176 nmp->nm_wcommitsize = hibufspace / (desiredvnodes / 1000);
1177 nmp->nm_numgrps = NFS_MAXGRPS;
1178 nmp->nm_readahead = NFS_DEFRAHEAD;
1179 nmp->nm_tprintf_delay = nfs_tprintf_delay;
1180 if (nmp->nm_tprintf_delay < 0)
1181 nmp->nm_tprintf_delay = 0;
1182 nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
1183 if (nmp->nm_tprintf_initial_delay < 0)
1184 nmp->nm_tprintf_initial_delay = 0;
1185 nmp->nm_fhsize = argp->fhsize;
1186 if (nmp->nm_fhsize > 0)
1187 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
1188 bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
1190 /* Set up the sockets and per-host congestion */
1191 nmp->nm_sotype = argp->sotype;
1192 nmp->nm_soproto = argp->proto;
1193 nmp->nm_sockreq.nr_prog = NFS_PROG;
1194 if ((argp->flags & NFSMNT_NFSV4))
1195 nmp->nm_sockreq.nr_vers = NFS_VER4;
1196 else if ((argp->flags & NFSMNT_NFSV3))
1197 nmp->nm_sockreq.nr_vers = NFS_VER3;
1199 nmp->nm_sockreq.nr_vers = NFS_VER2;
1202 if ((error = newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0)))
1206 * A reference count is needed on the nfsnode representing the
1207 * remote root. If this object is not persistent, then backward
1208 * traversals of the mount point (i.e. "..") will not work if
1209 * the nfsnode gets flushed out of the cache. Ufs does not have
1210 * this problem, because one can identify root inodes by their
1211 * number == ROOTINO (2).
1213 if (nmp->nm_fhsize == 0 && (nmp->nm_flag & NFSMNT_NFSV4) &&
1214 nmp->nm_dirpathlen > 0) {
1216 * If the fhsize on the mount point == 0 for V4, the mount
1217 * path needs to be looked up.
1221 error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp),
1224 (void) nfs_catnap(PZERO, error, "nfsgetdirp");
1225 } while (error && --trycnt > 0);
1227 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
1231 if (nmp->nm_fhsize > 0) {
1233 * Set f_iosize to NFS_DIRBLKSIZ so that bo_bsize gets set
1234 * non-zero for the root vnode. f_iosize will be set correctly
1235 * by nfs_statfs() before any I/O occurs.
1237 mp->mnt_stat.f_iosize = NFS_DIRBLKSIZ;
1238 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np,
1245 * Get file attributes and transfer parameters for the
1246 * mountpoint. This has the side effect of filling in
1247 * (*vpp)->v_type with the correct value.
1249 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
1250 cred, td, &nfsva, NULL);
1253 * Just set default values to get things going.
1255 NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
1256 nfsva.na_vattr.va_type = VDIR;
1257 nfsva.na_vattr.va_mode = 0777;
1258 nfsva.na_vattr.va_nlink = 100;
1259 nfsva.na_vattr.va_uid = (uid_t)0;
1260 nfsva.na_vattr.va_gid = (gid_t)0;
1261 nfsva.na_vattr.va_fileid = 2;
1262 nfsva.na_vattr.va_gen = 1;
1263 nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
1264 nfsva.na_vattr.va_size = 512 * 1024;
1266 (void) nfscl_loadattrcache(vpp, &nfsva, NULL, NULL, 0, 1);
1267 if (argp->flags & NFSMNT_NFSV3)
1268 ncl_fsinfo(nmp, *vpp, cred, td);
1271 * Lose the lock but keep the ref.
1273 VOP_UNLOCK(*vpp, 0);
1279 newnfs_disconnect(&nmp->nm_sockreq);
1280 crfree(nmp->nm_sockreq.nr_cred);
1281 mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1282 mtx_destroy(&nmp->nm_mtx);
1283 FREE(nmp, M_NEWNFSMNT);
1284 FREE(nam, M_SONAME);
1289 * unmount system call
1292 nfs_unmount(struct mount *mp, int mntflags)
1295 struct nfsmount *nmp;
1296 int error, flags = 0, trycnt = 0;
1300 if (mntflags & MNT_FORCE)
1301 flags |= FORCECLOSE;
1304 * Goes something like this..
1305 * - Call vflush() to clear out vnodes for this filesystem
1306 * - Close the socket
1307 * - Free up the data structures
1309 /* In the forced case, cancel any outstanding requests. */
1310 if (mntflags & MNT_FORCE) {
1311 error = newnfs_nmcancelreqs(nmp);
1314 /* For a forced close, get rid of the renew thread now */
1315 nfscl_umount(nmp, td);
1317 /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
1319 error = vflush(mp, 1, flags, td);
1320 if ((mntflags & MNT_FORCE) && error != 0 && ++trycnt < 30)
1321 (void) nfs_catnap(PSOCK, error, "newndm");
1322 } while ((mntflags & MNT_FORCE) && error != 0 && trycnt < 30);
1327 * We are now committed to the unmount.
1329 if ((mntflags & MNT_FORCE) == 0)
1330 nfscl_umount(nmp, td);
1331 newnfs_disconnect(&nmp->nm_sockreq);
1332 crfree(nmp->nm_sockreq.nr_cred);
1333 FREE(nmp->nm_nam, M_SONAME);
1335 mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1336 mtx_destroy(&nmp->nm_mtx);
1337 FREE(nmp, M_NEWNFSMNT);
1343 * Return root of a filesystem
1346 nfs_root(struct mount *mp, int flags, struct vnode **vpp)
1349 struct nfsmount *nmp;
1354 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, flags);
1359 * Get transfer parameters and attributes for root vnode once.
1361 mtx_lock(&nmp->nm_mtx);
1362 if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
1363 mtx_unlock(&nmp->nm_mtx);
1364 ncl_fsinfo(nmp, vp, curthread->td_ucred, curthread);
1366 mtx_unlock(&nmp->nm_mtx);
1367 if (vp->v_type == VNON)
1369 vp->v_vflag |= VV_ROOT;
1375 * Flush out the buffer cache
1379 nfs_sync(struct mount *mp, int waitfor)
1381 struct vnode *vp, *mvp;
1383 int error, allerror = 0;
1388 * Force stale buffer cache information to be flushed.
1392 MNT_VNODE_FOREACH(vp, mp, mvp) {
1395 /* XXX Racy bv_cnt check. */
1396 if (VOP_ISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
1397 waitfor == MNT_LAZY) {
1402 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
1404 MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp);
1407 error = VOP_FSYNC(vp, waitfor, td);
1420 nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
1422 struct nfsmount *nmp = VFSTONFS(mp);
1426 bzero(&vq, sizeof(vq));
1429 case VFS_CTL_NOLOCKS:
1430 val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
1431 if (req->oldptr != NULL) {
1432 error = SYSCTL_OUT(req, &val, sizeof(val));
1436 if (req->newptr != NULL) {
1437 error = SYSCTL_IN(req, &val, sizeof(val));
1441 nmp->nm_flag |= NFSMNT_NOLOCKS;
1443 nmp->nm_flag &= ~NFSMNT_NOLOCKS;
1448 mtx_lock(&nmp->nm_mtx);
1449 if (nmp->nm_state & NFSSTA_TIMEO)
1450 vq.vq_flags |= VQ_NOTRESP;
1451 mtx_unlock(&nmp->nm_mtx);
1453 if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
1454 (nmp->nm_state & NFSSTA_LOCKTIMEO))
1455 vq.vq_flags |= VQ_NOTRESPLOCK;
1457 error = SYSCTL_OUT(req, &vq, sizeof(vq));
1460 if (req->oldptr != NULL) {
1461 error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
1462 sizeof(nmp->nm_tprintf_initial_delay));
1466 if (req->newptr != NULL) {
1467 error = vfs_suser(mp, req->td);
1470 error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
1471 sizeof(nmp->nm_tprintf_initial_delay));
1474 if (nmp->nm_tprintf_initial_delay < 0)
1475 nmp->nm_tprintf_initial_delay = 0;
1485 * Extract the information needed by the nlm from the nfs vnode.
1488 nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp,
1489 struct sockaddr_storage *sp, int *is_v3p, off_t *sizep,
1490 struct timeval *timeop)
1492 struct nfsmount *nmp;
1493 struct nfsnode *np = VTONFS(vp);
1495 nmp = VFSTONFS(vp->v_mount);
1497 *fhlenp = (size_t)np->n_fhp->nfh_len;
1499 bcopy(np->n_fhp->nfh_fh, fhp, np->n_fhp->nfh_len);
1501 bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp)));
1503 *is_v3p = NFS_ISV3(vp);
1505 *sizep = np->n_size;
1506 if (timeop != NULL) {
1507 timeop->tv_sec = nmp->nm_timeo / NFS_HZ;
1508 timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ);