The following commit has been merged in the linux branch: commit 89061d3d58e1f0742139605dc6a7950aa1ecc019 Author: Darren Hart dvhltc@us.ibm.com Date: Thu Oct 15 15:30:48 2009 -0700
futex: Move drop_futex_key_refs out of spinlock'ed region
When requeuing tasks from one futex to another, the reference held by the requeued task to the original futex location needs to be dropped eventually.
Dropping the reference may ultimately lead to a call to "iput_final" and subsequently call into filesystem- specific code - which may be non-atomic.
It is therefore safer to defer this drop operation until after the futex_hash_bucket spinlock has been dropped.
Originally-From: Helge Bahmann hcb@chaoticmind.net Signed-off-by: Darren Hart dvhltc@us.ibm.com Cc: stable@kernel.org Cc: Peter Zijlstra peterz@infradead.org Cc: Eric Dumazet eric.dumazet@gmail.com Cc: Dinakar Guniguntala dino@in.ibm.com Cc: John Stultz johnstul@linux.vnet.ibm.com Cc: Sven-Thorsten Dietrich sdietrich@novell.com Cc: John Kacur jkacur@redhat.com LKML-Reference: 4AD7A298.5040802@us.ibm.com Signed-off-by: Ingo Molnar mingo@elte.hu
diff --git a/kernel/futex.c b/kernel/futex.c index 06938e5..642f3bb 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -1029,7 +1029,6 @@ static inline void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key, struct futex_hash_bucket *hb) { - drop_futex_key_refs(&q->key); get_futex_key_refs(key); q->key = *key;
@@ -1227,6 +1226,7 @@ retry_private: */ if (ret == 1) { WARN_ON(pi_state); + drop_count++; task_count++; ret = get_futex_value_locked(&curval2, uaddr2); if (!ret) @@ -1305,6 +1305,7 @@ retry_private: if (ret == 1) { /* We got the lock. */ requeue_pi_wake_futex(this, &key2, hb2); + drop_count++; continue; } else if (ret) { /* -EDEADLK */