]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/fs/nfsclient/nfs_clvfsops.c
THIS BRANCH IS OBSOLETE, PLEASE READ:
[FreeBSD/FreeBSD.git] / sys / fs / nfsclient / nfs_clvfsops.c
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 1989, 1993, 1995
5  *      The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Rick Macklem at The University of Guelph.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  *      from nfs_vfsops.c       8.12 (Berkeley) 5/20/95
35  */
36
37 #include <sys/cdefs.h>
38 __FBSDID("$FreeBSD$");
39
40 #include "opt_bootp.h"
41 #include "opt_nfsroot.h"
42 #include "opt_kern_tls.h"
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/kernel.h>
47 #include <sys/bio.h>
48 #include <sys/buf.h>
49 #include <sys/clock.h>
50 #include <sys/jail.h>
51 #include <sys/limits.h>
52 #include <sys/lock.h>
53 #include <sys/malloc.h>
54 #include <sys/mbuf.h>
55 #include <sys/module.h>
56 #include <sys/mount.h>
57 #include <sys/proc.h>
58 #include <sys/socket.h>
59 #include <sys/socketvar.h>
60 #include <sys/sockio.h>
61 #include <sys/sysctl.h>
62 #include <sys/vnode.h>
63 #include <sys/signalvar.h>
64
65 #include <vm/vm.h>
66 #include <vm/vm_extern.h>
67 #include <vm/uma.h>
68
69 #include <net/if.h>
70 #include <net/route.h>
71 #include <net/route/route_ctl.h>
72 #include <netinet/in.h>
73
74 #include <fs/nfs/nfsport.h>
75 #include <fs/nfsclient/nfsnode.h>
76 #include <fs/nfsclient/nfsmount.h>
77 #include <fs/nfsclient/nfs.h>
78 #include <nfs/nfsdiskless.h>
79
80 #include <rpc/rpcsec_tls.h>
81
82 FEATURE(nfscl, "NFSv4 client");
83
84 extern int nfscl_ticks;
85 extern struct timeval nfsboottime;
86 extern int nfsrv_useacl;
87 extern int nfscl_debuglevel;
88 extern enum nfsiod_state ncl_iodwant[NFS_MAXASYNCDAEMON];
89 extern struct nfsmount *ncl_iodmount[NFS_MAXASYNCDAEMON];
90 extern struct mtx ncl_iod_mutex;
91 NFSCLSTATEMUTEX;
92 extern struct mtx nfsrv_dslock_mtx;
93
94 MALLOC_DEFINE(M_NEWNFSREQ, "newnfsclient_req", "NFS request header");
95 MALLOC_DEFINE(M_NEWNFSMNT, "newnfsmnt", "NFS mount struct");
96
97 SYSCTL_DECL(_vfs_nfs);
98 static int nfs_ip_paranoia = 1;
99 SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW,
100     &nfs_ip_paranoia, 0, "");
101 static int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
102 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_INITIAL_DELAY,
103         downdelayinitial, CTLFLAG_RW, &nfs_tprintf_initial_delay, 0, "");
104 /* how long between console messages "nfs server foo not responding" */
105 static int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
106 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_DELAY,
107         downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0, "");
108 #ifdef NFS_DEBUG
109 int nfs_debug;
110 SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0,
111     "Toggle debug flag");
112 #endif
113
114 static int      nfs_mountroot(struct mount *);
115 static void     nfs_sec_name(char *, int *);
116 static void     nfs_decode_args(struct mount *mp, struct nfsmount *nmp,
117                     struct nfs_args *argp, const char *, struct ucred *,
118                     struct thread *);
119 static int      mountnfs(struct nfs_args *, struct mount *,
120                     struct sockaddr *, char *, u_char *, int, u_char *, int,
121                     u_char *, int, struct vnode **, struct ucred *,
122                     struct thread *, int, int, int, uint32_t);
123 static void     nfs_getnlminfo(struct vnode *, uint8_t *, size_t *,
124                     struct sockaddr_storage *, int *, off_t *,
125                     struct timeval *);
126 static vfs_mount_t nfs_mount;
127 static vfs_cmount_t nfs_cmount;
128 static vfs_unmount_t nfs_unmount;
129 static vfs_root_t nfs_root;
130 static vfs_statfs_t nfs_statfs;
131 static vfs_sync_t nfs_sync;
132 static vfs_sysctl_t nfs_sysctl;
133 static vfs_purge_t nfs_purge;
134
135 /*
136  * nfs vfs operations.
137  */
138 static struct vfsops nfs_vfsops = {
139         .vfs_init =             ncl_init,
140         .vfs_mount =            nfs_mount,
141         .vfs_cmount =           nfs_cmount,
142         .vfs_root =             vfs_cache_root,
143         .vfs_cachedroot =       nfs_root,
144         .vfs_statfs =           nfs_statfs,
145         .vfs_sync =             nfs_sync,
146         .vfs_uninit =           ncl_uninit,
147         .vfs_unmount =          nfs_unmount,
148         .vfs_sysctl =           nfs_sysctl,
149         .vfs_purge =            nfs_purge,
150 };
151 VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK | VFCF_SBDRY);
152
153 /* So that loader and kldload(2) can find us, wherever we are.. */
154 MODULE_VERSION(nfs, 1);
155 MODULE_DEPEND(nfs, nfscommon, 1, 1, 1);
156 MODULE_DEPEND(nfs, krpc, 1, 1, 1);
157 MODULE_DEPEND(nfs, nfssvc, 1, 1, 1);
158
159 /*
160  * This structure is now defined in sys/nfs/nfs_diskless.c so that it
161  * can be shared by both NFS clients. It is declared here so that it
162  * will be defined for kernels built without NFS_ROOT, although it
163  * isn't used in that case.
164  */
165 #if !defined(NFS_ROOT)
166 struct nfs_diskless     nfs_diskless = { { { 0 } } };
167 struct nfsv3_diskless   nfsv3_diskless = { { { 0 } } };
168 int                     nfs_diskless_valid = 0;
169 #endif
170
171 SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
172     &nfs_diskless_valid, 0,
173     "Has the diskless struct been filled correctly");
174
175 SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
176     nfsv3_diskless.root_hostnam, 0, "Path to nfs root");
177
178 SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
179     &nfsv3_diskless.root_saddr, sizeof(nfsv3_diskless.root_saddr),
180     "%Ssockaddr_in", "Diskless root nfs address");
181
182 void            newnfsargs_ntoh(struct nfs_args *);
183 static int      nfs_mountdiskless(char *,
184                     struct sockaddr_in *, struct nfs_args *,
185                     struct thread *, struct vnode **, struct mount *);
186 static void     nfs_convert_diskless(void);
187 static void     nfs_convert_oargs(struct nfs_args *args,
188                     struct onfs_args *oargs);
189
190 int
191 newnfs_iosize(struct nfsmount *nmp)
192 {
193         int iosize, maxio;
194
195         /* First, set the upper limit for iosize */
196         if (nmp->nm_flag & NFSMNT_NFSV4) {
197                 maxio = NFS_MAXBSIZE;
198         } else if (nmp->nm_flag & NFSMNT_NFSV3) {
199                 if (nmp->nm_sotype == SOCK_DGRAM)
200                         maxio = NFS_MAXDGRAMDATA;
201                 else
202                         maxio = NFS_MAXBSIZE;
203         } else {
204                 maxio = NFS_V2MAXDATA;
205         }
206         if (nmp->nm_rsize > maxio || nmp->nm_rsize == 0)
207                 nmp->nm_rsize = maxio;
208         if (nmp->nm_rsize > NFS_MAXBSIZE)
209                 nmp->nm_rsize = NFS_MAXBSIZE;
210         if (nmp->nm_readdirsize > maxio || nmp->nm_readdirsize == 0)
211                 nmp->nm_readdirsize = maxio;
212         if (nmp->nm_readdirsize > nmp->nm_rsize)
213                 nmp->nm_readdirsize = nmp->nm_rsize;
214         if (nmp->nm_wsize > maxio || nmp->nm_wsize == 0)
215                 nmp->nm_wsize = maxio;
216         if (nmp->nm_wsize > NFS_MAXBSIZE)
217                 nmp->nm_wsize = NFS_MAXBSIZE;
218
219         /*
220          * Calculate the size used for io buffers.  Use the larger
221          * of the two sizes to minimise nfs requests but make sure
222          * that it is at least one VM page to avoid wasting buffer
223          * space.  It must also be at least NFS_DIRBLKSIZ, since
224          * that is the buffer size used for directories.
225          */
226         iosize = imax(nmp->nm_rsize, nmp->nm_wsize);
227         iosize = imax(iosize, PAGE_SIZE);
228         iosize = imax(iosize, NFS_DIRBLKSIZ);
229         nmp->nm_mountp->mnt_stat.f_iosize = iosize;
230         return (iosize);
231 }
232
233 static void
234 nfs_convert_oargs(struct nfs_args *args, struct onfs_args *oargs)
235 {
236
237         args->version = NFS_ARGSVERSION;
238         args->addr = oargs->addr;
239         args->addrlen = oargs->addrlen;
240         args->sotype = oargs->sotype;
241         args->proto = oargs->proto;
242         args->fh = oargs->fh;
243         args->fhsize = oargs->fhsize;
244         args->flags = oargs->flags;
245         args->wsize = oargs->wsize;
246         args->rsize = oargs->rsize;
247         args->readdirsize = oargs->readdirsize;
248         args->timeo = oargs->timeo;
249         args->retrans = oargs->retrans;
250         args->readahead = oargs->readahead;
251         args->hostname = oargs->hostname;
252 }
253
254 static void
255 nfs_convert_diskless(void)
256 {
257
258         bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
259                 sizeof(struct ifaliasreq));
260         bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
261                 sizeof(struct sockaddr_in));
262         nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
263         if (nfsv3_diskless.root_args.flags & NFSMNT_NFSV3) {
264                 nfsv3_diskless.root_fhsize = NFSX_MYFH;
265                 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_MYFH);
266         } else {
267                 nfsv3_diskless.root_fhsize = NFSX_V2FH;
268                 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
269         }
270         bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
271                 sizeof(struct sockaddr_in));
272         bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN);
273         nfsv3_diskless.root_time = nfs_diskless.root_time;
274         bcopy(nfs_diskless.my_hostnam, nfsv3_diskless.my_hostnam,
275                 MAXHOSTNAMELEN);
276         nfs_diskless_valid = 3;
277 }
278
279 /*
280  * nfs statfs call
281  */
282 static int
283 nfs_statfs(struct mount *mp, struct statfs *sbp)
284 {
285         struct vnode *vp;
286         struct thread *td;
287         struct nfsmount *nmp = VFSTONFS(mp);
288         struct nfsvattr nfsva;
289         struct nfsfsinfo fs;
290         struct nfsstatfs sb;
291         int error = 0, attrflag, gotfsinfo = 0, ret;
292         struct nfsnode *np;
293
294         td = curthread;
295
296         error = vfs_busy(mp, MBF_NOWAIT);
297         if (error)
298                 return (error);
299         error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
300         if (error) {
301                 vfs_unbusy(mp);
302                 return (error);
303         }
304         vp = NFSTOV(np);
305         mtx_lock(&nmp->nm_mtx);
306         if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
307                 mtx_unlock(&nmp->nm_mtx);
308                 error = nfsrpc_fsinfo(vp, &fs, td->td_ucred, td, &nfsva,
309                     &attrflag, NULL);
310                 if (!error)
311                         gotfsinfo = 1;
312         } else
313                 mtx_unlock(&nmp->nm_mtx);
314         if (!error)
315                 error = nfsrpc_statfs(vp, &sb, &fs, td->td_ucred, td, &nfsva,
316                     &attrflag, NULL);
317         if (error != 0)
318                 NFSCL_DEBUG(2, "statfs=%d\n", error);
319         if (attrflag == 0) {
320                 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
321                     td->td_ucred, td, &nfsva, NULL, NULL);
322                 if (ret) {
323                         /*
324                          * Just set default values to get things going.
325                          */
326                         NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
327                         nfsva.na_vattr.va_type = VDIR;
328                         nfsva.na_vattr.va_mode = 0777;
329                         nfsva.na_vattr.va_nlink = 100;
330                         nfsva.na_vattr.va_uid = (uid_t)0;
331                         nfsva.na_vattr.va_gid = (gid_t)0;
332                         nfsva.na_vattr.va_fileid = 2;
333                         nfsva.na_vattr.va_gen = 1;
334                         nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
335                         nfsva.na_vattr.va_size = 512 * 1024;
336                 }
337         }
338         (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
339         if (!error) {
340             mtx_lock(&nmp->nm_mtx);
341             if (gotfsinfo || (nmp->nm_flag & NFSMNT_NFSV4))
342                 nfscl_loadfsinfo(nmp, &fs);
343             nfscl_loadsbinfo(nmp, &sb, sbp);
344             sbp->f_iosize = newnfs_iosize(nmp);
345             mtx_unlock(&nmp->nm_mtx);
346             if (sbp != &mp->mnt_stat) {
347                 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
348                 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
349             }
350             strncpy(&sbp->f_fstypename[0], mp->mnt_vfc->vfc_name, MFSNAMELEN);
351         } else if (NFS_ISV4(vp)) {
352                 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
353         }
354         vput(vp);
355         vfs_unbusy(mp);
356         return (error);
357 }
358
359 /*
360  * nfs version 3 fsinfo rpc call
361  */
362 int
363 ncl_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred,
364     struct thread *td)
365 {
366         struct nfsfsinfo fs;
367         struct nfsvattr nfsva;
368         int error, attrflag;
369
370         error = nfsrpc_fsinfo(vp, &fs, cred, td, &nfsva, &attrflag, NULL);
371         if (!error) {
372                 if (attrflag)
373                         (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0,
374                             1);
375                 mtx_lock(&nmp->nm_mtx);
376                 nfscl_loadfsinfo(nmp, &fs);
377                 mtx_unlock(&nmp->nm_mtx);
378         }
379         return (error);
380 }
381
382 /*
383  * Mount a remote root fs via. nfs. This depends on the info in the
384  * nfs_diskless structure that has been filled in properly by some primary
385  * bootstrap.
386  * It goes something like this:
387  * - do enough of "ifconfig" by calling ifioctl() so that the system
388  *   can talk to the server
389  * - If nfs_diskless.mygateway is filled in, use that address as
390  *   a default gateway.
391  * - build the rootfs mount point and call mountnfs() to do the rest.
392  *
393  * It is assumed to be safe to read, modify, and write the nfsv3_diskless
394  * structure, as well as other global NFS client variables here, as
395  * nfs_mountroot() will be called once in the boot before any other NFS
396  * client activity occurs.
397  */
398 static int
399 nfs_mountroot(struct mount *mp)
400 {
401         struct thread *td = curthread;
402         struct nfsv3_diskless *nd = &nfsv3_diskless;
403         struct socket *so;
404         struct vnode *vp;
405         struct ifreq ir;
406         int error;
407         u_long l;
408         char buf[128];
409         char *cp;
410
411 #if defined(BOOTP_NFSROOT) && defined(BOOTP)
412         bootpc_init();          /* use bootp to get nfs_diskless filled in */
413 #elif defined(NFS_ROOT)
414         nfs_setup_diskless();
415 #endif
416
417         if (nfs_diskless_valid == 0)
418                 return (-1);
419         if (nfs_diskless_valid == 1)
420                 nfs_convert_diskless();
421
422         /*
423          * Do enough of ifconfig(8) so that the critical net interface can
424          * talk to the server.
425          */
426         error = socreate(nd->myif.ifra_addr.sa_family, &so, nd->root_args.sotype, 0,
427             td->td_ucred, td);
428         if (error)
429                 panic("nfs_mountroot: socreate(%04x): %d",
430                         nd->myif.ifra_addr.sa_family, error);
431
432 #if 0 /* XXX Bad idea */
433         /*
434          * We might not have been told the right interface, so we pass
435          * over the first ten interfaces of the same kind, until we get
436          * one of them configured.
437          */
438
439         for (i = strlen(nd->myif.ifra_name) - 1;
440                 nd->myif.ifra_name[i] >= '0' &&
441                 nd->myif.ifra_name[i] <= '9';
442                 nd->myif.ifra_name[i] ++) {
443                 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
444                 if(!error)
445                         break;
446         }
447 #endif
448         error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
449         if (error)
450                 panic("nfs_mountroot: SIOCAIFADDR: %d", error);
451         if ((cp = kern_getenv("boot.netif.mtu")) != NULL) {
452                 ir.ifr_mtu = strtol(cp, NULL, 10);
453                 bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ);
454                 freeenv(cp);
455                 error = ifioctl(so, SIOCSIFMTU, (caddr_t)&ir, td);
456                 if (error)
457                         printf("nfs_mountroot: SIOCSIFMTU: %d", error);
458         }
459         soclose(so);
460
461         /*
462          * If the gateway field is filled in, set it as the default route.
463          * Note that pxeboot will set a default route of 0 if the route
464          * is not set by the DHCP server.  Check also for a value of 0
465          * to avoid panicking inappropriately in that situation.
466          */
467         if (nd->mygateway.sin_len != 0 &&
468             nd->mygateway.sin_addr.s_addr != 0) {
469                 struct sockaddr_in mask, sin;
470                 struct epoch_tracker et;
471                 struct rt_addrinfo info;
472                 struct rib_cmd_info rc;
473
474                 bzero((caddr_t)&mask, sizeof(mask));
475                 sin = mask;
476                 sin.sin_family = AF_INET;
477                 sin.sin_len = sizeof(sin);
478                 /* XXX MRT use table 0 for this sort of thing */
479                 NET_EPOCH_ENTER(et);
480                 CURVNET_SET(TD_TO_VNET(td));
481
482                 bzero((caddr_t)&info, sizeof(info));
483                 info.rti_flags = RTF_UP | RTF_GATEWAY;
484                 info.rti_info[RTAX_DST] = (struct sockaddr *)&sin;
485                 info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&nd->mygateway;
486                 info.rti_info[RTAX_NETMASK] = (struct sockaddr *)&mask;
487
488                 error = rib_action(RT_DEFAULT_FIB, RTM_ADD, &info, &rc);
489                 CURVNET_RESTORE();
490                 NET_EPOCH_EXIT(et);
491                 if (error)
492                         panic("nfs_mountroot: RTM_ADD: %d", error);
493         }
494
495         /*
496          * Create the rootfs mount point.
497          */
498         nd->root_args.fh = nd->root_fh;
499         nd->root_args.fhsize = nd->root_fhsize;
500         l = ntohl(nd->root_saddr.sin_addr.s_addr);
501         snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
502                 (l >> 24) & 0xff, (l >> 16) & 0xff,
503                 (l >>  8) & 0xff, (l >>  0) & 0xff, nd->root_hostnam);
504         printf("NFS ROOT: %s\n", buf);
505         nd->root_args.hostname = buf;
506         if ((error = nfs_mountdiskless(buf,
507             &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) {
508                 return (error);
509         }
510
511         /*
512          * This is not really an nfs issue, but it is much easier to
513          * set hostname here and then let the "/etc/rc.xxx" files
514          * mount the right /var based upon its preset value.
515          */
516         mtx_lock(&prison0.pr_mtx);
517         strlcpy(prison0.pr_hostname, nd->my_hostnam,
518             sizeof(prison0.pr_hostname));
519         mtx_unlock(&prison0.pr_mtx);
520         inittodr(ntohl(nd->root_time));
521         return (0);
522 }
523
524 /*
525  * Internal version of mount system call for diskless setup.
526  */
527 static int
528 nfs_mountdiskless(char *path,
529     struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
530     struct vnode **vpp, struct mount *mp)
531 {
532         struct sockaddr *nam;
533         int dirlen, error;
534         char *dirpath;
535
536         /*
537          * Find the directory path in "path", which also has the server's
538          * name/ip address in it.
539          */
540         dirpath = strchr(path, ':');
541         if (dirpath != NULL)
542                 dirlen = strlen(++dirpath);
543         else
544                 dirlen = 0;
545         nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
546         if ((error = mountnfs(args, mp, nam, path, NULL, 0, dirpath, dirlen,
547             NULL, 0, vpp, td->td_ucred, td, NFS_DEFAULT_NAMETIMEO, 
548             NFS_DEFAULT_NEGNAMETIMEO, 0, 0)) != 0) {
549                 printf("nfs_mountroot: mount %s on /: %d\n", path, error);
550                 return (error);
551         }
552         return (0);
553 }
554
555 static void
556 nfs_sec_name(char *sec, int *flagsp)
557 {
558         if (!strcmp(sec, "krb5"))
559                 *flagsp |= NFSMNT_KERB;
560         else if (!strcmp(sec, "krb5i"))
561                 *flagsp |= (NFSMNT_KERB | NFSMNT_INTEGRITY);
562         else if (!strcmp(sec, "krb5p"))
563                 *flagsp |= (NFSMNT_KERB | NFSMNT_PRIVACY);
564 }
565
566 static void
567 nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
568     const char *hostname, struct ucred *cred, struct thread *td)
569 {
570         int adjsock;
571         char *p;
572
573         /*
574          * Set read-only flag if requested; otherwise, clear it if this is
575          * an update.  If this is not an update, then either the read-only
576          * flag is already clear, or this is a root mount and it was set
577          * intentionally at some previous point.
578          */
579         if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) {
580                 MNT_ILOCK(mp);
581                 mp->mnt_flag |= MNT_RDONLY;
582                 MNT_IUNLOCK(mp);
583         } else if (mp->mnt_flag & MNT_UPDATE) {
584                 MNT_ILOCK(mp);
585                 mp->mnt_flag &= ~MNT_RDONLY;
586                 MNT_IUNLOCK(mp);
587         }
588
589         /*
590          * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
591          * no sense in that context.  Also, set up appropriate retransmit
592          * and soft timeout behavior.
593          */
594         if (argp->sotype == SOCK_STREAM) {
595                 nmp->nm_flag &= ~NFSMNT_NOCONN;
596                 nmp->nm_timeo = NFS_MAXTIMEO;
597                 if ((argp->flags & NFSMNT_NFSV4) != 0)
598                         nmp->nm_retry = INT_MAX;
599                 else
600                         nmp->nm_retry = NFS_RETRANS_TCP;
601         }
602
603         /* Also clear RDIRPLUS if NFSv2, it crashes some servers */
604         if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
605                 argp->flags &= ~NFSMNT_RDIRPLUS;
606                 nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
607         }
608
609         /* Clear ONEOPENOWN for NFSv2, 3 and 4.0. */
610         if (nmp->nm_minorvers == 0) {
611                 argp->flags &= ~NFSMNT_ONEOPENOWN;
612                 nmp->nm_flag &= ~NFSMNT_ONEOPENOWN;
613         }
614
615         /* Re-bind if rsrvd port requested and wasn't on one */
616         adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
617                   && (argp->flags & NFSMNT_RESVPORT);
618         /* Also re-bind if we're switching to/from a connected UDP socket */
619         adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
620                     (argp->flags & NFSMNT_NOCONN));
621
622         /* Update flags atomically.  Don't change the lock bits. */
623         nmp->nm_flag = argp->flags | nmp->nm_flag;
624
625         if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
626                 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
627                 if (nmp->nm_timeo < NFS_MINTIMEO)
628                         nmp->nm_timeo = NFS_MINTIMEO;
629                 else if (nmp->nm_timeo > NFS_MAXTIMEO)
630                         nmp->nm_timeo = NFS_MAXTIMEO;
631         }
632
633         if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
634                 nmp->nm_retry = argp->retrans;
635                 if (nmp->nm_retry > NFS_MAXREXMIT)
636                         nmp->nm_retry = NFS_MAXREXMIT;
637         }
638
639         if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
640                 nmp->nm_wsize = argp->wsize;
641                 /*
642                  * Clip at the power of 2 below the size. There is an
643                  * issue (not isolated) that causes intermittent page
644                  * faults if this is not done.
645                  */
646                 if (nmp->nm_wsize > NFS_FABLKSIZE)
647                         nmp->nm_wsize = 1 << (fls(nmp->nm_wsize) - 1);
648                 else
649                         nmp->nm_wsize = NFS_FABLKSIZE;
650         }
651
652         if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
653                 nmp->nm_rsize = argp->rsize;
654                 /*
655                  * Clip at the power of 2 below the size. There is an
656                  * issue (not isolated) that causes intermittent page
657                  * faults if this is not done.
658                  */
659                 if (nmp->nm_rsize > NFS_FABLKSIZE)
660                         nmp->nm_rsize = 1 << (fls(nmp->nm_rsize) - 1);
661                 else
662                         nmp->nm_rsize = NFS_FABLKSIZE;
663         }
664
665         if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
666                 nmp->nm_readdirsize = argp->readdirsize;
667         }
668
669         if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
670                 nmp->nm_acregmin = argp->acregmin;
671         else
672                 nmp->nm_acregmin = NFS_MINATTRTIMO;
673         if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
674                 nmp->nm_acregmax = argp->acregmax;
675         else
676                 nmp->nm_acregmax = NFS_MAXATTRTIMO;
677         if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
678                 nmp->nm_acdirmin = argp->acdirmin;
679         else
680                 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
681         if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
682                 nmp->nm_acdirmax = argp->acdirmax;
683         else
684                 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
685         if (nmp->nm_acdirmin > nmp->nm_acdirmax)
686                 nmp->nm_acdirmin = nmp->nm_acdirmax;
687         if (nmp->nm_acregmin > nmp->nm_acregmax)
688                 nmp->nm_acregmin = nmp->nm_acregmax;
689
690         if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
691                 if (argp->readahead <= NFS_MAXRAHEAD)
692                         nmp->nm_readahead = argp->readahead;
693                 else
694                         nmp->nm_readahead = NFS_MAXRAHEAD;
695         }
696         if ((argp->flags & NFSMNT_WCOMMITSIZE) && argp->wcommitsize >= 0) {
697                 if (argp->wcommitsize < nmp->nm_wsize)
698                         nmp->nm_wcommitsize = nmp->nm_wsize;
699                 else
700                         nmp->nm_wcommitsize = argp->wcommitsize;
701         }
702
703         adjsock |= ((nmp->nm_sotype != argp->sotype) ||
704                     (nmp->nm_soproto != argp->proto));
705
706         if (nmp->nm_client != NULL && adjsock) {
707                 int haslock = 0, error = 0;
708
709                 if (nmp->nm_sotype == SOCK_STREAM) {
710                         error = newnfs_sndlock(&nmp->nm_sockreq.nr_lock);
711                         if (!error)
712                                 haslock = 1;
713                 }
714                 if (!error) {
715                     newnfs_disconnect(&nmp->nm_sockreq);
716                     if (haslock)
717                         newnfs_sndunlock(&nmp->nm_sockreq.nr_lock);
718                     nmp->nm_sotype = argp->sotype;
719                     nmp->nm_soproto = argp->proto;
720                     if (nmp->nm_sotype == SOCK_DGRAM)
721                         while (newnfs_connect(nmp, &nmp->nm_sockreq,
722                             cred, td, 0, false)) {
723                                 printf("newnfs_args: retrying connect\n");
724                                 (void) nfs_catnap(PSOCK, 0, "nfscon");
725                         }
726                 }
727         } else {
728                 nmp->nm_sotype = argp->sotype;
729                 nmp->nm_soproto = argp->proto;
730         }
731
732         if (hostname != NULL) {
733                 strlcpy(nmp->nm_hostname, hostname,
734                     sizeof(nmp->nm_hostname));
735                 p = strchr(nmp->nm_hostname, ':');
736                 if (p != NULL)
737                         *p = '\0';
738         }
739 }
740
741 static const char *nfs_opts[] = { "from", "nfs_args",
742     "noac", "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
743     "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
744     "async", "noconn", "nolockd", "conn", "lockd", "intr", "rdirplus",
745     "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize",
746     "retrans", "actimeo", "acregmin", "acregmax", "acdirmin", "acdirmax",
747     "resvport", "readahead", "hostname", "timeo", "timeout", "addr", "fh",
748     "nfsv3", "sec", "principal", "nfsv4", "gssname", "allgssname", "dirpath",
749     "minorversion", "nametimeo", "negnametimeo", "nocto", "noncontigwr",
750     "pnfs", "wcommitsize", "oneopenown", "tls",
751     NULL };
752
753 /*
754  * Parse the "from" mountarg, passed by the generic mount(8) program
755  * or the mountroot code.  This is used when rerooting into NFS.
756  *
757  * Note that the "hostname" is actually a "hostname:/share/path" string.
758  */
759 static int
760 nfs_mount_parse_from(struct vfsoptlist *opts, char **hostnamep,
761     struct sockaddr_in **sinp, char *dirpath, size_t dirpathsize, int *dirlenp)
762 {
763         char *nam, *delimp, *hostp, *spec;
764         int error, have_bracket = 0, offset, rv, speclen;
765         struct sockaddr_in *sin;
766         size_t len;
767
768         error = vfs_getopt(opts, "from", (void **)&spec, &speclen);
769         if (error != 0)
770                 return (error);
771         nam = malloc(MNAMELEN + 1, M_TEMP, M_WAITOK);
772
773         /*
774          * This part comes from sbin/mount_nfs/mount_nfs.c:getnfsargs().
775          */
776         if (*spec == '[' && (delimp = strchr(spec + 1, ']')) != NULL &&
777             *(delimp + 1) == ':') {
778                 hostp = spec + 1;
779                 spec = delimp + 2;
780                 have_bracket = 1;
781         } else if ((delimp = strrchr(spec, ':')) != NULL) {
782                 hostp = spec;
783                 spec = delimp + 1;
784         } else if ((delimp = strrchr(spec, '@')) != NULL) {
785                 printf("%s: path@server syntax is deprecated, "
786                     "use server:path\n", __func__);
787                 hostp = delimp + 1;
788         } else {
789                 printf("%s: no <host>:<dirpath> nfs-name\n", __func__);
790                 free(nam, M_TEMP);
791                 return (EINVAL);
792         }
793         *delimp = '\0';
794
795         /*
796          * If there has been a trailing slash at mounttime it seems
797          * that some mountd implementations fail to remove the mount
798          * entries from their mountlist while unmounting.
799          */
800         for (speclen = strlen(spec);
801             speclen > 1 && spec[speclen - 1] == '/';
802             speclen--)
803                 spec[speclen - 1] = '\0';
804         if (strlen(hostp) + strlen(spec) + 1 > MNAMELEN) {
805                 printf("%s: %s:%s: name too long", __func__, hostp, spec);
806                 free(nam, M_TEMP);
807                 return (EINVAL);
808         }
809         /* Make both '@' and ':' notations equal */
810         if (*hostp != '\0') {
811                 len = strlen(hostp);
812                 offset = 0;
813                 if (have_bracket)
814                         nam[offset++] = '[';
815                 memmove(nam + offset, hostp, len);
816                 if (have_bracket)
817                         nam[len + offset++] = ']';
818                 nam[len + offset++] = ':';
819                 memmove(nam + len + offset, spec, speclen);
820                 nam[len + speclen + offset] = '\0';
821         } else
822                 nam[0] = '\0';
823
824         /*
825          * XXX: IPv6
826          */
827         sin = malloc(sizeof(*sin), M_SONAME, M_WAITOK);
828         rv = inet_pton(AF_INET, hostp, &sin->sin_addr);
829         if (rv != 1) {
830                 printf("%s: cannot parse '%s', inet_pton() returned %d\n",
831                     __func__, hostp, rv);
832                 free(nam, M_TEMP);
833                 free(sin, M_SONAME);
834                 return (EINVAL);
835         }
836
837         sin->sin_len = sizeof(*sin);
838         sin->sin_family = AF_INET;
839         /*
840          * XXX: hardcoded port number.
841          */
842         sin->sin_port = htons(2049);
843
844         *hostnamep = strdup(nam, M_NEWNFSMNT);
845         *sinp = sin;
846         strlcpy(dirpath, spec, dirpathsize);
847         *dirlenp = strlen(dirpath);
848
849         free(nam, M_TEMP);
850         return (0);
851 }
852
853 /*
854  * VFS Operations.
855  *
856  * mount system call
857  * It seems a bit dumb to copyinstr() the host and path here and then
858  * bcopy() them in mountnfs(), but I wanted to detect errors before
859  * doing the getsockaddr() call because getsockaddr() allocates an mbuf and
860  * an error after that means that I have to release the mbuf.
861  */
862 /* ARGSUSED */
863 static int
864 nfs_mount(struct mount *mp)
865 {
866         struct nfs_args args = {
867             .version = NFS_ARGSVERSION,
868             .addr = NULL,
869             .addrlen = sizeof (struct sockaddr_in),
870             .sotype = SOCK_STREAM,
871             .proto = 0,
872             .fh = NULL,
873             .fhsize = 0,
874             .flags = NFSMNT_RESVPORT,
875             .wsize = NFS_WSIZE,
876             .rsize = NFS_RSIZE,
877             .readdirsize = NFS_READDIRSIZE,
878             .timeo = 10,
879             .retrans = NFS_RETRANS,
880             .readahead = NFS_DEFRAHEAD,
881             .wcommitsize = 0,                   /* was: NQ_DEFLEASE */
882             .hostname = NULL,
883             .acregmin = NFS_MINATTRTIMO,
884             .acregmax = NFS_MAXATTRTIMO,
885             .acdirmin = NFS_MINDIRATTRTIMO,
886             .acdirmax = NFS_MAXDIRATTRTIMO,
887         };
888         int error = 0, ret, len;
889         struct sockaddr *nam = NULL;
890         struct vnode *vp;
891         struct thread *td;
892         char *hst;
893         u_char nfh[NFSX_FHMAX], krbname[100], dirpath[100], srvkrbname[100];
894         char *cp, *opt, *name, *secname;
895         int nametimeo = NFS_DEFAULT_NAMETIMEO;
896         int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
897         int minvers = 0;
898         int dirlen, has_nfs_args_opt, has_nfs_from_opt,
899             krbnamelen, srvkrbnamelen;
900         size_t hstlen;
901         uint32_t newflag;
902
903         has_nfs_args_opt = 0;
904         has_nfs_from_opt = 0;
905         newflag = 0;
906         hst = malloc(MNAMELEN, M_TEMP, M_WAITOK);
907         if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
908                 error = EINVAL;
909                 goto out;
910         }
911
912         td = curthread;
913         if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS &&
914             nfs_diskless_valid != 0) {
915                 error = nfs_mountroot(mp);
916                 goto out;
917         }
918
919         nfscl_init();
920
921         /*
922          * The old mount_nfs program passed the struct nfs_args
923          * from userspace to kernel.  The new mount_nfs program
924          * passes string options via nmount() from userspace to kernel
925          * and we populate the struct nfs_args in the kernel.
926          */
927         if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
928                 error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
929                     sizeof(args));
930                 if (error != 0)
931                         goto out;
932
933                 if (args.version != NFS_ARGSVERSION) {
934                         error = EPROGMISMATCH;
935                         goto out;
936                 }
937                 has_nfs_args_opt = 1;
938         }
939
940         /* Handle the new style options. */
941         if (vfs_getopt(mp->mnt_optnew, "noac", NULL, NULL) == 0) {
942                 args.acdirmin = args.acdirmax =
943                     args.acregmin = args.acregmax = 0;
944                 args.flags |= NFSMNT_ACDIRMIN | NFSMNT_ACDIRMAX |
945                     NFSMNT_ACREGMIN | NFSMNT_ACREGMAX;
946         }
947         if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
948                 args.flags |= NFSMNT_NOCONN;
949         if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
950                 args.flags &= ~NFSMNT_NOCONN;
951         if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
952                 args.flags |= NFSMNT_NOLOCKD;
953         if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
954                 args.flags &= ~NFSMNT_NOLOCKD;
955         if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
956                 args.flags |= NFSMNT_INT;
957         if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
958                 args.flags |= NFSMNT_RDIRPLUS;
959         if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
960                 args.flags |= NFSMNT_RESVPORT;
961         if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
962                 args.flags &= ~NFSMNT_RESVPORT;
963         if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
964                 args.flags |= NFSMNT_SOFT;
965         if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
966                 args.flags &= ~NFSMNT_SOFT;
967         if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
968                 args.sotype = SOCK_DGRAM;
969         if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
970                 args.sotype = SOCK_DGRAM;
971         if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
972                 args.sotype = SOCK_STREAM;
973         if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
974                 args.flags |= NFSMNT_NFSV3;
975         if (vfs_getopt(mp->mnt_optnew, "nfsv4", NULL, NULL) == 0) {
976                 args.flags |= NFSMNT_NFSV4;
977                 args.sotype = SOCK_STREAM;
978         }
979         if (vfs_getopt(mp->mnt_optnew, "allgssname", NULL, NULL) == 0)
980                 args.flags |= NFSMNT_ALLGSSNAME;
981         if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0)
982                 args.flags |= NFSMNT_NOCTO;
983         if (vfs_getopt(mp->mnt_optnew, "noncontigwr", NULL, NULL) == 0)
984                 args.flags |= NFSMNT_NONCONTIGWR;
985         if (vfs_getopt(mp->mnt_optnew, "pnfs", NULL, NULL) == 0)
986                 args.flags |= NFSMNT_PNFS;
987         if (vfs_getopt(mp->mnt_optnew, "oneopenown", NULL, NULL) == 0)
988                 args.flags |= NFSMNT_ONEOPENOWN;
989         if (vfs_getopt(mp->mnt_optnew, "tls", NULL, NULL) == 0)
990                 newflag |= NFSMNT_TLS;
991         if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
992                 if (opt == NULL) { 
993                         vfs_mount_error(mp, "illegal readdirsize");
994                         error = EINVAL;
995                         goto out;
996                 }
997                 ret = sscanf(opt, "%d", &args.readdirsize);
998                 if (ret != 1 || args.readdirsize <= 0) {
999                         vfs_mount_error(mp, "illegal readdirsize: %s",
1000                             opt);
1001                         error = EINVAL;
1002                         goto out;
1003                 }
1004                 args.flags |= NFSMNT_READDIRSIZE;
1005         }
1006         if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
1007                 if (opt == NULL) { 
1008                         vfs_mount_error(mp, "illegal readahead");
1009                         error = EINVAL;
1010                         goto out;
1011                 }
1012                 ret = sscanf(opt, "%d", &args.readahead);
1013                 if (ret != 1 || args.readahead <= 0) {
1014                         vfs_mount_error(mp, "illegal readahead: %s",
1015                             opt);
1016                         error = EINVAL;
1017                         goto out;
1018                 }
1019                 args.flags |= NFSMNT_READAHEAD;
1020         }
1021         if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
1022                 if (opt == NULL) { 
1023                         vfs_mount_error(mp, "illegal wsize");
1024                         error = EINVAL;
1025                         goto out;
1026                 }
1027                 ret = sscanf(opt, "%d", &args.wsize);
1028                 if (ret != 1 || args.wsize <= 0) {
1029                         vfs_mount_error(mp, "illegal wsize: %s",
1030                             opt);
1031                         error = EINVAL;
1032                         goto out;
1033                 }
1034                 args.flags |= NFSMNT_WSIZE;
1035         }
1036         if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
1037                 if (opt == NULL) { 
1038                         vfs_mount_error(mp, "illegal rsize");
1039                         error = EINVAL;
1040                         goto out;
1041                 }
1042                 ret = sscanf(opt, "%d", &args.rsize);
1043                 if (ret != 1 || args.rsize <= 0) {
1044                         vfs_mount_error(mp, "illegal wsize: %s",
1045                             opt);
1046                         error = EINVAL;
1047                         goto out;
1048                 }
1049                 args.flags |= NFSMNT_RSIZE;
1050         }
1051         if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
1052                 if (opt == NULL) { 
1053                         vfs_mount_error(mp, "illegal retrans");
1054                         error = EINVAL;
1055                         goto out;
1056                 }
1057                 ret = sscanf(opt, "%d", &args.retrans);
1058                 if (ret != 1 || args.retrans <= 0) {
1059                         vfs_mount_error(mp, "illegal retrans: %s",
1060                             opt);
1061                         error = EINVAL;
1062                         goto out;
1063                 }
1064                 args.flags |= NFSMNT_RETRANS;
1065         }
1066         if (vfs_getopt(mp->mnt_optnew, "actimeo", (void **)&opt, NULL) == 0) {
1067                 ret = sscanf(opt, "%d", &args.acregmin);
1068                 if (ret != 1 || args.acregmin < 0) {
1069                         vfs_mount_error(mp, "illegal actimeo: %s",
1070                             opt);
1071                         error = EINVAL;
1072                         goto out;
1073                 }
1074                 args.acdirmin = args.acdirmax = args.acregmax = args.acregmin;
1075                 args.flags |= NFSMNT_ACDIRMIN | NFSMNT_ACDIRMAX |
1076                     NFSMNT_ACREGMIN | NFSMNT_ACREGMAX;
1077         }
1078         if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
1079                 ret = sscanf(opt, "%d", &args.acregmin);
1080                 if (ret != 1 || args.acregmin < 0) {
1081                         vfs_mount_error(mp, "illegal acregmin: %s",
1082                             opt);
1083                         error = EINVAL;
1084                         goto out;
1085                 }
1086                 args.flags |= NFSMNT_ACREGMIN;
1087         }
1088         if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
1089                 ret = sscanf(opt, "%d", &args.acregmax);
1090                 if (ret != 1 || args.acregmax < 0) {
1091                         vfs_mount_error(mp, "illegal acregmax: %s",
1092                             opt);
1093                         error = EINVAL;
1094                         goto out;
1095                 }
1096                 args.flags |= NFSMNT_ACREGMAX;
1097         }
1098         if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
1099                 ret = sscanf(opt, "%d", &args.acdirmin);
1100                 if (ret != 1 || args.acdirmin < 0) {
1101                         vfs_mount_error(mp, "illegal acdirmin: %s",
1102                             opt);
1103                         error = EINVAL;
1104                         goto out;
1105                 }
1106                 args.flags |= NFSMNT_ACDIRMIN;
1107         }
1108         if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
1109                 ret = sscanf(opt, "%d", &args.acdirmax);
1110                 if (ret != 1 || args.acdirmax < 0) {
1111                         vfs_mount_error(mp, "illegal acdirmax: %s",
1112                             opt);
1113                         error = EINVAL;
1114                         goto out;
1115                 }
1116                 args.flags |= NFSMNT_ACDIRMAX;
1117         }
1118         if (vfs_getopt(mp->mnt_optnew, "wcommitsize", (void **)&opt, NULL) == 0) {
1119                 ret = sscanf(opt, "%d", &args.wcommitsize);
1120                 if (ret != 1 || args.wcommitsize < 0) {
1121                         vfs_mount_error(mp, "illegal wcommitsize: %s", opt);
1122                         error = EINVAL;
1123                         goto out;
1124                 }
1125                 args.flags |= NFSMNT_WCOMMITSIZE;
1126         }
1127         if (vfs_getopt(mp->mnt_optnew, "timeo", (void **)&opt, NULL) == 0) {
1128                 ret = sscanf(opt, "%d", &args.timeo);
1129                 if (ret != 1 || args.timeo <= 0) {
1130                         vfs_mount_error(mp, "illegal timeo: %s",
1131                             opt);
1132                         error = EINVAL;
1133                         goto out;
1134                 }
1135                 args.flags |= NFSMNT_TIMEO;
1136         }
1137         if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
1138                 ret = sscanf(opt, "%d", &args.timeo);
1139                 if (ret != 1 || args.timeo <= 0) {
1140                         vfs_mount_error(mp, "illegal timeout: %s",
1141                             opt);
1142                         error = EINVAL;
1143                         goto out;
1144                 }
1145                 args.flags |= NFSMNT_TIMEO;
1146         }
1147         if (vfs_getopt(mp->mnt_optnew, "nametimeo", (void **)&opt, NULL) == 0) {
1148                 ret = sscanf(opt, "%d", &nametimeo);
1149                 if (ret != 1 || nametimeo < 0) {
1150                         vfs_mount_error(mp, "illegal nametimeo: %s", opt);
1151                         error = EINVAL;
1152                         goto out;
1153                 }
1154         }
1155         if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
1156             == 0) {
1157                 ret = sscanf(opt, "%d", &negnametimeo);
1158                 if (ret != 1 || negnametimeo < 0) {
1159                         vfs_mount_error(mp, "illegal negnametimeo: %s",
1160                             opt);
1161                         error = EINVAL;
1162                         goto out;
1163                 }
1164         }
1165         if (vfs_getopt(mp->mnt_optnew, "minorversion", (void **)&opt, NULL) ==
1166             0) {
1167                 ret = sscanf(opt, "%d", &minvers);
1168                 if (ret != 1 || minvers < 0 || minvers > 2 ||
1169                     (args.flags & NFSMNT_NFSV4) == 0) {
1170                         vfs_mount_error(mp, "illegal minorversion: %s", opt);
1171                         error = EINVAL;
1172                         goto out;
1173                 }
1174         }
1175         if (vfs_getopt(mp->mnt_optnew, "sec",
1176                 (void **) &secname, NULL) == 0)
1177                 nfs_sec_name(secname, &args.flags);
1178
1179         if (mp->mnt_flag & MNT_UPDATE) {
1180                 struct nfsmount *nmp = VFSTONFS(mp);
1181
1182                 if (nmp == NULL) {
1183                         error = EIO;
1184                         goto out;
1185                 }
1186
1187                 /*
1188                  * If a change from TCP->UDP is done and there are thread(s)
1189                  * that have I/O RPC(s) in progress with a transfer size
1190                  * greater than NFS_MAXDGRAMDATA, those thread(s) will be
1191                  * hung, retrying the RPC(s) forever. Usually these threads
1192                  * will be seen doing an uninterruptible sleep on wait channel
1193                  * "nfsreq".
1194                  */
1195                 if (args.sotype == SOCK_DGRAM && nmp->nm_sotype == SOCK_STREAM)
1196                         tprintf(td->td_proc, LOG_WARNING,
1197         "Warning: mount -u that changes TCP->UDP can result in hung threads\n");
1198
1199                 /*
1200                  * When doing an update, we can't change version,
1201                  * security, switch lockd strategies, change cookie
1202                  * translation or switch oneopenown.
1203                  */
1204                 args.flags = (args.flags &
1205                     ~(NFSMNT_NFSV3 |
1206                       NFSMNT_NFSV4 |
1207                       NFSMNT_KERB |
1208                       NFSMNT_INTEGRITY |
1209                       NFSMNT_PRIVACY |
1210                       NFSMNT_ONEOPENOWN |
1211                       NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
1212                     (nmp->nm_flag &
1213                         (NFSMNT_NFSV3 |
1214                          NFSMNT_NFSV4 |
1215                          NFSMNT_KERB |
1216                          NFSMNT_INTEGRITY |
1217                          NFSMNT_PRIVACY |
1218                          NFSMNT_ONEOPENOWN |
1219                          NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
1220                 nfs_decode_args(mp, nmp, &args, NULL, td->td_ucred, td);
1221                 goto out;
1222         }
1223
1224         /*
1225          * Make the nfs_ip_paranoia sysctl serve as the default connection
1226          * or no-connection mode for those protocols that support 
1227          * no-connection mode (the flag will be cleared later for protocols
1228          * that do not support no-connection mode).  This will allow a client
1229          * to receive replies from a different IP then the request was
1230          * sent to.  Note: default value for nfs_ip_paranoia is 1 (paranoid),
1231          * not 0.
1232          */
1233         if (nfs_ip_paranoia == 0)
1234                 args.flags |= NFSMNT_NOCONN;
1235
1236         if (has_nfs_args_opt != 0) {
1237                 /*
1238                  * In the 'nfs_args' case, the pointers in the args
1239                  * structure are in userland - we copy them in here.
1240                  */
1241                 if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
1242                         vfs_mount_error(mp, "Bad file handle");
1243                         error = EINVAL;
1244                         goto out;
1245                 }
1246                 error = copyin((caddr_t)args.fh, (caddr_t)nfh,
1247                     args.fhsize);
1248                 if (error != 0)
1249                         goto out;
1250                 error = copyinstr(args.hostname, hst, MNAMELEN - 1, &hstlen);
1251                 if (error != 0)
1252                         goto out;
1253                 bzero(&hst[hstlen], MNAMELEN - hstlen);
1254                 args.hostname = hst;
1255                 /* getsockaddr() call must be after above copyin() calls */
1256                 error = getsockaddr(&nam, args.addr, args.addrlen);
1257                 if (error != 0)
1258                         goto out;
1259         } else if (nfs_mount_parse_from(mp->mnt_optnew,
1260             &args.hostname, (struct sockaddr_in **)&nam, dirpath,
1261             sizeof(dirpath), &dirlen) == 0) {
1262                 has_nfs_from_opt = 1;
1263                 bcopy(args.hostname, hst, MNAMELEN);
1264                 hst[MNAMELEN - 1] = '\0';
1265
1266                 /*
1267                  * This only works with NFSv4 for now.
1268                  */
1269                 args.fhsize = 0;
1270                 args.flags |= NFSMNT_NFSV4;
1271                 args.sotype = SOCK_STREAM;
1272         } else {
1273                 if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
1274                     &args.fhsize) == 0) {
1275                         if (args.fhsize < 0 || args.fhsize > NFSX_FHMAX) {
1276                                 vfs_mount_error(mp, "Bad file handle");
1277                                 error = EINVAL;
1278                                 goto out;
1279                         }
1280                         bcopy(args.fh, nfh, args.fhsize);
1281                 } else {
1282                         args.fhsize = 0;
1283                 }
1284                 (void) vfs_getopt(mp->mnt_optnew, "hostname",
1285                     (void **)&args.hostname, &len);
1286                 if (args.hostname == NULL) {
1287                         vfs_mount_error(mp, "Invalid hostname");
1288                         error = EINVAL;
1289                         goto out;
1290                 }
1291                 if (len >= MNAMELEN) {
1292                         vfs_mount_error(mp, "Hostname too long");
1293                         error = EINVAL;
1294                         goto out;
1295                 }
1296                 bcopy(args.hostname, hst, len);
1297                 hst[len] = '\0';
1298         }
1299
1300         if (vfs_getopt(mp->mnt_optnew, "principal", (void **)&name, NULL) == 0)
1301                 strlcpy(srvkrbname, name, sizeof (srvkrbname));
1302         else {
1303                 snprintf(srvkrbname, sizeof (srvkrbname), "nfs@%s", hst);
1304                 cp = strchr(srvkrbname, ':');
1305                 if (cp != NULL)
1306                         *cp = '\0';
1307         }
1308         srvkrbnamelen = strlen(srvkrbname);
1309
1310         if (vfs_getopt(mp->mnt_optnew, "gssname", (void **)&name, NULL) == 0)
1311                 strlcpy(krbname, name, sizeof (krbname));
1312         else
1313                 krbname[0] = '\0';
1314         krbnamelen = strlen(krbname);
1315
1316         if (has_nfs_from_opt == 0) {
1317                 if (vfs_getopt(mp->mnt_optnew,
1318                     "dirpath", (void **)&name, NULL) == 0)
1319                         strlcpy(dirpath, name, sizeof (dirpath));
1320                 else
1321                         dirpath[0] = '\0';
1322                 dirlen = strlen(dirpath);
1323         }
1324
1325         if (has_nfs_args_opt == 0 && has_nfs_from_opt == 0) {
1326                 if (vfs_getopt(mp->mnt_optnew, "addr",
1327                     (void **)&args.addr, &args.addrlen) == 0) {
1328                         if (args.addrlen > SOCK_MAXADDRLEN) {
1329                                 error = ENAMETOOLONG;
1330                                 goto out;
1331                         }
1332                         nam = malloc(args.addrlen, M_SONAME, M_WAITOK);
1333                         bcopy(args.addr, nam, args.addrlen);
1334                         nam->sa_len = args.addrlen;
1335                 } else {
1336                         vfs_mount_error(mp, "No server address");
1337                         error = EINVAL;
1338                         goto out;
1339                 }
1340         }
1341
1342         args.fh = nfh;
1343         error = mountnfs(&args, mp, nam, hst, krbname, krbnamelen, dirpath,
1344             dirlen, srvkrbname, srvkrbnamelen, &vp, td->td_ucred, td,
1345             nametimeo, negnametimeo, minvers, newflag);
1346 out:
1347         if (!error) {
1348                 MNT_ILOCK(mp);
1349                 mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED | MNTK_NO_IOPF |
1350                     MNTK_USES_BCACHE;
1351                 if ((VFSTONFS(mp)->nm_flag & NFSMNT_NFSV4) != 0)
1352                         mp->mnt_kern_flag |= MNTK_NULL_NOCACHE;
1353                 MNT_IUNLOCK(mp);
1354         }
1355         free(hst, M_TEMP);
1356         return (error);
1357 }
1358
1359 /*
1360  * VFS Operations.
1361  *
1362  * mount system call
1363  * It seems a bit dumb to copyinstr() the host and path here and then
1364  * bcopy() them in mountnfs(), but I wanted to detect errors before
1365  * doing the getsockaddr() call because getsockaddr() allocates an mbuf and
1366  * an error after that means that I have to release the mbuf.
1367  */
1368 /* ARGSUSED */
1369 static int
1370 nfs_cmount(struct mntarg *ma, void *data, uint64_t flags)
1371 {
1372         int error;
1373         struct nfs_args args;
1374
1375         error = copyin(data, &args, sizeof (struct nfs_args));
1376         if (error)
1377                 return error;
1378
1379         ma = mount_arg(ma, "nfs_args", &args, sizeof args);
1380
1381         error = kernel_mount(ma, flags);
1382         return (error);
1383 }
1384
1385 /*
1386  * Common code for mount and mountroot
1387  */
1388 static int
1389 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
1390     char *hst, u_char *krbname, int krbnamelen, u_char *dirpath, int dirlen,
1391     u_char *srvkrbname, int srvkrbnamelen, struct vnode **vpp,
1392     struct ucred *cred, struct thread *td, int nametimeo, int negnametimeo,
1393     int minvers, uint32_t newflag)
1394 {
1395         struct nfsmount *nmp;
1396         struct nfsnode *np;
1397         int error, trycnt, ret;
1398         struct nfsvattr nfsva;
1399         struct nfsclclient *clp;
1400         struct nfsclds *dsp, *tdsp;
1401         uint32_t lease;
1402         static u_int64_t clval = 0;
1403 #ifdef KERN_TLS
1404         u_int maxlen;
1405 #endif
1406
1407         NFSCL_DEBUG(3, "in mnt\n");
1408         clp = NULL;
1409         if (mp->mnt_flag & MNT_UPDATE) {
1410                 nmp = VFSTONFS(mp);
1411                 printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
1412                 free(nam, M_SONAME);
1413                 return (0);
1414         } else {
1415                 /* NFS-over-TLS requires that rpctls be functioning. */
1416                 if ((newflag & NFSMNT_TLS) != 0) {
1417                         error = EINVAL;
1418 #ifdef KERN_TLS
1419                         /* KERN_TLS is only supported for TCP. */
1420                         if (argp->sotype == SOCK_STREAM &&
1421                             rpctls_getinfo(&maxlen, true, false))
1422                                 error = 0;
1423 #endif
1424                         if (error != 0) {
1425                                 free(nam, M_SONAME);
1426                                 return (error);
1427                         }
1428                 }
1429                 nmp = malloc(sizeof (struct nfsmount) +
1430                     krbnamelen + dirlen + srvkrbnamelen + 2,
1431                     M_NEWNFSMNT, M_WAITOK | M_ZERO);
1432                 nmp->nm_newflag = newflag;
1433                 TAILQ_INIT(&nmp->nm_bufq);
1434                 TAILQ_INIT(&nmp->nm_sess);
1435                 if (clval == 0)
1436                         clval = (u_int64_t)nfsboottime.tv_sec;
1437                 nmp->nm_clval = clval++;
1438                 nmp->nm_krbnamelen = krbnamelen;
1439                 nmp->nm_dirpathlen = dirlen;
1440                 nmp->nm_srvkrbnamelen = srvkrbnamelen;
1441                 if (td->td_ucred->cr_uid != (uid_t)0) {
1442                         /*
1443                          * nm_uid is used to get KerberosV credentials for
1444                          * the nfsv4 state handling operations if there is
1445                          * no host based principal set. Use the uid of
1446                          * this user if not root, since they are doing the
1447                          * mount. I don't think setting this for root will
1448                          * work, since root normally does not have user
1449                          * credentials in a credentials cache.
1450                          */
1451                         nmp->nm_uid = td->td_ucred->cr_uid;
1452                 } else {
1453                         /*
1454                          * Just set to -1, so it won't be used.
1455                          */
1456                         nmp->nm_uid = (uid_t)-1;
1457                 }
1458
1459                 /* Copy and null terminate all the names */
1460                 if (nmp->nm_krbnamelen > 0) {
1461                         bcopy(krbname, nmp->nm_krbname, nmp->nm_krbnamelen);
1462                         nmp->nm_name[nmp->nm_krbnamelen] = '\0';
1463                 }
1464                 if (nmp->nm_dirpathlen > 0) {
1465                         bcopy(dirpath, NFSMNT_DIRPATH(nmp),
1466                             nmp->nm_dirpathlen);
1467                         nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1468                             + 1] = '\0';
1469                 }
1470                 if (nmp->nm_srvkrbnamelen > 0) {
1471                         bcopy(srvkrbname, NFSMNT_SRVKRBNAME(nmp),
1472                             nmp->nm_srvkrbnamelen);
1473                         nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1474                             + nmp->nm_srvkrbnamelen + 2] = '\0';
1475                 }
1476                 nmp->nm_sockreq.nr_cred = crhold(cred);
1477                 mtx_init(&nmp->nm_sockreq.nr_mtx, "nfssock", NULL, MTX_DEF);
1478                 mp->mnt_data = nmp;
1479                 nmp->nm_getinfo = nfs_getnlminfo;
1480                 nmp->nm_vinvalbuf = ncl_vinvalbuf;
1481         }
1482         vfs_getnewfsid(mp);
1483         nmp->nm_mountp = mp;
1484         mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF | MTX_DUPOK);
1485
1486         /*
1487          * Since nfs_decode_args() might optionally set them, these
1488          * need to be set to defaults before the call, so that the
1489          * optional settings aren't overwritten.
1490          */
1491         nmp->nm_nametimeo = nametimeo;
1492         nmp->nm_negnametimeo = negnametimeo;
1493         nmp->nm_timeo = NFS_TIMEO;
1494         nmp->nm_retry = NFS_RETRANS;
1495         nmp->nm_readahead = NFS_DEFRAHEAD;
1496
1497         /* This is empirical approximation of sqrt(hibufspace) * 256. */
1498         nmp->nm_wcommitsize = NFS_MAXBSIZE / 256;
1499         while ((long)nmp->nm_wcommitsize * nmp->nm_wcommitsize < hibufspace)
1500                 nmp->nm_wcommitsize *= 2;
1501         nmp->nm_wcommitsize *= 256;
1502
1503         if ((argp->flags & NFSMNT_NFSV4) != 0)
1504                 nmp->nm_minorvers = minvers;
1505         else
1506                 nmp->nm_minorvers = 0;
1507
1508         nfs_decode_args(mp, nmp, argp, hst, cred, td);
1509
1510         /*
1511          * V2 can only handle 32 bit filesizes.  A 4GB-1 limit may be too
1512          * high, depending on whether we end up with negative offsets in
1513          * the client or server somewhere.  2GB-1 may be safer.
1514          *
1515          * For V3, ncl_fsinfo will adjust this as necessary.  Assume maximum
1516          * that we can handle until we find out otherwise.
1517          */
1518         if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0)
1519                 nmp->nm_maxfilesize = 0xffffffffLL;
1520         else
1521                 nmp->nm_maxfilesize = OFF_MAX;
1522
1523         if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
1524                 nmp->nm_wsize = NFS_WSIZE;
1525                 nmp->nm_rsize = NFS_RSIZE;
1526                 nmp->nm_readdirsize = NFS_READDIRSIZE;
1527         }
1528         nmp->nm_numgrps = NFS_MAXGRPS;
1529         nmp->nm_tprintf_delay = nfs_tprintf_delay;
1530         if (nmp->nm_tprintf_delay < 0)
1531                 nmp->nm_tprintf_delay = 0;
1532         nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
1533         if (nmp->nm_tprintf_initial_delay < 0)
1534                 nmp->nm_tprintf_initial_delay = 0;
1535         nmp->nm_fhsize = argp->fhsize;
1536         if (nmp->nm_fhsize > 0)
1537                 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
1538         bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
1539         nmp->nm_nam = nam;
1540         /* Set up the sockets and per-host congestion */
1541         nmp->nm_sotype = argp->sotype;
1542         nmp->nm_soproto = argp->proto;
1543         nmp->nm_sockreq.nr_prog = NFS_PROG;
1544         if ((argp->flags & NFSMNT_NFSV4))
1545                 nmp->nm_sockreq.nr_vers = NFS_VER4;
1546         else if ((argp->flags & NFSMNT_NFSV3))
1547                 nmp->nm_sockreq.nr_vers = NFS_VER3;
1548         else
1549                 nmp->nm_sockreq.nr_vers = NFS_VER2;
1550
1551         if ((error = newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0, false)))
1552                 goto bad;
1553         /* For NFSv4.1, get the clientid now. */
1554         if (nmp->nm_minorvers > 0) {
1555                 NFSCL_DEBUG(3, "at getcl\n");
1556                 error = nfscl_getcl(mp, cred, td, 0, &clp);
1557                 NFSCL_DEBUG(3, "aft getcl=%d\n", error);
1558                 if (error != 0)
1559                         goto bad;
1560         }
1561
1562         if (nmp->nm_fhsize == 0 && (nmp->nm_flag & NFSMNT_NFSV4) &&
1563             nmp->nm_dirpathlen > 0) {
1564                 NFSCL_DEBUG(3, "in dirp\n");
1565                 /*
1566                  * If the fhsize on the mount point == 0 for V4, the mount
1567                  * path needs to be looked up.
1568                  */
1569                 trycnt = 3;
1570                 do {
1571                         error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp),
1572                             cred, td);
1573                         NFSCL_DEBUG(3, "aft dirp=%d\n", error);
1574                         if (error)
1575                                 (void) nfs_catnap(PZERO, error, "nfsgetdirp");
1576                 } while (error && --trycnt > 0);
1577                 if (error)
1578                         goto bad;
1579         }
1580
1581         /*
1582          * A reference count is needed on the nfsnode representing the
1583          * remote root.  If this object is not persistent, then backward
1584          * traversals of the mount point (i.e. "..") will not work if
1585          * the nfsnode gets flushed out of the cache. Ufs does not have
1586          * this problem, because one can identify root inodes by their
1587          * number == UFS_ROOTINO (2).
1588          */
1589         if (nmp->nm_fhsize > 0) {
1590                 /*
1591                  * Set f_iosize to NFS_DIRBLKSIZ so that bo_bsize gets set
1592                  * non-zero for the root vnode. f_iosize will be set correctly
1593                  * by nfs_statfs() before any I/O occurs.
1594                  */
1595                 mp->mnt_stat.f_iosize = NFS_DIRBLKSIZ;
1596                 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np,
1597                     LK_EXCLUSIVE);
1598                 if (error)
1599                         goto bad;
1600                 *vpp = NFSTOV(np);
1601
1602                 /*
1603                  * Get file attributes and transfer parameters for the
1604                  * mountpoint.  This has the side effect of filling in
1605                  * (*vpp)->v_type with the correct value.
1606                  */
1607                 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
1608                     cred, td, &nfsva, NULL, &lease);
1609                 if (ret) {
1610                         /*
1611                          * Just set default values to get things going.
1612                          */
1613                         NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
1614                         nfsva.na_vattr.va_type = VDIR;
1615                         nfsva.na_vattr.va_mode = 0777;
1616                         nfsva.na_vattr.va_nlink = 100;
1617                         nfsva.na_vattr.va_uid = (uid_t)0;
1618                         nfsva.na_vattr.va_gid = (gid_t)0;
1619                         nfsva.na_vattr.va_fileid = 2;
1620                         nfsva.na_vattr.va_gen = 1;
1621                         nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
1622                         nfsva.na_vattr.va_size = 512 * 1024;
1623                         lease = 60;
1624                 }
1625                 (void) nfscl_loadattrcache(vpp, &nfsva, NULL, NULL, 0, 1);
1626                 if (nmp->nm_minorvers > 0) {
1627                         NFSCL_DEBUG(3, "lease=%d\n", (int)lease);
1628                         NFSLOCKCLSTATE();
1629                         clp->nfsc_renew = NFSCL_RENEW(lease);
1630                         clp->nfsc_expire = NFSD_MONOSEC + clp->nfsc_renew;
1631                         clp->nfsc_clientidrev++;
1632                         if (clp->nfsc_clientidrev == 0)
1633                                 clp->nfsc_clientidrev++;
1634                         NFSUNLOCKCLSTATE();
1635                         /*
1636                          * Mount will succeed, so the renew thread can be
1637                          * started now.
1638                          */
1639                         nfscl_start_renewthread(clp);
1640                         nfscl_clientrelease(clp);
1641                 }
1642                 if (argp->flags & NFSMNT_NFSV3)
1643                         ncl_fsinfo(nmp, *vpp, cred, td);
1644
1645                 /* Mark if the mount point supports NFSv4 ACLs. */
1646                 if ((argp->flags & NFSMNT_NFSV4) != 0 && nfsrv_useacl != 0 &&
1647                     ret == 0 &&
1648                     NFSISSET_ATTRBIT(&nfsva.na_suppattr, NFSATTRBIT_ACL)) {
1649                         MNT_ILOCK(mp);
1650                         mp->mnt_flag |= MNT_NFS4ACLS;
1651                         MNT_IUNLOCK(mp);
1652                 }
1653
1654                 /*
1655                  * Lose the lock but keep the ref.
1656                  */
1657                 NFSVOPUNLOCK(*vpp);
1658                 vfs_cache_root_set(mp, *vpp);
1659                 return (0);
1660         }
1661         error = EIO;
1662
1663 bad:
1664         if (clp != NULL)
1665                 nfscl_clientrelease(clp);
1666         newnfs_disconnect(&nmp->nm_sockreq);
1667         crfree(nmp->nm_sockreq.nr_cred);
1668         if (nmp->nm_sockreq.nr_auth != NULL)
1669                 AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
1670         mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1671         mtx_destroy(&nmp->nm_mtx);
1672         if (nmp->nm_clp != NULL) {
1673                 NFSLOCKCLSTATE();
1674                 LIST_REMOVE(nmp->nm_clp, nfsc_list);
1675                 NFSUNLOCKCLSTATE();
1676                 free(nmp->nm_clp, M_NFSCLCLIENT);
1677         }
1678         TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp) {
1679                 if (dsp != TAILQ_FIRST(&nmp->nm_sess) &&
1680                     dsp->nfsclds_sockp != NULL)
1681                         newnfs_disconnect(dsp->nfsclds_sockp);
1682                 nfscl_freenfsclds(dsp);
1683         }
1684         free(nmp, M_NEWNFSMNT);
1685         free(nam, M_SONAME);
1686         return (error);
1687 }
1688
1689 /*
1690  * unmount system call
1691  */
1692 static int
1693 nfs_unmount(struct mount *mp, int mntflags)
1694 {
1695         struct thread *td;
1696         struct nfsmount *nmp;
1697         int error, flags = 0, i, trycnt = 0;
1698         struct nfsclds *dsp, *tdsp;
1699
1700         td = curthread;
1701
1702         if (mntflags & MNT_FORCE)
1703                 flags |= FORCECLOSE;
1704         nmp = VFSTONFS(mp);
1705         error = 0;
1706         /*
1707          * Goes something like this..
1708          * - Call vflush() to clear out vnodes for this filesystem
1709          * - Close the socket
1710          * - Free up the data structures
1711          */
1712         /* In the forced case, cancel any outstanding requests. */
1713         if (mntflags & MNT_FORCE) {
1714                 NFSDDSLOCK();
1715                 if (nfsv4_findmirror(nmp) != NULL)
1716                         error = ENXIO;
1717                 NFSDDSUNLOCK();
1718                 if (error)
1719                         goto out;
1720                 error = newnfs_nmcancelreqs(nmp);
1721                 if (error)
1722                         goto out;
1723                 /* For a forced close, get rid of the renew thread now */
1724                 nfscl_umount(nmp, td);
1725         }
1726         /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
1727         do {
1728                 error = vflush(mp, 1, flags, td);
1729                 if ((mntflags & MNT_FORCE) && error != 0 && ++trycnt < 30)
1730                         (void) nfs_catnap(PSOCK, error, "newndm");
1731         } while ((mntflags & MNT_FORCE) && error != 0 && trycnt < 30);
1732         if (error)
1733                 goto out;
1734
1735         /*
1736          * We are now committed to the unmount.
1737          */
1738         if ((mntflags & MNT_FORCE) == 0)
1739                 nfscl_umount(nmp, td);
1740         else {
1741                 mtx_lock(&nmp->nm_mtx);
1742                 nmp->nm_privflag |= NFSMNTP_FORCEDISM;
1743                 mtx_unlock(&nmp->nm_mtx);
1744         }
1745         /* Make sure no nfsiods are assigned to this mount. */
1746         NFSLOCKIOD();
1747         for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
1748                 if (ncl_iodmount[i] == nmp) {
1749                         ncl_iodwant[i] = NFSIOD_AVAILABLE;
1750                         ncl_iodmount[i] = NULL;
1751                 }
1752         NFSUNLOCKIOD();
1753
1754         /*
1755          * We can now set mnt_data to NULL and wait for
1756          * nfssvc(NFSSVC_FORCEDISM) to complete.
1757          */
1758         mtx_lock(&mountlist_mtx);
1759         mtx_lock(&nmp->nm_mtx);
1760         mp->mnt_data = NULL;
1761         mtx_unlock(&mountlist_mtx);
1762         while ((nmp->nm_privflag & NFSMNTP_CANCELRPCS) != 0)
1763                 msleep(nmp, &nmp->nm_mtx, PVFS, "nfsfdism", 0);
1764         mtx_unlock(&nmp->nm_mtx);
1765
1766         newnfs_disconnect(&nmp->nm_sockreq);
1767         crfree(nmp->nm_sockreq.nr_cred);
1768         free(nmp->nm_nam, M_SONAME);
1769         if (nmp->nm_sockreq.nr_auth != NULL)
1770                 AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
1771         mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1772         mtx_destroy(&nmp->nm_mtx);
1773         TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp) {
1774                 if (dsp != TAILQ_FIRST(&nmp->nm_sess) &&
1775                     dsp->nfsclds_sockp != NULL)
1776                         newnfs_disconnect(dsp->nfsclds_sockp);
1777                 nfscl_freenfsclds(dsp);
1778         }
1779         free(nmp, M_NEWNFSMNT);
1780 out:
1781         return (error);
1782 }
1783
1784 /*
1785  * Return root of a filesystem
1786  */
1787 static int
1788 nfs_root(struct mount *mp, int flags, struct vnode **vpp)
1789 {
1790         struct vnode *vp;
1791         struct nfsmount *nmp;
1792         struct nfsnode *np;
1793         int error;
1794
1795         nmp = VFSTONFS(mp);
1796         error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, flags);
1797         if (error)
1798                 return error;
1799         vp = NFSTOV(np);
1800         /*
1801          * Get transfer parameters and attributes for root vnode once.
1802          */
1803         mtx_lock(&nmp->nm_mtx);
1804         if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
1805                 mtx_unlock(&nmp->nm_mtx);
1806                 ncl_fsinfo(nmp, vp, curthread->td_ucred, curthread);
1807         } else 
1808                 mtx_unlock(&nmp->nm_mtx);
1809         if (vp->v_type == VNON)
1810             vp->v_type = VDIR;
1811         vp->v_vflag |= VV_ROOT;
1812         *vpp = vp;
1813         return (0);
1814 }
1815
1816 /*
1817  * Flush out the buffer cache
1818  */
1819 /* ARGSUSED */
1820 static int
1821 nfs_sync(struct mount *mp, int waitfor)
1822 {
1823         struct vnode *vp, *mvp;
1824         struct thread *td;
1825         int error, allerror = 0;
1826
1827         td = curthread;
1828
1829         MNT_ILOCK(mp);
1830         /*
1831          * If a forced dismount is in progress, return from here so that
1832          * the umount(2) syscall doesn't get stuck in VFS_SYNC() before
1833          * calling VFS_UNMOUNT().
1834          */
1835         if (NFSCL_FORCEDISM(mp)) {
1836                 MNT_IUNLOCK(mp);
1837                 return (EBADF);
1838         }
1839         MNT_IUNLOCK(mp);
1840
1841         /*
1842          * Force stale buffer cache information to be flushed.
1843          */
1844 loop:
1845         MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
1846                 /* XXX Racy bv_cnt check. */
1847                 if (NFSVOPISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
1848                     waitfor == MNT_LAZY) {
1849                         VI_UNLOCK(vp);
1850                         continue;
1851                 }
1852                 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK)) {
1853                         MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
1854                         goto loop;
1855                 }
1856                 error = VOP_FSYNC(vp, waitfor, td);
1857                 if (error)
1858                         allerror = error;
1859                 NFSVOPUNLOCK(vp);
1860                 vrele(vp);
1861         }
1862         return (allerror);
1863 }
1864
1865 static int
1866 nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
1867 {
1868         struct nfsmount *nmp = VFSTONFS(mp);
1869         struct vfsquery vq;
1870         int error;
1871
1872         bzero(&vq, sizeof(vq));
1873         switch (op) {
1874 #if 0
1875         case VFS_CTL_NOLOCKS:
1876                 val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
1877                 if (req->oldptr != NULL) {
1878                         error = SYSCTL_OUT(req, &val, sizeof(val));
1879                         if (error)
1880                                 return (error);
1881                 }
1882                 if (req->newptr != NULL) {
1883                         error = SYSCTL_IN(req, &val, sizeof(val));
1884                         if (error)
1885                                 return (error);
1886                         if (val)
1887                                 nmp->nm_flag |= NFSMNT_NOLOCKS;
1888                         else
1889                                 nmp->nm_flag &= ~NFSMNT_NOLOCKS;
1890                 }
1891                 break;
1892 #endif
1893         case VFS_CTL_QUERY:
1894                 mtx_lock(&nmp->nm_mtx);
1895                 if (nmp->nm_state & NFSSTA_TIMEO)
1896                         vq.vq_flags |= VQ_NOTRESP;
1897                 mtx_unlock(&nmp->nm_mtx);
1898 #if 0
1899                 if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
1900                     (nmp->nm_state & NFSSTA_LOCKTIMEO))
1901                         vq.vq_flags |= VQ_NOTRESPLOCK;
1902 #endif
1903                 error = SYSCTL_OUT(req, &vq, sizeof(vq));
1904                 break;
1905         case VFS_CTL_TIMEO:
1906                 if (req->oldptr != NULL) {
1907                         error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
1908                             sizeof(nmp->nm_tprintf_initial_delay));
1909                         if (error)
1910                                 return (error);
1911                 }
1912                 if (req->newptr != NULL) {
1913                         error = vfs_suser(mp, req->td);
1914                         if (error)
1915                                 return (error);
1916                         error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
1917                             sizeof(nmp->nm_tprintf_initial_delay));
1918                         if (error)
1919                                 return (error);
1920                         if (nmp->nm_tprintf_initial_delay < 0)
1921                                 nmp->nm_tprintf_initial_delay = 0;
1922                 }
1923                 break;
1924         default:
1925                 return (ENOTSUP);
1926         }
1927         return (0);
1928 }
1929
1930 /*
1931  * Purge any RPCs in progress, so that they will all return errors.
1932  * This allows dounmount() to continue as far as VFS_UNMOUNT() for a
1933  * forced dismount.
1934  */
1935 static void
1936 nfs_purge(struct mount *mp)
1937 {
1938         struct nfsmount *nmp = VFSTONFS(mp);
1939
1940         newnfs_nmcancelreqs(nmp);
1941 }
1942
1943 /*
1944  * Extract the information needed by the nlm from the nfs vnode.
1945  */
1946 static void
1947 nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp,
1948     struct sockaddr_storage *sp, int *is_v3p, off_t *sizep,
1949     struct timeval *timeop)
1950 {
1951         struct nfsmount *nmp;
1952         struct nfsnode *np = VTONFS(vp);
1953
1954         nmp = VFSTONFS(vp->v_mount);
1955         if (fhlenp != NULL)
1956                 *fhlenp = (size_t)np->n_fhp->nfh_len;
1957         if (fhp != NULL)
1958                 bcopy(np->n_fhp->nfh_fh, fhp, np->n_fhp->nfh_len);
1959         if (sp != NULL)
1960                 bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp)));
1961         if (is_v3p != NULL)
1962                 *is_v3p = NFS_ISV3(vp);
1963         if (sizep != NULL)
1964                 *sizep = np->n_size;
1965         if (timeop != NULL) {
1966                 timeop->tv_sec = nmp->nm_timeo / NFS_HZ;
1967                 timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ);
1968         }
1969 }
1970
1971 /*
1972  * This function prints out an option name, based on the conditional
1973  * argument.
1974  */
1975 static __inline void nfscl_printopt(struct nfsmount *nmp, int testval,
1976     char *opt, char **buf, size_t *blen)
1977 {
1978         int len;
1979
1980         if (testval != 0 && *blen > strlen(opt)) {
1981                 len = snprintf(*buf, *blen, "%s", opt);
1982                 if (len != strlen(opt))
1983                         printf("EEK!!\n");
1984                 *buf += len;
1985                 *blen -= len;
1986         }
1987 }
1988
1989 /*
1990  * This function printf out an options integer value.
1991  */
1992 static __inline void nfscl_printoptval(struct nfsmount *nmp, int optval,
1993     char *opt, char **buf, size_t *blen)
1994 {
1995         int len;
1996
1997         if (*blen > strlen(opt) + 1) {
1998                 /* Could result in truncated output string. */
1999                 len = snprintf(*buf, *blen, "%s=%d", opt, optval);
2000                 if (len < *blen) {
2001                         *buf += len;
2002                         *blen -= len;
2003                 }
2004         }
2005 }
2006
2007 /*
2008  * Load the option flags and values into the buffer.
2009  */
2010 void nfscl_retopts(struct nfsmount *nmp, char *buffer, size_t buflen)
2011 {
2012         char *buf;
2013         size_t blen;
2014
2015         buf = buffer;
2016         blen = buflen;
2017         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV4) != 0, "nfsv4", &buf,
2018             &blen);
2019         if ((nmp->nm_flag & NFSMNT_NFSV4) != 0) {
2020                 nfscl_printoptval(nmp, nmp->nm_minorvers, ",minorversion", &buf,
2021                     &blen);
2022                 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_PNFS) != 0, ",pnfs",
2023                     &buf, &blen);
2024                 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_ONEOPENOWN) != 0 &&
2025                     nmp->nm_minorvers > 0, ",oneopenown", &buf, &blen);
2026         }
2027         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV3) != 0, "nfsv3", &buf,
2028             &blen);
2029         nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0,
2030             "nfsv2", &buf, &blen);
2031         nfscl_printopt(nmp, nmp->nm_sotype == SOCK_STREAM, ",tcp", &buf, &blen);
2032         nfscl_printopt(nmp, nmp->nm_sotype != SOCK_STREAM, ",udp", &buf, &blen);
2033         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RESVPORT) != 0, ",resvport",
2034             &buf, &blen);
2035         nfscl_printopt(nmp, (nmp->nm_newflag & NFSMNT_TLS) != 0, ",tls", &buf,
2036             &blen);
2037         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCONN) != 0, ",noconn",
2038             &buf, &blen);
2039         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) == 0, ",hard", &buf,
2040             &blen);
2041         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) != 0, ",soft", &buf,
2042             &blen);
2043         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_INT) != 0, ",intr", &buf,
2044             &blen);
2045         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) == 0, ",cto", &buf,
2046             &blen);
2047         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) != 0, ",nocto", &buf,
2048             &blen);
2049         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NONCONTIGWR) != 0,
2050             ",noncontigwr", &buf, &blen);
2051         nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
2052             0, ",lockd", &buf, &blen);
2053         nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
2054             NFSMNT_NOLOCKD, ",nolockd", &buf, &blen);
2055         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RDIRPLUS) != 0, ",rdirplus",
2056             &buf, &blen);
2057         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_KERB) == 0, ",sec=sys",
2058             &buf, &blen);
2059         nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
2060             NFSMNT_PRIVACY)) == NFSMNT_KERB, ",sec=krb5", &buf, &blen);
2061         nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
2062             NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_INTEGRITY), ",sec=krb5i",
2063             &buf, &blen);
2064         nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
2065             NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_PRIVACY), ",sec=krb5p",
2066             &buf, &blen);
2067         nfscl_printoptval(nmp, nmp->nm_acdirmin, ",acdirmin", &buf, &blen);
2068         nfscl_printoptval(nmp, nmp->nm_acdirmax, ",acdirmax", &buf, &blen);
2069         nfscl_printoptval(nmp, nmp->nm_acregmin, ",acregmin", &buf, &blen);
2070         nfscl_printoptval(nmp, nmp->nm_acregmax, ",acregmax", &buf, &blen);
2071         nfscl_printoptval(nmp, nmp->nm_nametimeo, ",nametimeo", &buf, &blen);
2072         nfscl_printoptval(nmp, nmp->nm_negnametimeo, ",negnametimeo", &buf,
2073             &blen);
2074         nfscl_printoptval(nmp, nmp->nm_rsize, ",rsize", &buf, &blen);
2075         nfscl_printoptval(nmp, nmp->nm_wsize, ",wsize", &buf, &blen);
2076         nfscl_printoptval(nmp, nmp->nm_readdirsize, ",readdirsize", &buf,
2077             &blen);
2078         nfscl_printoptval(nmp, nmp->nm_readahead, ",readahead", &buf, &blen);
2079         nfscl_printoptval(nmp, nmp->nm_wcommitsize, ",wcommitsize", &buf,
2080             &blen);
2081         nfscl_printoptval(nmp, nmp->nm_timeo, ",timeout", &buf, &blen);
2082         nfscl_printoptval(nmp, nmp->nm_retry, ",retrans", &buf, &blen);
2083 }