vfs_export.c revision 7181
1/*
2 * Copyright (c) 1989, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 *    must display the following acknowledgement:
20 *	This product includes software developed by the University of
21 *	California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 *    may be used to endorse or promote products derived from this software
24 *    without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 *	@(#)vfs_subr.c	8.13 (Berkeley) 4/18/94
39 * $Id: vfs_subr.c,v 1.23 1995/03/16 18:12:49 bde Exp $
40 */
41
42/*
43 * External virtual filesystem routines
44 */
45
46#include <sys/param.h>
47#include <sys/systm.h>
48#include <sys/proc.h>
49#include <sys/mount.h>
50#include <sys/time.h>
51#include <sys/vnode.h>
52#include <sys/stat.h>
53#include <sys/namei.h>
54#include <sys/ucred.h>
55#include <sys/buf.h>
56#include <sys/errno.h>
57#include <sys/malloc.h>
58#include <sys/domain.h>
59#include <sys/mbuf.h>
60
61#include <vm/vm.h>
62#include <sys/sysctl.h>
63
64#include <miscfs/specfs/specdev.h>
65
66void insmntque __P((struct vnode *, struct mount *));
67
68enum vtype iftovt_tab[16] = {
69	VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,
70	VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VBAD,
71};
72int vttoif_tab[9] = {
73	0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK,
74	S_IFSOCK, S_IFIFO, S_IFMT,
75};
76
77/*
78 * Insq/Remq for the vnode usage lists.
79 */
80#define	bufinsvn(bp, dp)	LIST_INSERT_HEAD(dp, bp, b_vnbufs)
81#define	bufremvn(bp) {  \
82	LIST_REMOVE(bp, b_vnbufs); \
83	(bp)->b_vnbufs.le_next = NOLIST; \
84}
85
86TAILQ_HEAD(freelst, vnode) vnode_free_list;	/* vnode free list */
87u_long freevnodes	= 0;
88
89struct mntlist mountlist;	/* mounted filesystem list */
90
91int desiredvnodes;
92
93/*
94 * Initialize the vnode management data structures.
95 */
96void
97vntblinit()
98{
99	desiredvnodes = maxproc + vm_object_cache_max;
100
101	TAILQ_INIT(&vnode_free_list);
102	TAILQ_INIT(&mountlist);
103}
104
105/*
106 * Lock a filesystem.
107 * Used to prevent access to it while mounting and unmounting.
108 */
109int
110vfs_lock(mp)
111	register struct mount *mp;
112{
113
114	while (mp->mnt_flag & MNT_MLOCK) {
115		mp->mnt_flag |= MNT_MWAIT;
116		(void) tsleep((caddr_t) mp, PVFS, "vfslck", 0);
117	}
118	mp->mnt_flag |= MNT_MLOCK;
119	return (0);
120}
121
122/*
123 * Unlock a locked filesystem.
124 * Panic if filesystem is not locked.
125 */
126void
127vfs_unlock(mp)
128	register struct mount *mp;
129{
130
131	if ((mp->mnt_flag & MNT_MLOCK) == 0)
132		panic("vfs_unlock: not locked");
133	mp->mnt_flag &= ~MNT_MLOCK;
134	if (mp->mnt_flag & MNT_MWAIT) {
135		mp->mnt_flag &= ~MNT_MWAIT;
136		wakeup((caddr_t) mp);
137	}
138}
139
140/*
141 * Mark a mount point as busy.
142 * Used to synchronize access and to delay unmounting.
143 */
144int
145vfs_busy(mp)
146	register struct mount *mp;
147{
148
149	while (mp->mnt_flag & MNT_MPBUSY) {
150		mp->mnt_flag |= MNT_MPWANT;
151		(void) tsleep((caddr_t) &mp->mnt_flag, PVFS, "vfsbsy", 0);
152	}
153	if (mp->mnt_flag & MNT_UNMOUNT)
154		return (1);
155	mp->mnt_flag |= MNT_MPBUSY;
156	return (0);
157}
158
159/*
160 * Free a busy filesystem.
161 * Panic if filesystem is not busy.
162 */
163void
164vfs_unbusy(mp)
165	register struct mount *mp;
166{
167
168	if ((mp->mnt_flag & MNT_MPBUSY) == 0)
169		panic("vfs_unbusy: not busy");
170	mp->mnt_flag &= ~MNT_MPBUSY;
171	if (mp->mnt_flag & MNT_MPWANT) {
172		mp->mnt_flag &= ~MNT_MPWANT;
173		wakeup((caddr_t) &mp->mnt_flag);
174	}
175}
176
177void
178vfs_unmountroot(rootfs)
179	struct mount *rootfs;
180{
181	struct mount *mp = rootfs;
182	int error;
183
184	if (vfs_busy(mp)) {
185		printf("failed to unmount root\n");
186		return;
187	}
188	mp->mnt_flag |= MNT_UNMOUNT;
189	if ((error = vfs_lock(mp))) {
190		printf("lock of root filesystem failed (%d)\n", error);
191		return;
192	}
193	vnode_pager_umount(mp);	/* release cached vnodes */
194	cache_purgevfs(mp);	/* remove cache entries for this file sys */
195
196	if ((error = VFS_SYNC(mp, MNT_WAIT, initproc->p_ucred, initproc)))
197		printf("sync of root filesystem failed (%d)\n", error);
198
199	if ((error = VFS_UNMOUNT(mp, MNT_FORCE, initproc))) {
200		printf("unmount of root filesystem failed (");
201		if (error == EBUSY)
202			printf("BUSY)\n");
203		else
204			printf("%d)\n", error);
205	}
206	mp->mnt_flag &= ~MNT_UNMOUNT;
207	vfs_unbusy(mp);
208}
209
210/*
211 * Unmount all filesystems.  Should only be called by halt().
212 */
213void
214vfs_unmountall()
215{
216	struct mount *mp, *mp_next, *rootfs = NULL;
217	int error;
218
219	/* unmount all but rootfs */
220	for (mp = mountlist.tqh_first; mp != NULL; mp = mp_next) {
221		mp_next = mp->mnt_list.tqe_next;
222
223		if (mp->mnt_flag & MNT_ROOTFS) {
224			rootfs = mp;
225			continue;
226		}
227		error = dounmount(mp, MNT_FORCE, initproc);
228		if (error) {
229			printf("unmount of %s failed (", mp->mnt_stat.f_mntonname);
230			if (error == EBUSY)
231				printf("BUSY)\n");
232			else
233				printf("%d)\n", error);
234		}
235	}
236
237	/* and finally... */
238	if (rootfs) {
239		vfs_unmountroot(rootfs);
240	} else {
241		printf("no root filesystem\n");
242	}
243}
244
245/*
246 * Lookup a mount point by filesystem identifier.
247 */
248struct mount *
249getvfs(fsid)
250	fsid_t *fsid;
251{
252	register struct mount *mp;
253
254	for (mp = mountlist.tqh_first; mp != NULL; mp = mp->mnt_list.tqe_next) {
255		if (mp->mnt_stat.f_fsid.val[0] == fsid->val[0] &&
256		    mp->mnt_stat.f_fsid.val[1] == fsid->val[1])
257			return (mp);
258	}
259	return ((struct mount *) 0);
260}
261
262/*
263 * Get a new unique fsid
264 */
265void
266getnewfsid(mp, mtype)
267	struct mount *mp;
268	int mtype;
269{
270	static u_short xxxfs_mntid;
271
272	fsid_t tfsid;
273
274	mp->mnt_stat.f_fsid.val[0] = makedev(nblkdev + mtype, 0);
275	mp->mnt_stat.f_fsid.val[1] = mtype;
276	if (xxxfs_mntid == 0)
277		++xxxfs_mntid;
278	tfsid.val[0] = makedev(nblkdev + mtype, xxxfs_mntid);
279	tfsid.val[1] = mtype;
280	if (mountlist.tqh_first != NULL) {
281		while (getvfs(&tfsid)) {
282			tfsid.val[0]++;
283			xxxfs_mntid++;
284		}
285	}
286	mp->mnt_stat.f_fsid.val[0] = tfsid.val[0];
287}
288
289/*
290 * Set vnode attributes to VNOVAL
291 */
292void
293vattr_null(vap)
294	register struct vattr *vap;
295{
296
297	vap->va_type = VNON;
298	vap->va_size = VNOVAL;
299	vap->va_bytes = VNOVAL;
300	vap->va_mode = vap->va_nlink = vap->va_uid = vap->va_gid =
301	    vap->va_fsid = vap->va_fileid =
302	    vap->va_blocksize = vap->va_rdev =
303	    vap->va_atime.ts_sec = vap->va_atime.ts_nsec =
304	    vap->va_mtime.ts_sec = vap->va_mtime.ts_nsec =
305	    vap->va_ctime.ts_sec = vap->va_ctime.ts_nsec =
306	    vap->va_flags = vap->va_gen = VNOVAL;
307	vap->va_vaflags = 0;
308}
309
310/*
311 * Routines having to do with the management of the vnode table.
312 */
313extern int (**dead_vnodeop_p) ();
314extern void vclean();
315
316/*
317 * Return the next vnode from the free list.
318 */
319int
320getnewvnode(tag, mp, vops, vpp)
321	enum vtagtype tag;
322	struct mount *mp;
323	int (**vops) ();
324	struct vnode **vpp;
325{
326	register struct vnode *vp;
327
328	vp = vnode_free_list.tqh_first;
329	/*
330	 * we allocate a new vnode if
331	 * 	1. we don't have any free
332	 *		Pretty obvious, we actually used to panic, but that
333	 *		is a silly thing to do.
334	 *	2. we havn't filled our pool yet
335	 *		We don't want to trash the incore (VM-)vnodecache.
336	 *	3. if less that 1/16th of our vnodes are free.
337	 *		We don't want to trash the namei cache either.
338	 */
339	if (freevnodes < (numvnodes >> 4) ||
340	    numvnodes < desiredvnodes ||
341	    vp == NULL) {
342		vp = (struct vnode *) malloc((u_long) sizeof *vp,
343		    M_VNODE, M_WAITOK);
344		bzero((char *) vp, sizeof *vp);
345		numvnodes++;
346	} else {
347		TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
348		freevnodes--;
349
350		if (vp->v_usecount)
351			panic("free vnode isn't");
352
353		/* see comment on why 0xdeadb is set at end of vgone (below) */
354		vp->v_freelist.tqe_prev = (struct vnode **) 0xdeadb;
355		vp->v_lease = NULL;
356		if (vp->v_type != VBAD)
357			vgone(vp);
358#ifdef DIAGNOSTIC
359		{
360			int s;
361
362			if (vp->v_data)
363				panic("cleaned vnode isn't");
364			s = splbio();
365			if (vp->v_numoutput)
366				panic("Clean vnode has pending I/O's");
367			splx(s);
368		}
369#endif
370		vp->v_flag = 0;
371		vp->v_lastr = 0;
372		vp->v_ralen = 0;
373		vp->v_maxra = 0;
374		vp->v_lastw = 0;
375		vp->v_lasta = 0;
376		vp->v_cstart = 0;
377		vp->v_clen = 0;
378		vp->v_socket = 0;
379		vp->v_writecount = 0;	/* XXX */
380	}
381	vp->v_type = VNON;
382	cache_purge(vp);
383	vp->v_tag = tag;
384	vp->v_op = vops;
385	insmntque(vp, mp);
386	*vpp = vp;
387	vp->v_usecount = 1;
388	vp->v_data = 0;
389	return (0);
390}
391
392/*
393 * Move a vnode from one mount queue to another.
394 */
395void
396insmntque(vp, mp)
397	register struct vnode *vp;
398	register struct mount *mp;
399{
400
401	/*
402	 * Delete from old mount point vnode list, if on one.
403	 */
404	if (vp->v_mount != NULL)
405		LIST_REMOVE(vp, v_mntvnodes);
406	/*
407	 * Insert into list of vnodes for the new mount point, if available.
408	 */
409	if ((vp->v_mount = mp) == NULL)
410		return;
411	LIST_INSERT_HEAD(&mp->mnt_vnodelist, vp, v_mntvnodes);
412}
413
414/*
415 * Update outstanding I/O count and do wakeup if requested.
416 */
417void
418vwakeup(bp)
419	register struct buf *bp;
420{
421	register struct vnode *vp;
422
423	bp->b_flags &= ~B_WRITEINPROG;
424	if ((vp = bp->b_vp)) {
425		vp->v_numoutput--;
426		if (vp->v_numoutput < 0)
427			panic("vwakeup: neg numoutput");
428		if ((vp->v_numoutput == 0) && (vp->v_flag & VBWAIT)) {
429			vp->v_flag &= ~VBWAIT;
430			wakeup((caddr_t) &vp->v_numoutput);
431		}
432	}
433}
434
435/*
436 * Flush out and invalidate all buffers associated with a vnode.
437 * Called with the underlying object locked.
438 */
439int
440vinvalbuf(vp, flags, cred, p, slpflag, slptimeo)
441	register struct vnode *vp;
442	int flags;
443	struct ucred *cred;
444	struct proc *p;
445	int slpflag, slptimeo;
446{
447	register struct buf *bp;
448	struct buf *nbp, *blist;
449	int s, error;
450	vm_pager_t pager;
451	vm_object_t object;
452
453	if (flags & V_SAVE) {
454		if ((error = VOP_FSYNC(vp, cred, MNT_WAIT, p)))
455			return (error);
456		if (vp->v_dirtyblkhd.lh_first != NULL)
457			panic("vinvalbuf: dirty bufs");
458	}
459	for (;;) {
460		if ((blist = vp->v_cleanblkhd.lh_first) && (flags & V_SAVEMETA))
461			while (blist && blist->b_lblkno < 0)
462				blist = blist->b_vnbufs.le_next;
463		if (!blist && (blist = vp->v_dirtyblkhd.lh_first) &&
464		    (flags & V_SAVEMETA))
465			while (blist && blist->b_lblkno < 0)
466				blist = blist->b_vnbufs.le_next;
467		if (!blist)
468			break;
469
470		for (bp = blist; bp; bp = nbp) {
471			nbp = bp->b_vnbufs.le_next;
472			if ((flags & V_SAVEMETA) && bp->b_lblkno < 0)
473				continue;
474			s = splbio();
475			if (bp->b_flags & B_BUSY) {
476				bp->b_flags |= B_WANTED;
477				error = tsleep((caddr_t) bp,
478				    slpflag | (PRIBIO + 1), "vinvalbuf",
479				    slptimeo);
480				splx(s);
481				if (error)
482					return (error);
483				break;
484			}
485			bremfree(bp);
486			bp->b_flags |= B_BUSY;
487			splx(s);
488			/*
489			 * XXX Since there are no node locks for NFS, I
490			 * believe there is a slight chance that a delayed
491			 * write will occur while sleeping just above, so
492			 * check for it.
493			 */
494			if ((bp->b_flags & B_DELWRI) && (flags & V_SAVE)) {
495				(void) VOP_BWRITE(bp);
496				break;
497			}
498			bp->b_flags |= B_INVAL;
499			brelse(bp);
500		}
501	}
502
503
504	s = splbio();
505	while (vp->v_numoutput > 0) {
506		vp->v_flag |= VBWAIT;
507		tsleep(&vp->v_numoutput, PVM, "vnvlbv", 0);
508	}
509	splx(s);
510
511	/*
512	 * Destroy the copy in the VM cache, too.
513	 */
514	if ((flags & V_SAVE) == 0) {
515		pager = NULL;
516		object = (vm_object_t) vp->v_vmdata;
517		if (object != NULL)
518			pager = object->pager;
519		if (pager != NULL) {
520			object = vm_object_lookup(pager);
521			if (object) {
522				vm_object_lock(object);
523				vm_object_page_remove(object, 0, object->size);
524				vm_object_unlock(object);
525				vm_object_deallocate(object);
526			}
527		}
528	}
529	if (!(flags & V_SAVEMETA) &&
530	    (vp->v_dirtyblkhd.lh_first || vp->v_cleanblkhd.lh_first))
531		panic("vinvalbuf: flush failed");
532	return (0);
533}
534
535/*
536 * Associate a buffer with a vnode.
537 */
538void
539bgetvp(vp, bp)
540	register struct vnode *vp;
541	register struct buf *bp;
542{
543	int s;
544
545	if (bp->b_vp)
546		panic("bgetvp: not free");
547	VHOLD(vp);
548	bp->b_vp = vp;
549	if (vp->v_type == VBLK || vp->v_type == VCHR)
550		bp->b_dev = vp->v_rdev;
551	else
552		bp->b_dev = NODEV;
553	/*
554	 * Insert onto list for new vnode.
555	 */
556	s = splbio();
557	bufinsvn(bp, &vp->v_cleanblkhd);
558	splx(s);
559}
560
561/*
562 * Disassociate a buffer from a vnode.
563 */
564void
565brelvp(bp)
566	register struct buf *bp;
567{
568	struct vnode *vp;
569	int s;
570
571	if (bp->b_vp == (struct vnode *) 0)
572		panic("brelvp: NULL");
573	/*
574	 * Delete from old vnode list, if on one.
575	 */
576	s = splbio();
577	if (bp->b_vnbufs.le_next != NOLIST)
578		bufremvn(bp);
579	splx(s);
580
581	vp = bp->b_vp;
582	bp->b_vp = (struct vnode *) 0;
583	HOLDRELE(vp);
584}
585
586/*
587 * Associate a p-buffer with a vnode.
588 */
589void
590pbgetvp(vp, bp)
591	register struct vnode *vp;
592	register struct buf *bp;
593{
594	if (bp->b_vp)
595		panic("pbgetvp: not free");
596	VHOLD(vp);
597	bp->b_vp = vp;
598	if (vp->v_type == VBLK || vp->v_type == VCHR)
599		bp->b_dev = vp->v_rdev;
600	else
601		bp->b_dev = NODEV;
602}
603
604/*
605 * Disassociate a p-buffer from a vnode.
606 */
607void
608pbrelvp(bp)
609	register struct buf *bp;
610{
611	struct vnode *vp;
612
613	if (bp->b_vp == (struct vnode *) 0)
614		panic("brelvp: NULL");
615
616	vp = bp->b_vp;
617	bp->b_vp = (struct vnode *) 0;
618	HOLDRELE(vp);
619}
620
621/*
622 * Reassign a buffer from one vnode to another.
623 * Used to assign file specific control information
624 * (indirect blocks) to the vnode to which they belong.
625 */
626void
627reassignbuf(bp, newvp)
628	register struct buf *bp;
629	register struct vnode *newvp;
630{
631	register struct buflists *listheadp;
632
633	if (newvp == NULL) {
634		printf("reassignbuf: NULL");
635		return;
636	}
637	/*
638	 * Delete from old vnode list, if on one.
639	 */
640	if (bp->b_vnbufs.le_next != NOLIST)
641		bufremvn(bp);
642	/*
643	 * If dirty, put on list of dirty buffers; otherwise insert onto list
644	 * of clean buffers.
645	 */
646	if (bp->b_flags & B_DELWRI) {
647		struct buf *tbp;
648
649		tbp = newvp->v_dirtyblkhd.lh_first;
650		if (!tbp || (tbp->b_lblkno > bp->b_lblkno)) {
651			bufinsvn(bp, &newvp->v_dirtyblkhd);
652		} else {
653			while (tbp->b_vnbufs.le_next && (tbp->b_vnbufs.le_next->b_lblkno < bp->b_lblkno)) {
654				tbp = tbp->b_vnbufs.le_next;
655			}
656			LIST_INSERT_AFTER(tbp, bp, b_vnbufs);
657		}
658	} else {
659		listheadp = &newvp->v_cleanblkhd;
660		bufinsvn(bp, listheadp);
661	}
662}
663
664/*
665 * Create a vnode for a block device.
666 * Used for root filesystem, argdev, and swap areas.
667 * Also used for memory file system special devices.
668 */
669int
670bdevvp(dev, vpp)
671	dev_t dev;
672	struct vnode **vpp;
673{
674	register struct vnode *vp;
675	struct vnode *nvp;
676	int error;
677
678	if (dev == NODEV)
679		return (0);
680	error = getnewvnode(VT_NON, (struct mount *) 0, spec_vnodeop_p, &nvp);
681	if (error) {
682		*vpp = 0;
683		return (error);
684	}
685	vp = nvp;
686	vp->v_type = VBLK;
687	if ((nvp = checkalias(vp, dev, (struct mount *) 0))) {
688		vput(vp);
689		vp = nvp;
690	}
691	*vpp = vp;
692	return (0);
693}
694
695/*
696 * Check to see if the new vnode represents a special device
697 * for which we already have a vnode (either because of
698 * bdevvp() or because of a different vnode representing
699 * the same block device). If such an alias exists, deallocate
700 * the existing contents and return the aliased vnode. The
701 * caller is responsible for filling it with its new contents.
702 */
703struct vnode *
704checkalias(nvp, nvp_rdev, mp)
705	register struct vnode *nvp;
706	dev_t nvp_rdev;
707	struct mount *mp;
708{
709	register struct vnode *vp;
710	struct vnode **vpp;
711
712	if (nvp->v_type != VBLK && nvp->v_type != VCHR)
713		return (NULLVP);
714
715	vpp = &speclisth[SPECHASH(nvp_rdev)];
716loop:
717	for (vp = *vpp; vp; vp = vp->v_specnext) {
718		if (nvp_rdev != vp->v_rdev || nvp->v_type != vp->v_type)
719			continue;
720		/*
721		 * Alias, but not in use, so flush it out.
722		 */
723		if (vp->v_usecount == 0) {
724			vgone(vp);
725			goto loop;
726		}
727		if (vget(vp, 1))
728			goto loop;
729		break;
730	}
731	if (vp == NULL || vp->v_tag != VT_NON) {
732		MALLOC(nvp->v_specinfo, struct specinfo *,
733		    sizeof(struct specinfo), M_VNODE, M_WAITOK);
734		nvp->v_rdev = nvp_rdev;
735		nvp->v_hashchain = vpp;
736		nvp->v_specnext = *vpp;
737		nvp->v_specflags = 0;
738		*vpp = nvp;
739		if (vp != NULL) {
740			nvp->v_flag |= VALIASED;
741			vp->v_flag |= VALIASED;
742			vput(vp);
743		}
744		return (NULLVP);
745	}
746	VOP_UNLOCK(vp);
747	vclean(vp, 0);
748	vp->v_op = nvp->v_op;
749	vp->v_tag = nvp->v_tag;
750	nvp->v_type = VNON;
751	insmntque(vp, mp);
752	return (vp);
753}
754
755/*
756 * Grab a particular vnode from the free list, increment its
757 * reference count and lock it. The vnode lock bit is set the
758 * vnode is being eliminated in vgone. The process is awakened
759 * when the transition is completed, and an error returned to
760 * indicate that the vnode is no longer usable (possibly having
761 * been changed to a new file system type).
762 */
763int
764vget(vp, lockflag)
765	register struct vnode *vp;
766	int lockflag;
767{
768
769	/*
770	 * If the vnode is in the process of being cleaned out for another
771	 * use, we wait for the cleaning to finish and then return failure.
772	 * Cleaning is determined either by checking that the VXLOCK flag is
773	 * set, or that the use count is zero with the back pointer set to
774	 * show that it has been removed from the free list by getnewvnode.
775	 * The VXLOCK flag may not have been set yet because vclean is blocked
776	 * in the VOP_LOCK call waiting for the VOP_INACTIVE to complete.
777	 */
778	if ((vp->v_flag & VXLOCK) ||
779	    (vp->v_usecount == 0 &&
780		vp->v_freelist.tqe_prev == (struct vnode **) 0xdeadb)) {
781		vp->v_flag |= VXWANT;
782		(void) tsleep((caddr_t) vp, PINOD, "vget", 0);
783		return (1);
784	}
785	if (vp->v_usecount == 0) {
786		TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
787		freevnodes--;
788	}
789	vp->v_usecount++;
790	if (lockflag)
791		VOP_LOCK(vp);
792	return (0);
793}
794
795/*
796 * Vnode reference, just increment the count
797 */
798void
799vref(vp)
800	struct vnode *vp;
801{
802
803	if (vp->v_usecount <= 0)
804		panic("vref used where vget required");
805	vp->v_usecount++;
806}
807
808/*
809 * vput(), just unlock and vrele()
810 */
811void
812vput(vp)
813	register struct vnode *vp;
814{
815
816	VOP_UNLOCK(vp);
817	vrele(vp);
818}
819
820/*
821 * Vnode release.
822 * If count drops to zero, call inactive routine and return to freelist.
823 */
824void
825vrele(vp)
826	register struct vnode *vp;
827{
828
829#ifdef DIAGNOSTIC
830	if (vp == NULL)
831		panic("vrele: null vp");
832#endif
833	vp->v_usecount--;
834	if (vp->v_usecount > 0)
835		return;
836#ifdef DIAGNOSTIC
837	if (vp->v_usecount != 0 /* || vp->v_writecount != 0 */ ) {
838		vprint("vrele: bad ref count", vp);
839		panic("vrele: ref cnt");
840	}
841#endif
842	if (vp->v_flag & VAGE) {
843		TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist);
844		vp->v_flag &= ~VAGE;
845	} else {
846		TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
847	}
848	freevnodes++;
849
850	VOP_INACTIVE(vp);
851}
852
853/*
854 * Page or buffer structure gets a reference.
855 */
856void
857vhold(vp)
858	register struct vnode *vp;
859{
860
861	vp->v_holdcnt++;
862}
863
864/*
865 * Page or buffer structure frees a reference.
866 */
867void
868holdrele(vp)
869	register struct vnode *vp;
870{
871
872	if (vp->v_holdcnt <= 0)
873		panic("holdrele: holdcnt");
874	vp->v_holdcnt--;
875}
876
877/*
878 * Remove any vnodes in the vnode table belonging to mount point mp.
879 *
880 * If MNT_NOFORCE is specified, there should not be any active ones,
881 * return error if any are found (nb: this is a user error, not a
882 * system error). If MNT_FORCE is specified, detach any active vnodes
883 * that are found.
884 */
885#ifdef DIAGNOSTIC
886int busyprt = 0;		/* print out busy vnodes */
887struct ctldebug debug1 = {"busyprt", &busyprt};
888
889#endif
890
891int
892vflush(mp, skipvp, flags)
893	struct mount *mp;
894	struct vnode *skipvp;
895	int flags;
896{
897	register struct vnode *vp, *nvp;
898	int busy = 0;
899
900	if ((mp->mnt_flag & MNT_MPBUSY) == 0)
901		panic("vflush: not busy");
902loop:
903	for (vp = mp->mnt_vnodelist.lh_first; vp; vp = nvp) {
904		/*
905		 * Make sure this vnode wasn't reclaimed in getnewvnode().
906		 * Start over if it has (it won't be on the list anymore).
907		 */
908		if (vp->v_mount != mp)
909			goto loop;
910		nvp = vp->v_mntvnodes.le_next;
911		/*
912		 * Skip over a selected vnode.
913		 */
914		if (vp == skipvp)
915			continue;
916		/*
917		 * Skip over a vnodes marked VSYSTEM.
918		 */
919		if ((flags & SKIPSYSTEM) && (vp->v_flag & VSYSTEM))
920			continue;
921		/*
922		 * If WRITECLOSE is set, only flush out regular file vnodes
923		 * open for writing.
924		 */
925		if ((flags & WRITECLOSE) &&
926		    (vp->v_writecount == 0 || vp->v_type != VREG))
927			continue;
928		/*
929		 * With v_usecount == 0, all we need to do is clear out the
930		 * vnode data structures and we are done.
931		 */
932		if (vp->v_usecount == 0) {
933			vgone(vp);
934			continue;
935		}
936		/*
937		 * If FORCECLOSE is set, forcibly close the vnode. For block
938		 * or character devices, revert to an anonymous device. For
939		 * all other files, just kill them.
940		 */
941		if (flags & FORCECLOSE) {
942			if (vp->v_type != VBLK && vp->v_type != VCHR) {
943				vgone(vp);
944			} else {
945				vclean(vp, 0);
946				vp->v_op = spec_vnodeop_p;
947				insmntque(vp, (struct mount *) 0);
948			}
949			continue;
950		}
951#ifdef DIAGNOSTIC
952		if (busyprt)
953			vprint("vflush: busy vnode", vp);
954#endif
955		busy++;
956	}
957	if (busy)
958		return (EBUSY);
959	return (0);
960}
961
962/*
963 * Disassociate the underlying file system from a vnode.
964 */
965void
966vclean(vp, flags)
967	register struct vnode *vp;
968	int flags;
969{
970	int active;
971
972	/*
973	 * Check to see if the vnode is in use. If so we have to reference it
974	 * before we clean it out so that its count cannot fall to zero and
975	 * generate a race against ourselves to recycle it.
976	 */
977	if ((active = vp->v_usecount))
978		VREF(vp);
979	/*
980	 * Even if the count is zero, the VOP_INACTIVE routine may still have
981	 * the object locked while it cleans it out. The VOP_LOCK ensures that
982	 * the VOP_INACTIVE routine is done with its work. For active vnodes,
983	 * it ensures that no other activity can occur while the underlying
984	 * object is being cleaned out.
985	 */
986	VOP_LOCK(vp);
987	/*
988	 * Prevent the vnode from being recycled or brought into use while we
989	 * clean it out.
990	 */
991	if (vp->v_flag & VXLOCK)
992		panic("vclean: deadlock");
993	vp->v_flag |= VXLOCK;
994	/*
995	 * Clean out any buffers associated with the vnode.
996	 */
997	if (flags & DOCLOSE)
998		vinvalbuf(vp, V_SAVE, NOCRED, NULL, 0, 0);
999	/*
1000	 * Any other processes trying to obtain this lock must first wait for
1001	 * VXLOCK to clear, then call the new lock operation.
1002	 */
1003	VOP_UNLOCK(vp);
1004	/*
1005	 * If purging an active vnode, it must be closed and deactivated
1006	 * before being reclaimed.
1007	 */
1008	if (active) {
1009		if (flags & DOCLOSE)
1010			VOP_CLOSE(vp, IO_NDELAY, NOCRED, NULL);
1011		VOP_INACTIVE(vp);
1012	}
1013	/*
1014	 * Reclaim the vnode.
1015	 */
1016	if (VOP_RECLAIM(vp))
1017		panic("vclean: cannot reclaim");
1018	if (active)
1019		vrele(vp);
1020
1021	/*
1022	 * Done with purge, notify sleepers of the grim news.
1023	 */
1024	vp->v_op = dead_vnodeop_p;
1025	vp->v_tag = VT_NON;
1026	vp->v_flag &= ~VXLOCK;
1027	if (vp->v_flag & VXWANT) {
1028		vp->v_flag &= ~VXWANT;
1029		wakeup((caddr_t) vp);
1030	}
1031}
1032
1033/*
1034 * Eliminate all activity associated with  the requested vnode
1035 * and with all vnodes aliased to the requested vnode.
1036 */
1037void
1038vgoneall(vp)
1039	register struct vnode *vp;
1040{
1041	register struct vnode *vq;
1042
1043	if (vp->v_flag & VALIASED) {
1044		/*
1045		 * If a vgone (or vclean) is already in progress, wait until
1046		 * it is done and return.
1047		 */
1048		if (vp->v_flag & VXLOCK) {
1049			vp->v_flag |= VXWANT;
1050			(void) tsleep((caddr_t) vp, PINOD, "vgall", 0);
1051			return;
1052		}
1053		/*
1054		 * Ensure that vp will not be vgone'd while we are eliminating
1055		 * its aliases.
1056		 */
1057		vp->v_flag |= VXLOCK;
1058		while (vp->v_flag & VALIASED) {
1059			for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
1060				if (vq->v_rdev != vp->v_rdev ||
1061				    vq->v_type != vp->v_type || vp == vq)
1062					continue;
1063				vgone(vq);
1064				break;
1065			}
1066		}
1067		/*
1068		 * Remove the lock so that vgone below will really eliminate
1069		 * the vnode after which time vgone will awaken any sleepers.
1070		 */
1071		vp->v_flag &= ~VXLOCK;
1072	}
1073	vgone(vp);
1074}
1075
1076/*
1077 * Eliminate all activity associated with a vnode
1078 * in preparation for reuse.
1079 */
1080void
1081vgone(vp)
1082	register struct vnode *vp;
1083{
1084	register struct vnode *vq;
1085	struct vnode *vx;
1086
1087	/*
1088	 * If a vgone (or vclean) is already in progress, wait until it is
1089	 * done and return.
1090	 */
1091	if (vp->v_flag & VXLOCK) {
1092		vp->v_flag |= VXWANT;
1093		(void) tsleep((caddr_t) vp, PINOD, "vgone", 0);
1094		return;
1095	}
1096	/*
1097	 * Clean out the filesystem specific data.
1098	 */
1099	vclean(vp, DOCLOSE);
1100	/*
1101	 * Delete from old mount point vnode list, if on one.
1102	 */
1103	if (vp->v_mount != NULL) {
1104		LIST_REMOVE(vp, v_mntvnodes);
1105		vp->v_mount = NULL;
1106	}
1107	/*
1108	 * If special device, remove it from special device alias list.
1109	 */
1110	if (vp->v_type == VBLK || vp->v_type == VCHR) {
1111		if (*vp->v_hashchain == vp) {
1112			*vp->v_hashchain = vp->v_specnext;
1113		} else {
1114			for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
1115				if (vq->v_specnext != vp)
1116					continue;
1117				vq->v_specnext = vp->v_specnext;
1118				break;
1119			}
1120			if (vq == NULL)
1121				panic("missing bdev");
1122		}
1123		if (vp->v_flag & VALIASED) {
1124			vx = NULL;
1125			for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
1126				if (vq->v_rdev != vp->v_rdev ||
1127				    vq->v_type != vp->v_type)
1128					continue;
1129				if (vx)
1130					break;
1131				vx = vq;
1132			}
1133			if (vx == NULL)
1134				panic("missing alias");
1135			if (vq == NULL)
1136				vx->v_flag &= ~VALIASED;
1137			vp->v_flag &= ~VALIASED;
1138		}
1139		FREE(vp->v_specinfo, M_VNODE);
1140		vp->v_specinfo = NULL;
1141	}
1142	/*
1143	 * If it is on the freelist and not already at the head, move it to
1144	 * the head of the list. The test of the back pointer and the
1145	 * reference count of zero is because it will be removed from the free
1146	 * list by getnewvnode, but will not have its reference count
1147	 * incremented until after calling vgone. If the reference count were
1148	 * incremented first, vgone would (incorrectly) try to close the
1149	 * previous instance of the underlying object. So, the back pointer is
1150	 * explicitly set to `0xdeadb' in getnewvnode after removing it from
1151	 * the freelist to ensure that we do not try to move it here.
1152	 */
1153	if (vp->v_usecount == 0 &&
1154	    vp->v_freelist.tqe_prev != (struct vnode **) 0xdeadb &&
1155	    vnode_free_list.tqh_first != vp) {
1156		TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
1157		TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist);
1158	}
1159	vp->v_type = VBAD;
1160}
1161
1162/*
1163 * Lookup a vnode by device number.
1164 */
1165int
1166vfinddev(dev, type, vpp)
1167	dev_t dev;
1168	enum vtype type;
1169	struct vnode **vpp;
1170{
1171	register struct vnode *vp;
1172
1173	for (vp = speclisth[SPECHASH(dev)]; vp; vp = vp->v_specnext) {
1174		if (dev != vp->v_rdev || type != vp->v_type)
1175			continue;
1176		*vpp = vp;
1177		return (1);
1178	}
1179	return (0);
1180}
1181
1182/*
1183 * Calculate the total number of references to a special device.
1184 */
1185int
1186vcount(vp)
1187	register struct vnode *vp;
1188{
1189	register struct vnode *vq, *vnext;
1190	int count;
1191
1192loop:
1193	if ((vp->v_flag & VALIASED) == 0)
1194		return (vp->v_usecount);
1195	for (count = 0, vq = *vp->v_hashchain; vq; vq = vnext) {
1196		vnext = vq->v_specnext;
1197		if (vq->v_rdev != vp->v_rdev || vq->v_type != vp->v_type)
1198			continue;
1199		/*
1200		 * Alias, but not in use, so flush it out.
1201		 */
1202		if (vq->v_usecount == 0 && vq != vp) {
1203			vgone(vq);
1204			goto loop;
1205		}
1206		count += vq->v_usecount;
1207	}
1208	return (count);
1209}
1210
1211/*
1212 * Print out a description of a vnode.
1213 */
1214static char *typename[] =
1215{"VNON", "VREG", "VDIR", "VBLK", "VCHR", "VLNK", "VSOCK", "VFIFO", "VBAD"};
1216
1217void
1218vprint(label, vp)
1219	char *label;
1220	register struct vnode *vp;
1221{
1222	char buf[64];
1223
1224	if (label != NULL)
1225		printf("%s: ", label);
1226	printf("type %s, usecount %d, writecount %d, refcount %ld,",
1227	    typename[vp->v_type], vp->v_usecount, vp->v_writecount,
1228	    vp->v_holdcnt);
1229	buf[0] = '\0';
1230	if (vp->v_flag & VROOT)
1231		strcat(buf, "|VROOT");
1232	if (vp->v_flag & VTEXT)
1233		strcat(buf, "|VTEXT");
1234	if (vp->v_flag & VSYSTEM)
1235		strcat(buf, "|VSYSTEM");
1236	if (vp->v_flag & VXLOCK)
1237		strcat(buf, "|VXLOCK");
1238	if (vp->v_flag & VXWANT)
1239		strcat(buf, "|VXWANT");
1240	if (vp->v_flag & VBWAIT)
1241		strcat(buf, "|VBWAIT");
1242	if (vp->v_flag & VALIASED)
1243		strcat(buf, "|VALIASED");
1244	if (buf[0] != '\0')
1245		printf(" flags (%s)", &buf[1]);
1246	if (vp->v_data == NULL) {
1247		printf("\n");
1248	} else {
1249		printf("\n\t");
1250		VOP_PRINT(vp);
1251	}
1252}
1253
1254#ifdef DEBUG
1255/*
1256 * List all of the locked vnodes in the system.
1257 * Called when debugging the kernel.
1258 */
1259void
1260printlockedvnodes()
1261{
1262	register struct mount *mp;
1263	register struct vnode *vp;
1264
1265	printf("Locked vnodes\n");
1266	for (mp = mountlist.tqh_first; mp != NULL; mp = mp->mnt_list.tqe_next) {
1267		for (vp = mp->mnt_vnodelist.lh_first;
1268		    vp != NULL;
1269		    vp = vp->v_mntvnodes.le_next)
1270			if (VOP_ISLOCKED(vp))
1271				vprint((char *) 0, vp);
1272	}
1273}
1274#endif
1275
1276int kinfo_vdebug = 1;
1277int kinfo_vgetfailed;
1278
1279#define KINFO_VNODESLOP	10
1280/*
1281 * Dump vnode list (via sysctl).
1282 * Copyout address of vnode followed by vnode.
1283 */
1284/* ARGSUSED */
1285int
1286sysctl_vnode(where, sizep)
1287	char *where;
1288	size_t *sizep;
1289{
1290	register struct mount *mp, *nmp;
1291	struct vnode *vp;
1292	register char *bp = where, *savebp;
1293	char *ewhere;
1294	int error;
1295
1296#define VPTRSZ	sizeof (struct vnode *)
1297#define VNODESZ	sizeof (struct vnode)
1298	if (where == NULL) {
1299		*sizep = (numvnodes + KINFO_VNODESLOP) * (VPTRSZ + VNODESZ);
1300		return (0);
1301	}
1302	ewhere = where + *sizep;
1303
1304	for (mp = mountlist.tqh_first; mp != NULL; mp = nmp) {
1305		nmp = mp->mnt_list.tqe_next;
1306		if (vfs_busy(mp))
1307			continue;
1308		savebp = bp;
1309again:
1310		for (vp = mp->mnt_vnodelist.lh_first;
1311		    vp != NULL;
1312		    vp = vp->v_mntvnodes.le_next) {
1313			/*
1314			 * Check that the vp is still associated with this
1315			 * filesystem.  RACE: could have been recycled onto
1316			 * the same filesystem.
1317			 */
1318			if (vp->v_mount != mp) {
1319				if (kinfo_vdebug)
1320					printf("kinfo: vp changed\n");
1321				bp = savebp;
1322				goto again;
1323			}
1324			if (bp + VPTRSZ + VNODESZ > ewhere) {
1325				*sizep = bp - where;
1326				return (ENOMEM);
1327			}
1328			if ((error = copyout((caddr_t) &vp, bp, VPTRSZ)) ||
1329			    (error = copyout((caddr_t) vp, bp + VPTRSZ, VNODESZ)))
1330				return (error);
1331			bp += VPTRSZ + VNODESZ;
1332		}
1333		vfs_unbusy(mp);
1334	}
1335
1336	*sizep = bp - where;
1337	return (0);
1338}
1339
1340/*
1341 * Check to see if a filesystem is mounted on a block device.
1342 */
1343int
1344vfs_mountedon(vp)
1345	register struct vnode *vp;
1346{
1347	register struct vnode *vq;
1348
1349	if (vp->v_specflags & SI_MOUNTEDON)
1350		return (EBUSY);
1351	if (vp->v_flag & VALIASED) {
1352		for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
1353			if (vq->v_rdev != vp->v_rdev ||
1354			    vq->v_type != vp->v_type)
1355				continue;
1356			if (vq->v_specflags & SI_MOUNTEDON)
1357				return (EBUSY);
1358		}
1359	}
1360	return (0);
1361}
1362
1363/*
1364 * Build hash lists of net addresses and hang them off the mount point.
1365 * Called by ufs_mount() to set up the lists of export addresses.
1366 */
1367static int
1368vfs_hang_addrlist(mp, nep, argp)
1369	struct mount *mp;
1370	struct netexport *nep;
1371	struct export_args *argp;
1372{
1373	register struct netcred *np;
1374	register struct radix_node_head *rnh;
1375	register int i;
1376	struct radix_node *rn;
1377	struct sockaddr *saddr, *smask = 0;
1378	struct domain *dom;
1379	int error;
1380
1381	if (argp->ex_addrlen == 0) {
1382		if (mp->mnt_flag & MNT_DEFEXPORTED)
1383			return (EPERM);
1384		np = &nep->ne_defexported;
1385		np->netc_exflags = argp->ex_flags;
1386		np->netc_anon = argp->ex_anon;
1387		np->netc_anon.cr_ref = 1;
1388		mp->mnt_flag |= MNT_DEFEXPORTED;
1389		return (0);
1390	}
1391	i = sizeof(struct netcred) + argp->ex_addrlen + argp->ex_masklen;
1392	np = (struct netcred *) malloc(i, M_NETADDR, M_WAITOK);
1393	bzero((caddr_t) np, i);
1394	saddr = (struct sockaddr *) (np + 1);
1395	if ((error = copyin(argp->ex_addr, (caddr_t) saddr, argp->ex_addrlen)))
1396		goto out;
1397	if (saddr->sa_len > argp->ex_addrlen)
1398		saddr->sa_len = argp->ex_addrlen;
1399	if (argp->ex_masklen) {
1400		smask = (struct sockaddr *) ((caddr_t) saddr + argp->ex_addrlen);
1401		error = copyin(argp->ex_addr, (caddr_t) smask, argp->ex_masklen);
1402		if (error)
1403			goto out;
1404		if (smask->sa_len > argp->ex_masklen)
1405			smask->sa_len = argp->ex_masklen;
1406	}
1407	i = saddr->sa_family;
1408	if ((rnh = nep->ne_rtable[i]) == 0) {
1409		/*
1410		 * Seems silly to initialize every AF when most are not used,
1411		 * do so on demand here
1412		 */
1413		for (dom = domains; dom; dom = dom->dom_next)
1414			if (dom->dom_family == i && dom->dom_rtattach) {
1415				dom->dom_rtattach((void **) &nep->ne_rtable[i],
1416				    dom->dom_rtoffset);
1417				break;
1418			}
1419		if ((rnh = nep->ne_rtable[i]) == 0) {
1420			error = ENOBUFS;
1421			goto out;
1422		}
1423	}
1424	rn = (*rnh->rnh_addaddr) ((caddr_t) saddr, (caddr_t) smask, rnh,
1425	    np->netc_rnodes);
1426	if (rn == 0 || np != (struct netcred *) rn) {	/* already exists */
1427		error = EPERM;
1428		goto out;
1429	}
1430	np->netc_exflags = argp->ex_flags;
1431	np->netc_anon = argp->ex_anon;
1432	np->netc_anon.cr_ref = 1;
1433	return (0);
1434out:
1435	free(np, M_NETADDR);
1436	return (error);
1437}
1438
1439/* ARGSUSED */
1440static int
1441vfs_free_netcred(rn, w)
1442	struct radix_node *rn;
1443	caddr_t w;
1444{
1445	register struct radix_node_head *rnh = (struct radix_node_head *) w;
1446
1447	(*rnh->rnh_deladdr) (rn->rn_key, rn->rn_mask, rnh);
1448	free((caddr_t) rn, M_NETADDR);
1449	return (0);
1450}
1451
1452/*
1453 * Free the net address hash lists that are hanging off the mount points.
1454 */
1455static void
1456vfs_free_addrlist(nep)
1457	struct netexport *nep;
1458{
1459	register int i;
1460	register struct radix_node_head *rnh;
1461
1462	for (i = 0; i <= AF_MAX; i++)
1463		if ((rnh = nep->ne_rtable[i])) {
1464			(*rnh->rnh_walktree) (rnh, vfs_free_netcred,
1465			    (caddr_t) rnh);
1466			free((caddr_t) rnh, M_RTABLE);
1467			nep->ne_rtable[i] = 0;
1468		}
1469}
1470
1471int
1472vfs_export(mp, nep, argp)
1473	struct mount *mp;
1474	struct netexport *nep;
1475	struct export_args *argp;
1476{
1477	int error;
1478
1479	if (argp->ex_flags & MNT_DELEXPORT) {
1480		vfs_free_addrlist(nep);
1481		mp->mnt_flag &= ~(MNT_EXPORTED | MNT_DEFEXPORTED);
1482	}
1483	if (argp->ex_flags & MNT_EXPORTED) {
1484		if ((error = vfs_hang_addrlist(mp, nep, argp)))
1485			return (error);
1486		mp->mnt_flag |= MNT_EXPORTED;
1487	}
1488	return (0);
1489}
1490
1491struct netcred *
1492vfs_export_lookup(mp, nep, nam)
1493	register struct mount *mp;
1494	struct netexport *nep;
1495	struct mbuf *nam;
1496{
1497	register struct netcred *np;
1498	register struct radix_node_head *rnh;
1499	struct sockaddr *saddr;
1500
1501	np = NULL;
1502	if (mp->mnt_flag & MNT_EXPORTED) {
1503		/*
1504		 * Lookup in the export list first.
1505		 */
1506		if (nam != NULL) {
1507			saddr = mtod(nam, struct sockaddr *);
1508			rnh = nep->ne_rtable[saddr->sa_family];
1509			if (rnh != NULL) {
1510				np = (struct netcred *)
1511				    (*rnh->rnh_matchaddr) ((caddr_t) saddr,
1512				    rnh);
1513				if (np && np->netc_rnodes->rn_flags & RNF_ROOT)
1514					np = NULL;
1515			}
1516		}
1517		/*
1518		 * If no address match, use the default if it exists.
1519		 */
1520		if (np == NULL && mp->mnt_flag & MNT_DEFEXPORTED)
1521			np = &nep->ne_defexported;
1522	}
1523	return (np);
1524}
1525