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