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