From: Lee Jones lee.jones@linaro.org
From: Thomas Gleixner tglx@linutronix.de
[ Upstream commit f2dac39d93987f7de1e20b3988c8685523247ae2 ]
Too many gotos already and an upcoming fix would make it even more unreadable.
Signed-off-by: Thomas Gleixner tglx@linutronix.de Acked-by: Peter Zijlstra (Intel) peterz@infradead.org Cc: stable@vger.kernel.org Signed-off-by: Lee Jones lee.jones@linaro.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- kernel/futex.c | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-)
--- a/kernel/futex.c +++ b/kernel/futex.c @@ -2237,18 +2237,16 @@ static void unqueue_me_pi(struct futex_q spin_unlock(q->lock_ptr); }
-static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, - struct task_struct *argowner) +static int __fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, + struct task_struct *argowner) { struct futex_pi_state *pi_state = q->pi_state; - u32 uval, uninitialized_var(curval), newval; struct task_struct *oldowner, *newowner; - u32 newtid; - int ret; - - lockdep_assert_held(q->lock_ptr); + u32 uval, curval, newval, newtid; + int err = 0;
oldowner = pi_state->owner; + /* Owner died? */ if (!pi_state->owner) newtid |= FUTEX_OWNER_DIED; @@ -2289,7 +2287,7 @@ retry:
if (__rt_mutex_futex_trylock(&pi_state->pi_mutex)) { /* We got the lock after all, nothing to fix. */ - return 0; + return 1; }
/* @@ -2304,7 +2302,7 @@ retry: * We raced against a concurrent self; things are * already fixed up. Nothing to do. */ - return 0; + return 1; } newowner = argowner; } @@ -2345,7 +2343,7 @@ retry: handle_fault: spin_unlock(q->lock_ptr);
- ret = fault_in_user_writeable(uaddr); + err = fault_in_user_writeable(uaddr);
spin_lock(q->lock_ptr);
@@ -2353,12 +2351,27 @@ handle_fault: * Check if someone else fixed it for us: */ if (pi_state->owner != oldowner) - return 0; + return argowner == current; + + /* Retry if err was -EAGAIN or the fault in succeeded */ + if (!err) + goto retry;
- if (ret) - return ret; + return err; +} + +static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, + struct task_struct *argowner) +{ + struct futex_pi_state *pi_state = q->pi_state; + int ret; + + lockdep_assert_held(q->lock_ptr);
- goto retry; + raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock); + ret = __fixup_pi_state_owner(uaddr, q, argowner); + raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock); + return ret; }
static long futex_wait_restart(struct restart_block *restart);