]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/fs/nfsclient/nfs_clvfsops.c
MFC r273849:
[FreeBSD/stable/10.git] / sys / fs / nfsclient / nfs_clvfsops.c
1 /*-
2  * Copyright (c) 1989, 1993, 1995
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Rick Macklem at The University of Guelph.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 4. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  *      from nfs_vfsops.c       8.12 (Berkeley) 5/20/95
33  */
34
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
37
38
39 #include "opt_bootp.h"
40 #include "opt_nfsroot.h"
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/bio.h>
46 #include <sys/buf.h>
47 #include <sys/clock.h>
48 #include <sys/jail.h>
49 #include <sys/limits.h>
50 #include <sys/lock.h>
51 #include <sys/malloc.h>
52 #include <sys/mbuf.h>
53 #include <sys/module.h>
54 #include <sys/mount.h>
55 #include <sys/proc.h>
56 #include <sys/socket.h>
57 #include <sys/socketvar.h>
58 #include <sys/sockio.h>
59 #include <sys/sysctl.h>
60 #include <sys/vnode.h>
61 #include <sys/signalvar.h>
62
63 #include <vm/vm.h>
64 #include <vm/vm_extern.h>
65 #include <vm/uma.h>
66
67 #include <net/if.h>
68 #include <net/route.h>
69 #include <netinet/in.h>
70
71 #include <fs/nfs/nfsport.h>
72 #include <fs/nfsclient/nfsnode.h>
73 #include <fs/nfsclient/nfsmount.h>
74 #include <fs/nfsclient/nfs.h>
75 #include <nfs/nfsdiskless.h>
76
77 FEATURE(nfscl, "NFSv4 client");
78
79 extern int nfscl_ticks;
80 extern struct timeval nfsboottime;
81 extern struct nfsstats  newnfsstats;
82 extern int nfsrv_useacl;
83 extern int nfscl_debuglevel;
84 extern enum nfsiod_state ncl_iodwant[NFS_MAXASYNCDAEMON];
85 extern struct nfsmount *ncl_iodmount[NFS_MAXASYNCDAEMON];
86 extern struct mtx ncl_iod_mutex;
87 NFSCLSTATEMUTEX;
88
89 MALLOC_DEFINE(M_NEWNFSREQ, "newnfsclient_req", "New NFS request header");
90 MALLOC_DEFINE(M_NEWNFSMNT, "newnfsmnt", "New NFS mount struct");
91
92 SYSCTL_DECL(_vfs_nfs);
93 static int nfs_ip_paranoia = 1;
94 SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW,
95     &nfs_ip_paranoia, 0, "");
96 static int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
97 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_INITIAL_DELAY,
98         downdelayinitial, CTLFLAG_RW, &nfs_tprintf_initial_delay, 0, "");
99 /* how long between console messages "nfs server foo not responding" */
100 static int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
101 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_DELAY,
102         downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0, "");
103
104 static int      nfs_mountroot(struct mount *);
105 static void     nfs_sec_name(char *, int *);
106 static void     nfs_decode_args(struct mount *mp, struct nfsmount *nmp,
107                     struct nfs_args *argp, const char *, struct ucred *,
108                     struct thread *);
109 static int      mountnfs(struct nfs_args *, struct mount *,
110                     struct sockaddr *, char *, u_char *, int, u_char *, int,
111                     u_char *, int, struct vnode **, struct ucred *,
112                     struct thread *, int, int, int);
113 static void     nfs_getnlminfo(struct vnode *, uint8_t *, size_t *,
114                     struct sockaddr_storage *, int *, off_t *,
115                     struct timeval *);
116 static vfs_mount_t nfs_mount;
117 static vfs_cmount_t nfs_cmount;
118 static vfs_unmount_t nfs_unmount;
119 static vfs_root_t nfs_root;
120 static vfs_statfs_t nfs_statfs;
121 static vfs_sync_t nfs_sync;
122 static vfs_sysctl_t nfs_sysctl;
123 static vfs_purge_t nfs_purge;
124
125 /*
126  * nfs vfs operations.
127  */
128 static struct vfsops nfs_vfsops = {
129         .vfs_init =             ncl_init,
130         .vfs_mount =            nfs_mount,
131         .vfs_cmount =           nfs_cmount,
132         .vfs_root =             nfs_root,
133         .vfs_statfs =           nfs_statfs,
134         .vfs_sync =             nfs_sync,
135         .vfs_uninit =           ncl_uninit,
136         .vfs_unmount =          nfs_unmount,
137         .vfs_sysctl =           nfs_sysctl,
138         .vfs_purge =            nfs_purge,
139 };
140 VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK | VFCF_SBDRY);
141
142 /* So that loader and kldload(2) can find us, wherever we are.. */
143 MODULE_VERSION(nfs, 1);
144 MODULE_DEPEND(nfs, nfscommon, 1, 1, 1);
145 MODULE_DEPEND(nfs, krpc, 1, 1, 1);
146 MODULE_DEPEND(nfs, nfssvc, 1, 1, 1);
147 MODULE_DEPEND(nfs, nfslock, 1, 1, 1);
148
149 /*
150  * This structure is now defined in sys/nfs/nfs_diskless.c so that it
151  * can be shared by both NFS clients. It is declared here so that it
152  * will be defined for kernels built without NFS_ROOT, although it
153  * isn't used in that case.
154  */
155 #if !defined(NFS_ROOT) && !defined(NFSCLIENT)
156 struct nfs_diskless     nfs_diskless = { { { 0 } } };
157 struct nfsv3_diskless   nfsv3_diskless = { { { 0 } } };
158 int                     nfs_diskless_valid = 0;
159 #endif
160
161 SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
162     &nfs_diskless_valid, 0,
163     "Has the diskless struct been filled correctly");
164
165 SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
166     nfsv3_diskless.root_hostnam, 0, "Path to nfs root");
167
168 SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
169     &nfsv3_diskless.root_saddr, sizeof(nfsv3_diskless.root_saddr),
170     "%Ssockaddr_in", "Diskless root nfs address");
171
172
173 void            newnfsargs_ntoh(struct nfs_args *);
174 static int      nfs_mountdiskless(char *,
175                     struct sockaddr_in *, struct nfs_args *,
176                     struct thread *, struct vnode **, struct mount *);
177 static void     nfs_convert_diskless(void);
178 static void     nfs_convert_oargs(struct nfs_args *args,
179                     struct onfs_args *oargs);
180
181 int
182 newnfs_iosize(struct nfsmount *nmp)
183 {
184         int iosize, maxio;
185
186         /* First, set the upper limit for iosize */
187         if (nmp->nm_flag & NFSMNT_NFSV4) {
188                 maxio = NFS_MAXBSIZE;
189         } else if (nmp->nm_flag & NFSMNT_NFSV3) {
190                 if (nmp->nm_sotype == SOCK_DGRAM)
191                         maxio = NFS_MAXDGRAMDATA;
192                 else
193                         maxio = NFS_MAXBSIZE;
194         } else {
195                 maxio = NFS_V2MAXDATA;
196         }
197         if (nmp->nm_rsize > maxio || nmp->nm_rsize == 0)
198                 nmp->nm_rsize = maxio;
199         if (nmp->nm_rsize > MAXBSIZE)
200                 nmp->nm_rsize = MAXBSIZE;
201         if (nmp->nm_readdirsize > maxio || nmp->nm_readdirsize == 0)
202                 nmp->nm_readdirsize = maxio;
203         if (nmp->nm_readdirsize > nmp->nm_rsize)
204                 nmp->nm_readdirsize = nmp->nm_rsize;
205         if (nmp->nm_wsize > maxio || nmp->nm_wsize == 0)
206                 nmp->nm_wsize = maxio;
207         if (nmp->nm_wsize > MAXBSIZE)
208                 nmp->nm_wsize = MAXBSIZE;
209
210         /*
211          * Calculate the size used for io buffers.  Use the larger
212          * of the two sizes to minimise nfs requests but make sure
213          * that it is at least one VM page to avoid wasting buffer
214          * space.
215          */
216         iosize = imax(nmp->nm_rsize, nmp->nm_wsize);
217         iosize = imax(iosize, PAGE_SIZE);
218         nmp->nm_mountp->mnt_stat.f_iosize = iosize;
219         return (iosize);
220 }
221
222 static void
223 nfs_convert_oargs(struct nfs_args *args, struct onfs_args *oargs)
224 {
225
226         args->version = NFS_ARGSVERSION;
227         args->addr = oargs->addr;
228         args->addrlen = oargs->addrlen;
229         args->sotype = oargs->sotype;
230         args->proto = oargs->proto;
231         args->fh = oargs->fh;
232         args->fhsize = oargs->fhsize;
233         args->flags = oargs->flags;
234         args->wsize = oargs->wsize;
235         args->rsize = oargs->rsize;
236         args->readdirsize = oargs->readdirsize;
237         args->timeo = oargs->timeo;
238         args->retrans = oargs->retrans;
239         args->readahead = oargs->readahead;
240         args->hostname = oargs->hostname;
241 }
242
243 static void
244 nfs_convert_diskless(void)
245 {
246
247         bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
248                 sizeof(struct ifaliasreq));
249         bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
250                 sizeof(struct sockaddr_in));
251         nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
252         if (nfsv3_diskless.root_args.flags & NFSMNT_NFSV3) {
253                 nfsv3_diskless.root_fhsize = NFSX_MYFH;
254                 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_MYFH);
255         } else {
256                 nfsv3_diskless.root_fhsize = NFSX_V2FH;
257                 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
258         }
259         bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
260                 sizeof(struct sockaddr_in));
261         bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN);
262         nfsv3_diskless.root_time = nfs_diskless.root_time;
263         bcopy(nfs_diskless.my_hostnam, nfsv3_diskless.my_hostnam,
264                 MAXHOSTNAMELEN);
265         nfs_diskless_valid = 3;
266 }
267
268 /*
269  * nfs statfs call
270  */
271 static int
272 nfs_statfs(struct mount *mp, struct statfs *sbp)
273 {
274         struct vnode *vp;
275         struct thread *td;
276         struct nfsmount *nmp = VFSTONFS(mp);
277         struct nfsvattr nfsva;
278         struct nfsfsinfo fs;
279         struct nfsstatfs sb;
280         int error = 0, attrflag, gotfsinfo = 0, ret;
281         struct nfsnode *np;
282
283         td = curthread;
284
285         error = vfs_busy(mp, MBF_NOWAIT);
286         if (error)
287                 return (error);
288         error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
289         if (error) {
290                 vfs_unbusy(mp);
291                 return (error);
292         }
293         vp = NFSTOV(np);
294         mtx_lock(&nmp->nm_mtx);
295         if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
296                 mtx_unlock(&nmp->nm_mtx);
297                 error = nfsrpc_fsinfo(vp, &fs, td->td_ucred, td, &nfsva,
298                     &attrflag, NULL);
299                 if (!error)
300                         gotfsinfo = 1;
301         } else
302                 mtx_unlock(&nmp->nm_mtx);
303         if (!error)
304                 error = nfsrpc_statfs(vp, &sb, &fs, td->td_ucred, td, &nfsva,
305                     &attrflag, NULL);
306         if (error != 0)
307                 NFSCL_DEBUG(2, "statfs=%d\n", error);
308         if (attrflag == 0) {
309                 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
310                     td->td_ucred, td, &nfsva, NULL, NULL);
311                 if (ret) {
312                         /*
313                          * Just set default values to get things going.
314                          */
315                         NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
316                         nfsva.na_vattr.va_type = VDIR;
317                         nfsva.na_vattr.va_mode = 0777;
318                         nfsva.na_vattr.va_nlink = 100;
319                         nfsva.na_vattr.va_uid = (uid_t)0;
320                         nfsva.na_vattr.va_gid = (gid_t)0;
321                         nfsva.na_vattr.va_fileid = 2;
322                         nfsva.na_vattr.va_gen = 1;
323                         nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
324                         nfsva.na_vattr.va_size = 512 * 1024;
325                 }
326         }
327         (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
328         if (!error) {
329             mtx_lock(&nmp->nm_mtx);
330             if (gotfsinfo || (nmp->nm_flag & NFSMNT_NFSV4))
331                 nfscl_loadfsinfo(nmp, &fs);
332             nfscl_loadsbinfo(nmp, &sb, sbp);
333             sbp->f_iosize = newnfs_iosize(nmp);
334             mtx_unlock(&nmp->nm_mtx);
335             if (sbp != &mp->mnt_stat) {
336                 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
337                 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
338             }
339             strncpy(&sbp->f_fstypename[0], mp->mnt_vfc->vfc_name, MFSNAMELEN);
340         } else if (NFS_ISV4(vp)) {
341                 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
342         }
343         vput(vp);
344         vfs_unbusy(mp);
345         return (error);
346 }
347
348 /*
349  * nfs version 3 fsinfo rpc call
350  */
351 int
352 ncl_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred,
353     struct thread *td)
354 {
355         struct nfsfsinfo fs;
356         struct nfsvattr nfsva;
357         int error, attrflag;
358         
359         error = nfsrpc_fsinfo(vp, &fs, cred, td, &nfsva, &attrflag, NULL);
360         if (!error) {
361                 if (attrflag)
362                         (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0,
363                             1);
364                 mtx_lock(&nmp->nm_mtx);
365                 nfscl_loadfsinfo(nmp, &fs);
366                 mtx_unlock(&nmp->nm_mtx);
367         }
368         return (error);
369 }
370
371 /*
372  * Mount a remote root fs via. nfs. This depends on the info in the
373  * nfs_diskless structure that has been filled in properly by some primary
374  * bootstrap.
375  * It goes something like this:
376  * - do enough of "ifconfig" by calling ifioctl() so that the system
377  *   can talk to the server
378  * - If nfs_diskless.mygateway is filled in, use that address as
379  *   a default gateway.
380  * - build the rootfs mount point and call mountnfs() to do the rest.
381  *
382  * It is assumed to be safe to read, modify, and write the nfsv3_diskless
383  * structure, as well as other global NFS client variables here, as
384  * nfs_mountroot() will be called once in the boot before any other NFS
385  * client activity occurs.
386  */
387 static int
388 nfs_mountroot(struct mount *mp)
389 {
390         struct thread *td = curthread;
391         struct nfsv3_diskless *nd = &nfsv3_diskless;
392         struct socket *so;
393         struct vnode *vp;
394         struct ifreq ir;
395         int error;
396         u_long l;
397         char buf[128];
398         char *cp;
399
400 #if defined(BOOTP_NFSROOT) && defined(BOOTP)
401         bootpc_init();          /* use bootp to get nfs_diskless filled in */
402 #elif defined(NFS_ROOT)
403         nfs_setup_diskless();
404 #endif
405
406         if (nfs_diskless_valid == 0)
407                 return (-1);
408         if (nfs_diskless_valid == 1)
409                 nfs_convert_diskless();
410
411         /*
412          * XXX splnet, so networks will receive...
413          */
414         splnet();
415
416         /*
417          * Do enough of ifconfig(8) so that the critical net interface can
418          * talk to the server.
419          */
420         error = socreate(nd->myif.ifra_addr.sa_family, &so, nd->root_args.sotype, 0,
421             td->td_ucred, td);
422         if (error)
423                 panic("nfs_mountroot: socreate(%04x): %d",
424                         nd->myif.ifra_addr.sa_family, error);
425
426 #if 0 /* XXX Bad idea */
427         /*
428          * We might not have been told the right interface, so we pass
429          * over the first ten interfaces of the same kind, until we get
430          * one of them configured.
431          */
432
433         for (i = strlen(nd->myif.ifra_name) - 1;
434                 nd->myif.ifra_name[i] >= '0' &&
435                 nd->myif.ifra_name[i] <= '9';
436                 nd->myif.ifra_name[i] ++) {
437                 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
438                 if(!error)
439                         break;
440         }
441 #endif
442         error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
443         if (error)
444                 panic("nfs_mountroot: SIOCAIFADDR: %d", error);
445         if ((cp = getenv("boot.netif.mtu")) != NULL) {
446                 ir.ifr_mtu = strtol(cp, NULL, 10);
447                 bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ);
448                 freeenv(cp);
449                 error = ifioctl(so, SIOCSIFMTU, (caddr_t)&ir, td);
450                 if (error)
451                         printf("nfs_mountroot: SIOCSIFMTU: %d", error);
452         }
453         soclose(so);
454
455         /*
456          * If the gateway field is filled in, set it as the default route.
457          * Note that pxeboot will set a default route of 0 if the route
458          * is not set by the DHCP server.  Check also for a value of 0
459          * to avoid panicking inappropriately in that situation.
460          */
461         if (nd->mygateway.sin_len != 0 &&
462             nd->mygateway.sin_addr.s_addr != 0) {
463                 struct sockaddr_in mask, sin;
464
465                 bzero((caddr_t)&mask, sizeof(mask));
466                 sin = mask;
467                 sin.sin_family = AF_INET;
468                 sin.sin_len = sizeof(sin);
469                 /* XXX MRT use table 0 for this sort of thing */
470                 CURVNET_SET(TD_TO_VNET(td));
471                 error = rtrequest_fib(RTM_ADD, (struct sockaddr *)&sin,
472                     (struct sockaddr *)&nd->mygateway,
473                     (struct sockaddr *)&mask,
474                     RTF_UP | RTF_GATEWAY, NULL, RT_DEFAULT_FIB);
475                 CURVNET_RESTORE();
476                 if (error)
477                         panic("nfs_mountroot: RTM_ADD: %d", error);
478         }
479
480         /*
481          * Create the rootfs mount point.
482          */
483         nd->root_args.fh = nd->root_fh;
484         nd->root_args.fhsize = nd->root_fhsize;
485         l = ntohl(nd->root_saddr.sin_addr.s_addr);
486         snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
487                 (l >> 24) & 0xff, (l >> 16) & 0xff,
488                 (l >>  8) & 0xff, (l >>  0) & 0xff, nd->root_hostnam);
489         printf("NFS ROOT: %s\n", buf);
490         nd->root_args.hostname = buf;
491         if ((error = nfs_mountdiskless(buf,
492             &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) {
493                 return (error);
494         }
495
496         /*
497          * This is not really an nfs issue, but it is much easier to
498          * set hostname here and then let the "/etc/rc.xxx" files
499          * mount the right /var based upon its preset value.
500          */
501         mtx_lock(&prison0.pr_mtx);
502         strlcpy(prison0.pr_hostname, nd->my_hostnam,
503             sizeof(prison0.pr_hostname));
504         mtx_unlock(&prison0.pr_mtx);
505         inittodr(ntohl(nd->root_time));
506         return (0);
507 }
508
509 /*
510  * Internal version of mount system call for diskless setup.
511  */
512 static int
513 nfs_mountdiskless(char *path,
514     struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
515     struct vnode **vpp, struct mount *mp)
516 {
517         struct sockaddr *nam;
518         int dirlen, error;
519         char *dirpath;
520
521         /*
522          * Find the directory path in "path", which also has the server's
523          * name/ip address in it.
524          */
525         dirpath = strchr(path, ':');
526         if (dirpath != NULL)
527                 dirlen = strlen(++dirpath);
528         else
529                 dirlen = 0;
530         nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
531         if ((error = mountnfs(args, mp, nam, path, NULL, 0, dirpath, dirlen,
532             NULL, 0, vpp, td->td_ucred, td, NFS_DEFAULT_NAMETIMEO, 
533             NFS_DEFAULT_NEGNAMETIMEO, 0)) != 0) {
534                 printf("nfs_mountroot: mount %s on /: %d\n", path, error);
535                 return (error);
536         }
537         return (0);
538 }
539
540 static void
541 nfs_sec_name(char *sec, int *flagsp)
542 {
543         if (!strcmp(sec, "krb5"))
544                 *flagsp |= NFSMNT_KERB;
545         else if (!strcmp(sec, "krb5i"))
546                 *flagsp |= (NFSMNT_KERB | NFSMNT_INTEGRITY);
547         else if (!strcmp(sec, "krb5p"))
548                 *flagsp |= (NFSMNT_KERB | NFSMNT_PRIVACY);
549 }
550
551 static void
552 nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
553     const char *hostname, struct ucred *cred, struct thread *td)
554 {
555         int s;
556         int adjsock;
557         char *p;
558
559         s = splnet();
560
561         /*
562          * Set read-only flag if requested; otherwise, clear it if this is
563          * an update.  If this is not an update, then either the read-only
564          * flag is already clear, or this is a root mount and it was set
565          * intentionally at some previous point.
566          */
567         if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) {
568                 MNT_ILOCK(mp);
569                 mp->mnt_flag |= MNT_RDONLY;
570                 MNT_IUNLOCK(mp);
571         } else if (mp->mnt_flag & MNT_UPDATE) {
572                 MNT_ILOCK(mp);
573                 mp->mnt_flag &= ~MNT_RDONLY;
574                 MNT_IUNLOCK(mp);
575         }
576
577         /*
578          * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
579          * no sense in that context.  Also, set up appropriate retransmit
580          * and soft timeout behavior.
581          */
582         if (argp->sotype == SOCK_STREAM) {
583                 nmp->nm_flag &= ~NFSMNT_NOCONN;
584                 nmp->nm_timeo = NFS_MAXTIMEO;
585                 if ((argp->flags & NFSMNT_NFSV4) != 0)
586                         nmp->nm_retry = INT_MAX;
587                 else
588                         nmp->nm_retry = NFS_RETRANS_TCP;
589         }
590
591         /* Also clear RDIRPLUS if NFSv2, it crashes some servers */
592         if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
593                 argp->flags &= ~NFSMNT_RDIRPLUS;
594                 nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
595         }
596
597         /* Re-bind if rsrvd port requested and wasn't on one */
598         adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
599                   && (argp->flags & NFSMNT_RESVPORT);
600         /* Also re-bind if we're switching to/from a connected UDP socket */
601         adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
602                     (argp->flags & NFSMNT_NOCONN));
603
604         /* Update flags atomically.  Don't change the lock bits. */
605         nmp->nm_flag = argp->flags | nmp->nm_flag;
606         splx(s);
607
608         if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
609                 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
610                 if (nmp->nm_timeo < NFS_MINTIMEO)
611                         nmp->nm_timeo = NFS_MINTIMEO;
612                 else if (nmp->nm_timeo > NFS_MAXTIMEO)
613                         nmp->nm_timeo = NFS_MAXTIMEO;
614         }
615
616         if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
617                 nmp->nm_retry = argp->retrans;
618                 if (nmp->nm_retry > NFS_MAXREXMIT)
619                         nmp->nm_retry = NFS_MAXREXMIT;
620         }
621
622         if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
623                 nmp->nm_wsize = argp->wsize;
624                 /*
625                  * Clip at the power of 2 below the size. There is an
626                  * issue (not isolated) that causes intermittent page
627                  * faults if this is not done.
628                  */
629                 if (nmp->nm_wsize > NFS_FABLKSIZE)
630                         nmp->nm_wsize = 1 << (fls(nmp->nm_wsize) - 1);
631                 else
632                         nmp->nm_wsize = NFS_FABLKSIZE;
633         }
634
635         if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
636                 nmp->nm_rsize = argp->rsize;
637                 /*
638                  * Clip at the power of 2 below the size. There is an
639                  * issue (not isolated) that causes intermittent page
640                  * faults if this is not done.
641                  */
642                 if (nmp->nm_rsize > NFS_FABLKSIZE)
643                         nmp->nm_rsize = 1 << (fls(nmp->nm_rsize) - 1);
644                 else
645                         nmp->nm_rsize = NFS_FABLKSIZE;
646         }
647
648         if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
649                 nmp->nm_readdirsize = argp->readdirsize;
650         }
651
652         if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
653                 nmp->nm_acregmin = argp->acregmin;
654         else
655                 nmp->nm_acregmin = NFS_MINATTRTIMO;
656         if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
657                 nmp->nm_acregmax = argp->acregmax;
658         else
659                 nmp->nm_acregmax = NFS_MAXATTRTIMO;
660         if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
661                 nmp->nm_acdirmin = argp->acdirmin;
662         else
663                 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
664         if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
665                 nmp->nm_acdirmax = argp->acdirmax;
666         else
667                 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
668         if (nmp->nm_acdirmin > nmp->nm_acdirmax)
669                 nmp->nm_acdirmin = nmp->nm_acdirmax;
670         if (nmp->nm_acregmin > nmp->nm_acregmax)
671                 nmp->nm_acregmin = nmp->nm_acregmax;
672
673         if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
674                 if (argp->readahead <= NFS_MAXRAHEAD)
675                         nmp->nm_readahead = argp->readahead;
676                 else
677                         nmp->nm_readahead = NFS_MAXRAHEAD;
678         }
679         if ((argp->flags & NFSMNT_WCOMMITSIZE) && argp->wcommitsize >= 0) {
680                 if (argp->wcommitsize < nmp->nm_wsize)
681                         nmp->nm_wcommitsize = nmp->nm_wsize;
682                 else
683                         nmp->nm_wcommitsize = argp->wcommitsize;
684         }
685
686         adjsock |= ((nmp->nm_sotype != argp->sotype) ||
687                     (nmp->nm_soproto != argp->proto));
688
689         if (nmp->nm_client != NULL && adjsock) {
690                 int haslock = 0, error = 0;
691
692                 if (nmp->nm_sotype == SOCK_STREAM) {
693                         error = newnfs_sndlock(&nmp->nm_sockreq.nr_lock);
694                         if (!error)
695                                 haslock = 1;
696                 }
697                 if (!error) {
698                     newnfs_disconnect(&nmp->nm_sockreq);
699                     if (haslock)
700                         newnfs_sndunlock(&nmp->nm_sockreq.nr_lock);
701                     nmp->nm_sotype = argp->sotype;
702                     nmp->nm_soproto = argp->proto;
703                     if (nmp->nm_sotype == SOCK_DGRAM)
704                         while (newnfs_connect(nmp, &nmp->nm_sockreq,
705                             cred, td, 0)) {
706                                 printf("newnfs_args: retrying connect\n");
707                                 (void) nfs_catnap(PSOCK, 0, "newnfscon");
708                         }
709                 }
710         } else {
711                 nmp->nm_sotype = argp->sotype;
712                 nmp->nm_soproto = argp->proto;
713         }
714
715         if (hostname != NULL) {
716                 strlcpy(nmp->nm_hostname, hostname,
717                     sizeof(nmp->nm_hostname));
718                 p = strchr(nmp->nm_hostname, ':');
719                 if (p != NULL)
720                         *p = '\0';
721         }
722 }
723
724 static const char *nfs_opts[] = { "from", "nfs_args",
725     "noac", "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
726     "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
727     "async", "noconn", "nolockd", "conn", "lockd", "intr", "rdirplus",
728     "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize",
729     "retrans", "actimeo", "acregmin", "acregmax", "acdirmin", "acdirmax",
730     "resvport", "readahead", "hostname", "timeo", "timeout", "addr", "fh",
731     "nfsv3", "sec", "principal", "nfsv4", "gssname", "allgssname", "dirpath",
732     "minorversion", "nametimeo", "negnametimeo", "nocto", "noncontigwr",
733     "pnfs", "wcommitsize",
734     NULL };
735
736 /*
737  * VFS Operations.
738  *
739  * mount system call
740  * It seems a bit dumb to copyinstr() the host and path here and then
741  * bcopy() them in mountnfs(), but I wanted to detect errors before
742  * doing the sockargs() call because sockargs() allocates an mbuf and
743  * an error after that means that I have to release the mbuf.
744  */
745 /* ARGSUSED */
746 static int
747 nfs_mount(struct mount *mp)
748 {
749         struct nfs_args args = {
750             .version = NFS_ARGSVERSION,
751             .addr = NULL,
752             .addrlen = sizeof (struct sockaddr_in),
753             .sotype = SOCK_STREAM,
754             .proto = 0,
755             .fh = NULL,
756             .fhsize = 0,
757             .flags = NFSMNT_RESVPORT,
758             .wsize = NFS_WSIZE,
759             .rsize = NFS_RSIZE,
760             .readdirsize = NFS_READDIRSIZE,
761             .timeo = 10,
762             .retrans = NFS_RETRANS,
763             .readahead = NFS_DEFRAHEAD,
764             .wcommitsize = 0,                   /* was: NQ_DEFLEASE */
765             .hostname = NULL,
766             .acregmin = NFS_MINATTRTIMO,
767             .acregmax = NFS_MAXATTRTIMO,
768             .acdirmin = NFS_MINDIRATTRTIMO,
769             .acdirmax = NFS_MAXDIRATTRTIMO,
770         };
771         int error = 0, ret, len;
772         struct sockaddr *nam = NULL;
773         struct vnode *vp;
774         struct thread *td;
775         char hst[MNAMELEN];
776         u_char nfh[NFSX_FHMAX], krbname[100], dirpath[100], srvkrbname[100];
777         char *opt, *name, *secname;
778         int nametimeo = NFS_DEFAULT_NAMETIMEO;
779         int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
780         int minvers = 0;
781         int dirlen, has_nfs_args_opt, krbnamelen, srvkrbnamelen;
782         size_t hstlen;
783
784         has_nfs_args_opt = 0;
785         if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
786                 error = EINVAL;
787                 goto out;
788         }
789
790         td = curthread;
791         if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS) {
792                 error = nfs_mountroot(mp);
793                 goto out;
794         }
795
796         nfscl_init();
797
798         /*
799          * The old mount_nfs program passed the struct nfs_args
800          * from userspace to kernel.  The new mount_nfs program
801          * passes string options via nmount() from userspace to kernel
802          * and we populate the struct nfs_args in the kernel.
803          */
804         if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
805                 error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
806                     sizeof(args));
807                 if (error != 0)
808                         goto out;
809
810                 if (args.version != NFS_ARGSVERSION) {
811                         error = EPROGMISMATCH;
812                         goto out;
813                 }
814                 has_nfs_args_opt = 1;
815         }
816
817         /* Handle the new style options. */
818         if (vfs_getopt(mp->mnt_optnew, "noac", NULL, NULL) == 0) {
819                 args.acdirmin = args.acdirmax =
820                     args.acregmin = args.acregmax = 0;
821                 args.flags |= NFSMNT_ACDIRMIN | NFSMNT_ACDIRMAX |
822                     NFSMNT_ACREGMIN | NFSMNT_ACREGMAX;
823         }
824         if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
825                 args.flags |= NFSMNT_NOCONN;
826         if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
827                 args.flags |= NFSMNT_NOCONN;
828         if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
829                 args.flags |= NFSMNT_NOLOCKD;
830         if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
831                 args.flags &= ~NFSMNT_NOLOCKD;
832         if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
833                 args.flags |= NFSMNT_INT;
834         if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
835                 args.flags |= NFSMNT_RDIRPLUS;
836         if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
837                 args.flags |= NFSMNT_RESVPORT;
838         if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
839                 args.flags &= ~NFSMNT_RESVPORT;
840         if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
841                 args.flags |= NFSMNT_SOFT;
842         if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
843                 args.flags &= ~NFSMNT_SOFT;
844         if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
845                 args.sotype = SOCK_DGRAM;
846         if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
847                 args.sotype = SOCK_DGRAM;
848         if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
849                 args.sotype = SOCK_STREAM;
850         if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
851                 args.flags |= NFSMNT_NFSV3;
852         if (vfs_getopt(mp->mnt_optnew, "nfsv4", NULL, NULL) == 0) {
853                 args.flags |= NFSMNT_NFSV4;
854                 args.sotype = SOCK_STREAM;
855         }
856         if (vfs_getopt(mp->mnt_optnew, "allgssname", NULL, NULL) == 0)
857                 args.flags |= NFSMNT_ALLGSSNAME;
858         if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0)
859                 args.flags |= NFSMNT_NOCTO;
860         if (vfs_getopt(mp->mnt_optnew, "noncontigwr", NULL, NULL) == 0)
861                 args.flags |= NFSMNT_NONCONTIGWR;
862         if (vfs_getopt(mp->mnt_optnew, "pnfs", NULL, NULL) == 0)
863                 args.flags |= NFSMNT_PNFS;
864         if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
865                 if (opt == NULL) { 
866                         vfs_mount_error(mp, "illegal readdirsize");
867                         error = EINVAL;
868                         goto out;
869                 }
870                 ret = sscanf(opt, "%d", &args.readdirsize);
871                 if (ret != 1 || args.readdirsize <= 0) {
872                         vfs_mount_error(mp, "illegal readdirsize: %s",
873                             opt);
874                         error = EINVAL;
875                         goto out;
876                 }
877                 args.flags |= NFSMNT_READDIRSIZE;
878         }
879         if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
880                 if (opt == NULL) { 
881                         vfs_mount_error(mp, "illegal readahead");
882                         error = EINVAL;
883                         goto out;
884                 }
885                 ret = sscanf(opt, "%d", &args.readahead);
886                 if (ret != 1 || args.readahead <= 0) {
887                         vfs_mount_error(mp, "illegal readahead: %s",
888                             opt);
889                         error = EINVAL;
890                         goto out;
891                 }
892                 args.flags |= NFSMNT_READAHEAD;
893         }
894         if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
895                 if (opt == NULL) { 
896                         vfs_mount_error(mp, "illegal wsize");
897                         error = EINVAL;
898                         goto out;
899                 }
900                 ret = sscanf(opt, "%d", &args.wsize);
901                 if (ret != 1 || args.wsize <= 0) {
902                         vfs_mount_error(mp, "illegal wsize: %s",
903                             opt);
904                         error = EINVAL;
905                         goto out;
906                 }
907                 args.flags |= NFSMNT_WSIZE;
908         }
909         if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
910                 if (opt == NULL) { 
911                         vfs_mount_error(mp, "illegal rsize");
912                         error = EINVAL;
913                         goto out;
914                 }
915                 ret = sscanf(opt, "%d", &args.rsize);
916                 if (ret != 1 || args.rsize <= 0) {
917                         vfs_mount_error(mp, "illegal wsize: %s",
918                             opt);
919                         error = EINVAL;
920                         goto out;
921                 }
922                 args.flags |= NFSMNT_RSIZE;
923         }
924         if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
925                 if (opt == NULL) { 
926                         vfs_mount_error(mp, "illegal retrans");
927                         error = EINVAL;
928                         goto out;
929                 }
930                 ret = sscanf(opt, "%d", &args.retrans);
931                 if (ret != 1 || args.retrans <= 0) {
932                         vfs_mount_error(mp, "illegal retrans: %s",
933                             opt);
934                         error = EINVAL;
935                         goto out;
936                 }
937                 args.flags |= NFSMNT_RETRANS;
938         }
939         if (vfs_getopt(mp->mnt_optnew, "actimeo", (void **)&opt, NULL) == 0) {
940                 ret = sscanf(opt, "%d", &args.acregmin);
941                 if (ret != 1 || args.acregmin < 0) {
942                         vfs_mount_error(mp, "illegal actimeo: %s",
943                             opt);
944                         error = EINVAL;
945                         goto out;
946                 }
947                 args.acdirmin = args.acdirmax = args.acregmax = args.acregmin;
948                 args.flags |= NFSMNT_ACDIRMIN | NFSMNT_ACDIRMAX |
949                     NFSMNT_ACREGMIN | NFSMNT_ACREGMAX;
950         }
951         if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
952                 ret = sscanf(opt, "%d", &args.acregmin);
953                 if (ret != 1 || args.acregmin < 0) {
954                         vfs_mount_error(mp, "illegal acregmin: %s",
955                             opt);
956                         error = EINVAL;
957                         goto out;
958                 }
959                 args.flags |= NFSMNT_ACREGMIN;
960         }
961         if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
962                 ret = sscanf(opt, "%d", &args.acregmax);
963                 if (ret != 1 || args.acregmax < 0) {
964                         vfs_mount_error(mp, "illegal acregmax: %s",
965                             opt);
966                         error = EINVAL;
967                         goto out;
968                 }
969                 args.flags |= NFSMNT_ACREGMAX;
970         }
971         if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
972                 ret = sscanf(opt, "%d", &args.acdirmin);
973                 if (ret != 1 || args.acdirmin < 0) {
974                         vfs_mount_error(mp, "illegal acdirmin: %s",
975                             opt);
976                         error = EINVAL;
977                         goto out;
978                 }
979                 args.flags |= NFSMNT_ACDIRMIN;
980         }
981         if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
982                 ret = sscanf(opt, "%d", &args.acdirmax);
983                 if (ret != 1 || args.acdirmax < 0) {
984                         vfs_mount_error(mp, "illegal acdirmax: %s",
985                             opt);
986                         error = EINVAL;
987                         goto out;
988                 }
989                 args.flags |= NFSMNT_ACDIRMAX;
990         }
991         if (vfs_getopt(mp->mnt_optnew, "wcommitsize", (void **)&opt, NULL) == 0) {
992                 ret = sscanf(opt, "%d", &args.wcommitsize);
993                 if (ret != 1 || args.wcommitsize < 0) {
994                         vfs_mount_error(mp, "illegal wcommitsize: %s", opt);
995                         error = EINVAL;
996                         goto out;
997                 }
998                 args.flags |= NFSMNT_WCOMMITSIZE;
999         }
1000         if (vfs_getopt(mp->mnt_optnew, "timeo", (void **)&opt, NULL) == 0) {
1001                 ret = sscanf(opt, "%d", &args.timeo);
1002                 if (ret != 1 || args.timeo <= 0) {
1003                         vfs_mount_error(mp, "illegal timeo: %s",
1004                             opt);
1005                         error = EINVAL;
1006                         goto out;
1007                 }
1008                 args.flags |= NFSMNT_TIMEO;
1009         }
1010         if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
1011                 ret = sscanf(opt, "%d", &args.timeo);
1012                 if (ret != 1 || args.timeo <= 0) {
1013                         vfs_mount_error(mp, "illegal timeout: %s",
1014                             opt);
1015                         error = EINVAL;
1016                         goto out;
1017                 }
1018                 args.flags |= NFSMNT_TIMEO;
1019         }
1020         if (vfs_getopt(mp->mnt_optnew, "nametimeo", (void **)&opt, NULL) == 0) {
1021                 ret = sscanf(opt, "%d", &nametimeo);
1022                 if (ret != 1 || nametimeo < 0) {
1023                         vfs_mount_error(mp, "illegal nametimeo: %s", opt);
1024                         error = EINVAL;
1025                         goto out;
1026                 }
1027         }
1028         if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
1029             == 0) {
1030                 ret = sscanf(opt, "%d", &negnametimeo);
1031                 if (ret != 1 || negnametimeo < 0) {
1032                         vfs_mount_error(mp, "illegal negnametimeo: %s",
1033                             opt);
1034                         error = EINVAL;
1035                         goto out;
1036                 }
1037         }
1038         if (vfs_getopt(mp->mnt_optnew, "minorversion", (void **)&opt, NULL) ==
1039             0) {
1040                 ret = sscanf(opt, "%d", &minvers);
1041                 if (ret != 1 || minvers < 0 || minvers > 1 ||
1042                     (args.flags & NFSMNT_NFSV4) == 0) {
1043                         vfs_mount_error(mp, "illegal minorversion: %s", opt);
1044                         error = EINVAL;
1045                         goto out;
1046                 }
1047         }
1048         if (vfs_getopt(mp->mnt_optnew, "sec",
1049                 (void **) &secname, NULL) == 0)
1050                 nfs_sec_name(secname, &args.flags);
1051
1052         if (mp->mnt_flag & MNT_UPDATE) {
1053                 struct nfsmount *nmp = VFSTONFS(mp);
1054
1055                 if (nmp == NULL) {
1056                         error = EIO;
1057                         goto out;
1058                 }
1059
1060                 /*
1061                  * If a change from TCP->UDP is done and there are thread(s)
1062                  * that have I/O RPC(s) in progress with a tranfer size
1063                  * greater than NFS_MAXDGRAMDATA, those thread(s) will be
1064                  * hung, retrying the RPC(s) forever. Usually these threads
1065                  * will be seen doing an uninterruptible sleep on wait channel
1066                  * "newnfsreq" (truncated to "newnfsre" by procstat).
1067                  */
1068                 if (args.sotype == SOCK_DGRAM && nmp->nm_sotype == SOCK_STREAM)
1069                         tprintf(td->td_proc, LOG_WARNING,
1070         "Warning: mount -u that changes TCP->UDP can result in hung threads\n");
1071
1072                 /*
1073                  * When doing an update, we can't change version,
1074                  * security, switch lockd strategies or change cookie
1075                  * translation
1076                  */
1077                 args.flags = (args.flags &
1078                     ~(NFSMNT_NFSV3 |
1079                       NFSMNT_NFSV4 |
1080                       NFSMNT_KERB |
1081                       NFSMNT_INTEGRITY |
1082                       NFSMNT_PRIVACY |
1083                       NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
1084                     (nmp->nm_flag &
1085                         (NFSMNT_NFSV3 |
1086                          NFSMNT_NFSV4 |
1087                          NFSMNT_KERB |
1088                          NFSMNT_INTEGRITY |
1089                          NFSMNT_PRIVACY |
1090                          NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
1091                 nfs_decode_args(mp, nmp, &args, NULL, td->td_ucred, td);
1092                 goto out;
1093         }
1094
1095         /*
1096          * Make the nfs_ip_paranoia sysctl serve as the default connection
1097          * or no-connection mode for those protocols that support 
1098          * no-connection mode (the flag will be cleared later for protocols
1099          * that do not support no-connection mode).  This will allow a client
1100          * to receive replies from a different IP then the request was
1101          * sent to.  Note: default value for nfs_ip_paranoia is 1 (paranoid),
1102          * not 0.
1103          */
1104         if (nfs_ip_paranoia == 0)
1105                 args.flags |= NFSMNT_NOCONN;
1106
1107         if (has_nfs_args_opt != 0) {
1108                 /*
1109                  * In the 'nfs_args' case, the pointers in the args
1110                  * structure are in userland - we copy them in here.
1111                  */
1112                 if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
1113                         vfs_mount_error(mp, "Bad file handle");
1114                         error = EINVAL;
1115                         goto out;
1116                 }
1117                 error = copyin((caddr_t)args.fh, (caddr_t)nfh,
1118                     args.fhsize);
1119                 if (error != 0)
1120                         goto out;
1121                 error = copyinstr(args.hostname, hst, MNAMELEN - 1, &hstlen);
1122                 if (error != 0)
1123                         goto out;
1124                 bzero(&hst[hstlen], MNAMELEN - hstlen);
1125                 args.hostname = hst;
1126                 /* sockargs() call must be after above copyin() calls */
1127                 error = getsockaddr(&nam, (caddr_t)args.addr,
1128                     args.addrlen);
1129                 if (error != 0)
1130                         goto out;
1131         } else {
1132                 if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
1133                     &args.fhsize) == 0) {
1134                         if (args.fhsize < 0 || args.fhsize > NFSX_FHMAX) {
1135                                 vfs_mount_error(mp, "Bad file handle");
1136                                 error = EINVAL;
1137                                 goto out;
1138                         }
1139                         bcopy(args.fh, nfh, args.fhsize);
1140                 } else {
1141                         args.fhsize = 0;
1142                 }
1143                 (void) vfs_getopt(mp->mnt_optnew, "hostname",
1144                     (void **)&args.hostname, &len);
1145                 if (args.hostname == NULL) {
1146                         vfs_mount_error(mp, "Invalid hostname");
1147                         error = EINVAL;
1148                         goto out;
1149                 }
1150                 bcopy(args.hostname, hst, MNAMELEN);
1151                 hst[MNAMELEN - 1] = '\0';
1152         }
1153
1154         if (vfs_getopt(mp->mnt_optnew, "principal", (void **)&name, NULL) == 0)
1155                 strlcpy(srvkrbname, name, sizeof (srvkrbname));
1156         else
1157                 snprintf(srvkrbname, sizeof (srvkrbname), "nfs@%s", hst);
1158         srvkrbnamelen = strlen(srvkrbname);
1159
1160         if (vfs_getopt(mp->mnt_optnew, "gssname", (void **)&name, NULL) == 0)
1161                 strlcpy(krbname, name, sizeof (krbname));
1162         else
1163                 krbname[0] = '\0';
1164         krbnamelen = strlen(krbname);
1165
1166         if (vfs_getopt(mp->mnt_optnew, "dirpath", (void **)&name, NULL) == 0)
1167                 strlcpy(dirpath, name, sizeof (dirpath));
1168         else
1169                 dirpath[0] = '\0';
1170         dirlen = strlen(dirpath);
1171
1172         if (has_nfs_args_opt == 0) {
1173                 if (vfs_getopt(mp->mnt_optnew, "addr",
1174                     (void **)&args.addr, &args.addrlen) == 0) {
1175                         if (args.addrlen > SOCK_MAXADDRLEN) {
1176                                 error = ENAMETOOLONG;
1177                                 goto out;
1178                         }
1179                         nam = malloc(args.addrlen, M_SONAME, M_WAITOK);
1180                         bcopy(args.addr, nam, args.addrlen);
1181                         nam->sa_len = args.addrlen;
1182                 } else {
1183                         vfs_mount_error(mp, "No server address");
1184                         error = EINVAL;
1185                         goto out;
1186                 }
1187         }
1188
1189         args.fh = nfh;
1190         error = mountnfs(&args, mp, nam, hst, krbname, krbnamelen, dirpath,
1191             dirlen, srvkrbname, srvkrbnamelen, &vp, td->td_ucred, td,
1192             nametimeo, negnametimeo, minvers);
1193 out:
1194         if (!error) {
1195                 MNT_ILOCK(mp);
1196                 mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED | MNTK_NO_IOPF;
1197                 MNT_IUNLOCK(mp);
1198         }
1199         return (error);
1200 }
1201
1202
1203 /*
1204  * VFS Operations.
1205  *
1206  * mount system call
1207  * It seems a bit dumb to copyinstr() the host and path here and then
1208  * bcopy() them in mountnfs(), but I wanted to detect errors before
1209  * doing the sockargs() call because sockargs() allocates an mbuf and
1210  * an error after that means that I have to release the mbuf.
1211  */
1212 /* ARGSUSED */
1213 static int
1214 nfs_cmount(struct mntarg *ma, void *data, uint64_t flags)
1215 {
1216         int error;
1217         struct nfs_args args;
1218
1219         error = copyin(data, &args, sizeof (struct nfs_args));
1220         if (error)
1221                 return error;
1222
1223         ma = mount_arg(ma, "nfs_args", &args, sizeof args);
1224
1225         error = kernel_mount(ma, flags);
1226         return (error);
1227 }
1228
1229 /*
1230  * Common code for mount and mountroot
1231  */
1232 static int
1233 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
1234     char *hst, u_char *krbname, int krbnamelen, u_char *dirpath, int dirlen,
1235     u_char *srvkrbname, int srvkrbnamelen, struct vnode **vpp,
1236     struct ucred *cred, struct thread *td, int nametimeo, int negnametimeo,
1237     int minvers)
1238 {
1239         struct nfsmount *nmp;
1240         struct nfsnode *np;
1241         int error, trycnt, ret;
1242         struct nfsvattr nfsva;
1243         struct nfsclclient *clp;
1244         struct nfsclds *dsp, *tdsp;
1245         uint32_t lease;
1246         static u_int64_t clval = 0;
1247
1248         NFSCL_DEBUG(3, "in mnt\n");
1249         clp = NULL;
1250         if (mp->mnt_flag & MNT_UPDATE) {
1251                 nmp = VFSTONFS(mp);
1252                 printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
1253                 FREE(nam, M_SONAME);
1254                 return (0);
1255         } else {
1256                 MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount) +
1257                     krbnamelen + dirlen + srvkrbnamelen + 2,
1258                     M_NEWNFSMNT, M_WAITOK | M_ZERO);
1259                 TAILQ_INIT(&nmp->nm_bufq);
1260                 if (clval == 0)
1261                         clval = (u_int64_t)nfsboottime.tv_sec;
1262                 nmp->nm_clval = clval++;
1263                 nmp->nm_krbnamelen = krbnamelen;
1264                 nmp->nm_dirpathlen = dirlen;
1265                 nmp->nm_srvkrbnamelen = srvkrbnamelen;
1266                 if (td->td_ucred->cr_uid != (uid_t)0) {
1267                         /*
1268                          * nm_uid is used to get KerberosV credentials for
1269                          * the nfsv4 state handling operations if there is
1270                          * no host based principal set. Use the uid of
1271                          * this user if not root, since they are doing the
1272                          * mount. I don't think setting this for root will
1273                          * work, since root normally does not have user
1274                          * credentials in a credentials cache.
1275                          */
1276                         nmp->nm_uid = td->td_ucred->cr_uid;
1277                 } else {
1278                         /*
1279                          * Just set to -1, so it won't be used.
1280                          */
1281                         nmp->nm_uid = (uid_t)-1;
1282                 }
1283
1284                 /* Copy and null terminate all the names */
1285                 if (nmp->nm_krbnamelen > 0) {
1286                         bcopy(krbname, nmp->nm_krbname, nmp->nm_krbnamelen);
1287                         nmp->nm_name[nmp->nm_krbnamelen] = '\0';
1288                 }
1289                 if (nmp->nm_dirpathlen > 0) {
1290                         bcopy(dirpath, NFSMNT_DIRPATH(nmp),
1291                             nmp->nm_dirpathlen);
1292                         nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1293                             + 1] = '\0';
1294                 }
1295                 if (nmp->nm_srvkrbnamelen > 0) {
1296                         bcopy(srvkrbname, NFSMNT_SRVKRBNAME(nmp),
1297                             nmp->nm_srvkrbnamelen);
1298                         nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1299                             + nmp->nm_srvkrbnamelen + 2] = '\0';
1300                 }
1301                 nmp->nm_sockreq.nr_cred = crhold(cred);
1302                 mtx_init(&nmp->nm_sockreq.nr_mtx, "nfssock", NULL, MTX_DEF);
1303                 mp->mnt_data = nmp;
1304                 nmp->nm_getinfo = nfs_getnlminfo;
1305                 nmp->nm_vinvalbuf = ncl_vinvalbuf;
1306         }
1307         vfs_getnewfsid(mp);
1308         nmp->nm_mountp = mp;
1309         mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF | MTX_DUPOK);
1310
1311         /*
1312          * Since nfs_decode_args() might optionally set them, these
1313          * need to be set to defaults before the call, so that the
1314          * optional settings aren't overwritten.
1315          */
1316         nmp->nm_nametimeo = nametimeo;
1317         nmp->nm_negnametimeo = negnametimeo;
1318         nmp->nm_timeo = NFS_TIMEO;
1319         nmp->nm_retry = NFS_RETRANS;
1320         nmp->nm_readahead = NFS_DEFRAHEAD;
1321         if (desiredvnodes >= 11000)
1322                 nmp->nm_wcommitsize = hibufspace / (desiredvnodes / 1000);
1323         else
1324                 nmp->nm_wcommitsize = hibufspace / 10;
1325         if ((argp->flags & NFSMNT_NFSV4) != 0)
1326                 nmp->nm_minorvers = minvers;
1327         else
1328                 nmp->nm_minorvers = 0;
1329
1330         nfs_decode_args(mp, nmp, argp, hst, cred, td);
1331
1332         /*
1333          * V2 can only handle 32 bit filesizes.  A 4GB-1 limit may be too
1334          * high, depending on whether we end up with negative offsets in
1335          * the client or server somewhere.  2GB-1 may be safer.
1336          *
1337          * For V3, ncl_fsinfo will adjust this as necessary.  Assume maximum
1338          * that we can handle until we find out otherwise.
1339          */
1340         if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0)
1341                 nmp->nm_maxfilesize = 0xffffffffLL;
1342         else
1343                 nmp->nm_maxfilesize = OFF_MAX;
1344
1345         if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
1346                 nmp->nm_wsize = NFS_WSIZE;
1347                 nmp->nm_rsize = NFS_RSIZE;
1348                 nmp->nm_readdirsize = NFS_READDIRSIZE;
1349         }
1350         nmp->nm_numgrps = NFS_MAXGRPS;
1351         nmp->nm_tprintf_delay = nfs_tprintf_delay;
1352         if (nmp->nm_tprintf_delay < 0)
1353                 nmp->nm_tprintf_delay = 0;
1354         nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
1355         if (nmp->nm_tprintf_initial_delay < 0)
1356                 nmp->nm_tprintf_initial_delay = 0;
1357         nmp->nm_fhsize = argp->fhsize;
1358         if (nmp->nm_fhsize > 0)
1359                 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
1360         bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
1361         nmp->nm_nam = nam;
1362         /* Set up the sockets and per-host congestion */
1363         nmp->nm_sotype = argp->sotype;
1364         nmp->nm_soproto = argp->proto;
1365         nmp->nm_sockreq.nr_prog = NFS_PROG;
1366         if ((argp->flags & NFSMNT_NFSV4))
1367                 nmp->nm_sockreq.nr_vers = NFS_VER4;
1368         else if ((argp->flags & NFSMNT_NFSV3))
1369                 nmp->nm_sockreq.nr_vers = NFS_VER3;
1370         else
1371                 nmp->nm_sockreq.nr_vers = NFS_VER2;
1372
1373
1374         if ((error = newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0)))
1375                 goto bad;
1376         /* For NFSv4.1, get the clientid now. */
1377         if (nmp->nm_minorvers > 0) {
1378                 NFSCL_DEBUG(3, "at getcl\n");
1379                 error = nfscl_getcl(mp, cred, td, 0, &clp);
1380                 NFSCL_DEBUG(3, "aft getcl=%d\n", error);
1381                 if (error != 0)
1382                         goto bad;
1383         }
1384
1385         if (nmp->nm_fhsize == 0 && (nmp->nm_flag & NFSMNT_NFSV4) &&
1386             nmp->nm_dirpathlen > 0) {
1387                 NFSCL_DEBUG(3, "in dirp\n");
1388                 /*
1389                  * If the fhsize on the mount point == 0 for V4, the mount
1390                  * path needs to be looked up.
1391                  */
1392                 trycnt = 3;
1393                 do {
1394                         error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp),
1395                             cred, td);
1396                         NFSCL_DEBUG(3, "aft dirp=%d\n", error);
1397                         if (error)
1398                                 (void) nfs_catnap(PZERO, error, "nfsgetdirp");
1399                 } while (error && --trycnt > 0);
1400                 if (error) {
1401                         error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
1402                         goto bad;
1403                 }
1404         }
1405
1406         /*
1407          * A reference count is needed on the nfsnode representing the
1408          * remote root.  If this object is not persistent, then backward
1409          * traversals of the mount point (i.e. "..") will not work if
1410          * the nfsnode gets flushed out of the cache. Ufs does not have
1411          * this problem, because one can identify root inodes by their
1412          * number == ROOTINO (2).
1413          */
1414         if (nmp->nm_fhsize > 0) {
1415                 /*
1416                  * Set f_iosize to NFS_DIRBLKSIZ so that bo_bsize gets set
1417                  * non-zero for the root vnode. f_iosize will be set correctly
1418                  * by nfs_statfs() before any I/O occurs.
1419                  */
1420                 mp->mnt_stat.f_iosize = NFS_DIRBLKSIZ;
1421                 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np,
1422                     LK_EXCLUSIVE);
1423                 if (error)
1424                         goto bad;
1425                 *vpp = NFSTOV(np);
1426         
1427                 /*
1428                  * Get file attributes and transfer parameters for the
1429                  * mountpoint.  This has the side effect of filling in
1430                  * (*vpp)->v_type with the correct value.
1431                  */
1432                 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
1433                     cred, td, &nfsva, NULL, &lease);
1434                 if (ret) {
1435                         /*
1436                          * Just set default values to get things going.
1437                          */
1438                         NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
1439                         nfsva.na_vattr.va_type = VDIR;
1440                         nfsva.na_vattr.va_mode = 0777;
1441                         nfsva.na_vattr.va_nlink = 100;
1442                         nfsva.na_vattr.va_uid = (uid_t)0;
1443                         nfsva.na_vattr.va_gid = (gid_t)0;
1444                         nfsva.na_vattr.va_fileid = 2;
1445                         nfsva.na_vattr.va_gen = 1;
1446                         nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
1447                         nfsva.na_vattr.va_size = 512 * 1024;
1448                         lease = 60;
1449                 }
1450                 (void) nfscl_loadattrcache(vpp, &nfsva, NULL, NULL, 0, 1);
1451                 if (nmp->nm_minorvers > 0) {
1452                         NFSCL_DEBUG(3, "lease=%d\n", (int)lease);
1453                         NFSLOCKCLSTATE();
1454                         clp->nfsc_renew = NFSCL_RENEW(lease);
1455                         clp->nfsc_expire = NFSD_MONOSEC + clp->nfsc_renew;
1456                         clp->nfsc_clientidrev++;
1457                         if (clp->nfsc_clientidrev == 0)
1458                                 clp->nfsc_clientidrev++;
1459                         NFSUNLOCKCLSTATE();
1460                         /*
1461                          * Mount will succeed, so the renew thread can be
1462                          * started now.
1463                          */
1464                         nfscl_start_renewthread(clp);
1465                         nfscl_clientrelease(clp);
1466                 }
1467                 if (argp->flags & NFSMNT_NFSV3)
1468                         ncl_fsinfo(nmp, *vpp, cred, td);
1469         
1470                 /* Mark if the mount point supports NFSv4 ACLs. */
1471                 if ((argp->flags & NFSMNT_NFSV4) != 0 && nfsrv_useacl != 0 &&
1472                     ret == 0 &&
1473                     NFSISSET_ATTRBIT(&nfsva.na_suppattr, NFSATTRBIT_ACL)) {
1474                         MNT_ILOCK(mp);
1475                         mp->mnt_flag |= MNT_NFS4ACLS;
1476                         MNT_IUNLOCK(mp);
1477                 }
1478         
1479                 /*
1480                  * Lose the lock but keep the ref.
1481                  */
1482                 NFSVOPUNLOCK(*vpp, 0);
1483                 return (0);
1484         }
1485         error = EIO;
1486
1487 bad:
1488         if (clp != NULL)
1489                 nfscl_clientrelease(clp);
1490         newnfs_disconnect(&nmp->nm_sockreq);
1491         crfree(nmp->nm_sockreq.nr_cred);
1492         if (nmp->nm_sockreq.nr_auth != NULL)
1493                 AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
1494         mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1495         mtx_destroy(&nmp->nm_mtx);
1496         if (nmp->nm_clp != NULL) {
1497                 NFSLOCKCLSTATE();
1498                 LIST_REMOVE(nmp->nm_clp, nfsc_list);
1499                 NFSUNLOCKCLSTATE();
1500                 free(nmp->nm_clp, M_NFSCLCLIENT);
1501         }
1502         TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp)
1503                 nfscl_freenfsclds(dsp);
1504         FREE(nmp, M_NEWNFSMNT);
1505         FREE(nam, M_SONAME);
1506         return (error);
1507 }
1508
1509 /*
1510  * unmount system call
1511  */
1512 static int
1513 nfs_unmount(struct mount *mp, int mntflags)
1514 {
1515         struct thread *td;
1516         struct nfsmount *nmp;
1517         int error, flags = 0, i, trycnt = 0;
1518         struct nfsclds *dsp, *tdsp;
1519
1520         td = curthread;
1521
1522         if (mntflags & MNT_FORCE)
1523                 flags |= FORCECLOSE;
1524         nmp = VFSTONFS(mp);
1525         /*
1526          * Goes something like this..
1527          * - Call vflush() to clear out vnodes for this filesystem
1528          * - Close the socket
1529          * - Free up the data structures
1530          */
1531         /* In the forced case, cancel any outstanding requests. */
1532         if (mntflags & MNT_FORCE) {
1533                 error = newnfs_nmcancelreqs(nmp);
1534                 if (error)
1535                         goto out;
1536                 /* For a forced close, get rid of the renew thread now */
1537                 nfscl_umount(nmp, td);
1538         }
1539         /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
1540         do {
1541                 error = vflush(mp, 1, flags, td);
1542                 if ((mntflags & MNT_FORCE) && error != 0 && ++trycnt < 30)
1543                         (void) nfs_catnap(PSOCK, error, "newndm");
1544         } while ((mntflags & MNT_FORCE) && error != 0 && trycnt < 30);
1545         if (error)
1546                 goto out;
1547
1548         /*
1549          * We are now committed to the unmount.
1550          */
1551         if ((mntflags & MNT_FORCE) == 0)
1552                 nfscl_umount(nmp, td);
1553         /* Make sure no nfsiods are assigned to this mount. */
1554         mtx_lock(&ncl_iod_mutex);
1555         for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
1556                 if (ncl_iodmount[i] == nmp) {
1557                         ncl_iodwant[i] = NFSIOD_AVAILABLE;
1558                         ncl_iodmount[i] = NULL;
1559                 }
1560         mtx_unlock(&ncl_iod_mutex);
1561         newnfs_disconnect(&nmp->nm_sockreq);
1562         crfree(nmp->nm_sockreq.nr_cred);
1563         FREE(nmp->nm_nam, M_SONAME);
1564         if (nmp->nm_sockreq.nr_auth != NULL)
1565                 AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
1566         mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1567         mtx_destroy(&nmp->nm_mtx);
1568         TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp)
1569                 nfscl_freenfsclds(dsp);
1570         FREE(nmp, M_NEWNFSMNT);
1571 out:
1572         return (error);
1573 }
1574
1575 /*
1576  * Return root of a filesystem
1577  */
1578 static int
1579 nfs_root(struct mount *mp, int flags, struct vnode **vpp)
1580 {
1581         struct vnode *vp;
1582         struct nfsmount *nmp;
1583         struct nfsnode *np;
1584         int error;
1585
1586         nmp = VFSTONFS(mp);
1587         error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, flags);
1588         if (error)
1589                 return error;
1590         vp = NFSTOV(np);
1591         /*
1592          * Get transfer parameters and attributes for root vnode once.
1593          */
1594         mtx_lock(&nmp->nm_mtx);
1595         if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
1596                 mtx_unlock(&nmp->nm_mtx);
1597                 ncl_fsinfo(nmp, vp, curthread->td_ucred, curthread);
1598         } else 
1599                 mtx_unlock(&nmp->nm_mtx);
1600         if (vp->v_type == VNON)
1601             vp->v_type = VDIR;
1602         vp->v_vflag |= VV_ROOT;
1603         *vpp = vp;
1604         return (0);
1605 }
1606
1607 /*
1608  * Flush out the buffer cache
1609  */
1610 /* ARGSUSED */
1611 static int
1612 nfs_sync(struct mount *mp, int waitfor)
1613 {
1614         struct vnode *vp, *mvp;
1615         struct thread *td;
1616         int error, allerror = 0;
1617
1618         td = curthread;
1619
1620         MNT_ILOCK(mp);
1621         /*
1622          * If a forced dismount is in progress, return from here so that
1623          * the umount(2) syscall doesn't get stuck in VFS_SYNC() before
1624          * calling VFS_UNMOUNT().
1625          */
1626         if ((mp->mnt_kern_flag & MNTK_UNMOUNTF) != 0) {
1627                 MNT_IUNLOCK(mp);
1628                 return (EBADF);
1629         }
1630         MNT_IUNLOCK(mp);
1631
1632         /*
1633          * Force stale buffer cache information to be flushed.
1634          */
1635 loop:
1636         MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
1637                 /* XXX Racy bv_cnt check. */
1638                 if (NFSVOPISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
1639                     waitfor == MNT_LAZY) {
1640                         VI_UNLOCK(vp);
1641                         continue;
1642                 }
1643                 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
1644                         MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
1645                         goto loop;
1646                 }
1647                 error = VOP_FSYNC(vp, waitfor, td);
1648                 if (error)
1649                         allerror = error;
1650                 NFSVOPUNLOCK(vp, 0);
1651                 vrele(vp);
1652         }
1653         return (allerror);
1654 }
1655
1656 static int
1657 nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
1658 {
1659         struct nfsmount *nmp = VFSTONFS(mp);
1660         struct vfsquery vq;
1661         int error;
1662
1663         bzero(&vq, sizeof(vq));
1664         switch (op) {
1665 #if 0
1666         case VFS_CTL_NOLOCKS:
1667                 val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
1668                 if (req->oldptr != NULL) {
1669                         error = SYSCTL_OUT(req, &val, sizeof(val));
1670                         if (error)
1671                                 return (error);
1672                 }
1673                 if (req->newptr != NULL) {
1674                         error = SYSCTL_IN(req, &val, sizeof(val));
1675                         if (error)
1676                                 return (error);
1677                         if (val)
1678                                 nmp->nm_flag |= NFSMNT_NOLOCKS;
1679                         else
1680                                 nmp->nm_flag &= ~NFSMNT_NOLOCKS;
1681                 }
1682                 break;
1683 #endif
1684         case VFS_CTL_QUERY:
1685                 mtx_lock(&nmp->nm_mtx);
1686                 if (nmp->nm_state & NFSSTA_TIMEO)
1687                         vq.vq_flags |= VQ_NOTRESP;
1688                 mtx_unlock(&nmp->nm_mtx);
1689 #if 0
1690                 if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
1691                     (nmp->nm_state & NFSSTA_LOCKTIMEO))
1692                         vq.vq_flags |= VQ_NOTRESPLOCK;
1693 #endif
1694                 error = SYSCTL_OUT(req, &vq, sizeof(vq));
1695                 break;
1696         case VFS_CTL_TIMEO:
1697                 if (req->oldptr != NULL) {
1698                         error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
1699                             sizeof(nmp->nm_tprintf_initial_delay));
1700                         if (error)
1701                                 return (error);
1702                 }
1703                 if (req->newptr != NULL) {
1704                         error = vfs_suser(mp, req->td);
1705                         if (error)
1706                                 return (error);
1707                         error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
1708                             sizeof(nmp->nm_tprintf_initial_delay));
1709                         if (error)
1710                                 return (error);
1711                         if (nmp->nm_tprintf_initial_delay < 0)
1712                                 nmp->nm_tprintf_initial_delay = 0;
1713                 }
1714                 break;
1715         default:
1716                 return (ENOTSUP);
1717         }
1718         return (0);
1719 }
1720
1721 /*
1722  * Purge any RPCs in progress, so that they will all return errors.
1723  * This allows dounmount() to continue as far as VFS_UNMOUNT() for a
1724  * forced dismount.
1725  */
1726 static void
1727 nfs_purge(struct mount *mp)
1728 {
1729         struct nfsmount *nmp = VFSTONFS(mp);
1730
1731         newnfs_nmcancelreqs(nmp);
1732 }
1733
1734 /*
1735  * Extract the information needed by the nlm from the nfs vnode.
1736  */
1737 static void
1738 nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp,
1739     struct sockaddr_storage *sp, int *is_v3p, off_t *sizep,
1740     struct timeval *timeop)
1741 {
1742         struct nfsmount *nmp;
1743         struct nfsnode *np = VTONFS(vp);
1744
1745         nmp = VFSTONFS(vp->v_mount);
1746         if (fhlenp != NULL)
1747                 *fhlenp = (size_t)np->n_fhp->nfh_len;
1748         if (fhp != NULL)
1749                 bcopy(np->n_fhp->nfh_fh, fhp, np->n_fhp->nfh_len);
1750         if (sp != NULL)
1751                 bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp)));
1752         if (is_v3p != NULL)
1753                 *is_v3p = NFS_ISV3(vp);
1754         if (sizep != NULL)
1755                 *sizep = np->n_size;
1756         if (timeop != NULL) {
1757                 timeop->tv_sec = nmp->nm_timeo / NFS_HZ;
1758                 timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ);
1759         }
1760 }
1761
1762 /*
1763  * This function prints out an option name, based on the conditional
1764  * argument.
1765  */
1766 static __inline void nfscl_printopt(struct nfsmount *nmp, int testval,
1767     char *opt, char **buf, size_t *blen)
1768 {
1769         int len;
1770
1771         if (testval != 0 && *blen > strlen(opt)) {
1772                 len = snprintf(*buf, *blen, "%s", opt);
1773                 if (len != strlen(opt))
1774                         printf("EEK!!\n");
1775                 *buf += len;
1776                 *blen -= len;
1777         }
1778 }
1779
1780 /*
1781  * This function printf out an options integer value.
1782  */
1783 static __inline void nfscl_printoptval(struct nfsmount *nmp, int optval,
1784     char *opt, char **buf, size_t *blen)
1785 {
1786         int len;
1787
1788         if (*blen > strlen(opt) + 1) {
1789                 /* Could result in truncated output string. */
1790                 len = snprintf(*buf, *blen, "%s=%d", opt, optval);
1791                 if (len < *blen) {
1792                         *buf += len;
1793                         *blen -= len;
1794                 }
1795         }
1796 }
1797
1798 /*
1799  * Load the option flags and values into the buffer.
1800  */
1801 void nfscl_retopts(struct nfsmount *nmp, char *buffer, size_t buflen)
1802 {
1803         char *buf;
1804         size_t blen;
1805
1806         buf = buffer;
1807         blen = buflen;
1808         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV4) != 0, "nfsv4", &buf,
1809             &blen);
1810         if ((nmp->nm_flag & NFSMNT_NFSV4) != 0) {
1811                 nfscl_printoptval(nmp, nmp->nm_minorvers, ",minorversion", &buf,
1812                     &blen);
1813                 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_PNFS) != 0, ",pnfs",
1814                     &buf, &blen);
1815         }
1816         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV3) != 0, "nfsv3", &buf,
1817             &blen);
1818         nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0,
1819             "nfsv2", &buf, &blen);
1820         nfscl_printopt(nmp, nmp->nm_sotype == SOCK_STREAM, ",tcp", &buf, &blen);
1821         nfscl_printopt(nmp, nmp->nm_sotype != SOCK_STREAM, ",udp", &buf, &blen);
1822         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RESVPORT) != 0, ",resvport",
1823             &buf, &blen);
1824         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCONN) != 0, ",noconn",
1825             &buf, &blen);
1826         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) == 0, ",hard", &buf,
1827             &blen);
1828         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) != 0, ",soft", &buf,
1829             &blen);
1830         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_INT) != 0, ",intr", &buf,
1831             &blen);
1832         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) == 0, ",cto", &buf,
1833             &blen);
1834         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) != 0, ",nocto", &buf,
1835             &blen);
1836         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NONCONTIGWR) != 0,
1837             ",noncontigwr", &buf, &blen);
1838         nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
1839             0, ",lockd", &buf, &blen);
1840         nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
1841             NFSMNT_NOLOCKD, ",nolockd", &buf, &blen);
1842         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RDIRPLUS) != 0, ",rdirplus",
1843             &buf, &blen);
1844         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_KERB) == 0, ",sec=sys",
1845             &buf, &blen);
1846         nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
1847             NFSMNT_PRIVACY)) == NFSMNT_KERB, ",sec=krb5", &buf, &blen);
1848         nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
1849             NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_INTEGRITY), ",sec=krb5i",
1850             &buf, &blen);
1851         nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
1852             NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_PRIVACY), ",sec=krb5p",
1853             &buf, &blen);
1854         nfscl_printoptval(nmp, nmp->nm_acdirmin, ",acdirmin", &buf, &blen);
1855         nfscl_printoptval(nmp, nmp->nm_acdirmax, ",acdirmax", &buf, &blen);
1856         nfscl_printoptval(nmp, nmp->nm_acregmin, ",acregmin", &buf, &blen);
1857         nfscl_printoptval(nmp, nmp->nm_acregmax, ",acregmax", &buf, &blen);
1858         nfscl_printoptval(nmp, nmp->nm_nametimeo, ",nametimeo", &buf, &blen);
1859         nfscl_printoptval(nmp, nmp->nm_negnametimeo, ",negnametimeo", &buf,
1860             &blen);
1861         nfscl_printoptval(nmp, nmp->nm_rsize, ",rsize", &buf, &blen);
1862         nfscl_printoptval(nmp, nmp->nm_wsize, ",wsize", &buf, &blen);
1863         nfscl_printoptval(nmp, nmp->nm_readdirsize, ",readdirsize", &buf,
1864             &blen);
1865         nfscl_printoptval(nmp, nmp->nm_readahead, ",readahead", &buf, &blen);
1866         nfscl_printoptval(nmp, nmp->nm_wcommitsize, ",wcommitsize", &buf,
1867             &blen);
1868         nfscl_printoptval(nmp, nmp->nm_timeo, ",timeout", &buf, &blen);
1869         nfscl_printoptval(nmp, nmp->nm_retry, ",retrans", &buf, &blen);
1870 }
1871