diff options
author | Tejun Heo <tj@kernel.org> | 2012-11-06 15:26:23 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2012-11-06 15:26:23 -0500 |
commit | 5b805f2a7675634fbdf9ac1c9b2256905ab2ea68 (patch) | |
tree | ee00d1e3d757458d66209b926d274491c6c3f61c /kernel/cgroup.c | |
parent | 1db1e31b1ee3ae126ef98f39083b5f213c7b41bf (diff) | |
parent | 201e72acb2d3821e2de9ce6091e98859c316b29a (diff) |
Merge branch 'cgroup/for-3.7-fixes' into cgroup/for-3.8
This is to receive device_cgroup fixes so that further device_cgroup
changes can be made in cgroup/for-3.8.
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r-- | kernel/cgroup.c | 41 |
1 files changed, 10 insertions, 31 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index e3045ad4267a..3070164e2036 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -1911,9 +1911,8 @@ static void cgroup_task_migrate(struct cgroup *cgrp, struct cgroup *oldcgrp, | |||
1911 | * trading it for newcg is protected by cgroup_mutex, we're safe to drop | 1911 | * trading it for newcg is protected by cgroup_mutex, we're safe to drop |
1912 | * it here; it will be freed under RCU. | 1912 | * it here; it will be freed under RCU. |
1913 | */ | 1913 | */ |
1914 | put_css_set(oldcg); | ||
1915 | |||
1916 | set_bit(CGRP_RELEASABLE, &oldcgrp->flags); | 1914 | set_bit(CGRP_RELEASABLE, &oldcgrp->flags); |
1915 | put_css_set(oldcg); | ||
1917 | } | 1916 | } |
1918 | 1917 | ||
1919 | /** | 1918 | /** |
@@ -4681,31 +4680,20 @@ static const struct file_operations proc_cgroupstats_operations = { | |||
4681 | * | 4680 | * |
4682 | * A pointer to the shared css_set was automatically copied in | 4681 | * A pointer to the shared css_set was automatically copied in |
4683 | * fork.c by dup_task_struct(). However, we ignore that copy, since | 4682 | * fork.c by dup_task_struct(). However, we ignore that copy, since |
4684 | * it was not made under the protection of RCU, cgroup_mutex or | 4683 | * it was not made under the protection of RCU or cgroup_mutex, so |
4685 | * threadgroup_change_begin(), so it might no longer be a valid | 4684 | * might no longer be a valid cgroup pointer. cgroup_attach_task() might |
4686 | * cgroup pointer. cgroup_attach_task() might have already changed | 4685 | * have already changed current->cgroups, allowing the previously |
4687 | * current->cgroups, allowing the previously referenced cgroup | 4686 | * referenced cgroup group to be removed and freed. |
4688 | * group to be removed and freed. | ||
4689 | * | ||
4690 | * Outside the pointer validity we also need to process the css_set | ||
4691 | * inheritance between threadgoup_change_begin() and | ||
4692 | * threadgoup_change_end(), this way there is no leak in any process | ||
4693 | * wide migration performed by cgroup_attach_proc() that could otherwise | ||
4694 | * miss a thread because it is too early or too late in the fork stage. | ||
4695 | * | 4687 | * |
4696 | * At the point that cgroup_fork() is called, 'current' is the parent | 4688 | * At the point that cgroup_fork() is called, 'current' is the parent |
4697 | * task, and the passed argument 'child' points to the child task. | 4689 | * task, and the passed argument 'child' points to the child task. |
4698 | */ | 4690 | */ |
4699 | void cgroup_fork(struct task_struct *child) | 4691 | void cgroup_fork(struct task_struct *child) |
4700 | { | 4692 | { |
4701 | /* | 4693 | task_lock(current); |
4702 | * We don't need to task_lock() current because current->cgroups | ||
4703 | * can't be changed concurrently here. The parent obviously hasn't | ||
4704 | * exited and called cgroup_exit(), and we are synchronized against | ||
4705 | * cgroup migration through threadgroup_change_begin(). | ||
4706 | */ | ||
4707 | child->cgroups = current->cgroups; | 4694 | child->cgroups = current->cgroups; |
4708 | get_css_set(child->cgroups); | 4695 | get_css_set(child->cgroups); |
4696 | task_unlock(current); | ||
4709 | INIT_LIST_HEAD(&child->cg_list); | 4697 | INIT_LIST_HEAD(&child->cg_list); |
4710 | } | 4698 | } |
4711 | 4699 | ||
@@ -4736,19 +4724,10 @@ void cgroup_post_fork(struct task_struct *child) | |||
4736 | */ | 4724 | */ |
4737 | if (use_task_css_set_links) { | 4725 | if (use_task_css_set_links) { |
4738 | write_lock(&css_set_lock); | 4726 | write_lock(&css_set_lock); |
4739 | if (list_empty(&child->cg_list)) { | 4727 | task_lock(child); |
4740 | /* | 4728 | if (list_empty(&child->cg_list)) |
4741 | * It's safe to use child->cgroups without task_lock() | ||
4742 | * here because we are protected through | ||
4743 | * threadgroup_change_begin() against concurrent | ||
4744 | * css_set change in cgroup_task_migrate(). Also | ||
4745 | * the task can't exit at that point until | ||
4746 | * wake_up_new_task() is called, so we are protected | ||
4747 | * against cgroup_exit() setting child->cgroup to | ||
4748 | * init_css_set. | ||
4749 | */ | ||
4750 | list_add(&child->cg_list, &child->cgroups->tasks); | 4729 | list_add(&child->cg_list, &child->cgroups->tasks); |
4751 | } | 4730 | task_unlock(child); |
4752 | write_unlock(&css_set_lock); | 4731 | write_unlock(&css_set_lock); |
4753 | } | 4732 | } |
4754 | 4733 | ||