From: Greg Kroah-Hartman Date: Fri, 14 Aug 2015 16:48:18 +0000 (-0700) Subject: 3.14-stable patches X-Git-Tag: v3.10.87~13 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b2a6b5c3f39bce639ccfc991a32c76ff6ea7e462;p=thirdparty%2Fkernel%2Fstable-queue.git 3.14-stable patches added patches: fold-try_prune_one_dentry.patch --- diff --git a/queue-3.14/fold-try_prune_one_dentry.patch b/queue-3.14/fold-try_prune_one_dentry.patch new file mode 100644 index 00000000000..46d9f3bbda2 --- /dev/null +++ b/queue-3.14/fold-try_prune_one_dentry.patch @@ -0,0 +1,115 @@ +From 5c47e6d0ad608987b91affbcf7d1fc12dfbe8fb4 Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Tue, 29 Apr 2014 16:13:18 -0400 +Subject: fold try_prune_one_dentry() + +From: Al Viro + +commit 5c47e6d0ad608987b91affbcf7d1fc12dfbe8fb4 upstream. + +Signed-off-by: Al Viro +Cc: "Nicholas A. Bellinger" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/dcache.c | 75 ++++++++++++++++++++---------------------------------------- + 1 file changed, 25 insertions(+), 50 deletions(-) + +--- a/fs/dcache.c ++++ b/fs/dcache.c +@@ -788,47 +788,9 @@ restart: + } + EXPORT_SYMBOL(d_prune_aliases); + +-/* +- * Try to throw away a dentry - free the inode, dput the parent. +- * Requires dentry->d_lock is held, and dentry->d_count == 0. +- * Releases dentry->d_lock. +- * +- * This may fail if locks cannot be acquired no problem, just try again. +- */ +-static struct dentry * try_prune_one_dentry(struct dentry *dentry) +- __releases(dentry->d_lock) +-{ +- struct dentry *parent; +- +- parent = dentry_kill(dentry, 0); +- /* +- * If dentry_kill returns NULL, we have nothing more to do. +- * if it returns the same dentry, trylocks failed. In either +- * case, just loop again. +- * +- * Otherwise, we need to prune ancestors too. This is necessary +- * to prevent quadratic behavior of shrink_dcache_parent(), but +- * is also expected to be beneficial in reducing dentry cache +- * fragmentation. +- */ +- if (!parent) +- return NULL; +- if (parent == dentry) +- return dentry; +- +- /* Prune ancestors. */ +- dentry = parent; +- while (dentry) { +- if (lockref_put_or_lock(&dentry->d_lockref)) +- return NULL; +- dentry = dentry_kill(dentry, 1); +- } +- return NULL; +-} +- + static void shrink_dentry_list(struct list_head *list) + { +- struct dentry *dentry; ++ struct dentry *dentry, *parent; + + rcu_read_lock(); + for (;;) { +@@ -864,22 +826,35 @@ static void shrink_dentry_list(struct li + } + rcu_read_unlock(); + ++ parent = dentry_kill(dentry, 0); + /* +- * If 'try_to_prune()' returns a dentry, it will +- * be the same one we passed in, and d_lock will +- * have been held the whole time, so it will not +- * have been added to any other lists. We failed +- * to get the inode lock. +- * +- * We just add it back to the shrink list. ++ * If dentry_kill returns NULL, we have nothing more to do. + */ +- dentry = try_prune_one_dentry(dentry); +- +- rcu_read_lock(); +- if (dentry) { ++ if (!parent) { ++ rcu_read_lock(); ++ continue; ++ } ++ if (unlikely(parent == dentry)) { ++ /* ++ * trylocks have failed and d_lock has been held the ++ * whole time, so it could not have been added to any ++ * other lists. Just add it back to the shrink list. ++ */ ++ rcu_read_lock(); + d_shrink_add(dentry, list); + spin_unlock(&dentry->d_lock); ++ continue; + } ++ /* ++ * We need to prune ancestors too. This is necessary to prevent ++ * quadratic behavior of shrink_dcache_parent(), but is also ++ * expected to be beneficial in reducing dentry cache ++ * fragmentation. ++ */ ++ dentry = parent; ++ while (dentry && !lockref_put_or_lock(&dentry->d_lockref)) ++ dentry = dentry_kill(dentry, 1); ++ rcu_read_lock(); + } + rcu_read_unlock(); + } diff --git a/queue-3.14/series b/queue-3.14/series index 930341d8450..faaa532ba6f 100644 --- a/queue-3.14/series +++ b/queue-3.14/series @@ -31,3 +31,4 @@ signalfd-fix-information-leak-in-signalfd_copyinfo.patch signal-fix-information-leak-in-copy_siginfo_to_user.patch signal-fix-information-leak-in-copy_siginfo_from_user32.patch fold-d_kill-and-d_free.patch +fold-try_prune_one_dentry.patch