home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / kern / vfs_subr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-21  |  25.2 KB  |  1,186 lines

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