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);
 }
 
 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);
 
                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)) {
 
        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);