diff options
author | Tejun Heo <tj@kernel.org> | 2013-08-26 18:40:56 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2013-08-26 18:40:56 -0400 |
commit | ca8bdcaff0d77990fb69e0f946018c96a70851cc (patch) | |
tree | ac98548b8fc61cf8017a67df9be6c5a4e87a6201 /kernel/cgroup.c | |
parent | 35cf083619da5677f83e9a8eae813f0b413d7082 (diff) |
cgroup: make cgroup_css() take cgroup_subsys * instead and allow NULL subsys
cgroup_css() is no longer used in hot paths. Make it take struct
cgroup_subsys * and allow the users to specify NULL subsys to obtain
the dummy_css. This removes open-coded NULL subsystem testing in a
couple users and generally simplifies the code.
After this patch, css_from_dir() also allows NULL @ss and returns the
matching dummy_css. This behavior change doesn't affect its only user
- perf.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Li Zefan <lizefan@huawei.com>
Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r-- | kernel/cgroup.c | 90 |
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 | */ |
237 | static struct cgroup_subsys_state *cgroup_css(struct cgroup *cgrp, | 237 | static 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); | |||
1930 | struct cgroup_subsys_state *cgroup_taskset_cur_css(struct cgroup_taskset *tset, | 1933 | struct 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 | } |
1935 | EXPORT_SYMBOL_GPL(cgroup_taskset_cur_css); | 1938 | EXPORT_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: | |||
2135 | out_cancel_attach: | 2138 | out_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 | } |
3090 | EXPORT_SYMBOL_GPL(css_next_child); | 3086 | EXPORT_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 | /** |