aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorLai Jiangshan <laijs@cn.fujitsu.com>2009-01-07 21:07:36 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-08 11:31:02 -0500
commit2019f634ce5904c19eba4e86f51b1a119a53a9f1 (patch)
tree040b8645c0627baa0f4e44113589b5a4894ea629 /kernel
parentb12b533fa523e94e0cc9dc23274ae4f9439f1313 (diff)
cgroups: fix cgroup_iter_next() bug
We access res->cgroups without the task_lock(), so res->cgroups may be changed. it's unreliable, and "if (l == &res->cgroups->tasks)" may be false forever. We don't need add any lock for fixing this bug. we just access to struct css_set by struct cg_cgroup_link, not by struct task_struct. Since we hold css_set_lock, struct cg_cgroup_link is reliable. Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com> Reviewed-by: Paul Menage <menage@google.com> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Pavel Emelyanov <xemul@openvz.org> Cc: Balbir Singh <balbir@in.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/cgroup.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index d7ab4ffd8fd9..a391ab3bdfc6 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -1808,6 +1808,7 @@ struct task_struct *cgroup_iter_next(struct cgroup *cgrp,
1808{ 1808{
1809 struct task_struct *res; 1809 struct task_struct *res;
1810 struct list_head *l = it->task; 1810 struct list_head *l = it->task;
1811 struct cg_cgroup_link *link;
1811 1812
1812 /* If the iterator cg is NULL, we have no tasks */ 1813 /* If the iterator cg is NULL, we have no tasks */
1813 if (!it->cg_link) 1814 if (!it->cg_link)
@@ -1815,7 +1816,8 @@ struct task_struct *cgroup_iter_next(struct cgroup *cgrp,
1815 res = list_entry(l, struct task_struct, cg_list); 1816 res = list_entry(l, struct task_struct, cg_list);
1816 /* Advance iterator to find next entry */ 1817 /* Advance iterator to find next entry */
1817 l = l->next; 1818 l = l->next;
1818 if (l == &res->cgroups->tasks) { 1819 link = list_entry(it->cg_link, struct cg_cgroup_link, cgrp_link_list);
1820 if (l == &link->cg->tasks) {
1819 /* We reached the end of this task list - move on to 1821 /* We reached the end of this task list - move on to
1820 * the next cg_cgroup_link */ 1822 * the next cg_cgroup_link */
1821 cgroup_advance_iter(cgrp, it); 1823 cgroup_advance_iter(cgrp, it);