[Devel] [PATCH RHEL7 COMMIT] dcache: zap dentry_lru_del()

Konstantin Khorenko khorenko at virtuozzo.com
Thu Mar 24 08:14:59 PDT 2016


The commit is pushed to "branch-rh7-3.10.0-327.10.1.vz7.12.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-327.10.1.vz7.12.3
------>
commit e3404b80739f173730712b8dfcb47dea1cde167d
Author: Vladimir Davydov <vdavydov at virtuozzo.com>
Date:   Thu Mar 24 19:14:59 2016 +0400

    dcache: zap dentry_lru_del()
    
    dentry_lru_del() is buggy - it tries to remove a dentry from a shrink
    list, which is not protected by any locks and can only be safely
    modified by a caller of dcache shrinker. Previous two patches replaced
    this function calls with d_lru_del() and corresponding checks in two
    places where it could result in corrupting shrink lists - dentry_kill()
    and select_collect(). The only place left, shrink_dcache_for_umount(),
    should be safe, because shrinker should be already unregistered there.
    
    Still, to make sure that it doesn't race with a shrinker, let's replace
    dentry_lru_del() with d_lru_del() there and make it issue a warning if
    it encounters a dentry which is on a shrink list. After that
    dentry_lru_del() is not used anywhere and can be removed. Note, it was
    removed upstream either, but there are quite a few patches to be
    backported.
    
    Signed-off-by: Vladimir Davydov <vdavydov at virtuozzo.com>
    Acked-by: Dmitry Monakhov <dmonakhov at virtuozzo.com>
---
 fs/dcache.c | 20 +++-----------------
 1 file changed, 3 insertions(+), 17 deletions(-)

diff --git a/fs/dcache.c b/fs/dcache.c
index cba54cf..518c519 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -427,22 +427,6 @@ static void dentry_lru_add(struct dentry *dentry)
 		d_lru_add(dentry);
 }
 
-/*
- * Remove a dentry with references from the LRU.
- *
- * If we are on the shrink list, then we can get to try_prune_one_dentry() and
- * lose our last reference through the parent walk. In this case, we need to
- * remove ourselves from the shrink list, not the LRU.
- */
-static void dentry_lru_del(struct dentry *dentry)
-{
-	if (dentry->d_flags & DCACHE_LRU_LIST) {
-		if (dentry->d_flags & DCACHE_SHRINK_LIST)
-			return d_shrink_del(dentry);
-		d_lru_del(dentry);
-	}
-}
-
 /**
  * d_kill - kill dentry and return parent
  * @dentry: dentry to kill
@@ -1109,7 +1093,9 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
 			    !d_unhashed(dentry))
 				dentry->d_op->d_prune(dentry);
 
-			dentry_lru_del(dentry);
+			WARN_ON_ONCE(dentry->d_flags & DCACHE_SHRINK_LIST);
+			if (dentry->d_flags & DCACHE_LRU_LIST)
+				d_lru_del(dentry);
 			__d_shrink(dentry);
 
 			if (dentry->d_lockref.count != 0) {


More information about the Devel mailing list