xref: /csrg-svn/sys/kern/vfs_subr.c (revision 41400)
1 /*
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  *	@(#)vfs_subr.c	7.42 (Berkeley) 05/04/90
18  */
19 
20 /*
21  * External virtual filesystem routines
22  */
23 
24 #include "param.h"
25 #include "mount.h"
26 #include "time.h"
27 #include "vnode.h"
28 #include "specdev.h"
29 #include "namei.h"
30 #include "ucred.h"
31 #include "errno.h"
32 #include "malloc.h"
33 
34 /*
35  * Remove a mount point from the list of mounted filesystems.
36  * Unmount of the root is illegal.
37  */
38 void
39 vfs_remove(mp)
40 	register struct mount *mp;
41 {
42 
43 	if (mp == rootfs)
44 		panic("vfs_remove: unmounting root");
45 	mp->mnt_prev->mnt_next = mp->mnt_next;
46 	mp->mnt_next->mnt_prev = mp->mnt_prev;
47 	mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
48 	vfs_unlock(mp);
49 }
50 
51 /*
52  * Lock a filesystem.
53  * Used to prevent access to it while mounting and unmounting.
54  */
55 vfs_lock(mp)
56 	register struct mount *mp;
57 {
58 
59 	while(mp->mnt_flag & MNT_MLOCK) {
60 		mp->mnt_flag |= MNT_MWAIT;
61 		sleep((caddr_t)mp, PVFS);
62 	}
63 	mp->mnt_flag |= MNT_MLOCK;
64 	return (0);
65 }
66 
67 /*
68  * Unlock a locked filesystem.
69  * Panic if filesystem is not locked.
70  */
71 void
72 vfs_unlock(mp)
73 	register struct mount *mp;
74 {
75 
76 	if ((mp->mnt_flag & MNT_MLOCK) == 0)
77 		panic("vfs_unlock: not locked");
78 	mp->mnt_flag &= ~MNT_MLOCK;
79 	if (mp->mnt_flag & MNT_MWAIT) {
80 		mp->mnt_flag &= ~MNT_MWAIT;
81 		wakeup((caddr_t)mp);
82 	}
83 }
84 
85 /*
86  * Mark a mount point as busy.
87  * Used to synchronize access and to delay unmounting.
88  */
89 vfs_busy(mp)
90 	register struct mount *mp;
91 {
92 
93 	if (mp->mnt_flag & MNT_UNMOUNT)
94 		return (1);
95 	while(mp->mnt_flag & MNT_MPBUSY) {
96 		mp->mnt_flag |= MNT_MPWANT;
97 		sleep((caddr_t)&mp->mnt_flag, PVFS);
98 	}
99 	mp->mnt_flag |= MNT_MPBUSY;
100 	return (0);
101 }
102 
103 /*
104  * Free a busy filesystem.
105  * Panic if filesystem is not busy.
106  */
107 void
108 vfs_unbusy(mp)
109 	register struct mount *mp;
110 {
111 
112 	if ((mp->mnt_flag & MNT_MPBUSY) == 0)
113 		panic("vfs_unbusy: not busy");
114 	mp->mnt_flag &= ~MNT_MPBUSY;
115 	if (mp->mnt_flag & MNT_MPWANT) {
116 		mp->mnt_flag &= ~MNT_MPWANT;
117 		wakeup((caddr_t)&mp->mnt_flag);
118 	}
119 }
120 
121 /*
122  * Lookup a mount point by filesystem identifier.
123  */
124 struct mount *
125 getvfs(fsid)
126 	fsid_t *fsid;
127 {
128 	register struct mount *mp;
129 
130 	mp = rootfs;
131 	do {
132 		if (mp->mnt_stat.f_fsid.val[0] == fsid->val[0] &&
133 		    mp->mnt_stat.f_fsid.val[1] == fsid->val[1]) {
134 			return (mp);
135 		}
136 		mp = mp->mnt_next;
137 	} while (mp != rootfs);
138 	return ((struct mount *)0);
139 }
140 
141 /*
142  * Set vnode attributes to VNOVAL
143  */
144 void vattr_null(vap)
145 	register struct vattr *vap;
146 {
147 
148 	vap->va_type = VNON;
149 	vap->va_mode = vap->va_nlink = vap->va_uid = vap->va_gid =
150 		vap->va_fsid = vap->va_fileid = vap->va_size =
151 		vap->va_size_rsv = vap->va_blocksize = vap->va_rdev =
152 		vap->va_bytes = vap->va_bytes_rsv =
153 		vap->va_atime.tv_sec = vap->va_atime.tv_usec =
154 		vap->va_mtime.tv_sec = vap->va_mtime.tv_usec =
155 		vap->va_ctime.tv_sec = vap->va_ctime.tv_usec =
156 		vap->va_flags = vap->va_gen = VNOVAL;
157 }
158 
159 /*
160  * Initialize a nameidata structure
161  */
162 ndinit(ndp)
163 	register struct nameidata *ndp;
164 {
165 
166 	bzero((caddr_t)ndp, sizeof(struct nameidata));
167 	ndp->ni_iov = &ndp->ni_nd.nd_iovec;
168 	ndp->ni_iovcnt = 1;
169 	ndp->ni_base = (caddr_t)&ndp->ni_dent;
170 	ndp->ni_rw = UIO_WRITE;
171 	ndp->ni_uioseg = UIO_SYSSPACE;
172 }
173 
174 /*
175  * Duplicate a nameidata structure
176  */
177 nddup(ndp, newndp)
178 	register struct nameidata *ndp, *newndp;
179 {
180 
181 	ndinit(newndp);
182 	newndp->ni_cdir = ndp->ni_cdir;
183 	VREF(newndp->ni_cdir);
184 	newndp->ni_rdir = ndp->ni_rdir;
185 	if (newndp->ni_rdir)
186 		VREF(newndp->ni_rdir);
187 	newndp->ni_cred = ndp->ni_cred;
188 	crhold(newndp->ni_cred);
189 }
190 
191 /*
192  * Release a nameidata structure
193  */
194 ndrele(ndp)
195 	register struct nameidata *ndp;
196 {
197 
198 	vrele(ndp->ni_cdir);
199 	if (ndp->ni_rdir)
200 		vrele(ndp->ni_rdir);
201 	crfree(ndp->ni_cred);
202 }
203 
204 /*
205  * Routines having to do with the management of the vnode table.
206  */
207 struct vnode *vfreeh, **vfreet;
208 extern struct vnodeops dead_vnodeops, spec_vnodeops;
209 extern void vclean();
210 long numvnodes;
211 struct vattr va_null;
212 
213 /*
214  * Initialize the vnode structures and initialize each file system type.
215  */
216 vfsinit()
217 {
218 	struct vfsops **vfsp;
219 
220 	/*
221 	 * Initialize the vnode name cache
222 	 */
223 	nchinit();
224 	/*
225 	 * Initialize each file system type.
226 	 */
227 	vattr_null(&va_null);
228 	for (vfsp = &vfssw[0]; vfsp <= &vfssw[MOUNT_MAXTYPE]; vfsp++) {
229 		if (*vfsp == NULL)
230 			continue;
231 		(*(*vfsp)->vfs_init)();
232 	}
233 }
234 
235 /*
236  * Return the next vnode from the free list.
237  */
238 getnewvnode(tag, mp, vops, vpp)
239 	enum vtagtype tag;
240 	struct mount *mp;
241 	struct vnodeops *vops;
242 	struct vnode **vpp;
243 {
244 	register struct vnode *vp, *vq;
245 
246 	if (numvnodes < desiredvnodes) {
247 		vp = (struct vnode *)malloc(sizeof *vp, M_VNODE, M_WAITOK);
248 		bzero((char *)vp, sizeof *vp);
249 		numvnodes++;
250 	} else {
251 		if ((vp = vfreeh) == NULL) {
252 			tablefull("vnode");
253 			*vpp = 0;
254 			return (ENFILE);
255 		}
256 		if (vp->v_usecount)
257 			panic("free vnode isn't");
258 		if (vq = vp->v_freef)
259 			vq->v_freeb = &vfreeh;
260 		else
261 			vfreet = &vfreeh;
262 		vfreeh = vq;
263 		vp->v_freef = NULL;
264 		vp->v_freeb = NULL;
265 		if (vp->v_type != VBAD)
266 			vgone(vp);
267 		vp->v_flag = 0;
268 		vp->v_shlockc = 0;
269 		vp->v_exlockc = 0;
270 		vp->v_lastr = 0;
271 		vp->v_socket = 0;
272 	}
273 	vp->v_type = VNON;
274 	cache_purge(vp);
275 	vp->v_tag = tag;
276 	vp->v_op = vops;
277 	insmntque(vp, mp);
278 	VREF(vp);
279 	*vpp = vp;
280 	return (0);
281 }
282 
283 /*
284  * Move a vnode from one mount queue to another.
285  */
286 insmntque(vp, mp)
287 	register struct vnode *vp;
288 	register struct mount *mp;
289 {
290 	struct vnode *vq;
291 
292 	/*
293 	 * Delete from old mount point vnode list, if on one.
294 	 */
295 	if (vp->v_mountb) {
296 		if (vq = vp->v_mountf)
297 			vq->v_mountb = vp->v_mountb;
298 		*vp->v_mountb = vq;
299 	}
300 	/*
301 	 * Insert into list of vnodes for the new mount point, if available.
302 	 */
303 	vp->v_mount = mp;
304 	if (mp == NULL) {
305 		vp->v_mountf = NULL;
306 		vp->v_mountb = NULL;
307 		return;
308 	}
309 	if (mp->mnt_mounth) {
310 		vp->v_mountf = mp->mnt_mounth;
311 		vp->v_mountb = &mp->mnt_mounth;
312 		mp->mnt_mounth->v_mountb = &vp->v_mountf;
313 		mp->mnt_mounth = vp;
314 	} else {
315 		mp->mnt_mounth = vp;
316 		vp->v_mountb = &mp->mnt_mounth;
317 		vp->v_mountf = NULL;
318 	}
319 }
320 
321 /*
322  * Create a vnode for a block device.
323  * Used for root filesystem, argdev, and swap areas.
324  * Also used for memory file system special devices.
325  */
326 bdevvp(dev, vpp)
327 	dev_t dev;
328 	struct vnode **vpp;
329 {
330 	register struct vnode *vp;
331 	struct vnode *nvp;
332 	int error;
333 
334 	error = getnewvnode(VT_NON, (struct mount *)0, &spec_vnodeops, &nvp);
335 	if (error) {
336 		*vpp = 0;
337 		return (error);
338 	}
339 	vp = nvp;
340 	vp->v_type = VBLK;
341 	if (nvp = checkalias(vp, dev, (struct mount *)0)) {
342 		vput(vp);
343 		vp = nvp;
344 	}
345 	*vpp = vp;
346 	return (0);
347 }
348 
349 /*
350  * Check to see if the new vnode represents a special device
351  * for which we already have a vnode (either because of
352  * bdevvp() or because of a different vnode representing
353  * the same block device). If such an alias exists, deallocate
354  * the existing contents and return the aliased vnode. The
355  * caller is responsible for filling it with its new contents.
356  */
357 struct vnode *
358 checkalias(nvp, nvp_rdev, mp)
359 	register struct vnode *nvp;
360 	dev_t nvp_rdev;
361 	struct mount *mp;
362 {
363 	register struct vnode *vp;
364 	struct vnode **vpp;
365 
366 	if (nvp->v_type != VBLK && nvp->v_type != VCHR)
367 		return (NULLVP);
368 
369 	vpp = &speclisth[SPECHASH(nvp_rdev)];
370 loop:
371 	for (vp = *vpp; vp; vp = vp->v_specnext) {
372 		if (nvp_rdev != vp->v_rdev || nvp->v_type != vp->v_type)
373 			continue;
374 		/*
375 		 * Alias, but not in use, so flush it out.
376 		 */
377 		if (vp->v_usecount == 0) {
378 			vgone(vp);
379 			goto loop;
380 		}
381 		if (vget(vp))
382 			goto loop;
383 		break;
384 	}
385 	if (vp == NULL || vp->v_tag != VT_NON) {
386 		MALLOC(nvp->v_specinfo, struct specinfo *,
387 			sizeof(struct specinfo), M_VNODE, M_WAITOK);
388 		nvp->v_rdev = nvp_rdev;
389 		nvp->v_hashchain = vpp;
390 		nvp->v_specnext = *vpp;
391 		*vpp = nvp;
392 		if (vp != NULL) {
393 			nvp->v_flag |= VALIASED;
394 			vp->v_flag |= VALIASED;
395 			vput(vp);
396 		}
397 		return (NULLVP);
398 	}
399 	VOP_UNLOCK(vp);
400 	vclean(vp, 0);
401 	vp->v_op = nvp->v_op;
402 	vp->v_tag = nvp->v_tag;
403 	nvp->v_type = VNON;
404 	insmntque(vp, mp);
405 	return (vp);
406 }
407 
408 /*
409  * Grab a particular vnode from the free list, increment its
410  * reference count and lock it. The vnode lock bit is set the
411  * vnode is being eliminated in vgone. The process is awakened
412  * when the transition is completed, and an error returned to
413  * indicate that the vnode is no longer usable (possibly having
414  * been changed to a new file system type).
415  */
416 vget(vp)
417 	register struct vnode *vp;
418 {
419 	register struct vnode *vq;
420 
421 	if (vp->v_flag & VXLOCK) {
422 		vp->v_flag |= VXWANT;
423 		sleep((caddr_t)vp, PINOD);
424 		return (1);
425 	}
426 	if (vp->v_usecount == 0) {
427 		if (vq = vp->v_freef)
428 			vq->v_freeb = vp->v_freeb;
429 		else
430 			vfreet = vp->v_freeb;
431 		*vp->v_freeb = vq;
432 		vp->v_freef = NULL;
433 		vp->v_freeb = NULL;
434 	}
435 	VREF(vp);
436 	VOP_LOCK(vp);
437 	return (0);
438 }
439 
440 /*
441  * Vnode reference, just increment the count
442  */
443 void vref(vp)
444 	struct vnode *vp;
445 {
446 
447 	vp->v_usecount++;
448 }
449 
450 /*
451  * vput(), just unlock and vrele()
452  */
453 void vput(vp)
454 	register struct vnode *vp;
455 {
456 	VOP_UNLOCK(vp);
457 	vrele(vp);
458 }
459 
460 /*
461  * Vnode release.
462  * If count drops to zero, call inactive routine and return to freelist.
463  */
464 void vrele(vp)
465 	register struct vnode *vp;
466 {
467 
468 	if (vp == NULL)
469 		panic("vrele: null vp");
470 	vp->v_usecount--;
471 	if (vp->v_usecount < 0)
472 		vprint("vrele: bad ref count", vp);
473 	if (vp->v_usecount > 0)
474 		return;
475 	if (vfreeh == NULLVP) {
476 		/*
477 		 * insert into empty list
478 		 */
479 		vfreeh = vp;
480 		vp->v_freeb = &vfreeh;
481 	} else {
482 		/*
483 		 * insert at tail of list
484 		 */
485 		*vfreet = vp;
486 		vp->v_freeb = vfreet;
487 	}
488 	vp->v_freef = NULL;
489 	vfreet = &vp->v_freef;
490 	VOP_INACTIVE(vp);
491 }
492 
493 /*
494  * Page or buffer structure gets a reference.
495  */
496 vhold(vp)
497 	register struct vnode *vp;
498 {
499 
500 	vp->v_holdcnt++;
501 }
502 
503 /*
504  * Page or buffer structure frees a reference.
505  */
506 holdrele(vp)
507 	register struct vnode *vp;
508 {
509 
510 	if (vp->v_holdcnt <= 0)
511 		panic("holdrele: holdcnt");
512 	vp->v_holdcnt--;
513 }
514 
515 /*
516  * Remove any vnodes in the vnode table belonging to mount point mp.
517  *
518  * If MNT_NOFORCE is specified, there should not be any active ones,
519  * return error if any are found (nb: this is a user error, not a
520  * system error). If MNT_FORCE is specified, detach any active vnodes
521  * that are found.
522  */
523 int busyprt = 0;	/* patch to print out busy vnodes */
524 
525 vflush(mp, skipvp, flags)
526 	struct mount *mp;
527 	struct vnode *skipvp;
528 	int flags;
529 {
530 	register struct vnode *vp, *nvp;
531 	int busy = 0;
532 
533 	if ((mp->mnt_flag & MNT_MPBUSY) == 0)
534 		panic("vflush: not busy");
535 	for (vp = mp->mnt_mounth; vp; vp = nvp) {
536 		nvp = vp->v_mountf;
537 		/*
538 		 * Skip over a selected vnode.
539 		 */
540 		if (vp == skipvp)
541 			continue;
542 		/*
543 		 * Skip over a vnodes marked VSYSTEM.
544 		 */
545 		if ((flags & SKIPSYSTEM) && (vp->v_flag & VSYSTEM))
546 			continue;
547 		/*
548 		 * With v_usecount == 0, all we need to do is clear
549 		 * out the vnode data structures and we are done.
550 		 */
551 		if (vp->v_usecount == 0) {
552 			vgone(vp);
553 			continue;
554 		}
555 		/*
556 		 * For block or character devices, revert to an
557 		 * anonymous device. For all other files, just kill them.
558 		 */
559 		if (flags & FORCECLOSE) {
560 			if (vp->v_type != VBLK && vp->v_type != VCHR) {
561 				vgone(vp);
562 			} else {
563 				vclean(vp, 0);
564 				vp->v_op = &spec_vnodeops;
565 				insmntque(vp, (struct mount *)0);
566 			}
567 			continue;
568 		}
569 		if (busyprt)
570 			vprint("vflush: busy vnode", vp);
571 		busy++;
572 	}
573 	if (busy)
574 		return (EBUSY);
575 	return (0);
576 }
577 
578 /*
579  * Disassociate the underlying file system from a vnode.
580  */
581 void vclean(vp, flags)
582 	register struct vnode *vp;
583 	long flags;
584 {
585 	struct vnodeops *origops;
586 	int active;
587 
588 	/*
589 	 * Check to see if the vnode is in use.
590 	 * If so we have to reference it before we clean it out
591 	 * so that its count cannot fall to zero and generate a
592 	 * race against ourselves to recycle it.
593 	 */
594 	if (active = vp->v_usecount)
595 		VREF(vp);
596 	/*
597 	 * Prevent the vnode from being recycled or
598 	 * brought into use while we clean it out.
599 	 */
600 	if (vp->v_flag & VXLOCK)
601 		panic("vclean: deadlock");
602 	vp->v_flag |= VXLOCK;
603 	/*
604 	 * Even if the count is zero, the VOP_INACTIVE routine may still
605 	 * have the object locked while it cleans it out. The VOP_LOCK
606 	 * ensures that the VOP_INACTIVE routine is done with its work.
607 	 * For active vnodes, it ensures that no other activity can
608 	 * occur while the buffer list is being cleaned out.
609 	 */
610 	VOP_LOCK(vp);
611 	if (flags & DOCLOSE)
612 		vinvalbuf(vp, 1);
613 	/*
614 	 * Prevent any further operations on the vnode from
615 	 * being passed through to the old file system.
616 	 */
617 	origops = vp->v_op;
618 	vp->v_op = &dead_vnodeops;
619 	vp->v_tag = VT_NON;
620 	/*
621 	 * If purging an active vnode, it must be unlocked, closed,
622 	 * and deactivated before being reclaimed.
623 	 */
624 	(*(origops->vn_unlock))(vp);
625 	if (active) {
626 		if (flags & DOCLOSE)
627 			(*(origops->vn_close))(vp, 0, NOCRED);
628 		(*(origops->vn_inactive))(vp);
629 	}
630 	/*
631 	 * Reclaim the vnode.
632 	 */
633 	if ((*(origops->vn_reclaim))(vp))
634 		panic("vclean: cannot reclaim");
635 	if (active)
636 		vrele(vp);
637 	/*
638 	 * Done with purge, notify sleepers in vget of the grim news.
639 	 */
640 	vp->v_flag &= ~VXLOCK;
641 	if (vp->v_flag & VXWANT) {
642 		vp->v_flag &= ~VXWANT;
643 		wakeup((caddr_t)vp);
644 	}
645 }
646 
647 /*
648  * Eliminate all activity associated with  the requested vnode
649  * and with all vnodes aliased to the requested vnode.
650  */
651 void vgoneall(vp)
652 	register struct vnode *vp;
653 {
654 	register struct vnode *vq;
655 
656 	if (vp->v_flag & VALIASED) {
657 		/*
658 		 * If a vgone (or vclean) is already in progress,
659 		 * wait until it is done and return.
660 		 */
661 		if (vp->v_flag & VXLOCK) {
662 			vp->v_flag |= VXWANT;
663 			sleep((caddr_t)vp, PINOD);
664 			return;
665 		}
666 		/*
667 		 * Ensure that vp will not be vgone'd while we
668 		 * are eliminating its aliases.
669 		 */
670 		vp->v_flag |= VXLOCK;
671 		while (vp->v_flag & VALIASED) {
672 			for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
673 				if (vq->v_rdev != vp->v_rdev ||
674 				    vq->v_type != vp->v_type || vp == vq)
675 					continue;
676 				vgone(vq);
677 				break;
678 			}
679 		}
680 		/*
681 		 * Remove the lock so that vgone below will
682 		 * really eliminate the vnode after which time
683 		 * vgone will awaken any sleepers.
684 		 */
685 		vp->v_flag &= ~VXLOCK;
686 	}
687 	vgone(vp);
688 }
689 
690 /*
691  * Eliminate all activity associated with a vnode
692  * in preparation for reuse.
693  */
694 void vgone(vp)
695 	register struct vnode *vp;
696 {
697 	register struct vnode *vq;
698 	struct vnode *vx;
699 	long count;
700 
701 	/*
702 	 * If a vgone (or vclean) is already in progress,
703 	 * wait until it is done and return.
704 	 */
705 	if (vp->v_flag & VXLOCK) {
706 		vp->v_flag |= VXWANT;
707 		sleep((caddr_t)vp, PINOD);
708 		return;
709 	}
710 	/*
711 	 * Clean out the filesystem specific data.
712 	 */
713 	vclean(vp, DOCLOSE);
714 	/*
715 	 * Delete from old mount point vnode list, if on one.
716 	 */
717 	if (vp->v_mountb) {
718 		if (vq = vp->v_mountf)
719 			vq->v_mountb = vp->v_mountb;
720 		*vp->v_mountb = vq;
721 		vp->v_mountf = NULL;
722 		vp->v_mountb = NULL;
723 	}
724 	/*
725 	 * If special device, remove it from special device alias list.
726 	 */
727 	if (vp->v_type == VBLK || vp->v_type == VCHR) {
728 		if (*vp->v_hashchain == vp) {
729 			*vp->v_hashchain = vp->v_specnext;
730 		} else {
731 			for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
732 				if (vq->v_specnext != vp)
733 					continue;
734 				vq->v_specnext = vp->v_specnext;
735 				break;
736 			}
737 			if (vq == NULL)
738 				panic("missing bdev");
739 		}
740 		if (vp->v_flag & VALIASED) {
741 			count = 0;
742 			for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
743 				if (vq->v_rdev != vp->v_rdev ||
744 				    vq->v_type != vp->v_type)
745 					continue;
746 				count++;
747 				vx = vq;
748 			}
749 			if (count == 0)
750 				panic("missing alias");
751 			if (count == 1)
752 				vx->v_flag &= ~VALIASED;
753 			vp->v_flag &= ~VALIASED;
754 		}
755 		FREE(vp->v_specinfo, M_VNODE);
756 		vp->v_specinfo = NULL;
757 	}
758 	/*
759 	 * If it is on the freelist, move it to the head of the list.
760 	 */
761 	if (vp->v_freeb) {
762 		if (vq = vp->v_freef)
763 			vq->v_freeb = vp->v_freeb;
764 		else
765 			vfreet = vp->v_freeb;
766 		*vp->v_freeb = vq;
767 		vp->v_freef = vfreeh;
768 		vp->v_freeb = &vfreeh;
769 		vfreeh->v_freeb = &vp->v_freef;
770 		vfreeh = vp;
771 	}
772 	vp->v_type = VBAD;
773 }
774 
775 /*
776  * Lookup a vnode by device number.
777  */
778 vfinddev(dev, type, vpp)
779 	dev_t dev;
780 	enum vtype type;
781 	struct vnode **vpp;
782 {
783 	register struct vnode *vp;
784 
785 	for (vp = speclisth[SPECHASH(dev)]; vp; vp = vp->v_specnext) {
786 		if (dev != vp->v_rdev || type != vp->v_type)
787 			continue;
788 		*vpp = vp;
789 		return (0);
790 	}
791 	return (1);
792 }
793 
794 /*
795  * Calculate the total number of references to a special device.
796  */
797 vcount(vp)
798 	register struct vnode *vp;
799 {
800 	register struct vnode *vq;
801 	int count;
802 
803 	if ((vp->v_flag & VALIASED) == 0)
804 		return (vp->v_usecount);
805 loop:
806 	for (count = 0, vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
807 		if (vq->v_rdev != vp->v_rdev || vq->v_type != vp->v_type)
808 			continue;
809 		/*
810 		 * Alias, but not in use, so flush it out.
811 		 */
812 		if (vq->v_usecount == 0) {
813 			vgone(vq);
814 			goto loop;
815 		}
816 		count += vq->v_usecount;
817 	}
818 	return (count);
819 }
820 
821 /*
822  * Print out a description of a vnode.
823  */
824 static char *typename[] =
825    { "VNON", "VREG", "VDIR", "VBLK", "VCHR", "VLNK", "VSOCK", "VFIFO", "VBAD" };
826 
827 vprint(label, vp)
828 	char *label;
829 	register struct vnode *vp;
830 {
831 	char buf[64];
832 
833 	if (label != NULL)
834 		printf("%s: ", label);
835 	printf("type %s, usecount %d, refcount %d,", typename[vp->v_type],
836 		vp->v_usecount, vp->v_holdcnt);
837 	buf[0] = '\0';
838 	if (vp->v_flag & VROOT)
839 		strcat(buf, "|VROOT");
840 	if (vp->v_flag & VTEXT)
841 		strcat(buf, "|VTEXT");
842 	if (vp->v_flag & VSYSTEM)
843 		strcat(buf, "|VSYSTEM");
844 	if (vp->v_flag & VEXLOCK)
845 		strcat(buf, "|VEXLOCK");
846 	if (vp->v_flag & VSHLOCK)
847 		strcat(buf, "|VSHLOCK");
848 	if (vp->v_flag & VLWAIT)
849 		strcat(buf, "|VLWAIT");
850 	if (vp->v_flag & VXLOCK)
851 		strcat(buf, "|VXLOCK");
852 	if (vp->v_flag & VXWANT)
853 		strcat(buf, "|VXWANT");
854 	if (vp->v_flag & VBWAIT)
855 		strcat(buf, "|VBWAIT");
856 	if (vp->v_flag & VALIASED)
857 		strcat(buf, "|VALIASED");
858 	if (buf[0] != '\0')
859 		printf(" flags (%s)", &buf[1]);
860 	printf("\n\t");
861 	VOP_PRINT(vp);
862 }
863 
864 int kinfo_vdebug = 1;
865 int kinfo_vgetfailed;
866 #define KINFO_VNODESLOP	10
867 /*
868  * Dump vnode list (via kinfo).
869  * Copyout address of vnode followed by vnode.
870  */
871 kinfo_vnode(op, where, acopysize, arg, aneeded)
872 	char *where;
873 	int *acopysize, *aneeded;
874 {
875 	register struct mount *mp = rootfs;
876 	register struct vnode *nextvp;
877 	struct mount *omp;
878 	struct vnode *vp;
879 	register needed = 0;
880 	register char *bp = where, *savebp;
881 	char *ewhere = where + *acopysize;
882 	int error;
883 
884 #define VPTRSZ	sizeof (struct vnode *)
885 #define VNODESZ	sizeof (struct vnode)
886 	if (where == NULL) {
887 		*aneeded = (numvnodes + KINFO_VNODESLOP) * (VPTRSZ + VNODESZ);
888 		return (0);
889 	}
890 
891 #define RETRY	bp = savebp ; goto again
892 	do {
893 		if (vfs_busy(mp)) {
894 			mp = mp->mnt_next;
895 			continue;
896 		}
897 		/*
898 		 * A vget can fail if the vnode is being
899 		 * recycled.  In this (rare) case, we have to start
900 		 * over with this filesystem.  Also, have to
901 		 * check that nextvp is still associated
902 		 * with this filesystem.  RACE: could have been
903 		 * recycled onto same filesystem.
904 		 */
905 		savebp = bp;
906 again:
907 		nextvp = mp->mnt_mounth;
908 		while (vp = nextvp) {
909 			if (vget(vp)) {
910 				if (kinfo_vdebug)
911 					printf("kinfo: vget failed\n");
912 				kinfo_vgetfailed++;
913 				RETRY;
914 			}
915 			if (vp->v_mount != mp) {
916 				if (kinfo_vdebug)
917 					printf("kinfo: vp changed\n");
918 				vput(vp);
919 				RETRY;
920 			}
921 			if ((bp + VPTRSZ + VNODESZ <= ewhere) &&
922 			    ((error = copyout((caddr_t)&vp, bp, VPTRSZ)) ||
923 			     (error = copyout((caddr_t)vp, bp + VPTRSZ,
924 			      VNODESZ)))) {
925 				vput(vp);
926 				return (error);
927 			}
928 			bp += VPTRSZ + VNODESZ;
929 			nextvp = vp->v_mountf;
930 			vput(vp);
931 		}
932 		omp = mp;
933 		mp = mp->mnt_next;
934 		vfs_unbusy(omp);
935 	} while (mp != rootfs);
936 
937 	*aneeded = bp - where;
938 	if (bp > ewhere)
939 		*acopysize = ewhere - where;
940 	else
941 		*acopysize = bp - where;
942 	return (0);
943 }
944