Use SYSREF to reference count struct vnode. v_usecount is now
authorMatthew Dillon <dillon@dragonflybsd.org>
Sun, 6 May 2007 19:23:36 +0000 (19:23 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Sun, 6 May 2007 19:23:36 +0000 (19:23 +0000)
v_sysref(.refcnt).  v_holdcnt is now v_auxrefs.  SYSREF's termination state
(using a negative reference count from -0x40000000+) now places the vnode in
a VCACHED or VFREE state and deactivates it.  The vnode is now assigned a
64 bit unique id via SYSREF.

vhold() (which manipulates v_auxrefs) no longer reactivates a vnode and
is explicitly used only to track references from auxillary structures
and references to prevent premature destruction of the vnode.  vdrop()
will now only move a vnode from VCACHED to VFREE on the 1->0 transition
of v_auxrefs if the vnode is in a termination state.

vref() will now panic if used on a vnode in a termination state.  vget()
must now be used to explicitly reactivate a vnode.  These requirements
existed before but are now explicitly asserted.

vlrureclaim() and allocvnode() should now interact a bit better.  In
particular, vlrureclaim() will do a better job of finding vnodes to flush
and transition from VCACHED to VFREE, and allocvnode() will do a better
job finding vnodes to reuse without getting blocked by a flush.

allocvnode now uses a real VX lock to sequence vnodes into VRECLAIMED.  All
vnode special state processing now uses a VX lock.

Vnodes are now able to be slowly returned to the memory pool when
kern.maxvnodes is reduced at run time.

Various initialization elements have been moved to CTOR/DTOR and are
no longer in the critical path, improving performance.  However, since
SYSREF uses atomic_cmpset_int() (aka cmpxchgl), which reduces performance
somewhat, overall performance tends to be about the same.

40 files changed:
sys/dev/disk/ccd/ccd.c
sys/emulation/linux/i386/linprocfs/linprocfs_subr.c
sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c
sys/kern/kern_sysref.c
sys/kern/vfs_bio.c
sys/kern/vfs_cache.c
sys/kern/vfs_lock.c
sys/kern/vfs_mount.c
sys/kern/vfs_subr.c
sys/kern/vfs_sync.c
sys/kern/vfs_syscalls.c
sys/sys/sysref2.h
sys/sys/vnode.h
sys/vfs/fifofs/fifo_vnops.c
sys/vfs/gnu/ext2fs/ext2_inode.c
sys/vfs/gnu/ext2fs/ext2_vnops.c
sys/vfs/hpfs/hpfs_vnops.c
sys/vfs/isofs/cd9660/cd9660_node.c
sys/vfs/mfs/mfs_vfsops.c
sys/vfs/mfs/mfs_vnops.c
sys/vfs/msdosfs/msdosfs_denode.c
sys/vfs/msdosfs/msdosfs_vfsops.c
sys/vfs/msdosfs/msdosfs_vnops.c
sys/vfs/nfs/nfs_node.c
sys/vfs/nfs/nfs_vnops.c
sys/vfs/ntfs/ntfs_vfsops.c
sys/vfs/ntfs/ntfs_vnops.c
sys/vfs/nwfs/nwfs_node.c
sys/vfs/nwfs/nwfs_vfsops.c
sys/vfs/nwfs/nwfs_vnops.c
sys/vfs/procfs/procfs_subr.c
sys/vfs/procfs/procfs_vnops.c
sys/vfs/smbfs/smbfs_node.c
sys/vfs/smbfs/smbfs_vfsops.c
sys/vfs/smbfs/smbfs_vnops.c
sys/vfs/ufs/ufs_inode.c
sys/vfs/ufs/ufs_vnops.c
sys/vfs/union/union_subr.c
sys/vfs/union/union_vnops.c
sys/vm/vnode_pager.c

index 402835d..9b94e13 100644 (file)
@@ -1,5 +1,5 @@
 /* $FreeBSD: src/sys/dev/ccd/ccd.c,v 1.73.2.1 2001/09/11 09:49:52 kris Exp $ */
-/* $DragonFly: src/sys/dev/disk/ccd/ccd.c,v 1.38 2006/12/22 23:26:16 swildner Exp $ */
+/* $DragonFly: src/sys/dev/disk/ccd/ccd.c,v 1.39 2007/05/06 19:23:21 dillon Exp $ */
 
 /*     $NetBSD: ccd.c,v 1.22 1995/12/08 19:13:26 thorpej Exp $ */
 
@@ -1575,7 +1575,7 @@ ccdlookup(char *path, struct vnode **vpp)
        }
        vp = nd.nl_open_vp;
 
