119 lines
3.1 KiB
Diff
119 lines
3.1 KiB
Diff
|
From 6f05fc5bb3de3c6dd109a5d166d8c44c92464377 Mon Sep 17 00:00:00 2001
|
||
|
From: Thomas Gleixner <tglx@linutronix.de>
|
||
|
Date: Wed, 7 Mar 2012 21:00:34 +0100
|
||
|
Subject: [PATCH 219/365] 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 | 20 ++++++++++++++++----
|
||
|
fs/namespace.c | 3 ++-
|
||
|
4 files changed, 20 insertions(+), 6 deletions(-)
|
||
|
|
||
|
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
|
||
|
index 42f863346409..e4deae2d9fa1 100644
|
||
|
--- a/fs/autofs4/autofs_i.h
|
||
|
+++ b/fs/autofs4/autofs_i.h
|
||
|
@@ -32,6 +32,7 @@
|
||
|
#include <linux/sched.h>
|
||
|
#include <linux/mount.h>
|
||
|
#include <linux/namei.h>
|
||
|
+#include <linux/delay.h>
|
||
|
#include <asm/current.h>
|
||
|
#include <linux/uaccess.h>
|
||
|
|
||
|
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
|
||
|
index 02f0d373adbf..1454264c8c1a 100644
|
||
|
--- a/fs/autofs4/expire.c
|
||
|
+++ b/fs/autofs4/expire.c
|
||
|
@@ -148,7 +148,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 ed0a023a0567..f757c63e36a6 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>
|
||
|
@@ -787,6 +788,8 @@ static inline bool fast_dput(struct dentry *dentry)
|
||
|
*/
|
||
|
void dput(struct dentry *dentry)
|
||
|
{
|
||
|
+ struct dentry *parent;
|
||
|
+
|
||
|
if (unlikely(!dentry))
|
||
|
return;
|
||
|
|
||
|
@@ -825,9 +828,18 @@ void dput(struct dentry *dentry)
|
||
|
return;
|
||
|
|
||
|
kill_it:
|
||
|
- dentry = dentry_kill(dentry);
|
||
|
- if (dentry) {
|
||
|
- cond_resched();
|
||
|
+ parent = dentry_kill(dentry);
|
||
|
+ if (parent) {
|
||
|
+ int r;
|
||
|
+
|
||
|
+ if (parent == dentry) {
|
||
|
+ /* the task with the highest priority won't schedule */
|
||
|
+ r = cond_resched();
|
||
|
+ if (!r)
|
||
|
+ cpu_chill();
|
||
|
+ } else {
|
||
|
+ dentry = parent;
|
||
|
+ }
|
||
|
goto repeat;
|
||
|
}
|
||
|
}
|
||
|
@@ -2380,7 +2392,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 3f5b81c194ab..6d5149dc7667 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 */
|
||
|
@@ -360,7 +361,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.28.0
|
||
|
|