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