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