Linus,

please pull the latest locking-urgent-for-linus git tree from:

   git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git 
locking-urgent-for-linus

A fix for a state leak which was introduced in the recent rework of
futex/rtmutex interaction.

Thanks,

        tglx

------------------>
Peter Zijlstra (1):
      futex,rt_mutex: Fix rt_mutex_cleanup_proxy_lock()


 kernel/locking/rtmutex.c | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c
index b95509416909..28cd09e635ed 100644
--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -1785,12 +1785,14 @@ int rt_mutex_wait_proxy_lock(struct rt_mutex *lock,
        int ret;
 
        raw_spin_lock_irq(&lock->wait_lock);
-
-       set_current_state(TASK_INTERRUPTIBLE);
-
        /* sleep on the mutex */
+       set_current_state(TASK_INTERRUPTIBLE);
        ret = __rt_mutex_slowlock(lock, TASK_INTERRUPTIBLE, to, waiter);
-
+       /*
+        * try_to_take_rt_mutex() sets the waiter bit unconditionally. We might
+        * have to fix that up.
+        */
+       fixup_rt_mutex_waiters(lock);
        raw_spin_unlock_irq(&lock->wait_lock);
 
        return ret;
@@ -1822,15 +1824,25 @@ bool rt_mutex_cleanup_proxy_lock(struct rt_mutex *lock,
 
        raw_spin_lock_irq(&lock->wait_lock);
        /*
+        * Do an unconditional try-lock, this deals with the lock stealing
+        * state where __rt_mutex_futex_unlock() -> mark_wakeup_next_waiter()
+        * sets a NULL owner.
+        *
+        * We're not interested in the return value, because the subsequent
+        * test on rt_mutex_owner() will infer that. If the trylock succeeded,
+        * we will own the lock and it will have removed the waiter. If we
+        * failed the trylock, we're still not owner and we need to remove
+        * ourselves.
+        */
+       try_to_take_rt_mutex(lock, current, waiter);
+       /*
         * Unless we're the owner; we're still enqueued on the wait_list.
         * So check if we became owner, if not, take us off the wait_list.
         */
        if (rt_mutex_owner(lock) != current) {
                remove_waiter(lock, waiter);
-               fixup_rt_mutex_waiters(lock);
                cleanup = true;
        }
-
        /*
         * try_to_take_rt_mutex() sets the waiter bit unconditionally. We might
         * have to fix that up.

Reply via email to