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>
This commit is contained in:
parent
6f3d828f0f
commit
455050d23e
1 changed files with 35 additions and 26 deletions
|
@ -4379,13 +4379,8 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
|
|||
|
||||
/*
|
||||
* Block new css_tryget() by deactivating refcnt and mark @cgrp
|
||||
* removed. This makes future css_tryget() and child creation
|
||||
* attempts fail thus maintaining the removal conditions verified
|
||||
* above.
|
||||
*
|
||||
* Note that CGRP_DEAD assertion is depended upon by
|
||||
* cgroup_next_sibling() to resume iteration after dropping RCU
|
||||
* read lock. See cgroup_next_sibling() for details.
|
||||
* removed. This makes future css_tryget() attempts fail which we
|
||||
* guarantee to ->css_offline() callbacks.
|
||||
*/
|
||||
for_each_subsys(cgrp->root, ss) {
|
||||
struct cgroup_subsys_state *css = cgrp->subsys[ss->subsys_id];
|
||||
|
@ -4393,8 +4388,41 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
|
|||
WARN_ON(atomic_read(&css->refcnt) < 0);
|
||||
atomic_add(CSS_DEACT_BIAS, &css->refcnt);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark @cgrp dead. This prevents further task migration and child
|
||||
* creation by disabling cgroup_lock_live_group(). Note that
|
||||
* CGRP_DEAD assertion is depended upon by cgroup_next_sibling() to
|
||||
* resume iteration after dropping RCU read lock. See
|
||||
* cgroup_next_sibling() for details.
|
||||
*/
|
||||
set_bit(CGRP_DEAD, &cgrp->flags);
|
||||
|
||||
/* CGRP_DEAD is set, remove from ->release_list for the last time */
|
||||
raw_spin_lock(&release_list_lock);
|
||||
if (!list_empty(&cgrp->release_list))
|
||||
list_del_init(&cgrp->release_list);
|
||||
raw_spin_unlock(&release_list_lock);
|
||||
|
||||
/*
|
||||
* Remove @cgrp directory. The removal puts the base ref but we
|
||||
* aren't quite done with @cgrp yet, so hold onto it.
|
||||
*/
|
||||
dget(d);
|
||||
cgroup_d_remove_dir(d);
|
||||
|
||||
/*
|
||||
* Unregister events and notify userspace.
|
||||
* Notify userspace about cgroup removing only after rmdir of cgroup
|
||||
* directory to avoid race between userspace and kernelspace.
|
||||
*/
|
||||
spin_lock(&cgrp->event_list_lock);
|
||||
list_for_each_entry_safe(event, tmp, &cgrp->event_list, list) {
|
||||
list_del_init(&event->list);
|
||||
schedule_work(&event->remove);
|
||||
}
|
||||
spin_unlock(&cgrp->event_list_lock);
|
||||
|
||||
/* tell subsystems to initate destruction */
|
||||
for_each_subsys(cgrp->root, ss)
|
||||
offline_css(ss, cgrp);
|
||||
|
@ -4409,34 +4437,15 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
|
|||
for_each_subsys(cgrp->root, ss)
|
||||
css_put(cgrp->subsys[ss->subsys_id]);
|
||||
|
||||
raw_spin_lock(&release_list_lock);
|
||||
if (!list_empty(&cgrp->release_list))
|
||||
list_del_init(&cgrp->release_list);
|
||||
raw_spin_unlock(&release_list_lock);
|
||||
|
||||
/* delete this cgroup from parent->children */
|
||||
list_del_rcu(&cgrp->sibling);
|
||||
list_del_init(&cgrp->allcg_node);
|
||||
|
||||
dget(d);
|
||||
cgroup_d_remove_dir(d);
|
||||
dput(d);
|
||||
|
||||
set_bit(CGRP_RELEASABLE, &parent->flags);
|
||||
check_for_release(parent);
|
||||
|
||||
/*
|
||||
* Unregister events and notify userspace.
|
||||
* Notify userspace about cgroup removing only after rmdir of cgroup
|
||||
* directory to avoid race between userspace and kernelspace.
|
||||
*/
|
||||
spin_lock(&cgrp->event_list_lock);
|
||||
list_for_each_entry_safe(event, tmp, &cgrp->event_list, list) {
|
||||
list_del_init(&event->list);
|
||||
schedule_work(&event->remove);
|
||||
}
|
||||
spin_unlock(&cgrp->event_list_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue