[PATCH cgroup/for-3.7-fixes 2/2] Revert "cgroup: Drop task_lock(parent) on cgroup_fork()"
Frederic Weisbecker
fweisbec at gmail.com
Fri Oct 19 13:45:15 UTC 2012
2012/10/18 Tejun Heo <tj at kernel.org>:
> From c8b27924a8b6fd74066088f1cf07c256bbc6ed74 Mon Sep 17 00:00:00 2001
> From: Tejun Heo <tj at kernel.org>
> Date: Thu, 18 Oct 2012 17:52:07 -0700
>
> This reverts commit 7e381b0eb1e1a9805c37335562e8dc02e7d7848c.
>
> The commit incorrectly assumed that fork path always performed
> threadgroup_change_begin/end() and depended on that for
> synchronization against task exit and cgroup migration paths instead
> of explicitly grabbing task_lock().
>
> threadgroup_change is not locked when forking a new process (as
> opposed to a new thread in the same process) and even if it were it
> wouldn't be effective as different processes use different threadgroup
> locks.
>
> Revert the incorrect optimization.
>
> Signed-off-by: Tejun Heo <tj at kernel.org>
> LKML-Reference: <20121008020000.GB2575 at localhost>
(bitterly) Acked-by: Frederic Weisbecker <fweisbec at gmail.com> :-)
> Cc: Li Zefan <lizefan at huawei.com>
> Cc: stable at vger.kernel.org
> ---
> kernel/cgroup.c | 23 ++++++-----------------
> 1 files changed, 6 insertions(+), 17 deletions(-)
>
> diff --git a/kernel/cgroup.c b/kernel/cgroup.c
> index 2990dc7..f24f724 100644
> --- a/kernel/cgroup.c
> +++ b/kernel/cgroup.c
> @@ -4814,31 +4814,20 @@ static const struct file_operations proc_cgroupstats_operations = {
> *
> * A pointer to the shared css_set was automatically copied in
> * fork.c by dup_task_struct(). However, we ignore that copy, since
> - * it was not made under the protection of RCU, cgroup_mutex or
> - * threadgroup_change_begin(), so it might no longer be a valid
> - * cgroup pointer. cgroup_attach_task() might have already changed
> - * current->cgroups, allowing the previously referenced cgroup
> - * group to be removed and freed.
> - *
> - * Outside the pointer validity we also need to process the css_set
> - * inheritance between threadgoup_change_begin() and
> - * threadgoup_change_end(), this way there is no leak in any process
> - * wide migration performed by cgroup_attach_proc() that could otherwise
> - * miss a thread because it is too early or too late in the fork stage.
> + * it was not made under the protection of RCU or cgroup_mutex, so
> + * might no longer be a valid cgroup pointer. cgroup_attach_task() might
> + * have already changed current->cgroups, allowing the previously
> + * referenced cgroup group to be removed and freed.
> *
> * At the point that cgroup_fork() is called, 'current' is the parent
> * task, and the passed argument 'child' points to the child task.
> */
> void cgroup_fork(struct task_struct *child)
> {
> - /*
> - * We don't need to task_lock() current because current->cgroups
> - * can't be changed concurrently here. The parent obviously hasn't
> - * exited and called cgroup_exit(), and we are synchronized against
> - * cgroup migration through threadgroup_change_begin().
> - */
> + task_lock(current);
> child->cgroups = current->cgroups;
> get_css_set(child->cgroups);
> + task_unlock(current);
> INIT_LIST_HEAD(&child->cg_list);
> }
>
> --
> 1.7.7.3
>
More information about the Containers
mailing list