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