diff options
Diffstat (limited to 'kernel/exit.c')
-rw-r--r-- | kernel/exit.c | 9 |
1 files changed, 4 insertions, 5 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index 7b71f87f1207..138887881a11 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -644,24 +644,23 @@ retry: | |||
644 | assign_new_owner: | 644 | assign_new_owner: |
645 | BUG_ON(c == p); | 645 | BUG_ON(c == p); |
646 | get_task_struct(c); | 646 | get_task_struct(c); |
647 | read_unlock(&tasklist_lock); | ||
648 | down_write(&mm->mmap_sem); | ||
647 | /* | 649 | /* |
648 | * The task_lock protects c->mm from changing. | 650 | * The task_lock protects c->mm from changing. |
649 | * We always want mm->owner->mm == mm | 651 | * We always want mm->owner->mm == mm |
650 | */ | 652 | */ |
651 | task_lock(c); | 653 | task_lock(c); |
652 | /* | ||
653 | * Delay read_unlock() till we have the task_lock() | ||
654 | * to ensure that c does not slip away underneath us | ||
655 | */ | ||
656 | read_unlock(&tasklist_lock); | ||
657 | if (c->mm != mm) { | 654 | if (c->mm != mm) { |
658 | task_unlock(c); | 655 | task_unlock(c); |
656 | up_write(&mm->mmap_sem); | ||
659 | put_task_struct(c); | 657 | put_task_struct(c); |
660 | goto retry; | 658 | goto retry; |
661 | } | 659 | } |
662 | cgroup_mm_owner_callbacks(mm->owner, c); | 660 | cgroup_mm_owner_callbacks(mm->owner, c); |
663 | mm->owner = c; | 661 | mm->owner = c; |
664 | task_unlock(c); | 662 | task_unlock(c); |
663 | up_write(&mm->mmap_sem); | ||
665 | put_task_struct(c); | 664 | put_task_struct(c); |
666 | } | 665 | } |
667 | #endif /* CONFIG_MM_OWNER */ | 666 | #endif /* CONFIG_MM_OWNER */ |