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