rtmutex: Fix deadlock detector for real
authorThomas Gleixner <tglx@linutronix.de>
Thu, 22 May 2014 03:25:39 +0000 (03:25 +0000)
committerThomas Gleixner <tglx@linutronix.de>
Wed, 28 May 2014 15:28:13 +0000 (17:28 +0200)
commit397335f004f41e5fcf7a795e94eb3ab83411a17c
tree57890f2b82ec6739e4dda7b2e51d85423885bfb6
parentf0d71b3dcb8332f7971b5f2363632573e6d9486a
rtmutex: Fix deadlock detector for real

The current deadlock detection logic does not work reliably due to the
following early exit path:

/*
 * Drop out, when the task has no waiters. Note,
 * top_waiter can be NULL, when we are in the deboosting
 * mode!
 */
if (top_waiter && (!task_has_pi_waiters(task) ||
   top_waiter != task_top_pi_waiter(task)))
goto out_unlock_pi;

So this not only exits when the task has no waiters, it also exits
unconditionally when the current waiter is not the top priority waiter
of the task.

So in a nested locking scenario, it might abort the lock chain walk
and therefor miss a potential deadlock.

Simple fix: Continue the chain walk, when deadlock detection is
enabled.

We also avoid the whole enqueue, if we detect the deadlock right away
(A-A). It's an optimization, but also prevents that another waiter who
comes in after the detection and before the task has undone the damage
observes the situation and detects the deadlock and returns
-EDEADLOCK, which is wrong as the other task is not in a deadlock
situation.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Reviewed-by: Steven Rostedt <rostedt@goodmis.org>
Cc: Lai Jiangshan <laijs@cn.fujitsu.com>
Cc: stable@vger.kernel.org
Link: http://lkml.kernel.org/r/20140522031949.725272460@linutronix.de
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
kernel/locking/rtmutex.c