xref: /dragonfly/sys/vfs/nfs/nfs_vfsops.c (revision 984263bc)
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 
1098