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