diff --git a/kernel/futex.c b/kernel/futex.c index 8ee0757496a87..4a59883ee756b 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -2445,20 +2445,22 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, } /* - * Since we just failed the trylock; there must be an owner. + * The trylock just failed, so either there is an owner or + * there is a higher priority waiter than this one. */ newowner = rt_mutex_owner(&pi_state->pi_mutex); - WARN_ON(!newowner); - /* - * pi_state is incorrect, some other task did a lock steal and - * we returned due to timeout or signal without taking the - * rt_mutex. Too late. + * If the higher priority waiter has not yet taken over the + * rtmutex then newowner is NULL. We can't return here with + * that state because it's inconsistent vs. the user space + * state. So drop the locks and try again. It's a valid + * situation and not any different from the other retry + * conditions. */ - if (!newowner) - newowner = rt_mutex_next_owner(&pi_state->pi_mutex); - - BUG_ON(!newowner); + if (unlikely(!newowner)) { + err = -EAGAIN; + goto handle_err; + } } else { WARN_ON_ONCE(argowner != current); if (oldowner == current) {