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