-       if (vp->v_usecount > 1) {
+       if (vp->v_opencount > 1) {
                error = EBUSY;
                goto done;
        }
index 24963e8..4299e3c 100644 (file)
@@ -39,7 +39,7 @@
  *     @(#)procfs_subr.c       8.6 (Berkeley) 5/14/95
  *
  * $FreeBSD: src/sys/i386/linux/linprocfs/linprocfs_subr.c,v 1.3.2.4 2001/06/25 19:46:47 pirzyk Exp $
- * $DragonFly: src/sys/emulation/linux/i386/linprocfs/linprocfs_subr.c,v 1.21 2006/08/11 01:54:58 dillon Exp $
+ * $DragonFly: src/sys/emulation/linux/i386/linprocfs/linprocfs_subr.c,v 1.22 2007/05/06 19:23:28 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -385,7 +385,7 @@ restart:
                if (pfs->pfs_pid == pid) {
                        vp = PFSTOV(pfs);
                        vx_get(vp);
-                       vgone(vp);
+                       vgone_vxlocked(vp);
                        vx_put(vp);
                        goto restart;
                }
index 50e96e4..585cfc1 100644 (file)
@@ -39,7 +39,7 @@
  *     @(#)procfs_vnops.c      8.18 (Berkeley) 5/21/95
  *
  * $FreeBSD: src/sys/i386/linux/linprocfs/linprocfs_vnops.c,v 1.3.2.5 2001/08/12 14:29:19 rwatson Exp $
- * $DragonFly: src/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c,v 1.39 2006/12/23 00:27:02 swildner Exp $
+ * $DragonFly: src/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c,v 1.40 2007/05/06 19:23:29 dillon Exp $
  */
 
 /*
@@ -213,7 +213,7 @@ linprocfs_close(struct vop_close_args *ap)
                 * told to stop on an event, but then the requesting process
                 * has gone away or forgotten about it.
                 */
-               if ((ap->a_vp->v_usecount < 2)
+               if ((ap->a_vp->v_opencount < 2)
                    && (p = pfind(pfs->pfs_pid))
                    && !(p->p_pfsflags & PF_LINGER)) {
                        p->p_stops = 0;
index e320f80..ffe69a7 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/kern/kern_sysref.c,v 1.3 2007/04/30 07:18:54 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_sysref.c,v 1.4 2007/05/06 19:23:30 dillon Exp $
  */
 /*
  * System resource control module for all cluster-addressable system resource
@@ -274,7 +274,8 @@ sysref_activate(struct sysref *sr)
 
        for (;;) {
                count = sr->refcnt;
-               KKASSERT(count < 0 && count + 0x40000001 > 0);
+               KASSERT(count < 0 && count + 0x40000001 > 0,
+                       ("sysref_activate: bad count %08x", count));
                if (atomic_cmpset_int(&sr->refcnt, count, count + 0x40000001))
                        break;
                cpu_pause();
index 267595f..ed93c36 100644 (file)
@@ -12,7 +12,7 @@
  *             John S. Dyson.
  *
  * $FreeBSD: src/sys/kern/vfs_bio.c,v 1.242.2.20 2003/05/28 18:38:10 alc Exp $
- * $DragonFly: src/sys/kern/vfs_bio.c,v 1.89 2007/01/12 03:05:49 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_bio.c,v 1.90 2007/05/06 19:23:31 dillon Exp $
  */
 
 /*
@@ -2882,7 +2882,7 @@ biodone(struct bio *bio)
                obj = vp->v_object;
 
 #if defined(VFS_BIO_DEBUG)
-               if (vp->v_holdcnt == 0)
+               if (vp->v_auxrefs == 0)
                        panic("biodone: zero vnode hold count");
                if ((vp->v_flag & VOBJBUF) == 0)
                        panic("biodone: vnode is not setup for merged cache");
index b4b0c1c..76d8768 100644 (file)
@@ -67,7 +67,7 @@
  *
  *     @(#)vfs_cache.c 8.5 (Berkeley) 3/22/95
  * $FreeBSD: src/sys/kern/vfs_cache.c,v 1.42.2.6 2001/10/05 20:07:03 dillon Exp $
- * $DragonFly: src/sys/kern/vfs_cache.c,v 1.80 2006/12/23 00:35:04 swildner Exp $
+ * $DragonFly: src/sys/kern/vfs_cache.c,v 1.81 2007/05/06 19:23:31 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -88,6 +88,8 @@
 #include <sys/dirent.h>
 #include <ddb/ddb.h>
 
+#include <sys/sysref2.h>
+
 #define MAX_RECURSION_DEPTH    64
 
 /*
@@ -603,7 +605,7 @@ _cache_setvp(struct namecache *ncp, struct vnode *vp)
                        vhold(vp);
 
                /*
-                * Set auxillary flags
+                * Set auxiliary flags
                 */
                switch(vp->v_type) {
                case VDIR:
@@ -1064,14 +1066,19 @@ again:
                 * we must lock and unresolve the cache, then loop
                 * to retry.
                 */
-               if (vp->v_flag & VRECLAIMED) {
-                       kprintf("Warning: vnode reclaim race detected on cache_vref %p (%s)\n", vp, ncp->nc_name);
-                       _cache_lock(ncp);
-                       _cache_setunresolved(ncp);
-                       _cache_unlock(ncp);
-                       goto again;
+               if ((error = vget(vp, LK_SHARED)) != 0) {
+                       if (error == ENOENT) {
+                               kprintf("Warning: vnode reclaim race detected on cache_vref %p (%s)\n", vp, ncp->nc_name);
+                               _cache_lock(ncp);
+                               _cache_setunresolved(ncp);
+                               _cache_unlock(ncp);
+                               goto again;
+                       }
+                       /* fatal error */
+               } else {
+                       /* caller does not want a lock */
+                       vn_unlock(vp);
                }
-               vref_initial(vp, 1);
        }
        if (error == 0 && vp == NULL)
                error = ENOENT;
index e0e359c..871a1b3 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/kern/vfs_lock.c,v 1.24 2006/09/05 00:55:45 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_lock.c,v 1.25 2007/05/06 19:23:31 dillon Exp $
  */
 
 /*
 
 #include <sys/buf2.h>
 #include <sys/thread2.h>
+#include <sys/sysref2.h>
 
+static void vnode_terminate(struct vnode *vp);
+static boolean_t vnode_ctor(void *obj, void *private, int ocflags);
+static void vnode_dtor(void *obj, void *private);
 
 static MALLOC_DEFINE(M_VNODE, "vnodes", "vnode structures");
+static struct sysref_class vnode_sysref_class = {
+       .name =         "vnode",
+       .mtype =        M_VNODE,
+       .proto =        SYSREF_PROTO_VNODE,
+       .offset =       offsetof(struct vnode, v_sysref),
+       .objsize =      sizeof(struct vnode),
+       .mag_capacity = 256,
+       .flags =        SRC_MANAGEDINIT,
+       .ctor =         vnode_ctor,
+       .dtor =         vnode_dtor,
+       .ops = {
+               .terminate = (sysref_terminate_func_t)vnode_terminate
+       }
+};
 
 static TAILQ_HEAD(freelst, vnode) vnode_free_list;     /* vnode free list */
 
@@ -112,142 +130,167 @@ __vfree(struct vnode *vp)
        vp->v_flag |= VFREE;
 }
 
+static __inline
+void
+__vfreetail(struct vnode *vp)
+{
+       TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
+       freevnodes++;
+       vp->v_flag |= VFREE;
+}
+
 /*
- * Return 1 if we can immediately place the vnode on the freelist.
+ * Return a C boolean if we should put the vnode on the freelist (VFREE),
+ * or leave it / mark it as VCACHED.
+ *
+ * This routine is only valid if the vnode is already either VFREE or
+ * VCACHED, or if it can become VFREE or VCACHED via vnode_terminate().
  */
-static __inline int
-vshouldfree(struct vnode *vp, int usecount)
+static __inline boolean_t
+vshouldfree(struct vnode *vp)
 {
-       if (vp->v_flag & VFREE)
-               return (0);             /* already free */
-       if (vp->v_holdcnt != 0 || vp->v_usecount != usecount)
-               return (0);             /* other holderse */
-       if (vp->v_object &&
-           (vp->v_object->ref_count || vp->v_object->resident_page_count)) {
-               return (0);
-       }
-       return (1);
+       return (vp->v_auxrefs == 0 &&
+           (vp->v_object == NULL || vp->v_object->resident_page_count == 0));
 }
 
 /*
- * Add another ref to a vnode.  The vnode must already have at least one
- * ref.
- *
- * NOTE: The vnode may continue to reside on the free list
+ * Add a ref to an active vnode.  This function should never be called
+ * with an inactive vnode (use vget() instead).
  */
 void
 vref(struct vnode *vp)
 {
-       KKASSERT(vp->v_usecount > 0 && (vp->v_flag & VINACTIVE) == 0);
-       atomic_add_int(&vp->v_usecount, 1);
+       KKASSERT(vp->v_sysref.refcnt > 0 && 
+                (vp->v_flag & (VFREE|VINACTIVE)) == 0);
+       sysref_get(&vp->v_sysref);
 }
 
 /*
- * Add a ref to a vnode which may not have any refs.  This routine is called
- * from the namecache and vx_get().  If requested, the vnode will be
- * reactivated.
- *
- * Removal of the vnode from the free list is optional.  Since most vnodes
- * are temporary in nature we opt not do it.  This also means we don't have
- * to deal with lock ordering issues between the freelist and vnode
- * spinlocks.
+ * Release a ref on an active or inactive vnode.  The sysref termination
+ * function will be called when the active last active reference is released,
+ * and the vnode is returned to the objcache when the last inactive
+ * reference is released.
+ */
+void
+vrele(struct vnode *vp)
+{
+       sysref_put(&vp->v_sysref);
+}
+
+/*
+ * Add an auxiliary data structure reference to the vnode.  Auxiliary
+ * references do not change the state of the vnode or prevent them
+ * from being deactivated, reclaimed, or placed on the free list.
  *
- * We must acquire the vnode's spinlock to interlock against vrele().
+ * An auxiliary reference DOES prevent the vnode from being destroyed,
+ * allowing you to vx_lock() it, test state, etc.
  *
- * vget(), cache_vget(), and cache_vref() reactives vnodes.  vx_get() does
- * not.
+ * An auxiliary reference DOES NOT move a vnode out of the VFREE state
+ * once it has entered it.
  */
 void
-vref_initial(struct vnode *vp, int reactivate)
+vhold(struct vnode *vp)
 {
-       spin_lock_wr(&vp->v_spinlock);
-       atomic_add_int(&vp->v_usecount, 1);
-       if (reactivate)
-               vp->v_flag &= ~VINACTIVE;
-       spin_unlock_wr(&vp->v_spinlock);
+       KKASSERT(vp->v_sysref.refcnt != 0);
+       atomic_add_int(&vp->v_auxrefs, 1);
 }
 
 /*
- * Release a ref on the vnode.  Since 0->1 transitions can only be made
- * by vref_initial(), 1->0 transitions will be protected by the spinlock.
+ * Remove an auxiliary reference from the vnode.
  *
- * When handling a 1->0 transition the vnode is guarenteed to not be locked
- * and we can set the exclusive lock atomically while interlocked with our
- * spinlock.  A panic will occur if the lock is held.
+ * vdrop needs to check for a VCACHE->VFREE transition to catch cases
+ * where a vnode is held past its reclamation.
  */
 void
-vrele(struct vnode *vp)
+vdrop(struct vnode *vp)
 {
-       spin_lock_wr(&vp->v_spinlock);
-       if (vp->v_usecount > 1) {
-               atomic_subtract_int(&vp->v_usecount, 1);
-               spin_unlock_wr(&vp->v_spinlock);
-               return;
-       }
-       KKASSERT(vp->v_usecount == 1);
-
-       /*
-        * This is roughly equivalent to obtaining an exclusive
-        * lock, but the spinlock is already held (and remains held
-        * on return) and the lock must be obtainable without 
-        * blocking, which it is in a 1->0 transition.
-        */
-       lockmgr_setexclusive_interlocked(&vp->v_lock);
-
-       /*
-        * VINACTIVE is interlocked by the spinlock, so we have to re-check
-        * the bit if we release and reacquire the spinlock even though
-        * we are holding the exclusive lockmgr lock throughout.
-        *
-        * VOP_INACTIVE can race other VOPs even though we hold an exclusive
-        * lock.  This is ok.  The ref count of 1 must remain intact through
-        * the VOP_INACTIVE call to avoid a recursion.
-        */
-       while ((vp->v_flag & VINACTIVE) == 0 && vp->v_usecount == 1) {
-               vp->v_flag |= VINACTIVE;
-               spin_unlock_wr(&vp->v_spinlock);
-               VOP_INACTIVE(vp);
-               spin_lock_wr(&vp->v_spinlock);
-       }
-
-       /*
-        * NOTE: v_usecount might no longer be 1
-        */
-       atomic_subtract_int(&vp->v_usecount, 1);
-       if (vshouldfree(vp, 0))
+       KKASSERT(vp->v_sysref.refcnt != 0 && vp->v_auxrefs > 0);
+       atomic_subtract_int(&vp->v_auxrefs, 1);
+       if ((vp->v_flag & VCACHED) && vshouldfree(vp)) {
+               vp->v_flag |= VAGE;
+               vp->v_flag &= ~VCACHED;
                __vfree(vp);
-       lockmgr_clrexclusive_interlocked(&vp->v_lock);
-       /* spinlock unlocked */
+       }
 }
 
 /*
- * Hold a vnode, preventing it from being recycled (unless it is already
- * undergoing a recyclement or already has been recycled).
+ * This function is called when the last active reference on the vnode
+ * is released, typically via vrele().  SYSREF will give the vnode a
+ * negative ref count, indicating that it is undergoing termination or
+ * is being set aside for the cache, and one final sysref_put() is
+ * required to actually return it to the memory subsystem.
  *
- * Opting not to remove a vnode from the freelist simply means that
- * allocvnode must do it for us if it finds an unsuitable vnode.
+ * However, because vnodes may have auxiliary structural references via
+ * v_auxrefs, we must interlock auxiliary references against termination
+ * via the VX lock mechanism.  It is possible for a vnode to be reactivated
+ * while we were blocked on the lock.
  */
 void
-vhold(struct vnode *vp)
+vnode_terminate(struct vnode *vp)
 {
-       spin_lock_wr(&vp->v_spinlock);
-       atomic_add_int(&vp->v_holdcnt, 1);
-       spin_unlock_wr(&vp->v_spinlock);
+       vx_lock(vp);
+       if (sysref_isinactive(&vp->v_sysref)) {
+               /*
+                * Deactivate the vnode by marking it VFREE or VCACHED.
+                * The vnode can be reactivated from either state until
+                * reclaimed.  These states inherit the 'last' sysref on the
+                * vnode.
+                *
+                * NOTE: There may be additional inactive references from
+                * other entities blocking on the VX lock while we hold it,
+                * but this does not prevent us from changing the vnode's
+                * state.
+                *
+                * NOTE: The vnode could already be marked inactive.  XXX
+                * how?
+                *
+                * NOTE: The vnode may be marked inactive with dirty buffers
+                * or dirty pages in its cached VM object still present.
+                */
+               if ((vp->v_flag & VINACTIVE) == 0) {
+                       vp->v_flag |= VINACTIVE;
+                       VOP_INACTIVE(vp);
+               }
+               KKASSERT((vp->v_flag & (VFREE|VCACHED)) == 0);
+               if (vshouldfree(vp))
+                       __vfree(vp);
+               else
+                       vp->v_flag |= VCACHED;
+               vx_unlock(vp);
+       } else {
+               /*
+                * Someone reactivated the vnode while were blocked on the
+                * VX lock.  Release the VX lock and release the (now active)
+                * last reference which is no longer last.
+                */
+               vx_unlock(vp);
+               vrele(vp);
+       }
 }
 
 /*
- * Like vrele(), we must atomically place the vnode on the free list if
- * it becomes suitable.  vhold()/vdrop() do not mess with VINACTIVE.
+ * Physical vnode constructor / destructor.  These are only executed on
+ * the backend of the objcache.  They are NOT executed on every vnode
+ * allocation or deallocation.
  */
+boolean_t
+vnode_ctor(void *obj, void *private, int ocflags)
+{
+       struct vnode *vp = obj;
+
+       lwkt_token_init(&vp->v_pollinfo.vpi_token);
+       lockinit(&vp->v_lock, "vnode", 0, 0);
+       ccms_dataspace_init(&vp->v_ccms);
+       TAILQ_INIT(&vp->v_namecache);
+       return(TRUE);
+}
+
 void
-vdrop(struct vnode *vp)
+vnode_dtor(void *obj, void *private)
 {
-       KKASSERT(vp->v_holdcnt > 0);
-       spin_lock_wr(&vp->v_spinlock);
-       atomic_subtract_int(&vp->v_holdcnt, 1);
-       if (vshouldfree(vp, 0))
-               __vfree(vp);
-       spin_unlock_wr(&vp->v_spinlock);
+       struct vnode *vp = obj;
+
+       ccms_dataspace_destroy(&vp->v_ccms);
 }
 
 /****************************************************************
@@ -255,12 +298,8 @@ vdrop(struct vnode *vp)
  ****************************************************************
  *
  * These functions lock vnodes for reclamation and deactivation related
- * activities.  Only vp->v_lock, the top layer of the VFS, is locked.
- * You must be holding a normal reference in order to be able to safely
- * call vx_lock() and vx_unlock().
- *
- * vx_get() also differs from vget() in that it does not clear the
- * VINACTIVE bit on a vnode.
+ * activities.  The caller must already be holding some sort of reference
+ * on the vnode.
  */
 
 void
@@ -269,81 +308,89 @@ vx_lock(struct vnode *vp)
        lockmgr(&vp->v_lock, LK_EXCLUSIVE);
 }
 
-void
-vx_unlock(struct vnode *vp)
+static int
+vx_lock_nonblock(struct vnode *vp)
 {
-       lockmgr(&vp->v_lock, LK_RELEASE);
+       return(lockmgr(&vp->v_lock, LK_EXCLUSIVE | LK_NOWAIT));
 }
 
 void
-vx_get(struct vnode *vp)
-{
-       vref_initial(vp, 0);
-       lockmgr(&vp->v_lock, LK_EXCLUSIVE);
-}
-
-int
-vx_get_nonblock(struct vnode *vp)
-{
-       int error;
-
-       vref_initial(vp, 0);
-       error = lockmgr(&vp->v_lock, LK_EXCLUSIVE | LK_NOWAIT);
-       if (error)
-               vrele(vp);
-       return(error);
-}
-
-void
-vx_put(struct vnode *vp)
+vx_unlock(struct vnode *vp)
 {
        lockmgr(&vp->v_lock, LK_RELEASE);
-       vrele(vp);
 }
 
 /****************************************************************
  *                     VNODE ACQUISITION FUNCTIONS             *
  ****************************************************************
  *
- * vget() and vput() access a vnode for the intent of executing an
- * operation other then a reclamation or deactivation.  vget() will ref
- * and lock the vnode, vput() will unlock and deref the vnode.  
- * The VOP_*() locking functions are used.
+ * These functions must be used when accessing a vnode via an auxiliary
+ * reference such as the namecache or free list, or when you wish to
+ * do a combo ref+lock sequence.
  *
- * CALLING VGET IS MANDATORY PRIOR TO ANY MODIFYING OPERATION ON A VNODE.
- * This is because vget handles the VINACTIVE interlock and is responsible
- * for clearing the bit.  If the bit is not cleared inode updates may not
- * make it to disk.
+ * These functions are MANDATORY for any code chain accessing a vnode
+ * whos activation state is not known.
  *
- * Special cases: If vget()'s locking operation fails the vrele() call may
- * cause the vnode to be deactivated (VOP_INACTIVE called).  However, this
- * never occurs if the vnode is in a reclaimed state.  Vnodes in reclaimed
- * states always return an error code of ENOENT.
+ * vget()/vput() are used when reactivation is desired.
  *
- * Special cases: vput() will unlock and, if it is the last reference, 
- * deactivate the vnode.  The deactivation uses a separate non-layered
- * VX lock after the normal unlock.  XXX make it more efficient.
+ * vx_get() and vx_put() are used when reactivation is not desired.
  */
 int
 vget(struct vnode *vp, int flags)
 {
        int error;
 
-       vref_initial(vp, 0);
-       if (flags & LK_TYPE_MASK) {
-               if ((error = vn_lock(vp, flags)) != 0) {
-                       vrele(vp);
-               } else if (vp->v_flag & VRECLAIMED) {
-                       vn_unlock(vp);
-                       vrele(vp);
-                       error = ENOENT;
+       /*
+        * A lock type must be passed
+        */
+       if ((flags & LK_TYPE_MASK) == 0) {
+               panic("vget() called with no lock specified!");
+               /* NOT REACHED */
+       }
+
+       /*
+        * Reference the structure and then acquire the lock.  0->1
+        * transitions and refs during termination are allowed here so
+        * call sysref directly.
+        */
+
+       sysref_get(&vp->v_sysref);
+       if ((error = vn_lock(vp, flags)) != 0) {
+               /*
+                * The lock failed, undo and return an error.
+                */
+               sysref_put(&vp->v_sysref);
+       } else if (vp->v_flag & VRECLAIMED) {
+               /*
+                * The node is being reclaimed and cannot be reactivated
+                * any more, undo and return ENOENT.
+                */
+               vn_unlock(vp);
+               vrele(vp);
+               error = ENOENT;
+       } else {
+               /*
+                * If the vnode is marked VFREE or VCACHED it needs to be
+                * reactivated, otherwise it had better already be active.
+                * VINACTIVE must also be cleared.
+                *
+                * In the VFREE/VCACHED case we have to throw away the
+                * sysref that was earmarking those cases and preventing
+                * the vnode from being destroyed.  Our sysref is still held.
+                */
+               if (vp->v_flag & VFREE) {
+                       __vbusy(vp);
+                       sysref_put(&vp->v_sysref);
+                       sysref_activate(&vp->v_sysref);
+               } else if (vp->v_flag & VCACHED) {
+                       vp->v_flag &= ~VCACHED;
+                       sysref_put(&vp->v_sysref);
+                       sysref_activate(&vp->v_sysref);
                } else {
-                       vp->v_flag &= ~VINACTIVE;       /* XXX not MP safe */
-                       error = 0;
+                       KKASSERT(sysref_isactive(&vp->v_sysref));
                }
-       } else {
-               panic("vget() called with no lock specified!");
-               error = ENOENT; /* not reached, compiler opt */
+               vp->v_flag &= ~VINACTIVE;
+               error = 0;
        }
        return(error);
 }
@@ -355,6 +402,50 @@ vput(struct vnode *vp)
        vrele(vp);
 }
 
+/*
+ * XXX The vx_*() locks should use auxrefs, not the main reference counter.
+ */
+void
+vx_get(struct vnode *vp)
+{
+       sysref_get(&vp->v_sysref);
+       lockmgr(&vp->v_lock, LK_EXCLUSIVE);
+}
+
+int
+vx_get_nonblock(struct vnode *vp)
+{
+       int error;
+
+       sysref_get(&vp->v_sysref);
+       error = lockmgr(&vp->v_lock, LK_EXCLUSIVE | LK_NOWAIT);
+       if (error)
+               sysref_put(&vp->v_sysref);
+       return(error);
+}
+
+/*
+ * Relase a VX lock that also held a ref on the vnode.
+ *
+ * vx_put needs to check for a VCACHE->VFREE transition to catch the
+ * case where e.g. vnlru issues a vgone*().
+ */
+void
+vx_put(struct vnode *vp)
+{
+       if ((vp->v_flag & VCACHED) && vshouldfree(vp)) {
+               vp->v_flag |= VAGE;
+               vp->v_flag &= ~VCACHED;
+               __vfree(vp);
+       }
+       lockmgr(&vp->v_lock, LK_RELEASE);
+       sysref_put(&vp->v_sysref);
+}
+
+/*
+ * Misc functions
+ */
+
 void
 vsetflags(struct vnode *vp, int flags)
 {
@@ -371,6 +462,75 @@ vclrflags(struct vnode *vp, int flags)
        crit_exit();
 }
 
+/*
+ * Try to reuse a vnode from the free list.  NOTE: The returned vnode
+ * is not completely initialized.
+ */
+static
+struct vnode *
+allocfreevnode(void)
+{
+       struct vnode *vp;
+       int count;
+
+       for (count = 0; count < freevnodes; count++) {
+               /*
+                * Note that regardless of how we block in this loop,
+                * we only get here if freevnodes != 0 so there
+                * had better be something on the list.
+                *
+                * Try to lock the first vnode on the free list.
+                * Cycle if we can't.
+                *
+                * XXX NOT MP SAFE
+                */
+               vp = TAILQ_FIRST(&vnode_free_list);
+               if (vx_lock_nonblock(vp)) {
+                       KKASSERT(vp->v_flag & VFREE);
+                       TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
+                       TAILQ_INSERT_TAIL(&vnode_free_list,
+                                         vp, v_freelist);
+                       continue;
+               }
+
+               /*
+                * With the vnode locked we can safely remove it
+                * from the free list.  We inherit the reference
+                * that was previously associated with the vnode
+                * being on the free list.
+                */
+               KKASSERT((vp->v_flag & (VFREE|VINACTIVE)) ==
+                         (VFREE|VINACTIVE));
+               KKASSERT(sysref_isinactive(&vp->v_sysref));
+               __vbusy(vp);
+
+               /*
+                * Ok.  Holding the VX lock on an inactive vnode
+                * prevents it from being reactivated.  We can
+                * safely reclaim the vnode.
+                */
+               if ((vp->v_flag & VRECLAIMED) == 0)
+                       vgone_vxlocked(vp);
+
+               /*
+                * We can reuse the vnode if no primary or auxiliary
+                * references remain other then ours, else put it
+                * back on the free list and keep looking.
+                *
+                * Either the free list inherits the last reference
+                * or we fall through and sysref_activate() the last
+                * reference.
+                */
+               if (vp->v_auxrefs ||
+                   !sysref_islastdeactivation(&vp->v_sysref)) {
+                       __vfreetail(vp);
+                       continue;
+               }
+               return(vp);
+       }
+       return(NULL);
+}
+
 /*
  * Obtain a new vnode from the freelist, allocating more if necessary.
  * The returned vnode is VX locked & refd.
@@ -378,7 +538,6 @@ vclrflags(struct vnode *vp, int flags)
 struct vnode *
 allocvnode(int lktimeout, int lkflags)
 {
-       struct thread *td;
        struct vnode *vp;
 
        /*
@@ -390,151 +549,52 @@ allocvnode(int lktimeout, int lkflags)
        while (numvnodes - freevnodes > desiredvnodes)
                vnlru_proc_wait();
 
-       td = curthread;
-       vp = NULL;
-
        /*
         * Attempt to reuse a vnode already on the free list, allocating
         * a new vnode if we can't find one or if we have not reached a
         * good minimum for good LRU performance.
         */
-       if (freevnodes >= wantfreevnodes && numvnodes >= minvnodes) {
-               int count;
-
-               for (count = 0; count < freevnodes; count++) {
-                       /*
-                        * __VNODESCAN__
-                        *
-                        * Pull the next vnode off the free list and do some
-                        * sanity checks.  Note that regardless of how we
-                        * block, if freevnodes is non-zero there had better
-                        * be something on the list.
-                        */
-                       vp = TAILQ_FIRST(&vnode_free_list);
-                       if (vp == NULL)
-                               panic("getnewvnode: free vnode isn't");
-
-                       /* XXX for now */
-                       KKASSERT(vp->v_flag & VFREE);
-
-                       /*
-                        * Handle the case where the vnode was pulled off
-                        * the free list while we were waiting for the
-                        * spinlock.
-                        */
-                       spin_lock_wr(&vp->v_spinlock);
-                       if ((vp->v_flag & VFREE) == 0) {
-                               spin_unlock_wr(&vp->v_spinlock);
-                               vp = NULL;
-                               continue;
-                       }
-
-                       /*
-                        * Lazy removal of the vnode from the freelist if
-                        * the vnode has references.
-                        */
-                       if (vp->v_usecount || vp->v_holdcnt) {
-                               __vbusy(vp);
-                               spin_unlock_wr(&vp->v_spinlock);
-                               vp = NULL;
-                               continue;
-                       }
-
-                       /*
-                        * vx_get() equivalent, but atomic with the
-                        * spinlock held.  Since 0->1 transitions and the
-                        * lockmgr are protected by the spinlock we must
-                        * be able to get an exclusive lock without blocking
-                        * here.
-                        *
-                        * Also take the vnode off of the free list and
-                        * assert that it is inactive.
-                        */
-                       vp->v_usecount = 1;
-                       lockmgr_setexclusive_interlocked(&vp->v_lock);
-                       __vbusy(vp);
-                       KKASSERT(vp->v_flag & VINACTIVE);
-
-                       /*
-                        * Reclaim the vnode.  VRECLAIMED will be set
-                        * atomically before the spinlock is released
-                        * by vgone_interlocked().
-                        */
-                       if ((vp->v_flag & VRECLAIMED) == 0) {
-                               vgone_interlocked(vp);
-                               /* spinlock unlocked */
-                       } else {
-                               spin_unlock_wr(&vp->v_spinlock);
-                       }
-
-                       /*
-                        * We reclaimed the vnode but other claimants may
-                        * have referenced it while we were blocked.  We
-                        * cannot reuse a vnode until all refs are gone and
-                        * the vnode has completed reclamation.
-                        */
-                       KKASSERT(vp->v_flag & VRECLAIMED);
-                       if (vp->v_usecount != 1 || vp->v_holdcnt) {
-                               vx_put(vp);
-                               vp = NULL;
-                               continue;
-                       }
-                           
-                       /*
-                        * There are no more structural references to the
-                        * vnode, referenced or otherwise.  We have a vnode!
-                        *
-                        * The vnode may have been placed on the free list
-                        * while we were blocked.
-                        */
-                       if (vp->v_flag & VFREE)
-                               __vbusy(vp);
-                       KKASSERT(vp->v_flag & VINACTIVE);
-                       break;
-               }
+       if (freevnodes >= wantfreevnodes && numvnodes >= minvnodes)
+               vp = allocfreevnode();
+       else
+               vp = NULL;
+       if (vp == NULL) {
+               vp = sysref_alloc(&vnode_sysref_class);
+               lockmgr(&vp->v_lock, LK_EXCLUSIVE);
+               numvnodes++;
        }
 
        /*
-        * If we have a vp it will be refd and VX locked.
+        * We are using a managed sysref class, vnode fields are only
+        * zerod on initial allocation from the backing store, not
+        * on reallocation.  Thus we have to clear these fields for both
+        * reallocation and reuse.
         */
-       if (vp) {
 #ifdef INVARIANTS
-               if (vp->v_data)
-                       panic("cleaned vnode isn't");
-               if (vp->v_track_read.bk_active + vp->v_track_write.bk_active)
-                       panic("Clean vnode has pending I/O's");
-               KKASSERT(vp->v_mount == NULL);
+       if (vp->v_data)
+               panic("cleaned vnode isn't");
+       if (vp->v_track_read.bk_active + vp->v_track_write.bk_active)
+               panic("Clean vnode has pending I/O's");
+       KKASSERT(vp->v_mount == NULL);
 #endif
-               vp->v_flag = 0;
-               vp->v_lastw = 0;
-               vp->v_lasta = 0;
-               vp->v_cstart = 0;
-               vp->v_clen = 0;
-               vp->v_socket = 0;
-               vp->v_opencount = 0;
-               vp->v_writecount = 0;   /* XXX */
-               lockreinit(&vp->v_lock, "vnode", lktimeout, lkflags);
-               KKASSERT(TAILQ_FIRST(&vp->v_namecache) == NULL);
-       } else {
-               /*
-                * A brand-new vnode (we could use malloc() here I think) XXX
-                */
-               vp = kmalloc(sizeof(struct vnode), M_VNODE, M_WAITOK|M_ZERO);
-               lwkt_token_init(&vp->v_pollinfo.vpi_token);
-               lockinit(&vp->v_lock, "vnode", lktimeout, lkflags);
-               ccms_dataspace_init(&vp->v_ccms);
-               TAILQ_INIT(&vp->v_namecache);
-
-               /*
-                * short cut around vfreeing it and looping, just set it up
-                * as if we had pulled a reclaimed vnode off the freelist
-                * and reinitialized it.
-                */
-               vp->v_usecount = 1;
-               lockmgr(&vp->v_lock, LK_EXCLUSIVE);
-               numvnodes++;
-       }
+       vp->v_flag = 0;
+       vp->v_lastw = 0;
+       vp->v_lasta = 0;
+       vp->v_cstart = 0;
+       vp->v_clen = 0;
+       vp->v_socket = 0;
+       vp->v_opencount = 0;
+       vp->v_writecount = 0;   /* XXX */
+       lockreinit(&vp->v_lock, "vnode", lktimeout, lkflags);
+       KKASSERT(TAILQ_FIRST(&vp->v_namecache) == NULL);
+       /* exclusive lock still held */
 
+       /*
+        * Note: sysref needs to be activated to convert -0x40000000 to +1.
+        * The -0x40000000 comes from the last ref on reuse, and from
+        * sysref_init() on allocate.
+        */
+       sysref_activate(&vp->v_sysref);
        RB_INIT(&vp->v_rbclean_tree);
        RB_INIT(&vp->v_rbdirty_tree);
        RB_INIT(&vp->v_rbhash_tree);
@@ -544,6 +604,23 @@ allocvnode(int lktimeout, int lkflags)
        vp->v_ops = NULL;
        vp->v_data = NULL;
        KKASSERT(vp->v_mount == NULL);
+
        return (vp);
 }
 
+int
+freesomevnodes(int n)
+{
+       struct vnode *vp;
+       int count = 0;
+
+       while (n) {
+               --n;
+               if ((vp = allocfreevnode()) == NULL)
+                       break;
+               vx_put(vp);
+               --numvnodes;
+       }
+       return(count);
+}
+
index 0818baa..a2d04ea 100644 (file)
@@ -67,7 +67,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/kern/vfs_mount.c,v 1.25 2007/01/12 03:05:49 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_mount.c,v 1.26 2007/05/06 19:23:31 dillon Exp $
  */
 
 /*
@@ -91,6 +91,7 @@
 
 #include <sys/buf2.h>
 #include <sys/thread2.h>
+#include <sys/sysref2.h>
 
 #include <vm/vm.h>
 #include <vm/vm_object.h>
@@ -393,9 +394,6 @@ vfs_getnewfsid(struct mount *mp)
  * This is a quick non-blocking check to determine if the vnode is a good
  * candidate for being (eventually) vgone()'d.  Returns 0 if the vnode is
  * not a good candidate, 1 if it is.
- *
- * Note that a vnode can be marked VFREE without really being free, so
- * we don't use the flag for any tests.
  */
 static __inline int 
 vmightfree(struct vnode *vp, int page_count)
@@ -406,7 +404,7 @@ vmightfree(struct vnode *vp, int page_count)
        if ((vp->v_flag & VFREE) && TAILQ_EMPTY(&vp->v_namecache))
                return (0);
 #endif
-       if (vp->v_usecount != 0)
+       if (sysref_isactive(&vp->v_sysref))
                return (0);
        if (vp->v_object && vp->v_object->resident_page_count >= page_count)
                return (0);
@@ -419,14 +417,14 @@ vmightfree(struct vnode *vp, int page_count)
  * vgone()able, doing some cleanups in the process.  Returns 1 if the vnode
  * can be vgone()'d, 0 otherwise.
  *
- * Note that v_holdcnt may be non-zero because (A) this vnode is not a leaf
+ * Note that v_auxrefs may be non-zero because (A) this vnode is not a leaf
  * in the namecache topology and (B) this vnode has buffer cache bufs.
  * We cannot remove vnodes with non-leaf namecache associations.  We do a
  * tentitive leaf check prior to attempting to flush out any buffers but the
- * 'real' test when all is said in done is that v_holdcnt must become 0 for
+ * 'real' test when all is said in done is that v_auxrefs must become 0 for
  * the vnode to be freeable.
  *
- * We could theoretically just unconditionally flush when v_holdcnt != 0,
+ * We could theoretically just unconditionally flush when v_auxrefs != 0,
  * but flushing data associated with non-leaf nodes (which are always
  * directories), just throws it away for no benefit.  It is the buffer 
  * cache's responsibility to choose buffers to recycle from the cached
@@ -457,20 +455,20 @@ vtrytomakegoneable(struct vnode *vp, int page_count)
 {
        if (vp->v_flag & VRECLAIMED)
                return (0);
-       if (vp->v_usecount != 1)
+       if (vp->v_sysref.refcnt > 1)
                return (0);
        if (vp->v_object && vp->v_object->resident_page_count >= page_count)
                return (0);
-       if (vp->v_holdcnt && visleaf(vp)) {
+       if (vp->v_auxrefs && visleaf(vp)) {
                vinvalbuf(vp, V_SAVE, 0, 0);
 #if 0  /* DEBUG */
-               kprintf((vp->v_holdcnt ? "vrecycle: vp %p failed: %s\n" :
+               kprintf((vp->v_auxrefs ? "vrecycle: vp %p failed: %s\n" :
                        "vrecycle: vp %p succeeded: %s\n"), vp,
                        (TAILQ_FIRST(&vp->v_namecache) ? 
                            TAILQ_FIRST(&vp->v_namecache)->nc_name : "?"));
 #endif
        }
-       return(vp->v_usecount == 1 && vp->v_holdcnt == 0);
+       return(vp->v_sysref.refcnt <= 1 && vp->v_auxrefs == 0);
 }
 
 /*
@@ -571,7 +569,7 @@ vlrureclaim(struct mount *mp, void *data)
                 */
                KKASSERT(vp->v_mount == mp);
                vmovevnodetoend(mp, vp);
-               vgone(vp);
+               vgone_vxlocked(vp);
                vx_put(vp);
                ++done;
                --count;
@@ -610,6 +608,25 @@ vnlru_proc(void)
        crit_enter();
        for (;;) {
                kproc_suspend_loop();
+
+               /*
+                * Try to free some vnodes if we have too many
+                */
+               if (numvnodes > desiredvnodes &&
+                   freevnodes > desiredvnodes * 2 / 10) {
+                       int count = numvnodes - desiredvnodes;
+
+                       if (count > freevnodes / 100)
+                               count = freevnodes / 100;
+                       if (count < 5)
+                               count = 5;
+                       freesomevnodes(count);
+               }
+
+               /*
+                * Nothing to do if most of our vnodes are already on
+                * the free list.
+                */
                if (numvnodes - freevnodes <= desiredvnodes * 9 / 10) {
                        vnlruproc_sig = 0;
                        wakeup(&vnlruproc_sig);
@@ -980,7 +997,7 @@ next:
  *
  * `rootrefs' specifies the base reference count for the root vnode
  * of this filesystem. The root vnode is considered busy if its
- * v_usecount exceeds this value. On a successful return, vflush()
+ * v_sysref.refcnt exceeds this value. On a successful return, vflush()
  * will call vrele() on the root vnode exactly rootrefs times.
  * If the SKIPSYSTEM or WRITECLOSE flags are specified, rootrefs must
  * be zero.
@@ -1029,10 +1046,10 @@ vflush(struct mount *mp, int rootrefs, int flags)
                 * is equal to `rootrefs', then go ahead and kill it.
                 */
                KASSERT(vflush_info.busy > 0, ("vflush: not busy"));
-               KASSERT(rootvp->v_usecount >= rootrefs, ("vflush: rootrefs"));
-               if (vflush_info.busy == 1 && rootvp->v_usecount == rootrefs) {
+               KASSERT(rootvp->v_sysref.refcnt >= rootrefs, ("vflush: rootrefs"));
+               if (vflush_info.busy == 1 && rootvp->v_sysref.refcnt == rootrefs) {
                        vx_lock(rootvp);
-                       vgone(rootvp);
+                       vgone_vxlocked(rootvp);
                        vx_unlock(rootvp);
                        vflush_info.busy = 0;
                }
@@ -1074,11 +1091,11 @@ vflush_scan(struct mount *mp, struct vnode *vp, void *data)
        }
 
        /*
-        * With v_usecount == 0, all we need to do is clear out the
-        * vnode data structures and we are done.
+        * If we are the only holder (refcnt of 1) or the vnode is in
+        * termination (refcnt < 0), we can vgone the vnode.
         */
-       if (vp->v_usecount == 1) {
-               vgone(vp);
+       if (vp->v_sysref.refcnt <= 1) {
+               vgone_vxlocked(vp);
                return(0);
        }
 
@@ -1089,11 +1106,9 @@ vflush_scan(struct mount *mp, struct vnode *vp, void *data)
         */
        if (info->flags & FORCECLOSE) {
                if (vp->v_type != VBLK && vp->v_type != VCHR) {
-                       vgone(vp);
+                       vgone_vxlocked(vp);
                } else {
-                       spin_lock_wr(&vp->v_spinlock);
-                       vclean_interlocked(vp, 0);
-                       /* spinlock unlocked */
+                       vclean_vxlocked(vp, 0);
                        vp->v_ops = &spec_vnode_vops_p;
                        insmntque(vp, NULL);
                }
index f4e3648..668b3a7 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)vfs_subr.c  8.31 (Berkeley) 5/26/95
  * $FreeBSD: src/sys/kern/vfs_subr.c,v 1.249.2.30 2003/04/04 20:35:57 tegge Exp $
- * $DragonFly: src/sys/kern/vfs_subr.c,v 1.101 2006/12/28 18:29:03 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_subr.c,v 1.102 2007/05/06 19:23:31 dillon Exp $
  */
 
 /*
@@ -83,6 +83,7 @@
 
 #include <sys/buf2.h>
 #include <sys/thread2.h>
+#include <sys/sysref2.h>
 
 static MALLOC_DEFINE(M_NETADDR, "Export Host", "Export host address structure");
 
@@ -152,9 +153,9 @@ rb_buf_compare(struct buf *b1, struct buf *b2)
  * Returns non-zero if the vnode is a candidate for lazy msyncing.
  */
 static __inline int
-vshouldmsync(struct vnode *vp, int usecount)
+vshouldmsync(struct vnode *vp)
 {
-       if (vp->v_holdcnt != 0 || vp->v_usecount != usecount)
+       if (vp->v_auxrefs != 0 || vp->v_sysref.refcnt > 0)
                return (0);             /* other holders */
        if (vp->v_object &&
            (vp->v_object->ref_count || vp->v_object->resident_page_count)) {
@@ -1041,14 +1042,13 @@ addaliasu(struct vnode *nvp, udev_t nvp_udev)
 /*
  * Disassociate a vnode from its underlying filesystem. 
  *
- * The vnode must be VX locked, referenced, and v_spinlock must be held.
- * This routine releases v_spinlock.
- *
- * If there are v_usecount references to the vnode other then ours we have
- * to VOP_CLOSE the vnode before we can deactivate and reclaim it.
+ * The vnode must be VX locked and referenced.  In all normal situations
+ * there are no active references.  If vclean_vxlocked() is called while
+ * there are active references, the vnode is being ripped out and we have
+ * to call VOP_CLOSE() as appropriate before we can reclaim it.
  */
 void
-vclean_interlocked(struct vnode *vp, int flags)
+vclean_vxlocked(struct vnode *vp, int flags)
 {
        int active;
        int n;
@@ -1056,14 +1056,10 @@ vclean_interlocked(struct vnode *vp, int flags)
 
        /*
         * If the vnode has already been reclaimed we have nothing to do.
-        * VRECLAIMED must be interlocked with the vnode's spinlock.
         */
-       if (vp->v_flag & VRECLAIMED) {
-               spin_unlock_wr(&vp->v_spinlock);
+       if (vp->v_flag & VRECLAIMED)
                return;
-       }
        vp->v_flag |= VRECLAIMED;
-       spin_unlock_wr(&vp->v_spinlock);
 
        /*
         * Scrap the vfs cache
@@ -1078,7 +1074,7 @@ vclean_interlocked(struct vnode *vp, int flags)
         * before we clean it out so that its count cannot fall to zero and
         * generate a race against ourselves to recycle it.
         */
-       active = (vp->v_usecount > 1);
+       active = sysref_isactive(&vp->v_sysref);
 
        /*
         * Clean out any buffers associated with the vnode and destroy its
@@ -1196,7 +1192,7 @@ vop_stdrevoke(struct vop_revoke_args *ap)
                if (vp != vq)
                        vx_get(vq);
                if (vq == SLIST_FIRST(&dev->si_hlist))
-                       vgone(vq);
+                       vgone_vxlocked(vq);
                if (vp != vq)
                        vx_put(vq);
        }
@@ -1206,16 +1202,15 @@ vop_stdrevoke(struct vop_revoke_args *ap)
 }
 
 /*
- * Recycle an unused vnode to the front of the free list.
- *
- * Returns 1 if we were successfully able to recycle the vnode, 
- * 0 otherwise.
+ * This is called when the object underlying a vnode is being destroyed,
+ * such as in a remove().  Try to recycle the vnode immediately if the
+ * only active reference is our reference.
  */
 int
 vrecycle(struct vnode *vp)
 {
-       if (vp->v_usecount == 1) {
-               vgone(vp);
+       if (vp->v_sysref.refcnt == 1) {
+               vgone_vxlocked(vp);
                return (1);
        }
        return (0);
@@ -1238,19 +1233,13 @@ vrecycle(struct vnode *vp)
  * Instead, it happens automatically when the caller releases the VX lock
  * (assuming there aren't any other references).
  */
-void
-vgone(struct vnode *vp)
-{
-       spin_lock_wr(&vp->v_spinlock);
-       vgone_interlocked(vp);
-}
 
 void
-vgone_interlocked(struct vnode *vp)
+vgone_vxlocked(struct vnode *vp)
 {
        /*
         * assert that the VX lock is held.  This is an absolute requirement
-        * now for vgone() to be called.
+        * now for vgone_vxlocked() to be called.
         */
        KKASSERT(vp->v_lock.lk_exclusivecount == 1);
 
@@ -1258,8 +1247,7 @@ vgone_interlocked(struct vnode *vp)
         * Clean out the filesystem specific data and set the VRECLAIMED
         * bit.  Also deactivate the vnode if necessary. 
         */
-       vclean_interlocked(vp, DOCLOSE);
-       /* spinlock unlocked */
+       vclean_vxlocked(vp, DOCLOSE);
 
        /*
         * Delete from old mount point vnode list, if on one.
@@ -1320,7 +1308,8 @@ count_dev(cdev_t dev)
        if (SLIST_FIRST(&dev->si_hlist)) {
                lwkt_gettoken(&ilock, &spechash_token);
                SLIST_FOREACH(vp, &dev->si_hlist, v_cdevnext) {
-                       count += vp->v_usecount;
+                       if (vp->v_sysref.refcnt > 0)
+                               count += vp->v_sysref.refcnt;
                }
                lwkt_reltoken(&ilock);
        }
@@ -1364,7 +1353,7 @@ retry:
                 * that the object is associated with the vp.
                 */
                object->ref_count--;
-               vp->v_usecount--;
+               vrele(vp);
        } else {
                if (object->flags & OBJ_DEAD) {
                        vn_unlock(vp);
@@ -1394,9 +1383,9 @@ vprint(char *label, struct vnode *vp)
                kprintf("%s: %p: ", label, (void *)vp);
        else
                kprintf("%p: ", (void *)vp);
-       kprintf("type %s, usecount %d, writecount %d, refcount %d,",
-           typename[vp->v_type], vp->v_usecount, vp->v_writecount,
-           vp->v_holdcnt);
+       kprintf("type %s, sysrefs %d, writecount %d, holdcnt %d,",
+               typename[vp->v_type],
+               vp->v_sysref.refcnt, vp->v_writecount, vp->v_auxrefs);
        buf[0] = '\0';
        if (vp->v_flag & VROOT)
                strcat(buf, "|VROOT");
@@ -1867,7 +1856,7 @@ vfs_msync_scan1(struct mount *mp, struct vnode *vp, void *data)
        int flags = (int)data;
 
        if ((vp->v_flag & VRECLAIMED) == 0) {
-               if (vshouldmsync(vp, 0))
+               if (vshouldmsync(vp))
                        return(0);      /* call scan2 */
                if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
                    (vp->v_flag & VOBJDIRTY) &&
index 6feb25b..e07ca8e 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)vfs_subr.c  8.31 (Berkeley) 5/26/95
  * $FreeBSD: src/sys/kern/vfs_subr.c,v 1.249.2.30 2003/04/04 20:35:57 tegge Exp $
- * $DragonFly: src/sys/kern/vfs_sync.c,v 1.14 2006/12/23 00:35:04 swildner Exp $
+ * $DragonFly: src/sys/kern/vfs_sync.c,v 1.15 2007/05/06 19:23:31 dillon Exp $
  */
 
 /*
@@ -413,14 +413,14 @@ sync_fsync(struct vop_fsync_args *ap)
 }
 
 /*
- * The syncer vnode is no referenced.
+ * The syncer vnode is no longer referenced.
  *
  * sync_inactive { struct vnode *a_vp, struct proc *a_p }
  */
 static int
 sync_inactive(struct vop_inactive_args *ap)
 {
-       vgone(ap->a_vp);
+       vgone_vxlocked(ap->a_vp);
        return (0);
 }
 
index 5f67973..42849e2 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)vfs_syscalls.c      8.13 (Berkeley) 4/15/94
  * $FreeBSD: src/sys/kern/vfs_syscalls.c,v 1.151.2.18 2003/04/04 20:35:58 tegge Exp $
- * $DragonFly: src/sys/kern/vfs_syscalls.c,v 1.114 2007/02/18 07:12:19 swildner Exp $
+ * $DragonFly: src/sys/kern/vfs_syscalls.c,v 1.115 2007/05/06 19:23:31 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -430,7 +430,7 @@ checkdirs(struct nchandle *old_nch, struct nchandle *new_nch)
         * being held as a descriptor anywhere.
         */
        olddp = old_nch->ncp->nc_vp;
-       if (olddp == NULL || olddp->v_usecount == 1)
+       if (olddp == NULL || olddp->v_sysref.refcnt == 1)
                return;
 
        /*
index fde9115..ce9bf08 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/sys/sysref2.h,v 1.1 2007/04/29 01:29:31 dillon Exp $
+ * $DragonFly: src/sys/sys/sysref2.h,v 1.2 2007/05/06 19:23:33 dillon Exp $
  */
 /*
  * System resource registration, reference counter, and allocation
@@ -85,6 +85,9 @@ sysref_put(struct sysref *sr)
                _sysref_put(sr);
 }
 
+/*
+ * Return true of the object is fully active
+ */
 static __inline
 int
 sysref_isactive(struct sysref *sr)
@@ -92,6 +95,9 @@ sysref_isactive(struct sysref *sr)
        return(sr->refcnt > 0);
 }
 
+/*
+ * Return true of the object is being deactivated
+ */
 static __inline
 int
 sysref_isinactive(struct sysref *sr)
@@ -99,6 +105,16 @@ sysref_isinactive(struct sysref *sr)
        return(sr->refcnt <= 0);
 }
 
+/*
+ * Return true if we control the last deactivation ref on the object
+ */
+static __inline
+int
+sysref_islastdeactivation(struct sysref *sr)
+{
+       return(sr->refcnt == -0x40000000);
+}
+
 #ifdef _KERNEL
 
 void sysref_init(struct sysref *sr, struct sysref_class *);
index 335d502..7c81647 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     @(#)vnode.h     8.7 (Berkeley) 2/4/94
  * $FreeBSD: src/sys/sys/vnode.h,v 1.111.2.19 2002/12/29 18:19:53 dillon Exp $
- * $DragonFly: src/sys/sys/vnode.h,v 1.73 2007/04/26 02:11:00 dillon Exp $
+ * $DragonFly: src/sys/sys/vnode.h,v 1.74 2007/05/06 19:23:33 dillon Exp $
  */
 
 #ifndef _SYS_VNODE_H_
@@ -76,6 +76,9 @@
 #ifndef _SYS_SYSLINK_RPC_H_
 #include <sys/syslink_rpc.h>
 #endif
+#ifndef _SYS_SYSREF_H_
+#include <sys/sysref.h>
+#endif
 #ifndef _SYS_CCMS_H_
 #include <sys/ccms.h>
 #endif
@@ -188,10 +191,10 @@ RB_HEAD(buf_rb_hash, buf);
 
 struct vnode {
        int     v_flag;                         /* vnode flags (see below) */
-       int     v_usecount;                     /* reference count of users */
        int     v_writecount;
-       int     v_holdcnt;                      /* page & buffer references */
        int     v_opencount;                    /* number of explicit opens */
+       int     v_auxrefs;                      /* auxiliary references */
+       struct sysref v_sysref;                 /* normal references */
        struct bio_track v_track_read;          /* track I/O's in progress */
        struct bio_track v_track_write;         /* track I/O's in progress */
        struct mount *v_mount;                  /* ptr to vfs we are in */
@@ -266,9 +269,9 @@ struct vnode {
 /* open for business    0x00200 */
 /* open for business   0x00400 */
 /* open for business    0x00800 */
-/* open for business    0x01000 */
+#define VCACHED                0x01000 /* No active references but has cache value */
 #define        VOBJBUF         0x02000 /* Allocate buffers in VM object */
-#define        VINACTIVE       0x04000 /* The vnode is inactive */
+#define        VINACTIVE       0x04000 /* The vnode is inactive (did VOP_INACTIVE) */
 #define        VAGE            0x08000 /* Insert vnode at head of free list */
 #define        VOLOCK          0x10000 /* vnode is locked waiting for an object */
 #define        VOWANT          0x20000 /* a process is waiting for VOLOCK */
@@ -446,6 +449,7 @@ int v_associate_rdev(struct vnode *vp, cdev_t dev);
 void   v_release_rdev(struct vnode *vp);
 int    bdevvp (cdev_t dev, struct vnode **vpp);
 struct vnode *allocvnode(int lktimeout, int lkflags);
+int    freesomevnodes(int count);
 int    getnewvnode (enum vtagtype tag, struct mount *mp, 
                    struct vnode **vpp, int timo, int lkflags);
 int    getspecialvnode (enum vtagtype tag, struct mount *mp, 
@@ -467,9 +471,8 @@ int vmntvnodescan(struct mount *mp, int flags,
            void *data);
 void   insmntque(struct vnode *vp, struct mount *mp);
 
-void   vclean_interlocked (struct vnode *vp, int flags);
-void   vgone (struct vnode *vp);
-void   vgone_interlocked (struct vnode *vp);
+void   vclean_vxlocked (struct vnode *vp, int flags);
+void   vgone_vxlocked (struct vnode *vp);
 void   vupdatefsmid (struct vnode *vp);
 int    vinvalbuf (struct vnode *vp, int save, int slpflag, int slptimeo);
 int    vtruncbuf (struct vnode *vp, off_t length, int blksize);
@@ -547,7 +550,6 @@ void        vput (struct vnode *vp);
 void   vhold (struct vnode *);
 void   vdrop (struct vnode *);
 void   vref (struct vnode *vp);
-void   vref_initial (struct vnode *vp, int reactivate);
 void   vrele (struct vnode *vp);
 void   vsetflags (struct vnode *vp, int flags);
 void   vclrflags (struct vnode *vp, int flags);
index b30a7c3..8277497 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     @(#)fifo_vnops.c        8.10 (Berkeley) 5/27/95
  * $FreeBSD: src/sys/miscfs/fifofs/fifo_vnops.c,v 1.45.2.4 2003/04/22 10:11:24 bde Exp $
- * $DragonFly: src/sys/vfs/fifofs/fifo_vnops.c,v 1.37 2007/04/22 01:13:17 dillon Exp $
+ * $DragonFly: src/sys/vfs/fifofs/fifo_vnops.c,v 1.38 2007/05/06 19:23:33 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -529,7 +529,7 @@ fifo_close(struct vop_close_args *ap)
                if (fip->fi_writers == 0)
                        socantrcvmore(fip->fi_readsock);
        }
-       if (vp->v_usecount > 1) {
+       if (vp->v_sysref.refcnt > 1) {
                vop_stdclose(ap);
                return (0);
        }
index 9bec59d..cfd27e2 100644 (file)
@@ -38,7 +38,7 @@
  *
  *     @(#)ext2_inode.c        8.5 (Berkeley) 12/30/93
  * $FreeBSD: src/sys/gnu/ext2fs/ext2_inode.c,v 1.24.2.1 2000/08/03 00:52:57 peter Exp $
- * $DragonFly: src/sys/vfs/gnu/ext2fs/ext2_inode.c,v 1.20 2006/12/23 00:41:29 swildner Exp $
+ * $DragonFly: src/sys/vfs/gnu/ext2fs/ext2_inode.c,v 1.21 2007/05/06 19:23:33 dillon Exp $
  */
 
 #include "opt_quota.h"
@@ -477,7 +477,7 @@ ext2_inactive(struct vop_inactive_args *ap)
        int mode, error = 0;
 
        ext2_discard_prealloc(ip);
-       if (prtactive && vp->v_usecount != 1)
+       if (prtactive && vp->v_sysref.refcnt > 1)
                vprint("ext2_inactive: pushing active", vp);
 
        /*
@@ -523,7 +523,7 @@ ext2_reclaim(struct vop_reclaim_args *ap)
        int i;
 #endif
 
-       if (prtactive && vp->v_usecount != 1)
+       if (prtactive && vp->v_sysref.refcnt > 1)
                vprint("ext2_reclaim: pushing active", vp);
        ip = VTOI(vp);
 
index 6690df9..6c13dc0 100644 (file)
@@ -44,7 +44,7 @@
  *     @(#)ufs_vnops.c 8.27 (Berkeley) 5/27/95
  *     @(#)ext2_vnops.c        8.7 (Berkeley) 2/3/94
  * $FreeBSD: src/sys/gnu/ext2fs/ext2_vnops.c,v 1.51.2.2 2003/01/02 17:26:18 bde Exp $
- * $DragonFly: src/sys/vfs/gnu/ext2fs/ext2_vnops.c,v 1.37 2006/12/23 00:41:29 swildner Exp $
+ * $DragonFly: src/sys/vfs/gnu/ext2fs/ext2_vnops.c,v 1.38 2007/05/06 19:23:33 dillon Exp $
  */
 
 #include "opt_quota.h"
@@ -306,7 +306,7 @@ ext2_mknod(struct vop_old_mknod_args *ap)
         */
        (*vpp)->v_type = VNON;
        ino = ip->i_number;     /* Save this before vgone() invalidates ip. */
-       vgone(*vpp);
+       vgone_vxlocked(*vpp);
        vput(*vpp);
        error = VFS_VGET(ap->a_dvp->v_mount, ino, vpp);
        if (error) {
@@ -1331,7 +1331,7 @@ ext2_close(struct vop_close_args *ap)
 {
        struct vnode *vp = ap->a_vp;
 
-       if (vp->v_usecount > 1)
+       if (vp->v_sysref.refcnt > 1)
                ext2_itimes(vp);
        return (vop_stdclose(ap));
 }
@@ -1886,7 +1886,7 @@ ext2spec_close(struct vop_close_args *ap)
 {
        struct vnode *vp = ap->a_vp;
 
-       if (vp->v_usecount > 1)
+       if (vp->v_sysref.refcnt > 1)
                ext2_itimes(vp);
        return (VOCALL(&spec_vnode_vops, &ap->a_head));
 }
@@ -1951,7 +1951,7 @@ ext2fifo_close(struct vop_close_args *ap)
 {
        struct vnode *vp = ap->a_vp;
 
-       if (vp->v_usecount > 1)
+       if (vp->v_sysref.refcnt > 1)
                ext2_itimes(vp);
        return (VOCALL(&fifo_vnode_vops, &ap->a_head));
 }
index 18e6af9..e78fe25 100644 (file)
@@ -24,7 +24,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/fs/hpfs/hpfs_vnops.c,v 1.2.2.2 2002/01/15 18:35:09 semenu Exp $
- * $DragonFly: src/sys/vfs/hpfs/hpfs_vnops.c,v 1.39 2006/12/23 00:41:29 swildner Exp $
+ * $DragonFly: src/sys/vfs/hpfs/hpfs_vnops.c,v 1.40 2007/05/06 19:23:34 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -612,7 +612,7 @@ hpfs_inactive(struct vop_inactive_args *ap)
                        return (error);
        }
 
-       if (prtactive && vp->v_usecount != 0)
+       if (prtactive && vp->v_sysref.refcnt > 1)
                vprint("hpfs_inactive: pushing active", vp);
 
        if (hp->h_flag & H_INVAL) {
index 5344752..567fca6 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)cd9660_node.c       8.2 (Berkeley) 1/23/94
  * $FreeBSD: src/sys/isofs/cd9660/cd9660_node.c,v 1.29.2.1 2000/07/08 14:35:56 bp Exp $
- * $DragonFly: src/sys/vfs/isofs/cd9660/cd9660_node.c,v 1.20 2006/09/10 01:26:40 dillon Exp $
+ * $DragonFly: src/sys/vfs/isofs/cd9660/cd9660_node.c,v 1.21 2007/05/06 19:23:34 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -198,7 +198,7 @@ cd9660_inactive(struct vop_inactive_args *ap)
        struct iso_node *ip = VTOI(vp);
        int error = 0;
 
-       if (prtactive && vp->v_usecount != 0)
+       if (prtactive && vp->v_sysref.refcnt > 1)
                vprint("cd9660_inactive: pushing active", vp);
 
        if (ip)
@@ -223,7 +223,7 @@ cd9660_reclaim(struct vop_reclaim_args *ap)
        struct vnode *vp = ap->a_vp;
        struct iso_node *ip = VTOI(vp);
 
-       if (prtactive && vp->v_usecount != 0)
+       if (prtactive && vp->v_sysref.refcnt > 1)
                vprint("cd9660_reclaim: pushing active", vp);
        /*
         * Remove the inode from its hash chain.
index 02b9b92..d284159 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     @(#)mfs_vfsops.c        8.11 (Berkeley) 6/19/95
  * $FreeBSD: src/sys/ufs/mfs/mfs_vfsops.c,v 1.81.2.3 2001/07/04 17:35:21 tegge Exp $
- * $DragonFly: src/sys/vfs/mfs/mfs_vfsops.c,v 1.38 2007/02/25 23:17:13 corecode Exp $
+ * $DragonFly: src/sys/vfs/mfs/mfs_vfsops.c,v 1.39 2007/05/06 19:23:34 dillon Exp $
  */
 
 
@@ -345,7 +345,7 @@ mfs_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
         * the self reference between vnode and object.
         */
        vnode_pager_alloc(devvp, args.size, 0, 0);
-       --devvp->v_usecount;
+       vrele(devvp);
        --devvp->v_object->ref_count;
 
        /* Save "mounted from" info for mount point (NULL pad)*/
index 10d5d60..d0e356f 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     @(#)mfs_vnops.c 8.11 (Berkeley) 5/22/95
  * $FreeBSD: src/sys/ufs/mfs/mfs_vnops.c,v 1.47.2.1 2001/05/22 02:06:43 bp Exp $
- * $DragonFly: src/sys/vfs/mfs/mfs_vnops.c,v 1.33 2006/12/23 00:41:29 swildner Exp $
+ * $DragonFly: src/sys/vfs/mfs/mfs_vnops.c,v 1.34 2007/05/06 19:23:34 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -357,9 +357,9 @@ mfs_close(struct vop_close_args *ap)
         * There should be no way to have any more uses of this
         * vnode, so if we find any other uses, it is a panic.
         */
-       if (vp->v_usecount > 1)
-               kprintf("mfs_close: ref count %d > 1\n", vp->v_usecount);
-       if (vp->v_usecount > 1 || (bioq_first(&mfsp->bio_queue) != NULL))
+       if (vp->v_sysref.refcnt > 1)
+               kprintf("mfs_close: ref count %d > 1\n", vp->v_sysref.refcnt);
+       if (vp->v_sysref.refcnt > 1 || (bioq_first(&mfsp->bio_queue) != NULL))
                panic("mfs_close");
        /*
         * Send a request to the filesystem server to exit.
index e8f182b..5862635 100644 (file)
@@ -1,5 +1,5 @@
 /* $FreeBSD: src/sys/msdosfs/msdosfs_denode.c,v 1.47.2.3 2002/08/22 16:20:15 trhodes Exp $ */
-/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_denode.c,v 1.27 2006/12/23 00:41:29 swildner Exp $ */
+/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_denode.c,v 1.28 2007/05/06 19:23:34 dillon Exp $ */
 /*     $NetBSD: msdosfs_denode.c,v 1.28 1998/02/10 14:10:00 mrg Exp $  */
 
 /*-
@@ -659,7 +659,7 @@ msdosfs_reclaim(struct vop_reclaim_args *ap)
            dep, dep ? dep->de_Name : "?", dep ? dep->de_refcnt : -1);
 #endif
 
-       if (prtactive && vp->v_usecount != 0)
+       if (prtactive && vp->v_sysref.refcnt > 1)
                vprint("msdosfs_reclaim(): pushing active", vp);
        /*
         * Remove the denode from its hash chain.
@@ -690,7 +690,7 @@ msdosfs_inactive(struct vop_inactive_args *ap)
        kprintf("msdosfs_inactive(): dep %p, de_Name[0] %x\n", dep, dep->de_Name[0]);
 #endif
 
-       if (prtactive && vp->v_usecount != 0)
+       if (prtactive && vp->v_sysref.refcnt > 1)
                vprint("msdosfs_inactive(): pushing active", vp);
 
        /*
@@ -721,8 +721,8 @@ out:
         * so that it can be reused immediately.
         */
 #ifdef MSDOSFS_DEBUG
-       kprintf("msdosfs_inactive(): v_usecount %d, de_Name[0] %x\n", vp->v_usecount,
-              dep->de_Name[0]);
+       kprintf("msdosfs_inactive(): v_sysrefs %d, de_Name[0] %x\n",
+               vp->v_sysref.refcnt, dep->de_Name[0]);
 #endif
        if (dep->de_Name[0] == SLOT_DELETED)
                vrecycle(vp);
index 6181da1..3090a19 100644 (file)
@@ -1,5 +1,5 @@
 /* $FreeBSD: /usr/local/www/cvsroot/FreeBSD/src/sys/msdosfs/Attic/msdosfs_vfsops.c,v 1.60.2.8 2004/03/02 09:43:04 tjr Exp $ */
-/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_vfsops.c,v 1.43 2006/12/23 00:41:29 swildner Exp $ */
+/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_vfsops.c,v 1.44 2007/05/06 19:23:34 dillon Exp $ */
 /*     $NetBSD: msdosfs_vfsops.c,v 1.51 1997/11/17 15:36:58 ws Exp $   */
 
 /*-
@@ -684,8 +684,9 @@ msdosfs_unmount(struct mount *mp, int mntflags)
                struct vnode *vp = pmp->pm_devvp;
 
                kprintf("msdosfs_umount(): just before calling VOP_CLOSE()\n");
-               kprintf("flag %08lx, usecount %d, writecount %d, holdcnt %ld\n",
-                   vp->v_flag, vp->v_usecount, vp->v_writecount, vp->v_holdcnt);
+               kprintf("flag %08lx, sysrefs %d, writecount %d, auxrefs %ld\n",
+                   vp->v_flag, vp->v_sysref.refcnt,
+                   vp->v_writecount, vp->v_auxrefs);
                kprintf("mount %p, op %p\n", vp->v_mount, vp->v_op);
                kprintf("freef %p, freeb %p, mount %p\n",
                    TAILQ_NEXT(vp, v_freelist), TAILQ_PREV(vp, v_freelist),
index c167e27..86240e1 100644 (file)
@@ -1,5 +1,5 @@
 /* $FreeBSD: src/sys/msdosfs/msdosfs_vnops.c,v 1.95.2.4 2003/06/13 15:05:47 trhodes Exp $ */
-/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_vnops.c,v 1.45 2007/02/22 15:50:50 corecode Exp $ */
+/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_vnops.c,v 1.46 2007/05/06 19:23:34 dillon Exp $ */
 /*     $NetBSD: msdosfs_vnops.c,v 1.68 1998/02/10 14:10:04 mrg Exp $   */
 
 /*-
@@ -230,11 +230,9 @@ msdosfs_close(struct vop_close_args *ap)
        struct denode *dep = VTODE(vp);
        struct timespec ts;
 
-       if (vp->v_usecount > 1) {
+       if (vp->v_sysref.refcnt > 1) {
                getnanotime(&ts);
-               if (vp->v_usecount > 1) {
-                       DETIMES(dep, &ts, &ts, &ts);
-               }
+               DETIMES(dep, &ts, &ts, &ts);
        }
        return (vop_stdclose(ap));
 }
@@ -896,7 +894,8 @@ msdosfs_remove(struct vop_old_remove_args *ap)
        else
                error = removede(ddep, dep);
 #ifdef MSDOSFS_DEBUG
-       kprintf("msdosfs_remove(), dep %p, v_usecount %d\n", dep, ap->a_vp->v_usecount);
+       kprintf("msdosfs_remove(), dep %p, v_sysrefs %d\n",
+               dep, ap->a_vp->v_sysref.refcnt);
 #endif
        return (error);
 }
index 5bea938..810640f 100644 (file)
@@ -35,7 +35,7 @@
  *
  *     @(#)nfs_node.c  8.6 (Berkeley) 5/22/95
  * $FreeBSD: src/sys/nfs/nfs_node.c,v 1.36.2.3 2002/01/05 22:25:04 dillon Exp $
- * $DragonFly: src/sys/vfs/nfs/nfs_node.c,v 1.25 2006/08/12 00:26:21 dillon Exp $
+ * $DragonFly: src/sys/vfs/nfs/nfs_node.c,v 1.26 2007/05/06 19:23:34 dillon Exp $
  */
 
 
@@ -211,7 +211,7 @@ nfs_inactive(struct vop_inactive_args *ap)
        struct sillyrename *sp;
 
        np = VTONFS(ap->a_vp);
-       if (prtactive && ap->a_vp->v_usecount != 0)
+       if (prtactive && ap->a_vp->v_sysref.refcnt > 1)
                vprint("nfs_inactive: pushing active", ap->a_vp);
        if (ap->a_vp->v_type != VDIR) {
                sp = np->n_sillyrename;
@@ -228,13 +228,6 @@ nfs_inactive(struct vop_inactive_args *ap)
                 */
                nfs_vinvalbuf(ap->a_vp, 0, 1);
 
-               /*
-                * Either we have the only ref or we were vgone()'d via
-                * revoke and might have more.
-                */
-               KKASSERT(ap->a_vp->v_usecount == 1 || 
-                       (ap->a_vp->v_flag & VRECLAIMED));
-
                /*
                 * Remove the silly file that was rename'd earlier
                 */
@@ -261,7 +254,7 @@ nfs_reclaim(struct vop_reclaim_args *ap)
        struct nfsnode *np = VTONFS(vp);
        struct nfsdmap *dp, *dp2;
 
-       if (prtactive && vp->v_usecount != 0)
+       if (prtactive && vp->v_sysref.refcnt > 1)
                vprint("nfs_reclaim: pushing active", vp);
 
        if (np->n_hash.le_prev != NULL)
index 48d6268..726fa3e 100644 (file)
@@ -35,7 +35,7 @@
  *
  *     @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95
  * $FreeBSD: src/sys/nfs/nfs_vnops.c,v 1.150.2.5 2001/12/20 19:56:28 dillon Exp $
- * $DragonFly: src/sys/vfs/nfs/nfs_vnops.c,v 1.69 2006/12/23 00:41:29 swildner Exp $
+ * $DragonFly: src/sys/vfs/nfs/nfs_vnops.c,v 1.70 2007/05/06 19:23:34 dillon Exp $
  */
 
 
@@ -1574,7 +1574,7 @@ nfsmout:
  * To try and make nfs semantics closer to ufs semantics, a file that has
  * other processes using the vnode is renamed instead of removed and then
  * removed later on the last close.
- * - If v_usecount > 1
+ * - If v_sysref.refcnt > 1
  *       If a rename is not already in the works
  *          call nfs_sillyrename() to set it up
  *     else
@@ -1594,12 +1594,12 @@ nfs_remove(struct vop_old_remove_args *ap)
        struct vattr vattr;
 
 #ifndef DIAGNOSTIC
-       if (vp->v_usecount < 1)
-               panic("nfs_remove: bad v_usecount");
+       if (vp->v_sysref.refcnt < 1)
+               panic("nfs_remove: bad v_sysref.refcnt");
 #endif
        if (vp->v_type == VDIR)
                error = EPERM;
-       else if (vp->v_usecount == 1 || (np->n_sillyrename &&
+       else if (vp->v_sysref.refcnt == 1 || (np->n_sillyrename &&
            VOP_GETATTR(vp, &vattr) == 0 &&
            vattr.va_nlink > 1)) {
                /*
@@ -1715,7 +1715,7 @@ nfs_rename(struct vop_old_rename_args *ap)
         * routine.  The new API compat functions have access to the actual
         * namecache structures and will do it for us.
         */
-       if (tvp && tvp->v_usecount > 1 && !VTONFS(tvp)->n_sillyrename &&
+       if (tvp && tvp->v_sysref.refcnt > 1 && !VTONFS(tvp)->n_sillyrename &&
                tvp->v_type != VDIR && !nfs_sillyrename(tdvp, tvp, tcnp)) {
                vput(tvp);
                tvp = NULL;
@@ -3336,7 +3336,7 @@ nfsspec_close(struct vop_close_args *ap)
 
        if (np->n_flag & (NACC | NUPD)) {
                np->n_flag |= NCHG;
-               if (vp->v_usecount == 1 &&
+               if (vp->v_sysref.refcnt == 1 &&
                    (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
                        VATTR_NULL(&vattr);
                        if (np->n_flag & NACC)
@@ -3409,7 +3409,7 @@ nfsfifo_close(struct vop_close_args *ap)
                if (np->n_flag & NUPD)
                        np->n_mtim = ts;
                np->n_flag |= NCHG;
-               if (vp->v_usecount == 1 &&
+               if (vp->v_sysref.refcnt == 1 &&
                    (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
                        VATTR_NULL(&vattr);
                        if (np->n_flag & NACC)
index 82f8618..574dd79 100644 (file)
@@ -26,7 +26,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/ntfs/ntfs_vfsops.c,v 1.20.2.5 2001/12/25 01:44:45 dillon Exp $
- * $DragonFly: src/sys/vfs/ntfs/ntfs_vfsops.c,v 1.44 2006/12/23 00:41:30 swildner Exp $
+ * $DragonFly: src/sys/vfs/ntfs/ntfs_vfsops.c,v 1.45 2007/05/06 19:23:34 dillon Exp $
  */
 
 
@@ -636,7 +636,7 @@ ntfs_unmount(struct mount *mp, int mntflags)
        /* Check if only system vnodes are rest */
        for(i=0;i<NTFS_SYSNODESNUM;i++)
                 if((ntmp->ntm_sysvn[i]) && 
-                   (ntmp->ntm_sysvn[i]->v_usecount > 1)) return (EBUSY);
+                   (ntmp->ntm_sysvn[i]->v_sysref.refcnt > 1)) return (EBUSY);
 
        /* Dereference all system vnodes */
        for(i=0;i<NTFS_SYSNODESNUM;i++)
index 22fa8a8..43fda75 100644 (file)
@@ -36,7 +36,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/ntfs/ntfs_vnops.c,v 1.9.2.4 2002/08/06 19:35:18 semenu Exp $
- * $DragonFly: src/sys/vfs/ntfs/ntfs_vnops.c,v 1.38 2006/12/23 00:41:30 swildner Exp $
+ * $DragonFly: src/sys/vfs/ntfs/ntfs_vnops.c,v 1.39 2007/05/06 19:23:34 dillon Exp $
  *
  */
 
@@ -268,7 +268,7 @@ ntfs_inactive(struct vop_inactive_args *ap)
 
        dprintf(("ntfs_inactive: vnode: %p, ntnode: %d\n", vp, ip->i_number));
 
-       if (ntfs_prtactive && vp->v_usecount != 1)
+       if (ntfs_prtactive && vp->v_sysref.refcnt > 1)
                vprint("ntfs_inactive: pushing active", vp);
 
        /*
@@ -293,7 +293,7 @@ ntfs_reclaim(struct vop_reclaim_args *ap)
 
        dprintf(("ntfs_reclaim: vnode: %p, ntnode: %d\n", vp, ip->i_number));
 
-       if (ntfs_prtactive && vp->v_usecount != 1)
+       if (ntfs_prtactive && vp->v_sysref.refcnt > 1)
                vprint("ntfs_reclaim: pushing active", vp);
 
        if ((error = ntfs_ntget(ip)) != 0)
index 044a992..b9ebbc3 100644 (file)
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/nwfs/nwfs_node.c,v 1.3.2.8 2001/12/25 01:44:45 dillon Exp $
- * $DragonFly: src/sys/vfs/nwfs/nwfs_node.c,v 1.24 2006/12/23 00:41:30 swildner Exp $
+ * $DragonFly: src/sys/vfs/nwfs/nwfs_node.c,v 1.25 2007/05/06 19:23:35 dillon Exp $
  */
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -101,8 +101,9 @@ nwfs_sysctl_vnprint(SYSCTL_HANDLER_ARGS)
                LIST_FOREACH(np, nhpp, n_hash) {
                        vp = NWTOV(np);
                        vprint(NULL, vp);
-                       kprintf("%s:%d:%d:%d:%d\n",np->n_name,vp->v_usecount,vp->v_holdcnt,
-                           np->n_fid.f_id, np->n_fid.f_parent);
+                       kprintf("%s:%d:%d:%d:%d\n",
+                               np->n_name, vp->v_sysref.refcnt, vp->v_auxrefs,
+                               np->n_fid.f_id, np->n_fid.f_parent);
                }
        }
        return 0;
@@ -221,7 +222,7 @@ nwfs_reclaim(struct vop_reclaim_args *ap)
        struct nwmount *nmp = VTONWFS(vp);
        struct thread *td = curthread;  /* XXX */
        
-       NCPVNDEBUG("%s,%d\n", (np ? np->n_name : "?"), vp->v_usecount);
+       NCPVNDEBUG("%s,%d\n", (np ? np->n_name : "?"), vp->v_sysref.refcnt);
        if (np && np->n_refparent) {
                np->n_refparent = 0;
                if (nwfs_lookupnp(nmp, np->n_parent, td, &dnp) == 0) {
@@ -260,14 +261,14 @@ nwfs_inactive(struct vop_inactive_args *ap)
        KKASSERT(td->td_proc);          /* XXX */
        cred = td->td_proc->p_ucred;    /* XXX */
 
-       NCPVNDEBUG("%s: %d\n", VTONW(vp)->n_name, vp->v_usecount);
+       NCPVNDEBUG("%s: %d\n", VTONW(vp)->n_name, vp->v_sysref.refcnt);
        if (np && np->opened) {
                error = nwfs_vinvalbuf(vp, V_SAVE, 1);
                error = ncp_close_file(NWFSTOCONN(VTONWFS(vp)), &np->n_fh, td, cred);
                np->opened = 0;
        }
        if (np == NULL || (np->n_flag & NSHOULDFREE)) {
-               vgone(vp);
+               vgone_vxlocked(vp);
        }
        return (0);
 }
index 9c99caa..7c0c564 100644 (file)
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/nwfs/nwfs_vfsops.c,v 1.6.2.6 2001/10/25 19:18:54 dillon Exp $
- * $DragonFly: src/sys/vfs/nwfs/nwfs_vfsops.c,v 1.27 2006/12/23 00:41:30 swildner Exp $
+ * $DragonFly: src/sys/vfs/nwfs/nwfs_vfsops.c,v 1.28 2007/05/06 19:23:35 dillon Exp $
  */
 #include "opt_ncp.h"
 #ifndef NCP
@@ -213,7 +213,7 @@ nwfs_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
         * Lose the lock but keep the ref.
         */
        vn_unlock(vp);
-       NCPVODEBUG("rootvp.vrefcnt=%d\n",vp->v_usecount);
+       NCPVODEBUG("rootvp.vrefcnt=%d\n",vp->v_sysref.refcnt);
        return error;
 bad:
         if (nmp)
index feb3177..7eeb254 100644 (file)
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/nwfs/nwfs_vnops.c,v 1.6.2.3 2001/03/14 11:26:59 bp Exp $
- * $DragonFly: src/sys/vfs/nwfs/nwfs_vnops.c,v 1.34 2006/12/23 00:41:30 swildner Exp $
+ * $DragonFly: src/sys/vfs/nwfs/nwfs_vnops.c,v 1.35 2007/05/06 19:23:35 dillon Exp $
  */
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -454,7 +454,7 @@ nwfs_remove(struct vop_old_remove_args *ap)
        struct nwmount *nmp = VTONWFS(vp);
        int error;
 
-       if (vp->v_type == VDIR || np->opened || vp->v_usecount != 1) {
+       if (vp->v_type == VDIR || np->opened || vp->v_sysref.refcnt > 1) {
                error = EPERM;
        } else if (!ncp_conn_valid(NWFSTOCONN(nmp))) {
                error = EIO;
@@ -496,7 +496,7 @@ nwfs_rename(struct vop_old_rename_args *ap)
                goto out;
        }
 
-       if (tvp && tvp->v_usecount > 1) {
+       if (tvp && tvp->v_sysref.refcnt > 1) {
                error = EBUSY;
                goto out;
        }
@@ -537,9 +537,9 @@ out:
         * Need to get rid of old vnodes, because netware will change
         * file id on rename
         */
-       vgone(fvp);
+       vgone_vxlocked(fvp);
        if (tvp)
-               vgone(tvp);
+               vgone_vxlocked(tvp);
        /*
         * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry.
         */
index 132a40c..2e78491 100644 (file)
@@ -37,7 +37,7 @@
  *     @(#)procfs_subr.c       8.6 (Berkeley) 5/14/95
  *
  * $FreeBSD: src/sys/miscfs/procfs/procfs_subr.c,v 1.26.2.3 2002/02/18 21:28:04 des Exp $
- * $DragonFly: src/sys/vfs/procfs/procfs_subr.c,v 1.16 2007/02/19 01:14:24 corecode Exp $
+ * $DragonFly: src/sys/vfs/procfs/procfs_subr.c,v 1.17 2007/05/06 19:23:35 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -429,7 +429,7 @@ again:
                if (pfs->pfs_pid == pid) {
                        vp = PFSTOV(pfs);
                        vx_lock(vp);
-                       vgone(vp);
+                       vgone_vxlocked(vp);
                        vx_unlock(vp);
                        goto again;
                }
index 96f9195..3f73895 100644 (file)
@@ -37,7 +37,7 @@
  *     @(#)procfs_vnops.c      8.18 (Berkeley) 5/21/95
  *
  * $FreeBSD: src/sys/miscfs/procfs/procfs_vnops.c,v 1.76.2.7 2002/01/22 17:22:59 nectar Exp $
- * $DragonFly: src/sys/vfs/procfs/procfs_vnops.c,v 1.42 2007/02/19 01:14:24 corecode Exp $
+ * $DragonFly: src/sys/vfs/procfs/procfs_vnops.c,v 1.43 2007/05/06 19:23:35 dillon Exp $
  */
 
 /*
@@ -222,14 +222,8 @@ procfs_close(struct vop_close_args *ap)
                if ((ap->a_fflag & FWRITE) && (pfs->pfs_flags & O_EXCL))
                        pfs->pfs_flags &= ~(FWRITE|O_EXCL);
                /*
-                * This rather complicated-looking code is trying to
-                * determine if this was the last close on this particular
-                * vnode.  While one would expect v_usecount to be 1 at
-                * that point, it seems that (according to John Dyson)
-                * the VM system will bump up the usecount.  So:  if the
-                * usecount is 2, and VOBJBUF is set, then this is really
-                * the last close.  Otherwise, if the usecount is < 2
-                * then it is definitely the last close.
+                * v_opencount determines the last real close on the vnode.
+                *
                 * If this is the last close, then it checks to see if
                 * the target process has PF_LINGER set in p_pfsflags,
                 * if this is *not* the case, then the process' stop flags
@@ -238,7 +232,7 @@ procfs_close(struct vop_close_args *ap)
                 * told to stop on an event, but then the requesting process
                 * has gone away or forgotten about it.
                 */
-               if ((ap->a_vp->v_usecount < 2)
+               if ((ap->a_vp->v_opencount < 2)
                    && (p = pfind(pfs->pfs_pid))
                    && !(p->p_pfsflags & PF_LINGER)) {
                        p->p_stops = 0;
index c8039b8..74ab3c7 100644 (file)
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/fs/smbfs/smbfs_node.c,v 1.2.2.3 2003/01/17 08:20:26 tjr Exp $
- * $DragonFly: src/sys/vfs/smbfs/smbfs_node.c,v 1.22 2006/12/23 00:41:30 swildner Exp $
+ * $DragonFly: src/sys/vfs/smbfs/smbfs_node.c,v 1.23 2007/05/06 19:23:35 dillon Exp $
  */
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -302,7 +302,7 @@ smbfs_reclaim(struct vop_reclaim_args *ap)
        struct smbnode *np = VTOSMB(vp);
        struct smbmount *smp = VTOSMBFS(vp);
        
-       SMBVDEBUG("%s,%d\n", np->n_name, vp->v_usecount);
+       SMBVDEBUG("%s,%d\n", np->n_name, vp->v_sysref.refcnt);
 
        smbfs_hash_lock(smp, td);
 
@@ -343,7 +343,7 @@ smbfs_inactive(struct vop_inactive_args *ap)
        struct smb_cred scred;
        int error;
 
-       SMBVDEBUG("%s: %d\n", VTOSMB(vp)->n_name, vp->v_usecount);
+       SMBVDEBUG("%s: %d\n", VTOSMB(vp)->n_name, vp->v_sysref.refcnt);
        if (np->n_opencount) {
                error = smbfs_vinvalbuf(vp, V_SAVE, 1);
                cred = np->n_cached_cred;
index 70a238d..16f2355 100644 (file)
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/fs/smbfs/smbfs_vfsops.c,v 1.2.2.5 2003/01/17 08:20:26 tjr Exp $
- * $DragonFly: src/sys/vfs/smbfs/smbfs_vfsops.c,v 1.32 2006/12/23 00:41:30 swildner Exp $
+ * $DragonFly: src/sys/vfs/smbfs/smbfs_vfsops.c,v 1.33 2007/05/06 19:23:35 dillon Exp $
  */
 #include "opt_netsmb.h"
 #ifndef NETSMB
@@ -205,7 +205,7 @@ smbfs_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
        if (error)
                goto bad;
        vn_unlock(vp);
-       SMBVDEBUG("root.v_usecount = %d\n", vp->v_usecount);
+       SMBVDEBUG("root.v_sysrefs = %d\n", vp->v_sysref.refcnt);
 
 #ifdef DIAGNOSTICS
        SMBERROR("mp=%p\n", mp);
index 2dd1712..24e2488 100644 (file)
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/fs/smbfs/smbfs_vnops.c,v 1.2.2.8 2003/04/04 08:57:23 tjr Exp $
- * $DragonFly: src/sys/vfs/smbfs/smbfs_vnops.c,v 1.37 2007/01/29 06:10:01 dillon Exp $
+ * $DragonFly: src/sys/vfs/smbfs/smbfs_vnops.c,v 1.38 2007/05/06 19:23:35 dillon Exp $
  */
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -516,7 +516,7 @@ smbfs_remove(struct vop_old_remove_args *ap)
        struct smb_cred scred;
        int error;
 
-       if (vp->v_type == VDIR || np->n_opencount || vp->v_usecount != 1)
+       if (vp->v_type == VDIR || np->n_opencount || vp->v_sysref.refcnt > 1)
                return EPERM;
        smb_makescred(&scred, cnp->cn_td, cnp->cn_cred);
        error = smbfs_smb_delete(np, &scred);
@@ -550,7 +550,7 @@ smbfs_rename(struct vop_old_rename_args *ap)
                goto out;
        }
 
-       if (tvp && tvp->v_usecount > 1) {
+       if (tvp && tvp->v_sysref.refcnt > 1) {
                error = EBUSY;
                goto out;
        }
@@ -600,9 +600,9 @@ out:
        vrele(fvp);
 #ifdef possible_mistake
 #error x
-       vgone(fvp);
+       vgone_vxlocked(fvp);
        if (tvp)
-               vgone(tvp);
+               vgone_vxlocked(tvp);
 #endif
        return error;
 }
index be2764a..6b6324d 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)ufs_inode.c 8.9 (Berkeley) 5/14/95
  * $FreeBSD: src/sys/ufs/ufs/ufs_inode.c,v 1.25.2.3 2002/07/05 22:42:31 dillon Exp $
- * $DragonFly: src/sys/vfs/ufs/ufs_inode.c,v 1.21 2006/12/23 00:41:30 swildner Exp $
+ * $DragonFly: src/sys/vfs/ufs/ufs_inode.c,v 1.22 2007/05/06 19:23:35 dillon Exp $
  */
 
 #include "opt_quota.h"
@@ -73,7 +73,7 @@ ufs_inactive(struct vop_inactive_args *ap)
        struct inode *ip = VTOI(vp);
        int mode, error = 0;
 
-       if (prtactive && vp->v_usecount != 1)
+       if (prtactive && vp->v_sysref.refcnt > 1)
                vprint("ufs_inactive: pushing active", vp);
 
        /*
@@ -119,7 +119,7 @@ ufs_reclaim(struct vop_reclaim_args *ap)
        int i;
 #endif
 
-       if (prtactive && vp->v_usecount != 1)
+       if (prtactive && vp->v_sysref.refcnt > 1)
                vprint("ufs_reclaim: pushing active", vp);
        ip = VTOI(vp);
 
index 781837b..d811262 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)ufs_vnops.c 8.27 (Berkeley) 5/27/95
  * $FreeBSD: src/sys/ufs/ufs/ufs_vnops.c,v 1.131.2.8 2003/01/02 17:26:19 bde Exp $
- * $DragonFly: src/sys/vfs/ufs/ufs_vnops.c,v 1.58 2006/12/23 00:41:30 swildner Exp $
+ * $DragonFly: src/sys/vfs/ufs/ufs_vnops.c,v 1.59 2007/05/06 19:23:35 dillon Exp $
  */
 
 #include "opt_quota.h"
@@ -241,7 +241,7 @@ ufs_mknod(struct vop_old_mknod_args *ap)
         */
        (*vpp)->v_type = VNON;
        ino = ip->i_number;     /* Save this before vgone() invalidates ip. */
-       vgone(*vpp);
+       vgone_vxlocked(*vpp);
        vput(*vpp);
        error = VFS_VGET(ap->a_dvp->v_mount, ino, vpp);
        if (error) {
@@ -292,7 +292,7 @@ ufs_close(struct vop_close_args *ap)
 {
        struct vnode *vp = ap->a_vp;
 
-       if (vp->v_usecount > 1)
+       if (vp->v_sysref.refcnt > 1)
                ufs_itimes(vp);
        return (vop_stdclose(ap));
 }
@@ -1939,7 +1939,7 @@ ufsspec_close(struct vop_close_args *ap)
 {
        struct vnode *vp = ap->a_vp;
 
-       if (vp->v_usecount > 1)
+       if (vp->v_sysref.refcnt > 1)
                ufs_itimes(vp);
        return (VOCALL(&spec_vnode_vops, &ap->a_head));
 }
@@ -2005,7 +2005,7 @@ ufsfifo_close(struct vop_close_args *ap)
 {
        struct vnode *vp = ap->a_vp;
 
-       if (vp->v_usecount > 1)
+       if (vp->v_sysref.refcnt > 1)
                ufs_itimes(vp);
        return (VOCALL(&fifo_vnode_vops, &ap->a_head));
 }
index 59d053a..5833a14 100644 (file)
@@ -36,7 +36,7 @@
  *
  *     @(#)union_subr.c        8.20 (Berkeley) 5/20/95
  * $FreeBSD: src/sys/miscfs/union/union_subr.c,v 1.43.2.2 2001/12/25 01:44:45 dillon Exp $
- * $DragonFly: src/sys/vfs/union/union_subr.c,v 1.27 2006/09/05 00:55:51 dillon Exp $
+ * $DragonFly: src/sys/vfs/union/union_subr.c,v 1.28 2007/05/06 19:23:35 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -464,16 +464,16 @@ loop:
                 */
                UDEBUG(("Modify existing un %p vn %p upper %p(refs %d) -> %p(refs %d)\n",
                        un, un->un_vnode, un->un_uppervp, 
-                       (un->un_uppervp ? un->un_uppervp->v_usecount : -99),
+                       (un->un_uppervp ? un->un_uppervp->v_sysref.refcnt : -99),
                        uppervp,
-                       (uppervp ? uppervp->v_usecount : -99)
+                       (uppervp ? uppervp->v_sysref.refcnt : -99)
                ));
 
                if (uppervp != un->un_uppervp) {
-                       KASSERT(uppervp == NULL || uppervp->v_usecount > 0, ("union_allocvp: too few refs %d (at least 1 required) on uppervp", uppervp->v_usecount));
+                       KASSERT(uppervp == NULL || uppervp->v_sysref.refcnt > 0, ("union_allocvp: too few refs %d (at least 1 required) on uppervp", uppervp->v_sysref.refcnt));
                        union_newupper(un, uppervp);
                } else if (uppervp) {
-                       KASSERT(uppervp->v_usecount > 1, ("union_allocvp: too few refs %d (at least 2 required) on uppervp", uppervp->v_usecount));
+                       KASSERT(uppervp->v_sysref.refcnt > 1, ("union_allocvp: too few refs %d (at least 2 required) on uppervp", uppervp->v_sysref.refcnt));
                        vrele(uppervp);
                }
 
@@ -736,7 +736,7 @@ union_copyup(struct union_node *un, int docopy, struct ucred *cred,
 
        lvp = un->un_lowervp;
 
-       KASSERT(uvp->v_usecount > 0, ("copy: uvp refcount 0: %d", uvp->v_usecount));
+       KASSERT(uvp->v_sysref.refcnt > 0, ("copy: uvp refcount 0: %d", uvp->v_sysref.refcnt));
        if (docopy) {
                /*
                 * XX - should not ignore errors
@@ -755,9 +755,9 @@ union_copyup(struct union_node *un, int docopy, struct ucred *cred,
        }
        vn_unlock(uvp);
        union_newupper(un, uvp);
-       KASSERT(uvp->v_usecount > 0, ("copy: uvp refcount 0: %d", uvp->v_usecount));
+       KASSERT(uvp->v_sysref.refcnt > 0, ("copy: uvp refcount 0: %d", uvp->v_sysref.refcnt));
        union_vn_close(uvp, FWRITE, cred);
-       KASSERT(uvp->v_usecount > 0, ("copy: uvp refcount 0: %d", uvp->v_usecount));
+       KASSERT(uvp->v_sysref.refcnt > 0, ("copy: uvp refcount 0: %d", uvp->v_sysref.refcnt));
        /*
         * Subsequent IOs will go to the top layer, so
         * call close on the lower vnode and open on the
@@ -1161,10 +1161,10 @@ union_dircache(struct vnode *vp, struct thread *td)
                goto out;
 
        /*vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY);*/
-       UDEBUG(("ALLOCVP-3 %p ref %d\n", *vpp, (*vpp ? (*vpp)->v_usecount : -99)));
+       UDEBUG(("ALLOCVP-3 %p ref %d\n", *vpp, (*vpp ? (*vpp)->v_sysref.refcnt : -99)));
        vref(*vpp);
        error = union_allocvp(&nvp, vp->v_mount, NULLVP, NULLVP, NULL, *vpp, NULLVP, 0);
-       UDEBUG(("ALLOCVP-3B %p ref %d\n", nvp, (*vpp ? (*vpp)->v_usecount : -99)));
+       UDEBUG(("ALLOCVP-3B %p ref %d\n", nvp, (*vpp ? (*vpp)->v_sysref.refcnt : -99)));
        if (error)
                goto out;
 
index 9d6580e..648f667 100644 (file)
@@ -36,7 +36,7 @@
  *
  *     @(#)union_vnops.c       8.32 (Berkeley) 6/23/95
  * $FreeBSD: src/sys/miscfs/union/union_vnops.c,v 1.72 1999/12/15 23:02:14 eivind Exp $
- * $DragonFly: src/sys/vfs/union/union_vnops.c,v 1.36 2006/12/23 00:41:30 swildner Exp $
+ * $DragonFly: src/sys/vfs/union/union_vnops.c,v 1.37 2007/05/06 19:23:35 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -115,7 +115,7 @@ union_lock_upper(struct union_node *un, struct thread *td)
                vref(uppervp);
                vn_lock(uppervp, LK_EXCLUSIVE | LK_CANRECURSE | LK_RETRY);
        }
-       KASSERT((uppervp == NULL || uppervp->v_usecount > 0), ("uppervp usecount is 0"));
+       KASSERT((uppervp == NULL || uppervp->v_sysref.refcnt > 0), ("uppervp usecount is 0"));
        return(uppervp);
 }
 
@@ -371,10 +371,10 @@ union_lookup(struct vop_old_lookup_args *ap)
                    "uerror %d upperdvp %p %d/%d, uppervp %p ref=%d/lck=%d\n",
                    uerror,
                    upperdvp,
-                   upperdvp->v_usecount,
+                   upperdvp->v_sysref.refcnt,
                    vn_islocked(upperdvp),
                    uppervp,
-                   (uppervp ? uppervp->v_usecount : -99),
+                   (uppervp ? uppervp->v_sysref.refcnt : -99),
                    (uppervp ? vn_islocked(uppervp) : -99)
                ));
 
@@ -551,7 +551,7 @@ union_lookup(struct vop_old_lookup_args *ap)
        error = union_allocvp(ap->a_vpp, dvp->v_mount, dvp, upperdvp, cnp,
                              uppervp, lowervp, 1);
 
-       UDEBUG(("Create %p = %p %p refs=%d\n", *ap->a_vpp, uppervp, lowervp, (*ap->a_vpp) ? ((*ap->a_vpp)->v_usecount) : -99));
+       UDEBUG(("Create %p = %p %p refs=%d\n", *ap->a_vpp, uppervp, lowervp, (*ap->a_vpp) ? ((*ap->a_vpp)->v_sysref.refcnt) : -99));
 
        uppervp = NULL;
        upperdvp = NULL;
@@ -591,7 +591,7 @@ out:
                cnp->cn_flags &= ~CNP_LOCKPARENT;
 
        UDEBUG(("Out %d vpp %p/%d lower %p upper %p\n", error, *ap->a_vpp,
-               ((*ap->a_vpp) ? (*ap->a_vpp)->v_usecount : -99),
+               ((*ap->a_vpp) ? (*ap->a_vpp)->v_sysref.refcnt : -99),
                lowervp, uppervp));
 
        /*
@@ -653,10 +653,10 @@ union_create(struct vop_old_create_args *ap)
                if (error == 0) {
                        mp = ap->a_dvp->v_mount;
                        vn_unlock(vp);
-                       UDEBUG(("ALLOCVP-1 FROM %p REFS %d\n", vp, vp->v_usecount));
+                       UDEBUG(("ALLOCVP-1 FROM %p REFS %d\n", vp, vp->v_sysref.refcnt));
                        error = union_allocvp(ap->a_vpp, mp, NULLVP, NULLVP,
                                cnp, vp, NULLVP, 1);
-                       UDEBUG(("ALLOCVP-2B FROM %p REFS %d\n", *ap->a_vpp, vp->v_usecount));
+                       UDEBUG(("ALLOCVP-2B FROM %p REFS %d\n", *ap->a_vpp, vp->v_sysref.refcnt));
                }
                union_unlock_upper(dvp, td);
        }
@@ -1161,7 +1161,7 @@ union_revoke(struct vop_revoke_args *ap)
                VOP_REVOKE(vx, ap->a_flags);
                vx_put(vx);
        }
-       vgone(vp);
+       vgone_vxlocked(vp);
        return (0);
 }
 
@@ -1497,10 +1497,10 @@ union_mkdir(struct vop_old_mkdir_args *ap)
 
                if (error == 0) {
                        vn_unlock(vp);
-                       UDEBUG(("ALLOCVP-2 FROM %p REFS %d\n", vp, vp->v_usecount));
+                       UDEBUG(("ALLOCVP-2 FROM %p REFS %d\n", vp, vp->v_sysref.refcnt));
                        error = union_allocvp(ap->a_vpp, ap->a_dvp->v_mount,
                                ap->a_dvp, NULLVP, cnp, vp, NULLVP, 1);
-                       UDEBUG(("ALLOCVP-2B FROM %p REFS %d\n", *ap->a_vpp, vp->v_usecount));
+                       UDEBUG(("ALLOCVP-2B FROM %p REFS %d\n", *ap->a_vpp, vp->v_sysref.refcnt));
                }
        }
        return (error);
@@ -1658,7 +1658,7 @@ union_inactive(struct vop_inactive_args *ap)
 #endif
 
        if ((un->un_flags & UN_CACHED) == 0)
-               vgone(vp);
+               vgone_vxlocked(vp);
 
        return (0);
 }
index 8ec4fdd..a912327 100644 (file)
@@ -39,7 +39,7 @@
  *
  *     from: @(#)vnode_pager.c 7.5 (Berkeley) 4/20/91
  * $FreeBSD: src/sys/vm/vnode_pager.c,v 1.116.2.7 2002/12/31 09:34:51 dillon Exp $
- * $DragonFly: src/sys/vm/vnode_pager.c,v 1.32 2006/12/23 00:41:31 swildner Exp $
+ * $DragonFly: src/sys/vm/vnode_pager.c,v 1.33 2007/05/06 19:23:36 dillon Exp $
  */
 
 /*
@@ -137,7 +137,7 @@ vnode_pager_alloc(void *handle, off_t size, vm_prot_t prot, off_t offset)
                tsleep(object, 0, "vadead", 0);
        }
 
-       if (vp->v_usecount == 0)
+       if (vp->v_sysref.refcnt <= 0)
                panic("vnode_pager_alloc: no vnode reference");
 
        if (object == NULL) {
@@ -154,7 +154,7 @@ vnode_pager_alloc(void *handle, off_t size, vm_prot_t prot, off_t offset)
                if (vp->v_filesize != size)
                        kprintf("vnode_pager_alloc: Warning, filesize mismatch %lld/%lld\n", vp->v_filesize, size);
        }
-       vp->v_usecount++;
+       vref(vp);
 
        vp->v_flag &= ~VOLOCK;
        if (vp->v_flag & VOWANT) {