Commit 0575db88 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'core-fixes-for-linus' of...

Merge branch 'core-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'core-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  futex: Fix errors in nested key ref-counting
parents c029e405 7ada876a
...@@ -1363,7 +1363,6 @@ static inline struct futex_hash_bucket *queue_lock(struct futex_q *q) ...@@ -1363,7 +1363,6 @@ static inline struct futex_hash_bucket *queue_lock(struct futex_q *q)
{ {
struct futex_hash_bucket *hb; struct futex_hash_bucket *hb;
get_futex_key_refs(&q->key);
hb = hash_futex(&q->key); hb = hash_futex(&q->key);
q->lock_ptr = &hb->lock; q->lock_ptr = &hb->lock;
...@@ -1375,7 +1374,6 @@ static inline void ...@@ -1375,7 +1374,6 @@ static inline void
queue_unlock(struct futex_q *q, struct futex_hash_bucket *hb) queue_unlock(struct futex_q *q, struct futex_hash_bucket *hb)
{ {
spin_unlock(&hb->lock); spin_unlock(&hb->lock);
drop_futex_key_refs(&q->key);
} }
/** /**
...@@ -1480,8 +1478,6 @@ static void unqueue_me_pi(struct futex_q *q) ...@@ -1480,8 +1478,6 @@ static void unqueue_me_pi(struct futex_q *q)
q->pi_state = NULL; q->pi_state = NULL;
spin_unlock(q->lock_ptr); spin_unlock(q->lock_ptr);
drop_futex_key_refs(&q->key);
} }
/* /*
...@@ -1812,7 +1808,10 @@ static int futex_wait(u32 __user *uaddr, int fshared, ...@@ -1812,7 +1808,10 @@ static int futex_wait(u32 __user *uaddr, int fshared,
} }
retry: retry:
/* Prepare to wait on uaddr. */ /*
* Prepare to wait on uaddr. On success, holds hb lock and increments
* q.key refs.
*/
ret = futex_wait_setup(uaddr, val, fshared, &q, &hb); ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);
if (ret) if (ret)
goto out; goto out;
...@@ -1822,24 +1821,23 @@ static int futex_wait(u32 __user *uaddr, int fshared, ...@@ -1822,24 +1821,23 @@ static int futex_wait(u32 __user *uaddr, int fshared,
/* If we were woken (and unqueued), we succeeded, whatever. */ /* If we were woken (and unqueued), we succeeded, whatever. */
ret = 0; ret = 0;
/* unqueue_me() drops q.key ref */
if (!unqueue_me(&q)) if (!unqueue_me(&q))
goto out_put_key; goto out;
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
if (to && !to->task) if (to && !to->task)
goto out_put_key; goto out;
/* /*
* We expect signal_pending(current), but we might be the * We expect signal_pending(current), but we might be the
* victim of a spurious wakeup as well. * victim of a spurious wakeup as well.
*/ */
if (!signal_pending(current)) { if (!signal_pending(current))
put_futex_key(fshared, &q.key);
goto retry; goto retry;
}
ret = -ERESTARTSYS; ret = -ERESTARTSYS;
if (!abs_time) if (!abs_time)
goto out_put_key; goto out;
restart = &current_thread_info()->restart_block; restart = &current_thread_info()->restart_block;
restart->fn = futex_wait_restart; restart->fn = futex_wait_restart;
...@@ -1856,8 +1854,6 @@ static int futex_wait(u32 __user *uaddr, int fshared, ...@@ -1856,8 +1854,6 @@ static int futex_wait(u32 __user *uaddr, int fshared,
ret = -ERESTART_RESTARTBLOCK; ret = -ERESTART_RESTARTBLOCK;
out_put_key:
put_futex_key(fshared, &q.key);
out: out:
if (to) { if (to) {
hrtimer_cancel(&to->timer); hrtimer_cancel(&to->timer);
...@@ -2236,7 +2232,10 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, int fshared, ...@@ -2236,7 +2232,10 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, int fshared,
q.rt_waiter = &rt_waiter; q.rt_waiter = &rt_waiter;
q.requeue_pi_key = &key2; q.requeue_pi_key = &key2;
/* Prepare to wait on uaddr. */ /*
* Prepare to wait on uaddr. On success, increments q.key (key1) ref
* count.
*/
ret = futex_wait_setup(uaddr, val, fshared, &q, &hb); ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);
if (ret) if (ret)
goto out_key2; goto out_key2;
...@@ -2254,7 +2253,9 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, int fshared, ...@@ -2254,7 +2253,9 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, int fshared,
* In order for us to be here, we know our q.key == key2, and since * In order for us to be here, we know our q.key == key2, and since
* we took the hb->lock above, we also know that futex_requeue() has * we took the hb->lock above, we also know that futex_requeue() has
* completed and we no longer have to concern ourselves with a wakeup * completed and we no longer have to concern ourselves with a wakeup
* race with the atomic proxy lock acquition by the requeue code. * race with the atomic proxy lock acquisition by the requeue code. The
* futex_requeue dropped our key1 reference and incremented our key2
* reference count.
*/ */
/* Check if the requeue code acquired the second futex for us. */ /* Check if the requeue code acquired the second futex for us. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment