aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cgroup.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2013-08-08 20:11:23 -0400
committerTejun Heo <tj@kernel.org>2013-08-08 20:11:23 -0400
commiteb95419b023abacb415e2a18fea899023ce7624d (patch)
tree705284469b67cbe440b86c6cb81e1cf27648eba9 /kernel/cgroup.c
parent6387698699afd72d6304566fb6ccf84bffe07c56 (diff)
cgroup: pass around cgroup_subsys_state instead of cgroup in subsystem methods
cgroup is currently in the process of transitioning to using struct cgroup_subsys_state * as the primary handle instead of struct cgroup * in subsystem implementations for the following reasons. * With unified hierarchy, subsystems will be dynamically bound and unbound from cgroups and thus css's (cgroup_subsys_state) may be created and destroyed dynamically over the lifetime of a cgroup, which is different from the current state where all css's are allocated and destroyed together with the associated cgroup. This in turn means that cgroup_css() should be synchronized and may return NULL, making it more cumbersome to use. * Differing levels of per-subsystem granularity in the unified hierarchy means that the task and descendant iterators should behave differently depending on the specific subsystem the iteration is being performed for. * In majority of the cases, subsystems only care about its part in the cgroup hierarchy - ie. the hierarchy of css's. Subsystem methods often obtain the matching css pointer from the cgroup and don't bother with the cgroup pointer itself. Passing around css fits much better. This patch converts all cgroup_subsys methods to take @css instead of @cgroup. The conversions are mostly straight-forward. A few noteworthy changes are * ->css_alloc() now takes css of the parent cgroup rather than the pointer to the new cgroup as the css for the new cgroup doesn't exist yet. Knowing the parent css is enough for all the existing subsystems. * In kernel/cgroup.c::offline_css(), unnecessary open coded css dereference is replaced with local variable access. This patch shouldn't cause any behavior differences. v2: Unnecessary explicit cgrp->subsys[] deref in css_online() replaced with local variable @css as suggested by Li Zefan. Rebased on top of new for-3.12 which includes for-3.11-fixes so that ->css_free() invocation added by da0a12caff ("cgroup: fix a leak when percpu_ref_init() fails") is converted too. Suggested by Li Zefan. Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Li Zefan <lizefan@huawei.com> Acked-by: Michal Hocko <mhocko@suse.cz> Acked-by: Vivek Goyal <vgoyal@redhat.com> Acked-by: Aristeu Rozanski <aris@redhat.com> Acked-by: Daniel Wagner <daniel.wagner@bmw-carit.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ingo Molnar <mingo@redhat.com> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Balbir Singh <bsingharora@gmail.com> Cc: Matt Helsley <matthltc@us.ibm.com> Cc: Jens Axboe <axboe@kernel.dk> Cc: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r--kernel/cgroup.c57
1 files changed, 34 insertions, 23 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 4234428f1014..271d9a5cde5f 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -853,8 +853,11 @@ static void cgroup_free_fn(struct work_struct *work)
853 /* 853 /*
854 * Release the subsystem state objects. 854 * Release the subsystem state objects.
855 */ 855 */
856 for_each_root_subsys(cgrp->root, ss) 856 for_each_root_subsys(cgrp->root, ss) {
857 ss->css_free(cgrp); 857 struct cgroup_subsys_state *css = cgrp->subsys[ss->subsys_id];
858
859 ss->css_free(css);
860 }
858 861
859 cgrp->root->number_of_cgroups--; 862 cgrp->root->number_of_cgroups--;
860 mutex_unlock(&cgroup_mutex); 863 mutex_unlock(&cgroup_mutex);
@@ -1056,7 +1059,7 @@ static int rebind_subsystems(struct cgroupfs_root *root,
1056 list_move(&ss->sibling, &root->subsys_list); 1059 list_move(&ss->sibling, &root->subsys_list);
1057 ss->root = root; 1060 ss->root = root;
1058 if (ss->bind) 1061 if (ss->bind)
1059 ss->bind(cgrp); 1062 ss->bind(cgrp->subsys[i]);
1060 1063
1061 /* refcount was already taken, and we're keeping it */ 1064 /* refcount was already taken, and we're keeping it */
1062 root->subsys_mask |= bit; 1065 root->subsys_mask |= bit;
@@ -1066,7 +1069,7 @@ static int rebind_subsystems(struct cgroupfs_root *root,
1066 BUG_ON(cgrp->subsys[i]->cgroup != cgrp); 1069 BUG_ON(cgrp->subsys[i]->cgroup != cgrp);
1067 1070
1068 if (ss->bind) 1071 if (ss->bind)
1069 ss->bind(cgroup_dummy_top); 1072 ss->bind(cgroup_dummy_top->subsys[i]);
1070 cgroup_dummy_top->subsys[i]->cgroup = cgroup_dummy_top; 1073 cgroup_dummy_top->subsys[i]->cgroup = cgroup_dummy_top;
1071 cgrp->subsys[i] = NULL; 1074 cgrp->subsys[i] = NULL;
1072 cgroup_subsys[i]->root = &cgroup_dummy_root; 1075 cgroup_subsys[i]->root = &cgroup_dummy_root;
@@ -2049,8 +2052,10 @@ static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk,
2049 * step 1: check that we can legitimately attach to the cgroup. 2052 * step 1: check that we can legitimately attach to the cgroup.
2050 */ 2053 */
2051 for_each_root_subsys(root, ss) { 2054 for_each_root_subsys(root, ss) {
2055 struct cgroup_subsys_state *css = cgrp->subsys[ss->subsys_id];
2056
2052 if (ss->can_attach) { 2057 if (ss->can_attach) {
2053 retval = ss->can_attach(cgrp, &tset); 2058 retval = ss->can_attach(css, &tset);
2054 if (retval) { 2059 if (retval) {
2055 failed_ss = ss; 2060 failed_ss = ss;
2056 goto out_cancel_attach; 2061 goto out_cancel_attach;
@@ -2089,8 +2094,10 @@ static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk,
2089 * step 4: do subsystem attach callbacks. 2094 * step 4: do subsystem attach callbacks.
2090 */ 2095 */
2091 for_each_root_subsys(root, ss) { 2096 for_each_root_subsys(root, ss) {
2097 struct cgroup_subsys_state *css = cgrp->subsys[ss->subsys_id];
2098
2092 if (ss->attach) 2099 if (ss->attach)
2093 ss->attach(cgrp, &tset); 2100 ss->attach(css, &tset);
2094 } 2101 }
2095 2102
2096 /* 2103 /*
@@ -2109,10 +2116,12 @@ out_put_css_set_refs:
2109out_cancel_attach: 2116out_cancel_attach:
2110 if (retval) { 2117 if (retval) {
2111 for_each_root_subsys(root, ss) { 2118 for_each_root_subsys(root, ss) {
2119 struct cgroup_subsys_state *css = cgrp->subsys[ss->subsys_id];
2120
2112 if (ss == failed_ss) 2121 if (ss == failed_ss)
2113 break; 2122 break;
2114 if (ss->cancel_attach) 2123 if (ss->cancel_attach)
2115 ss->cancel_attach(cgrp, &tset); 2124 ss->cancel_attach(css, &tset);
2116 } 2125 }
2117 } 2126 }
2118out_free_group_list: 2127out_free_group_list:
@@ -4206,14 +4215,15 @@ static void init_cgroup_css(struct cgroup_subsys_state *css,
4206/* invoke ->css_online() on a new CSS and mark it online if successful */ 4215/* invoke ->css_online() on a new CSS and mark it online if successful */
4207static int online_css(struct cgroup_subsys *ss, struct cgroup *cgrp) 4216static int online_css(struct cgroup_subsys *ss, struct cgroup *cgrp)
4208{ 4217{
4218 struct cgroup_subsys_state *css = cgrp->subsys[ss->subsys_id];
4209 int ret = 0; 4219 int ret = 0;
4210 4220
4211 lockdep_assert_held(&cgroup_mutex); 4221 lockdep_assert_held(&cgroup_mutex);
4212 4222
4213 if (ss->css_online) 4223 if (ss->css_online)
4214 ret = ss->css_online(cgrp); 4224 ret = ss->css_online(css);
4215 if (!ret) 4225 if (!ret)
4216 cgrp->subsys[ss->subsys_id]->flags |= CSS_ONLINE; 4226 css->flags |= CSS_ONLINE;
4217 return ret; 4227 return ret;
4218} 4228}
4219 4229
@@ -4228,9 +4238,9 @@ static void offline_css(struct cgroup_subsys *ss, struct cgroup *cgrp)
4228 return; 4238 return;
4229 4239
4230 if (ss->css_offline) 4240 if (ss->css_offline)
4231 ss->css_offline(cgrp); 4241 ss->css_offline(css);
4232 4242
4233 cgrp->subsys[ss->subsys_id]->flags &= ~CSS_ONLINE; 4243 css->flags &= ~CSS_ONLINE;
4234} 4244}
4235 4245
4236/* 4246/*
@@ -4305,7 +4315,7 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
4305 for_each_root_subsys(root, ss) { 4315 for_each_root_subsys(root, ss) {
4306 struct cgroup_subsys_state *css; 4316 struct cgroup_subsys_state *css;
4307 4317
4308 css = ss->css_alloc(cgrp); 4318 css = ss->css_alloc(parent->subsys[ss->subsys_id]);
4309 if (IS_ERR(css)) { 4319 if (IS_ERR(css)) {
4310 err = PTR_ERR(css); 4320 err = PTR_ERR(css);
4311 goto err_free_all; 4321 goto err_free_all;
@@ -4313,7 +4323,7 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
4313 4323
4314 err = percpu_ref_init(&css->refcnt, css_release); 4324 err = percpu_ref_init(&css->refcnt, css_release);
4315 if (err) { 4325 if (err) {
4316 ss->css_free(cgrp); 4326 ss->css_free(css);
4317 goto err_free_all; 4327 goto err_free_all;
4318 } 4328 }
4319 4329
@@ -4386,7 +4396,7 @@ err_free_all:
4386 4396
4387 if (css) { 4397 if (css) {
4388 percpu_ref_cancel_init(&css->refcnt); 4398 percpu_ref_cancel_init(&css->refcnt);
4389 ss->css_free(cgrp); 4399 ss->css_free(css);
4390 } 4400 }
4391 } 4401 }
4392 mutex_unlock(&cgroup_mutex); 4402 mutex_unlock(&cgroup_mutex);
@@ -4641,7 +4651,7 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
4641 /* Create the top cgroup state for this subsystem */ 4651 /* Create the top cgroup state for this subsystem */
4642 list_add(&ss->sibling, &cgroup_dummy_root.subsys_list); 4652 list_add(&ss->sibling, &cgroup_dummy_root.subsys_list);
4643 ss->root = &cgroup_dummy_root; 4653 ss->root = &cgroup_dummy_root;
4644 css = ss->css_alloc(cgroup_dummy_top); 4654 css = ss->css_alloc(cgroup_dummy_top->subsys[ss->subsys_id]);
4645 /* We don't handle early failures gracefully */ 4655 /* We don't handle early failures gracefully */
4646 BUG_ON(IS_ERR(css)); 4656 BUG_ON(IS_ERR(css));
4647 init_cgroup_css(css, ss, cgroup_dummy_top); 4657 init_cgroup_css(css, ss, cgroup_dummy_top);
@@ -4720,7 +4730,7 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
4720 * struct, so this can happen first (i.e. before the dummy root 4730 * struct, so this can happen first (i.e. before the dummy root
4721 * attachment). 4731 * attachment).
4722 */ 4732 */
4723 css = ss->css_alloc(cgroup_dummy_top); 4733 css = ss->css_alloc(cgroup_dummy_top->subsys[ss->subsys_id]);
4724 if (IS_ERR(css)) { 4734 if (IS_ERR(css)) {
4725 /* failure case - need to deassign the cgroup_subsys[] slot. */ 4735 /* failure case - need to deassign the cgroup_subsys[] slot. */
4726 cgroup_subsys[ss->subsys_id] = NULL; 4736 cgroup_subsys[ss->subsys_id] = NULL;
@@ -4836,7 +4846,7 @@ void cgroup_unload_subsys(struct cgroup_subsys *ss)
4836 * the cgrp->subsys pointer to find their state. note that this 4846 * the cgrp->subsys pointer to find their state. note that this
4837 * also takes care of freeing the css_id. 4847 * also takes care of freeing the css_id.
4838 */ 4848 */
4839 ss->css_free(cgroup_dummy_top); 4849 ss->css_free(cgroup_dummy_top->subsys[ss->subsys_id]);
4840 cgroup_dummy_top->subsys[ss->subsys_id] = NULL; 4850 cgroup_dummy_top->subsys[ss->subsys_id] = NULL;
4841 4851
4842 mutex_unlock(&cgroup_mutex); 4852 mutex_unlock(&cgroup_mutex);
@@ -5192,10 +5202,10 @@ void cgroup_exit(struct task_struct *tsk, int run_callbacks)
5192 */ 5202 */
5193 for_each_builtin_subsys(ss, i) { 5203 for_each_builtin_subsys(ss, i) {
5194 if (ss->exit) { 5204 if (ss->exit) {
5195 struct cgroup *old_cgrp = cset->subsys[i]->cgroup; 5205 struct cgroup_subsys_state *old_css = cset->subsys[i];
5196 struct cgroup *cgrp = task_cgroup(tsk, i); 5206 struct cgroup_subsys_state *css = task_css(tsk, i);
5197 5207
5198 ss->exit(cgrp, old_cgrp, tsk); 5208 ss->exit(css, old_css, tsk);
5199 } 5209 }
5200 } 5210 }
5201 } 5211 }
@@ -5529,7 +5539,8 @@ struct cgroup_subsys_state *cgroup_css_from_dir(struct file *f, int id)
5529} 5539}
5530 5540
5531#ifdef CONFIG_CGROUP_DEBUG 5541#ifdef CONFIG_CGROUP_DEBUG
5532static struct cgroup_subsys_state *debug_css_alloc(struct cgroup *cgrp) 5542static struct cgroup_subsys_state *
5543debug_css_alloc(struct cgroup_subsys_state *parent_css)
5533{ 5544{
5534 struct cgroup_subsys_state *css = kzalloc(sizeof(*css), GFP_KERNEL); 5545 struct cgroup_subsys_state *css = kzalloc(sizeof(*css), GFP_KERNEL);
5535 5546
@@ -5539,9 +5550,9 @@ static struct cgroup_subsys_state *debug_css_alloc(struct cgroup *cgrp)
5539 return css; 5550 return css;
5540} 5551}
5541 5552
5542static void debug_css_free(struct cgroup *cgrp) 5553static void debug_css_free(struct cgroup_subsys_state *css)
5543{ 5554{
5544 kfree(cgrp->subsys[debug_subsys_id]); 5555 kfree(css);
5545} 5556}
5546 5557
5547static u64 debug_taskcount_read(struct cgroup *cgrp, struct cftype *cft) 5558static u64 debug_taskcount_read(struct cgroup *cgrp, struct cftype *cft)