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