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