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 <nfs/nfsdiskless.h>
77 FEATURE(nfscl, "NFSv4 client");
79 extern int nfscl_ticks;
80 extern struct timeval nfsboottime;
81 extern struct nfsstats newnfsstats;
83 MALLOC_DEFINE(M_NEWNFSREQ, "newnfsclient_req", "New NFS request header");
84 MALLOC_DEFINE(M_NEWNFSMNT, "newnfsmnt", "New NFS mount struct");
86 SYSCTL_DECL(_vfs_newnfs);
87 SYSCTL_STRUCT(_vfs_newnfs, NFS_NFSSTATS, nfsstats, CTLFLAG_RW,
88 &newnfsstats, nfsstats, "S,nfsstats");
89 static int nfs_ip_paranoia = 1;
90 SYSCTL_INT(_vfs_newnfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW,
91 &nfs_ip_paranoia, 0, "");
92 static int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
93 SYSCTL_INT(_vfs_newnfs, NFS_TPRINTF_INITIAL_DELAY,
94 downdelayinitial, CTLFLAG_RW, &nfs_tprintf_initial_delay, 0, "");
95 /* how long between console messages "nfs server foo not responding" */
96 static int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
97 SYSCTL_INT(_vfs_newnfs, NFS_TPRINTF_DELAY,
98 downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0, "");
100 static int nfs_mountroot(struct mount *);
101 static void nfs_sec_name(char *, int *);
102 static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp,
103 struct nfs_args *argp, const char *, struct ucred *,
105 static int mountnfs(struct nfs_args *, struct mount *,
106 struct sockaddr *, char *, u_char *, int, u_char *, int,
107 u_char *, int, struct vnode **, struct ucred *,
108 struct thread *, int);
109 static void nfs_getnlminfo(struct vnode *, uint8_t *, size_t *,
110 struct sockaddr_storage *, int *, off_t *,
112 static vfs_mount_t nfs_mount;
113 static vfs_cmount_t nfs_cmount;
114 static vfs_unmount_t nfs_unmount;
115 static vfs_root_t nfs_root;
116 static vfs_statfs_t nfs_statfs;
117 static vfs_sync_t nfs_sync;
118 static vfs_sysctl_t nfs_sysctl;
121 * nfs vfs operations.
123 static struct vfsops nfs_vfsops = {
124 .vfs_init = ncl_init,
125 .vfs_mount = nfs_mount,
126 .vfs_cmount = nfs_cmount,
127 .vfs_root = nfs_root,
128 .vfs_statfs = nfs_statfs,
129 .vfs_sync = nfs_sync,
130 .vfs_uninit = ncl_uninit,
131 .vfs_unmount = nfs_unmount,
132 .vfs_sysctl = nfs_sysctl,
134 VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK);
136 /* So that loader and kldload(2) can find us, wherever we are.. */
137 MODULE_VERSION(nfs, 1);
138 MODULE_DEPEND(nfs, nfscommon, 1, 1, 1);
139 MODULE_DEPEND(nfs, krpc, 1, 1, 1);
140 MODULE_DEPEND(nfs, nfssvc, 1, 1, 1);
141 MODULE_DEPEND(nfs, nfslock, 1, 1, 1);
144 * This structure is now defined in sys/nfs/nfs_diskless.c so that it
145 * can be shared by both NFS clients. It is declared here so that it
146 * will be defined for kernels built without NFS_ROOT, although it
147 * isn't used in that case.
149 #if !defined(NFS_ROOT) && !defined(NFSCLIENT)
150 struct nfs_diskless nfs_diskless = { { { 0 } } };
151 struct nfsv3_diskless nfsv3_diskless = { { { 0 } } };
152 int nfs_diskless_valid = 0;
155 SYSCTL_INT(_vfs_newnfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
156 &nfs_diskless_valid, 0,
157 "Has the diskless struct been filled correctly");
159 SYSCTL_STRING(_vfs_newnfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
160 nfsv3_diskless.root_hostnam, 0, "Path to nfs root");
162 SYSCTL_OPAQUE(_vfs_newnfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
163 &nfsv3_diskless.root_saddr, sizeof(nfsv3_diskless.root_saddr),
164 "%Ssockaddr_in", "Diskless root nfs address");
167 void newnfsargs_ntoh(struct nfs_args *);
168 static int nfs_mountdiskless(char *,
169 struct sockaddr_in *, struct nfs_args *,
170 struct thread *, struct vnode **, struct mount *);
171 static void nfs_convert_diskless(void);
172 static void nfs_convert_oargs(struct nfs_args *args,
173 struct onfs_args *oargs);
176 newnfs_iosize(struct nfsmount *nmp)
180 /* First, set the upper limit for iosize */
181 if (nmp->nm_flag & NFSMNT_NFSV4) {
182 maxio = NFS_MAXBSIZE;
183 } else if (nmp->nm_flag & NFSMNT_NFSV3) {
184 if (nmp->nm_sotype == SOCK_DGRAM)
185 maxio = NFS_MAXDGRAMDATA;
187 maxio = NFS_MAXBSIZE;
189 maxio = NFS_V2MAXDATA;
191 if (nmp->nm_rsize > maxio || nmp->nm_rsize == 0)
192 nmp->nm_rsize = maxio;
193 if (nmp->nm_rsize > MAXBSIZE)
194 nmp->nm_rsize = MAXBSIZE;
195 if (nmp->nm_readdirsize > maxio || nmp->nm_readdirsize == 0)
196 nmp->nm_readdirsize = maxio;
197 if (nmp->nm_readdirsize > nmp->nm_rsize)
198 nmp->nm_readdirsize = nmp->nm_rsize;
199 if (nmp->nm_wsize > maxio || nmp->nm_wsize == 0)
200 nmp->nm_wsize = maxio;
201 if (nmp->nm_wsize > MAXBSIZE)
202 nmp->nm_wsize = MAXBSIZE;
205 * Calculate the size used for io buffers. Use the larger
206 * of the two sizes to minimise nfs requests but make sure
207 * that it is at least one VM page to avoid wasting buffer
210 iosize = imax(nmp->nm_rsize, nmp->nm_wsize);
211 iosize = imax(iosize, PAGE_SIZE);
212 nmp->nm_mountp->mnt_stat.f_iosize = iosize;
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->readahead = oargs->readahead;
234 args->hostname = oargs->hostname;
238 nfs_convert_diskless(void)
241 bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
242 sizeof(struct ifaliasreq));
243 bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
244 sizeof(struct sockaddr_in));
245 nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
246 if (nfsv3_diskless.root_args.flags & NFSMNT_NFSV3) {
247 nfsv3_diskless.root_fhsize = NFSX_MYFH;
248 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_MYFH);
250 nfsv3_diskless.root_fhsize = NFSX_V2FH;
251 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
253 bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
254 sizeof(struct sockaddr_in));
255 bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN);
256 nfsv3_diskless.root_time = nfs_diskless.root_time;
257 bcopy(nfs_diskless.my_hostnam, nfsv3_diskless.my_hostnam,
259 nfs_diskless_valid = 3;
266 nfs_statfs(struct mount *mp, struct statfs *sbp)
270 struct nfsmount *nmp = VFSTONFS(mp);
271 struct nfsvattr nfsva;
274 int error = 0, attrflag, gotfsinfo = 0, ret;
279 error = vfs_busy(mp, MBF_NOWAIT);
282 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
288 mtx_lock(&nmp->nm_mtx);
289 if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
290 mtx_unlock(&nmp->nm_mtx);
291 error = nfsrpc_fsinfo(vp, &fs, td->td_ucred, td, &nfsva,
296 mtx_unlock(&nmp->nm_mtx);
298 error = nfsrpc_statfs(vp, &sb, &fs, td->td_ucred, td, &nfsva,
301 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
302 td->td_ucred, td, &nfsva, NULL);
305 * Just set default values to get things going.
307 NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
308 nfsva.na_vattr.va_type = VDIR;
309 nfsva.na_vattr.va_mode = 0777;
310 nfsva.na_vattr.va_nlink = 100;
311 nfsva.na_vattr.va_uid = (uid_t)0;
312 nfsva.na_vattr.va_gid = (gid_t)0;
313 nfsva.na_vattr.va_fileid = 2;
314 nfsva.na_vattr.va_gen = 1;
315 nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
316 nfsva.na_vattr.va_size = 512 * 1024;
319 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
321 mtx_lock(&nmp->nm_mtx);
322 if (gotfsinfo || (nmp->nm_flag & NFSMNT_NFSV4))
323 nfscl_loadfsinfo(nmp, &fs);
324 nfscl_loadsbinfo(nmp, &sb, sbp);
325 sbp->f_iosize = newnfs_iosize(nmp);
326 mtx_unlock(&nmp->nm_mtx);
327 if (sbp != &mp->mnt_stat) {
328 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
329 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
331 strncpy(&sbp->f_fstypename[0], mp->mnt_vfc->vfc_name, MFSNAMELEN);
332 } else if (NFS_ISV4(vp)) {
333 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
341 * nfs version 3 fsinfo rpc call
344 ncl_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred,
348 struct nfsvattr nfsva;
351 error = nfsrpc_fsinfo(vp, &fs, cred, td, &nfsva, &attrflag, NULL);
354 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0,
356 mtx_lock(&nmp->nm_mtx);
357 nfscl_loadfsinfo(nmp, &fs);
358 mtx_unlock(&nmp->nm_mtx);
364 * Mount a remote root fs via. nfs. This depends on the info in the
365 * nfs_diskless structure that has been filled in properly by some primary
367 * It goes something like this:
368 * - do enough of "ifconfig" by calling ifioctl() so that the system
369 * can talk to the server
370 * - If nfs_diskless.mygateway is filled in, use that address as
372 * - build the rootfs mount point and call mountnfs() to do the rest.
374 * It is assumed to be safe to read, modify, and write the nfsv3_diskless
375 * structure, as well as other global NFS client variables here, as
376 * nfs_mountroot() will be called once in the boot before any other NFS
377 * client activity occurs.
380 nfs_mountroot(struct mount *mp)
382 struct thread *td = curthread;
383 struct nfsv3_diskless *nd = &nfsv3_diskless;
392 #if defined(BOOTP_NFSROOT) && defined(BOOTP)
393 bootpc_init(); /* use bootp to get nfs_diskless filled in */
394 #elif defined(NFS_ROOT)
395 nfs_setup_diskless();
398 if (nfs_diskless_valid == 0)
400 if (nfs_diskless_valid == 1)
401 nfs_convert_diskless();
404 * XXX splnet, so networks will receive...
409 * Do enough of ifconfig(8) so that the critical net interface can
410 * talk to the server.
412 error = socreate(nd->myif.ifra_addr.sa_family, &so, nd->root_args.sotype, 0,
415 panic("nfs_mountroot: socreate(%04x): %d",
416 nd->myif.ifra_addr.sa_family, error);
418 #if 0 /* XXX Bad idea */
420 * We might not have been told the right interface, so we pass
421 * over the first ten interfaces of the same kind, until we get
422 * one of them configured.
425 for (i = strlen(nd->myif.ifra_name) - 1;
426 nd->myif.ifra_name[i] >= '0' &&
427 nd->myif.ifra_name[i] <= '9';
428 nd->myif.ifra_name[i] ++) {
429 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
434 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
436 panic("nfs_mountroot: SIOCAIFADDR: %d", error);
437 if ((cp = getenv("boot.netif.mtu")) != NULL) {
438 ir.ifr_mtu = strtol(cp, NULL, 10);
439 bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ);
441 error = ifioctl(so, SIOCSIFMTU, (caddr_t)&ir, td);
443 printf("nfs_mountroot: SIOCSIFMTU: %d", error);
448 * If the gateway field is filled in, set it as the default route.
449 * Note that pxeboot will set a default route of 0 if the route
450 * is not set by the DHCP server. Check also for a value of 0
451 * to avoid panicking inappropriately in that situation.
453 if (nd->mygateway.sin_len != 0 &&
454 nd->mygateway.sin_addr.s_addr != 0) {
455 struct sockaddr_in mask, sin;
457 bzero((caddr_t)&mask, sizeof(mask));
459 sin.sin_family = AF_INET;
460 sin.sin_len = sizeof(sin);
461 /* XXX MRT use table 0 for this sort of thing */
462 CURVNET_SET(TD_TO_VNET(td));
463 error = rtrequest(RTM_ADD, (struct sockaddr *)&sin,
464 (struct sockaddr *)&nd->mygateway,
465 (struct sockaddr *)&mask,
466 RTF_UP | RTF_GATEWAY, NULL);
469 panic("nfs_mountroot: RTM_ADD: %d", error);
473 * Create the rootfs mount point.
475 nd->root_args.fh = nd->root_fh;
476 nd->root_args.fhsize = nd->root_fhsize;
477 l = ntohl(nd->root_saddr.sin_addr.s_addr);
478 snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
479 (l >> 24) & 0xff, (l >> 16) & 0xff,
480 (l >> 8) & 0xff, (l >> 0) & 0xff, nd->root_hostnam);
481 printf("NFS ROOT: %s\n", buf);
482 nd->root_args.hostname = buf;
483 if ((error = nfs_mountdiskless(buf,
484 &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) {
489 * This is not really an nfs issue, but it is much easier to
490 * set hostname here and then let the "/etc/rc.xxx" files
491 * mount the right /var based upon its preset value.
493 mtx_lock(&prison0.pr_mtx);
494 strlcpy(prison0.pr_hostname, nd->my_hostnam,
495 sizeof(prison0.pr_hostname));
496 mtx_unlock(&prison0.pr_mtx);
497 inittodr(ntohl(nd->root_time));
502 * Internal version of mount system call for diskless setup.
505 nfs_mountdiskless(char *path,
506 struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
507 struct vnode **vpp, struct mount *mp)
509 struct sockaddr *nam;
514 * Find the directory path in "path", which also has the server's
515 * name/ip address in it.
517 dirpath = strchr(path, ':');
519 dirlen = strlen(++dirpath);
522 nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
523 if ((error = mountnfs(args, mp, nam, path, NULL, 0, dirpath, dirlen,
524 NULL, 0, vpp, td->td_ucred, td, NFS_DEFAULT_NEGNAMETIMEO)) != 0) {
525 printf("nfs_mountroot: mount %s on /: %d\n", path, error);
532 nfs_sec_name(char *sec, int *flagsp)
534 if (!strcmp(sec, "krb5"))
535 *flagsp |= NFSMNT_KERB;
536 else if (!strcmp(sec, "krb5i"))
537 *flagsp |= (NFSMNT_KERB | NFSMNT_INTEGRITY);
538 else if (!strcmp(sec, "krb5p"))
539 *flagsp |= (NFSMNT_KERB | NFSMNT_PRIVACY);
543 nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
544 const char *hostname, struct ucred *cred, struct thread *td)
553 * Set read-only flag if requested; otherwise, clear it if this is
554 * an update. If this is not an update, then either the read-only
555 * flag is already clear, or this is a root mount and it was set
556 * intentionally at some previous point.
558 if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) {
560 mp->mnt_flag |= MNT_RDONLY;
562 } else if (mp->mnt_flag & MNT_UPDATE) {
564 mp->mnt_flag &= ~MNT_RDONLY;
569 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
570 * no sense in that context. Also, set up appropriate retransmit
571 * and soft timeout behavior.
573 if (argp->sotype == SOCK_STREAM) {
574 nmp->nm_flag &= ~NFSMNT_NOCONN;
575 nmp->nm_timeo = NFS_MAXTIMEO;
576 if ((argp->flags & NFSMNT_NFSV4) != 0)
577 nmp->nm_retry = INT_MAX;
579 nmp->nm_retry = NFS_RETRANS_TCP;
582 /* Also clear RDIRPLUS if NFSv2, it crashes some servers */
583 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
584 argp->flags &= ~NFSMNT_RDIRPLUS;
585 nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
588 /* Clear NFSMNT_RESVPORT for NFSv4, since it is not required. */
589 if ((argp->flags & NFSMNT_NFSV4) != 0) {
590 argp->flags &= ~NFSMNT_RESVPORT;
591 nmp->nm_flag &= ~NFSMNT_RESVPORT;
594 /* Re-bind if rsrvd port requested and wasn't on one */
595 adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
596 && (argp->flags & NFSMNT_RESVPORT);
597 /* Also re-bind if we're switching to/from a connected UDP socket */
598 adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
599 (argp->flags & NFSMNT_NOCONN));
601 /* Update flags atomically. Don't change the lock bits. */
602 nmp->nm_flag = argp->flags | nmp->nm_flag;
605 if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
606 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
607 if (nmp->nm_timeo < NFS_MINTIMEO)
608 nmp->nm_timeo = NFS_MINTIMEO;
609 else if (nmp->nm_timeo > NFS_MAXTIMEO)
610 nmp->nm_timeo = NFS_MAXTIMEO;
613 if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
614 nmp->nm_retry = argp->retrans;
615 if (nmp->nm_retry > NFS_MAXREXMIT)
616 nmp->nm_retry = NFS_MAXREXMIT;
619 if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
620 nmp->nm_wsize = argp->wsize;
621 /* Round down to multiple of blocksize */
622 nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
623 if (nmp->nm_wsize <= 0)
624 nmp->nm_wsize = NFS_FABLKSIZE;
627 if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
628 nmp->nm_rsize = argp->rsize;
629 /* Round down to multiple of blocksize */
630 nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
631 if (nmp->nm_rsize <= 0)
632 nmp->nm_rsize = NFS_FABLKSIZE;
635 if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
636 nmp->nm_readdirsize = argp->readdirsize;
639 if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
640 nmp->nm_acregmin = argp->acregmin;
642 nmp->nm_acregmin = NFS_MINATTRTIMO;
643 if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
644 nmp->nm_acregmax = argp->acregmax;
646 nmp->nm_acregmax = NFS_MAXATTRTIMO;
647 if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
648 nmp->nm_acdirmin = argp->acdirmin;
650 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
651 if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
652 nmp->nm_acdirmax = argp->acdirmax;
654 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
655 if (nmp->nm_acdirmin > nmp->nm_acdirmax)
656 nmp->nm_acdirmin = nmp->nm_acdirmax;
657 if (nmp->nm_acregmin > nmp->nm_acregmax)
658 nmp->nm_acregmin = nmp->nm_acregmax;
660 if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
661 if (argp->readahead <= NFS_MAXRAHEAD)
662 nmp->nm_readahead = argp->readahead;
664 nmp->nm_readahead = NFS_MAXRAHEAD;
666 if ((argp->flags & NFSMNT_WCOMMITSIZE) && argp->wcommitsize >= 0) {
667 if (argp->wcommitsize < nmp->nm_wsize)
668 nmp->nm_wcommitsize = nmp->nm_wsize;
670 nmp->nm_wcommitsize = argp->wcommitsize;
673 adjsock |= ((nmp->nm_sotype != argp->sotype) ||
674 (nmp->nm_soproto != argp->proto));
676 if (nmp->nm_client != NULL && adjsock) {
677 int haslock = 0, error = 0;
679 if (nmp->nm_sotype == SOCK_STREAM) {
680 error = newnfs_sndlock(&nmp->nm_sockreq.nr_lock);
685 newnfs_disconnect(&nmp->nm_sockreq);
687 newnfs_sndunlock(&nmp->nm_sockreq.nr_lock);
688 nmp->nm_sotype = argp->sotype;
689 nmp->nm_soproto = argp->proto;
690 if (nmp->nm_sotype == SOCK_DGRAM)
691 while (newnfs_connect(nmp, &nmp->nm_sockreq,
693 printf("newnfs_args: retrying connect\n");
694 (void) nfs_catnap(PSOCK, 0, "newnfscon");
698 nmp->nm_sotype = argp->sotype;
699 nmp->nm_soproto = argp->proto;
702 if (hostname != NULL) {
703 strlcpy(nmp->nm_hostname, hostname,
704 sizeof(nmp->nm_hostname));
705 p = strchr(nmp->nm_hostname, ':');
711 static const char *nfs_opts[] = { "from", "nfs_args",
712 "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
713 "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
714 "async", "noconn", "nolockd", "conn", "lockd", "intr", "rdirplus",
715 "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize",
716 "retrans", "acregmin", "acregmax", "acdirmin", "acdirmax", "resvport",
717 "readahead", "hostname", "timeout", "addr", "fh", "nfsv3", "sec",
718 "principal", "nfsv4", "gssname", "allgssname", "dirpath",
719 "negnametimeo", "nocto",
726 * It seems a bit dumb to copyinstr() the host and path here and then
727 * bcopy() them in mountnfs(), but I wanted to detect errors before
728 * doing the sockargs() call because sockargs() allocates an mbuf and
729 * an error after that means that I have to release the mbuf.
733 nfs_mount(struct mount *mp)
735 struct nfs_args args = {
736 .version = NFS_ARGSVERSION,
738 .addrlen = sizeof (struct sockaddr_in),
739 .sotype = SOCK_STREAM,
743 .flags = NFSMNT_RESVPORT,
746 .readdirsize = NFS_READDIRSIZE,
748 .retrans = NFS_RETRANS,
749 .readahead = NFS_DEFRAHEAD,
750 .wcommitsize = 0, /* was: NQ_DEFLEASE */
752 .acregmin = NFS_MINATTRTIMO,
753 .acregmax = NFS_MAXATTRTIMO,
754 .acdirmin = NFS_MINDIRATTRTIMO,
755 .acdirmax = NFS_MAXDIRATTRTIMO,
757 int error = 0, ret, len;
758 struct sockaddr *nam = NULL;
762 u_char nfh[NFSX_FHMAX], krbname[100], dirpath[100], srvkrbname[100];
763 char *opt, *name, *secname;
764 int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
765 int dirlen, has_nfs_args_opt, krbnamelen, srvkrbnamelen;
768 has_nfs_args_opt = 0;
769 if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
775 if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS) {
776 error = nfs_mountroot(mp);
783 * The old mount_nfs program passed the struct nfs_args
784 * from userspace to kernel. The new mount_nfs program
785 * passes string options via nmount() from userspace to kernel
786 * and we populate the struct nfs_args in the kernel.
788 if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
789 error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
794 if (args.version != NFS_ARGSVERSION) {
795 error = EPROGMISMATCH;
798 has_nfs_args_opt = 1;
801 /* Handle the new style options. */
802 if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
803 args.flags |= NFSMNT_NOCONN;
804 if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
805 args.flags |= NFSMNT_NOCONN;
806 if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
807 args.flags |= NFSMNT_NOLOCKD;
808 if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
809 args.flags &= ~NFSMNT_NOLOCKD;
810 if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
811 args.flags |= NFSMNT_INT;
812 if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
813 args.flags |= NFSMNT_RDIRPLUS;
814 if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
815 args.flags |= NFSMNT_RESVPORT;
816 if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
817 args.flags &= ~NFSMNT_RESVPORT;
818 if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
819 args.flags |= NFSMNT_SOFT;
820 if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
821 args.flags &= ~NFSMNT_SOFT;
822 if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
823 args.sotype = SOCK_DGRAM;
824 if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
825 args.sotype = SOCK_DGRAM;
826 if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
827 args.sotype = SOCK_STREAM;
828 if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
829 args.flags |= NFSMNT_NFSV3;
830 if (vfs_getopt(mp->mnt_optnew, "nfsv4", NULL, NULL) == 0) {
831 args.flags |= NFSMNT_NFSV4;
832 args.sotype = SOCK_STREAM;
834 if (vfs_getopt(mp->mnt_optnew, "allgssname", NULL, NULL) == 0)
835 args.flags |= NFSMNT_ALLGSSNAME;
836 if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0)
837 args.flags |= NFSMNT_NOCTO;
838 if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
840 vfs_mount_error(mp, "illegal readdirsize");
844 ret = sscanf(opt, "%d", &args.readdirsize);
845 if (ret != 1 || args.readdirsize <= 0) {
846 vfs_mount_error(mp, "illegal readdirsize: %s",
851 args.flags |= NFSMNT_READDIRSIZE;
853 if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
855 vfs_mount_error(mp, "illegal readahead");
859 ret = sscanf(opt, "%d", &args.readahead);
860 if (ret != 1 || args.readahead <= 0) {
861 vfs_mount_error(mp, "illegal readahead: %s",
866 args.flags |= NFSMNT_READAHEAD;
868 if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
870 vfs_mount_error(mp, "illegal wsize");
874 ret = sscanf(opt, "%d", &args.wsize);
875 if (ret != 1 || args.wsize <= 0) {
876 vfs_mount_error(mp, "illegal wsize: %s",
881 args.flags |= NFSMNT_WSIZE;
883 if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
885 vfs_mount_error(mp, "illegal rsize");
889 ret = sscanf(opt, "%d", &args.rsize);
890 if (ret != 1 || args.rsize <= 0) {
891 vfs_mount_error(mp, "illegal wsize: %s",
896 args.flags |= NFSMNT_RSIZE;
898 if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
900 vfs_mount_error(mp, "illegal retrans");
904 ret = sscanf(opt, "%d", &args.retrans);
905 if (ret != 1 || args.retrans <= 0) {
906 vfs_mount_error(mp, "illegal retrans: %s",
911 args.flags |= NFSMNT_RETRANS;
913 if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
914 ret = sscanf(opt, "%d", &args.acregmin);
915 if (ret != 1 || args.acregmin < 0) {
916 vfs_mount_error(mp, "illegal acregmin: %s",
921 args.flags |= NFSMNT_ACREGMIN;
923 if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
924 ret = sscanf(opt, "%d", &args.acregmax);
925 if (ret != 1 || args.acregmax < 0) {
926 vfs_mount_error(mp, "illegal acregmax: %s",
931 args.flags |= NFSMNT_ACREGMAX;
933 if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
934 ret = sscanf(opt, "%d", &args.acdirmin);
935 if (ret != 1 || args.acdirmin < 0) {
936 vfs_mount_error(mp, "illegal acdirmin: %s",
941 args.flags |= NFSMNT_ACDIRMIN;
943 if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
944 ret = sscanf(opt, "%d", &args.acdirmax);
945 if (ret != 1 || args.acdirmax < 0) {
946 vfs_mount_error(mp, "illegal acdirmax: %s",
951 args.flags |= NFSMNT_ACDIRMAX;
953 if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
954 ret = sscanf(opt, "%d", &args.timeo);
955 if (ret != 1 || args.timeo <= 0) {
956 vfs_mount_error(mp, "illegal timeout: %s",
961 args.flags |= NFSMNT_TIMEO;
963 if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
965 ret = sscanf(opt, "%d", &negnametimeo);
966 if (ret != 1 || negnametimeo < 0) {
967 vfs_mount_error(mp, "illegal negnametimeo: %s",
973 if (vfs_getopt(mp->mnt_optnew, "sec",
974 (void **) &secname, NULL) == 0)
975 nfs_sec_name(secname, &args.flags);
977 if (mp->mnt_flag & MNT_UPDATE) {
978 struct nfsmount *nmp = VFSTONFS(mp);
985 * When doing an update, we can't change version,
986 * security, switch lockd strategies or change cookie
989 args.flags = (args.flags &
995 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
1002 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
1003 nfs_decode_args(mp, nmp, &args, NULL, td->td_ucred, td);
1008 * Make the nfs_ip_paranoia sysctl serve as the default connection
1009 * or no-connection mode for those protocols that support
1010 * no-connection mode (the flag will be cleared later for protocols
1011 * that do not support no-connection mode). This will allow a client
1012 * to receive replies from a different IP then the request was
1013 * sent to. Note: default value for nfs_ip_paranoia is 1 (paranoid),
1016 if (nfs_ip_paranoia == 0)
1017 args.flags |= NFSMNT_NOCONN;
1019 if (has_nfs_args_opt != 0) {
1021 * In the 'nfs_args' case, the pointers in the args
1022 * structure are in userland - we copy them in here.
1024 if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
1025 vfs_mount_error(mp, "Bad file handle");
1029 error = copyin((caddr_t)args.fh, (caddr_t)nfh,
1033 error = copyinstr(args.hostname, hst, MNAMELEN - 1, &hstlen);
1036 bzero(&hst[hstlen], MNAMELEN - hstlen);
1037 args.hostname = hst;
1038 /* sockargs() call must be after above copyin() calls */
1039 error = getsockaddr(&nam, (caddr_t)args.addr,
1044 if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
1045 &args.fhsize) == 0) {
1046 if (args.fhsize < 0 || args.fhsize > NFSX_FHMAX) {
1047 vfs_mount_error(mp, "Bad file handle");
1051 bcopy(args.fh, nfh, args.fhsize);
1055 (void) vfs_getopt(mp->mnt_optnew, "hostname",
1056 (void **)&args.hostname, &len);
1057 if (args.hostname == NULL) {
1058 vfs_mount_error(mp, "Invalid hostname");
1062 bcopy(args.hostname, hst, MNAMELEN);
1063 hst[MNAMELEN - 1] = '\0';
1066 if (vfs_getopt(mp->mnt_optnew, "principal", (void **)&name, NULL) == 0)
1067 strlcpy(srvkrbname, name, sizeof (srvkrbname));
1069 snprintf(srvkrbname, sizeof (srvkrbname), "nfs@%s", hst);
1070 srvkrbnamelen = strlen(srvkrbname);
1072 if (vfs_getopt(mp->mnt_optnew, "gssname", (void **)&name, NULL) == 0)
1073 strlcpy(krbname, name, sizeof (krbname));
1076 krbnamelen = strlen(krbname);
1078 if (vfs_getopt(mp->mnt_optnew, "dirpath", (void **)&name, NULL) == 0)
1079 strlcpy(dirpath, name, sizeof (dirpath));
1082 dirlen = strlen(dirpath);
1084 if (has_nfs_args_opt == 0 && vfs_getopt(mp->mnt_optnew, "addr",
1085 (void **)&args.addr, &args.addrlen) == 0) {
1086 if (args.addrlen > SOCK_MAXADDRLEN) {
1087 error = ENAMETOOLONG;
1090 nam = malloc(args.addrlen, M_SONAME, M_WAITOK);
1091 bcopy(args.addr, nam, args.addrlen);
1092 nam->sa_len = args.addrlen;
1096 error = mountnfs(&args, mp, nam, hst, krbname, krbnamelen, dirpath,
1097 dirlen, srvkrbname, srvkrbnamelen, &vp, td->td_ucred, td,
1102 mp->mnt_kern_flag |= (MNTK_MPSAFE|MNTK_LOOKUP_SHARED);
1113 * It seems a bit dumb to copyinstr() the host and path here and then
1114 * bcopy() them in mountnfs(), but I wanted to detect errors before
1115 * doing the sockargs() call because sockargs() allocates an mbuf and
1116 * an error after that means that I have to release the mbuf.
1120 nfs_cmount(struct mntarg *ma, void *data, int flags)
1123 struct nfs_args args;
1125 error = copyin(data, &args, sizeof (struct nfs_args));
1129 ma = mount_arg(ma, "nfs_args", &args, sizeof args);
1131 error = kernel_mount(ma, flags);
1136 * Common code for mount and mountroot
1139 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
1140 char *hst, u_char *krbname, int krbnamelen, u_char *dirpath, int dirlen,
1141 u_char *srvkrbname, int srvkrbnamelen, struct vnode **vpp,
1142 struct ucred *cred, struct thread *td, int negnametimeo)
1144 struct nfsmount *nmp;
1146 int error, trycnt, ret;
1147 struct nfsvattr nfsva;
1148 static u_int64_t clval = 0;
1150 if (mp->mnt_flag & MNT_UPDATE) {
1152 printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
1153 FREE(nam, M_SONAME);
1156 MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount) +
1157 krbnamelen + dirlen + srvkrbnamelen + 2,
1158 M_NEWNFSMNT, M_WAITOK | M_ZERO);
1159 TAILQ_INIT(&nmp->nm_bufq);
1161 clval = (u_int64_t)nfsboottime.tv_sec;
1162 nmp->nm_clval = clval++;
1163 nmp->nm_krbnamelen = krbnamelen;
1164 nmp->nm_dirpathlen = dirlen;
1165 nmp->nm_srvkrbnamelen = srvkrbnamelen;
1166 if (td->td_ucred->cr_uid != (uid_t)0) {
1168 * nm_uid is used to get KerberosV credentials for
1169 * the nfsv4 state handling operations if there is
1170 * no host based principal set. Use the uid of
1171 * this user if not root, since they are doing the
1172 * mount. I don't think setting this for root will
1173 * work, since root normally does not have user
1174 * credentials in a credentials cache.
1176 nmp->nm_uid = td->td_ucred->cr_uid;
1179 * Just set to -1, so it won't be used.
1181 nmp->nm_uid = (uid_t)-1;
1184 /* Copy and null terminate all the names */
1185 if (nmp->nm_krbnamelen > 0) {
1186 bcopy(krbname, nmp->nm_krbname, nmp->nm_krbnamelen);
1187 nmp->nm_name[nmp->nm_krbnamelen] = '\0';
1189 if (nmp->nm_dirpathlen > 0) {
1190 bcopy(dirpath, NFSMNT_DIRPATH(nmp),
1191 nmp->nm_dirpathlen);
1192 nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1195 if (nmp->nm_srvkrbnamelen > 0) {
1196 bcopy(srvkrbname, NFSMNT_SRVKRBNAME(nmp),
1197 nmp->nm_srvkrbnamelen);
1198 nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1199 + nmp->nm_srvkrbnamelen + 2] = '\0';
1201 nmp->nm_sockreq.nr_cred = crhold(cred);
1202 mtx_init(&nmp->nm_sockreq.nr_mtx, "nfssock", NULL, MTX_DEF);
1204 nmp->nm_getinfo = nfs_getnlminfo;
1205 nmp->nm_vinvalbuf = ncl_vinvalbuf;
1208 nmp->nm_mountp = mp;
1209 mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF | MTX_DUPOK);
1210 nmp->nm_negnametimeo = negnametimeo;
1212 nfs_decode_args(mp, nmp, argp, hst, cred, td);
1215 * V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too
1216 * high, depending on whether we end up with negative offsets in
1217 * the client or server somewhere. 2GB-1 may be safer.
1219 * For V3, ncl_fsinfo will adjust this as necessary. Assume maximum
1220 * that we can handle until we find out otherwise.
1221 * XXX Our "safe" limit on the client is what we can store in our
1222 * buffer cache using signed(!) block numbers.
1224 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0)
1225 nmp->nm_maxfilesize = 0xffffffffLL;
1227 nmp->nm_maxfilesize = OFF_MAX;
1229 nmp->nm_timeo = NFS_TIMEO;
1230 nmp->nm_retry = NFS_RETRANS;
1231 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
1232 nmp->nm_wsize = NFS_WSIZE;
1233 nmp->nm_rsize = NFS_RSIZE;
1234 nmp->nm_readdirsize = NFS_READDIRSIZE;
1236 nmp->nm_wcommitsize = hibufspace / (desiredvnodes / 1000);
1237 nmp->nm_numgrps = NFS_MAXGRPS;
1238 nmp->nm_readahead = NFS_DEFRAHEAD;
1239 nmp->nm_tprintf_delay = nfs_tprintf_delay;
1240 if (nmp->nm_tprintf_delay < 0)
1241 nmp->nm_tprintf_delay = 0;
1242 nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
1243 if (nmp->nm_tprintf_initial_delay < 0)
1244 nmp->nm_tprintf_initial_delay = 0;
1245 nmp->nm_fhsize = argp->fhsize;
1246 if (nmp->nm_fhsize > 0)
1247 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
1248 bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
1250 /* Set up the sockets and per-host congestion */
1251 nmp->nm_sotype = argp->sotype;
1252 nmp->nm_soproto = argp->proto;
1253 nmp->nm_sockreq.nr_prog = NFS_PROG;
1254 if ((argp->flags & NFSMNT_NFSV4))
1255 nmp->nm_sockreq.nr_vers = NFS_VER4;
1256 else if ((argp->flags & NFSMNT_NFSV3))
1257 nmp->nm_sockreq.nr_vers = NFS_VER3;
1259 nmp->nm_sockreq.nr_vers = NFS_VER2;
1262 if ((error = newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0)))
1266 * A reference count is needed on the nfsnode representing the
1267 * remote root. If this object is not persistent, then backward
1268 * traversals of the mount point (i.e. "..") will not work if
1269 * the nfsnode gets flushed out of the cache. Ufs does not have
1270 * this problem, because one can identify root inodes by their
1271 * number == ROOTINO (2).
1273 if (nmp->nm_fhsize == 0 && (nmp->nm_flag & NFSMNT_NFSV4) &&
1274 nmp->nm_dirpathlen > 0) {
1276 * If the fhsize on the mount point == 0 for V4, the mount
1277 * path needs to be looked up.
1281 error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp),
1284 (void) nfs_catnap(PZERO, error, "nfsgetdirp");
1285 } while (error && --trycnt > 0);
1287 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
1291 if (nmp->nm_fhsize > 0) {
1293 * Set f_iosize to NFS_DIRBLKSIZ so that bo_bsize gets set
1294 * non-zero for the root vnode. f_iosize will be set correctly
1295 * by nfs_statfs() before any I/O occurs.
1297 mp->mnt_stat.f_iosize = NFS_DIRBLKSIZ;
1298 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np,
1305 * Get file attributes and transfer parameters for the
1306 * mountpoint. This has the side effect of filling in
1307 * (*vpp)->v_type with the correct value.
1309 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
1310 cred, td, &nfsva, NULL);
1313 * Just set default values to get things going.
1315 NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
1316 nfsva.na_vattr.va_type = VDIR;
1317 nfsva.na_vattr.va_mode = 0777;
1318 nfsva.na_vattr.va_nlink = 100;
1319 nfsva.na_vattr.va_uid = (uid_t)0;
1320 nfsva.na_vattr.va_gid = (gid_t)0;
1321 nfsva.na_vattr.va_fileid = 2;
1322 nfsva.na_vattr.va_gen = 1;
1323 nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
1324 nfsva.na_vattr.va_size = 512 * 1024;
1326 (void) nfscl_loadattrcache(vpp, &nfsva, NULL, NULL, 0, 1);
1327 if (argp->flags & NFSMNT_NFSV3)
1328 ncl_fsinfo(nmp, *vpp, cred, td);
1331 * Lose the lock but keep the ref.
1333 VOP_UNLOCK(*vpp, 0);
1339 newnfs_disconnect(&nmp->nm_sockreq);
1340 crfree(nmp->nm_sockreq.nr_cred);
1341 mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1342 mtx_destroy(&nmp->nm_mtx);
1343 FREE(nmp, M_NEWNFSMNT);
1344 FREE(nam, M_SONAME);
1349 * unmount system call
1352 nfs_unmount(struct mount *mp, int mntflags)
1355 struct nfsmount *nmp;
1356 int error, flags = 0, trycnt = 0;
1360 if (mntflags & MNT_FORCE)
1361 flags |= FORCECLOSE;
1364 * Goes something like this..
1365 * - Call vflush() to clear out vnodes for this filesystem
1366 * - Close the socket
1367 * - Free up the data structures
1369 /* In the forced case, cancel any outstanding requests. */
1370 if (mntflags & MNT_FORCE) {
1371 error = newnfs_nmcancelreqs(nmp);
1374 /* For a forced close, get rid of the renew thread now */
1375 nfscl_umount(nmp, td);
1377 /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
1379 error = vflush(mp, 1, flags, td);
1380 if ((mntflags & MNT_FORCE) && error != 0 && ++trycnt < 30)
1381 (void) nfs_catnap(PSOCK, error, "newndm");
1382 } while ((mntflags & MNT_FORCE) && error != 0 && trycnt < 30);
1387 * We are now committed to the unmount.
1389 if ((mntflags & MNT_FORCE) == 0)
1390 nfscl_umount(nmp, td);
1391 newnfs_disconnect(&nmp->nm_sockreq);
1392 crfree(nmp->nm_sockreq.nr_cred);
1393 FREE(nmp->nm_nam, M_SONAME);
1395 mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1396 mtx_destroy(&nmp->nm_mtx);
1397 FREE(nmp, M_NEWNFSMNT);
1403 * Return root of a filesystem
1406 nfs_root(struct mount *mp, int flags, struct vnode **vpp)
1409 struct nfsmount *nmp;
1414 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, flags);
1419 * Get transfer parameters and attributes for root vnode once.
1421 mtx_lock(&nmp->nm_mtx);
1422 if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
1423 mtx_unlock(&nmp->nm_mtx);
1424 ncl_fsinfo(nmp, vp, curthread->td_ucred, curthread);
1426 mtx_unlock(&nmp->nm_mtx);
1427 if (vp->v_type == VNON)
1429 vp->v_vflag |= VV_ROOT;
1435 * Flush out the buffer cache
1439 nfs_sync(struct mount *mp, int waitfor)
1441 struct vnode *vp, *mvp;
1443 int error, allerror = 0;
1448 * Force stale buffer cache information to be flushed.
1452 MNT_VNODE_FOREACH(vp, mp, mvp) {
1455 /* XXX Racy bv_cnt check. */
1456 if (VOP_ISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
1457 waitfor == MNT_LAZY) {
1462 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
1464 MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp);
1467 error = VOP_FSYNC(vp, waitfor, td);
1480 nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
1482 struct nfsmount *nmp = VFSTONFS(mp);
1486 bzero(&vq, sizeof(vq));
1489 case VFS_CTL_NOLOCKS:
1490 val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
1491 if (req->oldptr != NULL) {
1492 error = SYSCTL_OUT(req, &val, sizeof(val));
1496 if (req->newptr != NULL) {
1497 error = SYSCTL_IN(req, &val, sizeof(val));
1501 nmp->nm_flag |= NFSMNT_NOLOCKS;
1503 nmp->nm_flag &= ~NFSMNT_NOLOCKS;
1508 mtx_lock(&nmp->nm_mtx);
1509 if (nmp->nm_state & NFSSTA_TIMEO)
1510 vq.vq_flags |= VQ_NOTRESP;
1511 mtx_unlock(&nmp->nm_mtx);
1513 if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
1514 (nmp->nm_state & NFSSTA_LOCKTIMEO))
1515 vq.vq_flags |= VQ_NOTRESPLOCK;
1517 error = SYSCTL_OUT(req, &vq, sizeof(vq));
1520 if (req->oldptr != NULL) {
1521 error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
1522 sizeof(nmp->nm_tprintf_initial_delay));
1526 if (req->newptr != NULL) {
1527 error = vfs_suser(mp, req->td);
1530 error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
1531 sizeof(nmp->nm_tprintf_initial_delay));
1534 if (nmp->nm_tprintf_initial_delay < 0)
1535 nmp->nm_tprintf_initial_delay = 0;
1545 * Extract the information needed by the nlm from the nfs vnode.
1548 nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp,
1549 struct sockaddr_storage *sp, int *is_v3p, off_t *sizep,
1550 struct timeval *timeop)
1552 struct nfsmount *nmp;
1553 struct nfsnode *np = VTONFS(vp);
1555 nmp = VFSTONFS(vp->v_mount);
1557 *fhlenp = (size_t)np->n_fhp->nfh_len;
1559 bcopy(np->n_fhp->nfh_fh, fhp, np->n_fhp->nfh_len);
1561 bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp)));
1563 *is_v3p = NFS_ISV3(vp);
1565 *sizep = np->n_size;
1566 if (timeop != NULL) {
1567 timeop->tv_sec = nmp->nm_timeo / NFS_HZ;
1568 timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ);