diff options
author | Tejun Heo <tj@kernel.org> | 2012-11-19 11:13:37 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2012-11-19 11:13:37 -0500 |
commit | 02ae7486d05ae6df8395409a4945b2420f1e35c2 (patch) | |
tree | 18d3f09250a850d9d6dfe3f62dfe13f4f6353374 | |
parent | 648bb56d076bde31113f09a7d24d95bc8d4155ac (diff) |
cgroup: fix harmless bugs in cgroup_load_subsys() fail path and cgroup_unload_subsys()
* If idr init fails, cgroup_load_subsys() cleared dummytop->subsys[]
before calilng ->destroy() making CSS inaccessible to the callback,
and didn't unlink ss->sibling. As no modular controller uses
->use_id, this doesn't cause any actual problems.
* cgroup_unload_subsys() was forgetting to free idr, call
->pre_destroy() and clear ->active. As there currently is no
modular controller which uses ->use_id, ->pre_destroy() or ->active,
this doesn't cause any actual problems.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Li Zefan <lizefan@huawei.com>
-rw-r--r-- | kernel/cgroup.c | 15 |
1 files changed, 14 insertions, 1 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 09751657abdc..5679cb1ce43f 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -4420,9 +4420,10 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss) | |||
4420 | if (ss->use_id) { | 4420 | if (ss->use_id) { |
4421 | int ret = cgroup_init_idr(ss, css); | 4421 | int ret = cgroup_init_idr(ss, css); |
4422 | if (ret) { | 4422 | if (ret) { |
4423 | dummytop->subsys[ss->subsys_id] = NULL; | ||
4424 | ss->destroy(dummytop); | 4423 | ss->destroy(dummytop); |
4424 | dummytop->subsys[ss->subsys_id] = NULL; | ||
4425 | subsys[ss->subsys_id] = NULL; | 4425 | subsys[ss->subsys_id] = NULL; |
4426 | list_del_init(&ss->sibling); | ||
4426 | mutex_unlock(&cgroup_mutex); | 4427 | mutex_unlock(&cgroup_mutex); |
4427 | return ret; | 4428 | return ret; |
4428 | } | 4429 | } |
@@ -4490,7 +4491,19 @@ void cgroup_unload_subsys(struct cgroup_subsys *ss) | |||
4490 | */ | 4491 | */ |
4491 | BUG_ON(ss->root != &rootnode); | 4492 | BUG_ON(ss->root != &rootnode); |
4492 | 4493 | ||
4494 | /* ->pre_destroy() should be called outside cgroup_mutex for now */ | ||
4495 | if (ss->pre_destroy) | ||
4496 | ss->pre_destroy(dummytop); | ||
4497 | |||
4493 | mutex_lock(&cgroup_mutex); | 4498 | mutex_lock(&cgroup_mutex); |
4499 | |||
4500 | ss->active = 0; | ||
4501 | |||
4502 | if (ss->use_id) { | ||
4503 | idr_remove_all(&ss->idr); | ||
4504 | idr_destroy(&ss->idr); | ||
4505 | } | ||
4506 | |||
4494 | /* deassign the subsys_id */ | 4507 | /* deassign the subsys_id */ |
4495 | subsys[ss->subsys_id] = NULL; | 4508 | subsys[ss->subsys_id] = NULL; |
4496 | 4509 | ||