This commit represents a major revamping of the clock interrupt and timebase
[dragonfly.git] / sys / vfs / nfs / 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  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by the University of
19  *      California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  *      @(#)nfs_vfsops.c        8.12 (Berkeley) 5/20/95
37  * $FreeBSD: src/sys/nfs/nfs_vfsops.c,v 1.91.2.7 2003/01/27 20:04:08 dillon Exp $
38  * $DragonFly: src/sys/vfs/nfs/nfs_vfsops.c,v 1.11 2004/01/30 06:18:28 dillon Exp $
39  */
40
41 #include "opt_bootp.h"
42
43 #include <sys/param.h>
44 #include <sys/sockio.h>
45 #include <sys/proc.h>
46 #include <sys/vnode.h>
47 #include <sys/kernel.h>
48 #include <sys/sysctl.h>
49 #include <sys/malloc.h>
50 #include <sys/mount.h>
51 #include <sys/mbuf.h>
52 #include <sys/socket.h>
53 #include <sys/socketvar.h>
54 #include <sys/systm.h>
55
56 #include <vm/vm.h>
57 #include <vm/vm_extern.h>
58 #include <vm/vm_zone.h>
59
60 #include <net/if.h>
61 #include <net/route.h>
62 #include <netinet/in.h>
63
64 #include "rpcv2.h"
65 #include "nfsproto.h"
66 #include "nfs.h"
67 #include "nfsmount.h"
68 #include "nfsnode.h"
69 #include "xdr_subs.h"
70 #include "nfsm_subs.h"
71 #include "nfsdiskless.h"
72 #include "nqnfs.h"
73
74 extern int      nfs_mountroot (struct mount *mp);
75
76 extern int      nfs_ticks;
77
78 MALLOC_DEFINE(M_NFSREQ, "NFS req", "NFS request header");
79 MALLOC_DEFINE(M_NFSBIGFH, "NFSV3 bigfh", "NFS version 3 file handle");
80 MALLOC_DEFINE(M_NFSD, "NFS daemon", "Nfs server daemon structure");
81 MALLOC_DEFINE(M_NFSDIROFF, "NFSV3 diroff", "NFS directory offset data");
82 MALLOC_DEFINE(M_NFSRVDESC, "NFSV3 srvdesc", "NFS server socket descriptor");
83 MALLOC_DEFINE(M_NFSUID, "NFS uid", "Nfs uid mapping structure");
84 MALLOC_DEFINE(M_NQLEASE, "NQNFS Lease", "Nqnfs lease");
85 MALLOC_DEFINE(M_NFSHASH, "NFS hash", "NFS hash tables");
86
87 vm_zone_t nfsmount_zone;
88
89 struct nfsstats nfsstats;
90 SYSCTL_NODE(_vfs, OID_AUTO, nfs, CTLFLAG_RW, 0, "NFS filesystem");
91 SYSCTL_STRUCT(_vfs_nfs, NFS_NFSSTATS, nfsstats, CTLFLAG_RD,
92         &nfsstats, nfsstats, "");
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 #ifdef NFS_DEBUG
97 int nfs_debug;
98 SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0, "");
99 #endif
100
101 static int      nfs_iosize (struct nfsmount *nmp);
102 static void     nfs_decode_args (struct nfsmount *nmp,
103                         struct nfs_args *argp);
104 static int      mountnfs (struct nfs_args *,struct mount *,
105                         struct sockaddr *,char *,char *,struct vnode **);
106 static int      nfs_mount ( struct mount *mp, char *path, caddr_t data,
107                         struct nameidata *ndp, struct thread *td);
108 static int      nfs_unmount ( struct mount *mp, int mntflags,
109                         struct thread *td);
110 static int      nfs_root ( struct mount *mp, struct vnode **vpp);
111 static int      nfs_statfs ( struct mount *mp, struct statfs *sbp,
112                         struct thread *td);
113 static int      nfs_sync ( struct mount *mp, int waitfor,
114                         struct thread *td);
115
116 /*
117  * nfs vfs operations.
118  */
119 static struct vfsops nfs_vfsops = {
120         nfs_mount,
121         vfs_stdstart,
122         nfs_unmount,
123         nfs_root,
124         vfs_stdquotactl,
125         nfs_statfs,
126         nfs_sync,
127         vfs_stdvget,
128         vfs_stdfhtovp,          /* shouldn't happen */
129         vfs_stdcheckexp,
130         vfs_stdvptofh,          /* shouldn't happen */
131         nfs_init,
132         nfs_uninit,
133         vfs_stdextattrctl,
134 };
135 VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK);
136
137 /*
138  * This structure must be filled in by a primary bootstrap or bootstrap
139  * server for a diskless/dataless machine. It is initialized below just
140  * to ensure that it is allocated to initialized data (.data not .bss).
141  */
142 struct nfs_diskless nfs_diskless = { { { 0 } } };
143 struct nfsv3_diskless nfsv3_diskless = { { { 0 } } };
144 int nfs_diskless_valid = 0;
145
146 SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD, 
147         &nfs_diskless_valid, 0, "");
148
149 SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
150         nfsv3_diskless.root_hostnam, 0, "");
151
152 SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
153         &nfsv3_diskless.root_saddr, sizeof nfsv3_diskless.root_saddr,
154         "%Ssockaddr_in", "");
155
156 SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_swappath, CTLFLAG_RD,
157         nfsv3_diskless.swap_hostnam, 0, "");
158
159 SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_swapaddr, CTLFLAG_RD,
160         &nfsv3_diskless.swap_saddr, sizeof nfsv3_diskless.swap_saddr, 
161         "%Ssockaddr_in","");
162
163
164 void nfsargs_ntoh (struct nfs_args *);
165 static int nfs_mountdiskless (char *, char *, int,
166                                   struct sockaddr_in *, struct nfs_args *,
167                                   struct thread *, struct vnode **,
168                                   struct mount **);
169 static void nfs_convert_diskless (void);
170 static void nfs_convert_oargs (struct nfs_args *args,
171                                    struct onfs_args *oargs);
172
173 static int
174 nfs_iosize(nmp)
175         struct nfsmount* nmp;
176 {
177         int iosize;
178
179         /*
180          * Calculate the size used for io buffers.  Use the larger
181          * of the two sizes to minimise nfs requests but make sure
182          * that it is at least one VM page to avoid wasting buffer
183          * space.
184          */
185         iosize = max(nmp->nm_rsize, nmp->nm_wsize);
186         if (iosize < PAGE_SIZE) iosize = PAGE_SIZE;
187         return iosize;
188 }
189
190 static void
191 nfs_convert_oargs(args, oargs)
192         struct nfs_args *args;
193         struct onfs_args *oargs;
194 {
195         args->version = NFS_ARGSVERSION;
196         args->addr = oargs->addr;
197         args->addrlen = oargs->addrlen;
198         args->sotype = oargs->sotype;
199         args->proto = oargs->proto;
200         args->fh = oargs->fh;
201         args->fhsize = oargs->fhsize;
202         args->flags = oargs->flags;
203         args->wsize = oargs->wsize;
204         args->rsize = oargs->rsize;
205         args->readdirsize = oargs->readdirsize;
206         args->timeo = oargs->timeo;
207         args->retrans = oargs->retrans;
208         args->maxgrouplist = oargs->maxgrouplist;
209         args->readahead = oargs->readahead;
210         args->leaseterm = oargs->leaseterm;
211         args->deadthresh = oargs->deadthresh;
212         args->hostname = oargs->hostname;
213 }
214
215 static void
216 nfs_convert_diskless()
217 {
218         bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
219                 sizeof(struct ifaliasreq));
220         bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
221                 sizeof(struct sockaddr_in));
222         nfs_convert_oargs(&nfsv3_diskless.swap_args,&nfs_diskless.swap_args);
223         nfsv3_diskless.swap_fhsize = NFSX_V2FH;
224         bcopy(nfs_diskless.swap_fh,nfsv3_diskless.swap_fh,NFSX_V2FH);
225         bcopy(&nfs_diskless.swap_saddr,&nfsv3_diskless.swap_saddr,
226                 sizeof(struct sockaddr_in));
227         bcopy(nfs_diskless.swap_hostnam,nfsv3_diskless.swap_hostnam, MNAMELEN);
228         nfsv3_diskless.swap_nblks = nfs_diskless.swap_nblks;
229         bcopy(&nfs_diskless.swap_ucred, &nfsv3_diskless.swap_ucred,
230                 sizeof(struct ucred));
231         nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
232         nfsv3_diskless.root_fhsize = NFSX_V2FH;
233         bcopy(nfs_diskless.root_fh,nfsv3_diskless.root_fh,NFSX_V2FH);
234         bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
235                 sizeof(struct sockaddr_in));
236         bcopy(nfs_diskless.root_hostnam,nfsv3_diskless.root_hostnam, MNAMELEN);
237         nfsv3_diskless.root_time = nfs_diskless.root_time;
238         bcopy(nfs_diskless.my_hostnam,nfsv3_diskless.my_hostnam,
239                 MAXHOSTNAMELEN);
240         nfs_diskless_valid = 3;
241 }
242
243 /*
244  * nfs statfs call
245  */
246 int
247 nfs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td)
248 {
249         struct vnode *vp;
250         struct nfs_statfs *sfp;
251         caddr_t cp;
252         u_int32_t *tl;
253         int32_t t1, t2;
254         caddr_t bpos, dpos, cp2;
255         struct nfsmount *nmp = VFSTONFS(mp);
256         int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr;
257         struct mbuf *mreq, *mrep, *md, *mb, *mb2;
258         struct ucred *cred;
259         struct nfsnode *np;
260         u_quad_t tquad;
261
262 #ifndef nolint
263         sfp = (struct nfs_statfs *)0;
264 #endif
265         error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
266         if (error)
267                 return (error);
268         vp = NFSTOV(np);
269         cred = crget();
270         cred->cr_ngroups = 1;
271         if (v3 && (nmp->nm_state & NFSSTA_GOTFSINFO) == 0)
272                 (void)nfs_fsinfo(nmp, vp, td);
273         nfsstats.rpccnt[NFSPROC_FSSTAT]++;
274         nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3));
275         nfsm_fhtom(vp, v3);
276         nfsm_request(vp, NFSPROC_FSSTAT, td, cred);
277         if (v3)
278                 nfsm_postop_attr(vp, retattr);
279         if (error) {
280                 if (mrep != NULL)
281                         m_freem(mrep);
282                 goto nfsmout;
283         }
284         nfsm_dissect(sfp, struct nfs_statfs *, NFSX_STATFS(v3));
285         sbp->f_flags = nmp->nm_flag;
286         sbp->f_iosize = nfs_iosize(nmp);
287         if (v3) {
288                 sbp->f_bsize = NFS_FABLKSIZE;
289                 tquad = fxdr_hyper(&sfp->sf_tbytes);
290                 sbp->f_blocks = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
291                 tquad = fxdr_hyper(&sfp->sf_fbytes);
292                 sbp->f_bfree = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
293                 tquad = fxdr_hyper(&sfp->sf_abytes);
294                 sbp->f_bavail = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
295                 sbp->f_files = (fxdr_unsigned(int32_t,
296                     sfp->sf_tfiles.nfsuquad[1]) & 0x7fffffff);
297                 sbp->f_ffree = (fxdr_unsigned(int32_t,
298                     sfp->sf_ffiles.nfsuquad[1]) & 0x7fffffff);
299         } else {
300                 sbp->f_bsize = fxdr_unsigned(int32_t, sfp->sf_bsize);
301                 sbp->f_blocks = fxdr_unsigned(int32_t, sfp->sf_blocks);
302                 sbp->f_bfree = fxdr_unsigned(int32_t, sfp->sf_bfree);
303                 sbp->f_bavail = fxdr_unsigned(int32_t, sfp->sf_bavail);
304                 sbp->f_files = 0;
305                 sbp->f_ffree = 0;
306         }
307         if (sbp != &mp->mnt_stat) {
308                 sbp->f_type = mp->mnt_vfc->vfc_typenum;
309                 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
310                 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
311         }
312         m_freem(mrep);
313 nfsmout:
314         vput(vp);
315         crfree(cred);
316         return (error);
317 }
318
319 /*
320  * nfs version 3 fsinfo rpc call
321  */
322 int
323 nfs_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct thread *td)
324 {
325         struct nfsv3_fsinfo *fsp;
326         caddr_t cp;
327         int32_t t1, t2;
328         u_int32_t *tl, pref, max;
329         caddr_t bpos, dpos, cp2;
330         int error = 0, retattr;
331         struct mbuf *mreq, *mrep, *md, *mb, *mb2;
332         u_int64_t maxfsize;
333
334         nfsstats.rpccnt[NFSPROC_FSINFO]++;
335         nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1));
336         nfsm_fhtom(vp, 1);
337         nfsm_request(vp, NFSPROC_FSINFO, td, nfs_vpcred(vp, ND_READ));
338         nfsm_postop_attr(vp, retattr);
339         if (!error) {
340                 nfsm_dissect(fsp, struct nfsv3_fsinfo *, NFSX_V3FSINFO);
341                 pref = fxdr_unsigned(u_int32_t, fsp->fs_wtpref);
342                 if (pref < nmp->nm_wsize && pref >= NFS_FABLKSIZE)
343                         nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) &
344                                 ~(NFS_FABLKSIZE - 1);
345                 max = fxdr_unsigned(u_int32_t, fsp->fs_wtmax);
346                 if (max < nmp->nm_wsize && max > 0) {
347                         nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1);
348                         if (nmp->nm_wsize == 0)
349                                 nmp->nm_wsize = max;
350                 }
351                 pref = fxdr_unsigned(u_int32_t, fsp->fs_rtpref);
352                 if (pref < nmp->nm_rsize && pref >= NFS_FABLKSIZE)
353                         nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) &
354                                 ~(NFS_FABLKSIZE - 1);
355                 max = fxdr_unsigned(u_int32_t, fsp->fs_rtmax);
356                 if (max < nmp->nm_rsize && max > 0) {
357                         nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1);
358                         if (nmp->nm_rsize == 0)
359                                 nmp->nm_rsize = max;
360                 }
361                 pref = fxdr_unsigned(u_int32_t, fsp->fs_dtpref);
362                 if (pref < nmp->nm_readdirsize && pref >= NFS_DIRBLKSIZ)
363                         nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ - 1) &
364                                 ~(NFS_DIRBLKSIZ - 1);
365                 if (max < nmp->nm_readdirsize && max > 0) {
366                         nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1);
367                         if (nmp->nm_readdirsize == 0)
368                                 nmp->nm_readdirsize = max;
369                 }
370                 maxfsize = fxdr_hyper(&fsp->fs_maxfilesize);
371                 if (maxfsize > 0 && maxfsize < nmp->nm_maxfilesize)
372                         nmp->nm_maxfilesize = maxfsize;
373                 nmp->nm_state |= NFSSTA_GOTFSINFO;
374         }
375         m_freem(mrep);
376 nfsmout:
377         return (error);
378 }
379
380 /*
381  * Mount a remote root fs via. nfs. This depends on the info in the
382  * nfs_diskless structure that has been filled in properly by some primary
383  * bootstrap.
384  * It goes something like this:
385  * - do enough of "ifconfig" by calling ifioctl() so that the system
386  *   can talk to the server
387  * - If nfs_diskless.mygateway is filled in, use that address as
388  *   a default gateway.
389  * - build the rootfs mount point and call mountnfs() to do the rest.
390  */
391 int
392 nfs_mountroot(mp)
393         struct mount *mp;
394 {
395         struct mount  *swap_mp;
396         struct nfsv3_diskless *nd = &nfsv3_diskless;
397         struct socket *so;
398         struct vnode *vp;
399         struct thread *td = curthread;          /* XXX */
400         int error, i;
401         u_long l;
402         char buf[128];
403
404 #if defined(BOOTP_NFSROOT) && defined(BOOTP)
405         bootpc_init();          /* use bootp to get nfs_diskless filled in */
406 #endif
407
408         /*
409          * XXX time must be non-zero when we init the interface or else
410          * the arp code will wedge...
411          */
412         while (mycpu->gd_time_seconds == 0)
413                 tsleep(mycpu, 0, "arpkludge", 10);
414
415         if (nfs_diskless_valid==1) 
416           nfs_convert_diskless();
417
418         /*
419          * XXX splnet, so networks will receive...
420          */
421         splnet();
422
423 #ifdef notyet
424         /* Set up swap credentials. */
425         proc0.p_ucred->cr_uid = ntohl(nd->swap_ucred.cr_uid);
426         proc0.p_ucred->cr_gid = ntohl(nd->swap_ucred.cr_gid);
427         if ((proc0.p_ucred->cr_ngroups = ntohs(nd->swap_ucred.cr_ngroups)) >
428                 NGROUPS)
429                 proc0.p_ucred->cr_ngroups = NGROUPS;
430         for (i = 0; i < proc0.p_ucred->cr_ngroups; i++)
431             proc0.p_ucred->cr_groups[i] = ntohl(nd->swap_ucred.cr_groups[i]);
432 #endif
433
434         /*
435          * Do enough of ifconfig(8) so that the critical net interface can
436          * talk to the server.
437          */
438         error = socreate(nd->myif.ifra_addr.sa_family, &so, SOCK_DGRAM, 0, td);
439         if (error)
440                 panic("nfs_mountroot: socreate(%04x): %d",
441                         nd->myif.ifra_addr.sa_family, error);
442
443 #if 0 /* XXX Bad idea */
444         /*
445          * We might not have been told the right interface, so we pass
446          * over the first ten interfaces of the same kind, until we get
447          * one of them configured.
448          */
449
450         for (i = strlen(nd->myif.ifra_name) - 1;
451                 nd->myif.ifra_name[i] >= '0' &&
452                 nd->myif.ifra_name[i] <= '9';
453                 nd->myif.ifra_name[i] ++) {
454                 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
455                 if(!error)
456                         break;
457         }
458 #endif
459         error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
460         if (error)
461                 panic("nfs_mountroot: SIOCAIFADDR: %d", error);
462         soclose(so);
463
464         /*
465          * If the gateway field is filled in, set it as the default route.
466          */
467         if (nd->mygateway.sin_len != 0) {
468                 struct sockaddr_in mask, sin;
469
470                 bzero((caddr_t)&mask, sizeof(mask));
471                 sin = mask;
472                 sin.sin_family = AF_INET;
473                 sin.sin_len = sizeof(sin);
474                 error = rtrequest(RTM_ADD, (struct sockaddr *)&sin,
475                     (struct sockaddr *)&nd->mygateway,
476                     (struct sockaddr *)&mask,
477                     RTF_UP | RTF_GATEWAY, (struct rtentry **)0);
478                 if (error)
479                         panic("nfs_mountroot: RTM_ADD: %d", error);
480         }
481
482         /*
483          * Create the rootfs mount point.
484          */
485         nd->root_args.fh = nd->root_fh;
486         nd->root_args.fhsize = nd->root_fhsize;
487         l = ntohl(nd->root_saddr.sin_addr.s_addr);
488         snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
489                 (l >> 24) & 0xff, (l >> 16) & 0xff,
490                 (l >>  8) & 0xff, (l >>  0) & 0xff,nd->root_hostnam);
491         printf("NFS ROOT: %s\n",buf);
492         if ((error = nfs_mountdiskless(buf, "/", MNT_RDONLY,
493             &nd->root_saddr, &nd->root_args, td, &vp, &mp)) != 0) {
494                 if (swap_mp) {
495                         mp->mnt_vfc->vfc_refcount--;
496                         free(swap_mp, M_MOUNT);
497                 }
498                 return (error);
499         }
500
501         swap_mp = NULL;
502         if (nd->swap_nblks) {
503
504                 /* Convert to DEV_BSIZE instead of Kilobyte */
505                 nd->swap_nblks *= 2;
506
507                 /*
508                  * Create a fake mount point just for the swap vnode so that the
509                  * swap file can be on a different server from the rootfs.
510                  */
511                 nd->swap_args.fh = nd->swap_fh;
512                 nd->swap_args.fhsize = nd->swap_fhsize;
513                 l = ntohl(nd->swap_saddr.sin_addr.s_addr);
514                 snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
515                         (l >> 24) & 0xff, (l >> 16) & 0xff,
516                         (l >>  8) & 0xff, (l >>  0) & 0xff,nd->swap_hostnam);
517                 printf("NFS SWAP: %s\n",buf);
518                 if ((error = nfs_mountdiskless(buf, "/swap", 0,
519                     &nd->swap_saddr, &nd->swap_args, td, &vp, &swap_mp)) != 0)
520                         return (error);
521                 vfs_unbusy(swap_mp, td);
522
523                 VTONFS(vp)->n_size = VTONFS(vp)->n_vattr.va_size = 
524                                 nd->swap_nblks * DEV_BSIZE ;
525                 
526                 /*
527                  * Since the swap file is not the root dir of a file system,
528                  * hack it to a regular file.
529                  */
530                 vp->v_type = VREG;
531                 vp->v_flag = 0;
532                 VREF(vp);
533                 swaponvp(td, vp, NODEV, nd->swap_nblks);
534         }
535
536         mp->mnt_flag |= MNT_ROOTFS;
537         mp->mnt_vnodecovered = NULLVP;
538         rootvp = vp;
539         vfs_unbusy(mp, td);
540
541         /*
542          * This is not really an nfs issue, but it is much easier to
543          * set hostname here and then let the "/etc/rc.xxx" files
544          * mount the right /var based upon its preset value.
545          */
546         bcopy(nd->my_hostnam, hostname, MAXHOSTNAMELEN);
547         hostname[MAXHOSTNAMELEN - 1] = '\0';
548         for (i = 0; i < MAXHOSTNAMELEN; i++)
549                 if (hostname[i] == '\0')
550                         break;
551         inittodr(ntohl(nd->root_time));
552         return (0);
553 }
554
555 /*
556  * Internal version of mount system call for diskless setup.
557  */
558 static int
559 nfs_mountdiskless(char *path, char *which, int mountflag,
560         struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
561         struct vnode **vpp, struct mount **mpp)
562 {
563         struct mount *mp;
564         struct sockaddr *nam;
565         int error;
566         int didalloc = 0;
567
568         mp = *mpp;
569
570         if (mp == NULL) {
571                 if ((error = vfs_rootmountalloc("nfs", path, &mp)) != 0) {
572                         printf("nfs_mountroot: NFS not configured");
573                         return (error);
574                 }
575                 didalloc = 1;
576         }
577
578         mp->mnt_kern_flag = 0;
579         mp->mnt_flag = mountflag;
580         nam = dup_sockaddr((struct sockaddr *)sin, 1);
581         if ((error = mountnfs(args, mp, nam, which, path, vpp)) != 0) {
582                 printf("nfs_mountroot: mount %s on %s: %d", path, which, error);
583                 mp->mnt_vfc->vfc_refcount--;
584                 vfs_unbusy(mp, td);
585                 if (didalloc)
586                         free(mp, M_MOUNT);
587                 FREE(nam, M_SONAME);
588                 return (error);
589         }
590         (void) copystr(which, mp->mnt_stat.f_mntonname, MNAMELEN - 1, 0);
591         *mpp = mp;
592         return (0);
593 }
594
595 static void
596 nfs_decode_args(nmp, argp)
597         struct nfsmount *nmp;
598         struct nfs_args *argp;
599 {
600         int s;
601         int adjsock;
602         int maxio;
603
604         s = splnet();
605         /*
606          * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
607          * no sense in that context.
608          */
609         if (argp->sotype == SOCK_STREAM)
610                 nmp->nm_flag &= ~NFSMNT_NOCONN;
611
612         /* Also clear RDIRPLUS if not NFSv3, it crashes some servers */
613         if ((argp->flags & NFSMNT_NFSV3) == 0)
614                 nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
615
616         /* Re-bind if rsrvd port requested and wasn't on one */
617         adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
618                   && (argp->flags & NFSMNT_RESVPORT);
619         /* Also re-bind if we're switching to/from a connected UDP socket */
620         adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
621                     (argp->flags & NFSMNT_NOCONN));
622
623         /* Update flags atomically.  Don't change the lock bits. */
624         nmp->nm_flag = argp->flags | nmp->nm_flag;
625         splx(s);
626
627         if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
628                 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
629                 if (nmp->nm_timeo < NFS_MINTIMEO)
630                         nmp->nm_timeo = NFS_MINTIMEO;
631                 else if (nmp->nm_timeo > NFS_MAXTIMEO)
632                         nmp->nm_timeo = NFS_MAXTIMEO;
633         }
634
635         if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
636                 nmp->nm_retry = argp->retrans;
637                 if (nmp->nm_retry > NFS_MAXREXMIT)
638                         nmp->nm_retry = NFS_MAXREXMIT;
639         }
640
641         if (argp->flags & NFSMNT_NFSV3) {
642                 if (argp->sotype == SOCK_DGRAM)
643                         maxio = NFS_MAXDGRAMDATA;
644                 else
645                         maxio = NFS_MAXDATA;
646         } else
647                 maxio = NFS_V2MAXDATA;
648
649         if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
650                 nmp->nm_wsize = argp->wsize;
651                 /* Round down to multiple of blocksize */
652                 nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
653                 if (nmp->nm_wsize <= 0)
654                         nmp->nm_wsize = NFS_FABLKSIZE;
655         }
656         if (nmp->nm_wsize > maxio)
657                 nmp->nm_wsize = maxio;
658         if (nmp->nm_wsize > MAXBSIZE)
659                 nmp->nm_wsize = MAXBSIZE;
660
661         if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
662                 nmp->nm_rsize = argp->rsize;
663                 /* Round down to multiple of blocksize */
664                 nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
665                 if (nmp->nm_rsize <= 0)
666                         nmp->nm_rsize = NFS_FABLKSIZE;
667         }
668         if (nmp->nm_rsize > maxio)
669                 nmp->nm_rsize = maxio;
670         if (nmp->nm_rsize > MAXBSIZE)
671                 nmp->nm_rsize = MAXBSIZE;
672
673         if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
674                 nmp->nm_readdirsize = argp->readdirsize;
675         }
676         if (nmp->nm_readdirsize > maxio)
677                 nmp->nm_readdirsize = maxio;
678         if (nmp->nm_readdirsize > nmp->nm_rsize)
679                 nmp->nm_readdirsize = nmp->nm_rsize;
680
681         if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
682                 nmp->nm_acregmin = argp->acregmin;
683         else
684                 nmp->nm_acregmin = NFS_MINATTRTIMO;
685         if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
686                 nmp->nm_acregmax = argp->acregmax;
687         else
688                 nmp->nm_acregmax = NFS_MAXATTRTIMO;
689         if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
690                 nmp->nm_acdirmin = argp->acdirmin;
691         else
692                 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
693         if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
694                 nmp->nm_acdirmax = argp->acdirmax;
695         else
696                 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
697         if (nmp->nm_acdirmin > nmp->nm_acdirmax)
698                 nmp->nm_acdirmin = nmp->nm_acdirmax;
699         if (nmp->nm_acregmin > nmp->nm_acregmax)
700                 nmp->nm_acregmin = nmp->nm_acregmax;
701
702         if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0) {
703                 if (argp->maxgrouplist <= NFS_MAXGRPS)
704                         nmp->nm_numgrps = argp->maxgrouplist;
705                 else
706                         nmp->nm_numgrps = NFS_MAXGRPS;
707         }
708         if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
709                 if (argp->readahead <= NFS_MAXRAHEAD)
710                         nmp->nm_readahead = argp->readahead;
711                 else
712                         nmp->nm_readahead = NFS_MAXRAHEAD;
713         }
714         if ((argp->flags & NFSMNT_LEASETERM) && argp->leaseterm >= 2) {
715                 if (argp->leaseterm <= NQ_MAXLEASE)
716                         nmp->nm_leaseterm = argp->leaseterm;
717                 else
718                         nmp->nm_leaseterm = NQ_MAXLEASE;
719         }
720         if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 1) {
721                 if (argp->deadthresh <= NQ_NEVERDEAD)
722                         nmp->nm_deadthresh = argp->deadthresh;
723                 else
724                         nmp->nm_deadthresh = NQ_NEVERDEAD;
725         }
726
727         adjsock |= ((nmp->nm_sotype != argp->sotype) ||
728                     (nmp->nm_soproto != argp->proto));
729         nmp->nm_sotype = argp->sotype;
730         nmp->nm_soproto = argp->proto;
731
732         if (nmp->nm_so && adjsock) {
733                 nfs_safedisconnect(nmp);
734                 if (nmp->nm_sotype == SOCK_DGRAM)
735                         while (nfs_connect(nmp, (struct nfsreq *)0)) {
736                                 printf("nfs_args: retrying connect\n");
737                                 (void) tsleep((caddr_t)&lbolt, 0, "nfscon", 0);
738                         }
739         }
740 }
741
742 /*
743  * VFS Operations.
744  *
745  * mount system call
746  * It seems a bit dumb to copyinstr() the host and path here and then
747  * bcopy() them in mountnfs(), but I wanted to detect errors before
748  * doing the sockargs() call because sockargs() allocates an mbuf and
749  * an error after that means that I have to release the mbuf.
750  */
751 /* ARGSUSED */
752 static int
753 nfs_mount(struct mount *mp, char *path, caddr_t data,
754         struct nameidata *ndp, struct thread *td)
755 {
756         int error;
757         struct nfs_args args;
758         struct sockaddr *nam;
759         struct vnode *vp;
760         char pth[MNAMELEN], hst[MNAMELEN];
761         size_t len;
762         u_char nfh[NFSX_V3FHMAX];
763
764         if (path == NULL) {
765                 nfs_mountroot(mp);
766                 return (0);
767         }
768         error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args));
769         if (error)
770                 return (error);
771         if (args.version != NFS_ARGSVERSION) {
772 #ifdef COMPAT_PRELITE2
773                 /*
774                  * If the argument version is unknown, then assume the
775                  * caller is a pre-lite2 4.4BSD client and convert its
776                  * arguments.
777                  */
778                 struct onfs_args oargs;
779                 error = copyin(data, (caddr_t)&oargs, sizeof (struct onfs_args));
780                 if (error)
781                         return (error);
782                 nfs_convert_oargs(&args,&oargs);
783 #else /* !COMPAT_PRELITE2 */
784                 return (EPROGMISMATCH);
785 #endif /* COMPAT_PRELITE2 */
786         }
787         if (mp->mnt_flag & MNT_UPDATE) {
788                 struct nfsmount *nmp = VFSTONFS(mp);
789
790                 if (nmp == NULL)
791                         return (EIO);
792                 /*
793                  * When doing an update, we can't change from or to
794                  * v3 and/or nqnfs, or change cookie translation
795                  */
796                 args.flags = (args.flags &
797                     ~(NFSMNT_NFSV3|NFSMNT_NQNFS /*|NFSMNT_XLATECOOKIE*/)) |
798                     (nmp->nm_flag &
799                         (NFSMNT_NFSV3|NFSMNT_NQNFS /*|NFSMNT_XLATECOOKIE*/));
800                 nfs_decode_args(nmp, &args);
801                 return (0);
802         }
803
804         /*
805          * Make the nfs_ip_paranoia sysctl serve as the default connection
806          * or no-connection mode for those protocols that support 
807          * no-connection mode (the flag will be cleared later for protocols
808          * that do not support no-connection mode).  This will allow a client
809          * to receive replies from a different IP then the request was
810          * sent to.  Note: default value for nfs_ip_paranoia is 1 (paranoid),
811          * not 0.
812          */
813         if (nfs_ip_paranoia == 0)
814                 args.flags |= NFSMNT_NOCONN;
815         if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX)
816                 return (EINVAL);
817         error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize);
818         if (error)
819                 return (error);
820         error = copyinstr(path, pth, MNAMELEN-1, &len);
821         if (error)
822                 return (error);
823         bzero(&pth[len], MNAMELEN - len);
824         error = copyinstr(args.hostname, hst, MNAMELEN-1, &len);
825         if (error)
826                 return (error);
827         bzero(&hst[len], MNAMELEN - len);
828         /* sockargs() call must be after above copyin() calls */
829         error = getsockaddr(&nam, (caddr_t)args.addr, args.addrlen);
830         if (error)
831                 return (error);
832         args.fh = nfh;
833         error = mountnfs(&args, mp, nam, pth, hst, &vp);
834         return (error);
835 }
836
837 /*
838  * Common code for mount and mountroot
839  */
840 static int
841 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
842         char *pth, char *hst, struct vnode **vpp)
843 {
844         struct nfsmount *nmp;
845         struct nfsnode *np;
846         int error;
847         struct vattr attrs;
848
849         if (mp->mnt_flag & MNT_UPDATE) {
850                 nmp = VFSTONFS(mp);
851                 /* update paths, file handles, etc, here        XXX */
852                 FREE(nam, M_SONAME);
853                 return (0);
854         } else {
855                 nmp = zalloc(nfsmount_zone);
856                 bzero((caddr_t)nmp, sizeof (struct nfsmount));
857                 TAILQ_INIT(&nmp->nm_uidlruhead);
858                 TAILQ_INIT(&nmp->nm_bufq);
859                 mp->mnt_data = (qaddr_t)nmp;
860         }
861         vfs_getnewfsid(mp);
862         nmp->nm_mountp = mp;
863         if (argp->flags & NFSMNT_NQNFS)
864                 /*
865                  * We have to set mnt_maxsymlink to a non-zero value so
866                  * that COMPAT_43 routines will know that we are setting
867                  * the d_type field in directories (and can zero it for
868                  * unsuspecting binaries).
869                  */
870                 mp->mnt_maxsymlinklen = 1;
871
872         /*
873          * V2 can only handle 32 bit filesizes.  A 4GB-1 limit may be too
874          * high, depending on whether we end up with negative offsets in
875          * the client or server somewhere.  2GB-1 may be safer.
876          *
877          * For V3, nfs_fsinfo will adjust this as necessary.  Assume maximum
878          * that we can handle until we find out otherwise.
879          * XXX Our "safe" limit on the client is what we can store in our
880          * buffer cache using signed(!) block numbers.
881          */
882         if ((argp->flags & NFSMNT_NFSV3) == 0)
883                 nmp->nm_maxfilesize = 0xffffffffLL;
884         else
885                 nmp->nm_maxfilesize = (u_int64_t)0x80000000 * DEV_BSIZE - 1;
886
887         nmp->nm_timeo = NFS_TIMEO;
888         nmp->nm_retry = NFS_RETRANS;
889         nmp->nm_wsize = NFS_WSIZE;
890         nmp->nm_rsize = NFS_RSIZE;
891         nmp->nm_readdirsize = NFS_READDIRSIZE;
892         nmp->nm_numgrps = NFS_MAXGRPS;
893         nmp->nm_readahead = NFS_DEFRAHEAD;
894         nmp->nm_leaseterm = NQ_DEFLEASE;
895         nmp->nm_deadthresh = NQ_DEADTHRESH;
896         CIRCLEQ_INIT(&nmp->nm_timerhead);
897         nmp->nm_inprog = NULLVP;
898         nmp->nm_fhsize = argp->fhsize;
899         bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
900         bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
901         bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN);
902         nmp->nm_nam = nam;
903         /* Set up the sockets and per-host congestion */
904         nmp->nm_sotype = argp->sotype;
905         nmp->nm_soproto = argp->proto;
906         nmp->nm_cred = crhold(proc0.p_ucred);
907
908         nfs_decode_args(nmp, argp);
909
910         /*
911          * For Connection based sockets (TCP,...) defer the connect until
912          * the first request, in case the server is not responding.
913          */
914         if (nmp->nm_sotype == SOCK_DGRAM &&
915                 (error = nfs_connect(nmp, (struct nfsreq *)0)))
916                 goto bad;
917
918         /*
919          * This is silly, but it has to be set so that vinifod() works.
920          * We do not want to do an nfs_statfs() here since we can get
921          * stuck on a dead server and we are holding a lock on the mount
922          * point.
923          */
924         mp->mnt_stat.f_iosize = nfs_iosize(nmp);
925         /*
926          * A reference count is needed on the nfsnode representing the
927          * remote root.  If this object is not persistent, then backward
928          * traversals of the mount point (i.e. "..") will not work if
929          * the nfsnode gets flushed out of the cache. Ufs does not have
930          * this problem, because one can identify root inodes by their
931          * number == ROOTINO (2).
932          */
933         error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
934         if (error)
935                 goto bad;
936         *vpp = NFSTOV(np);
937
938         /*
939          * Get file attributes for the mountpoint.  This has the side
940          * effect of filling in (*vpp)->v_type with the correct value.
941          */
942         VOP_GETATTR(*vpp, &attrs, curthread);
943
944         /*
945          * Lose the lock but keep the ref.
946          */
947         VOP_UNLOCK(*vpp, 0, curthread);
948
949         return (0);
950 bad:
951         nfs_disconnect(nmp);
952         nfs_free_mount(nmp);
953         FREE(nam, M_SONAME);
954         return (error);
955 }
956
957 /*
958  * unmount system call
959  */
960 static int
961 nfs_unmount(struct mount *mp, int mntflags, struct thread *td)
962 {
963         struct nfsmount *nmp;
964         int error, flags = 0;
965
966         if (mntflags & MNT_FORCE)
967                 flags |= FORCECLOSE;
968         nmp = VFSTONFS(mp);
969         /*
970          * Goes something like this..
971          * - Call vflush() to clear out vnodes for this file system
972          * - Close the socket
973          * - Free up the data structures
974          */
975         /* In the forced case, cancel any outstanding requests. */
976         if (flags & FORCECLOSE) {
977                 error = nfs_nmcancelreqs(nmp);
978                 if (error)
979                         return (error);
980         }
981         /*
982          * Must handshake with nqnfs_clientd() if it is active.
983          */
984         nmp->nm_state |= NFSSTA_DISMINPROG;
985         while (nmp->nm_inprog != NULLVP)
986                 (void) tsleep((caddr_t)&lbolt, 0, "nfsdism", 0);
987
988         /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
989         error = vflush(mp, 1, flags);
990         if (error) {
991                 nmp->nm_state &= ~NFSSTA_DISMINPROG;
992                 return (error);
993         }
994
995         /*
996          * We are now committed to the unmount.
997          * For NQNFS, let the server daemon free the nfsmount structure.
998          */
999         if (nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB))
1000                 nmp->nm_state |= NFSSTA_DISMNT;
1001
1002         nfs_disconnect(nmp);
1003         FREE(nmp->nm_nam, M_SONAME);
1004
1005         if ((nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB)) == 0)
1006                 nfs_free_mount(nmp);
1007         return (0);
1008 }
1009
1010 void
1011 nfs_free_mount(struct nfsmount *nmp)
1012 {
1013         if (nmp->nm_cred)  {
1014                 crfree(nmp->nm_cred);
1015                 nmp->nm_cred = NULL;
1016         }
1017         zfree(nfsmount_zone, nmp);
1018 }
1019
1020 /*
1021  * Return root of a filesystem
1022  */
1023 static int
1024 nfs_root(mp, vpp)
1025         struct mount *mp;
1026         struct vnode **vpp;
1027 {
1028         struct vnode *vp;
1029         struct nfsmount *nmp;
1030         struct nfsnode *np;
1031         int error;
1032
1033         nmp = VFSTONFS(mp);
1034         error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
1035         if (error)
1036                 return (error);
1037         vp = NFSTOV(np);
1038         if (vp->v_type == VNON)
1039             vp->v_type = VDIR;
1040         vp->v_flag = VROOT;
1041         *vpp = vp;
1042         return (0);
1043 }
1044
1045 extern int syncprt;
1046
1047 /*
1048  * Flush out the buffer cache
1049  */
1050 /* ARGSUSED */
1051 static int
1052 nfs_sync(struct mount *mp, int waitfor, struct thread *td)
1053 {
1054         struct vnode *vp;
1055         int error, allerror = 0;
1056
1057         /*
1058          * Force stale buffer cache information to be flushed.
1059          */
1060 loop:
1061         for (vp = TAILQ_FIRST(&mp->mnt_nvnodelist);
1062              vp != NULL;
1063              vp = TAILQ_NEXT(vp, v_nmntvnodes)) {
1064                 /*
1065                  * If the vnode that we are about to sync is no longer
1066                  * associated with this mount point, start over.
1067                  */
1068                 if (vp->v_mount != mp)
1069                         goto loop;
1070                 if (VOP_ISLOCKED(vp, NULL) || TAILQ_EMPTY(&vp->v_dirtyblkhd) ||
1071                     waitfor == MNT_LAZY)
1072                         continue;
1073                 if (vget(vp, LK_EXCLUSIVE, td))
1074                         goto loop;
1075                 error = VOP_FSYNC(vp, waitfor, td);
1076                 if (error)
1077                         allerror = error;
1078                 vput(vp);
1079         }
1080         return (allerror);
1081 }
1082