[RHEL7,COMMIT] rh/fs/dcache.c: Revert "fs/dcache.c: add cond_resched() in shrink_dentry_list()"

Submitted by Konstantin Khorenko on Aug. 23, 2018, 4:13 p.m.

Details

Message ID 201808231613.w7NGDndU004236@finist_ce7.work
State New
Series "rh/fs/dcache.c: Revert "fs/dcache.c: add cond_resched() in shrink_dentry_list()""
Headers show

Commit Message

Konstantin Khorenko Aug. 23, 2018, 4:13 p.m.
The commit is pushed to "branch-rh7-3.10.0-862.11.6.vz7.64.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-862.11.6.vz7.64.6
------>
commit 1698214d6a3175b479483557794a182b20d6dae6
Author: Konstantin Khorenko <khorenko@virtuozzo.com>
Date:   Thu Aug 23 18:45:57 2018 +0300

    rh/fs/dcache.c: Revert "fs/dcache.c: add cond_resched() in shrink_dentry_list()"
    
    This reverts RedHat patch
    - [fs] dcache.c: add cond_resched() in shrink_dentry_list()
      (Aaron Tomlin) [1596184 1584693]
    
    Which is a backport of mainstream patch
    32785c0539b7 ("fs/dcache.c: add cond_resched() in shrink_dentry_list()")
    
    RedHat has added this patch due to:
    https://access.redhat.com/solutions/3465291
    
    We rollback RedHat's patch because we face endless loop in
    d_invalidate() caused by cond_resched() in shrink_dentry_list().
    
    Short story:
    
    "mount" process                 "systemd" process
    sys_mount
     do_mount
      do_remount_sb
       shrink_dcache_sb
        // put dentries in
        // "dispose" list
        shrink_dentry_list
         cond_resched
          __schedule                sys_waitid
                                     do_wait
                                      wait_consider_task
                                       release_task
                                        proc_flush_task
                                         d_invalidate // livelock
                                          d_walk
    
    d_walk() in "systemd" faces dentries which are in "dispose" list in
    shrink_dcache_sb() in "mount" process =>
    on first iteration "data.select.found" is greater than the number of
    dentries in "data.select.dispose" list,
    on next iterations
    
      data.select.found > 0 && list_empty(&data.select.dispose)
    
    => livelock.
    
    LKML related discussions and patches:
    https://lkml.org/lkml/2018/4/13/603
    https://lkml.org/lkml/2018/6/3/177
    
    https://jira.sw.ru/browse/PSBM-87864
    
    Signed-off-by: Konstantin Khorenko <khorenko@virtuozzo.com>
---
 fs/dcache.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

Patch hide | download patch | download mbox

diff --git a/fs/dcache.c b/fs/dcache.c
index b7bdf01fb548..085264fad542 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -850,8 +850,6 @@  static void shrink_dentry_list(struct list_head *list)
 	while (!list_empty(list)) {
 		struct inode *inode;
 
-		cond_resched();
-
 		dentry = list_entry(list->prev, struct dentry, d_lru);
 		spin_lock(&dentry->d_lock);
 		parent = lock_parent(dentry);
@@ -1479,6 +1477,7 @@  void shrink_dcache_parent(struct dentry *parent)
 			break;
 
 		shrink_dentry_list(&data.dispose);
+		cond_resched();
 	}
 }
 EXPORT_SYMBOL(shrink_dcache_parent);
@@ -1561,6 +1560,8 @@  int d_invalidate(struct dentry *dentry)
 
 		if (!data.mountpoint && !data.select.found)
 			return 0;
+
+		cond_resched();
 	}
 }
 EXPORT_SYMBOL(d_invalidate);