--- /dev/null
+From 5c47e6d0ad608987b91affbcf7d1fc12dfbe8fb4 Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Tue, 29 Apr 2014 16:13:18 -0400
+Subject: fold try_prune_one_dentry()
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit 5c47e6d0ad608987b91affbcf7d1fc12dfbe8fb4 upstream.
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Cc: "Nicholas A. Bellinger" <nab@linux-iscsi.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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();
+ }