|
@@ -4138,19 +4138,21 @@ static void css_release_work_fn(struct work_struct *work)
|
|
struct cgroup_subsys *ss = css->ss;
|
|
struct cgroup_subsys *ss = css->ss;
|
|
struct cgroup *cgrp = css->cgroup;
|
|
struct cgroup *cgrp = css->cgroup;
|
|
|
|
|
|
|
|
+ mutex_lock(&cgroup_mutex);
|
|
|
|
+
|
|
|
|
+ list_del_rcu(&css->sibling);
|
|
|
|
+
|
|
if (ss) {
|
|
if (ss) {
|
|
/* css release path */
|
|
/* css release path */
|
|
cgroup_idr_remove(&ss->css_idr, css->id);
|
|
cgroup_idr_remove(&ss->css_idr, css->id);
|
|
} else {
|
|
} else {
|
|
/* cgroup release path */
|
|
/* 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);
|
|
cgroup_idr_remove(&cgrp->root->cgroup_idr, cgrp->id);
|
|
cgrp->id = -1;
|
|
cgrp->id = -1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ mutex_unlock(&cgroup_mutex);
|
|
|
|
+
|
|
call_rcu(&css->rcu_head, css_free_rcu_fn);
|
|
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)
|
|
static int create_css(struct cgroup *cgrp, struct cgroup_subsys *ss)
|
|
{
|
|
{
|
|
struct cgroup *parent = cgroup_parent(cgrp);
|
|
struct cgroup *parent = cgroup_parent(cgrp);
|
|
|
|
+ struct cgroup_subsys_state *parent_css = cgroup_css(parent, ss);
|
|
struct cgroup_subsys_state *css;
|
|
struct cgroup_subsys_state *css;
|
|
int err;
|
|
int err;
|
|
|
|
|
|
lockdep_assert_held(&cgroup_mutex);
|
|
lockdep_assert_held(&cgroup_mutex);
|
|
|
|
|
|
- css = ss->css_alloc(cgroup_css(parent, ss));
|
|
|
|
|
|
+ css = ss->css_alloc(parent_css);
|
|
if (IS_ERR(css))
|
|
if (IS_ERR(css))
|
|
return PTR_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;
|
|
goto err_free_id;
|
|
|
|
|
|
/* @css is ready to be brought online now, make it visible */
|
|
/* @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);
|
|
cgroup_idr_replace(&ss->css_idr, css, css->id);
|
|
|
|
|
|
err = online_css(css);
|
|
err = online_css(css);
|
|
if (err)
|
|
if (err)
|
|
- goto err_clear_dir;
|
|
|
|
|
|
+ goto err_list_del;
|
|
|
|
|
|
if (ss->broken_hierarchy && !ss->warned_broken_hierarchy &&
|
|
if (ss->broken_hierarchy && !ss->warned_broken_hierarchy &&
|
|
cgroup_parent(parent)) {
|
|
cgroup_parent(parent)) {
|
|
@@ -4272,7 +4276,8 @@ static int create_css(struct cgroup *cgrp, struct cgroup_subsys *ss)
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
-err_clear_dir:
|
|
|
|
|
|
+err_list_del:
|
|
|
|
+ list_del_rcu(&css->sibling);
|
|
cgroup_clear_dir(css->cgroup, 1 << css->ss->id);
|
|
cgroup_clear_dir(css->cgroup, 1 << css->ss->id);
|
|
err_free_id:
|
|
err_free_id:
|
|
cgroup_idr_remove(&ss->css_idr, css->id);
|
|
cgroup_idr_remove(&ss->css_idr, css->id);
|