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