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 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 int nfs_mountroot(struct mount *);
99 static void nfs_sec_name(char *, int *);
100 static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp,
101 struct nfs_args *argp, const char *, struct ucred *,
103 static int mountnfs(struct nfs_args *, struct mount *,
104 struct sockaddr *, char *, u_char *, int, u_char *, int,
105 u_char *, int, struct vnode **, struct ucred *,
106 struct thread *, int);
107 static void nfs_getnlminfo(struct vnode *, uint8_t *, size_t *,
108 struct sockaddr_storage *, int *, off_t *,
110 static vfs_mount_t nfs_mount;
111 static vfs_cmount_t nfs_cmount;
112 static vfs_unmount_t nfs_unmount;
113 static vfs_root_t nfs_root;
114 static vfs_statfs_t nfs_statfs;
115 static vfs_sync_t nfs_sync;
116 static vfs_sysctl_t nfs_sysctl;
119 * nfs vfs operations.
121 static struct vfsops nfs_vfsops = {
122 .vfs_init = ncl_init,
123 .vfs_mount = nfs_mount,
124 .vfs_cmount = nfs_cmount,
125 .vfs_root = nfs_root,
126 .vfs_statfs = nfs_statfs,
127 .vfs_sync = nfs_sync,
128 .vfs_uninit = ncl_uninit,
129 .vfs_unmount = nfs_unmount,
130 .vfs_sysctl = nfs_sysctl,
132 VFS_SET(nfs_vfsops, newnfs, VFCF_NETWORK);
134 /* So that loader and kldload(2) can find us, wherever we are.. */
135 MODULE_VERSION(newnfs, 1);
138 * This structure is now defined in sys/nfs/nfs_diskless.c so that it
139 * can be shared by both NFS clients. It is declared here so that it
140 * will be defined for kernels built without NFS_ROOT, although it
141 * isn't used in that case.
143 #if !defined(NFS_ROOT) && !defined(NFSCLIENT)
144 struct nfs_diskless nfs_diskless = { { { 0 } } };
145 struct nfsv3_diskless nfsv3_diskless = { { { 0 } } };
146 int nfs_diskless_valid = 0;
149 SYSCTL_INT(_vfs_newnfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
150 &nfs_diskless_valid, 0,
151 "Has the diskless struct been filled correctly");
153 SYSCTL_STRING(_vfs_newnfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
154 nfsv3_diskless.root_hostnam, 0, "Path to nfs root");
156 SYSCTL_OPAQUE(_vfs_newnfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
157 &nfsv3_diskless.root_saddr, sizeof(nfsv3_diskless.root_saddr),
158 "%Ssockaddr_in", "Diskless root nfs address");
161 void newnfsargs_ntoh(struct nfs_args *);
162 static int nfs_mountdiskless(char *,
163 struct sockaddr_in *, struct nfs_args *,
164 struct thread *, struct vnode **, struct mount *);
165 static void nfs_convert_diskless(void);
166 static void nfs_convert_oargs(struct nfs_args *args,
167 struct onfs_args *oargs);
170 newnfs_iosize(struct nfsmount *nmp)
174 /* First, set the upper limit for iosize */
175 if (nmp->nm_flag & NFSMNT_NFSV4) {
176 maxio = NFS_MAXBSIZE;
177 } else if (nmp->nm_flag & NFSMNT_NFSV3) {
178 if (nmp->nm_sotype == SOCK_DGRAM)
179 maxio = NFS_MAXDGRAMDATA;
181 maxio = NFS_MAXBSIZE;
183 maxio = NFS_V2MAXDATA;
185 if (nmp->nm_rsize > maxio || nmp->nm_rsize == 0)
186 nmp->nm_rsize = maxio;
187 if (nmp->nm_rsize > MAXBSIZE)
188 nmp->nm_rsize = MAXBSIZE;
189 if (nmp->nm_readdirsize > maxio || nmp->nm_readdirsize == 0)
190 nmp->nm_readdirsize = maxio;
191 if (nmp->nm_readdirsize > nmp->nm_rsize)
192 nmp->nm_readdirsize = nmp->nm_rsize;
193 if (nmp->nm_wsize > maxio || nmp->nm_wsize == 0)
194 nmp->nm_wsize = maxio;
195 if (nmp->nm_wsize > MAXBSIZE)
196 nmp->nm_wsize = MAXBSIZE;
199 * Calculate the size used for io buffers. Use the larger
200 * of the two sizes to minimise nfs requests but make sure
201 * that it is at least one VM page to avoid wasting buffer
204 iosize = imax(nmp->nm_rsize, nmp->nm_wsize);
205 iosize = imax(iosize, PAGE_SIZE);
206 nmp->nm_mountp->mnt_stat.f_iosize = iosize;
211 nfs_convert_oargs(struct nfs_args *args, struct onfs_args *oargs)
214 args->version = NFS_ARGSVERSION;
215 args->addr = oargs->addr;
216 args->addrlen = oargs->addrlen;
217 args->sotype = oargs->sotype;
218 args->proto = oargs->proto;
219 args->fh = oargs->fh;
220 args->fhsize = oargs->fhsize;
221 args->flags = oargs->flags;
222 args->wsize = oargs->wsize;
223 args->rsize = oargs->rsize;
224 args->readdirsize = oargs->readdirsize;
225 args->timeo = oargs->timeo;
226 args->retrans = oargs->retrans;
227 args->readahead = oargs->readahead;
228 args->hostname = oargs->hostname;
232 nfs_convert_diskless(void)
235 bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
236 sizeof(struct ifaliasreq));
237 bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
238 sizeof(struct sockaddr_in));
239 nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
240 if (nfsv3_diskless.root_args.flags & NFSMNT_NFSV3) {
241 nfsv3_diskless.root_fhsize = NFSX_MYFH;
242 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_MYFH);
244 nfsv3_diskless.root_fhsize = NFSX_V2FH;
245 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
247 bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
248 sizeof(struct sockaddr_in));
249 bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN);
250 nfsv3_diskless.root_time = nfs_diskless.root_time;
251 bcopy(nfs_diskless.my_hostnam, nfsv3_diskless.my_hostnam,
253 nfs_diskless_valid = 3;
260 nfs_statfs(struct mount *mp, struct statfs *sbp)
264 struct nfsmount *nmp = VFSTONFS(mp);
265 struct nfsvattr nfsva;
268 int error = 0, attrflag, gotfsinfo = 0, ret;
273 error = vfs_busy(mp, MBF_NOWAIT);
276 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
282 mtx_lock(&nmp->nm_mtx);
283 if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
284 mtx_unlock(&nmp->nm_mtx);
285 error = nfsrpc_fsinfo(vp, &fs, td->td_ucred, td, &nfsva,
290 mtx_unlock(&nmp->nm_mtx);
292 error = nfsrpc_statfs(vp, &sb, &fs, td->td_ucred, td, &nfsva,
295 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
296 td->td_ucred, td, &nfsva, NULL);
299 * Just set default values to get things going.
301 NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
302 nfsva.na_vattr.va_type = VDIR;
303 nfsva.na_vattr.va_mode = 0777;
304 nfsva.na_vattr.va_nlink = 100;
305 nfsva.na_vattr.va_uid = (uid_t)0;
306 nfsva.na_vattr.va_gid = (gid_t)0;
307 nfsva.na_vattr.va_fileid = 2;
308 nfsva.na_vattr.va_gen = 1;
309 nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
310 nfsva.na_vattr.va_size = 512 * 1024;
313 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
315 mtx_lock(&nmp->nm_mtx);
316 if (gotfsinfo || (nmp->nm_flag & NFSMNT_NFSV4))
317 nfscl_loadfsinfo(nmp, &fs);
318 nfscl_loadsbinfo(nmp, &sb, sbp);
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 * nfs_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 nfs_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 nfs_mountroot(struct mount *mp)
376 struct thread *td = curthread;
377 struct nfsv3_diskless *nd = &nfsv3_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 (nfs_diskless_valid == 0)
394 if (nfs_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;
508 * Find the directory path in "path", which also has the server's
509 * name/ip address in it.
511 dirpath = strchr(path, ':');
513 dirlen = strlen(++dirpath);
516 nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
517 if ((error = mountnfs(args, mp, nam, path, NULL, 0, dirpath, dirlen,
518 NULL, 0, vpp, td->td_ucred, td, NFS_DEFAULT_NEGNAMETIMEO)) != 0) {
519 printf("nfs_mountroot: mount %s on /: %d\n", path, error);
526 nfs_sec_name(char *sec, int *flagsp)
528 if (!strcmp(sec, "krb5"))
529 *flagsp |= NFSMNT_KERB;
530 else if (!strcmp(sec, "krb5i"))
531 *flagsp |= (NFSMNT_KERB | NFSMNT_INTEGRITY);
532 else if (!strcmp(sec, "krb5p"))
533 *flagsp |= (NFSMNT_KERB | NFSMNT_PRIVACY);
537 nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
538 const char *hostname, struct ucred *cred, struct thread *td)
547 * Set read-only flag if requested; otherwise, clear it if this is
548 * an update. If this is not an update, then either the read-only
549 * flag is already clear, or this is a root mount and it was set
550 * intentionally at some previous point.
552 if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) {
554 mp->mnt_flag |= MNT_RDONLY;
556 } else if (mp->mnt_flag & MNT_UPDATE) {
558 mp->mnt_flag &= ~MNT_RDONLY;
563 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
564 * no sense in that context. Also, set up appropriate retransmit
565 * and soft timeout behavior.
567 if (argp->sotype == SOCK_STREAM) {
568 nmp->nm_flag &= ~NFSMNT_NOCONN;
569 nmp->nm_timeo = NFS_MAXTIMEO;
570 if ((argp->flags & NFSMNT_NFSV4) != 0)
571 nmp->nm_retry = INT_MAX;
573 nmp->nm_retry = NFS_RETRANS_TCP;
576 /* Also clear RDIRPLUS if NFSv2, it crashes some servers */
577 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
578 argp->flags &= ~NFSMNT_RDIRPLUS;
579 nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
582 /* Clear NFSMNT_RESVPORT for NFSv4, since it is not required. */
583 if ((argp->flags & NFSMNT_NFSV4) != 0) {
584 argp->flags &= ~NFSMNT_RESVPORT;
585 nmp->nm_flag &= ~NFSMNT_RESVPORT;
588 /* Re-bind if rsrvd port requested and wasn't on one */
589 adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
590 && (argp->flags & NFSMNT_RESVPORT);
591 /* Also re-bind if we're switching to/from a connected UDP socket */
592 adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
593 (argp->flags & NFSMNT_NOCONN));
595 /* Update flags atomically. Don't change the lock bits. */
596 nmp->nm_flag = argp->flags | nmp->nm_flag;
599 if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
600 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
601 if (nmp->nm_timeo < NFS_MINTIMEO)
602 nmp->nm_timeo = NFS_MINTIMEO;
603 else if (nmp->nm_timeo > NFS_MAXTIMEO)
604 nmp->nm_timeo = NFS_MAXTIMEO;
607 if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
608 nmp->nm_retry = argp->retrans;
609 if (nmp->nm_retry > NFS_MAXREXMIT)
610 nmp->nm_retry = NFS_MAXREXMIT;
613 if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
614 nmp->nm_wsize = argp->wsize;
615 /* Round down to multiple of blocksize */
616 nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
617 if (nmp->nm_wsize <= 0)
618 nmp->nm_wsize = NFS_FABLKSIZE;
621 if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
622 nmp->nm_rsize = argp->rsize;
623 /* Round down to multiple of blocksize */
624 nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
625 if (nmp->nm_rsize <= 0)
626 nmp->nm_rsize = NFS_FABLKSIZE;
629 if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
630 nmp->nm_readdirsize = argp->readdirsize;
633 if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
634 nmp->nm_acregmin = argp->acregmin;
636 nmp->nm_acregmin = NFS_MINATTRTIMO;
637 if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
638 nmp->nm_acregmax = argp->acregmax;
640 nmp->nm_acregmax = NFS_MAXATTRTIMO;
641 if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
642 nmp->nm_acdirmin = argp->acdirmin;
644 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
645 if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
646 nmp->nm_acdirmax = argp->acdirmax;
648 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
649 if (nmp->nm_acdirmin > nmp->nm_acdirmax)
650 nmp->nm_acdirmin = nmp->nm_acdirmax;
651 if (nmp->nm_acregmin > nmp->nm_acregmax)
652 nmp->nm_acregmin = nmp->nm_acregmax;
654 if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
655 if (argp->readahead <= NFS_MAXRAHEAD)
656 nmp->nm_readahead = argp->readahead;
658 nmp->nm_readahead = NFS_MAXRAHEAD;
660 if ((argp->flags & NFSMNT_WCOMMITSIZE) && argp->wcommitsize >= 0) {
661 if (argp->wcommitsize < nmp->nm_wsize)
662 nmp->nm_wcommitsize = nmp->nm_wsize;
664 nmp->nm_wcommitsize = argp->wcommitsize;
667 adjsock |= ((nmp->nm_sotype != argp->sotype) ||
668 (nmp->nm_soproto != argp->proto));
670 if (nmp->nm_client != NULL && adjsock) {
671 int haslock = 0, error = 0;
673 if (nmp->nm_sotype == SOCK_STREAM) {
674 error = newnfs_sndlock(&nmp->nm_sockreq.nr_lock);
679 newnfs_disconnect(&nmp->nm_sockreq);
681 newnfs_sndunlock(&nmp->nm_sockreq.nr_lock);
682 nmp->nm_sotype = argp->sotype;
683 nmp->nm_soproto = argp->proto;
684 if (nmp->nm_sotype == SOCK_DGRAM)
685 while (newnfs_connect(nmp, &nmp->nm_sockreq,
687 printf("newnfs_args: retrying connect\n");
688 (void) nfs_catnap(PSOCK, 0, "newnfscon");
692 nmp->nm_sotype = argp->sotype;
693 nmp->nm_soproto = argp->proto;
696 if (hostname != NULL) {
697 strlcpy(nmp->nm_hostname, hostname,
698 sizeof(nmp->nm_hostname));
699 p = strchr(nmp->nm_hostname, ':');
705 static const char *nfs_opts[] = { "from", "nfs_args",
706 "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
707 "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
708 "async", "noconn", "nolockd", "conn", "lockd", "intr", "rdirplus",
709 "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize",
710 "retrans", "acregmin", "acregmax", "acdirmin", "acdirmax", "resvport",
711 "readahead", "hostname", "timeout", "addr", "fh", "nfsv3", "sec",
712 "principal", "nfsv4", "gssname", "allgssname", "dirpath",
713 "negnametimeo", "nocto",
720 * It seems a bit dumb to copyinstr() the host and path here and then
721 * bcopy() them in mountnfs(), but I wanted to detect errors before
722 * doing the sockargs() call because sockargs() allocates an mbuf and
723 * an error after that means that I have to release the mbuf.
727 nfs_mount(struct mount *mp)
729 struct nfs_args args = {
730 .version = NFS_ARGSVERSION,
732 .addrlen = sizeof (struct sockaddr_in),
733 .sotype = SOCK_STREAM,
737 .flags = NFSMNT_RESVPORT,
740 .readdirsize = NFS_READDIRSIZE,
742 .retrans = NFS_RETRANS,
743 .readahead = NFS_DEFRAHEAD,
744 .wcommitsize = 0, /* was: NQ_DEFLEASE */
746 .acregmin = NFS_MINATTRTIMO,
747 .acregmax = NFS_MAXATTRTIMO,
748 .acdirmin = NFS_MINDIRATTRTIMO,
749 .acdirmax = NFS_MAXDIRATTRTIMO,
751 int error = 0, ret, len;
752 struct sockaddr *nam = NULL;
756 u_char nfh[NFSX_FHMAX], krbname[100], dirpath[100], srvkrbname[100];
757 char *opt, *name, *secname;
758 int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
759 int dirlen, has_nfs_args_opt, krbnamelen, srvkrbnamelen;
762 has_nfs_args_opt = 0;
763 if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
769 if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS) {
770 error = nfs_mountroot(mp);
777 * The old mount_nfs program passed the struct nfs_args
778 * from userspace to kernel. The new mount_nfs program
779 * passes string options via nmount() from userspace to kernel
780 * and we populate the struct nfs_args in the kernel.
782 if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
783 error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
788 if (args.version != NFS_ARGSVERSION) {
789 error = EPROGMISMATCH;
792 has_nfs_args_opt = 1;
795 /* Handle the new style options. */
796 if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
797 args.flags |= NFSMNT_NOCONN;
798 if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
799 args.flags |= NFSMNT_NOCONN;
800 if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
801 args.flags |= NFSMNT_NOLOCKD;
802 if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
803 args.flags &= ~NFSMNT_NOLOCKD;
804 if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
805 args.flags |= NFSMNT_INT;
806 if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
807 args.flags |= NFSMNT_RDIRPLUS;
808 if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
809 args.flags |= NFSMNT_RESVPORT;
810 if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
811 args.flags &= ~NFSMNT_RESVPORT;
812 if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
813 args.flags |= NFSMNT_SOFT;
814 if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
815 args.flags &= ~NFSMNT_SOFT;
816 if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
817 args.sotype = SOCK_DGRAM;
818 if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
819 args.sotype = SOCK_DGRAM;
820 if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
821 args.sotype = SOCK_STREAM;
822 if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
823 args.flags |= NFSMNT_NFSV3;
824 if (vfs_getopt(mp->mnt_optnew, "nfsv4", NULL, NULL) == 0) {
825 args.flags |= NFSMNT_NFSV4;
826 args.sotype = SOCK_STREAM;
828 if (vfs_getopt(mp->mnt_optnew, "allgssname", NULL, NULL) == 0)
829 args.flags |= NFSMNT_ALLGSSNAME;
830 if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0)
831 args.flags |= NFSMNT_NOCTO;
832 if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
834 vfs_mount_error(mp, "illegal readdirsize");
838 ret = sscanf(opt, "%d", &args.readdirsize);
839 if (ret != 1 || args.readdirsize <= 0) {
840 vfs_mount_error(mp, "illegal readdirsize: %s",
845 args.flags |= NFSMNT_READDIRSIZE;
847 if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
849 vfs_mount_error(mp, "illegal readahead");
853 ret = sscanf(opt, "%d", &args.readahead);
854 if (ret != 1 || args.readahead <= 0) {
855 vfs_mount_error(mp, "illegal readahead: %s",
860 args.flags |= NFSMNT_READAHEAD;
862 if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
864 vfs_mount_error(mp, "illegal wsize");
868 ret = sscanf(opt, "%d", &args.wsize);
869 if (ret != 1 || args.wsize <= 0) {
870 vfs_mount_error(mp, "illegal wsize: %s",
875 args.flags |= NFSMNT_WSIZE;
877 if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
879 vfs_mount_error(mp, "illegal rsize");
883 ret = sscanf(opt, "%d", &args.rsize);
884 if (ret != 1 || args.rsize <= 0) {
885 vfs_mount_error(mp, "illegal wsize: %s",
890 args.flags |= NFSMNT_RSIZE;
892 if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
894 vfs_mount_error(mp, "illegal retrans");
898 ret = sscanf(opt, "%d", &args.retrans);
899 if (ret != 1 || args.retrans <= 0) {
900 vfs_mount_error(mp, "illegal retrans: %s",
905 args.flags |= NFSMNT_RETRANS;
907 if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
908 ret = sscanf(opt, "%d", &args.acregmin);
909 if (ret != 1 || args.acregmin < 0) {
910 vfs_mount_error(mp, "illegal acregmin: %s",
915 args.flags |= NFSMNT_ACREGMIN;
917 if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
918 ret = sscanf(opt, "%d", &args.acregmax);
919 if (ret != 1 || args.acregmax < 0) {
920 vfs_mount_error(mp, "illegal acregmax: %s",
925 args.flags |= NFSMNT_ACREGMAX;
927 if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
928 ret = sscanf(opt, "%d", &args.acdirmin);
929 if (ret != 1 || args.acdirmin < 0) {
930 vfs_mount_error(mp, "illegal acdirmin: %s",
935 args.flags |= NFSMNT_ACDIRMIN;
937 if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
938 ret = sscanf(opt, "%d", &args.acdirmax);
939 if (ret != 1 || args.acdirmax < 0) {
940 vfs_mount_error(mp, "illegal acdirmax: %s",
945 args.flags |= NFSMNT_ACDIRMAX;
947 if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
948 ret = sscanf(opt, "%d", &args.timeo);
949 if (ret != 1 || args.timeo <= 0) {
950 vfs_mount_error(mp, "illegal timeout: %s",
955 args.flags |= NFSMNT_TIMEO;
957 if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
959 ret = sscanf(opt, "%d", &negnametimeo);
960 if (ret != 1 || negnametimeo < 0) {
961 vfs_mount_error(mp, "illegal negnametimeo: %s",
967 if (vfs_getopt(mp->mnt_optnew, "sec",
968 (void **) &secname, NULL) == 0)
969 nfs_sec_name(secname, &args.flags);
971 if (mp->mnt_flag & MNT_UPDATE) {
972 struct nfsmount *nmp = VFSTONFS(mp);
979 * When doing an update, we can't change version,
980 * security, switch lockd strategies or change cookie
983 args.flags = (args.flags &
989 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
996 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
997 nfs_decode_args(mp, nmp, &args, NULL, td->td_ucred, td);
1002 * Make the nfs_ip_paranoia sysctl serve as the default connection
1003 * or no-connection mode for those protocols that support
1004 * no-connection mode (the flag will be cleared later for protocols
1005 * that do not support no-connection mode). This will allow a client
1006 * to receive replies from a different IP then the request was
1007 * sent to. Note: default value for nfs_ip_paranoia is 1 (paranoid),
1010 if (nfs_ip_paranoia == 0)
1011 args.flags |= NFSMNT_NOCONN;
1013 if (has_nfs_args_opt != 0) {
1015 * In the 'nfs_args' case, the pointers in the args
1016 * structure are in userland - we copy them in here.
1018 if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
1019 vfs_mount_error(mp, "Bad file handle");
1023 error = copyin((caddr_t)args.fh, (caddr_t)nfh,
1027 error = copyinstr(args.hostname, hst, MNAMELEN - 1, &hstlen);
1030 bzero(&hst[hstlen], MNAMELEN - hstlen);
1031 args.hostname = hst;
1032 /* sockargs() call must be after above copyin() calls */
1033 error = getsockaddr(&nam, (caddr_t)args.addr,
1038 if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
1039 &args.fhsize) == 0) {
1040 if (args.fhsize < 0 || args.fhsize > NFSX_FHMAX) {
1041 vfs_mount_error(mp, "Bad file handle");
1045 bcopy(args.fh, nfh, args.fhsize);
1049 (void) vfs_getopt(mp->mnt_optnew, "hostname",
1050 (void **)&args.hostname, &len);
1051 if (args.hostname == NULL) {
1052 vfs_mount_error(mp, "Invalid hostname");
1056 bcopy(args.hostname, hst, MNAMELEN);
1057 hst[MNAMELEN - 1] = '\0';
1060 if (vfs_getopt(mp->mnt_optnew, "principal", (void **)&name, NULL) == 0)
1061 strlcpy(srvkrbname, name, sizeof (srvkrbname));
1063 snprintf(srvkrbname, sizeof (srvkrbname), "nfs@%s", hst);
1064 srvkrbnamelen = strlen(srvkrbname);
1066 if (vfs_getopt(mp->mnt_optnew, "gssname", (void **)&name, NULL) == 0)
1067 strlcpy(krbname, name, sizeof (krbname));
1070 krbnamelen = strlen(krbname);
1072 if (vfs_getopt(mp->mnt_optnew, "dirpath", (void **)&name, NULL) == 0)
1073 strlcpy(dirpath, name, sizeof (dirpath));
1076 dirlen = strlen(dirpath);
1078 if (has_nfs_args_opt == 0 && vfs_getopt(mp->mnt_optnew, "addr",
1079 (void **)&args.addr, &args.addrlen) == 0) {
1080 if (args.addrlen > SOCK_MAXADDRLEN) {
1081 error = ENAMETOOLONG;
1084 nam = malloc(args.addrlen, M_SONAME, M_WAITOK);
1085 bcopy(args.addr, nam, args.addrlen);
1086 nam->sa_len = args.addrlen;
1090 error = mountnfs(&args, mp, nam, hst, krbname, krbnamelen, dirpath,
1091 dirlen, srvkrbname, srvkrbnamelen, &vp, td->td_ucred, td,
1096 mp->mnt_kern_flag |= (MNTK_MPSAFE|MNTK_LOOKUP_SHARED);
1107 * It seems a bit dumb to copyinstr() the host and path here and then
1108 * bcopy() them in mountnfs(), but I wanted to detect errors before
1109 * doing the sockargs() call because sockargs() allocates an mbuf and
1110 * an error after that means that I have to release the mbuf.
1114 nfs_cmount(struct mntarg *ma, void *data, int flags)
1117 struct nfs_args args;
1119 error = copyin(data, &args, sizeof (struct nfs_args));
1123 ma = mount_arg(ma, "nfs_args", &args, sizeof args);
1125 error = kernel_mount(ma, flags);
1130 * Common code for mount and mountroot
1133 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
1134 char *hst, u_char *krbname, int krbnamelen, u_char *dirpath, int dirlen,
1135 u_char *srvkrbname, int srvkrbnamelen, struct vnode **vpp,
1136 struct ucred *cred, struct thread *td, int negnametimeo)
1138 struct nfsmount *nmp;
1140 int error, trycnt, ret;
1141 struct nfsvattr nfsva;
1142 static u_int64_t clval = 0;
1144 if (mp->mnt_flag & MNT_UPDATE) {
1146 printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
1147 FREE(nam, M_SONAME);
1150 MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount) +
1151 krbnamelen + dirlen + srvkrbnamelen + 2,
1152 M_NEWNFSMNT, M_WAITOK | M_ZERO);
1153 TAILQ_INIT(&nmp->nm_bufq);
1155 clval = (u_int64_t)nfsboottime.tv_sec;
1156 nmp->nm_clval = clval++;
1157 nmp->nm_krbnamelen = krbnamelen;
1158 nmp->nm_dirpathlen = dirlen;
1159 nmp->nm_srvkrbnamelen = srvkrbnamelen;
1160 if (td->td_ucred->cr_uid != (uid_t)0) {
1162 * nm_uid is used to get KerberosV credentials for
1163 * the nfsv4 state handling operations if there is
1164 * no host based principal set. Use the uid of
1165 * this user if not root, since they are doing the
1166 * mount. I don't think setting this for root will
1167 * work, since root normally does not have user
1168 * credentials in a credentials cache.
1170 nmp->nm_uid = td->td_ucred->cr_uid;
1173 * Just set to -1, so it won't be used.
1175 nmp->nm_uid = (uid_t)-1;
1178 /* Copy and null terminate all the names */
1179 if (nmp->nm_krbnamelen > 0) {
1180 bcopy(krbname, nmp->nm_krbname, nmp->nm_krbnamelen);
1181 nmp->nm_name[nmp->nm_krbnamelen] = '\0';
1183 if (nmp->nm_dirpathlen > 0) {
1184 bcopy(dirpath, NFSMNT_DIRPATH(nmp),
1185 nmp->nm_dirpathlen);
1186 nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1189 if (nmp->nm_srvkrbnamelen > 0) {
1190 bcopy(srvkrbname, NFSMNT_SRVKRBNAME(nmp),
1191 nmp->nm_srvkrbnamelen);
1192 nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1193 + nmp->nm_srvkrbnamelen + 2] = '\0';
1195 nmp->nm_sockreq.nr_cred = crhold(cred);
1196 mtx_init(&nmp->nm_sockreq.nr_mtx, "nfssock", NULL, MTX_DEF);
1198 nmp->nm_getinfo = nfs_getnlminfo;
1199 nmp->nm_vinvalbuf = ncl_vinvalbuf;
1202 nmp->nm_mountp = mp;
1203 mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF | MTX_DUPOK);
1204 nmp->nm_negnametimeo = negnametimeo;
1206 nfs_decode_args(mp, nmp, argp, hst, cred, td);
1209 * V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too
1210 * high, depending on whether we end up with negative offsets in
1211 * the client or server somewhere. 2GB-1 may be safer.
1213 * For V3, ncl_fsinfo will adjust this as necessary. Assume maximum
1214 * that we can handle until we find out otherwise.
1215 * XXX Our "safe" limit on the client is what we can store in our
1216 * buffer cache using signed(!) block numbers.
1218 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0)
1219 nmp->nm_maxfilesize = 0xffffffffLL;
1221 nmp->nm_maxfilesize = OFF_MAX;
1223 nmp->nm_timeo = NFS_TIMEO;
1224 nmp->nm_retry = NFS_RETRANS;
1225 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
1226 nmp->nm_wsize = NFS_WSIZE;
1227 nmp->nm_rsize = NFS_RSIZE;
1228 nmp->nm_readdirsize = NFS_READDIRSIZE;
1230 nmp->nm_wcommitsize = hibufspace / (desiredvnodes / 1000);
1231 nmp->nm_numgrps = NFS_MAXGRPS;
1232 nmp->nm_readahead = NFS_DEFRAHEAD;
1233 nmp->nm_tprintf_delay = nfs_tprintf_delay;
1234 if (nmp->nm_tprintf_delay < 0)
1235 nmp->nm_tprintf_delay = 0;
1236 nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
1237 if (nmp->nm_tprintf_initial_delay < 0)
1238 nmp->nm_tprintf_initial_delay = 0;
1239 nmp->nm_fhsize = argp->fhsize;
1240 if (nmp->nm_fhsize > 0)
1241 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
1242 bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
1244 /* Set up the sockets and per-host congestion */
1245 nmp->nm_sotype = argp->sotype;
1246 nmp->nm_soproto = argp->proto;
1247 nmp->nm_sockreq.nr_prog = NFS_PROG;
1248 if ((argp->flags & NFSMNT_NFSV4))
1249 nmp->nm_sockreq.nr_vers = NFS_VER4;
1250 else if ((argp->flags & NFSMNT_NFSV3))
1251 nmp->nm_sockreq.nr_vers = NFS_VER3;
1253 nmp->nm_sockreq.nr_vers = NFS_VER2;
1256 if ((error = newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0)))
1260 * A reference count is needed on the nfsnode representing the
1261 * remote root. If this object is not persistent, then backward
1262 * traversals of the mount point (i.e. "..") will not work if
1263 * the nfsnode gets flushed out of the cache. Ufs does not have
1264 * this problem, because one can identify root inodes by their
1265 * number == ROOTINO (2).
1267 if (nmp->nm_fhsize == 0 && (nmp->nm_flag & NFSMNT_NFSV4) &&
1268 nmp->nm_dirpathlen > 0) {
1270 * If the fhsize on the mount point == 0 for V4, the mount
1271 * path needs to be looked up.
1275 error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp),
1278 (void) nfs_catnap(PZERO, error, "nfsgetdirp");
1279 } while (error && --trycnt > 0);
1281 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
1285 if (nmp->nm_fhsize > 0) {
1287 * Set f_iosize to NFS_DIRBLKSIZ so that bo_bsize gets set
1288 * non-zero for the root vnode. f_iosize will be set correctly
1289 * by nfs_statfs() before any I/O occurs.
1291 mp->mnt_stat.f_iosize = NFS_DIRBLKSIZ;
1292 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np,
1299 * Get file attributes and transfer parameters for the
1300 * mountpoint. This has the side effect of filling in
1301 * (*vpp)->v_type with the correct value.
1303 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
1304 cred, td, &nfsva, NULL);
1307 * Just set default values to get things going.
1309 NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
1310 nfsva.na_vattr.va_type = VDIR;
1311 nfsva.na_vattr.va_mode = 0777;
1312 nfsva.na_vattr.va_nlink = 100;
1313 nfsva.na_vattr.va_uid = (uid_t)0;
1314 nfsva.na_vattr.va_gid = (gid_t)0;
1315 nfsva.na_vattr.va_fileid = 2;
1316 nfsva.na_vattr.va_gen = 1;
1317 nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
1318 nfsva.na_vattr.va_size = 512 * 1024;
1320 (void) nfscl_loadattrcache(vpp, &nfsva, NULL, NULL, 0, 1);
1321 if (argp->flags & NFSMNT_NFSV3)
1322 ncl_fsinfo(nmp, *vpp, cred, td);
1325 * Lose the lock but keep the ref.
1327 VOP_UNLOCK(*vpp, 0);
1333 newnfs_disconnect(&nmp->nm_sockreq);
1334 crfree(nmp->nm_sockreq.nr_cred);
1335 mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1336 mtx_destroy(&nmp->nm_mtx);
1337 FREE(nmp, M_NEWNFSMNT);
1338 FREE(nam, M_SONAME);
1343 * unmount system call
1346 nfs_unmount(struct mount *mp, int mntflags)
1349 struct nfsmount *nmp;
1350 int error, flags = 0, trycnt = 0;
1354 if (mntflags & MNT_FORCE)
1355 flags |= FORCECLOSE;
1358 * Goes something like this..
1359 * - Call vflush() to clear out vnodes for this filesystem
1360 * - Close the socket
1361 * - Free up the data structures
1363 /* In the forced case, cancel any outstanding requests. */
1364 if (mntflags & MNT_FORCE) {
1365 error = newnfs_nmcancelreqs(nmp);
1368 /* For a forced close, get rid of the renew thread now */
1369 nfscl_umount(nmp, td);
1371 /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
1373 error = vflush(mp, 1, flags, td);
1374 if ((mntflags & MNT_FORCE) && error != 0 && ++trycnt < 30)
1375 (void) nfs_catnap(PSOCK, error, "newndm");
1376 } while ((mntflags & MNT_FORCE) && error != 0 && trycnt < 30);
1381 * We are now committed to the unmount.
1383 if ((mntflags & MNT_FORCE) == 0)
1384 nfscl_umount(nmp, td);
1385 newnfs_disconnect(&nmp->nm_sockreq);
1386 crfree(nmp->nm_sockreq.nr_cred);
1387 FREE(nmp->nm_nam, M_SONAME);
1389 mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1390 mtx_destroy(&nmp->nm_mtx);
1391 FREE(nmp, M_NEWNFSMNT);
1397 * Return root of a filesystem
1400 nfs_root(struct mount *mp, int flags, struct vnode **vpp)
1403 struct nfsmount *nmp;
1408 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, flags);
1413 * Get transfer parameters and attributes for root vnode once.
1415 mtx_lock(&nmp->nm_mtx);
1416 if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
1417 mtx_unlock(&nmp->nm_mtx);
1418 ncl_fsinfo(nmp, vp, curthread->td_ucred, curthread);
1420 mtx_unlock(&nmp->nm_mtx);
1421 if (vp->v_type == VNON)
1423 vp->v_vflag |= VV_ROOT;
1429 * Flush out the buffer cache
1433 nfs_sync(struct mount *mp, int waitfor)
1435 struct vnode *vp, *mvp;
1437 int error, allerror = 0;
1442 * Force stale buffer cache information to be flushed.
1446 MNT_VNODE_FOREACH(vp, mp, mvp) {
1449 /* XXX Racy bv_cnt check. */
1450 if (VOP_ISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
1451 waitfor == MNT_LAZY) {
1456 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
1458 MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp);
1461 error = VOP_FSYNC(vp, waitfor, td);
1474 nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
1476 struct nfsmount *nmp = VFSTONFS(mp);
1480 bzero(&vq, sizeof(vq));
1483 case VFS_CTL_NOLOCKS:
1484 val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
1485 if (req->oldptr != NULL) {
1486 error = SYSCTL_OUT(req, &val, sizeof(val));
1490 if (req->newptr != NULL) {
1491 error = SYSCTL_IN(req, &val, sizeof(val));
1495 nmp->nm_flag |= NFSMNT_NOLOCKS;
1497 nmp->nm_flag &= ~NFSMNT_NOLOCKS;
1502 mtx_lock(&nmp->nm_mtx);
1503 if (nmp->nm_state & NFSSTA_TIMEO)
1504 vq.vq_flags |= VQ_NOTRESP;
1505 mtx_unlock(&nmp->nm_mtx);
1507 if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
1508 (nmp->nm_state & NFSSTA_LOCKTIMEO))
1509 vq.vq_flags |= VQ_NOTRESPLOCK;
1511 error = SYSCTL_OUT(req, &vq, sizeof(vq));
1514 if (req->oldptr != NULL) {
1515 error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
1516 sizeof(nmp->nm_tprintf_initial_delay));
1520 if (req->newptr != NULL) {
1521 error = vfs_suser(mp, req->td);
1524 error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
1525 sizeof(nmp->nm_tprintf_initial_delay));
1528 if (nmp->nm_tprintf_initial_delay < 0)
1529 nmp->nm_tprintf_initial_delay = 0;
1539 * Extract the information needed by the nlm from the nfs vnode.
1542 nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp,
1543 struct sockaddr_storage *sp, int *is_v3p, off_t *sizep,
1544 struct timeval *timeop)
1546 struct nfsmount *nmp;
1547 struct nfsnode *np = VTONFS(vp);
1549 nmp = VFSTONFS(vp->v_mount);
1551 *fhlenp = (size_t)np->n_fhp->nfh_len;
1553 bcopy(np->n_fhp->nfh_fh, fhp, np->n_fhp->nfh_len);
1555 bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp)));
1557 *is_v3p = NFS_ISV3(vp);
1559 *sizep = np->n_size;
1560 if (timeop != NULL) {
1561 timeop->tv_sec = nmp->nm_timeo / NFS_HZ;
1562 timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ);