]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - sys/fs/nfsclient/nfs_clvfsops.c
MFC r221436:
[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", "nocto",
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, "nocto", NULL, NULL) == 0)
803                 args.flags |= NFSMNT_NOCTO;
804         if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
805                 if (opt == NULL) { 
806                         vfs_mount_error(mp, "illegal readdirsize");
807                         error = EINVAL;
808                         goto out;
809                 }
810                 ret = sscanf(opt, "%d", &args.readdirsize);
811                 if (ret != 1 || args.readdirsize <= 0) {
812                         vfs_mount_error(mp, "illegal readdirsize: %s",
813                             opt);
814                         error = EINVAL;
815                         goto out;
816                 }
817                 args.flags |= NFSMNT_READDIRSIZE;
818         }
819         if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
820                 if (opt == NULL) { 
821                         vfs_mount_error(mp, "illegal readahead");
822                         error = EINVAL;
823                         goto out;
824                 }
825                 ret = sscanf(opt, "%d", &args.readahead);
826                 if (ret != 1 || args.readahead <= 0) {
827                         vfs_mount_error(mp, "illegal readahead: %s",
828                             opt);
829                         error = EINVAL;
830                         goto out;
831                 }
832                 args.flags |= NFSMNT_READAHEAD;
833         }
834         if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
835                 if (opt == NULL) { 
836                         vfs_mount_error(mp, "illegal wsize");
837                         error = EINVAL;
838                         goto out;
839                 }
840                 ret = sscanf(opt, "%d", &args.wsize);
841                 if (ret != 1 || args.wsize <= 0) {
842                         vfs_mount_error(mp, "illegal wsize: %s",
843                             opt);
844                         error = EINVAL;
845                         goto out;
846                 }
847                 args.flags |= NFSMNT_WSIZE;
848         }
849         if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
850                 if (opt == NULL) { 
851                         vfs_mount_error(mp, "illegal rsize");
852                         error = EINVAL;
853                         goto out;
854                 }
855                 ret = sscanf(opt, "%d", &args.rsize);
856                 if (ret != 1 || args.rsize <= 0) {
857                         vfs_mount_error(mp, "illegal wsize: %s",
858                             opt);
859                         error = EINVAL;
860                         goto out;
861                 }
862                 args.flags |= NFSMNT_RSIZE;
863         }
864         if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
865                 if (opt == NULL) { 
866                         vfs_mount_error(mp, "illegal retrans");
867                         error = EINVAL;
868                         goto out;
869                 }
870                 ret = sscanf(opt, "%d", &args.retrans);
871                 if (ret != 1 || args.retrans <= 0) {
872                         vfs_mount_error(mp, "illegal retrans: %s",
873                             opt);
874                         error = EINVAL;
875                         goto out;
876                 }
877                 args.flags |= NFSMNT_RETRANS;
878         }
879         if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
880                 ret = sscanf(opt, "%d", &args.acregmin);
881                 if (ret != 1 || args.acregmin < 0) {
882                         vfs_mount_error(mp, "illegal acregmin: %s",
883                             opt);
884                         error = EINVAL;
885                         goto out;
886                 }
887                 args.flags |= NFSMNT_ACREGMIN;
888         }
889         if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
890                 ret = sscanf(opt, "%d", &args.acregmax);
891                 if (ret != 1 || args.acregmax < 0) {
892                         vfs_mount_error(mp, "illegal acregmax: %s",
893                             opt);
894                         error = EINVAL;
895                         goto out;
896                 }
897                 args.flags |= NFSMNT_ACREGMAX;
898         }
899         if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
900                 ret = sscanf(opt, "%d", &args.acdirmin);
901                 if (ret != 1 || args.acdirmin < 0) {
902                         vfs_mount_error(mp, "illegal acdirmin: %s",
903                             opt);
904                         error = EINVAL;
905                         goto out;
906                 }
907                 args.flags |= NFSMNT_ACDIRMIN;
908         }
909         if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
910                 ret = sscanf(opt, "%d", &args.acdirmax);
911                 if (ret != 1 || args.acdirmax < 0) {
912                         vfs_mount_error(mp, "illegal acdirmax: %s",
913                             opt);
914                         error = EINVAL;
915                         goto out;
916                 }
917                 args.flags |= NFSMNT_ACDIRMAX;
918         }
919         if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
920                 ret = sscanf(opt, "%d", &args.timeo);
921                 if (ret != 1 || args.timeo <= 0) {
922                         vfs_mount_error(mp, "illegal timeout: %s",
923                             opt);
924                         error = EINVAL;
925                         goto out;
926                 }
927                 args.flags |= NFSMNT_TIMEO;
928         }
929         if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
930             == 0) {
931                 ret = sscanf(opt, "%d", &negnametimeo);
932                 if (ret != 1 || negnametimeo < 0) {
933                         vfs_mount_error(mp, "illegal negnametimeo: %s",
934                             opt);
935                         error = EINVAL;
936                         goto out;
937                 }
938         }
939         if (vfs_getopt(mp->mnt_optnew, "sec",
940                 (void **) &secname, NULL) == 0)
941                 nfs_sec_name(secname, &args.flags);
942
943         if (mp->mnt_flag & MNT_UPDATE) {
944                 struct nfsmount *nmp = VFSTONFS(mp);
945
946                 if (nmp == NULL) {
947                         error = EIO;
948                         goto out;
949                 }
950                 /*
951                  * When doing an update, we can't change version,
952                  * security, switch lockd strategies or change cookie
953                  * translation
954                  */
955                 args.flags = (args.flags &
956                     ~(NFSMNT_NFSV3 |
957                       NFSMNT_NFSV4 |
958                       NFSMNT_KERB |
959                       NFSMNT_INTEGRITY |
960                       NFSMNT_PRIVACY |
961                       NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
962                     (nmp->nm_flag &
963                         (NFSMNT_NFSV3 |
964                          NFSMNT_NFSV4 |
965                          NFSMNT_KERB |
966                          NFSMNT_INTEGRITY |
967                          NFSMNT_PRIVACY |
968                          NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
969                 nfs_decode_args(mp, nmp, &args, NULL, td->td_ucred, td);
970                 goto out;
971         }
972
973         /*
974          * Make the nfs_ip_paranoia sysctl serve as the default connection
975          * or no-connection mode for those protocols that support 
976          * no-connection mode (the flag will be cleared later for protocols
977          * that do not support no-connection mode).  This will allow a client
978          * to receive replies from a different IP then the request was
979          * sent to.  Note: default value for nfs_ip_paranoia is 1 (paranoid),
980          * not 0.
981          */
982         if (nfs_ip_paranoia == 0)
983                 args.flags |= NFSMNT_NOCONN;
984
985         if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
986             &args.fhsize) == 0) {
987                 if (args.fhsize < 0 || args.fhsize > NFSX_FHMAX) {
988                         vfs_mount_error(mp, "Bad file handle");
989                         error = EINVAL;
990                         goto out;
991                 }
992                 bcopy(args.fh, nfh, args.fhsize);
993         } else {
994                 args.fhsize = 0;
995         }
996
997         (void) vfs_getopt(mp->mnt_optnew, "hostname", (void **)&args.hostname,
998             &len);
999         if (args.hostname == NULL) {
1000                 vfs_mount_error(mp, "Invalid hostname");
1001                 error = EINVAL;
1002                 goto out;
1003         }
1004         bcopy(args.hostname, hst, MNAMELEN);
1005         hst[MNAMELEN - 1] = '\0';
1006
1007         if (vfs_getopt(mp->mnt_optnew, "principal", (void **)&name, NULL) == 0)
1008                 strlcpy(srvkrbname, name, sizeof (srvkrbname));
1009         else
1010                 snprintf(srvkrbname, sizeof (srvkrbname), "nfs@%s", hst);
1011         args.srvkrbnamelen = strlen(srvkrbname);
1012
1013         if (vfs_getopt(mp->mnt_optnew, "gssname", (void **)&name, NULL) == 0)
1014                 strlcpy(krbname, name, sizeof (krbname));
1015         else
1016                 krbname[0] = '\0';
1017         args.krbnamelen = strlen(krbname);
1018
1019         if (vfs_getopt(mp->mnt_optnew, "dirpath", (void **)&name, NULL) == 0)
1020                 strlcpy(dirpath, name, sizeof (dirpath));
1021         else
1022                 dirpath[0] = '\0';
1023         args.dirlen = strlen(dirpath);
1024
1025         if (vfs_getopt(mp->mnt_optnew, "addr", (void **)&args.addr,
1026             &args.addrlen) == 0) {
1027                 if (args.addrlen > SOCK_MAXADDRLEN) {
1028                         error = ENAMETOOLONG;
1029                         goto out;
1030                 }
1031                 nam = malloc(args.addrlen, M_SONAME, M_WAITOK);
1032                 bcopy(args.addr, nam, args.addrlen);
1033                 nam->sa_len = args.addrlen;
1034         }
1035
1036         args.fh = nfh;
1037         error = mountnfs(&args, mp, nam, hst, krbname, dirpath, srvkrbname,
1038             &vp, td->td_ucred, td, negnametimeo);
1039 out:
1040         if (!error) {
1041                 MNT_ILOCK(mp);
1042                 mp->mnt_kern_flag |= (MNTK_MPSAFE|MNTK_LOOKUP_SHARED);
1043                 MNT_IUNLOCK(mp);
1044         }
1045         return (error);
1046 }
1047
1048
1049 /*
1050  * VFS Operations.
1051  *
1052  * mount system call
1053  * It seems a bit dumb to copyinstr() the host and path here and then
1054  * bcopy() them in mountnfs(), but I wanted to detect errors before
1055  * doing the sockargs() call because sockargs() allocates an mbuf and
1056  * an error after that means that I have to release the mbuf.
1057  */
1058 /* ARGSUSED */
1059 static int
1060 nfs_cmount(struct mntarg *ma, void *data, int flags)
1061 {
1062         int error;
1063         struct nfs_args args;
1064
1065         error = copyin(data, &args, sizeof (struct nfs_args));
1066         if (error)
1067                 return error;
1068
1069         ma = mount_arg(ma, "nfs_args", &args, sizeof args);
1070
1071         error = kernel_mount(ma, flags);
1072         return (error);
1073 }
1074
1075 /*
1076  * Common code for mount and mountroot
1077  */
1078 static int
1079 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
1080     char *hst, u_char *krbname, u_char *dirpath, u_char *srvkrbname,
1081     struct vnode **vpp, struct ucred *cred, struct thread *td,
1082     int negnametimeo)
1083 {
1084         struct nfsmount *nmp;
1085         struct nfsnode *np;
1086         int error, trycnt, ret;
1087         struct nfsvattr nfsva;
1088         static u_int64_t clval = 0;
1089
1090         if (mp->mnt_flag & MNT_UPDATE) {
1091                 nmp = VFSTONFS(mp);
1092                 printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
1093                 FREE(nam, M_SONAME);
1094                 return (0);
1095         } else {
1096                 MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount) +
1097                     argp->krbnamelen + argp->dirlen + argp->srvkrbnamelen + 2,
1098                     M_NEWNFSMNT, M_WAITOK);
1099                 bzero((caddr_t)nmp, sizeof (struct nfsmount) +
1100                     argp->krbnamelen + argp->dirlen + argp->srvkrbnamelen + 2);
1101                 TAILQ_INIT(&nmp->nm_bufq);
1102                 if (clval == 0)
1103                         clval = (u_int64_t)nfsboottime.tv_sec;
1104                 nmp->nm_clval = clval++;
1105                 nmp->nm_krbnamelen = argp->krbnamelen;
1106                 nmp->nm_dirpathlen = argp->dirlen;
1107                 nmp->nm_srvkrbnamelen = argp->srvkrbnamelen;
1108                 if (td->td_ucred->cr_uid != (uid_t)0) {
1109                         /*
1110                          * nm_uid is used to get KerberosV credentials for
1111                          * the nfsv4 state handling operations if there is
1112                          * no host based principal set. Use the uid of
1113                          * this user if not root, since they are doing the
1114                          * mount. I don't think setting this for root will
1115                          * work, since root normally does not have user
1116                          * credentials in a credentials cache.
1117                          */
1118                         nmp->nm_uid = td->td_ucred->cr_uid;
1119                 } else {
1120                         /*
1121                          * Just set to -1, so it won't be used.
1122                          */
1123                         nmp->nm_uid = (uid_t)-1;
1124                 }
1125
1126                 /* Copy and null terminate all the names */
1127                 if (nmp->nm_krbnamelen > 0) {
1128                         bcopy(krbname, nmp->nm_krbname, nmp->nm_krbnamelen);
1129                         nmp->nm_name[nmp->nm_krbnamelen] = '\0';
1130                 }
1131                 if (nmp->nm_dirpathlen > 0) {
1132                         bcopy(dirpath, NFSMNT_DIRPATH(nmp),
1133                             nmp->nm_dirpathlen);
1134                         nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1135                             + 1] = '\0';
1136                 }
1137                 if (nmp->nm_srvkrbnamelen > 0) {
1138                         bcopy(srvkrbname, NFSMNT_SRVKRBNAME(nmp),
1139                             nmp->nm_srvkrbnamelen);
1140                         nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1141                             + nmp->nm_srvkrbnamelen + 2] = '\0';
1142                 }
1143                 nmp->nm_sockreq.nr_cred = crhold(cred);
1144                 mtx_init(&nmp->nm_sockreq.nr_mtx, "nfssock", NULL, MTX_DEF);
1145                 mp->mnt_data = nmp;
1146                 nmp->nm_getinfo = nfs_getnlminfo;
1147                 nmp->nm_vinvalbuf = ncl_vinvalbuf;
1148         }
1149         vfs_getnewfsid(mp);
1150         nmp->nm_mountp = mp;
1151         mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF | MTX_DUPOK);                     
1152         nmp->nm_negnametimeo = negnametimeo;
1153
1154         nfs_decode_args(mp, nmp, argp, hst, cred, td);
1155
1156         /*
1157          * V2 can only handle 32 bit filesizes.  A 4GB-1 limit may be too
1158          * high, depending on whether we end up with negative offsets in
1159          * the client or server somewhere.  2GB-1 may be safer.
1160          *
1161          * For V3, ncl_fsinfo will adjust this as necessary.  Assume maximum
1162          * that we can handle until we find out otherwise.
1163          * XXX Our "safe" limit on the client is what we can store in our
1164          * buffer cache using signed(!) block numbers.
1165          */
1166         if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0)
1167                 nmp->nm_maxfilesize = 0xffffffffLL;
1168         else
1169                 nmp->nm_maxfilesize = (u_int64_t)0x80000000 * DEV_BSIZE - 1;
1170
1171         nmp->nm_timeo = NFS_TIMEO;
1172         nmp->nm_retry = NFS_RETRANS;
1173         if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
1174                 nmp->nm_wsize = NFS_WSIZE;
1175                 nmp->nm_rsize = NFS_RSIZE;
1176                 nmp->nm_readdirsize = NFS_READDIRSIZE;
1177         }
1178         nmp->nm_wcommitsize = hibufspace / (desiredvnodes / 1000);
1179         nmp->nm_numgrps = NFS_MAXGRPS;
1180         nmp->nm_readahead = NFS_DEFRAHEAD;
1181         nmp->nm_tprintf_delay = nfs_tprintf_delay;
1182         if (nmp->nm_tprintf_delay < 0)
1183                 nmp->nm_tprintf_delay = 0;
1184         nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
1185         if (nmp->nm_tprintf_initial_delay < 0)
1186                 nmp->nm_tprintf_initial_delay = 0;
1187         nmp->nm_fhsize = argp->fhsize;
1188         if (nmp->nm_fhsize > 0)
1189                 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
1190         bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
1191         nmp->nm_nam = nam;
1192         /* Set up the sockets and per-host congestion */
1193         nmp->nm_sotype = argp->sotype;
1194         nmp->nm_soproto = argp->proto;
1195         nmp->nm_sockreq.nr_prog = NFS_PROG;
1196         if ((argp->flags & NFSMNT_NFSV4))
1197                 nmp->nm_sockreq.nr_vers = NFS_VER4;
1198         else if ((argp->flags & NFSMNT_NFSV3))
1199                 nmp->nm_sockreq.nr_vers = NFS_VER3;
1200         else
1201                 nmp->nm_sockreq.nr_vers = NFS_VER2;
1202
1203
1204         if ((error = newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0)))
1205                 goto bad;
1206
1207         /*
1208          * A reference count is needed on the nfsnode representing the
1209          * remote root.  If this object is not persistent, then backward
1210          * traversals of the mount point (i.e. "..") will not work if
1211          * the nfsnode gets flushed out of the cache. Ufs does not have
1212          * this problem, because one can identify root inodes by their
1213          * number == ROOTINO (2).
1214          */
1215         if (nmp->nm_fhsize == 0 && (nmp->nm_flag & NFSMNT_NFSV4) &&
1216             nmp->nm_dirpathlen > 0) {
1217                 /*
1218                  * If the fhsize on the mount point == 0 for V4, the mount
1219                  * path needs to be looked up.
1220                  */
1221                 trycnt = 3;
1222                 do {
1223                         error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp),
1224                             cred, td);
1225                         if (error)
1226                                 (void) nfs_catnap(PZERO, error, "nfsgetdirp");
1227                 } while (error && --trycnt > 0);
1228                 if (error) {
1229                         error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
1230                         goto bad;
1231                 }
1232         }
1233         if (nmp->nm_fhsize > 0) {
1234                 /*
1235                  * Set f_iosize to NFS_DIRBLKSIZ so that bo_bsize gets set
1236                  * non-zero for the root vnode. f_iosize will be set correctly
1237                  * by nfs_statfs() before any I/O occurs.
1238                  */
1239                 mp->mnt_stat.f_iosize = NFS_DIRBLKSIZ;
1240                 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np,
1241                     LK_EXCLUSIVE);
1242                 if (error)
1243                         goto bad;
1244                 *vpp = NFSTOV(np);
1245         
1246                 /*
1247                  * Get file attributes and transfer parameters for the
1248                  * mountpoint.  This has the side effect of filling in
1249                  * (*vpp)->v_type with the correct value.
1250                  */
1251                 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
1252                     cred, td, &nfsva, NULL);
1253                 if (ret) {
1254                         /*
1255                          * Just set default values to get things going.
1256                          */
1257                         NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
1258                         nfsva.na_vattr.va_type = VDIR;
1259                         nfsva.na_vattr.va_mode = 0777;
1260                         nfsva.na_vattr.va_nlink = 100;
1261                         nfsva.na_vattr.va_uid = (uid_t)0;
1262                         nfsva.na_vattr.va_gid = (gid_t)0;
1263                         nfsva.na_vattr.va_fileid = 2;
1264                         nfsva.na_vattr.va_gen = 1;
1265                         nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
1266                         nfsva.na_vattr.va_size = 512 * 1024;
1267                 }
1268                 (void) nfscl_loadattrcache(vpp, &nfsva, NULL, NULL, 0, 1);
1269                 if (argp->flags & NFSMNT_NFSV3)
1270                         ncl_fsinfo(nmp, *vpp, cred, td);
1271         
1272                 /*
1273                  * Lose the lock but keep the ref.
1274                  */
1275                 VOP_UNLOCK(*vpp, 0);
1276                 return (0);
1277         }
1278         error = EIO;
1279
1280 bad:
1281         newnfs_disconnect(&nmp->nm_sockreq);
1282         crfree(nmp->nm_sockreq.nr_cred);
1283         mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1284         mtx_destroy(&nmp->nm_mtx);
1285         FREE(nmp, M_NEWNFSMNT);
1286         FREE(nam, M_SONAME);
1287         return (error);
1288 }
1289
1290 /*
1291  * unmount system call
1292  */
1293 static int
1294 nfs_unmount(struct mount *mp, int mntflags)
1295 {
1296         struct thread *td;
1297         struct nfsmount *nmp;
1298         int error, flags = 0, trycnt = 0;
1299
1300         td = curthread;
1301
1302         if (mntflags & MNT_FORCE)
1303                 flags |= FORCECLOSE;
1304         nmp = VFSTONFS(mp);
1305         /*
1306          * Goes something like this..
1307          * - Call vflush() to clear out vnodes for this filesystem
1308          * - Close the socket
1309          * - Free up the data structures
1310          */
1311         /* In the forced case, cancel any outstanding requests. */
1312         if (mntflags & MNT_FORCE) {
1313                 error = newnfs_nmcancelreqs(nmp);
1314                 if (error)
1315                         goto out;
1316                 /* For a forced close, get rid of the renew thread now */
1317                 nfscl_umount(nmp, td);
1318         }
1319         /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
1320         do {
1321                 error = vflush(mp, 1, flags, td);
1322                 if ((mntflags & MNT_FORCE) && error != 0 && ++trycnt < 30)
1323                         (void) nfs_catnap(PSOCK, error, "newndm");
1324         } while ((mntflags & MNT_FORCE) && error != 0 && trycnt < 30);
1325         if (error)
1326                 goto out;
1327
1328         /*
1329          * We are now committed to the unmount.
1330          */
1331         if ((mntflags & MNT_FORCE) == 0)
1332                 nfscl_umount(nmp, td);
1333         newnfs_disconnect(&nmp->nm_sockreq);
1334         crfree(nmp->nm_sockreq.nr_cred);
1335         FREE(nmp->nm_nam, M_SONAME);
1336
1337         mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1338         mtx_destroy(&nmp->nm_mtx);
1339         FREE(nmp, M_NEWNFSMNT);
1340 out:
1341         return (error);
1342 }
1343
1344 /*
1345  * Return root of a filesystem
1346  */
1347 static int
1348 nfs_root(struct mount *mp, int flags, struct vnode **vpp)
1349 {
1350         struct vnode *vp;
1351         struct nfsmount *nmp;
1352         struct nfsnode *np;
1353         int error;
1354
1355         nmp = VFSTONFS(mp);
1356         error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, flags);
1357         if (error)
1358                 return error;
1359         vp = NFSTOV(np);
1360         /*
1361          * Get transfer parameters and attributes for root vnode once.
1362          */
1363         mtx_lock(&nmp->nm_mtx);
1364         if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
1365                 mtx_unlock(&nmp->nm_mtx);
1366                 ncl_fsinfo(nmp, vp, curthread->td_ucred, curthread);
1367         } else 
1368                 mtx_unlock(&nmp->nm_mtx);
1369         if (vp->v_type == VNON)
1370             vp->v_type = VDIR;
1371         vp->v_vflag |= VV_ROOT;
1372         *vpp = vp;
1373         return (0);
1374 }
1375
1376 /*
1377  * Flush out the buffer cache
1378  */
1379 /* ARGSUSED */
1380 static int
1381 nfs_sync(struct mount *mp, int waitfor)
1382 {
1383         struct vnode *vp, *mvp;
1384         struct thread *td;
1385         int error, allerror = 0;
1386
1387         td = curthread;
1388
1389         /*
1390          * Force stale buffer cache information to be flushed.
1391          */
1392         MNT_ILOCK(mp);
1393 loop:
1394         MNT_VNODE_FOREACH(vp, mp, mvp) {
1395                 VI_LOCK(vp);
1396                 MNT_IUNLOCK(mp);
1397                 /* XXX Racy bv_cnt check. */
1398                 if (VOP_ISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
1399                     waitfor == MNT_LAZY) {
1400                         VI_UNLOCK(vp);
1401                         MNT_ILOCK(mp);
1402                         continue;
1403                 }
1404                 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
1405                         MNT_ILOCK(mp);
1406                         MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp);
1407                         goto loop;
1408                 }
1409                 error = VOP_FSYNC(vp, waitfor, td);
1410                 if (error)
1411                         allerror = error;
1412                 VOP_UNLOCK(vp, 0);
1413                 vrele(vp);
1414
1415                 MNT_ILOCK(mp);
1416         }
1417         MNT_IUNLOCK(mp);
1418         return (allerror);
1419 }
1420
1421 static int
1422 nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
1423 {
1424         struct nfsmount *nmp = VFSTONFS(mp);
1425         struct vfsquery vq;
1426         int error;
1427
1428         bzero(&vq, sizeof(vq));
1429         switch (op) {
1430 #if 0
1431         case VFS_CTL_NOLOCKS:
1432                 val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
1433                 if (req->oldptr != NULL) {
1434                         error = SYSCTL_OUT(req, &val, sizeof(val));
1435                         if (error)
1436                                 return (error);
1437                 }
1438                 if (req->newptr != NULL) {
1439                         error = SYSCTL_IN(req, &val, sizeof(val));
1440                         if (error)
1441                                 return (error);
1442                         if (val)
1443                                 nmp->nm_flag |= NFSMNT_NOLOCKS;
1444                         else
1445                                 nmp->nm_flag &= ~NFSMNT_NOLOCKS;
1446                 }
1447                 break;
1448 #endif
1449         case VFS_CTL_QUERY:
1450                 mtx_lock(&nmp->nm_mtx);
1451                 if (nmp->nm_state & NFSSTA_TIMEO)
1452                         vq.vq_flags |= VQ_NOTRESP;
1453                 mtx_unlock(&nmp->nm_mtx);
1454 #if 0
1455                 if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
1456                     (nmp->nm_state & NFSSTA_LOCKTIMEO))
1457                         vq.vq_flags |= VQ_NOTRESPLOCK;
1458 #endif
1459                 error = SYSCTL_OUT(req, &vq, sizeof(vq));
1460                 break;
1461         case VFS_CTL_TIMEO:
1462                 if (req->oldptr != NULL) {
1463                         error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
1464                             sizeof(nmp->nm_tprintf_initial_delay));
1465                         if (error)
1466                                 return (error);
1467                 }
1468                 if (req->newptr != NULL) {
1469                         error = vfs_suser(mp, req->td);
1470                         if (error)
1471                                 return (error);
1472                         error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
1473                             sizeof(nmp->nm_tprintf_initial_delay));
1474                         if (error)
1475                                 return (error);
1476                         if (nmp->nm_tprintf_initial_delay < 0)
1477                                 nmp->nm_tprintf_initial_delay = 0;
1478                 }
1479                 break;
1480         default:
1481                 return (ENOTSUP);
1482         }
1483         return (0);
1484 }
1485
1486 /*
1487  * Extract the information needed by the nlm from the nfs vnode.
1488  */
1489 static void
1490 nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp,
1491     struct sockaddr_storage *sp, int *is_v3p, off_t *sizep,
1492     struct timeval *timeop)
1493 {
1494         struct nfsmount *nmp;
1495         struct nfsnode *np = VTONFS(vp);
1496
1497         nmp = VFSTONFS(vp->v_mount);
1498         if (fhlenp != NULL)
1499                 *fhlenp = (size_t)np->n_fhp->nfh_len;
1500         if (fhp != NULL)
1501                 bcopy(np->n_fhp->nfh_fh, fhp, np->n_fhp->nfh_len);
1502         if (sp != NULL)
1503                 bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp)));
1504         if (is_v3p != NULL)
1505                 *is_v3p = NFS_ISV3(vp);
1506         if (sizep != NULL)
1507                 *sizep = np->n_size;
1508         if (timeop != NULL) {
1509                 timeop->tv_sec = nmp->nm_timeo / NFS_HZ;
1510                 timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ);
1511         }
1512 }
1513