diff options
Diffstat (limited to 'kernel/futex.c')
-rw-r--r-- | kernel/futex.c | 60 |
1 files changed, 33 insertions, 27 deletions
diff --git a/kernel/futex.c b/kernel/futex.c index fb65e822fc41..8e3c3ffe1b9a 100644 --- a/kernel/futex.c +++ b/kernel/futex.c | |||
@@ -304,8 +304,14 @@ void put_futex_key(int fshared, union futex_key *key) | |||
304 | */ | 304 | */ |
305 | static int fault_in_user_writeable(u32 __user *uaddr) | 305 | static int fault_in_user_writeable(u32 __user *uaddr) |
306 | { | 306 | { |
307 | int ret = get_user_pages(current, current->mm, (unsigned long)uaddr, | 307 | struct mm_struct *mm = current->mm; |
308 | 1, 1, 0, NULL, NULL); | 308 | int ret; |
309 | |||
310 | down_read(&mm->mmap_sem); | ||
311 | ret = get_user_pages(current, mm, (unsigned long)uaddr, | ||
312 | 1, 1, 0, NULL, NULL); | ||
313 | up_read(&mm->mmap_sem); | ||
314 | |||
309 | return ret < 0 ? ret : 0; | 315 | return ret < 0 ? ret : 0; |
310 | } | 316 | } |
311 | 317 | ||
@@ -397,9 +403,9 @@ static void free_pi_state(struct futex_pi_state *pi_state) | |||
397 | * and has cleaned up the pi_state already | 403 | * and has cleaned up the pi_state already |
398 | */ | 404 | */ |
399 | if (pi_state->owner) { | 405 | if (pi_state->owner) { |
400 | spin_lock_irq(&pi_state->owner->pi_lock); | 406 | raw_spin_lock_irq(&pi_state->owner->pi_lock); |
401 | list_del_init(&pi_state->list); | 407 | list_del_init(&pi_state->list); |
402 | spin_unlock_irq(&pi_state->owner->pi_lock); | 408 | raw_spin_unlock_irq(&pi_state->owner->pi_lock); |
403 | 409 | ||
404 | rt_mutex_proxy_unlock(&pi_state->pi_mutex, pi_state->owner); | 410 | rt_mutex_proxy_unlock(&pi_state->pi_mutex, pi_state->owner); |
405 | } | 411 | } |
@@ -464,18 +470,18 @@ void exit_pi_state_list(struct task_struct *curr) | |||
464 | * pi_state_list anymore, but we have to be careful | 470 | * pi_state_list anymore, but we have to be careful |
465 | * versus waiters unqueueing themselves: | 471 | * versus waiters unqueueing themselves: |
466 | */ | 472 | */ |
467 | spin_lock_irq(&curr->pi_lock); | 473 | raw_spin_lock_irq(&curr->pi_lock); |
468 | while (!list_empty(head)) { | 474 | while (!list_empty(head)) { |
469 | 475 | ||
470 | next = head->next; | 476 | next = head->next; |
471 | pi_state = list_entry(next, struct futex_pi_state, list); | 477 | pi_state = list_entry(next, struct futex_pi_state, list); |
472 | key = pi_state->key; | 478 | key = pi_state->key; |
473 | hb = hash_futex(&key); | 479 | hb = hash_futex(&key); |
474 | spin_unlock_irq(&curr->pi_lock); | 480 | raw_spin_unlock_irq(&curr->pi_lock); |
475 | 481 | ||
476 | spin_lock(&hb->lock); | 482 | spin_lock(&hb->lock); |
477 | 483 | ||
478 | spin_lock_irq(&curr->pi_lock); | 484 | raw_spin_lock_irq(&curr->pi_lock); |
479 | /* | 485 | /* |
480 | * We dropped the pi-lock, so re-check whether this | 486 | * We dropped the pi-lock, so re-check whether this |
481 | * task still owns the PI-state: | 487 | * task still owns the PI-state: |
@@ -489,15 +495,15 @@ void exit_pi_state_list(struct task_struct *curr) | |||
489 | WARN_ON(list_empty(&pi_state->list)); | 495 | WARN_ON(list_empty(&pi_state->list)); |
490 | list_del_init(&pi_state->list); | 496 | list_del_init(&pi_state->list); |
491 | pi_state->owner = NULL; | 497 | pi_state->owner = NULL; |
492 | spin_unlock_irq(&curr->pi_lock); | 498 | raw_spin_unlock_irq(&curr->pi_lock); |
493 | 499 | ||
494 | rt_mutex_unlock(&pi_state->pi_mutex); | 500 | rt_mutex_unlock(&pi_state->pi_mutex); |
495 | 501 | ||
496 | spin_unlock(&hb->lock); | 502 | spin_unlock(&hb->lock); |
497 | 503 | ||
498 | spin_lock_irq(&curr->pi_lock); | 504 | raw_spin_lock_irq(&curr->pi_lock); |
499 | } | 505 | } |
500 | spin_unlock_irq(&curr->pi_lock); | 506 | raw_spin_unlock_irq(&curr->pi_lock); |
501 | } | 507 | } |
502 | 508 | ||
503 | static int | 509 | static int |
@@ -552,7 +558,7 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, | |||
552 | * change of the task flags, we do this protected by | 558 | * change of the task flags, we do this protected by |
553 | * p->pi_lock: | 559 | * p->pi_lock: |
554 | */ | 560 | */ |
555 | spin_lock_irq(&p->pi_lock); | 561 | raw_spin_lock_irq(&p->pi_lock); |
556 | if (unlikely(p->flags & PF_EXITING)) { | 562 | if (unlikely(p->flags & PF_EXITING)) { |
557 | /* | 563 | /* |
558 | * The task is on the way out. When PF_EXITPIDONE is | 564 | * The task is on the way out. When PF_EXITPIDONE is |
@@ -561,7 +567,7 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, | |||
561 | */ | 567 | */ |
562 | int ret = (p->flags & PF_EXITPIDONE) ? -ESRCH : -EAGAIN; | 568 | int ret = (p->flags & PF_EXITPIDONE) ? -ESRCH : -EAGAIN; |
563 | 569 | ||
564 | spin_unlock_irq(&p->pi_lock); | 570 | raw_spin_unlock_irq(&p->pi_lock); |
565 | put_task_struct(p); | 571 | put_task_struct(p); |
566 | return ret; | 572 | return ret; |
567 | } | 573 | } |
@@ -580,7 +586,7 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, | |||
580 | WARN_ON(!list_empty(&pi_state->list)); | 586 | WARN_ON(!list_empty(&pi_state->list)); |
581 | list_add(&pi_state->list, &p->pi_state_list); | 587 | list_add(&pi_state->list, &p->pi_state_list); |
582 | pi_state->owner = p; | 588 | pi_state->owner = p; |
583 | spin_unlock_irq(&p->pi_lock); | 589 | raw_spin_unlock_irq(&p->pi_lock); |
584 | 590 | ||
585 | put_task_struct(p); | 591 | put_task_struct(p); |
586 | 592 | ||
@@ -754,7 +760,7 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this) | |||
754 | if (!pi_state) | 760 | if (!pi_state) |
755 | return -EINVAL; | 761 | return -EINVAL; |
756 | 762 | ||
757 | spin_lock(&pi_state->pi_mutex.wait_lock); | 763 | raw_spin_lock(&pi_state->pi_mutex.wait_lock); |
758 | new_owner = rt_mutex_next_owner(&pi_state->pi_mutex); | 764 | new_owner = rt_mutex_next_owner(&pi_state->pi_mutex); |
759 | 765 | ||
760 | /* | 766 | /* |
@@ -783,23 +789,23 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this) | |||
783 | else if (curval != uval) | 789 | else if (curval != uval) |
784 | ret = -EINVAL; | 790 | ret = -EINVAL; |
785 | if (ret) { | 791 | if (ret) { |
786 | spin_unlock(&pi_state->pi_mutex.wait_lock); | 792 | raw_spin_unlock(&pi_state->pi_mutex.wait_lock); |
787 | return ret; | 793 | return ret; |
788 | } | 794 | } |
789 | } | 795 | } |
790 | 796 | ||
791 | spin_lock_irq(&pi_state->owner->pi_lock); | 797 | raw_spin_lock_irq(&pi_state->owner->pi_lock); |
792 | WARN_ON(list_empty(&pi_state->list)); | 798 | WARN_ON(list_empty(&pi_state->list)); |
793 | list_del_init(&pi_state->list); | 799 | list_del_init(&pi_state->list); |
794 | spin_unlock_irq(&pi_state->owner->pi_lock); | 800 | raw_spin_unlock_irq(&pi_state->owner->pi_lock); |
795 | 801 | ||
796 | spin_lock_irq(&new_owner->pi_lock); | 802 | raw_spin_lock_irq(&new_owner->pi_lock); |
797 | WARN_ON(!list_empty(&pi_state->list)); | 803 | WARN_ON(!list_empty(&pi_state->list)); |
798 | list_add(&pi_state->list, &new_owner->pi_state_list); | 804 | list_add(&pi_state->list, &new_owner->pi_state_list); |
799 | pi_state->owner = new_owner; | 805 | pi_state->owner = new_owner; |
800 | spin_unlock_irq(&new_owner->pi_lock); | 806 | raw_spin_unlock_irq(&new_owner->pi_lock); |
801 | 807 | ||
802 | spin_unlock(&pi_state->pi_mutex.wait_lock); | 808 | raw_spin_unlock(&pi_state->pi_mutex.wait_lock); |
803 | rt_mutex_unlock(&pi_state->pi_mutex); | 809 | rt_mutex_unlock(&pi_state->pi_mutex); |
804 | 810 | ||
805 | return 0; | 811 | return 0; |
@@ -1004,7 +1010,7 @@ void requeue_futex(struct futex_q *q, struct futex_hash_bucket *hb1, | |||
1004 | plist_add(&q->list, &hb2->chain); | 1010 | plist_add(&q->list, &hb2->chain); |
1005 | q->lock_ptr = &hb2->lock; | 1011 | q->lock_ptr = &hb2->lock; |
1006 | #ifdef CONFIG_DEBUG_PI_LIST | 1012 | #ifdef CONFIG_DEBUG_PI_LIST |
1007 | q->list.plist.lock = &hb2->lock; | 1013 | q->list.plist.spinlock = &hb2->lock; |
1008 | #endif | 1014 | #endif |
1009 | } | 1015 | } |
1010 | get_futex_key_refs(key2); | 1016 | get_futex_key_refs(key2); |
@@ -1040,7 +1046,7 @@ void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key, | |||
1040 | 1046 | ||
1041 | q->lock_ptr = &hb->lock; | 1047 | q->lock_ptr = &hb->lock; |
1042 | #ifdef CONFIG_DEBUG_PI_LIST | 1048 | #ifdef CONFIG_DEBUG_PI_LIST |
1043 | q->list.plist.lock = &hb->lock; | 1049 | q->list.plist.spinlock = &hb->lock; |
1044 | #endif | 1050 | #endif |
1045 | 1051 | ||
1046 | wake_up_state(q->task, TASK_NORMAL); | 1052 | wake_up_state(q->task, TASK_NORMAL); |
@@ -1388,7 +1394,7 @@ static inline void queue_me(struct futex_q *q, struct futex_hash_bucket *hb) | |||
1388 | 1394 | ||
1389 | plist_node_init(&q->list, prio); | 1395 | plist_node_init(&q->list, prio); |
1390 | #ifdef CONFIG_DEBUG_PI_LIST | 1396 | #ifdef CONFIG_DEBUG_PI_LIST |
1391 | q->list.plist.lock = &hb->lock; | 1397 | q->list.plist.spinlock = &hb->lock; |
1392 | #endif | 1398 | #endif |
1393 | plist_add(&q->list, &hb->chain); | 1399 | plist_add(&q->list, &hb->chain); |
1394 | q->task = current; | 1400 | q->task = current; |
@@ -1523,18 +1529,18 @@ retry: | |||
1523 | * itself. | 1529 | * itself. |
1524 | */ | 1530 | */ |
1525 | if (pi_state->owner != NULL) { | 1531 | if (pi_state->owner != NULL) { |
1526 | spin_lock_irq(&pi_state->owner->pi_lock); | 1532 | raw_spin_lock_irq(&pi_state->owner->pi_lock); |
1527 | WARN_ON(list_empty(&pi_state->list)); | 1533 | WARN_ON(list_empty(&pi_state->list)); |
1528 | list_del_init(&pi_state->list); | 1534 | list_del_init(&pi_state->list); |
1529 | spin_unlock_irq(&pi_state->owner->pi_lock); | 1535 | raw_spin_unlock_irq(&pi_state->owner->pi_lock); |
1530 | } | 1536 | } |
1531 | 1537 | ||
1532 | pi_state->owner = newowner; | 1538 | pi_state->owner = newowner; |
1533 | 1539 | ||
1534 | spin_lock_irq(&newowner->pi_lock); | 1540 | raw_spin_lock_irq(&newowner->pi_lock); |
1535 | WARN_ON(!list_empty(&pi_state->list)); | 1541 | WARN_ON(!list_empty(&pi_state->list)); |
1536 | list_add(&pi_state->list, &newowner->pi_state_list); | 1542 | list_add(&pi_state->list, &newowner->pi_state_list); |
1537 | spin_unlock_irq(&newowner->pi_lock); | 1543 | raw_spin_unlock_irq(&newowner->pi_lock); |
1538 | return 0; | 1544 | return 0; |
1539 | 1545 | ||
1540 | /* | 1546 | /* |