aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/cgroup.c90
1 files changed, 43 insertions, 47 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 921b1387c944..7516668d8325 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -226,19 +226,22 @@ static int cgroup_addrm_files(struct cgroup *cgrp, struct cftype cfts[],
226/** 226/**
227 * cgroup_css - obtain a cgroup's css for the specified subsystem 227 * cgroup_css - obtain a cgroup's css for the specified subsystem
228 * @cgrp: the cgroup of interest 228 * @cgrp: the cgroup of interest
229 * @subsys_id: the subsystem of interest 229 * @ss: the subsystem of interest (%NULL returns the dummy_css)
230 * 230 *
231 * Return @cgrp's css (cgroup_subsys_state) associated with @subsys_id. 231 * Return @cgrp's css (cgroup_subsys_state) associated with @ss. This
232 * This function must be called either under cgroup_mutex or 232 * function must be called either under cgroup_mutex or rcu_read_lock() and
233 * rcu_read_lock() and the caller is responsible for pinning the returned 233 * the caller is responsible for pinning the returned css if it wants to
234 * css if it wants to keep accessing it outside the said locks. This 234 * keep accessing it outside the said locks. This function may return
235 * function may return %NULL if @cgrp doesn't have @subsys_id enabled. 235 * %NULL if @cgrp doesn't have @subsys_id enabled.
236 */ 236 */
237static struct cgroup_subsys_state *cgroup_css(struct cgroup *cgrp, 237static struct cgroup_subsys_state *cgroup_css(struct cgroup *cgrp,
238 int subsys_id) 238 struct cgroup_subsys *ss)
239{ 239{
240 return rcu_dereference_check(cgrp->subsys[subsys_id], 240 if (ss)
241 lockdep_is_held(&cgroup_mutex)); 241 return rcu_dereference_check(cgrp->subsys[ss->subsys_id],
242 lockdep_is_held(&cgroup_mutex));
243 else
244 return &cgrp->dummy_css;
242} 245}
243 246
244/* convenient tests for these bits */ 247/* convenient tests for these bits */
@@ -580,7 +583,7 @@ static struct css_set *find_existing_css_set(struct css_set *old_cset,
580 /* Subsystem is in this hierarchy. So we want 583 /* Subsystem is in this hierarchy. So we want
581 * the subsystem state from the new 584 * the subsystem state from the new
582 * cgroup */ 585 * cgroup */
583 template[i] = cgroup_css(cgrp, i); 586 template[i] = cgroup_css(cgrp, ss);
584 } else { 587 } else {
585 /* Subsystem is not in this hierarchy, so we 588 /* Subsystem is not in this hierarchy, so we
586 * don't want to change the subsystem state */ 589 * don't want to change the subsystem state */
@@ -1062,30 +1065,30 @@ static int rebind_subsystems(struct cgroupfs_root *root,
1062 1065
1063 if (bit & added_mask) { 1066 if (bit & added_mask) {
1064 /* We're binding this subsystem to this hierarchy */ 1067 /* We're binding this subsystem to this hierarchy */
1065 BUG_ON(cgroup_css(cgrp, i)); 1068 BUG_ON(cgroup_css(cgrp, ss));
1066 BUG_ON(!cgroup_css(cgroup_dummy_top, i)); 1069 BUG_ON(!cgroup_css(cgroup_dummy_top, ss));
1067 BUG_ON(cgroup_css(cgroup_dummy_top, i)->cgroup != cgroup_dummy_top); 1070 BUG_ON(cgroup_css(cgroup_dummy_top, ss)->cgroup != cgroup_dummy_top);
1068 1071
1069 rcu_assign_pointer(cgrp->subsys[i], 1072 rcu_assign_pointer(cgrp->subsys[i],
1070 cgroup_css(cgroup_dummy_top, i)); 1073 cgroup_css(cgroup_dummy_top, ss));
1071 cgroup_css(cgrp, i)->cgroup = cgrp; 1074 cgroup_css(cgrp, ss)->cgroup = cgrp;
1072 1075
1073 list_move(&ss->sibling, &root->subsys_list); 1076 list_move(&ss->sibling, &root->subsys_list);
1074 ss->root = root; 1077 ss->root = root;
1075 if (ss->bind) 1078 if (ss->bind)
1076 ss->bind(cgroup_css(cgrp, i)); 1079 ss->bind(cgroup_css(cgrp, ss));
1077 1080
1078 /* refcount was already taken, and we're keeping it */ 1081 /* refcount was already taken, and we're keeping it */
1079 root->subsys_mask |= bit; 1082 root->subsys_mask |= bit;
1080 } else if (bit & removed_mask) { 1083 } else if (bit & removed_mask) {
1081 /* We're removing this subsystem */ 1084 /* We're removing this subsystem */
1082 BUG_ON(cgroup_css(cgrp, i) != cgroup_css(cgroup_dummy_top, i)); 1085 BUG_ON(cgroup_css(cgrp, ss) != cgroup_css(cgroup_dummy_top, ss));
1083 BUG_ON(cgroup_css(cgrp, i)->cgroup != cgrp); 1086 BUG_ON(cgroup_css(cgrp, ss)->cgroup != cgrp);
1084 1087
1085 if (ss->bind) 1088 if (ss->bind)
1086 ss->bind(cgroup_css(cgroup_dummy_top, i)); 1089 ss->bind(cgroup_css(cgroup_dummy_top, ss));
1087 1090
1088 cgroup_css(cgroup_dummy_top, i)->cgroup = cgroup_dummy_top; 1091 cgroup_css(cgroup_dummy_top, ss)->cgroup = cgroup_dummy_top;
1089 RCU_INIT_POINTER(cgrp->subsys[i], NULL); 1092 RCU_INIT_POINTER(cgrp->subsys[i], NULL);
1090 1093
1091 cgroup_subsys[i]->root = &cgroup_dummy_root; 1094 cgroup_subsys[i]->root = &cgroup_dummy_root;
@@ -1930,7 +1933,7 @@ EXPORT_SYMBOL_GPL(cgroup_taskset_next);
1930struct cgroup_subsys_state *cgroup_taskset_cur_css(struct cgroup_taskset *tset, 1933struct cgroup_subsys_state *cgroup_taskset_cur_css(struct cgroup_taskset *tset,
1931 int subsys_id) 1934 int subsys_id)
1932{ 1935{
1933 return cgroup_css(tset->cur_cgrp, subsys_id); 1936 return cgroup_css(tset->cur_cgrp, cgroup_subsys[subsys_id]);
1934} 1937}
1935EXPORT_SYMBOL_GPL(cgroup_taskset_cur_css); 1938EXPORT_SYMBOL_GPL(cgroup_taskset_cur_css);
1936 1939
@@ -2071,7 +2074,7 @@ static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk,
2071 * step 1: check that we can legitimately attach to the cgroup. 2074 * step 1: check that we can legitimately attach to the cgroup.
2072 */ 2075 */
2073 for_each_root_subsys(root, ss) { 2076 for_each_root_subsys(root, ss) {
2074 struct cgroup_subsys_state *css = cgroup_css(cgrp, ss->subsys_id); 2077 struct cgroup_subsys_state *css = cgroup_css(cgrp, ss);
2075 2078
2076 if (ss->can_attach) { 2079 if (ss->can_attach) {
2077 retval = ss->can_attach(css, &tset); 2080 retval = ss->can_attach(css, &tset);
@@ -2113,7 +2116,7 @@ static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk,
2113 * step 4: do subsystem attach callbacks. 2116 * step 4: do subsystem attach callbacks.
2114 */ 2117 */
2115 for_each_root_subsys(root, ss) { 2118 for_each_root_subsys(root, ss) {
2116 struct cgroup_subsys_state *css = cgroup_css(cgrp, ss->subsys_id); 2119 struct cgroup_subsys_state *css = cgroup_css(cgrp, ss);
2117 2120
2118 if (ss->attach) 2121 if (ss->attach)
2119 ss->attach(css, &tset); 2122 ss->attach(css, &tset);
@@ -2135,7 +2138,7 @@ out_put_css_set_refs:
2135out_cancel_attach: 2138out_cancel_attach:
2136 if (retval) { 2139 if (retval) {
2137 for_each_root_subsys(root, ss) { 2140 for_each_root_subsys(root, ss) {
2138 struct cgroup_subsys_state *css = cgroup_css(cgrp, ss->subsys_id); 2141 struct cgroup_subsys_state *css = cgroup_css(cgrp, ss);
2139 2142
2140 if (ss == failed_ss) 2143 if (ss == failed_ss)
2141 break; 2144 break;
@@ -2481,13 +2484,9 @@ static int cgroup_file_open(struct inode *inode, struct file *file)
2481 * @css stays alive for all file operations. 2484 * @css stays alive for all file operations.
2482 */ 2485 */
2483 rcu_read_lock(); 2486 rcu_read_lock();
2484 if (cft->ss) { 2487 css = cgroup_css(cgrp, cft->ss);
2485 css = cgroup_css(cgrp, cft->ss->subsys_id); 2488 if (cft->ss && !css_tryget(css))
2486 if (!css_tryget(css)) 2489 css = NULL;
2487 css = NULL;
2488 } else {
2489 css = &cgrp->dummy_css;
2490 }
2491 rcu_read_unlock(); 2490 rcu_read_unlock();
2492 2491
2493 if (!css) 2492 if (!css)
@@ -2878,7 +2877,7 @@ static int cgroup_cfts_commit(struct cftype *cfts, bool is_add)
2878 2877
2879 /* add/rm files for all cgroups created before */ 2878 /* add/rm files for all cgroups created before */
2880 rcu_read_lock(); 2879 rcu_read_lock();
2881 css_for_each_descendant_pre(css, cgroup_css(root, ss->subsys_id)) { 2880 css_for_each_descendant_pre(css, cgroup_css(root, ss)) {
2882 struct cgroup *cgrp = css->cgroup; 2881 struct cgroup *cgrp = css->cgroup;
2883 2882
2884 if (cgroup_is_dead(cgrp)) 2883 if (cgroup_is_dead(cgrp))
@@ -3082,10 +3081,7 @@ css_next_child(struct cgroup_subsys_state *pos_css,
3082 if (&next->sibling == &cgrp->children) 3081 if (&next->sibling == &cgrp->children)
3083 return NULL; 3082 return NULL;
3084 3083
3085 if (parent_css->ss) 3084 return cgroup_css(next, parent_css->ss);
3086 return cgroup_css(next, parent_css->ss->subsys_id);
3087 else
3088 return &next->dummy_css;
3089} 3085}
3090EXPORT_SYMBOL_GPL(css_next_child); 3086EXPORT_SYMBOL_GPL(css_next_child);
3091 3087
@@ -4110,7 +4106,7 @@ static int cgroup_write_event_control(struct cgroup_subsys_state *dummy_css,
4110 rcu_read_lock(); 4106 rcu_read_lock();
4111 4107
4112 ret = -EINVAL; 4108 ret = -EINVAL;
4113 event->css = cgroup_css(cgrp, event->cft->ss->subsys_id); 4109 event->css = cgroup_css(cgrp, event->cft->ss);
4114 if (event->css) 4110 if (event->css)
4115 ret = 0; 4111 ret = 0;
4116 4112
@@ -4266,7 +4262,7 @@ static int cgroup_populate_dir(struct cgroup *cgrp, unsigned long subsys_mask)
4266 4262
4267 /* This cgroup is ready now */ 4263 /* This cgroup is ready now */
4268 for_each_root_subsys(cgrp->root, ss) { 4264 for_each_root_subsys(cgrp->root, ss) {
4269 struct cgroup_subsys_state *css = cgroup_css(cgrp, ss->subsys_id); 4265 struct cgroup_subsys_state *css = cgroup_css(cgrp, ss);
4270 struct css_id *id = rcu_dereference_protected(css->id, true); 4266 struct css_id *id = rcu_dereference_protected(css->id, true);
4271 4267
4272 /* 4268 /*
@@ -4349,11 +4345,11 @@ static void init_css(struct cgroup_subsys_state *css, struct cgroup_subsys *ss,
4349 css->id = NULL; 4345 css->id = NULL;
4350 4346
4351 if (cgrp->parent) 4347 if (cgrp->parent)
4352 css->parent = cgroup_css(cgrp->parent, ss->subsys_id); 4348 css->parent = cgroup_css(cgrp->parent, ss);
4353 else 4349 else
4354 css->flags |= CSS_ROOT; 4350 css->flags |= CSS_ROOT;
4355 4351
4356 BUG_ON(cgroup_css(cgrp, ss->subsys_id)); 4352 BUG_ON(cgroup_css(cgrp, ss));
4357} 4353}
4358 4354
4359/* invoke ->css_online() on a new CSS and mark it online if successful */ 4355/* invoke ->css_online() on a new CSS and mark it online if successful */
@@ -4466,7 +4462,7 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
4466 for_each_root_subsys(root, ss) { 4462 for_each_root_subsys(root, ss) {
4467 struct cgroup_subsys_state *css; 4463 struct cgroup_subsys_state *css;
4468 4464
4469 css = ss->css_alloc(cgroup_css(parent, ss->subsys_id)); 4465 css = ss->css_alloc(cgroup_css(parent, ss));
4470 if (IS_ERR(css)) { 4466 if (IS_ERR(css)) {
4471 err = PTR_ERR(css); 4467 err = PTR_ERR(css);
4472 goto err_free_all; 4468 goto err_free_all;
@@ -4712,7 +4708,7 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
4712 * percpu refs of all css's are confirmed to be killed. 4708 * percpu refs of all css's are confirmed to be killed.
4713 */ 4709 */
4714 for_each_root_subsys(cgrp->root, ss) 4710 for_each_root_subsys(cgrp->root, ss)
4715 kill_css(cgroup_css(cgrp, ss->subsys_id)); 4711 kill_css(cgroup_css(cgrp, ss));
4716 4712
4717 /* 4713 /*
4718 * Mark @cgrp dead. This prevents further task migration and child 4714 * Mark @cgrp dead. This prevents further task migration and child
@@ -4839,7 +4835,7 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
4839 /* Create the top cgroup state for this subsystem */ 4835 /* Create the top cgroup state for this subsystem */
4840 list_add(&ss->sibling, &cgroup_dummy_root.subsys_list); 4836 list_add(&ss->sibling, &cgroup_dummy_root.subsys_list);
4841 ss->root = &cgroup_dummy_root; 4837 ss->root = &cgroup_dummy_root;
4842 css = ss->css_alloc(cgroup_css(cgroup_dummy_top, ss->subsys_id)); 4838 css = ss->css_alloc(cgroup_css(cgroup_dummy_top, ss));
4843 /* We don't handle early failures gracefully */ 4839 /* We don't handle early failures gracefully */
4844 BUG_ON(IS_ERR(css)); 4840 BUG_ON(IS_ERR(css));
4845 init_css(css, ss, cgroup_dummy_top); 4841 init_css(css, ss, cgroup_dummy_top);
@@ -4918,7 +4914,7 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
4918 * struct, so this can happen first (i.e. before the dummy root 4914 * struct, so this can happen first (i.e. before the dummy root
4919 * attachment). 4915 * attachment).
4920 */ 4916 */
4921 css = ss->css_alloc(cgroup_css(cgroup_dummy_top, ss->subsys_id)); 4917 css = ss->css_alloc(cgroup_css(cgroup_dummy_top, ss));
4922 if (IS_ERR(css)) { 4918 if (IS_ERR(css)) {
4923 /* failure case - need to deassign the cgroup_subsys[] slot. */ 4919 /* failure case - need to deassign the cgroup_subsys[] slot. */
4924 cgroup_subsys[ss->subsys_id] = NULL; 4920 cgroup_subsys[ss->subsys_id] = NULL;
@@ -5000,7 +4996,7 @@ void cgroup_unload_subsys(struct cgroup_subsys *ss)
5000 4996
5001 mutex_lock(&cgroup_mutex); 4997 mutex_lock(&cgroup_mutex);
5002 4998
5003 offline_css(cgroup_css(cgroup_dummy_top, ss->subsys_id)); 4999 offline_css(cgroup_css(cgroup_dummy_top, ss));
5004 5000
5005 if (ss->use_id) 5001 if (ss->use_id)
5006 idr_destroy(&ss->idr); 5002 idr_destroy(&ss->idr);
@@ -5034,7 +5030,7 @@ void cgroup_unload_subsys(struct cgroup_subsys *ss)
5034 * the cgrp->subsys pointer to find their state. note that this 5030 * the cgrp->subsys pointer to find their state. note that this
5035 * also takes care of freeing the css_id. 5031 * also takes care of freeing the css_id.
5036 */ 5032 */
5037 ss->css_free(cgroup_css(cgroup_dummy_top, ss->subsys_id)); 5033 ss->css_free(cgroup_css(cgroup_dummy_top, ss));
5038 RCU_INIT_POINTER(cgroup_dummy_top->subsys[ss->subsys_id], NULL); 5034 RCU_INIT_POINTER(cgroup_dummy_top->subsys[ss->subsys_id], NULL);
5039 5035
5040 mutex_unlock(&cgroup_mutex); 5036 mutex_unlock(&cgroup_mutex);
@@ -5721,7 +5717,7 @@ struct cgroup_subsys_state *css_from_dir(struct dentry *dentry,
5721 return ERR_PTR(-EBADF); 5717 return ERR_PTR(-EBADF);
5722 5718
5723 cgrp = __d_cgrp(dentry); 5719 cgrp = __d_cgrp(dentry);
5724 return cgroup_css(cgrp, ss->subsys_id) ?: ERR_PTR(-ENOENT); 5720 return cgroup_css(cgrp, ss) ?: ERR_PTR(-ENOENT);
5725} 5721}
5726 5722
5727/** 5723/**