]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - sys/fs/nfsclient/nfs_clvfsops.c
MFC: r227517
[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(RTM_ADD, (struct sockaddr *)&sin,
459                     (struct sockaddr *)&nd->mygateway,
460                     (struct sockaddr *)&mask,
461                     RTF_UP | RTF_GATEWAY, NULL);
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",
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, "timeout", (void **)&opt, NULL) == 0) {
949                 ret = sscanf(opt, "%d", &args.timeo);
950                 if (ret != 1 || args.timeo <= 0) {
951                         vfs_mount_error(mp, "illegal timeout: %s",
952                             opt);
953                         error = EINVAL;
954                         goto out;
955                 }
956                 args.flags |= NFSMNT_TIMEO;
957         }
958         if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
959             == 0) {
960                 ret = sscanf(opt, "%d", &negnametimeo);
961                 if (ret != 1 || negnametimeo < 0) {
962                         vfs_mount_error(mp, "illegal negnametimeo: %s",
963                             opt);
964                         error = EINVAL;
965                         goto out;
966                 }
967         }
968         if (vfs_getopt(mp->mnt_optnew, "sec",
969                 (void **) &secname, NULL) == 0)
970                 nfs_sec_name(secname, &args.flags);
971
972         if (mp->mnt_flag & MNT_UPDATE) {
973                 struct nfsmount *nmp = VFSTONFS(mp);
974
975                 if (nmp == NULL) {
976                         error = EIO;
977                         goto out;
978                 }
979                 /*
980                  * When doing an update, we can't change version,
981                  * security, switch lockd strategies or change cookie
982                  * translation
983                  */
984                 args.flags = (args.flags &
985                     ~(NFSMNT_NFSV3 |
986                       NFSMNT_NFSV4 |
987                       NFSMNT_KERB |
988                       NFSMNT_INTEGRITY |
989                       NFSMNT_PRIVACY |
990                       NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
991                     (nmp->nm_flag &
992                         (NFSMNT_NFSV3 |
993                          NFSMNT_NFSV4 |
994                          NFSMNT_KERB |
995                          NFSMNT_INTEGRITY |
996                          NFSMNT_PRIVACY |
997                          NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
998                 nfs_decode_args(mp, nmp, &args, NULL, td->td_ucred, td);
999                 goto out;
1000         }
1001
1002         /*
1003          * Make the nfs_ip_paranoia sysctl serve as the default connection
1004          * or no-connection mode for those protocols that support 
1005          * no-connection mode (the flag will be cleared later for protocols
1006          * that do not support no-connection mode).  This will allow a client
1007          * to receive replies from a different IP then the request was
1008          * sent to.  Note: default value for nfs_ip_paranoia is 1 (paranoid),
1009          * not 0.
1010          */
1011         if (nfs_ip_paranoia == 0)
1012                 args.flags |= NFSMNT_NOCONN;
1013
1014         if (has_nfs_args_opt != 0) {
1015                 /*
1016                  * In the 'nfs_args' case, the pointers in the args
1017                  * structure are in userland - we copy them in here.
1018                  */
1019                 if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
1020                         vfs_mount_error(mp, "Bad file handle");
1021                         error = EINVAL;
1022                         goto out;
1023                 }
1024                 error = copyin((caddr_t)args.fh, (caddr_t)nfh,
1025                     args.fhsize);
1026                 if (error != 0)
1027                         goto out;
1028                 error = copyinstr(args.hostname, hst, MNAMELEN - 1, &hstlen);
1029                 if (error != 0)
1030                         goto out;
1031                 bzero(&hst[hstlen], MNAMELEN - hstlen);
1032                 args.hostname = hst;
1033                 /* sockargs() call must be after above copyin() calls */
1034                 error = getsockaddr(&nam, (caddr_t)args.addr,
1035                     args.addrlen);
1036                 if (error != 0)
1037                         goto out;
1038         } else {
1039                 if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
1040                     &args.fhsize) == 0) {
1041                         if (args.fhsize < 0 || args.fhsize > NFSX_FHMAX) {
1042                                 vfs_mount_error(mp, "Bad file handle");
1043                                 error = EINVAL;
1044                                 goto out;
1045                         }
1046                         bcopy(args.fh, nfh, args.fhsize);
1047                 } else {
1048                         args.fhsize = 0;
1049                 }
1050                 (void) vfs_getopt(mp->mnt_optnew, "hostname",
1051                     (void **)&args.hostname, &len);
1052                 if (args.hostname == NULL) {
1053                         vfs_mount_error(mp, "Invalid hostname");
1054                         error = EINVAL;
1055                         goto out;
1056                 }
1057                 bcopy(args.hostname, hst, MNAMELEN);
1058                 hst[MNAMELEN - 1] = '\0';
1059         }
1060
1061         if (vfs_getopt(mp->mnt_optnew, "principal", (void **)&name, NULL) == 0)
1062                 strlcpy(srvkrbname, name, sizeof (srvkrbname));
1063         else
1064                 snprintf(srvkrbname, sizeof (srvkrbname), "nfs@%s", hst);
1065         srvkrbnamelen = strlen(srvkrbname);
1066
1067         if (vfs_getopt(mp->mnt_optnew, "gssname", (void **)&name, NULL) == 0)
1068                 strlcpy(krbname, name, sizeof (krbname));
1069         else
1070                 krbname[0] = '\0';
1071         krbnamelen = strlen(krbname);
1072
1073         if (vfs_getopt(mp->mnt_optnew, "dirpath", (void **)&name, NULL) == 0)
1074                 strlcpy(dirpath, name, sizeof (dirpath));
1075         else
1076                 dirpath[0] = '\0';
1077         dirlen = strlen(dirpath);
1078
1079         if (has_nfs_args_opt == 0) {
1080                 if (vfs_getopt(mp->mnt_optnew, "addr",
1081                     (void **)&args.addr, &args.addrlen) == 0) {
1082                         if (args.addrlen > SOCK_MAXADDRLEN) {
1083                                 error = ENAMETOOLONG;
1084                                 goto out;
1085                         }
1086                         nam = malloc(args.addrlen, M_SONAME, M_WAITOK);
1087                         bcopy(args.addr, nam, args.addrlen);
1088                         nam->sa_len = args.addrlen;
1089                 } else {
1090                         vfs_mount_error(mp, "No server address");
1091                         error = EINVAL;
1092                         goto out;
1093                 }
1094         }
1095
1096         args.fh = nfh;
1097         error = mountnfs(&args, mp, nam, hst, krbname, krbnamelen, dirpath,
1098             dirlen, srvkrbname, srvkrbnamelen, &vp, td->td_ucred, td,
1099             negnametimeo);
1100 out:
1101         if (!error) {
1102                 MNT_ILOCK(mp);
1103                 mp->mnt_kern_flag |= (MNTK_MPSAFE|MNTK_LOOKUP_SHARED);
1104                 MNT_IUNLOCK(mp);
1105         }
1106         return (error);
1107 }
1108
1109
1110 /*
1111  * VFS Operations.
1112  *
1113  * mount system call
1114  * It seems a bit dumb to copyinstr() the host and path here and then
1115  * bcopy() them in mountnfs(), but I wanted to detect errors before
1116  * doing the sockargs() call because sockargs() allocates an mbuf and
1117  * an error after that means that I have to release the mbuf.
1118  */
1119 /* ARGSUSED */
1120 static int
1121 nfs_cmount(struct mntarg *ma, void *data, int flags)
1122 {
1123         int error;
1124         struct nfs_args args;
1125
1126         error = copyin(data, &args, sizeof (struct nfs_args));
1127         if (error)
1128                 return error;
1129
1130         ma = mount_arg(ma, "nfs_args", &args, sizeof args);
1131
1132         error = kernel_mount(ma, flags);
1133         return (error);
1134 }
1135
1136 /*
1137  * Common code for mount and mountroot
1138  */
1139 static int
1140 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
1141     char *hst, u_char *krbname, int krbnamelen, u_char *dirpath, int dirlen,
1142     u_char *srvkrbname, int srvkrbnamelen, struct vnode **vpp,
1143     struct ucred *cred, struct thread *td, int negnametimeo)
1144 {
1145         struct nfsmount *nmp;
1146         struct nfsnode *np;
1147         int error, trycnt, ret;
1148         struct nfsvattr nfsva;
1149         static u_int64_t clval = 0;
1150
1151         if (mp->mnt_flag & MNT_UPDATE) {
1152                 nmp = VFSTONFS(mp);
1153                 printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
1154                 FREE(nam, M_SONAME);
1155                 return (0);
1156         } else {
1157                 MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount) +
1158                     krbnamelen + dirlen + srvkrbnamelen + 2,
1159                     M_NEWNFSMNT, M_WAITOK | M_ZERO);
1160                 TAILQ_INIT(&nmp->nm_bufq);
1161                 if (clval == 0)
1162                         clval = (u_int64_t)nfsboottime.tv_sec;
1163                 nmp->nm_clval = clval++;
1164                 nmp->nm_krbnamelen = krbnamelen;
1165                 nmp->nm_dirpathlen = dirlen;
1166                 nmp->nm_srvkrbnamelen = srvkrbnamelen;
1167                 if (td->td_ucred->cr_uid != (uid_t)0) {
1168                         /*
1169                          * nm_uid is used to get KerberosV credentials for
1170                          * the nfsv4 state handling operations if there is
1171                          * no host based principal set. Use the uid of
1172                          * this user if not root, since they are doing the
1173                          * mount. I don't think setting this for root will
1174                          * work, since root normally does not have user
1175                          * credentials in a credentials cache.
1176                          */
1177                         nmp->nm_uid = td->td_ucred->cr_uid;
1178                 } else {
1179                         /*
1180                          * Just set to -1, so it won't be used.
1181                          */
1182                         nmp->nm_uid = (uid_t)-1;
1183                 }
1184
1185                 /* Copy and null terminate all the names */
1186                 if (nmp->nm_krbnamelen > 0) {
1187                         bcopy(krbname, nmp->nm_krbname, nmp->nm_krbnamelen);
1188                         nmp->nm_name[nmp->nm_krbnamelen] = '\0';
1189                 }
1190                 if (nmp->nm_dirpathlen > 0) {
1191                         bcopy(dirpath, NFSMNT_DIRPATH(nmp),
1192                             nmp->nm_dirpathlen);
1193                         nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1194                             + 1] = '\0';
1195                 }
1196                 if (nmp->nm_srvkrbnamelen > 0) {
1197                         bcopy(srvkrbname, NFSMNT_SRVKRBNAME(nmp),
1198                             nmp->nm_srvkrbnamelen);
1199                         nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1200                             + nmp->nm_srvkrbnamelen + 2] = '\0';
1201                 }
1202                 nmp->nm_sockreq.nr_cred = crhold(cred);
1203                 mtx_init(&nmp->nm_sockreq.nr_mtx, "nfssock", NULL, MTX_DEF);
1204                 mp->mnt_data = nmp;
1205                 nmp->nm_getinfo = nfs_getnlminfo;
1206                 nmp->nm_vinvalbuf = ncl_vinvalbuf;
1207         }
1208         vfs_getnewfsid(mp);
1209         nmp->nm_mountp = mp;
1210         mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF | MTX_DUPOK);                     
1211
1212         /*
1213          * Since nfs_decode_args() might optionally set them, these need to
1214          * set to defaults before the call, so that the optional settings
1215          * aren't overwritten.
1216          */
1217         nmp->nm_negnametimeo = negnametimeo;
1218         nmp->nm_timeo = NFS_TIMEO;
1219         nmp->nm_retry = NFS_RETRANS;
1220         nmp->nm_readahead = NFS_DEFRAHEAD;
1221         if (desiredvnodes >= 11000)
1222                 nmp->nm_wcommitsize = hibufspace / (desiredvnodes / 1000);
1223         else
1224                 nmp->nm_wcommitsize = hibufspace / 10;
1225
1226         nfs_decode_args(mp, nmp, argp, hst, cred, td);
1227
1228         /*
1229          * V2 can only handle 32 bit filesizes.  A 4GB-1 limit may be too
1230          * high, depending on whether we end up with negative offsets in
1231          * the client or server somewhere.  2GB-1 may be safer.
1232          *
1233          * For V3, ncl_fsinfo will adjust this as necessary.  Assume maximum
1234          * that we can handle until we find out otherwise.
1235          * XXX Our "safe" limit on the client is what we can store in our
1236          * buffer cache using signed(!) block numbers.
1237          */
1238         if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0)
1239                 nmp->nm_maxfilesize = 0xffffffffLL;
1240         else
1241                 nmp->nm_maxfilesize = OFF_MAX;
1242
1243         if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
1244                 nmp->nm_wsize = NFS_WSIZE;
1245                 nmp->nm_rsize = NFS_RSIZE;
1246                 nmp->nm_readdirsize = NFS_READDIRSIZE;
1247         }
1248         nmp->nm_numgrps = NFS_MAXGRPS;
1249         nmp->nm_tprintf_delay = nfs_tprintf_delay;
1250         if (nmp->nm_tprintf_delay < 0)
1251                 nmp->nm_tprintf_delay = 0;
1252         nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
1253         if (nmp->nm_tprintf_initial_delay < 0)
1254                 nmp->nm_tprintf_initial_delay = 0;
1255         nmp->nm_fhsize = argp->fhsize;
1256         if (nmp->nm_fhsize > 0)
1257                 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
1258         bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
1259         nmp->nm_nam = nam;
1260         /* Set up the sockets and per-host congestion */
1261         nmp->nm_sotype = argp->sotype;
1262         nmp->nm_soproto = argp->proto;
1263         nmp->nm_sockreq.nr_prog = NFS_PROG;
1264         if ((argp->flags & NFSMNT_NFSV4))
1265                 nmp->nm_sockreq.nr_vers = NFS_VER4;
1266         else if ((argp->flags & NFSMNT_NFSV3))
1267                 nmp->nm_sockreq.nr_vers = NFS_VER3;
1268         else
1269                 nmp->nm_sockreq.nr_vers = NFS_VER2;
1270
1271
1272         if ((error = newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0)))
1273                 goto bad;
1274
1275         /*
1276          * A reference count is needed on the nfsnode representing the
1277          * remote root.  If this object is not persistent, then backward
1278          * traversals of the mount point (i.e. "..") will not work if
1279          * the nfsnode gets flushed out of the cache. Ufs does not have
1280          * this problem, because one can identify root inodes by their
1281          * number == ROOTINO (2).
1282          */
1283         if (nmp->nm_fhsize == 0 && (nmp->nm_flag & NFSMNT_NFSV4) &&
1284             nmp->nm_dirpathlen > 0) {
1285                 /*
1286                  * If the fhsize on the mount point == 0 for V4, the mount
1287                  * path needs to be looked up.
1288                  */
1289                 trycnt = 3;
1290                 do {
1291                         error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp),
1292                             cred, td);
1293                         if (error)
1294                                 (void) nfs_catnap(PZERO, error, "nfsgetdirp");
1295                 } while (error && --trycnt > 0);
1296                 if (error) {
1297                         error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
1298                         goto bad;
1299                 }
1300         }
1301         if (nmp->nm_fhsize > 0) {
1302                 /*
1303                  * Set f_iosize to NFS_DIRBLKSIZ so that bo_bsize gets set
1304                  * non-zero for the root vnode. f_iosize will be set correctly
1305                  * by nfs_statfs() before any I/O occurs.
1306                  */
1307                 mp->mnt_stat.f_iosize = NFS_DIRBLKSIZ;
1308                 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np,
1309                     LK_EXCLUSIVE);
1310                 if (error)
1311                         goto bad;
1312                 *vpp = NFSTOV(np);
1313         
1314                 /*
1315                  * Get file attributes and transfer parameters for the
1316                  * mountpoint.  This has the side effect of filling in
1317                  * (*vpp)->v_type with the correct value.
1318                  */
1319                 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
1320                     cred, td, &nfsva, NULL);
1321                 if (ret) {
1322                         /*
1323                          * Just set default values to get things going.
1324                          */
1325                         NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
1326                         nfsva.na_vattr.va_type = VDIR;
1327                         nfsva.na_vattr.va_mode = 0777;
1328                         nfsva.na_vattr.va_nlink = 100;
1329                         nfsva.na_vattr.va_uid = (uid_t)0;
1330                         nfsva.na_vattr.va_gid = (gid_t)0;
1331                         nfsva.na_vattr.va_fileid = 2;
1332                         nfsva.na_vattr.va_gen = 1;
1333                         nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
1334                         nfsva.na_vattr.va_size = 512 * 1024;
1335                 }
1336                 (void) nfscl_loadattrcache(vpp, &nfsva, NULL, NULL, 0, 1);
1337                 if (argp->flags & NFSMNT_NFSV3)
1338                         ncl_fsinfo(nmp, *vpp, cred, td);
1339         
1340                 /* Mark if the mount point supports NFSv4 ACLs. */
1341                 if ((argp->flags & NFSMNT_NFSV4) != 0 && nfsrv_useacl != 0 &&
1342                     ret == 0 &&
1343                     NFSISSET_ATTRBIT(&nfsva.na_suppattr, NFSATTRBIT_ACL)) {
1344                         MNT_ILOCK(mp);
1345                         mp->mnt_flag |= MNT_NFS4ACLS;
1346                         MNT_IUNLOCK(mp);
1347                 }
1348         
1349                 /*
1350                  * Lose the lock but keep the ref.
1351                  */
1352                 NFSVOPUNLOCK(*vpp, 0);
1353                 return (0);
1354         }
1355         error = EIO;
1356
1357 bad:
1358         newnfs_disconnect(&nmp->nm_sockreq);
1359         crfree(nmp->nm_sockreq.nr_cred);
1360         mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1361         mtx_destroy(&nmp->nm_mtx);
1362         FREE(nmp, M_NEWNFSMNT);
1363         FREE(nam, M_SONAME);
1364         return (error);
1365 }
1366
1367 /*
1368  * unmount system call
1369  */
1370 static int
1371 nfs_unmount(struct mount *mp, int mntflags)
1372 {
1373         struct thread *td;
1374         struct nfsmount *nmp;
1375         int error, flags = 0, trycnt = 0;
1376
1377         td = curthread;
1378
1379         if (mntflags & MNT_FORCE)
1380                 flags |= FORCECLOSE;
1381         nmp = VFSTONFS(mp);
1382         /*
1383          * Goes something like this..
1384          * - Call vflush() to clear out vnodes for this filesystem
1385          * - Close the socket
1386          * - Free up the data structures
1387          */
1388         /* In the forced case, cancel any outstanding requests. */
1389         if (mntflags & MNT_FORCE) {
1390                 error = newnfs_nmcancelreqs(nmp);
1391                 if (error)
1392                         goto out;
1393                 /* For a forced close, get rid of the renew thread now */
1394                 nfscl_umount(nmp, td);
1395         }
1396         /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
1397         do {
1398                 error = vflush(mp, 1, flags, td);
1399                 if ((mntflags & MNT_FORCE) && error != 0 && ++trycnt < 30)
1400                         (void) nfs_catnap(PSOCK, error, "newndm");
1401         } while ((mntflags & MNT_FORCE) && error != 0 && trycnt < 30);
1402         if (error)
1403                 goto out;
1404
1405         /*
1406          * We are now committed to the unmount.
1407          */
1408         if ((mntflags & MNT_FORCE) == 0)
1409                 nfscl_umount(nmp, td);
1410         newnfs_disconnect(&nmp->nm_sockreq);
1411         crfree(nmp->nm_sockreq.nr_cred);
1412         FREE(nmp->nm_nam, M_SONAME);
1413
1414         mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1415         mtx_destroy(&nmp->nm_mtx);
1416         FREE(nmp, M_NEWNFSMNT);
1417 out:
1418         return (error);
1419 }
1420
1421 /*
1422  * Return root of a filesystem
1423  */
1424 static int
1425 nfs_root(struct mount *mp, int flags, struct vnode **vpp)
1426 {
1427         struct vnode *vp;
1428         struct nfsmount *nmp;
1429         struct nfsnode *np;
1430         int error;
1431
1432         nmp = VFSTONFS(mp);
1433         error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, flags);
1434         if (error)
1435                 return error;
1436         vp = NFSTOV(np);
1437         /*
1438          * Get transfer parameters and attributes for root vnode once.
1439          */
1440         mtx_lock(&nmp->nm_mtx);
1441         if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
1442                 mtx_unlock(&nmp->nm_mtx);
1443                 ncl_fsinfo(nmp, vp, curthread->td_ucred, curthread);
1444         } else 
1445                 mtx_unlock(&nmp->nm_mtx);
1446         if (vp->v_type == VNON)
1447             vp->v_type = VDIR;
1448         vp->v_vflag |= VV_ROOT;
1449         *vpp = vp;
1450         return (0);
1451 }
1452
1453 /*
1454  * Flush out the buffer cache
1455  */
1456 /* ARGSUSED */
1457 static int
1458 nfs_sync(struct mount *mp, int waitfor)
1459 {
1460         struct vnode *vp, *mvp;
1461         struct thread *td;
1462         int error, allerror = 0;
1463
1464         td = curthread;
1465
1466         MNT_ILOCK(mp);
1467         /*
1468          * If a forced dismount is in progress, return from here so that
1469          * the umount(2) syscall doesn't get stuck in VFS_SYNC() before
1470          * calling VFS_UNMOUNT().
1471          */
1472         if ((mp->mnt_kern_flag & MNTK_UNMOUNTF) != 0) {
1473                 MNT_IUNLOCK(mp);
1474                 return (EBADF);
1475         }
1476
1477         /*
1478          * Force stale buffer cache information to be flushed.
1479          */
1480 loop:
1481         MNT_VNODE_FOREACH(vp, mp, mvp) {
1482                 VI_LOCK(vp);
1483                 MNT_IUNLOCK(mp);
1484                 /* XXX Racy bv_cnt check. */
1485                 if (NFSVOPISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
1486                     waitfor == MNT_LAZY) {
1487                         VI_UNLOCK(vp);
1488                         MNT_ILOCK(mp);
1489                         continue;
1490                 }
1491                 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
1492                         MNT_ILOCK(mp);
1493                         MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp);
1494                         goto loop;
1495                 }
1496                 error = VOP_FSYNC(vp, waitfor, td);
1497                 if (error)
1498                         allerror = error;
1499                 NFSVOPUNLOCK(vp, 0);
1500                 vrele(vp);
1501
1502                 MNT_ILOCK(mp);
1503         }
1504         MNT_IUNLOCK(mp);
1505         return (allerror);
1506 }
1507
1508 static int
1509 nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
1510 {
1511         struct nfsmount *nmp = VFSTONFS(mp);
1512         struct vfsquery vq;
1513         int error;
1514
1515         bzero(&vq, sizeof(vq));
1516         switch (op) {
1517 #if 0
1518         case VFS_CTL_NOLOCKS:
1519                 val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
1520                 if (req->oldptr != NULL) {
1521                         error = SYSCTL_OUT(req, &val, sizeof(val));
1522                         if (error)
1523                                 return (error);
1524                 }
1525                 if (req->newptr != NULL) {
1526                         error = SYSCTL_IN(req, &val, sizeof(val));
1527                         if (error)
1528                                 return (error);
1529                         if (val)
1530                                 nmp->nm_flag |= NFSMNT_NOLOCKS;
1531                         else
1532                                 nmp->nm_flag &= ~NFSMNT_NOLOCKS;
1533                 }
1534                 break;
1535 #endif
1536         case VFS_CTL_QUERY:
1537                 mtx_lock(&nmp->nm_mtx);
1538                 if (nmp->nm_state & NFSSTA_TIMEO)
1539                         vq.vq_flags |= VQ_NOTRESP;
1540                 mtx_unlock(&nmp->nm_mtx);
1541 #if 0
1542                 if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
1543                     (nmp->nm_state & NFSSTA_LOCKTIMEO))
1544                         vq.vq_flags |= VQ_NOTRESPLOCK;
1545 #endif
1546                 error = SYSCTL_OUT(req, &vq, sizeof(vq));
1547                 break;
1548         case VFS_CTL_TIMEO:
1549                 if (req->oldptr != NULL) {
1550                         error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
1551                             sizeof(nmp->nm_tprintf_initial_delay));
1552                         if (error)
1553                                 return (error);
1554                 }
1555                 if (req->newptr != NULL) {
1556                         error = vfs_suser(mp, req->td);
1557                         if (error)
1558                                 return (error);
1559                         error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
1560                             sizeof(nmp->nm_tprintf_initial_delay));
1561                         if (error)
1562                                 return (error);
1563                         if (nmp->nm_tprintf_initial_delay < 0)
1564                                 nmp->nm_tprintf_initial_delay = 0;
1565                 }
1566                 break;
1567         default:
1568                 return (ENOTSUP);
1569         }
1570         return (0);
1571 }
1572
1573 /*
1574  * Extract the information needed by the nlm from the nfs vnode.
1575  */
1576 static void
1577 nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp,
1578     struct sockaddr_storage *sp, int *is_v3p, off_t *sizep,
1579     struct timeval *timeop)
1580 {
1581         struct nfsmount *nmp;
1582         struct nfsnode *np = VTONFS(vp);
1583
1584         nmp = VFSTONFS(vp->v_mount);
1585         if (fhlenp != NULL)
1586                 *fhlenp = (size_t)np->n_fhp->nfh_len;
1587         if (fhp != NULL)
1588                 bcopy(np->n_fhp->nfh_fh, fhp, np->n_fhp->nfh_len);
1589         if (sp != NULL)
1590                 bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp)));
1591         if (is_v3p != NULL)
1592                 *is_v3p = NFS_ISV3(vp);
1593         if (sizep != NULL)
1594                 *sizep = np->n_size;
1595         if (timeop != NULL) {
1596                 timeop->tv_sec = nmp->nm_timeo / NFS_HZ;
1597                 timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ);
1598         }
1599 }
1600