From 8cbdfa013bd1eb26576fe9f787a6d391023930d0 Mon Sep 17 00:00:00 2001
From: Thomas Gleixner <tglx@linutronix.de>
Date: Wed, 7 Mar 2012 21:00:34 +0100
Subject: [PATCH 167/398] fs: dcache: Use cpu_chill() in trylock loops

Retry loops on RT might loop forever when the modifying side was
preempted. Use cpu_chill() instead of cpu_relax() to let the system
make progress.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 fs/autofs4/autofs_i.h |  1 +
 fs/autofs4/expire.c   |  2 +-
 fs/dcache.c           | 10 ++++++++--
 fs/namespace.c        |  3 ++-
 4 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index 502d3892d8a4..05af8d3e6e88 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -34,6 +34,7 @@
 #include <linux/sched.h>
 #include <linux/mount.h>
 #include <linux/namei.h>
+#include <linux/delay.h>
 #include <asm/current.h>
 #include <asm/uaccess.h>
 
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index 7a5a598a2d94..d08bcdc30566 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -150,7 +150,7 @@ static struct dentry *get_next_positive_dentry(struct dentry *prev,
 			parent = p->d_parent;
 			if (!spin_trylock(&parent->d_lock)) {
 				spin_unlock(&p->d_lock);
-				cpu_relax();
+				cpu_chill();
 				goto relock;
 			}
 			spin_unlock(&p->d_lock);
diff --git a/fs/dcache.c b/fs/dcache.c
index 250c1222e30c..b93a484d240c 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -19,6 +19,7 @@
 #include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/fsnotify.h>
+#include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/hash.h>
@@ -817,7 +818,12 @@ void dput(struct dentry *dentry)
 kill_it:
 	dentry = dentry_kill(dentry);
 	if (dentry) {
-		cond_resched();
+		int r;
+
+		/* the task with the highest priority won't schedule */
+		r = cond_resched();
+		if (!r)
+			cpu_chill();
 		goto repeat;
 	}
 }
@@ -2452,7 +2458,7 @@ void d_delete(struct dentry * dentry)
 	if (dentry->d_lockref.count == 1) {
 		if (!spin_trylock(&inode->i_lock)) {
 			spin_unlock(&dentry->d_lock);
-			cpu_relax();
+			cpu_chill();
 			goto again;
 		}
 		dentry->d_flags &= ~DCACHE_CANT_MOUNT;
diff --git a/fs/namespace.c b/fs/namespace.c
index b3b1e011eaf5..4225d28121c6 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -14,6 +14,7 @@
 #include <linux/mnt_namespace.h>
 #include <linux/user_namespace.h>
 #include <linux/namei.h>
+#include <linux/delay.h>
 #include <linux/security.h>
 #include <linux/idr.h>
 #include <linux/init.h>		/* init_rootfs */
@@ -359,7 +360,7 @@ int __mnt_want_write(struct vfsmount *m)
 	smp_mb();
 	while (ACCESS_ONCE(mnt->mnt.mnt_flags) & MNT_WRITE_HOLD) {
 		preempt_enable();
-		cpu_relax();
+		cpu_chill();
 		preempt_disable();
 	}
 	/*
-- 
2.14.4

