Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/kern cleanvnode():



details:   https://anonhg.NetBSD.org/src/rev/2103d1d70c90
branches:  trunk
changeset: 791075:2103d1d70c90
user:      hannken <hannken%NetBSD.org@localhost>
date:      Sun Nov 03 08:33:00 2013 +0000

description:
cleanvnode():
- VC_XLOCK/VC_MASK are not used anymore, remove.
- If we get a reference while cleaning, there is no need to retry as
  these reference and this vnode will disappear soon.
- Make sure we run inside a fstrans transaction to prevent deadlocks
  against vget().

vrecycle():
- don't even try to recycle a vnode currently cleaning.

diffstat:

 sys/kern/vfs_vnode.c |  78 ++++++++++++++++------------------------------------
 1 files changed, 24 insertions(+), 54 deletions(-)

diffs (156 lines):

diff -r f2e1fe2ab8e4 -r 2103d1d70c90 sys/kern/vfs_vnode.c
--- a/sys/kern/vfs_vnode.c      Sun Nov 03 01:12:16 2013 +0000
+++ b/sys/kern/vfs_vnode.c      Sun Nov 03 08:33:00 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: vfs_vnode.c,v 1.23 2013/10/29 09:53:51 hannken Exp $   */
+/*     $NetBSD: vfs_vnode.c,v 1.24 2013/11/03 08:33:00 hannken Exp $   */
 
 /*-
  * Copyright (c) 1997-2011 The NetBSD Foundation, Inc.
@@ -106,18 +106,8 @@
  *     from zero, the interlock must be held.  To change from a non-zero
  *     value to zero, again the interlock must be held.
  *
- *     There is a flag bit, VC_XLOCK, embedded in v_usecount.  To raise
- *     v_usecount, if the VC_XLOCK bit is set in it, the interlock must
- *     be held.  To modify the VC_XLOCK bit, the interlock must be held.
- *     We always keep the usecount (v_usecount & VC_MASK) non-zero while
- *     the VC_XLOCK bit is set.
- *
- *     Unless the VC_XLOCK bit is set, changing the usecount from a non-zero
- *     value to a non-zero value can safely be done using atomic operations,
- *     without the interlock held.
- *
- *     Even if the VC_XLOCK bit is set, decreasing the usecount to a non-zero
- *     value can be done using atomic operations, without the interlock held.
+ *     Changing the usecount from a non-zero value to a non-zero value can
+ *     safely be done using atomic operations, without the interlock held.
  *
  *     Note: if VI_CLEAN is set, vnode_t::v_interlock will be released while
  *     mntvnode_lock is still held.
@@ -126,7 +116,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.23 2013/10/29 09:53:51 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.24 2013/11/03 08:33:00 hannken Exp $");
 
 #define _VFS_VNODE_PRIVATE
 
@@ -148,14 +138,11 @@
 #include <sys/systm.h>
 #include <sys/vnode.h>
 #include <sys/wapbl.h>
+#include <sys/fstrans.h>
 
 #include <uvm/uvm.h>
 #include <uvm/uvm_readahead.h>
 
-/* v_usecount; see the comment near the top of vfs_vnode.c */
-#define        VC_XLOCK        0x80000000
-#define        VC_MASK         0x7fffffff
-
 #define        DOCLOSE         0x0008          /* vclean: close active files */
 
 /* Flags to vrelel. */
@@ -284,9 +271,10 @@
 {
        vnode_t *vp;
        vnodelst_t *listhd;
+       struct mount *mp;
 
        KASSERT(mutex_owned(&vnode_free_list_lock));
-retry:
+
        listhd = &vnode_free_list;
 try_nextlist:
        TAILQ_FOREACH(vp, listhd, v_freelist) {
@@ -302,9 +290,16 @@
 
                if (!mutex_tryenter(vp->v_interlock))
                        continue;
-               if ((vp->v_iflag & VI_XLOCK) == 0)
-                       break;
-               mutex_exit(vp->v_interlock);
+               if ((vp->v_iflag & VI_XLOCK) != 0) {
+                       mutex_exit(vp->v_interlock);
+                       continue;
+               }
+               mp = vp->v_mount;
+               if (fstrans_start_nowait(mp, FSTRANS_SHARED) != 0) {
+                       mutex_exit(vp->v_interlock);
+                       continue;
+               }
+               break;
        }
 
        if (vp == NULL) {
@@ -326,37 +321,12 @@
        /*
         * The vnode is still associated with a file system, so we must
         * clean it out before freeing it.  We need to add a reference
-        * before doing this.  If the vnode gains another reference while
-        * being cleaned out then we lose - retry.
+        * before doing this.
         */
-       atomic_add_int(&vp->v_usecount, 1 + VC_XLOCK);
+       vp->v_usecount = 1;
        vclean(vp, DOCLOSE);
-       KASSERT(vp->v_usecount >= 1 + VC_XLOCK);
-       atomic_add_int(&vp->v_usecount, -VC_XLOCK);
-       if (vp->v_usecount > 1) {
-               /*
-                * Don't return to freelist - the holder of the last
-                * reference will destroy it.
-                */
-               vrelel(vp, 0); /* releases vp->v_interlock */
-               mutex_enter(&vnode_free_list_lock);
-               goto retry;
-       }
-
-       KASSERT((vp->v_iflag & VI_CLEAN) == VI_CLEAN);
-       mutex_exit(vp->v_interlock);
-       if (vp->v_type == VBLK || vp->v_type == VCHR) {
-               spec_node_destroy(vp);
-       }
-       vp->v_type = VNON;
-
-       KASSERT(vp->v_data == NULL);
-       KASSERT(vp->v_uobj.uo_npages == 0);
-       KASSERT(TAILQ_EMPTY(&vp->v_uobj.memq));
-       KASSERT(vp->v_numoutput == 0);
-       KASSERT((vp->v_iflag & VI_ONWORKLST) == 0);
-
-       vrele(vp);
+       vrelel(vp, 0);
+       fstrans_done(mp);
 
        return 0;
 }
@@ -604,7 +574,7 @@
                if (use == 1) {
                        return false;
                }
-               KASSERT((use & VC_MASK) > 1);
+               KASSERT(use > 1);
                next = atomic_cas_uint(&vp->v_usecount, use, use - 1);
                if (__predict_true(next == use)) {
                        return true;
@@ -990,7 +960,7 @@
                atomic_add_int(&uvmexp.filepages, vp->v_uobj.uo_npages);
        }
        vp->v_iflag &= ~(VI_TEXT|VI_EXECMAP);
-       active = (vp->v_usecount & VC_MASK) > 1;
+       active = (vp->v_usecount > 1);
 
        /* XXXAD should not lock vnode under layer */
        mutex_exit(vp->v_interlock);
@@ -1085,7 +1055,7 @@
        KASSERT((vp->v_iflag & VI_MARKER) == 0);
 
        mutex_enter(vp->v_interlock);
-       if (vp->v_usecount != 0) {
+       if (vp->v_usecount != 0 || (vp->v_iflag & (VI_CLEAN|VI_XLOCK)) != 0) {
                mutex_exit(vp->v_interlock);
                return 0;
        }



Home | Main Index | Thread Index | Old Index