diff options
Diffstat (limited to 'kernel/futex.c')
-rw-r--r-- | kernel/futex.c | 67 |
1 files changed, 36 insertions, 31 deletions
diff --git a/kernel/futex.c b/kernel/futex.c index b4f87bac91c1..c5ac55cc0c16 100644 --- a/kernel/futex.c +++ b/kernel/futex.c | |||
@@ -723,8 +723,8 @@ static int futex_wake(u32 __user *uaddr, int fshared, int nr_wake, u32 bitset) | |||
723 | } | 723 | } |
724 | 724 | ||
725 | spin_unlock(&hb->lock); | 725 | spin_unlock(&hb->lock); |
726 | out: | ||
727 | put_futex_key(fshared, &key); | 726 | put_futex_key(fshared, &key); |
727 | out: | ||
728 | return ret; | 728 | return ret; |
729 | } | 729 | } |
730 | 730 | ||
@@ -748,7 +748,7 @@ retryfull: | |||
748 | goto out; | 748 | goto out; |
749 | ret = get_futex_key(uaddr2, fshared, &key2); | 749 | ret = get_futex_key(uaddr2, fshared, &key2); |
750 | if (unlikely(ret != 0)) | 750 | if (unlikely(ret != 0)) |
751 | goto out; | 751 | goto out_put_key1; |
752 | 752 | ||
753 | hb1 = hash_futex(&key1); | 753 | hb1 = hash_futex(&key1); |
754 | hb2 = hash_futex(&key2); | 754 | hb2 = hash_futex(&key2); |
@@ -770,12 +770,12 @@ retry: | |||
770 | * but we might get them from range checking | 770 | * but we might get them from range checking |
771 | */ | 771 | */ |
772 | ret = op_ret; | 772 | ret = op_ret; |
773 | goto out; | 773 | goto out_put_keys; |
774 | #endif | 774 | #endif |
775 | 775 | ||
776 | if (unlikely(op_ret != -EFAULT)) { | 776 | if (unlikely(op_ret != -EFAULT)) { |
777 | ret = op_ret; | 777 | ret = op_ret; |
778 | goto out; | 778 | goto out_put_keys; |
779 | } | 779 | } |
780 | 780 | ||
781 | /* | 781 | /* |
@@ -789,7 +789,7 @@ retry: | |||
789 | ret = futex_handle_fault((unsigned long)uaddr2, | 789 | ret = futex_handle_fault((unsigned long)uaddr2, |
790 | attempt); | 790 | attempt); |
791 | if (ret) | 791 | if (ret) |
792 | goto out; | 792 | goto out_put_keys; |
793 | goto retry; | 793 | goto retry; |
794 | } | 794 | } |
795 | 795 | ||
@@ -827,10 +827,11 @@ retry: | |||
827 | spin_unlock(&hb1->lock); | 827 | spin_unlock(&hb1->lock); |
828 | if (hb1 != hb2) | 828 | if (hb1 != hb2) |
829 | spin_unlock(&hb2->lock); | 829 | spin_unlock(&hb2->lock); |
830 | out: | 830 | out_put_keys: |
831 | put_futex_key(fshared, &key2); | 831 | put_futex_key(fshared, &key2); |
832 | out_put_key1: | ||
832 | put_futex_key(fshared, &key1); | 833 | put_futex_key(fshared, &key1); |
833 | 834 | out: | |
834 | return ret; | 835 | return ret; |
835 | } | 836 | } |
836 | 837 | ||
@@ -847,13 +848,13 @@ static int futex_requeue(u32 __user *uaddr1, int fshared, u32 __user *uaddr2, | |||
847 | struct futex_q *this, *next; | 848 | struct futex_q *this, *next; |
848 | int ret, drop_count = 0; | 849 | int ret, drop_count = 0; |
849 | 850 | ||
850 | retry: | 851 | retry: |
851 | ret = get_futex_key(uaddr1, fshared, &key1); | 852 | ret = get_futex_key(uaddr1, fshared, &key1); |
852 | if (unlikely(ret != 0)) | 853 | if (unlikely(ret != 0)) |
853 | goto out; | 854 | goto out; |
854 | ret = get_futex_key(uaddr2, fshared, &key2); | 855 | ret = get_futex_key(uaddr2, fshared, &key2); |
855 | if (unlikely(ret != 0)) | 856 | if (unlikely(ret != 0)) |
856 | goto out; | 857 | goto out_put_key1; |
857 | 858 | ||
858 | hb1 = hash_futex(&key1); | 859 | hb1 = hash_futex(&key1); |
859 | hb2 = hash_futex(&key2); | 860 | hb2 = hash_futex(&key2); |
@@ -875,7 +876,7 @@ static int futex_requeue(u32 __user *uaddr1, int fshared, u32 __user *uaddr2, | |||
875 | if (!ret) | 876 | if (!ret) |
876 | goto retry; | 877 | goto retry; |
877 | 878 | ||
878 | return ret; | 879 | goto out_put_keys; |
879 | } | 880 | } |
880 | if (curval != *cmpval) { | 881 | if (curval != *cmpval) { |
881 | ret = -EAGAIN; | 882 | ret = -EAGAIN; |
@@ -920,9 +921,11 @@ out_unlock: | |||
920 | while (--drop_count >= 0) | 921 | while (--drop_count >= 0) |
921 | drop_futex_key_refs(&key1); | 922 | drop_futex_key_refs(&key1); |
922 | 923 | ||
923 | out: | 924 | out_put_keys: |
924 | put_futex_key(fshared, &key2); | 925 | put_futex_key(fshared, &key2); |
926 | out_put_key1: | ||
925 | put_futex_key(fshared, &key1); | 927 | put_futex_key(fshared, &key1); |
928 | out: | ||
926 | return ret; | 929 | return ret; |
927 | } | 930 | } |
928 | 931 | ||
@@ -983,7 +986,7 @@ static int unqueue_me(struct futex_q *q) | |||
983 | int ret = 0; | 986 | int ret = 0; |
984 | 987 | ||
985 | /* In the common case we don't take the spinlock, which is nice. */ | 988 | /* In the common case we don't take the spinlock, which is nice. */ |
986 | retry: | 989 | retry: |
987 | lock_ptr = q->lock_ptr; | 990 | lock_ptr = q->lock_ptr; |
988 | barrier(); | 991 | barrier(); |
989 | if (lock_ptr != NULL) { | 992 | if (lock_ptr != NULL) { |
@@ -1165,11 +1168,11 @@ static int futex_wait(u32 __user *uaddr, int fshared, | |||
1165 | 1168 | ||
1166 | q.pi_state = NULL; | 1169 | q.pi_state = NULL; |
1167 | q.bitset = bitset; | 1170 | q.bitset = bitset; |
1168 | retry: | 1171 | retry: |
1169 | q.key = FUTEX_KEY_INIT; | 1172 | q.key = FUTEX_KEY_INIT; |
1170 | ret = get_futex_key(uaddr, fshared, &q.key); | 1173 | ret = get_futex_key(uaddr, fshared, &q.key); |
1171 | if (unlikely(ret != 0)) | 1174 | if (unlikely(ret != 0)) |
1172 | goto out_release_sem; | 1175 | goto out; |
1173 | 1176 | ||
1174 | hb = queue_lock(&q); | 1177 | hb = queue_lock(&q); |
1175 | 1178 | ||
@@ -1197,6 +1200,7 @@ static int futex_wait(u32 __user *uaddr, int fshared, | |||
1197 | 1200 | ||
1198 | if (unlikely(ret)) { | 1201 | if (unlikely(ret)) { |
1199 | queue_unlock(&q, hb); | 1202 | queue_unlock(&q, hb); |
1203 | put_futex_key(fshared, &q.key); | ||
1200 | 1204 | ||
1201 | ret = get_user(uval, uaddr); | 1205 | ret = get_user(uval, uaddr); |
1202 | 1206 | ||
@@ -1206,7 +1210,7 @@ static int futex_wait(u32 __user *uaddr, int fshared, | |||
1206 | } | 1210 | } |
1207 | ret = -EWOULDBLOCK; | 1211 | ret = -EWOULDBLOCK; |
1208 | if (uval != val) | 1212 | if (uval != val) |
1209 | goto out_unlock_release_sem; | 1213 | goto out_unlock_put_key; |
1210 | 1214 | ||
1211 | /* Only actually queue if *uaddr contained val. */ | 1215 | /* Only actually queue if *uaddr contained val. */ |
1212 | queue_me(&q, hb); | 1216 | queue_me(&q, hb); |
@@ -1298,11 +1302,11 @@ static int futex_wait(u32 __user *uaddr, int fshared, | |||
1298 | return -ERESTART_RESTARTBLOCK; | 1302 | return -ERESTART_RESTARTBLOCK; |
1299 | } | 1303 | } |
1300 | 1304 | ||
1301 | out_unlock_release_sem: | 1305 | out_unlock_put_key: |
1302 | queue_unlock(&q, hb); | 1306 | queue_unlock(&q, hb); |
1303 | |||
1304 | out_release_sem: | ||
1305 | put_futex_key(fshared, &q.key); | 1307 | put_futex_key(fshared, &q.key); |
1308 | |||
1309 | out: | ||
1306 | return ret; | 1310 | return ret; |
1307 | } | 1311 | } |
1308 | 1312 | ||
@@ -1351,16 +1355,16 @@ static int futex_lock_pi(u32 __user *uaddr, int fshared, | |||
1351 | } | 1355 | } |
1352 | 1356 | ||
1353 | q.pi_state = NULL; | 1357 | q.pi_state = NULL; |
1354 | retry: | 1358 | retry: |
1355 | q.key = FUTEX_KEY_INIT; | 1359 | q.key = FUTEX_KEY_INIT; |
1356 | ret = get_futex_key(uaddr, fshared, &q.key); | 1360 | ret = get_futex_key(uaddr, fshared, &q.key); |
1357 | if (unlikely(ret != 0)) | 1361 | if (unlikely(ret != 0)) |
1358 | goto out_release_sem; | 1362 | goto out; |
1359 | 1363 | ||
1360 | retry_unlocked: | 1364 | retry_unlocked: |
1361 | hb = queue_lock(&q); | 1365 | hb = queue_lock(&q); |
1362 | 1366 | ||
1363 | retry_locked: | 1367 | retry_locked: |
1364 | ret = lock_taken = 0; | 1368 | ret = lock_taken = 0; |
1365 | 1369 | ||
1366 | /* | 1370 | /* |
@@ -1381,14 +1385,14 @@ static int futex_lock_pi(u32 __user *uaddr, int fshared, | |||
1381 | */ | 1385 | */ |
1382 | if (unlikely((curval & FUTEX_TID_MASK) == task_pid_vnr(current))) { | 1386 | if (unlikely((curval & FUTEX_TID_MASK) == task_pid_vnr(current))) { |
1383 | ret = -EDEADLK; | 1387 | ret = -EDEADLK; |
1384 | goto out_unlock_release_sem; | 1388 | goto out_unlock_put_key; |
1385 | } | 1389 | } |
1386 | 1390 | ||
1387 | /* | 1391 | /* |
1388 | * Surprise - we got the lock. Just return to userspace: | 1392 | * Surprise - we got the lock. Just return to userspace: |
1389 | */ | 1393 | */ |
1390 | if (unlikely(!curval)) | 1394 | if (unlikely(!curval)) |
1391 | goto out_unlock_release_sem; | 1395 | goto out_unlock_put_key; |
1392 | 1396 | ||
1393 | uval = curval; | 1397 | uval = curval; |
1394 | 1398 | ||
@@ -1424,7 +1428,7 @@ static int futex_lock_pi(u32 __user *uaddr, int fshared, | |||
1424 | * We took the lock due to owner died take over. | 1428 | * We took the lock due to owner died take over. |
1425 | */ | 1429 | */ |
1426 | if (unlikely(lock_taken)) | 1430 | if (unlikely(lock_taken)) |
1427 | goto out_unlock_release_sem; | 1431 | goto out_unlock_put_key; |
1428 | 1432 | ||
1429 | /* | 1433 | /* |
1430 | * We dont have the lock. Look up the PI state (or create it if | 1434 | * We dont have the lock. Look up the PI state (or create it if |
@@ -1463,7 +1467,7 @@ static int futex_lock_pi(u32 __user *uaddr, int fshared, | |||
1463 | goto retry_locked; | 1467 | goto retry_locked; |
1464 | } | 1468 | } |
1465 | default: | 1469 | default: |
1466 | goto out_unlock_release_sem; | 1470 | goto out_unlock_put_key; |
1467 | } | 1471 | } |
1468 | } | 1472 | } |
1469 | 1473 | ||
@@ -1554,16 +1558,17 @@ static int futex_lock_pi(u32 __user *uaddr, int fshared, | |||
1554 | destroy_hrtimer_on_stack(&to->timer); | 1558 | destroy_hrtimer_on_stack(&to->timer); |
1555 | return ret != -EINTR ? ret : -ERESTARTNOINTR; | 1559 | return ret != -EINTR ? ret : -ERESTARTNOINTR; |
1556 | 1560 | ||
1557 | out_unlock_release_sem: | 1561 | out_unlock_put_key: |
1558 | queue_unlock(&q, hb); | 1562 | queue_unlock(&q, hb); |
1559 | 1563 | ||
1560 | out_release_sem: | 1564 | out_put_key: |
1561 | put_futex_key(fshared, &q.key); | 1565 | put_futex_key(fshared, &q.key); |
1566 | out: | ||
1562 | if (to) | 1567 | if (to) |
1563 | destroy_hrtimer_on_stack(&to->timer); | 1568 | destroy_hrtimer_on_stack(&to->timer); |
1564 | return ret; | 1569 | return ret; |
1565 | 1570 | ||
1566 | uaddr_faulted: | 1571 | uaddr_faulted: |
1567 | /* | 1572 | /* |
1568 | * We have to r/w *(int __user *)uaddr, and we have to modify it | 1573 | * We have to r/w *(int __user *)uaddr, and we have to modify it |
1569 | * atomically. Therefore, if we continue to fault after get_user() | 1574 | * atomically. Therefore, if we continue to fault after get_user() |
@@ -1576,7 +1581,7 @@ static int futex_lock_pi(u32 __user *uaddr, int fshared, | |||
1576 | if (attempt++) { | 1581 | if (attempt++) { |
1577 | ret = futex_handle_fault((unsigned long)uaddr, attempt); | 1582 | ret = futex_handle_fault((unsigned long)uaddr, attempt); |
1578 | if (ret) | 1583 | if (ret) |
1579 | goto out_release_sem; | 1584 | goto out_put_key; |
1580 | goto retry_unlocked; | 1585 | goto retry_unlocked; |
1581 | } | 1586 | } |
1582 | 1587 | ||
@@ -1668,9 +1673,9 @@ retry_unlocked: | |||
1668 | 1673 | ||
1669 | out_unlock: | 1674 | out_unlock: |
1670 | spin_unlock(&hb->lock); | 1675 | spin_unlock(&hb->lock); |
1671 | out: | ||
1672 | put_futex_key(fshared, &key); | 1676 | put_futex_key(fshared, &key); |
1673 | 1677 | ||
1678 | out: | ||
1674 | return ret; | 1679 | return ret; |
1675 | 1680 | ||
1676 | pi_faulted: | 1681 | pi_faulted: |