]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - sys/fs/nfsclient/nfs_clvfsops.c
MFC r231852,232127:
[FreeBSD/stable/8.git] / sys / fs / nfsclient / nfs_clvfsops.c
1 /*-
2  * Copyright (c) 1989, 1993, 1995
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Rick Macklem at The University of Guelph.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 4. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  *      from nfs_vfsops.c       8.12 (Berkeley) 5/20/95
33  */
34
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
37
38
39 #include "opt_bootp.h"
40 #include "opt_nfsroot.h"
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/bio.h>
46 #include <sys/buf.h>
47 #include <sys/clock.h>
48 #include <sys/jail.h>
49 #include <sys/limits.h>
50 #include <sys/lock.h>
51 #include <sys/malloc.h>
52 #include <sys/mbuf.h>
53 #include <sys/module.h>
54 #include <sys/mount.h>
55 #include <sys/proc.h>
56 #include <sys/socket.h>
57 #include <sys/socketvar.h>
58 #include <sys/sockio.h>
59 #include <sys/sysctl.h>
60 #include <sys/vnode.h>
61 #include <sys/signalvar.h>
62
63 #include <vm/vm.h>
64 #include <vm/vm_extern.h>
65 #include <vm/uma.h>
66
67 #include <net/if.h>
68 #include <net/route.h>
69 #include <netinet/in.h>
70
71 #include <fs/nfs/nfsport.h>
72 #include <fs/nfsclient/nfsnode.h>
73 #include <fs/nfsclient/nfsmount.h>
74 #include <fs/nfsclient/nfs.h>
75 #include <nfs/nfsdiskless.h>
76
77 extern int nfscl_ticks;
78 extern struct timeval nfsboottime;
79 extern struct nfsstats  newnfsstats;
80 extern int nfsrv_useacl;
81
82 MALLOC_DEFINE(M_NEWNFSREQ, "newnfsclient_req", "New NFS request header");
83 MALLOC_DEFINE(M_NEWNFSMNT, "newnfsmnt", "New NFS mount struct");
84
85 SYSCTL_DECL(_vfs_newnfs);
86 SYSCTL_STRUCT(_vfs_newnfs, NFS_NFSSTATS, nfsstats, CTLFLAG_RW,
87         &newnfsstats, nfsstats, "S,nfsstats");
88 static int nfs_ip_paranoia = 1;
89 SYSCTL_INT(_vfs_newnfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW,
90     &nfs_ip_paranoia, 0, "");
91 static int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
92 SYSCTL_INT(_vfs_newnfs, NFS_TPRINTF_INITIAL_DELAY,
93         downdelayinitial, CTLFLAG_RW, &nfs_tprintf_initial_delay, 0, "");
94 /* how long between console messages "nfs server foo not responding" */
95 static int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
96 SYSCTL_INT(_vfs_newnfs, NFS_TPRINTF_DELAY,
97         downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0, "");
98
99 static int      nfs_mountroot(struct mount *);
100 static void     nfs_sec_name(char *, int *);
101 static void     nfs_decode_args(struct mount *mp, struct nfsmount *nmp,
102                     struct nfs_args *argp, const char *, struct ucred *,
103                     struct thread *);
104 static int      mountnfs(struct nfs_args *, struct mount *,
105                     struct sockaddr *, char *, u_char *, int, u_char *, int,
106                     u_char *, int, struct vnode **, struct ucred *,
107                     struct thread *, int);
108 static void     nfs_getnlminfo(struct vnode *, uint8_t *, size_t *,
109                     struct sockaddr_storage *, int *, off_t *,
110                     struct timeval *);
111 static vfs_mount_t nfs_mount;
112 static vfs_cmount_t nfs_cmount;
113 static vfs_unmount_t nfs_unmount;
114 static vfs_root_t nfs_root;
115 static vfs_statfs_t nfs_statfs;
116 static vfs_sync_t nfs_sync;
117 static vfs_sysctl_t nfs_sysctl;
118
119 /*
120  * nfs vfs operations.
121  */
122 static struct vfsops nfs_vfsops = {
123         .vfs_init =             ncl_init,
124         .vfs_mount =            nfs_mount,
125         .vfs_cmount =           nfs_cmount,
126         .vfs_root =             nfs_root,
127         .vfs_statfs =           nfs_statfs,
128         .vfs_sync =             nfs_sync,
129         .vfs_uninit =           ncl_uninit,
130         .vfs_unmount =          nfs_unmount,
131         .vfs_sysctl =           nfs_sysctl,
132 };
133 VFS_SET(nfs_vfsops, newnfs, VFCF_NETWORK);
134
135 /* So that loader and kldload(2) can find us, wherever we are.. */
136 MODULE_VERSION(newnfs, 1);
137
138 /*
139  * This structure is now defined in sys/nfs/nfs_diskless.c so that it
140  * can be shared by both NFS clients. It is declared here so that it
141  * will be defined for kernels built without NFS_ROOT, although it
142  * isn't used in that case.
143  */
144 #if !defined(NFS_ROOT) && !defined(NFSCLIENT)
145 struct nfs_diskless     nfs_diskless = { { { 0 } } };
146 struct nfsv3_diskless   nfsv3_diskless = { { { 0 } } };
147 int                     nfs_diskless_valid = 0;
148 #endif
149
150 SYSCTL_INT(_vfs_newnfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
151     &nfs_diskless_valid, 0,
152     "Has the diskless struct been filled correctly");
153
154 SYSCTL_STRING(_vfs_newnfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
155     nfsv3_diskless.root_hostnam, 0, "Path to nfs root");
156
157 SYSCTL_OPAQUE(_vfs_newnfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
158     &nfsv3_diskless.root_saddr, sizeof(nfsv3_diskless.root_saddr),
159     "%Ssockaddr_in", "Diskless root nfs address");
160
161
162 void            newnfsargs_ntoh(struct nfs_args *);
163 static int      nfs_mountdiskless(char *,
164                     struct sockaddr_in *, struct nfs_args *,
165                     struct thread *, struct vnode **, struct mount *);
166 static void     nfs_convert_diskless(void);
167 static void     nfs_convert_oargs(struct nfs_args *args,
168                     struct onfs_args *oargs);
169
170 int
171 newnfs_iosize(struct nfsmount *nmp)
172 {
173         int iosize, maxio;
174
175         /* First, set the upper limit for iosize */
176         if (nmp->nm_flag & NFSMNT_NFSV4) {
177                 maxio = NFS_MAXBSIZE;
178         } else if (nmp->nm_flag & NFSMNT_NFSV3) {
179                 if (nmp->nm_sotype == SOCK_DGRAM)
180                         maxio = NFS_MAXDGRAMDATA;
181                 else
182                         maxio = NFS_MAXBSIZE;
183         } else {
184                 maxio = NFS_V2MAXDATA;
185         }
186         if (nmp->nm_rsize > maxio || nmp->nm_rsize == 0)
187                 nmp->nm_rsize = maxio;
188         if (nmp->nm_rsize > MAXBSIZE)
189                 nmp->nm_rsize = MAXBSIZE;
190         if (nmp->nm_readdirsize > maxio || nmp->nm_readdirsize == 0)
191                 nmp->nm_readdirsize = maxio;
192         if (nmp->nm_readdirsize > nmp->nm_rsize)
193                 nmp->nm_readdirsize = nmp->nm_rsize;
194         if (nmp->nm_wsize > maxio || nmp->nm_wsize == 0)
195                 nmp->nm_wsize = maxio;
196         if (nmp->nm_wsize > MAXBSIZE)
197                 nmp->nm_wsize = MAXBSIZE;
198
199         /*
200          * Calculate the size used for io buffers.  Use the larger
201          * of the two sizes to minimise nfs requests but make sure
202          * that it is at least one VM page to avoid wasting buffer
203          * space.
204          */
205         iosize = imax(nmp->nm_rsize, nmp->nm_wsize);
206         iosize = imax(iosize, PAGE_SIZE);
207         nmp->nm_mountp->mnt_stat.f_iosize = iosize;
208         return (iosize);
209 }
210
211 static void
212 nfs_convert_oargs(struct nfs_args *args, struct onfs_args *oargs)
213 {
214
215         args->version = NFS_ARGSVERSION;
216         args->addr = oargs->addr;
217         args->addrlen = oargs->addrlen;
218         args->sotype = oargs->sotype;
219         args->proto = oargs->proto;
220         args->fh = oargs->fh;
221         args->fhsize = oargs->fhsize;
222         args->flags = oargs->flags;
223         args->wsize = oargs->wsize;
224         args->rsize = oargs->rsize;
225         args->readdirsize = oargs->readdirsize;
226         args->timeo = oargs->timeo;
227         args->retrans = oargs->retrans;
228         args->readahead = oargs->readahead;
229         args->hostname = oargs->hostname;
230 }
231
232 static void
233 nfs_convert_diskless(void)
234 {
235
236         bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
237                 sizeof(struct ifaliasreq));
238         bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
239                 sizeof(struct sockaddr_in));
240         nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
241         if (nfsv3_diskless.root_args.flags & NFSMNT_NFSV3) {
242                 nfsv3_diskless.root_fhsize = NFSX_MYFH;
243                 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_MYFH);
244         } else {
245                 nfsv3_diskless.root_fhsize = NFSX_V2FH;
246                 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
247         }
248         bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
249                 sizeof(struct sockaddr_in));
250         bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN);
251         nfsv3_diskless.root_time = nfs_diskless.root_time;
252         bcopy(nfs_diskless.my_hostnam, nfsv3_diskless.my_hostnam,
253                 MAXHOSTNAMELEN);
254         nfs_diskless_valid = 3;
255 }
256
257 /*
258  * nfs statfs call
259  */
260 static int
261 nfs_statfs(struct mount *mp, struct statfs *sbp)
262 {
263         struct vnode *vp;
264         struct thread *td;
265         struct nfsmount *nmp = VFSTONFS(mp);
266         struct nfsvattr nfsva;
267         struct nfsfsinfo fs;
268         struct nfsstatfs sb;
269         int error = 0, attrflag, gotfsinfo = 0, ret;
270         struct nfsnode *np;
271
272         td = curthread;
273
274         error = vfs_busy(mp, MBF_NOWAIT);
275         if (error)
276                 return (error);
277         error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
278         if (error) {
279                 vfs_unbusy(mp);
280                 return (error);
281         }
282         vp = NFSTOV(np);
283         mtx_lock(&nmp->nm_mtx);
284         if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
285                 mtx_unlock(&nmp->nm_mtx);
286                 error = nfsrpc_fsinfo(vp, &fs, td->td_ucred, td, &nfsva,
287                     &attrflag, NULL);
288                 if (!error)
289                         gotfsinfo = 1;
290         } else
291                 mtx_unlock(&nmp->nm_mtx);
292         if (!error)
293                 error = nfsrpc_statfs(vp, &sb, &fs, td->td_ucred, td, &nfsva,
294                     &attrflag, NULL);
295         if (attrflag == 0) {
296                 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
297                     td->td_ucred, td, &nfsva, NULL);
298                 if (ret) {
299                         /*
300                          * Just set default values to get things going.
301                          */
302                         NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
303                         nfsva.na_vattr.va_type = VDIR;
304                         nfsva.na_vattr.va_mode = 0777;
305                         nfsva.na_vattr.va_nlink = 100;
306                         nfsva.na_vattr.va_uid = (uid_t)0;
307                         nfsva.na_vattr.va_gid = (gid_t)0;
308                         nfsva.na_vattr.va_fileid = 2;
309                         nfsva.na_vattr.va_gen = 1;
310                         nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
311                         nfsva.na_vattr.va_size = 512 * 1024;
312                 }
313         }
314         (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
315         if (!error) {
316             mtx_lock(&nmp->nm_mtx);
317             if (gotfsinfo || (nmp->nm_flag & NFSMNT_NFSV4))
318                 nfscl_loadfsinfo(nmp, &fs);
319             nfscl_loadsbinfo(nmp, &sb, sbp);
320             sbp->f_iosize = newnfs_iosize(nmp);
321             mtx_unlock(&nmp->nm_mtx);
322             if (sbp != &mp->mnt_stat) {
323                 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
324                 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
325             }
326             strncpy(&sbp->f_fstypename[0], mp->mnt_vfc->vfc_name, MFSNAMELEN);
327         } else if (NFS_ISV4(vp)) {
328                 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
329         }
330         vput(vp);
331         vfs_unbusy(mp);
332         return (error);
333 }
334
335 /*
336  * nfs version 3 fsinfo rpc call
337  */
338 int
339 ncl_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred,
340     struct thread *td)
341 {
342         struct nfsfsinfo fs;
343         struct nfsvattr nfsva;
344         int error, attrflag;
345         
346         error = nfsrpc_fsinfo(vp, &fs, cred, td, &nfsva, &attrflag, NULL);
347         if (!error) {
348                 if (attrflag)
349                         (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0,
350                             1);
351                 mtx_lock(&nmp->nm_mtx);
352                 nfscl_loadfsinfo(nmp, &fs);
353                 mtx_unlock(&nmp->nm_mtx);
354         }
355         return (error);
356 }
357
358 /*
359  * Mount a remote root fs via. nfs. This depends on the info in the
360  * nfs_diskless structure that has been filled in properly by some primary
361  * bootstrap.
362  * It goes something like this:
363  * - do enough of "ifconfig" by calling ifioctl() so that the system
364  *   can talk to the server
365  * - If nfs_diskless.mygateway is filled in, use that address as
366  *   a default gateway.
367  * - build the rootfs mount point and call mountnfs() to do the rest.
368  *
369  * It is assumed to be safe to read, modify, and write the nfsv3_diskless
370  * structure, as well as other global NFS client variables here, as
371  * nfs_mountroot() will be called once in the boot before any other NFS
372  * client activity occurs.
373  */
374 static int
375 nfs_mountroot(struct mount *mp)
376 {
377         struct thread *td = curthread;
378         struct nfsv3_diskless *nd = &nfsv3_diskless;
379         struct socket *so;
380         struct vnode *vp;
381         struct ifreq ir;
382         int error;
383         u_long l;
384         char buf[128];
385         char *cp;
386
387 #if defined(BOOTP_NFSROOT) && defined(BOOTP)
388         bootpc_init();          /* use bootp to get nfs_diskless filled in */
389 #elif defined(NFS_ROOT)
390         nfs_setup_diskless();
391 #endif
392
393         if (nfs_diskless_valid == 0)
394                 return (-1);
395         if (nfs_diskless_valid == 1)
396                 nfs_convert_diskless();
397
398         /*
399          * XXX splnet, so networks will receive...
400          */
401         splnet();
402
403         /*
404          * Do enough of ifconfig(8) so that the critical net interface can
405          * talk to the server.
406          */
407         error = socreate(nd->myif.ifra_addr.sa_family, &so, nd->root_args.sotype, 0,
408             td->td_ucred, td);
409         if (error)
410                 panic("nfs_mountroot: socreate(%04x): %d",
411                         nd->myif.ifra_addr.sa_family, error);
412
413 #if 0 /* XXX Bad idea */
414         /*
415          * We might not have been told the right interface, so we pass
416          * over the first ten interfaces of the same kind, until we get
417          * one of them configured.
418          */
419
420         for (i = strlen(nd->myif.ifra_name) - 1;
421                 nd->myif.ifra_name[i] >= '0' &&
422                 nd->myif.ifra_name[i] <= '9';
423                 nd->myif.ifra_name[i] ++) {
424                 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
425                 if(!error)
426                         break;
427         }
428 #endif
429         error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
430         if (error)
431                 panic("nfs_mountroot: SIOCAIFADDR: %d", error);
432         if ((cp = getenv("boot.netif.mtu")) != NULL) {
433                 ir.ifr_mtu = strtol(cp, NULL, 10);
434                 bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ);
435                 freeenv(cp);
436                 error = ifioctl(so, SIOCSIFMTU, (caddr_t)&ir, td);
437                 if (error)
438                         printf("nfs_mountroot: SIOCSIFMTU: %d", error);
439         }
440         soclose(so);
441
442         /*
443          * If the gateway field is filled in, set it as the default route.
444          * Note that pxeboot will set a default route of 0 if the route
445          * is not set by the DHCP server.  Check also for a value of 0
446          * to avoid panicking inappropriately in that situation.
447          */
448         if (nd->mygateway.sin_len != 0 &&
449             nd->mygateway.sin_addr.s_addr != 0) {
450                 struct sockaddr_in mask, sin;
451
452                 bzero((caddr_t)&mask, sizeof(mask));
453                 sin = mask;
454                 sin.sin_family = AF_INET;
455                 sin.sin_len = sizeof(sin);
456                 /* XXX MRT use table 0 for this sort of thing */
457                 CURVNET_SET(TD_TO_VNET(td));
458                 error = rtrequest_fib(RTM_ADD, (struct sockaddr *)&sin,
459                     (struct sockaddr *)&nd->mygateway,
460                     (struct sockaddr *)&mask,
461                     RTF_UP | RTF_GATEWAY, NULL, RT_DEFAULT_FIB);
462                 CURVNET_RESTORE();
463                 if (error)
464                         panic("nfs_mountroot: RTM_ADD: %d", error);
465         }
466
467         /*
468          * Create the rootfs mount point.
469          */
470         nd->root_args.fh = nd->root_fh;
471         nd->root_args.fhsize = nd->root_fhsize;
472         l = ntohl(nd->root_saddr.sin_addr.s_addr);
473         snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
474                 (l >> 24) & 0xff, (l >> 16) & 0xff,
475                 (l >>  8) & 0xff, (l >>  0) & 0xff, nd->root_hostnam);
476         printf("NFS ROOT: %s\n", buf);
477         nd->root_args.hostname = buf;
478         if ((error = nfs_mountdiskless(buf,
479             &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) {
480                 return (error);
481         }
482
483         /*
484          * This is not really an nfs issue, but it is much easier to
485          * set hostname here and then let the "/etc/rc.xxx" files
486          * mount the right /var based upon its preset value.
487          */
488         mtx_lock(&prison0.pr_mtx);
489         strlcpy(prison0.pr_hostname, nd->my_hostnam,
490             sizeof(prison0.pr_hostname));
491         mtx_unlock(&prison0.pr_mtx);
492         inittodr(ntohl(nd->root_time));
493         return (0);
494 }
495
496 /*
497  * Internal version of mount system call for diskless setup.
498  */
499 static int
500 nfs_mountdiskless(char *path,
501     struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
502     struct vnode **vpp, struct mount *mp)
503 {
504         struct sockaddr *nam;
505         int dirlen, error;
506         char *dirpath;
507
508         /*
509          * Find the directory path in "path", which also has the server's
510          * name/ip address in it.
511          */
512         dirpath = strchr(path, ':');
513         if (dirpath != NULL)
514                 dirlen = strlen(++dirpath);
515         else
516                 dirlen = 0;
517         nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
518         if ((error = mountnfs(args, mp, nam, path, NULL, 0, dirpath, dirlen,
519             NULL, 0, vpp, td->td_ucred, td, NFS_DEFAULT_NEGNAMETIMEO)) != 0) {
520                 printf("nfs_mountroot: mount %s on /: %d\n", path, error);
521                 return (error);
522         }
523         return (0);
524 }
525
526 static void
527 nfs_sec_name(char *sec, int *flagsp)
528 {
529         if (!strcmp(sec, "krb5"))
530                 *flagsp |= NFSMNT_KERB;
531         else if (!strcmp(sec, "krb5i"))
532                 *flagsp |= (NFSMNT_KERB | NFSMNT_INTEGRITY);
533         else if (!strcmp(sec, "krb5p"))
534                 *flagsp |= (NFSMNT_KERB | NFSMNT_PRIVACY);
535 }
536
537 static void
538 nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
539     const char *hostname, struct ucred *cred, struct thread *td)
540 {
541         int s;
542         int adjsock;
543         char *p;
544
545         s = splnet();
546
547         /*
548          * Set read-only flag if requested; otherwise, clear it if this is
549          * an update.  If this is not an update, then either the read-only
550          * flag is already clear, or this is a root mount and it was set
551          * intentionally at some previous point.
552          */
553         if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) {
554                 MNT_ILOCK(mp);
555                 mp->mnt_flag |= MNT_RDONLY;
556                 MNT_IUNLOCK(mp);
557         } else if (mp->mnt_flag & MNT_UPDATE) {
558                 MNT_ILOCK(mp);
559                 mp->mnt_flag &= ~MNT_RDONLY;
560                 MNT_IUNLOCK(mp);
561         }
562
563         /*
564          * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
565          * no sense in that context.  Also, set up appropriate retransmit
566          * and soft timeout behavior.
567          */
568         if (argp->sotype == SOCK_STREAM) {
569                 nmp->nm_flag &= ~NFSMNT_NOCONN;
570                 nmp->nm_timeo = NFS_MAXTIMEO;
571                 if ((argp->flags & NFSMNT_NFSV4) != 0)
572                         nmp->nm_retry = INT_MAX;
573                 else
574                         nmp->nm_retry = NFS_RETRANS_TCP;
575         }
576
577         /* Also clear RDIRPLUS if NFSv2, it crashes some servers */
578         if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
579                 argp->flags &= ~NFSMNT_RDIRPLUS;
580                 nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
581         }
582
583         /* Clear NFSMNT_RESVPORT for NFSv4, since it is not required. */
584         if ((argp->flags & NFSMNT_NFSV4) != 0) {
585                 argp->flags &= ~NFSMNT_RESVPORT;
586                 nmp->nm_flag &= ~NFSMNT_RESVPORT;
587         }
588
589         /* Re-bind if rsrvd port requested and wasn't on one */
590         adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
591                   && (argp->flags & NFSMNT_RESVPORT);
592         /* Also re-bind if we're switching to/from a connected UDP socket */
593         adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
594                     (argp->flags & NFSMNT_NOCONN));
595
596         /* Update flags atomically.  Don't change the lock bits. */
597         nmp->nm_flag = argp->flags | nmp->nm_flag;
598         splx(s);
599
600         if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
601                 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
602                 if (nmp->nm_timeo < NFS_MINTIMEO)
603                         nmp->nm_timeo = NFS_MINTIMEO;
604                 else if (nmp->nm_timeo > NFS_MAXTIMEO)
605                         nmp->nm_timeo = NFS_MAXTIMEO;
606         }
607
608         if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
609                 nmp->nm_retry = argp->retrans;
610                 if (nmp->nm_retry > NFS_MAXREXMIT)
611                         nmp->nm_retry = NFS_MAXREXMIT;
612         }
613
614         if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
615                 nmp->nm_wsize = argp->wsize;
616                 /* Round down to multiple of blocksize */
617                 nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
618                 if (nmp->nm_wsize <= 0)
619                         nmp->nm_wsize = NFS_FABLKSIZE;
620         }
621
622         if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
623                 nmp->nm_rsize = argp->rsize;
624                 /* Round down to multiple of blocksize */
625                 nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
626                 if (nmp->nm_rsize <= 0)
627                         nmp->nm_rsize = NFS_FABLKSIZE;
628         }
629
630         if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
631                 nmp->nm_readdirsize = argp->readdirsize;
632         }
633
634         if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
635                 nmp->nm_acregmin = argp->acregmin;
636         else
637                 nmp->nm_acregmin = NFS_MINATTRTIMO;
638         if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
639                 nmp->nm_acregmax = argp->acregmax;
640         else
641                 nmp->nm_acregmax = NFS_MAXATTRTIMO;
642         if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
643                 nmp->nm_acdirmin = argp->acdirmin;
644         else
645                 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
646         if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
647                 nmp->nm_acdirmax = argp->acdirmax;
648         else
649                 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
650         if (nmp->nm_acdirmin > nmp->nm_acdirmax)
651                 nmp->nm_acdirmin = nmp->nm_acdirmax;
652         if (nmp->nm_acregmin > nmp->nm_acregmax)
653                 nmp->nm_acregmin = nmp->nm_acregmax;
654
655         if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
656                 if (argp->readahead <= NFS_MAXRAHEAD)
657                         nmp->nm_readahead = argp->readahead;
658                 else
659                         nmp->nm_readahead = NFS_MAXRAHEAD;
660         }
661         if ((argp->flags & NFSMNT_WCOMMITSIZE) && argp->wcommitsize >= 0) {
662                 if (argp->wcommitsize < nmp->nm_wsize)
663                         nmp->nm_wcommitsize = nmp->nm_wsize;
664                 else
665                         nmp->nm_wcommitsize = argp->wcommitsize;
666         }
667
668         adjsock |= ((nmp->nm_sotype != argp->sotype) ||
669                     (nmp->nm_soproto != argp->proto));
670
671         if (nmp->nm_client != NULL && adjsock) {
672                 int haslock = 0, error = 0;
673
674                 if (nmp->nm_sotype == SOCK_STREAM) {
675                         error = newnfs_sndlock(&nmp->nm_sockreq.nr_lock);
676                         if (!error)
677                                 haslock = 1;
678                 }
679                 if (!error) {
680                     newnfs_disconnect(&nmp->nm_sockreq);
681                     if (haslock)
682                         newnfs_sndunlock(&nmp->nm_sockreq.nr_lock);
683                     nmp->nm_sotype = argp->sotype;
684                     nmp->nm_soproto = argp->proto;
685                     if (nmp->nm_sotype == SOCK_DGRAM)
686                         while (newnfs_connect(nmp, &nmp->nm_sockreq,
687                             cred, td, 0)) {
688                                 printf("newnfs_args: retrying connect\n");
689                                 (void) nfs_catnap(PSOCK, 0, "newnfscon");
690                         }
691                 }
692         } else {
693                 nmp->nm_sotype = argp->sotype;
694                 nmp->nm_soproto = argp->proto;
695         }
696
697         if (hostname != NULL) {
698                 strlcpy(nmp->nm_hostname, hostname,
699                     sizeof(nmp->nm_hostname));
700                 p = strchr(nmp->nm_hostname, ':');
701                 if (p != NULL)
702                         *p = '\0';
703         }
704 }
705
706 static const char *nfs_opts[] = { "from", "nfs_args",
707     "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
708     "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
709     "async", "noconn", "nolockd", "conn", "lockd", "intr", "rdirplus",
710     "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize",
711     "retrans", "acregmin", "acregmax", "acdirmin", "acdirmax", "resvport",
712     "readahead", "hostname", "timeout", "addr", "fh", "nfsv3", "sec",
713     "principal", "nfsv4", "gssname", "allgssname", "dirpath",
714     "negnametimeo", "nocto", "wcommitsize",
715     NULL };
716
717 /*
718  * VFS Operations.
719  *
720  * mount system call
721  * It seems a bit dumb to copyinstr() the host and path here and then
722  * bcopy() them in mountnfs(), but I wanted to detect errors before
723  * doing the sockargs() call because sockargs() allocates an mbuf and
724  * an error after that means that I have to release the mbuf.
725  */
726 /* ARGSUSED */
727 static int
728 nfs_mount(struct mount *mp)
729 {
730         struct nfs_args args = {
731             .version = NFS_ARGSVERSION,
732             .addr = NULL,
733             .addrlen = sizeof (struct sockaddr_in),
734             .sotype = SOCK_STREAM,
735             .proto = 0,
736             .fh = NULL,
737             .fhsize = 0,
738             .flags = NFSMNT_RESVPORT,
739             .wsize = NFS_WSIZE,
740             .rsize = NFS_RSIZE,
741             .readdirsize = NFS_READDIRSIZE,
742             .timeo = 10,
743             .retrans = NFS_RETRANS,
744             .readahead = NFS_DEFRAHEAD,
745             .wcommitsize = 0,                   /* was: NQ_DEFLEASE */
746             .hostname = NULL,
747             .acregmin = NFS_MINATTRTIMO,
748             .acregmax = NFS_MAXATTRTIMO,
749             .acdirmin = NFS_MINDIRATTRTIMO,
750             .acdirmax = NFS_MAXDIRATTRTIMO,
751         };
752         int error = 0, ret, len;
753         struct sockaddr *nam = NULL;
754         struct vnode *vp;
755         struct thread *td;
756         char hst[MNAMELEN];
757         u_char nfh[NFSX_FHMAX], krbname[100], dirpath[100], srvkrbname[100];
758         char *opt, *name, *secname;
759         int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
760         int dirlen, has_nfs_args_opt, krbnamelen, srvkrbnamelen;
761         size_t hstlen;
762
763         has_nfs_args_opt = 0;
764         if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
765                 error = EINVAL;
766                 goto out;
767         }
768
769         td = curthread;
770         if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS) {
771                 error = nfs_mountroot(mp);
772                 goto out;
773         }
774
775         nfscl_init();
776
777         /*
778          * The old mount_nfs program passed the struct nfs_args
779          * from userspace to kernel.  The new mount_nfs program
780          * passes string options via nmount() from userspace to kernel
781          * and we populate the struct nfs_args in the kernel.
782          */
783         if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
784                 error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
785                     sizeof(args));
786                 if (error != 0)
787                         goto out;
788
789                 if (args.version != NFS_ARGSVERSION) {
790                         error = EPROGMISMATCH;
791                         goto out;
792                 }
793                 has_nfs_args_opt = 1;
794         }
795
796         /* Handle the new style options. */
797         if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
798                 args.flags |= NFSMNT_NOCONN;
799         if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
800                 args.flags |= NFSMNT_NOCONN;
801         if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
802                 args.flags |= NFSMNT_NOLOCKD;
803         if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
804                 args.flags &= ~NFSMNT_NOLOCKD;
805         if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
806                 args.flags |= NFSMNT_INT;
807         if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
808                 args.flags |= NFSMNT_RDIRPLUS;
809         if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
810                 args.flags |= NFSMNT_RESVPORT;
811         if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
812                 args.flags &= ~NFSMNT_RESVPORT;
813         if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
814                 args.flags |= NFSMNT_SOFT;
815         if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
816                 args.flags &= ~NFSMNT_SOFT;
817         if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
818                 args.sotype = SOCK_DGRAM;
819         if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
820                 args.sotype = SOCK_DGRAM;
821         if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
822                 args.sotype = SOCK_STREAM;
823         if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
824                 args.flags |= NFSMNT_NFSV3;
825         if (vfs_getopt(mp->mnt_optnew, "nfsv4", NULL, NULL) == 0) {
826                 args.flags |= NFSMNT_NFSV4;
827                 args.sotype = SOCK_STREAM;
828         }
829         if (vfs_getopt(mp->mnt_optnew, "allgssname", NULL, NULL) == 0)
830                 args.flags |= NFSMNT_ALLGSSNAME;
831         if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0)
832                 args.flags |= NFSMNT_NOCTO;
833         if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
834                 if (opt == NULL) { 
835                         vfs_mount_error(mp, "illegal readdirsize");
836                         error = EINVAL;
837                         goto out;
838                 }
839                 ret = sscanf(opt, "%d", &args.readdirsize);
840                 if (ret != 1 || args.readdirsize <= 0) {
841                         vfs_mount_error(mp, "illegal readdirsize: %s",
842                             opt);
843                         error = EINVAL;
844                         goto out;
845                 }
846                 args.flags |= NFSMNT_READDIRSIZE;
847         }
848         if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
849                 if (opt == NULL) { 
850                         vfs_mount_error(mp, "illegal readahead");
851                         error = EINVAL;
852                         goto out;
853                 }
854                 ret = sscanf(opt, "%d", &args.readahead);
855                 if (ret != 1 || args.readahead <= 0) {
856                         vfs_mount_error(mp, "illegal readahead: %s",
857                             opt);
858                         error = EINVAL;
859                         goto out;
860                 }
861                 args.flags |= NFSMNT_READAHEAD;
862         }
863         if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
864                 if (opt == NULL) { 
865                         vfs_mount_error(mp, "illegal wsize");
866                         error = EINVAL;
867                         goto out;
868                 }
869                 ret = sscanf(opt, "%d", &args.wsize);
870                 if (ret != 1 || args.wsize <= 0) {
871                         vfs_mount_error(mp, "illegal wsize: %s",
872                             opt);
873                         error = EINVAL;
874                         goto out;
875                 }
876                 args.flags |= NFSMNT_WSIZE;
877         }
878         if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
879                 if (opt == NULL) { 
880                         vfs_mount_error(mp, "illegal rsize");
881                         error = EINVAL;
882                         goto out;
883                 }
884                 ret = sscanf(opt, "%d", &args.rsize);
885                 if (ret != 1 || args.rsize <= 0) {
886                         vfs_mount_error(mp, "illegal wsize: %s",
887                             opt);
888                         error = EINVAL;
889                         goto out;
890                 }
891                 args.flags |= NFSMNT_RSIZE;
892         }
893         if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
894                 if (opt == NULL) { 
895                         vfs_mount_error(mp, "illegal retrans");
896                         error = EINVAL;
897                         goto out;
898                 }
899                 ret = sscanf(opt, "%d", &args.retrans);
900                 if (ret != 1 || args.retrans <= 0) {
901                         vfs_mount_error(mp, "illegal retrans: %s",
902                             opt);
903                         error = EINVAL;
904                         goto out;
905                 }
906                 args.flags |= NFSMNT_RETRANS;
907         }
908         if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
909                 ret = sscanf(opt, "%d", &args.acregmin);
910                 if (ret != 1 || args.acregmin < 0) {
911                         vfs_mount_error(mp, "illegal acregmin: %s",
912                             opt);
913                         error = EINVAL;
914                         goto out;
915                 }
916                 args.flags |= NFSMNT_ACREGMIN;
917         }
918         if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
919                 ret = sscanf(opt, "%d", &args.acregmax);
920                 if (ret != 1 || args.acregmax < 0) {
921                         vfs_mount_error(mp, "illegal acregmax: %s",
922                             opt);
923                         error = EINVAL;
924                         goto out;
925                 }
926                 args.flags |= NFSMNT_ACREGMAX;
927         }
928         if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
929                 ret = sscanf(opt, "%d", &args.acdirmin);
930                 if (ret != 1 || args.acdirmin < 0) {
931                         vfs_mount_error(mp, "illegal acdirmin: %s",
932                             opt);
933                         error = EINVAL;
934                         goto out;
935                 }
936                 args.flags |= NFSMNT_ACDIRMIN;
937         }
938         if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
939                 ret = sscanf(opt, "%d", &args.acdirmax);
940                 if (ret != 1 || args.acdirmax < 0) {
941                         vfs_mount_error(mp, "illegal acdirmax: %s",
942                             opt);
943                         error = EINVAL;
944                         goto out;
945                 }
946                 args.flags |= NFSMNT_ACDIRMAX;
947         }
948         if (vfs_getopt(mp->mnt_optnew, "wcommitsize", (void **)&opt, NULL) == 0) {
949                 ret = sscanf(opt, "%d", &args.wcommitsize);
950                 if (ret != 1 || args.wcommitsize < 0) {
951                         vfs_mount_error(mp, "illegal wcommitsize: %s", opt);
952                         error = EINVAL;
953                         goto out;
954                 }
955                 args.flags |= NFSMNT_WCOMMITSIZE;
956         }
957         if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
958                 ret = sscanf(opt, "%d", &args.timeo);
959                 if (ret != 1 || args.timeo <= 0) {
960                         vfs_mount_error(mp, "illegal timeout: %s",
961                             opt);
962                         error = EINVAL;
963                         goto out;
964                 }
965                 args.flags |= NFSMNT_TIMEO;
966         }
967         if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
968             == 0) {
969                 ret = sscanf(opt, "%d", &negnametimeo);
970                 if (ret != 1 || negnametimeo < 0) {
971                         vfs_mount_error(mp, "illegal negnametimeo: %s",
972                             opt);
973                         error = EINVAL;
974                         goto out;
975                 }
976         }
977         if (vfs_getopt(mp->mnt_optnew, "sec",
978                 (void **) &secname, NULL) == 0)
979                 nfs_sec_name(secname, &args.flags);
980
981         if (mp->mnt_flag & MNT_UPDATE) {
982                 struct nfsmount *nmp = VFSTONFS(mp);
983
984                 if (nmp == NULL) {
985                         error = EIO;
986                         goto out;
987                 }
988
989                 /*
990                  * If a change from TCP->UDP is done and there are thread(s)
991                  * that have I/O RPC(s) in progress with a tranfer size
992                  * greater than NFS_MAXDGRAMDATA, those thread(s) will be
993                  * hung, retrying the RPC(s) forever. Usually these threads
994                  * will be seen doing an uninterruptible sleep on wait channel
995                  * "newnfsreq" (truncated to "newnfsre" by procstat).
996                  */
997                 if (args.sotype == SOCK_DGRAM && nmp->nm_sotype == SOCK_STREAM)
998                         tprintf(td->td_proc, LOG_WARNING,
999         "Warning: mount -u that changes TCP->UDP can result in hung threads\n");
1000
1001                 /*
1002                  * When doing an update, we can't change version,
1003                  * security, switch lockd strategies or change cookie
1004                  * translation
1005                  */
1006                 args.flags = (args.flags &
1007                     ~(NFSMNT_NFSV3 |
1008                       NFSMNT_NFSV4 |
1009                       NFSMNT_KERB |
1010                       NFSMNT_INTEGRITY |
1011                       NFSMNT_PRIVACY |
1012                       NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
1013                     (nmp->nm_flag &
1014                         (NFSMNT_NFSV3 |
1015                          NFSMNT_NFSV4 |
1016                          NFSMNT_KERB |
1017                          NFSMNT_INTEGRITY |
1018                          NFSMNT_PRIVACY |
1019                          NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
1020                 nfs_decode_args(mp, nmp, &args, NULL, td->td_ucred, td);
1021                 goto out;
1022         }
1023
1024         /*
1025          * Make the nfs_ip_paranoia sysctl serve as the default connection
1026          * or no-connection mode for those protocols that support 
1027          * no-connection mode (the flag will be cleared later for protocols
1028          * that do not support no-connection mode).  This will allow a client
1029          * to receive replies from a different IP then the request was
1030          * sent to.  Note: default value for nfs_ip_paranoia is 1 (paranoid),
1031          * not 0.
1032          */
1033         if (nfs_ip_paranoia == 0)
1034                 args.flags |= NFSMNT_NOCONN;
1035
1036         if (has_nfs_args_opt != 0) {
1037                 /*
1038                  * In the 'nfs_args' case, the pointers in the args
1039                  * structure are in userland - we copy them in here.
1040                  */
1041                 if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
1042                         vfs_mount_error(mp, "Bad file handle");
1043                         error = EINVAL;
1044                         goto out;
1045                 }
1046                 error = copyin((caddr_t)args.fh, (caddr_t)nfh,
1047                     args.fhsize);
1048                 if (error != 0)
1049                         goto out;
1050                 error = copyinstr(args.hostname, hst, MNAMELEN - 1, &hstlen);
1051                 if (error != 0)
1052                         goto out;
1053                 bzero(&hst[hstlen], MNAMELEN - hstlen);
1054                 args.hostname = hst;
1055                 /* sockargs() call must be after above copyin() calls */
1056                 error = getsockaddr(&nam, (caddr_t)args.addr,
1057                     args.addrlen);
1058                 if (error != 0)
1059                         goto out;
1060         } else {
1061                 if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
1062                     &args.fhsize) == 0) {
1063                         if (args.fhsize < 0 || args.fhsize > NFSX_FHMAX) {
1064                                 vfs_mount_error(mp, "Bad file handle");
1065                                 error = EINVAL;
1066                                 goto out;
1067                         }
1068                         bcopy(args.fh, nfh, args.fhsize);
1069                 } else {
1070                         args.fhsize = 0;
1071                 }
1072                 (void) vfs_getopt(mp->mnt_optnew, "hostname",
1073                     (void **)&args.hostname, &len);
1074                 if (args.hostname == NULL) {
1075                         vfs_mount_error(mp, "Invalid hostname");
1076                         error = EINVAL;
1077                         goto out;
1078                 }
1079                 bcopy(args.hostname, hst, MNAMELEN);
1080                 hst[MNAMELEN - 1] = '\0';
1081         }
1082
1083         if (vfs_getopt(mp->mnt_optnew, "principal", (void **)&name, NULL) == 0)
1084                 strlcpy(srvkrbname, name, sizeof (srvkrbname));
1085         else
1086                 snprintf(srvkrbname, sizeof (srvkrbname), "nfs@%s", hst);
1087         srvkrbnamelen = strlen(srvkrbname);
1088
1089         if (vfs_getopt(mp->mnt_optnew, "gssname", (void **)&name, NULL) == 0)
1090                 strlcpy(krbname, name, sizeof (krbname));
1091         else
1092                 krbname[0] = '\0';
1093         krbnamelen = strlen(krbname);
1094
1095         if (vfs_getopt(mp->mnt_optnew, "dirpath", (void **)&name, NULL) == 0)
1096                 strlcpy(dirpath, name, sizeof (dirpath));
1097         else
1098                 dirpath[0] = '\0';
1099         dirlen = strlen(dirpath);
1100
1101         if (has_nfs_args_opt == 0) {
1102                 if (vfs_getopt(mp->mnt_optnew, "addr",
1103                     (void **)&args.addr, &args.addrlen) == 0) {
1104                         if (args.addrlen > SOCK_MAXADDRLEN) {
1105                                 error = ENAMETOOLONG;
1106                                 goto out;
1107                         }
1108                         nam = malloc(args.addrlen, M_SONAME, M_WAITOK);
1109                         bcopy(args.addr, nam, args.addrlen);
1110                         nam->sa_len = args.addrlen;
1111                 } else {
1112                         vfs_mount_error(mp, "No server address");
1113                         error = EINVAL;
1114                         goto out;
1115                 }
1116         }
1117
1118         args.fh = nfh;
1119         error = mountnfs(&args, mp, nam, hst, krbname, krbnamelen, dirpath,
1120             dirlen, srvkrbname, srvkrbnamelen, &vp, td->td_ucred, td,
1121             negnametimeo);
1122 out:
1123         if (!error) {
1124                 MNT_ILOCK(mp);
1125                 mp->mnt_kern_flag |= (MNTK_MPSAFE|MNTK_LOOKUP_SHARED);
1126                 MNT_IUNLOCK(mp);
1127         }
1128         return (error);
1129 }
1130
1131
1132 /*
1133  * VFS Operations.
1134  *
1135  * mount system call
1136  * It seems a bit dumb to copyinstr() the host and path here and then
1137  * bcopy() them in mountnfs(), but I wanted to detect errors before
1138  * doing the sockargs() call because sockargs() allocates an mbuf and
1139  * an error after that means that I have to release the mbuf.
1140  */
1141 /* ARGSUSED */
1142 static int
1143 nfs_cmount(struct mntarg *ma, void *data, int flags)
1144 {
1145         int error;
1146         struct nfs_args args;
1147
1148         error = copyin(data, &args, sizeof (struct nfs_args));
1149         if (error)
1150                 return error;
1151
1152         ma = mount_arg(ma, "nfs_args", &args, sizeof args);
1153
1154         error = kernel_mount(ma, flags);
1155         return (error);
1156 }
1157
1158 /*
1159  * Common code for mount and mountroot
1160  */
1161 static int
1162 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
1163     char *hst, u_char *krbname, int krbnamelen, u_char *dirpath, int dirlen,
1164     u_char *srvkrbname, int srvkrbnamelen, struct vnode **vpp,
1165     struct ucred *cred, struct thread *td, int negnametimeo)
1166 {
1167         struct nfsmount *nmp;
1168         struct nfsnode *np;
1169         int error, trycnt, ret;
1170         struct nfsvattr nfsva;
1171         static u_int64_t clval = 0;
1172
1173         if (mp->mnt_flag & MNT_UPDATE) {
1174                 nmp = VFSTONFS(mp);
1175                 printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
1176                 FREE(nam, M_SONAME);
1177                 return (0);
1178         } else {
1179                 MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount) +
1180                     krbnamelen + dirlen + srvkrbnamelen + 2,
1181                     M_NEWNFSMNT, M_WAITOK | M_ZERO);
1182                 TAILQ_INIT(&nmp->nm_bufq);
1183                 if (clval == 0)
1184                         clval = (u_int64_t)nfsboottime.tv_sec;
1185                 nmp->nm_clval = clval++;
1186                 nmp->nm_krbnamelen = krbnamelen;
1187                 nmp->nm_dirpathlen = dirlen;
1188                 nmp->nm_srvkrbnamelen = srvkrbnamelen;
1189                 if (td->td_ucred->cr_uid != (uid_t)0) {
1190                         /*
1191                          * nm_uid is used to get KerberosV credentials for
1192                          * the nfsv4 state handling operations if there is
1193                          * no host based principal set. Use the uid of
1194                          * this user if not root, since they are doing the
1195                          * mount. I don't think setting this for root will
1196                          * work, since root normally does not have user
1197                          * credentials in a credentials cache.
1198                          */
1199                         nmp->nm_uid = td->td_ucred->cr_uid;
1200                 } else {
1201                         /*
1202                          * Just set to -1, so it won't be used.
1203                          */
1204                         nmp->nm_uid = (uid_t)-1;
1205                 }
1206
1207                 /* Copy and null terminate all the names */
1208                 if (nmp->nm_krbnamelen > 0) {
1209                         bcopy(krbname, nmp->nm_krbname, nmp->nm_krbnamelen);
1210                         nmp->nm_name[nmp->nm_krbnamelen] = '\0';
1211                 }
1212                 if (nmp->nm_dirpathlen > 0) {
1213                         bcopy(dirpath, NFSMNT_DIRPATH(nmp),
1214                             nmp->nm_dirpathlen);
1215                         nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1216                             + 1] = '\0';
1217                 }
1218                 if (nmp->nm_srvkrbnamelen > 0) {
1219                         bcopy(srvkrbname, NFSMNT_SRVKRBNAME(nmp),
1220                             nmp->nm_srvkrbnamelen);
1221                         nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1222                             + nmp->nm_srvkrbnamelen + 2] = '\0';
1223                 }
1224                 nmp->nm_sockreq.nr_cred = crhold(cred);
1225                 mtx_init(&nmp->nm_sockreq.nr_mtx, "nfssock", NULL, MTX_DEF);
1226                 mp->mnt_data = nmp;
1227                 nmp->nm_getinfo = nfs_getnlminfo;
1228                 nmp->nm_vinvalbuf = ncl_vinvalbuf;
1229         }
1230         vfs_getnewfsid(mp);
1231         nmp->nm_mountp = mp;
1232         mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF | MTX_DUPOK);                     
1233
1234         /*
1235          * Since nfs_decode_args() might optionally set them, these need to
1236          * set to defaults before the call, so that the optional settings
1237          * aren't overwritten.
1238          */
1239         nmp->nm_negnametimeo = negnametimeo;
1240         nmp->nm_timeo = NFS_TIMEO;
1241         nmp->nm_retry = NFS_RETRANS;
1242         nmp->nm_readahead = NFS_DEFRAHEAD;
1243         if (desiredvnodes >= 11000)
1244                 nmp->nm_wcommitsize = hibufspace / (desiredvnodes / 1000);
1245         else
1246                 nmp->nm_wcommitsize = hibufspace / 10;
1247
1248         nfs_decode_args(mp, nmp, argp, hst, cred, td);
1249
1250         /*
1251          * V2 can only handle 32 bit filesizes.  A 4GB-1 limit may be too
1252          * high, depending on whether we end up with negative offsets in
1253          * the client or server somewhere.  2GB-1 may be safer.
1254          *
1255          * For V3, ncl_fsinfo will adjust this as necessary.  Assume maximum
1256          * that we can handle until we find out otherwise.
1257          * XXX Our "safe" limit on the client is what we can store in our
1258          * buffer cache using signed(!) block numbers.
1259          */
1260         if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0)
1261                 nmp->nm_maxfilesize = 0xffffffffLL;
1262         else
1263                 nmp->nm_maxfilesize = OFF_MAX;
1264
1265         if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
1266                 nmp->nm_wsize = NFS_WSIZE;
1267                 nmp->nm_rsize = NFS_RSIZE;
1268                 nmp->nm_readdirsize = NFS_READDIRSIZE;
1269         }
1270         nmp->nm_numgrps = NFS_MAXGRPS;
1271         nmp->nm_tprintf_delay = nfs_tprintf_delay;
1272         if (nmp->nm_tprintf_delay < 0)
1273                 nmp->nm_tprintf_delay = 0;
1274         nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
1275         if (nmp->nm_tprintf_initial_delay < 0)
1276                 nmp->nm_tprintf_initial_delay = 0;
1277         nmp->nm_fhsize = argp->fhsize;
1278         if (nmp->nm_fhsize > 0)
1279                 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
1280         bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
1281         nmp->nm_nam = nam;
1282         /* Set up the sockets and per-host congestion */
1283         nmp->nm_sotype = argp->sotype;
1284         nmp->nm_soproto = argp->proto;
1285         nmp->nm_sockreq.nr_prog = NFS_PROG;
1286         if ((argp->flags & NFSMNT_NFSV4))
1287                 nmp->nm_sockreq.nr_vers = NFS_VER4;
1288         else if ((argp->flags & NFSMNT_NFSV3))
1289                 nmp->nm_sockreq.nr_vers = NFS_VER3;
1290         else
1291                 nmp->nm_sockreq.nr_vers = NFS_VER2;
1292
1293
1294         if ((error = newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0)))
1295                 goto bad;
1296
1297         /*
1298          * A reference count is needed on the nfsnode representing the
1299          * remote root.  If this object is not persistent, then backward
1300          * traversals of the mount point (i.e. "..") will not work if
1301          * the nfsnode gets flushed out of the cache. Ufs does not have
1302          * this problem, because one can identify root inodes by their
1303          * number == ROOTINO (2).
1304          */
1305         if (nmp->nm_fhsize == 0 && (nmp->nm_flag & NFSMNT_NFSV4) &&
1306             nmp->nm_dirpathlen > 0) {
1307                 /*
1308                  * If the fhsize on the mount point == 0 for V4, the mount
1309                  * path needs to be looked up.
1310                  */
1311                 trycnt = 3;
1312                 do {
1313                         error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp),
1314                             cred, td);
1315                         if (error)
1316                                 (void) nfs_catnap(PZERO, error, "nfsgetdirp");
1317                 } while (error && --trycnt > 0);
1318                 if (error) {
1319                         error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
1320                         goto bad;
1321                 }
1322         }
1323         if (nmp->nm_fhsize > 0) {
1324                 /*
1325                  * Set f_iosize to NFS_DIRBLKSIZ so that bo_bsize gets set
1326                  * non-zero for the root vnode. f_iosize will be set correctly
1327                  * by nfs_statfs() before any I/O occurs.
1328                  */
1329                 mp->mnt_stat.f_iosize = NFS_DIRBLKSIZ;
1330                 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np,
1331                     LK_EXCLUSIVE);
1332                 if (error)
1333                         goto bad;
1334                 *vpp = NFSTOV(np);
1335         
1336                 /*
1337                  * Get file attributes and transfer parameters for the
1338                  * mountpoint.  This has the side effect of filling in
1339                  * (*vpp)->v_type with the correct value.
1340                  */
1341                 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
1342                     cred, td, &nfsva, NULL);
1343                 if (ret) {
1344                         /*
1345                          * Just set default values to get things going.
1346                          */
1347                         NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
1348                         nfsva.na_vattr.va_type = VDIR;
1349                         nfsva.na_vattr.va_mode = 0777;
1350                         nfsva.na_vattr.va_nlink = 100;
1351                         nfsva.na_vattr.va_uid = (uid_t)0;
1352                         nfsva.na_vattr.va_gid = (gid_t)0;
1353                         nfsva.na_vattr.va_fileid = 2;
1354                         nfsva.na_vattr.va_gen = 1;
1355                         nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
1356                         nfsva.na_vattr.va_size = 512 * 1024;
1357                 }
1358                 (void) nfscl_loadattrcache(vpp, &nfsva, NULL, NULL, 0, 1);
1359                 if (argp->flags & NFSMNT_NFSV3)
1360                         ncl_fsinfo(nmp, *vpp, cred, td);
1361         
1362                 /* Mark if the mount point supports NFSv4 ACLs. */
1363                 if ((argp->flags & NFSMNT_NFSV4) != 0 && nfsrv_useacl != 0 &&
1364                     ret == 0 &&
1365                     NFSISSET_ATTRBIT(&nfsva.na_suppattr, NFSATTRBIT_ACL)) {
1366                         MNT_ILOCK(mp);
1367                         mp->mnt_flag |= MNT_NFS4ACLS;
1368                         MNT_IUNLOCK(mp);
1369                 }
1370         
1371                 /*
1372                  * Lose the lock but keep the ref.
1373                  */
1374                 NFSVOPUNLOCK(*vpp, 0);
1375                 return (0);
1376         }
1377         error = EIO;
1378
1379 bad:
1380         newnfs_disconnect(&nmp->nm_sockreq);
1381         crfree(nmp->nm_sockreq.nr_cred);
1382         mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1383         mtx_destroy(&nmp->nm_mtx);
1384         FREE(nmp, M_NEWNFSMNT);
1385         FREE(nam, M_SONAME);
1386         return (error);
1387 }
1388
1389 /*
1390  * unmount system call
1391  */
1392 static int
1393 nfs_unmount(struct mount *mp, int mntflags)
1394 {
1395         struct thread *td;
1396         struct nfsmount *nmp;
1397         int error, flags = 0, trycnt = 0;
1398
1399         td = curthread;
1400
1401         if (mntflags & MNT_FORCE)
1402                 flags |= FORCECLOSE;
1403         nmp = VFSTONFS(mp);
1404         /*
1405          * Goes something like this..
1406          * - Call vflush() to clear out vnodes for this filesystem
1407          * - Close the socket
1408          * - Free up the data structures
1409          */
1410         /* In the forced case, cancel any outstanding requests. */
1411         if (mntflags & MNT_FORCE) {
1412                 error = newnfs_nmcancelreqs(nmp);
1413                 if (error)
1414                         goto out;
1415                 /* For a forced close, get rid of the renew thread now */
1416                 nfscl_umount(nmp, td);
1417         }
1418         /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
1419         do {
1420                 error = vflush(mp, 1, flags, td);
1421                 if ((mntflags & MNT_FORCE) && error != 0 && ++trycnt < 30)
1422                         (void) nfs_catnap(PSOCK, error, "newndm");
1423         } while ((mntflags & MNT_FORCE) && error != 0 && trycnt < 30);
1424         if (error)
1425                 goto out;
1426
1427         /*
1428          * We are now committed to the unmount.
1429          */
1430         if ((mntflags & MNT_FORCE) == 0)
1431                 nfscl_umount(nmp, td);
1432         newnfs_disconnect(&nmp->nm_sockreq);
1433         crfree(nmp->nm_sockreq.nr_cred);
1434         FREE(nmp->nm_nam, M_SONAME);
1435
1436         mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1437         mtx_destroy(&nmp->nm_mtx);
1438         FREE(nmp, M_NEWNFSMNT);
1439 out:
1440         return (error);
1441 }
1442
1443 /*
1444  * Return root of a filesystem
1445  */
1446 static int
1447 nfs_root(struct mount *mp, int flags, struct vnode **vpp)
1448 {
1449         struct vnode *vp;
1450         struct nfsmount *nmp;
1451         struct nfsnode *np;
1452         int error;
1453
1454         nmp = VFSTONFS(mp);
1455         error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, flags);
1456         if (error)
1457                 return error;
1458         vp = NFSTOV(np);
1459         /*
1460          * Get transfer parameters and attributes for root vnode once.
1461          */
1462         mtx_lock(&nmp->nm_mtx);
1463         if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
1464                 mtx_unlock(&nmp->nm_mtx);
1465                 ncl_fsinfo(nmp, vp, curthread->td_ucred, curthread);
1466         } else 
1467                 mtx_unlock(&nmp->nm_mtx);
1468         if (vp->v_type == VNON)
1469             vp->v_type = VDIR;
1470         vp->v_vflag |= VV_ROOT;
1471         *vpp = vp;
1472         return (0);
1473 }
1474
1475 /*
1476  * Flush out the buffer cache
1477  */
1478 /* ARGSUSED */
1479 static int
1480 nfs_sync(struct mount *mp, int waitfor)
1481 {
1482         struct vnode *vp, *mvp;
1483         struct thread *td;
1484         int error, allerror = 0;
1485
1486         td = curthread;
1487
1488         MNT_ILOCK(mp);
1489         /*
1490          * If a forced dismount is in progress, return from here so that
1491          * the umount(2) syscall doesn't get stuck in VFS_SYNC() before
1492          * calling VFS_UNMOUNT().
1493          */
1494         if ((mp->mnt_kern_flag & MNTK_UNMOUNTF) != 0) {
1495                 MNT_IUNLOCK(mp);
1496                 return (EBADF);
1497         }
1498
1499         /*
1500          * Force stale buffer cache information to be flushed.
1501          */
1502 loop:
1503         MNT_VNODE_FOREACH(vp, mp, mvp) {
1504                 VI_LOCK(vp);
1505                 MNT_IUNLOCK(mp);
1506                 /* XXX Racy bv_cnt check. */
1507                 if (NFSVOPISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
1508                     waitfor == MNT_LAZY) {
1509                         VI_UNLOCK(vp);
1510                         MNT_ILOCK(mp);
1511                         continue;
1512                 }
1513                 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
1514                         MNT_ILOCK(mp);
1515                         MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp);
1516                         goto loop;
1517                 }
1518                 error = VOP_FSYNC(vp, waitfor, td);
1519                 if (error)
1520                         allerror = error;
1521                 NFSVOPUNLOCK(vp, 0);
1522                 vrele(vp);
1523
1524                 MNT_ILOCK(mp);
1525         }
1526         MNT_IUNLOCK(mp);
1527         return (allerror);
1528 }
1529
1530 static int
1531 nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
1532 {
1533         struct nfsmount *nmp = VFSTONFS(mp);
1534         struct vfsquery vq;
1535         int error;
1536
1537         bzero(&vq, sizeof(vq));
1538         switch (op) {
1539 #if 0
1540         case VFS_CTL_NOLOCKS:
1541                 val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
1542                 if (req->oldptr != NULL) {
1543                         error = SYSCTL_OUT(req, &val, sizeof(val));
1544                         if (error)
1545                                 return (error);
1546                 }
1547                 if (req->newptr != NULL) {
1548                         error = SYSCTL_IN(req, &val, sizeof(val));
1549                         if (error)
1550                                 return (error);
1551                         if (val)
1552                                 nmp->nm_flag |= NFSMNT_NOLOCKS;
1553                         else
1554                                 nmp->nm_flag &= ~NFSMNT_NOLOCKS;
1555                 }
1556                 break;
1557 #endif
1558         case VFS_CTL_QUERY:
1559                 mtx_lock(&nmp->nm_mtx);
1560                 if (nmp->nm_state & NFSSTA_TIMEO)
1561                         vq.vq_flags |= VQ_NOTRESP;
1562                 mtx_unlock(&nmp->nm_mtx);
1563 #if 0
1564                 if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
1565                     (nmp->nm_state & NFSSTA_LOCKTIMEO))
1566                         vq.vq_flags |= VQ_NOTRESPLOCK;
1567 #endif
1568                 error = SYSCTL_OUT(req, &vq, sizeof(vq));
1569                 break;
1570         case VFS_CTL_TIMEO:
1571                 if (req->oldptr != NULL) {
1572                         error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
1573                             sizeof(nmp->nm_tprintf_initial_delay));
1574                         if (error)
1575                                 return (error);
1576                 }
1577                 if (req->newptr != NULL) {
1578                         error = vfs_suser(mp, req->td);
1579                         if (error)
1580                                 return (error);
1581                         error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
1582                             sizeof(nmp->nm_tprintf_initial_delay));
1583                         if (error)
1584                                 return (error);
1585                         if (nmp->nm_tprintf_initial_delay < 0)
1586                                 nmp->nm_tprintf_initial_delay = 0;
1587                 }
1588                 break;
1589         default:
1590                 return (ENOTSUP);
1591         }
1592         return (0);
1593 }
1594
1595 /*
1596  * Extract the information needed by the nlm from the nfs vnode.
1597  */
1598 static void
1599 nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp,
1600     struct sockaddr_storage *sp, int *is_v3p, off_t *sizep,
1601     struct timeval *timeop)
1602 {
1603         struct nfsmount *nmp;
1604         struct nfsnode *np = VTONFS(vp);
1605
1606         nmp = VFSTONFS(vp->v_mount);
1607         if (fhlenp != NULL)
1608                 *fhlenp = (size_t)np->n_fhp->nfh_len;
1609         if (fhp != NULL)
1610                 bcopy(np->n_fhp->nfh_fh, fhp, np->n_fhp->nfh_len);
1611         if (sp != NULL)
1612                 bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp)));
1613         if (is_v3p != NULL)
1614                 *is_v3p = NFS_ISV3(vp);
1615         if (sizep != NULL)
1616                 *sizep = np->n_size;
1617         if (timeop != NULL) {
1618                 timeop->tv_sec = nmp->nm_timeo / NFS_HZ;
1619                 timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ);
1620         }
1621 }
1622