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