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