diff options
| author | Lai Jiangshan <laijs@cn.fujitsu.com> | 2009-01-07 18:07:36 -0800 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-08 08:31:02 -0800 | 
| commit | 2019f634ce5904c19eba4e86f51b1a119a53a9f1 (patch) | |
| tree | 040b8645c0627baa0f4e44113589b5a4894ea629 /kernel/cgroup.c | |
| parent | b12b533fa523e94e0cc9dc23274ae4f9439f1313 (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/cgroup.c')
| -rw-r--r-- | kernel/cgroup.c | 4 | 
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,  {  	struct task_struct *res;  	struct list_head *l = it->task; +	struct cg_cgroup_link *link;  	/* If the iterator cg is NULL, we have no tasks */  	if (!it->cg_link) @@ -1815,7 +1816,8 @@ struct task_struct *cgroup_iter_next(struct cgroup *cgrp,  	res = list_entry(l, struct task_struct, cg_list);  	/* Advance iterator to find next entry */  	l = l->next; -	if (l == &res->cgroups->tasks) { +	link = list_entry(it->cg_link, struct cg_cgroup_link, cgrp_link_list); +	if (l == &link->cg->tasks) {  		/* We reached the end of this task list - move on to  		 * the next cg_cgroup_link */  		cgroup_advance_iter(cgrp, it); | 
