xref: /original-bsd/sys/kern/vfs_subr.c (revision 8fbb78b3)
1 /*
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)vfs_subr.c	7.60 (Berkeley) 06/21/91
8  */
9 
10 /*
11  * External virtual filesystem routines
12  */
13 
14 #include "param.h"
15 #include "proc.h"
16 #include "mount.h"
17 #include "time.h"
18 #include "vnode.h"
19 #include "specdev.h"
20 #include "namei.h"
21 #include "ucred.h"
22 #include "buf.h"
23 #include "errno.h"
24 #include "malloc.h"
25 
26 /*
27  * Remove a mount point from the list of mounted filesystems.
28  * Unmount of the root is illegal.
29  */
30 void
31 vfs_remove(mp)
32 	register struct mount *mp;
33 {
34 
35 	if (mp == rootfs)
36 		panic("vfs_remove: unmounting root");
37 	mp->mnt_prev->mnt_next = mp->mnt_next;
38 	mp->mnt_next->mnt_prev = mp->mnt_prev;
39 	mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
40 	vfs_unlock(mp);
41 }
42 
43 /*
44  * Lock a filesystem.
45  * Used to prevent access to it while mounting and unmounting.
46  */
47 vfs_lock(mp)
48 	register struct mount *mp;
49 {
50 
51 	while(mp->mnt_flag & MNT_MLOCK) {
52 		mp->mnt_flag |= MNT_MWAIT;
53 		sleep((caddr_t)mp, PVFS);
54 	}
55 	mp->mnt_flag |= MNT_MLOCK;
56 	return (0);
57 }
58 
59 /*
60  * Unlock a locked filesystem.
61  * Panic if filesystem is not locked.
62  */
63 void
64 vfs_unlock(mp)
65 	register struct mount *mp;
66 {
67 
68 	if ((mp->mnt_flag & MNT_MLOCK) == 0)
69 		panic("vfs_unlock: not locked");
70 	mp->mnt_flag &= ~MNT_MLOCK;
71 	if (mp->mnt_flag & MNT_MWAIT) {
72 		mp->mnt_flag &= ~MNT_MWAIT;
73 		wakeup((caddr_t)mp);
74 	}
75 }
76 
77 /*
78  * Mark a mount point as busy.
79  * Used to synchronize access and to delay unmounting.
80  */
81 vfs_busy(mp)
82 	register struct mount *mp;
83 {
84 
85 	while(mp->mnt_flag & MNT_MPBUSY) {
86 		mp->mnt_flag |= MNT_MPWANT;
87 		sleep((caddr_t)&mp->mnt_flag, PVFS);
88 	}
89 	if (mp->mnt_flag & MNT_UNMOUNT)
90 		return (1);
91 	mp->mnt_flag |= MNT_MPBUSY;
92 	return (0);
93 }
94 
95 /*
96  * Free a busy filesystem.
97  * Panic if filesystem is not busy.
98  */
99 vfs_unbusy(mp)
100 	register struct mount *mp;
101 {
102 
103 	if ((mp->mnt_flag & MNT_MPBUSY) == 0)
104 		panic("vfs_unbusy: not busy");
105 	mp->mnt_flag &= ~MNT_MPBUSY;
106 	if (mp->mnt_flag & MNT_MPWANT) {
107 		mp->mnt_flag &= ~MNT_MPWANT;
108 		wakeup((caddr_t)&mp->mnt_flag);
109 	}
110 }
111 
112 /*
113  * Lookup a mount point by filesystem identifier.
114  */
115 struct mount *
116 getvfs(fsid)
117 	fsid_t *fsid;
118 {
119 	register struct mount *mp;
120 
121 	mp = rootfs;
122 	do {
123 		if (mp->mnt_stat.f_fsid.val[0] == fsid->val[0] &&
124 		    mp->mnt_stat.f_fsid.val[1] == fsid->val[1]) {
125 			return (mp);
126 		}
127 		mp = mp->mnt_next;
128 	} while (mp != rootfs);
129 	return ((struct mount *)0);
130 }
131 
132 /*
133  * Set vnode attributes to VNOVAL
134  */
135 void vattr_null(vap)
136 	register struct vattr *vap;
137 {
138 
139 	vap->va_type = VNON;
140 	vap->va_mode = vap->va_nlink = vap->va_uid = vap->va_gid =
141 		vap->va_fsid = vap->va_fileid = vap->va_size =
142 		vap->va_size_rsv = vap->va_blocksize = vap->va_rdev =
143 		vap->va_bytes = vap->va_bytes_rsv =
144 		vap->va_atime.tv_sec = vap->va_atime.tv_usec =
145 		vap->va_mtime.tv_sec = vap->va_mtime.tv_usec =
146 		vap->va_ctime.tv_sec = vap->va_ctime.tv_usec =
147 		vap->va_flags = vap->va_gen = VNOVAL;
148 }
149 
150 /*
151  * Routines having to do with the management of the vnode table.
152  */
153 struct vnode *vfreeh, **vfreet;
154 extern struct vnodeops dead_vnodeops, spec_vnodeops;
155 extern void vclean();
156 long numvnodes;
157 struct vattr va_null;
158 
159 /*
160  * Initialize the vnode structures and initialize each file system type.
161  */
162 vfsinit()
163 {
164 	struct vfsops **vfsp;
165 
166 	/*
167 	 * Initialize the vnode name cache
168 	 */
169 	nchinit();
170 	/*
171 	 * Initialize each file system type.
172 	 */
173 	vattr_null(&va_null);
174 	for (vfsp = &vfssw[0]; vfsp <= &vfssw[MOUNT_MAXTYPE]; vfsp++) {
175 		if (*vfsp == NULL)
176 			continue;
177 		(*(*vfsp)->vfs_init)();
178 	}
179 }
180 
181 /*
182  * Return the next vnode from the free list.
183  */
184 getnewvnode(tag, mp, vops, vpp)
185 	enum vtagtype tag;
186 	struct mount *mp;
187 	struct vnodeops *vops;
188 	struct vnode **vpp;
189 {
190 	register struct vnode *vp, *vq;
191 
192 	if (numvnodes < desiredvnodes) {
193 		vp = (struct vnode *)malloc((u_long)sizeof *vp,
194 		    M_VNODE, M_WAITOK);
195 		bzero((char *)vp, sizeof *vp);
196 		numvnodes++;
197 	} else {
198 		if ((vp = vfreeh) == NULL) {
199 			tablefull("vnode");
200 			*vpp = 0;
201 			return (ENFILE);
202 		}
203 		if (vp->v_usecount)
204 			panic("free vnode isn't");
205 		if (vq = vp->v_freef)
206 			vq->v_freeb = &vfreeh;
207 		else
208 			vfreet = &vfreeh;
209 		vfreeh = vq;
210 		vp->v_freef = NULL;
211 		vp->v_freeb = NULL;
212 		if (vp->v_type != VBAD)
213 			vgone(vp);
214 		vp->v_flag = 0;
215 		vp->v_lastr = 0;
216 		vp->v_socket = 0;
217 	}
218 	vp->v_type = VNON;
219 	cache_purge(vp);
220 	vp->v_tag = tag;
221 	vp->v_op = vops;
222 	insmntque(vp, mp);
223 	VREF(vp);
224 	*vpp = vp;
225 	return (0);
226 }
227 
228 /*
229  * Move a vnode from one mount queue to another.
230  */
231 insmntque(vp, mp)
232 	register struct vnode *vp;
233 	register struct mount *mp;
234 {
235 	register struct vnode *vq;
236 
237 	/*
238 	 * Delete from old mount point vnode list, if on one.
239 	 */
240 	if (vp->v_mountb) {
241 		if (vq = vp->v_mountf)
242 			vq->v_mountb = vp->v_mountb;
243 		*vp->v_mountb = vq;
244 	}
245 	/*
246 	 * Insert into list of vnodes for the new mount point, if available.
247 	 */
248 	vp->v_mount = mp;
249 	if (mp == NULL) {
250 		vp->v_mountf = NULL;
251 		vp->v_mountb = NULL;
252 		return;
253 	}
254 	if (vq = mp->mnt_mounth)
255 		vq->v_mountb = &vp->v_mountf;
256 	vp->v_mountf = vq;
257 	vp->v_mountb = &mp->mnt_mounth;
258 	mp->mnt_mounth = vp;
259 }
260 
261 /*
262  * Make sure all write-behind blocks associated
263  * with mount point are flushed out (from sync).
264  */
265 mntflushbuf(mountp, flags)
266 	struct mount *mountp;
267 	int flags;
268 {
269 	register struct vnode *vp;
270 
271 	if ((mountp->mnt_flag & MNT_MPBUSY) == 0)
272 		panic("mntflushbuf: not busy");
273 loop:
274 	for (vp = mountp->mnt_mounth; vp; vp = vp->v_mountf) {
275 		if (VOP_ISLOCKED(vp))
276 			continue;
277 		if (vget(vp))
278 			goto loop;
279 		vflushbuf(vp, flags);
280 		vput(vp);
281 		if (vp->v_mount != mountp)
282 			goto loop;
283 	}
284 }
285 
286 /*
287  * Flush all dirty buffers associated with a vnode.
288  */
289 vflushbuf(vp, flags)
290 	register struct vnode *vp;
291 	int flags;
292 {
293 	register struct buf *bp;
294 	struct buf *nbp;
295 	int s;
296 
297 loop:
298 	s = splbio();
299 	for (bp = vp->v_dirtyblkhd; bp; bp = nbp) {
300 		nbp = bp->b_blockf;
301 		if ((bp->b_flags & B_BUSY))
302 			continue;
303 		if ((bp->b_flags & B_DELWRI) == 0)
304 			panic("vflushbuf: not dirty");
305 		bremfree(bp);
306 		bp->b_flags |= B_BUSY;
307 		splx(s);
308 		/*
309 		 * Wait for I/O associated with indirect blocks to complete,
310 		 * since there is no way to quickly wait for them below.
311 		 * NB: This is really specific to ufs, but is done here
312 		 * as it is easier and quicker.
313 		 */
314 		if (bp->b_vp == vp || (flags & B_SYNC) == 0)
315 			(void) bawrite(bp);
316 		else
317 			(void) bwrite(bp);
318 		goto loop;
319 	}
320 	splx(s);
321 	if ((flags & B_SYNC) == 0)
322 		return;
323 	s = splbio();
324 	while (vp->v_numoutput) {
325 		vp->v_flag |= VBWAIT;
326 		sleep((caddr_t)&vp->v_numoutput, PRIBIO + 1);
327 	}
328 	splx(s);
329 	if (vp->v_dirtyblkhd) {
330 		vprint("vflushbuf: dirty", vp);
331 		goto loop;
332 	}
333 }
334 
335 /*
336  * Update outstanding I/O count and do wakeup if requested.
337  */
338 vwakeup(bp)
339 	register struct buf *bp;
340 {
341 	register struct vnode *vp;
342 
343 	bp->b_dirtyoff = bp->b_dirtyend = 0;
344 	if (vp = bp->b_vp) {
345 		vp->v_numoutput--;
346 		if ((vp->v_flag & VBWAIT) && vp->v_numoutput <= 0) {
347 			if (vp->v_numoutput < 0)
348 				panic("vwakeup: neg numoutput");
349 			vp->v_flag &= ~VBWAIT;
350 			wakeup((caddr_t)&vp->v_numoutput);
351 		}
352 	}
353 }
354 
355 /*
356  * Invalidate in core blocks belonging to closed or umounted filesystem
357  *
358  * Go through the list of vnodes associated with the file system;
359  * for each vnode invalidate any buffers that it holds. Normally
360  * this routine is preceeded by a bflush call, so that on a quiescent
361  * filesystem there will be no dirty buffers when we are done. Binval
362  * returns the count of dirty buffers when it is finished.
363  */
364 mntinvalbuf(mountp)
365 	struct mount *mountp;
366 {
367 	register struct vnode *vp;
368 	int dirty = 0;
369 
370 	if ((mountp->mnt_flag & MNT_MPBUSY) == 0)
371 		panic("mntinvalbuf: not busy");
372 loop:
373 	for (vp = mountp->mnt_mounth; vp; vp = vp->v_mountf) {
374 		if (vget(vp))
375 			goto loop;
376 		dirty += vinvalbuf(vp, 1);
377 		vput(vp);
378 		if (vp->v_mount != mountp)
379 			goto loop;
380 	}
381 	return (dirty);
382 }
383 
384 /*
385  * Flush out and invalidate all buffers associated with a vnode.
386  * Called with the underlying object locked.
387  */
388 vinvalbuf(vp, save)
389 	register struct vnode *vp;
390 	int save;
391 {
392 	register struct buf *bp;
393 	struct buf *nbp, *blist;
394 	int s, dirty = 0;
395 
396 	for (;;) {
397 		if (blist = vp->v_dirtyblkhd)
398 			/* void */;
399 		else if (blist = vp->v_cleanblkhd)
400 			/* void */;
401 		else
402 			break;
403 		for (bp = blist; bp; bp = nbp) {
404 			nbp = bp->b_blockf;
405 			s = splbio();
406 			if (bp->b_flags & B_BUSY) {
407 				bp->b_flags |= B_WANTED;
408 				sleep((caddr_t)bp, PRIBIO + 1);
409 				splx(s);
410 				break;
411 			}
412 			bremfree(bp);
413 			bp->b_flags |= B_BUSY;
414 			splx(s);
415 			if (save && (bp->b_flags & B_DELWRI)) {
416 				dirty++;
417 				(void) bwrite(bp);
418 				break;
419 			}
420 			if (bp->b_vp != vp)
421 				reassignbuf(bp, bp->b_vp);
422 			else
423 				bp->b_flags |= B_INVAL;
424 			brelse(bp);
425 		}
426 	}
427 	if (vp->v_dirtyblkhd || vp->v_cleanblkhd)
428 		panic("vinvalbuf: flush failed");
429 	return (dirty);
430 }
431 
432 /*
433  * Associate a buffer with a vnode.
434  */
435 bgetvp(vp, bp)
436 	register struct vnode *vp;
437 	register struct buf *bp;
438 {
439 	register struct vnode *vq;
440 	register struct buf *bq;
441 
442 	if (bp->b_vp)
443 		panic("bgetvp: not free");
444 	VHOLD(vp);
445 	bp->b_vp = vp;
446 	if (vp->v_type == VBLK || vp->v_type == VCHR)
447 		bp->b_dev = vp->v_rdev;
448 	else
449 		bp->b_dev = NODEV;
450 	/*
451 	 * Insert onto list for new vnode.
452 	 */
453 	if (bq = vp->v_cleanblkhd)
454 		bq->b_blockb = &bp->b_blockf;
455 	bp->b_blockf = bq;
456 	bp->b_blockb = &vp->v_cleanblkhd;
457 	vp->v_cleanblkhd = bp;
458 }
459 
460 /*
461  * Disassociate a buffer from a vnode.
462  */
463 brelvp(bp)
464 	register struct buf *bp;
465 {
466 	struct buf *bq;
467 	struct vnode *vp;
468 
469 	if (bp->b_vp == (struct vnode *) 0)
470 		panic("brelvp: NULL");
471 	/*
472 	 * Delete from old vnode list, if on one.
473 	 */
474 	if (bp->b_blockb) {
475 		if (bq = bp->b_blockf)
476 			bq->b_blockb = bp->b_blockb;
477 		*bp->b_blockb = bq;
478 		bp->b_blockf = NULL;
479 		bp->b_blockb = NULL;
480 	}
481 	vp = bp->b_vp;
482 	bp->b_vp = (struct vnode *) 0;
483 	HOLDRELE(vp);
484 }
485 
486 /*
487  * Reassign a buffer from one vnode to another.
488  * Used to assign file specific control information
489  * (indirect blocks) to the vnode to which they belong.
490  */
491 reassignbuf(bp, newvp)
492 	register struct buf *bp;
493 	register struct vnode *newvp;
494 {
495 	register struct buf *bq, **listheadp;
496 
497 	if (newvp == NULL)
498 		panic("reassignbuf: NULL");
499 	/*
500 	 * Delete from old vnode list, if on one.
501 	 */
502 	if (bp->b_blockb) {
503 		if (bq = bp->b_blockf)
504 			bq->b_blockb = bp->b_blockb;
505 		*bp->b_blockb = bq;
506 	}
507 	/*
508 	 * If dirty, put on list of dirty buffers;
509 	 * otherwise insert onto list of clean buffers.
510 	 */
511 	if (bp->b_flags & B_DELWRI)
512 		listheadp = &newvp->v_dirtyblkhd;
513 	else
514 		listheadp = &newvp->v_cleanblkhd;
515 	if (bq = *listheadp)
516 		bq->b_blockb = &bp->b_blockf;
517 	bp->b_blockf = bq;
518 	bp->b_blockb = listheadp;
519 	*listheadp = bp;
520 }
521 
522 /*
523  * Create a vnode for a block device.
524  * Used for root filesystem, argdev, and swap areas.
525  * Also used for memory file system special devices.
526  */
527 bdevvp(dev, vpp)
528 	dev_t dev;
529 	struct vnode **vpp;
530 {
531 	register struct vnode *vp;
532 	struct vnode *nvp;
533 	int error;
534 
535 	if (dev == NODEV)
536 		return (0);
537 	error = getnewvnode(VT_NON, (struct mount *)0, &spec_vnodeops, &nvp);
538 	if (error) {
539 		*vpp = 0;
540 		return (error);
541 	}
542 	vp = nvp;
543 	vp->v_type = VBLK;
544 	if (nvp = checkalias(vp, dev, (struct mount *)0)) {
545 		vput(vp);
546 		vp = nvp;
547 	}
548 	*vpp = vp;
549 	return (0);
550 }
551 
552 /*
553  * Check to see if the new vnode represents a special device
554  * for which we already have a vnode (either because of
555  * bdevvp() or because of a different vnode representing
556  * the same block device). If such an alias exists, deallocate
557  * the existing contents and return the aliased vnode. The
558  * caller is responsible for filling it with its new contents.
559  */
560 struct vnode *
561 checkalias(nvp, nvp_rdev, mp)
562 	register struct vnode *nvp;
563 	dev_t nvp_rdev;
564 	struct mount *mp;
565 {
566 	register struct vnode *vp;
567 	struct vnode **vpp;
568 
569 	if (nvp->v_type != VBLK && nvp->v_type != VCHR)
570 		return (NULLVP);
571 
572 	vpp = &speclisth[SPECHASH(nvp_rdev)];
573 loop:
574 	for (vp = *vpp; vp; vp = vp->v_specnext) {
575 		if (nvp_rdev != vp->v_rdev || nvp->v_type != vp->v_type)
576 			continue;
577 		/*
578 		 * Alias, but not in use, so flush it out.
579 		 */
580 		if (vp->v_usecount == 0) {
581 			vgone(vp);
582 			goto loop;
583 		}
584 		if (vget(vp))
585 			goto loop;
586 		break;
587 	}
588 	if (vp == NULL || vp->v_tag != VT_NON) {
589 		MALLOC(nvp->v_specinfo, struct specinfo *,
590 			sizeof(struct specinfo), M_VNODE, M_WAITOK);
591 		nvp->v_rdev = nvp_rdev;
592 		nvp->v_hashchain = vpp;
593 		nvp->v_specnext = *vpp;
594 		nvp->v_specflags = 0;
595 		*vpp = nvp;
596 		if (vp != NULL) {
597 			nvp->v_flag |= VALIASED;
598 			vp->v_flag |= VALIASED;
599 			vput(vp);
600 		}
601 		return (NULLVP);
602 	}
603 	VOP_UNLOCK(vp);
604 	vclean(vp, 0);
605 	vp->v_op = nvp->v_op;
606 	vp->v_tag = nvp->v_tag;
607 	nvp->v_type = VNON;
608 	insmntque(vp, mp);
609 	return (vp);
610 }
611 
612 /*
613  * Grab a particular vnode from the free list, increment its
614  * reference count and lock it. The vnode lock bit is set the
615  * vnode is being eliminated in vgone. The process is awakened
616  * when the transition is completed, and an error returned to
617  * indicate that the vnode is no longer usable (possibly having
618  * been changed to a new file system type).
619  */
620 vget(vp)
621 	register struct vnode *vp;
622 {
623 	register struct vnode *vq;
624 
625 	if (vp->v_flag & VXLOCK) {
626 		vp->v_flag |= VXWANT;
627 		sleep((caddr_t)vp, PINOD);
628 		return (1);
629 	}
630 	if (vp->v_usecount == 0) {
631 		if (vq = vp->v_freef)
632 			vq->v_freeb = vp->v_freeb;
633 		else
634 			vfreet = vp->v_freeb;
635 		*vp->v_freeb = vq;
636 		vp->v_freef = NULL;
637 		vp->v_freeb = NULL;
638 	}
639 	VREF(vp);
640 	VOP_LOCK(vp);
641 	return (0);
642 }
643 
644 /*
645  * Vnode reference, just increment the count
646  */
647 void vref(vp)
648 	struct vnode *vp;
649 {
650 
651 	vp->v_usecount++;
652 }
653 
654 /*
655  * vput(), just unlock and vrele()
656  */
657 void vput(vp)
658 	register struct vnode *vp;
659 {
660 	VOP_UNLOCK(vp);
661 	vrele(vp);
662 }
663 
664 /*
665  * Vnode release.
666  * If count drops to zero, call inactive routine and return to freelist.
667  */
668 void vrele(vp)
669 	register struct vnode *vp;
670 {
671 	struct proc *p = curproc;		/* XXX */
672 
673 #ifdef DIAGNOSTIC
674 	if (vp == NULL)
675 		panic("vrele: null vp");
676 #endif
677 	vp->v_usecount--;
678 	if (vp->v_usecount > 0)
679 		return;
680 #ifdef DIAGNOSTIC
681 	if (vp->v_usecount != 0 || vp->v_writecount != 0) {
682 		vprint("vrele: bad ref count", vp);
683 		panic("vrele: ref cnt");
684 	}
685 #endif
686 	if (vfreeh == NULLVP) {
687 		/*
688 		 * insert into empty list
689 		 */
690 		vfreeh = vp;
691 		vp->v_freeb = &vfreeh;
692 	} else {
693 		/*
694 		 * insert at tail of list
695 		 */
696 		*vfreet = vp;
697 		vp->v_freeb = vfreet;
698 	}
699 	vp->v_freef = NULL;
700 	vfreet = &vp->v_freef;
701 	VOP_INACTIVE(vp, p);
702 }
703 
704 /*
705  * Page or buffer structure gets a reference.
706  */
707 vhold(vp)
708 	register struct vnode *vp;
709 {
710 
711 	vp->v_holdcnt++;
712 }
713 
714 /*
715  * Page or buffer structure frees a reference.
716  */
717 holdrele(vp)
718 	register struct vnode *vp;
719 {
720 
721 	if (vp->v_holdcnt <= 0)
722 		panic("holdrele: holdcnt");
723 	vp->v_holdcnt--;
724 }
725 
726 /*
727  * Remove any vnodes in the vnode table belonging to mount point mp.
728  *
729  * If MNT_NOFORCE is specified, there should not be any active ones,
730  * return error if any are found (nb: this is a user error, not a
731  * system error). If MNT_FORCE is specified, detach any active vnodes
732  * that are found.
733  */
734 int busyprt = 0;	/* patch to print out busy vnodes */
735 
736 vflush(mp, skipvp, flags)
737 	struct mount *mp;
738 	struct vnode *skipvp;
739 	int flags;
740 {
741 	register struct vnode *vp, *nvp;
742 	int busy = 0;
743 
744 	if ((mp->mnt_flag & MNT_MPBUSY) == 0)
745 		panic("vflush: not busy");
746 loop:
747 	for (vp = mp->mnt_mounth; vp; vp = nvp) {
748 		if (vp->v_mount != mp)
749 			goto loop;
750 		nvp = vp->v_mountf;
751 		/*
752 		 * Skip over a selected vnode.
753 		 */
754 		if (vp == skipvp)
755 			continue;
756 		/*
757 		 * Skip over a vnodes marked VSYSTEM.
758 		 */
759 		if ((flags & SKIPSYSTEM) && (vp->v_flag & VSYSTEM))
760 			continue;
761 		/*
762 		 * With v_usecount == 0, all we need to do is clear
763 		 * out the vnode data structures and we are done.
764 		 */
765 		if (vp->v_usecount == 0) {
766 			vgone(vp);
767 			continue;
768 		}
769 		/*
770 		 * For block or character devices, revert to an
771 		 * anonymous device. For all other files, just kill them.
772 		 */
773 		if (flags & FORCECLOSE) {
774 			if (vp->v_type != VBLK && vp->v_type != VCHR) {
775 				vgone(vp);
776 			} else {
777 				vclean(vp, 0);
778 				vp->v_op = &spec_vnodeops;
779 				insmntque(vp, (struct mount *)0);
780 			}
781 			continue;
782 		}
783 		if (busyprt)
784 			vprint("vflush: busy vnode", vp);
785 		busy++;
786 	}
787 	if (busy)
788 		return (EBUSY);
789 	return (0);
790 }
791 
792 /*
793  * Disassociate the underlying file system from a vnode.
794  */
795 void vclean(vp, flags)
796 	register struct vnode *vp;
797 	int flags;
798 {
799 	struct vnodeops *origops;
800 	int active;
801 	struct proc *p = curproc;	/* XXX */
802 
803 	/*
804 	 * Check to see if the vnode is in use.
805 	 * If so we have to reference it before we clean it out
806 	 * so that its count cannot fall to zero and generate a
807 	 * race against ourselves to recycle it.
808 	 */
809 	if (active = vp->v_usecount)
810 		VREF(vp);
811 	/*
812 	 * Prevent the vnode from being recycled or
813 	 * brought into use while we clean it out.
814 	 */
815 	if (vp->v_flag & VXLOCK)
816 		panic("vclean: deadlock");
817 	vp->v_flag |= VXLOCK;
818 	/*
819 	 * Even if the count is zero, the VOP_INACTIVE routine may still
820 	 * have the object locked while it cleans it out. The VOP_LOCK
821 	 * ensures that the VOP_INACTIVE routine is done with its work.
822 	 * For active vnodes, it ensures that no other activity can
823 	 * occur while the buffer list is being cleaned out.
824 	 */
825 	VOP_LOCK(vp);
826 	if (flags & DOCLOSE)
827 		vinvalbuf(vp, 1);
828 	/*
829 	 * Prevent any further operations on the vnode from
830 	 * being passed through to the old file system.
831 	 */
832 	origops = vp->v_op;
833 	vp->v_op = &dead_vnodeops;
834 	vp->v_tag = VT_NON;
835 	/*
836 	 * If purging an active vnode, it must be unlocked, closed,
837 	 * and deactivated before being reclaimed.
838 	 */
839 	(*(origops->vop_unlock))(vp);
840 	if (active) {
841 		if (flags & DOCLOSE)
842 			(*(origops->vop_close))(vp, IO_NDELAY, NOCRED, p);
843 		(*(origops->vop_inactive))(vp, p);
844 	}
845 	/*
846 	 * Reclaim the vnode.
847 	 */
848 	if ((*(origops->vop_reclaim))(vp))
849 		panic("vclean: cannot reclaim");
850 	if (active)
851 		vrele(vp);
852 	/*
853 	 * Done with purge, notify sleepers in vget of the grim news.
854 	 */
855 	vp->v_flag &= ~VXLOCK;
856 	if (vp->v_flag & VXWANT) {
857 		vp->v_flag &= ~VXWANT;
858 		wakeup((caddr_t)vp);
859 	}
860 }
861 
862 /*
863  * Eliminate all activity associated with  the requested vnode
864  * and with all vnodes aliased to the requested vnode.
865  */
866 void vgoneall(vp)
867 	register struct vnode *vp;
868 {
869 	register struct vnode *vq;
870 
871 	if (vp->v_flag & VALIASED) {
872 		/*
873 		 * If a vgone (or vclean) is already in progress,
874 		 * wait until it is done and return.
875 		 */
876 		if (vp->v_flag & VXLOCK) {
877 			vp->v_flag |= VXWANT;
878 			sleep((caddr_t)vp, PINOD);
879 			return;
880 		}
881 		/*
882 		 * Ensure that vp will not be vgone'd while we
883 		 * are eliminating its aliases.
884 		 */
885 		vp->v_flag |= VXLOCK;
886 		while (vp->v_flag & VALIASED) {
887 			for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
888 				if (vq->v_rdev != vp->v_rdev ||
889 				    vq->v_type != vp->v_type || vp == vq)
890 					continue;
891 				vgone(vq);
892 				break;
893 			}
894 		}
895 		/*
896 		 * Remove the lock so that vgone below will
897 		 * really eliminate the vnode after which time
898 		 * vgone will awaken any sleepers.
899 		 */
900 		vp->v_flag &= ~VXLOCK;
901 	}
902 	vgone(vp);
903 }
904 
905 /*
906  * Eliminate all activity associated with a vnode
907  * in preparation for reuse.
908  */
909 void vgone(vp)
910 	register struct vnode *vp;
911 {
912 	register struct vnode *vq;
913 	struct vnode *vx;
914 	long count;
915 
916 	/*
917 	 * If a vgone (or vclean) is already in progress,
918 	 * wait until it is done and return.
919 	 */
920 	if (vp->v_flag & VXLOCK) {
921 		vp->v_flag |= VXWANT;
922 		sleep((caddr_t)vp, PINOD);
923 		return;
924 	}
925 	/*
926 	 * Clean out the filesystem specific data.
927 	 */
928 	vclean(vp, DOCLOSE);
929 	/*
930 	 * Delete from old mount point vnode list, if on one.
931 	 */
932 	if (vp->v_mountb) {
933 		if (vq = vp->v_mountf)
934 			vq->v_mountb = vp->v_mountb;
935 		*vp->v_mountb = vq;
936 		vp->v_mountf = NULL;
937 		vp->v_mountb = NULL;
938 	}
939 	/*
940 	 * If special device, remove it from special device alias list.
941 	 */
942 	if (vp->v_type == VBLK || vp->v_type == VCHR) {
943 		if (*vp->v_hashchain == vp) {
944 			*vp->v_hashchain = vp->v_specnext;
945 		} else {
946 			for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
947 				if (vq->v_specnext != vp)
948 					continue;
949 				vq->v_specnext = vp->v_specnext;
950 				break;
951 			}
952 			if (vq == NULL)
953 				panic("missing bdev");
954 		}
955 		if (vp->v_flag & VALIASED) {
956 			count = 0;
957 			for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
958 				if (vq->v_rdev != vp->v_rdev ||
959 				    vq->v_type != vp->v_type)
960 					continue;
961 				count++;
962 				vx = vq;
963 			}
964 			if (count == 0)
965 				panic("missing alias");
966 			if (count == 1)
967 				vx->v_flag &= ~VALIASED;
968 			vp->v_flag &= ~VALIASED;
969 		}
970 		FREE(vp->v_specinfo, M_VNODE);
971 		vp->v_specinfo = NULL;
972 	}
973 	/*
974 	 * If it is on the freelist, move it to the head of the list.
975 	 */
976 	if (vp->v_freeb) {
977 		if (vq = vp->v_freef)
978 			vq->v_freeb = vp->v_freeb;
979 		else
980 			vfreet = vp->v_freeb;
981 		*vp->v_freeb = vq;
982 		vp->v_freef = vfreeh;
983 		vp->v_freeb = &vfreeh;
984 		vfreeh->v_freeb = &vp->v_freef;
985 		vfreeh = vp;
986 	}
987 	vp->v_type = VBAD;
988 }
989 
990 /*
991  * Lookup a vnode by device number.
992  */
993 vfinddev(dev, type, vpp)
994 	dev_t dev;
995 	enum vtype type;
996 	struct vnode **vpp;
997 {
998 	register struct vnode *vp;
999 
1000 	for (vp = speclisth[SPECHASH(dev)]; vp; vp = vp->v_specnext) {
1001 		if (dev != vp->v_rdev || type != vp->v_type)
1002 			continue;
1003 		*vpp = vp;
1004 		return (0);
1005 	}
1006 	return (1);
1007 }
1008 
1009 /*
1010  * Calculate the total number of references to a special device.
1011  */
1012 vcount(vp)
1013 	register struct vnode *vp;
1014 {
1015 	register struct vnode *vq;
1016 	int count;
1017 
1018 	if ((vp->v_flag & VALIASED) == 0)
1019 		return (vp->v_usecount);
1020 loop:
1021 	for (count = 0, vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
1022 		if (vq->v_rdev != vp->v_rdev || vq->v_type != vp->v_type)
1023 			continue;
1024 		/*
1025 		 * Alias, but not in use, so flush it out.
1026 		 */
1027 		if (vq->v_usecount == 0) {
1028 			vgone(vq);
1029 			goto loop;
1030 		}
1031 		count += vq->v_usecount;
1032 	}
1033 	return (count);
1034 }
1035 
1036 /*
1037  * Print out a description of a vnode.
1038  */
1039 static char *typename[] =
1040    { "VNON", "VREG", "VDIR", "VBLK", "VCHR", "VLNK", "VSOCK", "VFIFO", "VBAD" };
1041 
1042 vprint(label, vp)
1043 	char *label;
1044 	register struct vnode *vp;
1045 {
1046 	char buf[64];
1047 
1048 	if (label != NULL)
1049 		printf("%s: ", label);
1050 	printf("type %s, usecount %d, writecount %d, refcount %d,",
1051 		typename[vp->v_type], vp->v_usecount, vp->v_writecount,
1052 		vp->v_holdcnt);
1053 	buf[0] = '\0';
1054 	if (vp->v_flag & VROOT)
1055 		strcat(buf, "|VROOT");
1056 	if (vp->v_flag & VTEXT)
1057 		strcat(buf, "|VTEXT");
1058 	if (vp->v_flag & VSYSTEM)
1059 		strcat(buf, "|VSYSTEM");
1060 	if (vp->v_flag & VXLOCK)
1061 		strcat(buf, "|VXLOCK");
1062 	if (vp->v_flag & VXWANT)
1063 		strcat(buf, "|VXWANT");
1064 	if (vp->v_flag & VBWAIT)
1065 		strcat(buf, "|VBWAIT");
1066 	if (vp->v_flag & VALIASED)
1067 		strcat(buf, "|VALIASED");
1068 	if (buf[0] != '\0')
1069 		printf(" flags (%s)", &buf[1]);
1070 	printf("\n\t");
1071 	VOP_PRINT(vp);
1072 }
1073 
1074 #ifdef DEBUG
1075 /*
1076  * List all of the locked vnodes in the system.
1077  * Called when debugging the kernel.
1078  */
1079 printlockedvnodes()
1080 {
1081 	register struct mount *mp;
1082 	register struct vnode *vp;
1083 
1084 	printf("Locked vnodes\n");
1085 	mp = rootfs;
1086 	do {
1087 		for (vp = mp->mnt_mounth; vp; vp = vp->v_mountf)
1088 			if (VOP_ISLOCKED(vp))
1089 				vprint((char *)0, vp);
1090 		mp = mp->mnt_next;
1091 	} while (mp != rootfs);
1092 }
1093 #endif
1094 
1095 int kinfo_vdebug = 1;
1096 int kinfo_vgetfailed;
1097 #define KINFO_VNODESLOP	10
1098 /*
1099  * Dump vnode list (via kinfo).
1100  * Copyout address of vnode followed by vnode.
1101  */
1102 /* ARGSUSED */
1103 kinfo_vnode(op, where, acopysize, arg, aneeded)
1104 	int op;
1105 	char *where;
1106 	int *acopysize, arg, *aneeded;
1107 {
1108 	register struct mount *mp = rootfs;
1109 	struct mount *omp;
1110 	struct vnode *vp;
1111 	register char *bp = where, *savebp;
1112 	char *ewhere = where + *acopysize;
1113 	int error;
1114 
1115 #define VPTRSZ	sizeof (struct vnode *)
1116 #define VNODESZ	sizeof (struct vnode)
1117 	if (where == NULL) {
1118 		*aneeded = (numvnodes + KINFO_VNODESLOP) * (VPTRSZ + VNODESZ);
1119 		return (0);
1120 	}
1121 
1122 	do {
1123 		if (vfs_busy(mp)) {
1124 			mp = mp->mnt_next;
1125 			continue;
1126 		}
1127 		savebp = bp;
1128 again:
1129 		for (vp = mp->mnt_mounth; vp; vp = vp->v_mountf) {
1130 			/*
1131 			 * Check that the vp is still associated with
1132 			 * this filesystem.  RACE: could have been
1133 			 * recycled onto the same filesystem.
1134 			 */
1135 			if (vp->v_mount != mp) {
1136 				if (kinfo_vdebug)
1137 					printf("kinfo: vp changed\n");
1138 				bp = savebp;
1139 				goto again;
1140 			}
1141 			if ((bp + VPTRSZ + VNODESZ <= ewhere) &&
1142 			    ((error = copyout((caddr_t)&vp, bp, VPTRSZ)) ||
1143 			     (error = copyout((caddr_t)vp, bp + VPTRSZ,
1144 			      VNODESZ))))
1145 				return (error);
1146 			bp += VPTRSZ + VNODESZ;
1147 		}
1148 		omp = mp;
1149 		mp = mp->mnt_next;
1150 		vfs_unbusy(omp);
1151 	} while (mp != rootfs);
1152 
1153 	*aneeded = bp - where;
1154 	if (bp > ewhere)
1155 		*acopysize = ewhere - where;
1156 	else
1157 		*acopysize = bp - where;
1158 	return (0);
1159 }
1160