diff options
author | Tejun Heo <tj@kernel.org> | 2012-11-19 11:13:38 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2012-11-19 11:13:38 -0500 |
commit | b1929db42f8a649d9a9e397119f628c27fd4021f (patch) | |
tree | 04c0fa6f056395f8d17b5cd918403547be3f1425 | |
parent | 4b8b47eb0001a89f271d671d959b235faa8f03e2 (diff) |
cgroup: allow ->post_create() to fail
There could be cases where controllers want to do initialization
operations which may fail from ->post_create(). This patch makes
->post_create() return -errno to indicate failure and online_css()
relay such failures.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Li Zefan <lizefan@huawei.com>
Cc: Glauber Costa <glommer@parallels.com>
-rw-r--r-- | include/linux/cgroup.h | 2 | ||||
-rw-r--r-- | kernel/cgroup.c | 29 | ||||
-rw-r--r-- | kernel/cgroup_freezer.c | 4 |
3 files changed, 23 insertions, 12 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index f4a9c9836906..03d8a92786da 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h | |||
@@ -440,7 +440,7 @@ int cgroup_taskset_size(struct cgroup_taskset *tset); | |||
440 | 440 | ||
441 | struct cgroup_subsys { | 441 | struct cgroup_subsys { |
442 | struct cgroup_subsys_state *(*create)(struct cgroup *cgrp); | 442 | struct cgroup_subsys_state *(*create)(struct cgroup *cgrp); |
443 | void (*post_create)(struct cgroup *cgrp); | 443 | int (*post_create)(struct cgroup *cgrp); |
444 | void (*pre_destroy)(struct cgroup *cgrp); | 444 | void (*pre_destroy)(struct cgroup *cgrp); |
445 | void (*destroy)(struct cgroup *cgrp); | 445 | void (*destroy)(struct cgroup *cgrp); |
446 | int (*can_attach)(struct cgroup *cgrp, struct cgroup_taskset *tset); | 446 | int (*can_attach)(struct cgroup *cgrp, struct cgroup_taskset *tset); |
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 027b66e66698..c389f4258681 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -4041,14 +4041,18 @@ static void init_cgroup_css(struct cgroup_subsys_state *css, | |||
4041 | INIT_WORK(&css->dput_work, css_dput_fn); | 4041 | INIT_WORK(&css->dput_work, css_dput_fn); |
4042 | } | 4042 | } |
4043 | 4043 | ||
4044 | /* invoke ->post_create() on a new CSS and mark it online */ | 4044 | /* invoke ->post_create() on a new CSS and mark it online if successful */ |
4045 | static void online_css(struct cgroup_subsys *ss, struct cgroup *cgrp) | 4045 | static int online_css(struct cgroup_subsys *ss, struct cgroup *cgrp) |
4046 | { | 4046 | { |
4047 | int ret = 0; | ||
4048 | |||
4047 | lockdep_assert_held(&cgroup_mutex); | 4049 | lockdep_assert_held(&cgroup_mutex); |
4048 | 4050 | ||
4049 | if (ss->post_create) | 4051 | if (ss->post_create) |
4050 | ss->post_create(cgrp); | 4052 | ret = ss->post_create(cgrp); |
4051 | cgrp->subsys[ss->subsys_id]->flags |= CSS_ONLINE; | 4053 | if (!ret) |
4054 | cgrp->subsys[ss->subsys_id]->flags |= CSS_ONLINE; | ||
4055 | return ret; | ||
4052 | } | 4056 | } |
4053 | 4057 | ||
4054 | /* if the CSS is online, invoke ->pre_destory() on it and mark it offline */ | 4058 | /* if the CSS is online, invoke ->pre_destory() on it and mark it offline */ |
@@ -4174,12 +4178,15 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, | |||
4174 | list_add_tail_rcu(&cgrp->sibling, &cgrp->parent->children); | 4178 | list_add_tail_rcu(&cgrp->sibling, &cgrp->parent->children); |
4175 | root->number_of_cgroups++; | 4179 | root->number_of_cgroups++; |
4176 | 4180 | ||
4177 | for_each_subsys(root, ss) { | 4181 | /* each css holds a ref to the cgroup's dentry */ |
4178 | /* each css holds a ref to the cgroup's dentry */ | 4182 | for_each_subsys(root, ss) |
4179 | dget(dentry); | 4183 | dget(dentry); |
4180 | 4184 | ||
4181 | /* creation succeeded, notify subsystems */ | 4185 | /* creation succeeded, notify subsystems */ |
4182 | online_css(ss, cgrp); | 4186 | for_each_subsys(root, ss) { |
4187 | err = online_css(ss, cgrp); | ||
4188 | if (err) | ||
4189 | goto err_destroy; | ||
4183 | } | 4190 | } |
4184 | 4191 | ||
4185 | err = cgroup_populate_dir(cgrp, true, root->subsys_mask); | 4192 | err = cgroup_populate_dir(cgrp, true, root->subsys_mask); |
@@ -4393,7 +4400,7 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss) | |||
4393 | BUG_ON(!list_empty(&init_task.tasks)); | 4400 | BUG_ON(!list_empty(&init_task.tasks)); |
4394 | 4401 | ||
4395 | ss->active = 1; | 4402 | ss->active = 1; |
4396 | online_css(ss, dummytop); | 4403 | BUG_ON(online_css(ss, dummytop)); |
4397 | 4404 | ||
4398 | mutex_unlock(&cgroup_mutex); | 4405 | mutex_unlock(&cgroup_mutex); |
4399 | 4406 | ||
@@ -4500,7 +4507,9 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss) | |||
4500 | write_unlock(&css_set_lock); | 4507 | write_unlock(&css_set_lock); |
4501 | 4508 | ||
4502 | ss->active = 1; | 4509 | ss->active = 1; |
4503 | online_css(ss, dummytop); | 4510 | ret = online_css(ss, dummytop); |
4511 | if (ret) | ||
4512 | goto err_unload; | ||
4504 | 4513 | ||
4505 | /* success! */ | 4514 | /* success! */ |
4506 | mutex_unlock(&cgroup_mutex); | 4515 | mutex_unlock(&cgroup_mutex); |
diff --git a/kernel/cgroup_freezer.c b/kernel/cgroup_freezer.c index 670a4af7dc94..ee8bb671688c 100644 --- a/kernel/cgroup_freezer.c +++ b/kernel/cgroup_freezer.c | |||
@@ -112,7 +112,7 @@ static struct cgroup_subsys_state *freezer_create(struct cgroup *cgroup) | |||
112 | * parent's freezing state while holding both parent's and our | 112 | * parent's freezing state while holding both parent's and our |
113 | * freezer->lock. | 113 | * freezer->lock. |
114 | */ | 114 | */ |
115 | static void freezer_post_create(struct cgroup *cgroup) | 115 | static int freezer_post_create(struct cgroup *cgroup) |
116 | { | 116 | { |
117 | struct freezer *freezer = cgroup_freezer(cgroup); | 117 | struct freezer *freezer = cgroup_freezer(cgroup); |
118 | struct freezer *parent = parent_freezer(freezer); | 118 | struct freezer *parent = parent_freezer(freezer); |
@@ -136,6 +136,8 @@ static void freezer_post_create(struct cgroup *cgroup) | |||
136 | spin_unlock(&freezer->lock); | 136 | spin_unlock(&freezer->lock); |
137 | if (parent) | 137 | if (parent) |
138 | spin_unlock_irq(&parent->lock); | 138 | spin_unlock_irq(&parent->lock); |
139 | |||
140 | return 0; | ||
139 | } | 141 | } |
140 | 142 | ||
141 | /** | 143 | /** |