mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-09-22 09:34:56 +02:00
cgroup: Increment nr_dying_subsys_* from rmdir context
[ Upstream commit13e786b64b] Incrementing nr_dying_subsys_* in offline_css(), which is executed by cgroup_offline_wq worker, leads to a race where user can see the value to be 0 if he reads cgroup.stat after calling rmdir and before the worker executes. This makes the user wrongly expect resources released by the removed cgroup to be available for a new assignment. Increment nr_dying_subsys_* from kill_css(), which is called from the cgroup_rmdir() context. Fixes:ab03125268("cgroup: Show # of subsystem CSSes in cgroup.stat") Signed-off-by: Petr Malat <oss@malat.biz> Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
64a5a3dfa8
commit
1aa08e1fd6
+12
-10
@@ -5773,16 +5773,6 @@ static void offline_css(struct cgroup_subsys_state *css)
|
||||
RCU_INIT_POINTER(css->cgroup->subsys[ss->id], NULL);
|
||||
|
||||
wake_up_all(&css->cgroup->offline_waitq);
|
||||
|
||||
css->cgroup->nr_dying_subsys[ss->id]++;
|
||||
/*
|
||||
* Parent css and cgroup cannot be freed until after the freeing
|
||||
* of child css, see css_free_rwork_fn().
|
||||
*/
|
||||
while ((css = css->parent)) {
|
||||
css->nr_descendants--;
|
||||
css->cgroup->nr_dying_subsys[ss->id]++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -6094,6 +6084,8 @@ static void css_killed_ref_fn(struct percpu_ref *ref)
|
||||
*/
|
||||
static void kill_css(struct cgroup_subsys_state *css)
|
||||
{
|
||||
struct cgroup_subsys *ss = css->ss;
|
||||
|
||||
lockdep_assert_held(&cgroup_mutex);
|
||||
|
||||
if (css->flags & CSS_DYING)
|
||||
@@ -6130,6 +6122,16 @@ static void kill_css(struct cgroup_subsys_state *css)
|
||||
* css is confirmed to be seen as killed on all CPUs.
|
||||
*/
|
||||
percpu_ref_kill_and_confirm(&css->refcnt, css_killed_ref_fn);
|
||||
|
||||
css->cgroup->nr_dying_subsys[ss->id]++;
|
||||
/*
|
||||
* Parent css and cgroup cannot be freed until after the freeing
|
||||
* of child css, see css_free_rwork_fn().
|
||||
*/
|
||||
while ((css = css->parent)) {
|
||||
css->nr_descendants--;
|
||||
css->cgroup->nr_dying_subsys[ss->id]++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user