aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2012-11-19 11:13:38 -0500
committerTejun Heo <tj@kernel.org>2012-11-19 11:13:38 -0500
commitb1929db42f8a649d9a9e397119f628c27fd4021f (patch)
tree04c0fa6f056395f8d17b5cd918403547be3f1425
parent4b8b47eb0001a89f271d671d959b235faa8f03e2 (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.h2
-rw-r--r--kernel/cgroup.c29
-rw-r--r--kernel/cgroup_freezer.c4
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
441struct cgroup_subsys { 441struct 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 */
4045static void online_css(struct cgroup_subsys *ss, struct cgroup *cgrp) 4045static 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 */
115static void freezer_post_create(struct cgroup *cgroup) 115static 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/**