Messages in this thread Patch in this message | | | Subject | [PATCH 1/4] exit: Move read_unlock() up in mm_update_next_owner() | From | Kirill Tkhai <> | Date | Thu, 26 Apr 2018 14:00:33 +0300 |
| |
All the places, we update task's mm, are made this under task_lock(). These are exec_mmap(), exit_mm() and kernel thread's use_mm() and unuse_mm(). The only exception is copy_mm(), which initializes newborn task's mm, but we can't race with it, as mm_update_next_owner() iterates tasks already linked to task list.
get_task_struct() guarantees that task_struct can't free. exec_mmap() and exit_mm() both call mm_update_next_owner():
task_lock(current); current->mm = new_mm; task_unlock(current); mm_update_next_owner(mm);
and since mm_update_next_owner() checks and assigns mm under task_lock() too, they can't miss they became a new mm owner. So we can relax the lock and release tasklist_lock earlier.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com> --- kernel/exit.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/kernel/exit.c b/kernel/exit.c index c3c7ac560114..9fb7b699bdeb 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -464,18 +464,15 @@ void mm_update_next_owner(struct mm_struct *mm) return; assign_new_owner: - BUG_ON(c == p); get_task_struct(c); + read_unlock(&tasklist_lock); + BUG_ON(c == p); + /* * The task_lock protects c->mm from changing. * We always want mm->owner->mm == mm */ task_lock(c); - /* - * Delay read_unlock() till we have the task_lock() - * to ensure that c does not slip away underneath us - */ - read_unlock(&tasklist_lock); if (c->mm != mm) { task_unlock(c); put_task_struct(c);
| |