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