diff options
| author | Tejun Heo <tj@kernel.org> | 2013-06-13 22:27:41 -0400 |
|---|---|---|
| committer | Tejun Heo <tj@kernel.org> | 2013-06-13 22:27:41 -0400 |
| commit | 455050d23e1bfc47ca98e943ad5b2f3a9bbe45fb (patch) | |
| tree | 690eb75fb11a1869aa5092fe29bb61be0a641fd8 /kernel | |
| parent | 6f3d828f0fb7fdaffc6f32cb8a1cb7fcf8824598 (diff) | |
cgroup: reorder the operations in cgroup_destroy_locked()
This patch reorders the operations in cgroup_destroy_locked() such
that the userland visible parts happen before css offlining and
removal from the ->sibling list. This will be used to make css use
percpu refcnt.
While at it, split out CGRP_DEAD related comment from the refcnt
deactivation one and correct / clarify how different guarantees are
met.
While this patch changes the specific order of operations, it
shouldn't cause any noticeable behavior difference.
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 | 61 |
1 files changed, 35 insertions, 26 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 49bfd7b0bbda..5a1ddecc3cfa 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
| @@ -4379,13 +4379,8 @@ static int cgroup_destroy_locked(struct cgroup *cgrp) | |||
| 4379 | 4379 | ||
| 4380 | /* | 4380 | /* |
| 4381 | * Block new css_tryget() by deactivating refcnt and mark @cgrp | 4381 | * Block new css_tryget() by deactivating refcnt and mark @cgrp |
| 4382 | * removed. This makes future css_tryget() and child creation | 4382 | * removed. This makes future css_tryget() attempts fail which we |
| 4383 | * attempts fail thus maintaining the removal conditions verified | 4383 | * guarantee to ->css_offline() callbacks. |
| 4384 | * above. | ||
| 4385 | * | ||
| 4386 | * Note that CGRP_DEAD assertion is depended upon by | ||
| 4387 | * cgroup_next_sibling() to resume iteration after dropping RCU | ||
| 4388 | * read lock. See cgroup_next_sibling() for details. | ||
| 4389 | */ | 4384 | */ |
| 4390 | for_each_subsys(cgrp->root, ss) { | 4385 | for_each_subsys(cgrp->root, ss) { |
| 4391 | struct cgroup_subsys_state *css = cgrp->subsys[ss->subsys_id]; | 4386 | struct cgroup_subsys_state *css = cgrp->subsys[ss->subsys_id]; |
| @@ -4393,8 +4388,41 @@ static int cgroup_destroy_locked(struct cgroup *cgrp) | |||
| 4393 | WARN_ON(atomic_read(&css->refcnt) < 0); | 4388 | WARN_ON(atomic_read(&css->refcnt) < 0); |
| 4394 | atomic_add(CSS_DEACT_BIAS, &css->refcnt); | 4389 | atomic_add(CSS_DEACT_BIAS, &css->refcnt); |
| 4395 | } | 4390 | } |
| 4391 | |||
| 4392 | /* | ||
| 4393 | * Mark @cgrp dead. This prevents further task migration and child | ||
| 4394 | * creation by disabling cgroup_lock_live_group(). Note that | ||
| 4395 | * CGRP_DEAD assertion is depended upon by cgroup_next_sibling() to | ||
| 4396 | * resume iteration after dropping RCU read lock. See | ||
| 4397 | * cgroup_next_sibling() for details. | ||
| 4398 | */ | ||
| 4396 | set_bit(CGRP_DEAD, &cgrp->flags); | 4399 | set_bit(CGRP_DEAD, &cgrp->flags); |
| 4397 | 4400 | ||
| 4401 | /* CGRP_DEAD is set, remove from ->release_list for the last time */ | ||
| 4402 | raw_spin_lock(&release_list_lock); | ||
| 4403 | if (!list_empty(&cgrp->release_list)) | ||
| 4404 | list_del_init(&cgrp->release_list); | ||
| 4405 | raw_spin_unlock(&release_list_lock); | ||
| 4406 | |||
| 4407 | /* | ||
| 4408 | * Remove @cgrp directory. The removal puts the base ref but we | ||
| 4409 | * aren't quite done with @cgrp yet, so hold onto it. | ||
| 4410 | */ | ||
| 4411 | dget(d); | ||
| 4412 | cgroup_d_remove_dir(d); | ||
| 4413 | |||
| 4414 | /* | ||
| 4415 | * Unregister events and notify userspace. | ||
| 4416 | * Notify userspace about cgroup removing only after rmdir of cgroup | ||
| 4417 | * directory to avoid race between userspace and kernelspace. | ||
| 4418 | */ | ||
| 4419 | spin_lock(&cgrp->event_list_lock); | ||
| 4420 | list_for_each_entry_safe(event, tmp, &cgrp->event_list, list) { | ||
| 4421 | list_del_init(&event->list); | ||
| 4422 | schedule_work(&event->remove); | ||
| 4423 | } | ||
| 4424 | spin_unlock(&cgrp->event_list_lock); | ||
| 4425 | |||
| 4398 | /* tell subsystems to initate destruction */ | 4426 | /* tell subsystems to initate destruction */ |
| 4399 | for_each_subsys(cgrp->root, ss) | 4427 | for_each_subsys(cgrp->root, ss) |
| 4400 | offline_css(ss, cgrp); | 4428 | offline_css(ss, cgrp); |
| @@ -4409,34 +4437,15 @@ static int cgroup_destroy_locked(struct cgroup *cgrp) | |||
| 4409 | for_each_subsys(cgrp->root, ss) | 4437 | for_each_subsys(cgrp->root, ss) |
| 4410 | css_put(cgrp->subsys[ss->subsys_id]); | 4438 | css_put(cgrp->subsys[ss->subsys_id]); |
| 4411 | 4439 | ||
| 4412 | raw_spin_lock(&release_list_lock); | ||
| 4413 | if (!list_empty(&cgrp->release_list)) | ||
| 4414 | list_del_init(&cgrp->release_list); | ||
| 4415 | raw_spin_unlock(&release_list_lock); | ||
| 4416 | |||
| 4417 | /* delete this cgroup from parent->children */ | 4440 | /* delete this cgroup from parent->children */ |
| 4418 | list_del_rcu(&cgrp->sibling); | 4441 | list_del_rcu(&cgrp->sibling); |
| 4419 | list_del_init(&cgrp->allcg_node); | 4442 | list_del_init(&cgrp->allcg_node); |
| 4420 | 4443 | ||
| 4421 | dget(d); | ||
| 4422 | cgroup_d_remove_dir(d); | ||
| 4423 | dput(d); | 4444 | dput(d); |
| 4424 | 4445 | ||
| 4425 | set_bit(CGRP_RELEASABLE, &parent->flags); | 4446 | set_bit(CGRP_RELEASABLE, &parent->flags); |
| 4426 | check_for_release(parent); | 4447 | check_for_release(parent); |
| 4427 | 4448 | ||
| 4428 | /* | ||
| 4429 | * Unregister events and notify userspace. | ||
| 4430 | * Notify userspace about cgroup removing only after rmdir of cgroup | ||
| 4431 | * directory to avoid race between userspace and kernelspace. | ||
| 4432 | */ | ||
| 4433 | spin_lock(&cgrp->event_list_lock); | ||
| 4434 | list_for_each_entry_safe(event, tmp, &cgrp->event_list, list) { | ||
| 4435 | list_del_init(&event->list); | ||
| 4436 | schedule_work(&event->remove); | ||
| 4437 | } | ||
| 4438 | spin_unlock(&cgrp->event_list_lock); | ||
| 4439 | |||
| 4440 | return 0; | 4449 | return 0; |
| 4441 | } | 4450 | } |
| 4442 | 4451 | ||
