diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-31 16:57:45 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-31 16:57:45 -0400 |
| commit | c958f9200fb48d092b17d3784168e4a6c56bbddc (patch) | |
| tree | e5bdf4fa493521daf96a45ae6a82903189dd03b9 /kernel | |
| parent | aea4869f68b5869afbb308bfb7d777d725df8900 (diff) | |
| parent | 30a6b8031fe14031ab27c1fa3483cb9780e7f63c (diff) | |
Merge branch 'locking-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull futex fixes from Ingo Molnar:
"This contains two futex fixes: one fixes a race condition, the other
clarifies shared/private futex comments"
* 'locking-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
futex: Fix a race condition between REQUEUE_PI and task death
futex: Mention key referencing differences between shared and private futexes
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/futex.c | 36 |
1 files changed, 21 insertions, 15 deletions
diff --git a/kernel/futex.c b/kernel/futex.c index f3a3a071283c..63678b573d61 100644 --- a/kernel/futex.c +++ b/kernel/futex.c | |||
| @@ -143,9 +143,8 @@ | |||
| 143 | * | 143 | * |
| 144 | * Where (A) orders the waiters increment and the futex value read through | 144 | * Where (A) orders the waiters increment and the futex value read through |
| 145 | * atomic operations (see hb_waiters_inc) and where (B) orders the write | 145 | * atomic operations (see hb_waiters_inc) and where (B) orders the write |
| 146 | * to futex and the waiters read -- this is done by the barriers in | 146 | * to futex and the waiters read -- this is done by the barriers for both |
| 147 | * get_futex_key_refs(), through either ihold or atomic_inc, depending on the | 147 | * shared and private futexes in get_futex_key_refs(). |
| 148 | * futex type. | ||
| 149 | * | 148 | * |
| 150 | * This yields the following case (where X:=waiters, Y:=futex): | 149 | * This yields the following case (where X:=waiters, Y:=futex): |
| 151 | * | 150 | * |
| @@ -344,13 +343,20 @@ static void get_futex_key_refs(union futex_key *key) | |||
| 344 | futex_get_mm(key); /* implies MB (B) */ | 343 | futex_get_mm(key); /* implies MB (B) */ |
| 345 | break; | 344 | break; |
| 346 | default: | 345 | default: |
| 346 | /* | ||
| 347 | * Private futexes do not hold reference on an inode or | ||
| 348 | * mm, therefore the only purpose of calling get_futex_key_refs | ||
| 349 | * is because we need the barrier for the lockless waiter check. | ||
| 350 | */ | ||
| 347 | smp_mb(); /* explicit MB (B) */ | 351 | smp_mb(); /* explicit MB (B) */ |
| 348 | } | 352 | } |
| 349 | } | 353 | } |
| 350 | 354 | ||
| 351 | /* | 355 | /* |
| 352 | * Drop a reference to the resource addressed by a key. | 356 | * Drop a reference to the resource addressed by a key. |
| 353 | * The hash bucket spinlock must not be held. | 357 | * The hash bucket spinlock must not be held. This is |
| 358 | * a no-op for private futexes, see comment in the get | ||
| 359 | * counterpart. | ||
| 354 | */ | 360 | */ |
| 355 | static void drop_futex_key_refs(union futex_key *key) | 361 | static void drop_futex_key_refs(union futex_key *key) |
| 356 | { | 362 | { |
| @@ -641,8 +647,14 @@ static struct futex_pi_state * alloc_pi_state(void) | |||
| 641 | return pi_state; | 647 | return pi_state; |
| 642 | } | 648 | } |
| 643 | 649 | ||
| 650 | /* | ||
| 651 | * Must be called with the hb lock held. | ||
| 652 | */ | ||
| 644 | static void free_pi_state(struct futex_pi_state *pi_state) | 653 | static void free_pi_state(struct futex_pi_state *pi_state) |
| 645 | { | 654 | { |
| 655 | if (!pi_state) | ||
| 656 | return; | ||
| 657 | |||
| 646 | if (!atomic_dec_and_test(&pi_state->refcount)) | 658 | if (!atomic_dec_and_test(&pi_state->refcount)) |
| 647 | return; | 659 | return; |
| 648 | 660 | ||
| @@ -1521,15 +1533,6 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags, | |||
| 1521 | } | 1533 | } |
| 1522 | 1534 | ||
| 1523 | retry: | 1535 | retry: |
| 1524 | if (pi_state != NULL) { | ||
| 1525 | /* | ||
| 1526 | * We will have to lookup the pi_state again, so free this one | ||
| 1527 | * to keep the accounting correct. | ||
| 1528 | */ | ||
| 1529 | free_pi_state(pi_state); | ||
| 1530 | pi_state = NULL; | ||
| 1531 | } | ||
| 1532 | |||
| 1533 | ret = get_futex_key(uaddr1, flags & FLAGS_SHARED, &key1, VERIFY_READ); | 1536 | ret = get_futex_key(uaddr1, flags & FLAGS_SHARED, &key1, VERIFY_READ); |
| 1534 | if (unlikely(ret != 0)) | 1537 | if (unlikely(ret != 0)) |
| 1535 | goto out; | 1538 | goto out; |
| @@ -1619,6 +1622,8 @@ retry_private: | |||
| 1619 | case 0: | 1622 | case 0: |
| 1620 | break; | 1623 | break; |
| 1621 | case -EFAULT: | 1624 | case -EFAULT: |
| 1625 | free_pi_state(pi_state); | ||
| 1626 | pi_state = NULL; | ||
| 1622 | double_unlock_hb(hb1, hb2); | 1627 | double_unlock_hb(hb1, hb2); |
| 1623 | hb_waiters_dec(hb2); | 1628 | hb_waiters_dec(hb2); |
| 1624 | put_futex_key(&key2); | 1629 | put_futex_key(&key2); |
| @@ -1634,6 +1639,8 @@ retry_private: | |||
| 1634 | * exit to complete. | 1639 | * exit to complete. |
| 1635 | * - The user space value changed. | 1640 | * - The user space value changed. |
| 1636 | */ | 1641 | */ |
| 1642 | free_pi_state(pi_state); | ||
| 1643 | pi_state = NULL; | ||
| 1637 | double_unlock_hb(hb1, hb2); | 1644 | double_unlock_hb(hb1, hb2); |
| 1638 | hb_waiters_dec(hb2); | 1645 | hb_waiters_dec(hb2); |
| 1639 | put_futex_key(&key2); | 1646 | put_futex_key(&key2); |
| @@ -1710,6 +1717,7 @@ retry_private: | |||
| 1710 | } | 1717 | } |
| 1711 | 1718 | ||
| 1712 | out_unlock: | 1719 | out_unlock: |
| 1720 | free_pi_state(pi_state); | ||
| 1713 | double_unlock_hb(hb1, hb2); | 1721 | double_unlock_hb(hb1, hb2); |
| 1714 | hb_waiters_dec(hb2); | 1722 | hb_waiters_dec(hb2); |
| 1715 | 1723 | ||
| @@ -1727,8 +1735,6 @@ out_put_keys: | |||
| 1727 | out_put_key1: | 1735 | out_put_key1: |
| 1728 | put_futex_key(&key1); | 1736 | put_futex_key(&key1); |
| 1729 | out: | 1737 | out: |
| 1730 | if (pi_state != NULL) | ||
| 1731 | free_pi_state(pi_state); | ||
| 1732 | return ret ? ret : task_count; | 1738 | return ret ? ret : task_count; |
| 1733 | } | 1739 | } |
| 1734 | 1740 | ||
