Impact: cleanup
This patch makes the calls to futex_get_key_refs() and futex_drop_key_refs()
explicitly symmetric by only "putting" keys we successfully "got". Also
cleanup a couple return points that didn't "put" after a successful "get".
Build and boot tested on an x86_64 system.
Signed-off-by: Darren Hart <dvhltc@us.ibm.com>
Cc: <stable@kernel.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
}
spin_unlock(&hb->lock);
}
spin_unlock(&hb->lock);
put_futex_key(fshared, &key);
put_futex_key(fshared, &key);
goto out;
ret = get_futex_key(uaddr2, fshared, &key2);
if (unlikely(ret != 0))
goto out;
ret = get_futex_key(uaddr2, fshared, &key2);
if (unlikely(ret != 0))
hb1 = hash_futex(&key1);
hb2 = hash_futex(&key2);
hb1 = hash_futex(&key1);
hb2 = hash_futex(&key2);
* but we might get them from range checking
*/
ret = op_ret;
* but we might get them from range checking
*/
ret = op_ret;
#endif
if (unlikely(op_ret != -EFAULT)) {
ret = op_ret;
#endif
if (unlikely(op_ret != -EFAULT)) {
ret = op_ret;
ret = futex_handle_fault((unsigned long)uaddr2,
attempt);
if (ret)
ret = futex_handle_fault((unsigned long)uaddr2,
attempt);
if (ret)
spin_unlock(&hb1->lock);
if (hb1 != hb2)
spin_unlock(&hb2->lock);
spin_unlock(&hb1->lock);
if (hb1 != hb2)
spin_unlock(&hb2->lock);
put_futex_key(fshared, &key2);
put_futex_key(fshared, &key2);
put_futex_key(fshared, &key1);
put_futex_key(fshared, &key1);
struct futex_q *this, *next;
int ret, drop_count = 0;
struct futex_q *this, *next;
int ret, drop_count = 0;
ret = get_futex_key(uaddr1, fshared, &key1);
if (unlikely(ret != 0))
goto out;
ret = get_futex_key(uaddr2, fshared, &key2);
if (unlikely(ret != 0))
ret = get_futex_key(uaddr1, fshared, &key1);
if (unlikely(ret != 0))
goto out;
ret = get_futex_key(uaddr2, fshared, &key2);
if (unlikely(ret != 0))
hb1 = hash_futex(&key1);
hb2 = hash_futex(&key2);
hb1 = hash_futex(&key1);
hb2 = hash_futex(&key2);
}
if (curval != *cmpval) {
ret = -EAGAIN;
}
if (curval != *cmpval) {
ret = -EAGAIN;
while (--drop_count >= 0)
drop_futex_key_refs(&key1);
while (--drop_count >= 0)
drop_futex_key_refs(&key1);
put_futex_key(fshared, &key2);
put_futex_key(fshared, &key2);
put_futex_key(fshared, &key1);
put_futex_key(fshared, &key1);
int ret = 0;
/* In the common case we don't take the spinlock, which is nice. */
int ret = 0;
/* In the common case we don't take the spinlock, which is nice. */
lock_ptr = q->lock_ptr;
barrier();
if (lock_ptr != NULL) {
lock_ptr = q->lock_ptr;
barrier();
if (lock_ptr != NULL) {
q.pi_state = NULL;
q.bitset = bitset;
q.pi_state = NULL;
q.bitset = bitset;
q.key = FUTEX_KEY_INIT;
ret = get_futex_key(uaddr, fshared, &q.key);
if (unlikely(ret != 0))
q.key = FUTEX_KEY_INIT;
ret = get_futex_key(uaddr, fshared, &q.key);
if (unlikely(ret != 0))
if (unlikely(ret)) {
queue_unlock(&q, hb);
if (unlikely(ret)) {
queue_unlock(&q, hb);
+ put_futex_key(fshared, &q.key);
ret = get_user(uval, uaddr);
ret = get_user(uval, uaddr);
}
ret = -EWOULDBLOCK;
if (uval != val)
}
ret = -EWOULDBLOCK;
if (uval != val)
- goto out_unlock_release_sem;
+ goto out_unlock_put_key;
/* Only actually queue if *uaddr contained val. */
queue_me(&q, hb);
/* Only actually queue if *uaddr contained val. */
queue_me(&q, hb);
return -ERESTART_RESTARTBLOCK;
}
return -ERESTART_RESTARTBLOCK;
}
- out_unlock_release_sem:
put_futex_key(fshared, &q.key);
put_futex_key(fshared, &q.key);
q.key = FUTEX_KEY_INIT;
ret = get_futex_key(uaddr, fshared, &q.key);
if (unlikely(ret != 0))
q.key = FUTEX_KEY_INIT;
ret = get_futex_key(uaddr, fshared, &q.key);
if (unlikely(ret != 0))
*/
if (unlikely((curval & FUTEX_TID_MASK) == task_pid_vnr(current))) {
ret = -EDEADLK;
*/
if (unlikely((curval & FUTEX_TID_MASK) == task_pid_vnr(current))) {
ret = -EDEADLK;
- goto out_unlock_release_sem;
+ goto out_unlock_put_key;
}
/*
* Surprise - we got the lock. Just return to userspace:
*/
if (unlikely(!curval))
}
/*
* Surprise - we got the lock. Just return to userspace:
*/
if (unlikely(!curval))
- goto out_unlock_release_sem;
+ goto out_unlock_put_key;
* We took the lock due to owner died take over.
*/
if (unlikely(lock_taken))
* We took the lock due to owner died take over.
*/
if (unlikely(lock_taken))
- goto out_unlock_release_sem;
+ goto out_unlock_put_key;
/*
* We dont have the lock. Look up the PI state (or create it if
/*
* We dont have the lock. Look up the PI state (or create it if
goto retry_locked;
}
default:
goto retry_locked;
}
default:
- goto out_unlock_release_sem;
+ goto out_unlock_put_key;
destroy_hrtimer_on_stack(&to->timer);
return ret != -EINTR ? ret : -ERESTARTNOINTR;
destroy_hrtimer_on_stack(&to->timer);
return ret != -EINTR ? ret : -ERESTARTNOINTR;
- out_unlock_release_sem:
put_futex_key(fshared, &q.key);
put_futex_key(fshared, &q.key);
if (to)
destroy_hrtimer_on_stack(&to->timer);
return ret;
if (to)
destroy_hrtimer_on_stack(&to->timer);
return ret;
/*
* We have to r/w *(int __user *)uaddr, and we have to modify it
* atomically. Therefore, if we continue to fault after get_user()
/*
* We have to r/w *(int __user *)uaddr, and we have to modify it
* atomically. Therefore, if we continue to fault after get_user()
if (attempt++) {
ret = futex_handle_fault((unsigned long)uaddr, attempt);
if (ret)
if (attempt++) {
ret = futex_handle_fault((unsigned long)uaddr, attempt);
if (ret)
out_unlock:
spin_unlock(&hb->lock);
out_unlock:
spin_unlock(&hb->lock);
put_futex_key(fshared, &key);
put_futex_key(fshared, &key);