aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cgroup.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2012-11-19 11:13:37 -0500
committerTejun Heo <tj@kernel.org>2012-11-19 11:13:37 -0500
commitd19e19de48aa0b90c56cd93c8a46ebac46273429 (patch)
treeea485692e0b5a7fdfa6bf6a80558957e89b220c2 /kernel/cgroup.c
parenta31f2d3ff7fe20cbe2a143515a7d7c408b29dd0d (diff)
cgroup: simplify cgroup_load_subsys() failure path
Now that cgroup_unload_subsys() can tell whether the root css is online or not, we can safely call cgroup_unload_subsys() after idr init failure in cgroup_load_subsys(). Replace the manual unrolling and invoke cgroup_unload_subsys() on failure. This drops cgroup_mutex inbetween but should be safe as the subsystem will fail try_module_get() and thus can't be mounted inbetween. As this means that cgroup_unload_subsys() can be called before css_sets are rehashed, remove BUG_ON() on %NULL css_set->subsys[] from cgroup_unload_subsys(). Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Li Zefan <lizefan@huawei.com>
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r--kernel/cgroup.c21
1 files changed, 10 insertions, 11 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 78a3d5c0968e..166b5141f3d4 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -4400,8 +4400,8 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
4400 */ 4400 */
4401int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss) 4401int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
4402{ 4402{
4403 int i;
4404 struct cgroup_subsys_state *css; 4403 struct cgroup_subsys_state *css;
4404 int i, ret;
4405 4405
4406 /* check name and function validity */ 4406 /* check name and function validity */
4407 if (ss->name == NULL || strlen(ss->name) > MAX_CGROUP_TYPE_NAMELEN || 4407 if (ss->name == NULL || strlen(ss->name) > MAX_CGROUP_TYPE_NAMELEN ||
@@ -4452,15 +4452,9 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
4452 init_cgroup_css(css, ss, dummytop); 4452 init_cgroup_css(css, ss, dummytop);
4453 /* init_idr must be after init_cgroup_css because it sets css->id. */ 4453 /* init_idr must be after init_cgroup_css because it sets css->id. */
4454 if (ss->use_id) { 4454 if (ss->use_id) {
4455 int ret = cgroup_init_idr(ss, css); 4455 ret = cgroup_init_idr(ss, css);
4456 if (ret) { 4456 if (ret)
4457 ss->destroy(dummytop); 4457 goto err_unload;
4458 dummytop->subsys[ss->subsys_id] = NULL;
4459 subsys[ss->subsys_id] = NULL;
4460 list_del_init(&ss->sibling);
4461 mutex_unlock(&cgroup_mutex);
4462 return ret;
4463 }
4464 } 4458 }
4465 4459
4466 /* 4460 /*
@@ -4498,6 +4492,12 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
4498 /* success! */ 4492 /* success! */
4499 mutex_unlock(&cgroup_mutex); 4493 mutex_unlock(&cgroup_mutex);
4500 return 0; 4494 return 0;
4495
4496err_unload:
4497 mutex_unlock(&cgroup_mutex);
4498 /* @ss can't be mounted here as try_module_get() would fail */
4499 cgroup_unload_subsys(ss);
4500 return ret;
4501} 4501}
4502EXPORT_SYMBOL_GPL(cgroup_load_subsys); 4502EXPORT_SYMBOL_GPL(cgroup_load_subsys);
4503 4503
@@ -4548,7 +4548,6 @@ void cgroup_unload_subsys(struct cgroup_subsys *ss)
4548 struct css_set *cg = link->cg; 4548 struct css_set *cg = link->cg;
4549 4549
4550 hlist_del(&cg->hlist); 4550 hlist_del(&cg->hlist);
4551 BUG_ON(!cg->subsys[ss->subsys_id]);
4552 cg->subsys[ss->subsys_id] = NULL; 4551 cg->subsys[ss->subsys_id] = NULL;
4553 hhead = css_set_hash(cg->subsys); 4552 hhead = css_set_hash(cg->subsys);
4554 hlist_add_head(&cg->hlist, hhead); 4553 hlist_add_head(&cg->hlist, hhead);