From: "Steven Rostedt (Red Hat)" <rost...@goodmis.org>

When trying to take locks in reverse order, it is possible that on
PREEMPT_RT that the running task could have preempted the owner and never
let it run, creating a live lock. This is because spinlocks in PREEMPT_RT
can be preempted.

Currently, this is solved by calling cpu_chill(), which on PREEMPT_RT is
converted into a msleep(1), and we just hopen that the owner will have time
to release the lock, and nobody else will take in when the task wakes up.

By converting these to spin_try_or_boost_lock() which will boost the owners,
the cpu_chill() can be converted into a sched_yield() which will allow the
owners to make immediate progress even if it was preempted by a high
priority task.

Signed-off-by: Steven Rostedt <rost...@goodmis.org>
---
 block/blk-ioc.c     | 4 ++--
 fs/autofs4/expire.c | 2 +-
 fs/dcache.c         | 6 +++---
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/block/blk-ioc.c b/block/blk-ioc.c
index 28f467e636cc..de5eccdc8abb 100644
--- a/block/blk-ioc.c
+++ b/block/blk-ioc.c
@@ -105,7 +105,7 @@ static void ioc_release_fn(struct work_struct *work)
                                                struct io_cq, ioc_node);
                struct request_queue *q = icq->q;
 
-               if (spin_trylock(q->queue_lock)) {
+               if (spin_try_or_boost_lock(q->queue_lock)) {
                        ioc_destroy_icq(icq);
                        spin_unlock(q->queue_lock);
                } else {
@@ -183,7 +183,7 @@ retry:
        hlist_for_each_entry(icq, &ioc->icq_list, ioc_node) {
                if (icq->flags & ICQ_EXITED)
                        continue;
-               if (spin_trylock(icq->q->queue_lock)) {
+               if (spin_try_or_boost_lock(icq->q->queue_lock)) {
                        ioc_exit_icq(icq);
                        spin_unlock(icq->q->queue_lock);
                } else {
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index d487fa27add5..025bfc71dc6c 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -148,7 +148,7 @@ again:
                        }
 
                        parent = p->d_parent;
-                       if (!spin_trylock(&parent->d_lock)) {
+                       if (!spin_try_or_boost_lock(&parent->d_lock)) {
                                spin_unlock(&p->d_lock);
                                cpu_chill();
                                goto relock;
diff --git a/fs/dcache.c b/fs/dcache.c
index c1dad92434d5..6b5643ecdf37 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -573,12 +573,12 @@ static struct dentry *dentry_kill(struct dentry *dentry)
        struct inode *inode = dentry->d_inode;
        struct dentry *parent = NULL;
 
-       if (inode && unlikely(!spin_trylock(&inode->i_lock)))
+       if (inode && unlikely(!spin_try_or_boost_lock(&inode->i_lock)))
                goto failed;
 
        if (!IS_ROOT(dentry)) {
                parent = dentry->d_parent;
-               if (unlikely(!spin_trylock(&parent->d_lock))) {
+               if (unlikely(!spin_try_or_boost_lock(&parent->d_lock))) {
                        if (inode)
                                spin_unlock(&inode->i_lock);
                        goto failed;
@@ -2394,7 +2394,7 @@ again:
        inode = dentry->d_inode;
        isdir = S_ISDIR(inode->i_mode);
        if (dentry->d_lockref.count == 1) {
-               if (!spin_trylock(&inode->i_lock)) {
+               if (!spin_try_or_boost_lock(&inode->i_lock)) {
                        spin_unlock(&dentry->d_lock);
                        cpu_chill();
                        goto again;
-- 
2.4.6


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to