summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/cgroup.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 5385839e727b..dcb06e181ce4 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -4138,19 +4138,21 @@ static void css_release_work_fn(struct work_struct *work)
struct cgroup_subsys *ss = css->ss;
struct cgroup *cgrp = css->cgroup;
+ mutex_lock(&cgroup_mutex);
+
+ list_del_rcu(&css->sibling);
+
if (ss) {
/* css release path */
cgroup_idr_remove(&ss->css_idr, css->id);
} else {
/* cgroup release path */
- mutex_lock(&cgroup_mutex);
- list_del_rcu(&cgrp->self.sibling);
- mutex_unlock(&cgroup_mutex);
-
cgroup_idr_remove(&cgrp->root->cgroup_idr, cgrp->id);
cgrp->id = -1;
}
+ mutex_unlock(&cgroup_mutex);
+
call_rcu(&css->rcu_head, css_free_rcu_fn);
}
@@ -4230,12 +4232,13 @@ static void offline_css(struct cgroup_subsys_state *css)
static int create_css(struct cgroup *cgrp, struct cgroup_subsys *ss)
{
struct cgroup *parent = cgroup_parent(cgrp);
+ struct cgroup_subsys_state *parent_css = cgroup_css(parent, ss);
struct cgroup_subsys_state *css;
int err;
lockdep_assert_held(&cgroup_mutex);
- css = ss->css_alloc(cgroup_css(parent, ss));
+ css = ss->css_alloc(parent_css);
if (IS_ERR(css))
return PTR_ERR(css);
@@ -4255,11 +4258,12 @@ static int create_css(struct cgroup *cgrp, struct cgroup_subsys *ss)
goto err_free_id;
/* @css is ready to be brought online now, make it visible */
+ list_add_tail_rcu(&css->sibling, &parent_css->children);
cgroup_idr_replace(&ss->css_idr, css, css->id);
err = online_css(css);
if (err)
- goto err_clear_dir;
+ goto err_list_del;
if (ss->broken_hierarchy && !ss->warned_broken_hierarchy &&
cgroup_parent(parent)) {
@@ -4272,7 +4276,8 @@ static int create_css(struct cgroup *cgrp, struct cgroup_subsys *ss)
return 0;
-err_clear_dir:
+err_list_del:
+ list_del_rcu(&css->sibling);
cgroup_clear_dir(css->cgroup, 1 << css->ss->id);
err_free_id:
cgroup_idr_remove(&ss->css_idr, css->id);