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;
80 extern int nfsrv_useacl;
82 MALLOC_DEFINE(M_NEWNFSREQ, "newnfsclient_req", "New NFS request header");
83 MALLOC_DEFINE(M_NEWNFSMNT, "newnfsmnt", "New NFS mount struct");
85 SYSCTL_DECL(_vfs_newnfs);
86 SYSCTL_STRUCT(_vfs_newnfs, NFS_NFSSTATS, nfsstats, CTLFLAG_RW,
87 &newnfsstats, nfsstats, "S,nfsstats");
88 static int nfs_ip_paranoia = 1;
89 SYSCTL_INT(_vfs_newnfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW,
90 &nfs_ip_paranoia, 0, "");
91 static int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
92 SYSCTL_INT(_vfs_newnfs, NFS_TPRINTF_INITIAL_DELAY,
93 downdelayinitial, CTLFLAG_RW, &nfs_tprintf_initial_delay, 0, "");
94 /* how long between console messages "nfs server foo not responding" */
95 static int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
96 SYSCTL_INT(_vfs_newnfs, NFS_TPRINTF_DELAY,
97 downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0, "");
99 static int nfs_mountroot(struct mount *);
100 static void nfs_sec_name(char *, int *);
101 static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp,
102 struct nfs_args *argp, const char *, struct ucred *,
104 static int mountnfs(struct nfs_args *, struct mount *,
105 struct sockaddr *, char *, u_char *, int, u_char *, int,
106 u_char *, int, struct vnode **, struct ucred *,
107 struct thread *, int);
108 static void nfs_getnlminfo(struct vnode *, uint8_t *, size_t *,
109 struct sockaddr_storage *, int *, off_t *,
111 static vfs_mount_t nfs_mount;
112 static vfs_cmount_t nfs_cmount;
113 static vfs_unmount_t nfs_unmount;
114 static vfs_root_t nfs_root;
115 static vfs_statfs_t nfs_statfs;
116 static vfs_sync_t nfs_sync;
117 static vfs_sysctl_t nfs_sysctl;
120 * nfs vfs operations.
122 static struct vfsops nfs_vfsops = {
123 .vfs_init = ncl_init,
124 .vfs_mount = nfs_mount,
125 .vfs_cmount = nfs_cmount,
126 .vfs_root = nfs_root,
127 .vfs_statfs = nfs_statfs,
128 .vfs_sync = nfs_sync,
129 .vfs_uninit = ncl_uninit,
130 .vfs_unmount = nfs_unmount,
131 .vfs_sysctl = nfs_sysctl,
133 VFS_SET(nfs_vfsops, newnfs, VFCF_NETWORK);
135 /* So that loader and kldload(2) can find us, wherever we are.. */
136 MODULE_VERSION(newnfs, 1);
139 * This structure is now defined in sys/nfs/nfs_diskless.c so that it
140 * can be shared by both NFS clients. It is declared here so that it
141 * will be defined for kernels built without NFS_ROOT, although it
142 * isn't used in that case.
144 #if !defined(NFS_ROOT) && !defined(NFSCLIENT)
145 struct nfs_diskless nfs_diskless = { { { 0 } } };
146 struct nfsv3_diskless nfsv3_diskless = { { { 0 } } };
147 int nfs_diskless_valid = 0;
150 SYSCTL_INT(_vfs_newnfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
151 &nfs_diskless_valid, 0,
152 "Has the diskless struct been filled correctly");
154 SYSCTL_STRING(_vfs_newnfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
155 nfsv3_diskless.root_hostnam, 0, "Path to nfs root");
157 SYSCTL_OPAQUE(_vfs_newnfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
158 &nfsv3_diskless.root_saddr, sizeof(nfsv3_diskless.root_saddr),
159 "%Ssockaddr_in", "Diskless root nfs address");
162 void newnfsargs_ntoh(struct nfs_args *);
163 static int nfs_mountdiskless(char *,
164 struct sockaddr_in *, struct nfs_args *,
165 struct thread *, struct vnode **, struct mount *);
166 static void nfs_convert_diskless(void);
167 static void nfs_convert_oargs(struct nfs_args *args,
168 struct onfs_args *oargs);
171 newnfs_iosize(struct nfsmount *nmp)
175 /* First, set the upper limit for iosize */
176 if (nmp->nm_flag & NFSMNT_NFSV4) {
177 maxio = NFS_MAXBSIZE;
178 } else if (nmp->nm_flag & NFSMNT_NFSV3) {
179 if (nmp->nm_sotype == SOCK_DGRAM)
180 maxio = NFS_MAXDGRAMDATA;
182 maxio = NFS_MAXBSIZE;
184 maxio = NFS_V2MAXDATA;
186 if (nmp->nm_rsize > maxio || nmp->nm_rsize == 0)
187 nmp->nm_rsize = maxio;
188 if (nmp->nm_rsize > MAXBSIZE)
189 nmp->nm_rsize = MAXBSIZE;
190 if (nmp->nm_readdirsize > maxio || nmp->nm_readdirsize == 0)
191 nmp->nm_readdirsize = maxio;
192 if (nmp->nm_readdirsize > nmp->nm_rsize)
193 nmp->nm_readdirsize = nmp->nm_rsize;
194 if (nmp->nm_wsize > maxio || nmp->nm_wsize == 0)
195 nmp->nm_wsize = maxio;
196 if (nmp->nm_wsize > MAXBSIZE)
197 nmp->nm_wsize = MAXBSIZE;
200 * Calculate the size used for io buffers. Use the larger
201 * of the two sizes to minimise nfs requests but make sure
202 * that it is at least one VM page to avoid wasting buffer
205 iosize = imax(nmp->nm_rsize, nmp->nm_wsize);
206 iosize = imax(iosize, PAGE_SIZE);
207 nmp->nm_mountp->mnt_stat.f_iosize = iosize;
212 nfs_convert_oargs(struct nfs_args *args, struct onfs_args *oargs)
215 args->version = NFS_ARGSVERSION;
216 args->addr = oargs->addr;
217 args->addrlen = oargs->addrlen;
218 args->sotype = oargs->sotype;
219 args->proto = oargs->proto;
220 args->fh = oargs->fh;
221 args->fhsize = oargs->fhsize;
222 args->flags = oargs->flags;
223 args->wsize = oargs->wsize;
224 args->rsize = oargs->rsize;
225 args->readdirsize = oargs->readdirsize;
226 args->timeo = oargs->timeo;
227 args->retrans = oargs->retrans;
228 args->readahead = oargs->readahead;
229 args->hostname = oargs->hostname;
233 nfs_convert_diskless(void)
236 bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
237 sizeof(struct ifaliasreq));
238 bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
239 sizeof(struct sockaddr_in));
240 nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
241 if (nfsv3_diskless.root_args.flags & NFSMNT_NFSV3) {
242 nfsv3_diskless.root_fhsize = NFSX_MYFH;
243 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_MYFH);
245 nfsv3_diskless.root_fhsize = NFSX_V2FH;
246 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
248 bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
249 sizeof(struct sockaddr_in));
250 bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN);
251 nfsv3_diskless.root_time = nfs_diskless.root_time;
252 bcopy(nfs_diskless.my_hostnam, nfsv3_diskless.my_hostnam,
254 nfs_diskless_valid = 3;
261 nfs_statfs(struct mount *mp, struct statfs *sbp)
265 struct nfsmount *nmp = VFSTONFS(mp);
266 struct nfsvattr nfsva;
269 int error = 0, attrflag, gotfsinfo = 0, ret;
274 error = vfs_busy(mp, MBF_NOWAIT);
277 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
283 mtx_lock(&nmp->nm_mtx);
284 if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
285 mtx_unlock(&nmp->nm_mtx);
286 error = nfsrpc_fsinfo(vp, &fs, td->td_ucred, td, &nfsva,
291 mtx_unlock(&nmp->nm_mtx);
293 error = nfsrpc_statfs(vp, &sb, &fs, td->td_ucred, td, &nfsva,
296 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
297 td->td_ucred, td, &nfsva, NULL);
300 * Just set default values to get things going.
302 NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
303 nfsva.na_vattr.va_type = VDIR;
304 nfsva.na_vattr.va_mode = 0777;
305 nfsva.na_vattr.va_nlink = 100;
306 nfsva.na_vattr.va_uid = (uid_t)0;
307 nfsva.na_vattr.va_gid = (gid_t)0;
308 nfsva.na_vattr.va_fileid = 2;
309 nfsva.na_vattr.va_gen = 1;
310 nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
311 nfsva.na_vattr.va_size = 512 * 1024;
314 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
316 mtx_lock(&nmp->nm_mtx);
317 if (gotfsinfo || (nmp->nm_flag & NFSMNT_NFSV4))
318 nfscl_loadfsinfo(nmp, &fs);
319 nfscl_loadsbinfo(nmp, &sb, sbp);
320 sbp->f_iosize = newnfs_iosize(nmp);
321 mtx_unlock(&nmp->nm_mtx);
322 if (sbp != &mp->mnt_stat) {
323 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
324 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
326 strncpy(&sbp->f_fstypename[0], mp->mnt_vfc->vfc_name, MFSNAMELEN);
327 } else if (NFS_ISV4(vp)) {
328 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
336 * nfs version 3 fsinfo rpc call
339 ncl_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred,
343 struct nfsvattr nfsva;
346 error = nfsrpc_fsinfo(vp, &fs, cred, td, &nfsva, &attrflag, NULL);
349 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0,
351 mtx_lock(&nmp->nm_mtx);
352 nfscl_loadfsinfo(nmp, &fs);
353 mtx_unlock(&nmp->nm_mtx);
359 * Mount a remote root fs via. nfs. This depends on the info in the
360 * nfs_diskless structure that has been filled in properly by some primary
362 * It goes something like this:
363 * - do enough of "ifconfig" by calling ifioctl() so that the system
364 * can talk to the server
365 * - If nfs_diskless.mygateway is filled in, use that address as
367 * - build the rootfs mount point and call mountnfs() to do the rest.
369 * It is assumed to be safe to read, modify, and write the nfsv3_diskless
370 * structure, as well as other global NFS client variables here, as
371 * nfs_mountroot() will be called once in the boot before any other NFS
372 * client activity occurs.
375 nfs_mountroot(struct mount *mp)
377 struct thread *td = curthread;
378 struct nfsv3_diskless *nd = &nfsv3_diskless;
387 #if defined(BOOTP_NFSROOT) && defined(BOOTP)
388 bootpc_init(); /* use bootp to get nfs_diskless filled in */
389 #elif defined(NFS_ROOT)
390 nfs_setup_diskless();
393 if (nfs_diskless_valid == 0)
395 if (nfs_diskless_valid == 1)
396 nfs_convert_diskless();
399 * XXX splnet, so networks will receive...
404 * Do enough of ifconfig(8) so that the critical net interface can
405 * talk to the server.
407 error = socreate(nd->myif.ifra_addr.sa_family, &so, nd->root_args.sotype, 0,
410 panic("nfs_mountroot: socreate(%04x): %d",
411 nd->myif.ifra_addr.sa_family, error);
413 #if 0 /* XXX Bad idea */
415 * We might not have been told the right interface, so we pass
416 * over the first ten interfaces of the same kind, until we get
417 * one of them configured.
420 for (i = strlen(nd->myif.ifra_name) - 1;
421 nd->myif.ifra_name[i] >= '0' &&
422 nd->myif.ifra_name[i] <= '9';
423 nd->myif.ifra_name[i] ++) {
424 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
429 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
431 panic("nfs_mountroot: SIOCAIFADDR: %d", error);
432 if ((cp = getenv("boot.netif.mtu")) != NULL) {
433 ir.ifr_mtu = strtol(cp, NULL, 10);
434 bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ);
436 error = ifioctl(so, SIOCSIFMTU, (caddr_t)&ir, td);
438 printf("nfs_mountroot: SIOCSIFMTU: %d", error);
443 * If the gateway field is filled in, set it as the default route.
444 * Note that pxeboot will set a default route of 0 if the route
445 * is not set by the DHCP server. Check also for a value of 0
446 * to avoid panicking inappropriately in that situation.
448 if (nd->mygateway.sin_len != 0 &&
449 nd->mygateway.sin_addr.s_addr != 0) {
450 struct sockaddr_in mask, sin;
452 bzero((caddr_t)&mask, sizeof(mask));
454 sin.sin_family = AF_INET;
455 sin.sin_len = sizeof(sin);
456 /* XXX MRT use table 0 for this sort of thing */
457 CURVNET_SET(TD_TO_VNET(td));
458 error = rtrequest(RTM_ADD, (struct sockaddr *)&sin,
459 (struct sockaddr *)&nd->mygateway,
460 (struct sockaddr *)&mask,
461 RTF_UP | RTF_GATEWAY, NULL);
464 panic("nfs_mountroot: RTM_ADD: %d", error);
468 * Create the rootfs mount point.
470 nd->root_args.fh = nd->root_fh;
471 nd->root_args.fhsize = nd->root_fhsize;
472 l = ntohl(nd->root_saddr.sin_addr.s_addr);
473 snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
474 (l >> 24) & 0xff, (l >> 16) & 0xff,
475 (l >> 8) & 0xff, (l >> 0) & 0xff, nd->root_hostnam);
476 printf("NFS ROOT: %s\n", buf);
477 nd->root_args.hostname = buf;
478 if ((error = nfs_mountdiskless(buf,
479 &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) {
484 * This is not really an nfs issue, but it is much easier to
485 * set hostname here and then let the "/etc/rc.xxx" files
486 * mount the right /var based upon its preset value.
488 mtx_lock(&prison0.pr_mtx);
489 strlcpy(prison0.pr_hostname, nd->my_hostnam,
490 sizeof(prison0.pr_hostname));
491 mtx_unlock(&prison0.pr_mtx);
492 inittodr(ntohl(nd->root_time));
497 * Internal version of mount system call for diskless setup.
500 nfs_mountdiskless(char *path,
501 struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
502 struct vnode **vpp, struct mount *mp)
504 struct sockaddr *nam;
509 * Find the directory path in "path", which also has the server's
510 * name/ip address in it.
512 dirpath = strchr(path, ':');
514 dirlen = strlen(++dirpath);
517 nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
518 if ((error = mountnfs(args, mp, nam, path, NULL, 0, dirpath, dirlen,
519 NULL, 0, vpp, td->td_ucred, td, NFS_DEFAULT_NEGNAMETIMEO)) != 0) {
520 printf("nfs_mountroot: mount %s on /: %d\n", path, error);
527 nfs_sec_name(char *sec, int *flagsp)
529 if (!strcmp(sec, "krb5"))
530 *flagsp |= NFSMNT_KERB;
531 else if (!strcmp(sec, "krb5i"))
532 *flagsp |= (NFSMNT_KERB | NFSMNT_INTEGRITY);
533 else if (!strcmp(sec, "krb5p"))
534 *flagsp |= (NFSMNT_KERB | NFSMNT_PRIVACY);
538 nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
539 const char *hostname, struct ucred *cred, struct thread *td)
548 * Set read-only flag if requested; otherwise, clear it if this is
549 * an update. If this is not an update, then either the read-only
550 * flag is already clear, or this is a root mount and it was set
551 * intentionally at some previous point.
553 if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) {
555 mp->mnt_flag |= MNT_RDONLY;
557 } else if (mp->mnt_flag & MNT_UPDATE) {
559 mp->mnt_flag &= ~MNT_RDONLY;
564 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
565 * no sense in that context. Also, set up appropriate retransmit
566 * and soft timeout behavior.
568 if (argp->sotype == SOCK_STREAM) {
569 nmp->nm_flag &= ~NFSMNT_NOCONN;
570 nmp->nm_timeo = NFS_MAXTIMEO;
571 if ((argp->flags & NFSMNT_NFSV4) != 0)
572 nmp->nm_retry = INT_MAX;
574 nmp->nm_retry = NFS_RETRANS_TCP;
577 /* Also clear RDIRPLUS if NFSv2, it crashes some servers */
578 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
579 argp->flags &= ~NFSMNT_RDIRPLUS;
580 nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
583 /* Clear NFSMNT_RESVPORT for NFSv4, since it is not required. */
584 if ((argp->flags & NFSMNT_NFSV4) != 0) {
585 argp->flags &= ~NFSMNT_RESVPORT;
586 nmp->nm_flag &= ~NFSMNT_RESVPORT;
589 /* Re-bind if rsrvd port requested and wasn't on one */
590 adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
591 && (argp->flags & NFSMNT_RESVPORT);
592 /* Also re-bind if we're switching to/from a connected UDP socket */
593 adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
594 (argp->flags & NFSMNT_NOCONN));
596 /* Update flags atomically. Don't change the lock bits. */
597 nmp->nm_flag = argp->flags | nmp->nm_flag;
600 if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
601 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
602 if (nmp->nm_timeo < NFS_MINTIMEO)
603 nmp->nm_timeo = NFS_MINTIMEO;
604 else if (nmp->nm_timeo > NFS_MAXTIMEO)
605 nmp->nm_timeo = NFS_MAXTIMEO;
608 if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
609 nmp->nm_retry = argp->retrans;
610 if (nmp->nm_retry > NFS_MAXREXMIT)
611 nmp->nm_retry = NFS_MAXREXMIT;
614 if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
615 nmp->nm_wsize = argp->wsize;
616 /* Round down to multiple of blocksize */
617 nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
618 if (nmp->nm_wsize <= 0)
619 nmp->nm_wsize = NFS_FABLKSIZE;
622 if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
623 nmp->nm_rsize = argp->rsize;
624 /* Round down to multiple of blocksize */
625 nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
626 if (nmp->nm_rsize <= 0)
627 nmp->nm_rsize = NFS_FABLKSIZE;
630 if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
631 nmp->nm_readdirsize = argp->readdirsize;
634 if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
635 nmp->nm_acregmin = argp->acregmin;
637 nmp->nm_acregmin = NFS_MINATTRTIMO;
638 if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
639 nmp->nm_acregmax = argp->acregmax;
641 nmp->nm_acregmax = NFS_MAXATTRTIMO;
642 if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
643 nmp->nm_acdirmin = argp->acdirmin;
645 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
646 if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
647 nmp->nm_acdirmax = argp->acdirmax;
649 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
650 if (nmp->nm_acdirmin > nmp->nm_acdirmax)
651 nmp->nm_acdirmin = nmp->nm_acdirmax;
652 if (nmp->nm_acregmin > nmp->nm_acregmax)
653 nmp->nm_acregmin = nmp->nm_acregmax;
655 if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
656 if (argp->readahead <= NFS_MAXRAHEAD)
657 nmp->nm_readahead = argp->readahead;
659 nmp->nm_readahead = NFS_MAXRAHEAD;
661 if ((argp->flags & NFSMNT_WCOMMITSIZE) && argp->wcommitsize >= 0) {
662 if (argp->wcommitsize < nmp->nm_wsize)
663 nmp->nm_wcommitsize = nmp->nm_wsize;
665 nmp->nm_wcommitsize = argp->wcommitsize;
668 adjsock |= ((nmp->nm_sotype != argp->sotype) ||
669 (nmp->nm_soproto != argp->proto));
671 if (nmp->nm_client != NULL && adjsock) {
672 int haslock = 0, error = 0;
674 if (nmp->nm_sotype == SOCK_STREAM) {
675 error = newnfs_sndlock(&nmp->nm_sockreq.nr_lock);
680 newnfs_disconnect(&nmp->nm_sockreq);
682 newnfs_sndunlock(&nmp->nm_sockreq.nr_lock);
683 nmp->nm_sotype = argp->sotype;
684 nmp->nm_soproto = argp->proto;
685 if (nmp->nm_sotype == SOCK_DGRAM)
686 while (newnfs_connect(nmp, &nmp->nm_sockreq,
688 printf("newnfs_args: retrying connect\n");
689 (void) nfs_catnap(PSOCK, 0, "newnfscon");
693 nmp->nm_sotype = argp->sotype;
694 nmp->nm_soproto = argp->proto;
697 if (hostname != NULL) {
698 strlcpy(nmp->nm_hostname, hostname,
699 sizeof(nmp->nm_hostname));
700 p = strchr(nmp->nm_hostname, ':');
706 static const char *nfs_opts[] = { "from", "nfs_args",
707 "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
708 "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
709 "async", "noconn", "nolockd", "conn", "lockd", "intr", "rdirplus",
710 "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize",
711 "retrans", "acregmin", "acregmax", "acdirmin", "acdirmax", "resvport",
712 "readahead", "hostname", "timeout", "addr", "fh", "nfsv3", "sec",
713 "principal", "nfsv4", "gssname", "allgssname", "dirpath",
714 "negnametimeo", "nocto",
721 * It seems a bit dumb to copyinstr() the host and path here and then
722 * bcopy() them in mountnfs(), but I wanted to detect errors before
723 * doing the sockargs() call because sockargs() allocates an mbuf and
724 * an error after that means that I have to release the mbuf.
728 nfs_mount(struct mount *mp)
730 struct nfs_args args = {
731 .version = NFS_ARGSVERSION,
733 .addrlen = sizeof (struct sockaddr_in),
734 .sotype = SOCK_STREAM,
738 .flags = NFSMNT_RESVPORT,
741 .readdirsize = NFS_READDIRSIZE,
743 .retrans = NFS_RETRANS,
744 .readahead = NFS_DEFRAHEAD,
745 .wcommitsize = 0, /* was: NQ_DEFLEASE */
747 .acregmin = NFS_MINATTRTIMO,
748 .acregmax = NFS_MAXATTRTIMO,
749 .acdirmin = NFS_MINDIRATTRTIMO,
750 .acdirmax = NFS_MAXDIRATTRTIMO,
752 int error = 0, ret, len;
753 struct sockaddr *nam = NULL;
757 u_char nfh[NFSX_FHMAX], krbname[100], dirpath[100], srvkrbname[100];
758 char *opt, *name, *secname;
759 int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
760 int dirlen, has_nfs_args_opt, krbnamelen, srvkrbnamelen;
763 has_nfs_args_opt = 0;
764 if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
770 if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS) {
771 error = nfs_mountroot(mp);
778 * The old mount_nfs program passed the struct nfs_args
779 * from userspace to kernel. The new mount_nfs program
780 * passes string options via nmount() from userspace to kernel
781 * and we populate the struct nfs_args in the kernel.
783 if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
784 error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
789 if (args.version != NFS_ARGSVERSION) {
790 error = EPROGMISMATCH;
793 has_nfs_args_opt = 1;
796 /* Handle the new style options. */
797 if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
798 args.flags |= NFSMNT_NOCONN;
799 if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
800 args.flags |= NFSMNT_NOCONN;
801 if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
802 args.flags |= NFSMNT_NOLOCKD;
803 if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
804 args.flags &= ~NFSMNT_NOLOCKD;
805 if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
806 args.flags |= NFSMNT_INT;
807 if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
808 args.flags |= NFSMNT_RDIRPLUS;
809 if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
810 args.flags |= NFSMNT_RESVPORT;
811 if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
812 args.flags &= ~NFSMNT_RESVPORT;
813 if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
814 args.flags |= NFSMNT_SOFT;
815 if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
816 args.flags &= ~NFSMNT_SOFT;
817 if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
818 args.sotype = SOCK_DGRAM;
819 if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
820 args.sotype = SOCK_DGRAM;
821 if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
822 args.sotype = SOCK_STREAM;
823 if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
824 args.flags |= NFSMNT_NFSV3;
825 if (vfs_getopt(mp->mnt_optnew, "nfsv4", NULL, NULL) == 0) {
826 args.flags |= NFSMNT_NFSV4;
827 args.sotype = SOCK_STREAM;
829 if (vfs_getopt(mp->mnt_optnew, "allgssname", NULL, NULL) == 0)
830 args.flags |= NFSMNT_ALLGSSNAME;
831 if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0)
832 args.flags |= NFSMNT_NOCTO;
833 if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
835 vfs_mount_error(mp, "illegal readdirsize");
839 ret = sscanf(opt, "%d", &args.readdirsize);
840 if (ret != 1 || args.readdirsize <= 0) {
841 vfs_mount_error(mp, "illegal readdirsize: %s",
846 args.flags |= NFSMNT_READDIRSIZE;
848 if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
850 vfs_mount_error(mp, "illegal readahead");
854 ret = sscanf(opt, "%d", &args.readahead);
855 if (ret != 1 || args.readahead <= 0) {
856 vfs_mount_error(mp, "illegal readahead: %s",
861 args.flags |= NFSMNT_READAHEAD;
863 if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
865 vfs_mount_error(mp, "illegal wsize");
869 ret = sscanf(opt, "%d", &args.wsize);
870 if (ret != 1 || args.wsize <= 0) {
871 vfs_mount_error(mp, "illegal wsize: %s",
876 args.flags |= NFSMNT_WSIZE;
878 if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
880 vfs_mount_error(mp, "illegal rsize");
884 ret = sscanf(opt, "%d", &args.rsize);
885 if (ret != 1 || args.rsize <= 0) {
886 vfs_mount_error(mp, "illegal wsize: %s",
891 args.flags |= NFSMNT_RSIZE;
893 if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
895 vfs_mount_error(mp, "illegal retrans");
899 ret = sscanf(opt, "%d", &args.retrans);
900 if (ret != 1 || args.retrans <= 0) {
901 vfs_mount_error(mp, "illegal retrans: %s",
906 args.flags |= NFSMNT_RETRANS;
908 if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
909 ret = sscanf(opt, "%d", &args.acregmin);
910 if (ret != 1 || args.acregmin < 0) {
911 vfs_mount_error(mp, "illegal acregmin: %s",
916 args.flags |= NFSMNT_ACREGMIN;
918 if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
919 ret = sscanf(opt, "%d", &args.acregmax);
920 if (ret != 1 || args.acregmax < 0) {
921 vfs_mount_error(mp, "illegal acregmax: %s",
926 args.flags |= NFSMNT_ACREGMAX;
928 if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
929 ret = sscanf(opt, "%d", &args.acdirmin);
930 if (ret != 1 || args.acdirmin < 0) {
931 vfs_mount_error(mp, "illegal acdirmin: %s",
936 args.flags |= NFSMNT_ACDIRMIN;
938 if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
939 ret = sscanf(opt, "%d", &args.acdirmax);
940 if (ret != 1 || args.acdirmax < 0) {
941 vfs_mount_error(mp, "illegal acdirmax: %s",
946 args.flags |= NFSMNT_ACDIRMAX;
948 if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
949 ret = sscanf(opt, "%d", &args.timeo);
950 if (ret != 1 || args.timeo <= 0) {
951 vfs_mount_error(mp, "illegal timeout: %s",
956 args.flags |= NFSMNT_TIMEO;
958 if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
960 ret = sscanf(opt, "%d", &negnametimeo);
961 if (ret != 1 || negnametimeo < 0) {
962 vfs_mount_error(mp, "illegal negnametimeo: %s",
968 if (vfs_getopt(mp->mnt_optnew, "sec",
969 (void **) &secname, NULL) == 0)
970 nfs_sec_name(secname, &args.flags);
972 if (mp->mnt_flag & MNT_UPDATE) {
973 struct nfsmount *nmp = VFSTONFS(mp);
980 * When doing an update, we can't change version,
981 * security, switch lockd strategies or change cookie
984 args.flags = (args.flags &
990 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
997 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
998 nfs_decode_args(mp, nmp, &args, NULL, td->td_ucred, td);
1003 * Make the nfs_ip_paranoia sysctl serve as the default connection
1004 * or no-connection mode for those protocols that support
1005 * no-connection mode (the flag will be cleared later for protocols
1006 * that do not support no-connection mode). This will allow a client
1007 * to receive replies from a different IP then the request was
1008 * sent to. Note: default value for nfs_ip_paranoia is 1 (paranoid),
1011 if (nfs_ip_paranoia == 0)
1012 args.flags |= NFSMNT_NOCONN;
1014 if (has_nfs_args_opt != 0) {
1016 * In the 'nfs_args' case, the pointers in the args
1017 * structure are in userland - we copy them in here.
1019 if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
1020 vfs_mount_error(mp, "Bad file handle");
1024 error = copyin((caddr_t)args.fh, (caddr_t)nfh,
1028 error = copyinstr(args.hostname, hst, MNAMELEN - 1, &hstlen);
1031 bzero(&hst[hstlen], MNAMELEN - hstlen);
1032 args.hostname = hst;
1033 /* sockargs() call must be after above copyin() calls */
1034 error = getsockaddr(&nam, (caddr_t)args.addr,
1039 if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
1040 &args.fhsize) == 0) {
1041 if (args.fhsize < 0 || args.fhsize > NFSX_FHMAX) {
1042 vfs_mount_error(mp, "Bad file handle");
1046 bcopy(args.fh, nfh, args.fhsize);
1050 (void) vfs_getopt(mp->mnt_optnew, "hostname",
1051 (void **)&args.hostname, &len);
1052 if (args.hostname == NULL) {
1053 vfs_mount_error(mp, "Invalid hostname");
1057 bcopy(args.hostname, hst, MNAMELEN);
1058 hst[MNAMELEN - 1] = '\0';
1061 if (vfs_getopt(mp->mnt_optnew, "principal", (void **)&name, NULL) == 0)
1062 strlcpy(srvkrbname, name, sizeof (srvkrbname));
1064 snprintf(srvkrbname, sizeof (srvkrbname), "nfs@%s", hst);
1065 srvkrbnamelen = strlen(srvkrbname);
1067 if (vfs_getopt(mp->mnt_optnew, "gssname", (void **)&name, NULL) == 0)
1068 strlcpy(krbname, name, sizeof (krbname));
1071 krbnamelen = strlen(krbname);
1073 if (vfs_getopt(mp->mnt_optnew, "dirpath", (void **)&name, NULL) == 0)
1074 strlcpy(dirpath, name, sizeof (dirpath));
1077 dirlen = strlen(dirpath);
1079 if (has_nfs_args_opt == 0) {
1080 if (vfs_getopt(mp->mnt_optnew, "addr",
1081 (void **)&args.addr, &args.addrlen) == 0) {
1082 if (args.addrlen > SOCK_MAXADDRLEN) {
1083 error = ENAMETOOLONG;
1086 nam = malloc(args.addrlen, M_SONAME, M_WAITOK);
1087 bcopy(args.addr, nam, args.addrlen);
1088 nam->sa_len = args.addrlen;
1090 vfs_mount_error(mp, "No server address");
1097 error = mountnfs(&args, mp, nam, hst, krbname, krbnamelen, dirpath,
1098 dirlen, srvkrbname, srvkrbnamelen, &vp, td->td_ucred, td,
1103 mp->mnt_kern_flag |= (MNTK_MPSAFE|MNTK_LOOKUP_SHARED);
1114 * It seems a bit dumb to copyinstr() the host and path here and then
1115 * bcopy() them in mountnfs(), but I wanted to detect errors before
1116 * doing the sockargs() call because sockargs() allocates an mbuf and
1117 * an error after that means that I have to release the mbuf.
1121 nfs_cmount(struct mntarg *ma, void *data, int flags)
1124 struct nfs_args args;
1126 error = copyin(data, &args, sizeof (struct nfs_args));
1130 ma = mount_arg(ma, "nfs_args", &args, sizeof args);
1132 error = kernel_mount(ma, flags);
1137 * Common code for mount and mountroot
1140 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
1141 char *hst, u_char *krbname, int krbnamelen, u_char *dirpath, int dirlen,
1142 u_char *srvkrbname, int srvkrbnamelen, struct vnode **vpp,
1143 struct ucred *cred, struct thread *td, int negnametimeo)
1145 struct nfsmount *nmp;
1147 int error, trycnt, ret;
1148 struct nfsvattr nfsva;
1149 static u_int64_t clval = 0;
1151 if (mp->mnt_flag & MNT_UPDATE) {
1153 printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
1154 FREE(nam, M_SONAME);
1157 MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount) +
1158 krbnamelen + dirlen + srvkrbnamelen + 2,
1159 M_NEWNFSMNT, M_WAITOK | M_ZERO);
1160 TAILQ_INIT(&nmp->nm_bufq);
1162 clval = (u_int64_t)nfsboottime.tv_sec;
1163 nmp->nm_clval = clval++;
1164 nmp->nm_krbnamelen = krbnamelen;
1165 nmp->nm_dirpathlen = dirlen;
1166 nmp->nm_srvkrbnamelen = srvkrbnamelen;
1167 if (td->td_ucred->cr_uid != (uid_t)0) {
1169 * nm_uid is used to get KerberosV credentials for
1170 * the nfsv4 state handling operations if there is
1171 * no host based principal set. Use the uid of
1172 * this user if not root, since they are doing the
1173 * mount. I don't think setting this for root will
1174 * work, since root normally does not have user
1175 * credentials in a credentials cache.
1177 nmp->nm_uid = td->td_ucred->cr_uid;
1180 * Just set to -1, so it won't be used.
1182 nmp->nm_uid = (uid_t)-1;
1185 /* Copy and null terminate all the names */
1186 if (nmp->nm_krbnamelen > 0) {
1187 bcopy(krbname, nmp->nm_krbname, nmp->nm_krbnamelen);
1188 nmp->nm_name[nmp->nm_krbnamelen] = '\0';
1190 if (nmp->nm_dirpathlen > 0) {
1191 bcopy(dirpath, NFSMNT_DIRPATH(nmp),
1192 nmp->nm_dirpathlen);
1193 nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1196 if (nmp->nm_srvkrbnamelen > 0) {
1197 bcopy(srvkrbname, NFSMNT_SRVKRBNAME(nmp),
1198 nmp->nm_srvkrbnamelen);
1199 nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1200 + nmp->nm_srvkrbnamelen + 2] = '\0';
1202 nmp->nm_sockreq.nr_cred = crhold(cred);
1203 mtx_init(&nmp->nm_sockreq.nr_mtx, "nfssock", NULL, MTX_DEF);
1205 nmp->nm_getinfo = nfs_getnlminfo;
1206 nmp->nm_vinvalbuf = ncl_vinvalbuf;
1209 nmp->nm_mountp = mp;
1210 mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF | MTX_DUPOK);
1211 nmp->nm_negnametimeo = negnametimeo;
1213 nfs_decode_args(mp, nmp, argp, hst, cred, td);
1216 * V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too
1217 * high, depending on whether we end up with negative offsets in
1218 * the client or server somewhere. 2GB-1 may be safer.
1220 * For V3, ncl_fsinfo will adjust this as necessary. Assume maximum
1221 * that we can handle until we find out otherwise.
1222 * XXX Our "safe" limit on the client is what we can store in our
1223 * buffer cache using signed(!) block numbers.
1225 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0)
1226 nmp->nm_maxfilesize = 0xffffffffLL;
1228 nmp->nm_maxfilesize = OFF_MAX;
1230 nmp->nm_timeo = NFS_TIMEO;
1231 nmp->nm_retry = NFS_RETRANS;
1232 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
1233 nmp->nm_wsize = NFS_WSIZE;
1234 nmp->nm_rsize = NFS_RSIZE;
1235 nmp->nm_readdirsize = NFS_READDIRSIZE;
1237 nmp->nm_wcommitsize = hibufspace / (desiredvnodes / 1000);
1238 nmp->nm_numgrps = NFS_MAXGRPS;
1239 nmp->nm_readahead = NFS_DEFRAHEAD;
1240 nmp->nm_tprintf_delay = nfs_tprintf_delay;
1241 if (nmp->nm_tprintf_delay < 0)
1242 nmp->nm_tprintf_delay = 0;
1243 nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
1244 if (nmp->nm_tprintf_initial_delay < 0)
1245 nmp->nm_tprintf_initial_delay = 0;
1246 nmp->nm_fhsize = argp->fhsize;
1247 if (nmp->nm_fhsize > 0)
1248 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
1249 bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
1251 /* Set up the sockets and per-host congestion */
1252 nmp->nm_sotype = argp->sotype;
1253 nmp->nm_soproto = argp->proto;
1254 nmp->nm_sockreq.nr_prog = NFS_PROG;
1255 if ((argp->flags & NFSMNT_NFSV4))
1256 nmp->nm_sockreq.nr_vers = NFS_VER4;
1257 else if ((argp->flags & NFSMNT_NFSV3))
1258 nmp->nm_sockreq.nr_vers = NFS_VER3;
1260 nmp->nm_sockreq.nr_vers = NFS_VER2;
1263 if ((error = newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0)))
1267 * A reference count is needed on the nfsnode representing the
1268 * remote root. If this object is not persistent, then backward
1269 * traversals of the mount point (i.e. "..") will not work if
1270 * the nfsnode gets flushed out of the cache. Ufs does not have
1271 * this problem, because one can identify root inodes by their
1272 * number == ROOTINO (2).
1274 if (nmp->nm_fhsize == 0 && (nmp->nm_flag & NFSMNT_NFSV4) &&
1275 nmp->nm_dirpathlen > 0) {
1277 * If the fhsize on the mount point == 0 for V4, the mount
1278 * path needs to be looked up.
1282 error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp),
1285 (void) nfs_catnap(PZERO, error, "nfsgetdirp");
1286 } while (error && --trycnt > 0);
1288 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
1292 if (nmp->nm_fhsize > 0) {
1294 * Set f_iosize to NFS_DIRBLKSIZ so that bo_bsize gets set
1295 * non-zero for the root vnode. f_iosize will be set correctly
1296 * by nfs_statfs() before any I/O occurs.
1298 mp->mnt_stat.f_iosize = NFS_DIRBLKSIZ;
1299 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np,
1306 * Get file attributes and transfer parameters for the
1307 * mountpoint. This has the side effect of filling in
1308 * (*vpp)->v_type with the correct value.
1310 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
1311 cred, td, &nfsva, NULL);
1314 * Just set default values to get things going.
1316 NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
1317 nfsva.na_vattr.va_type = VDIR;
1318 nfsva.na_vattr.va_mode = 0777;
1319 nfsva.na_vattr.va_nlink = 100;
1320 nfsva.na_vattr.va_uid = (uid_t)0;
1321 nfsva.na_vattr.va_gid = (gid_t)0;
1322 nfsva.na_vattr.va_fileid = 2;
1323 nfsva.na_vattr.va_gen = 1;
1324 nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
1325 nfsva.na_vattr.va_size = 512 * 1024;
1327 (void) nfscl_loadattrcache(vpp, &nfsva, NULL, NULL, 0, 1);
1328 if (argp->flags & NFSMNT_NFSV3)
1329 ncl_fsinfo(nmp, *vpp, cred, td);
1331 /* Mark if the mount point supports NFSv4 ACLs. */
1332 if ((argp->flags & NFSMNT_NFSV4) != 0 && nfsrv_useacl != 0 &&
1334 NFSISSET_ATTRBIT(&nfsva.na_suppattr, NFSATTRBIT_ACL)) {
1336 mp->mnt_flag |= MNT_NFS4ACLS;
1341 * Lose the lock but keep the ref.
1343 VOP_UNLOCK(*vpp, 0);
1349 newnfs_disconnect(&nmp->nm_sockreq);
1350 crfree(nmp->nm_sockreq.nr_cred);
1351 mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1352 mtx_destroy(&nmp->nm_mtx);
1353 FREE(nmp, M_NEWNFSMNT);
1354 FREE(nam, M_SONAME);
1359 * unmount system call
1362 nfs_unmount(struct mount *mp, int mntflags)
1365 struct nfsmount *nmp;
1366 int error, flags = 0, trycnt = 0;
1370 if (mntflags & MNT_FORCE)
1371 flags |= FORCECLOSE;
1374 * Goes something like this..
1375 * - Call vflush() to clear out vnodes for this filesystem
1376 * - Close the socket
1377 * - Free up the data structures
1379 /* In the forced case, cancel any outstanding requests. */
1380 if (mntflags & MNT_FORCE) {
1381 error = newnfs_nmcancelreqs(nmp);
1384 /* For a forced close, get rid of the renew thread now */
1385 nfscl_umount(nmp, td);
1387 /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
1389 error = vflush(mp, 1, flags, td);
1390 if ((mntflags & MNT_FORCE) && error != 0 && ++trycnt < 30)
1391 (void) nfs_catnap(PSOCK, error, "newndm");
1392 } while ((mntflags & MNT_FORCE) && error != 0 && trycnt < 30);
1397 * We are now committed to the unmount.
1399 if ((mntflags & MNT_FORCE) == 0)
1400 nfscl_umount(nmp, td);
1401 newnfs_disconnect(&nmp->nm_sockreq);
1402 crfree(nmp->nm_sockreq.nr_cred);
1403 FREE(nmp->nm_nam, M_SONAME);
1405 mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1406 mtx_destroy(&nmp->nm_mtx);
1407 FREE(nmp, M_NEWNFSMNT);
1413 * Return root of a filesystem
1416 nfs_root(struct mount *mp, int flags, struct vnode **vpp)
1419 struct nfsmount *nmp;
1424 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, flags);
1429 * Get transfer parameters and attributes for root vnode once.
1431 mtx_lock(&nmp->nm_mtx);
1432 if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
1433 mtx_unlock(&nmp->nm_mtx);
1434 ncl_fsinfo(nmp, vp, curthread->td_ucred, curthread);
1436 mtx_unlock(&nmp->nm_mtx);
1437 if (vp->v_type == VNON)
1439 vp->v_vflag |= VV_ROOT;
1445 * Flush out the buffer cache
1449 nfs_sync(struct mount *mp, int waitfor)
1451 struct vnode *vp, *mvp;
1453 int error, allerror = 0;
1459 * If a forced dismount is in progress, return from here so that
1460 * the umount(2) syscall doesn't get stuck in VFS_SYNC() before
1461 * calling VFS_UNMOUNT().
1463 if ((mp->mnt_kern_flag & MNTK_UNMOUNTF) != 0) {
1469 * Force stale buffer cache information to be flushed.
1472 MNT_VNODE_FOREACH(vp, mp, mvp) {
1475 /* XXX Racy bv_cnt check. */
1476 if (VOP_ISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
1477 waitfor == MNT_LAZY) {
1482 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
1484 MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp);
1487 error = VOP_FSYNC(vp, waitfor, td);
1500 nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
1502 struct nfsmount *nmp = VFSTONFS(mp);
1506 bzero(&vq, sizeof(vq));
1509 case VFS_CTL_NOLOCKS:
1510 val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
1511 if (req->oldptr != NULL) {
1512 error = SYSCTL_OUT(req, &val, sizeof(val));
1516 if (req->newptr != NULL) {
1517 error = SYSCTL_IN(req, &val, sizeof(val));
1521 nmp->nm_flag |= NFSMNT_NOLOCKS;
1523 nmp->nm_flag &= ~NFSMNT_NOLOCKS;
1528 mtx_lock(&nmp->nm_mtx);
1529 if (nmp->nm_state & NFSSTA_TIMEO)
1530 vq.vq_flags |= VQ_NOTRESP;
1531 mtx_unlock(&nmp->nm_mtx);
1533 if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
1534 (nmp->nm_state & NFSSTA_LOCKTIMEO))
1535 vq.vq_flags |= VQ_NOTRESPLOCK;
1537 error = SYSCTL_OUT(req, &vq, sizeof(vq));
1540 if (req->oldptr != NULL) {
1541 error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
1542 sizeof(nmp->nm_tprintf_initial_delay));
1546 if (req->newptr != NULL) {
1547 error = vfs_suser(mp, req->td);
1550 error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
1551 sizeof(nmp->nm_tprintf_initial_delay));
1554 if (nmp->nm_tprintf_initial_delay < 0)
1555 nmp->nm_tprintf_initial_delay = 0;
1565 * Extract the information needed by the nlm from the nfs vnode.
1568 nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp,
1569 struct sockaddr_storage *sp, int *is_v3p, off_t *sizep,
1570 struct timeval *timeop)
1572 struct nfsmount *nmp;
1573 struct nfsnode *np = VTONFS(vp);
1575 nmp = VFSTONFS(vp->v_mount);
1577 *fhlenp = (size_t)np->n_fhp->nfh_len;
1579 bcopy(np->n_fhp->nfh_fh, fhp, np->n_fhp->nfh_len);
1581 bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp)));
1583 *is_v3p = NFS_ISV3(vp);
1585 *sizep = np->n_size;
1586 if (timeop != NULL) {
1587 timeop->tv_sec = nmp->nm_timeo / NFS_HZ;
1588 timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ);