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 | a31f2d3ff7fe20cbe2a143515a7d7c408b29dd0d (patch) | |
| tree | fd9e909ad92609eb189d406c4812325788d25bbc /kernel | |
| parent | 42809dd4225b2f3127a4804314a1b33608620d96 (diff) | |
cgroup: introduce CSS_ONLINE flag and on/offline_css() helpers
New helpers on/offline_css() respectively wrap ->post_create() and
->pre_destroy() invocations. online_css() sets CSS_ONLINE after
->post_create() is complete and offline_css() invokes ->pre_destroy()
iff CSS_ONLINE is set and clears it while also handling the temporary
dropping of cgroup_mutex.
This patch doesn't introduce any behavior change at the moment but
will be used to improve cgroup_create() failure path and allow
->post_create() to fail.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Li Zefan <lizefan@huawei.com>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/cgroup.c | 65 |
1 files changed, 42 insertions, 23 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 4412d9694f1..78a3d5c0968 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
| @@ -4035,6 +4035,42 @@ static void init_cgroup_css(struct cgroup_subsys_state *css, | |||
| 4035 | INIT_WORK(&css->dput_work, css_dput_fn); | 4035 | INIT_WORK(&css->dput_work, css_dput_fn); |
| 4036 | } | 4036 | } |
| 4037 | 4037 | ||
| 4038 | /* invoke ->post_create() on a new CSS and mark it online */ | ||
| 4039 | static void online_css(struct cgroup_subsys *ss, struct cgroup *cgrp) | ||
| 4040 | { | ||
| 4041 | lockdep_assert_held(&cgroup_mutex); | ||
| 4042 | |||
| 4043 | if (ss->post_create) | ||
| 4044 | ss->post_create(cgrp); | ||
| 4045 | cgrp->subsys[ss->subsys_id]->flags |= CSS_ONLINE; | ||
| 4046 | } | ||
| 4047 | |||
| 4048 | /* if the CSS is online, invoke ->pre_destory() on it and mark it offline */ | ||
| 4049 | static void offline_css(struct cgroup_subsys *ss, struct cgroup *cgrp) | ||
| 4050 | __releases(&cgroup_mutex) __acquires(&cgroup_mutex) | ||
| 4051 | { | ||
| 4052 | struct cgroup_subsys_state *css = cgrp->subsys[ss->subsys_id]; | ||
| 4053 | |||
| 4054 | lockdep_assert_held(&cgroup_mutex); | ||
| 4055 | |||
| 4056 | if (!(css->flags & CSS_ONLINE)) | ||
| 4057 | return; | ||
| 4058 | |||
| 4059 | /* | ||
| 4060 | * pre_destroy() should be called with cgroup_mutex unlocked. See | ||
| 4061 | * 3fa59dfbc3 ("cgroup: fix potential deadlock in pre_destroy") for | ||
| 4062 | * details. This temporary unlocking should go away once | ||
| 4063 | * cgroup_mutex is unexported from controllers. | ||
| 4064 | */ | ||
| 4065 | if (ss->pre_destroy) { | ||
| 4066 | mutex_unlock(&cgroup_mutex); | ||
| 4067 | ss->pre_destroy(cgrp); | ||
| 4068 | mutex_lock(&cgroup_mutex); | ||
| 4069 | } | ||
| 4070 | |||
| 4071 | cgrp->subsys[ss->subsys_id]->flags &= ~CSS_ONLINE; | ||
| 4072 | } | ||
| 4073 | |||
| 4038 | /* | 4074 | /* |
| 4039 | * cgroup_create - create a cgroup | 4075 | * cgroup_create - create a cgroup |
| 4040 | * @parent: cgroup that will be parent of the new cgroup | 4076 | * @parent: cgroup that will be parent of the new cgroup |
| @@ -4137,8 +4173,7 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, | |||
| 4137 | dget(dentry); | 4173 | dget(dentry); |
| 4138 | 4174 | ||
| 4139 | /* creation succeeded, notify subsystems */ | 4175 | /* creation succeeded, notify subsystems */ |
| 4140 | if (ss->post_create) | 4176 | online_css(ss, cgrp); |
| 4141 | ss->post_create(cgrp); | ||
| 4142 | } | 4177 | } |
| 4143 | 4178 | ||
| 4144 | err = cgroup_populate_dir(cgrp, true, root->subsys_mask); | 4179 | err = cgroup_populate_dir(cgrp, true, root->subsys_mask); |
| @@ -4240,18 +4275,9 @@ static int cgroup_destroy_locked(struct cgroup *cgrp) | |||
| 4240 | } | 4275 | } |
| 4241 | set_bit(CGRP_REMOVED, &cgrp->flags); | 4276 | set_bit(CGRP_REMOVED, &cgrp->flags); |
| 4242 | 4277 | ||
| 4243 | /* | 4278 | /* tell subsystems to initate destruction */ |
| 4244 | * Tell subsystems to initate destruction. pre_destroy() should be | ||
| 4245 | * called with cgroup_mutex unlocked. See 3fa59dfbc3 ("cgroup: fix | ||
| 4246 | * potential deadlock in pre_destroy") for details. This temporary | ||
| 4247 | * unlocking should go away once cgroup_mutex is unexported from | ||
| 4248 | * controllers. | ||
| 4249 | */ | ||
| 4250 | mutex_unlock(&cgroup_mutex); | ||
| 4251 | for_each_subsys(cgrp->root, ss) | 4279 | for_each_subsys(cgrp->root, ss) |
| 4252 | if (ss->pre_destroy) | 4280 | offline_css(ss, cgrp); |
| 4253 | ss->pre_destroy(cgrp); | ||
| 4254 | mutex_lock(&cgroup_mutex); | ||
| 4255 | 4281 | ||
| 4256 | /* | 4282 | /* |
| 4257 | * Put all the base refs. Each css holds an extra reference to the | 4283 | * Put all the base refs. Each css holds an extra reference to the |
| @@ -4354,9 +4380,7 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss) | |||
| 4354 | BUG_ON(!list_empty(&init_task.tasks)); | 4380 | BUG_ON(!list_empty(&init_task.tasks)); |
| 4355 | 4381 | ||
| 4356 | ss->active = 1; | 4382 | ss->active = 1; |
| 4357 | 4383 | online_css(ss, dummytop); | |
| 4358 | if (ss->post_create) | ||
| 4359 | ss->post_create(dummytop); | ||
| 4360 | 4384 | ||
| 4361 | mutex_unlock(&cgroup_mutex); | 4385 | mutex_unlock(&cgroup_mutex); |
| 4362 | 4386 | ||
| @@ -4469,9 +4493,7 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss) | |||
| 4469 | write_unlock(&css_set_lock); | 4493 | write_unlock(&css_set_lock); |
| 4470 | 4494 | ||
| 4471 | ss->active = 1; | 4495 | ss->active = 1; |
| 4472 | 4496 | online_css(ss, dummytop); | |
| 4473 | if (ss->post_create) | ||
| 4474 | ss->post_create(dummytop); | ||
| 4475 | 4497 | ||
| 4476 | /* success! */ | 4498 | /* success! */ |
| 4477 | mutex_unlock(&cgroup_mutex); | 4499 | mutex_unlock(&cgroup_mutex); |
| @@ -4501,12 +4523,9 @@ void cgroup_unload_subsys(struct cgroup_subsys *ss) | |||
| 4501 | */ | 4523 | */ |
| 4502 | BUG_ON(ss->root != &rootnode); | 4524 | BUG_ON(ss->root != &rootnode); |
| 4503 | 4525 | ||
| 4504 | /* ->pre_destroy() should be called outside cgroup_mutex for now */ | ||
| 4505 | if (ss->pre_destroy) | ||
| 4506 | ss->pre_destroy(dummytop); | ||
| 4507 | |||
| 4508 | mutex_lock(&cgroup_mutex); | 4526 | mutex_lock(&cgroup_mutex); |
| 4509 | 4527 | ||
| 4528 | offline_css(ss, dummytop); | ||
| 4510 | ss->active = 0; | 4529 | ss->active = 0; |
| 4511 | 4530 | ||
| 4512 | if (ss->use_id) { | 4531 | if (ss->use_id) { |
