aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/cgroup.c72
1 files changed, 43 insertions, 29 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 5d452e7fcb4f..4178e45becb4 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -222,8 +222,8 @@ static struct cftype cgroup_legacy_base_files[];
222static int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask); 222static int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask);
223static void css_task_iter_advance(struct css_task_iter *it); 223static void css_task_iter_advance(struct css_task_iter *it);
224static int cgroup_destroy_locked(struct cgroup *cgrp); 224static int cgroup_destroy_locked(struct cgroup *cgrp);
225static int create_css(struct cgroup *cgrp, struct cgroup_subsys *ss, 225static struct cgroup_subsys_state *css_create(struct cgroup *cgrp,
226 bool visible); 226 struct cgroup_subsys *ss);
227static void css_release(struct percpu_ref *ref); 227static void css_release(struct percpu_ref *ref);
228static void kill_css(struct cgroup_subsys_state *css); 228static void kill_css(struct cgroup_subsys_state *css);
229static int cgroup_addrm_files(struct cgroup_subsys_state *css, 229static int cgroup_addrm_files(struct cgroup_subsys_state *css,
@@ -3082,14 +3082,26 @@ static ssize_t cgroup_subtree_control_write(struct kernfs_open_file *of,
3082 */ 3082 */
3083 do_each_subsys_mask(ss, ssid, enable) { 3083 do_each_subsys_mask(ss, ssid, enable) {
3084 cgroup_for_each_live_child(child, cgrp) { 3084 cgroup_for_each_live_child(child, cgrp) {
3085 if (css_enable & (1 << ssid)) 3085 if (css_enable & (1 << ssid)) {
3086 ret = create_css(child, ss, 3086 struct cgroup_subsys_state *css;
3087 cgrp->subtree_control & (1 << ssid)); 3087
3088 else 3088 css = css_create(child, ss);
3089 if (IS_ERR(css)) {
3090 ret = PTR_ERR(css);
3091 goto err_undo_css;
3092 }
3093
3094 if (cgrp->subtree_control & (1 << ssid)) {
3095 ret = css_populate_dir(css, NULL);
3096 if (ret)
3097 goto err_undo_css;
3098 }
3099 } else {
3089 ret = css_populate_dir(cgroup_css(child, ss), 3100 ret = css_populate_dir(cgroup_css(child, ss),
3090 NULL); 3101 NULL);
3091 if (ret) 3102 if (ret)
3092 goto err_undo_css; 3103 goto err_undo_css;
3104 }
3093 } 3105 }
3094 } while_each_subsys_mask(); 3106 } while_each_subsys_mask();
3095 3107
@@ -4717,7 +4729,9 @@ static void css_release_work_fn(struct work_struct *work)
4717 * Those are supported by RCU protecting clearing of 4729 * Those are supported by RCU protecting clearing of
4718 * cgrp->kn->priv backpointer. 4730 * cgrp->kn->priv backpointer.
4719 */ 4731 */
4720 RCU_INIT_POINTER(*(void __rcu __force **)&cgrp->kn->priv, NULL); 4732 if (cgrp->kn)
4733 RCU_INIT_POINTER(*(void __rcu __force **)&cgrp->kn->priv,
4734 NULL);
4721 } 4735 }
4722 4736
4723 mutex_unlock(&cgroup_mutex); 4737 mutex_unlock(&cgroup_mutex);
@@ -4801,17 +4815,16 @@ static void offline_css(struct cgroup_subsys_state *css)
4801} 4815}
4802 4816
4803/** 4817/**
4804 * create_css - create a cgroup_subsys_state 4818 * css_create - create a cgroup_subsys_state
4805 * @cgrp: the cgroup new css will be associated with 4819 * @cgrp: the cgroup new css will be associated with
4806 * @ss: the subsys of new css 4820 * @ss: the subsys of new css
4807 * @visible: whether to create control knobs for the new css or not
4808 * 4821 *
4809 * Create a new css associated with @cgrp - @ss pair. On success, the new 4822 * Create a new css associated with @cgrp - @ss pair. On success, the new
4810 * css is online and installed in @cgrp with all interface files created if 4823 * css is online and installed in @cgrp. This function doesn't create the
4811 * @visible. Returns 0 on success, -errno on failure. 4824 * interface files. Returns 0 on success, -errno on failure.
4812 */ 4825 */
4813static int create_css(struct cgroup *cgrp, struct cgroup_subsys *ss, 4826static struct cgroup_subsys_state *css_create(struct cgroup *cgrp,
4814 bool visible) 4827 struct cgroup_subsys *ss)
4815{ 4828{
4816 struct cgroup *parent = cgroup_parent(cgrp); 4829 struct cgroup *parent = cgroup_parent(cgrp);
4817 struct cgroup_subsys_state *parent_css = cgroup_css(parent, ss); 4830 struct cgroup_subsys_state *parent_css = cgroup_css(parent, ss);
@@ -4822,7 +4835,7 @@ static int create_css(struct cgroup *cgrp, struct cgroup_subsys *ss,
4822 4835
4823 css = ss->css_alloc(parent_css); 4836 css = ss->css_alloc(parent_css);
4824 if (IS_ERR(css)) 4837 if (IS_ERR(css))
4825 return PTR_ERR(css); 4838 return css;
4826 4839
4827 init_and_link_css(css, ss, cgrp); 4840 init_and_link_css(css, ss, cgrp);
4828 4841
@@ -4835,12 +4848,6 @@ static int create_css(struct cgroup *cgrp, struct cgroup_subsys *ss,
4835 goto err_free_percpu_ref; 4848 goto err_free_percpu_ref;
4836 css->id = err; 4849 css->id = err;
4837 4850
4838 if (visible) {
4839 err = css_populate_dir(css, NULL);
4840 if (err)
4841 goto err_free_id;
4842 }
4843
4844 /* @css is ready to be brought online now, make it visible */ 4851 /* @css is ready to be brought online now, make it visible */
4845 list_add_tail_rcu(&css->sibling, &parent_css->children); 4852 list_add_tail_rcu(&css->sibling, &parent_css->children);
4846 cgroup_idr_replace(&ss->css_idr, css, css->id); 4853 cgroup_idr_replace(&ss->css_idr, css, css->id);
@@ -4858,18 +4865,16 @@ static int create_css(struct cgroup *cgrp, struct cgroup_subsys *ss,
4858 ss->warned_broken_hierarchy = true; 4865 ss->warned_broken_hierarchy = true;
4859 } 4866 }
4860 4867
4861 return 0; 4868 return css;
4862 4869
4863err_list_del: 4870err_list_del:
4864 list_del_rcu(&css->sibling); 4871 list_del_rcu(&css->sibling);
4865 css_clear_dir(css, NULL);
4866err_free_id:
4867 cgroup_idr_remove(&ss->css_idr, css->id); 4872 cgroup_idr_remove(&ss->css_idr, css->id);
4868err_free_percpu_ref: 4873err_free_percpu_ref:
4869 percpu_ref_exit(&css->refcnt); 4874 percpu_ref_exit(&css->refcnt);
4870err_free_css: 4875err_free_css:
4871 call_rcu(&css->rcu_head, css_free_rcu_fn); 4876 call_rcu(&css->rcu_head, css_free_rcu_fn);
4872 return err; 4877 return ERR_PTR(err);
4873} 4878}
4874 4879
4875static int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name, 4880static int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
@@ -4966,10 +4971,19 @@ static int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
4966 4971
4967 /* let's create and online css's */ 4972 /* let's create and online css's */
4968 do_each_subsys_mask(ss, ssid, parent->subtree_ss_mask) { 4973 do_each_subsys_mask(ss, ssid, parent->subtree_ss_mask) {
4969 ret = create_css(cgrp, ss, 4974 struct cgroup_subsys_state *css;
4970 parent->subtree_control & (1 << ssid)); 4975
4971 if (ret) 4976 css = css_create(cgrp, ss);
4977 if (IS_ERR(css)) {
4978 ret = PTR_ERR(css);
4972 goto out_destroy; 4979 goto out_destroy;
4980 }
4981
4982 if (parent->subtree_control & (1 << ssid)) {
4983 ret = css_populate_dir(css, NULL);
4984 if (ret)
4985 goto out_destroy;
4986 }
4973 } while_each_subsys_mask(); 4987 } while_each_subsys_mask();
4974 4988
4975 /* 4989 /*