Skip to content

Commit

Permalink
cgroup: move check_for_release(parent) call to the end of cgroup_dest…
Browse files Browse the repository at this point in the history
…roy_locked()

Currently, check_for_release() on the parent of a destroyed cgroup is
invoked from cgroup_destroy_css_killed().  This is because this is
where the destroyed cgroup can be removed from the parent's children
list.  check_for_release() tests the emptiness of the list directly,
so invoking it before removing the cgroup from the list makes it think
that the parent still has children even when it no longer does.

This patch updates check_for_release() to use
cgroup_has_live_children() instead of directly testing ->children
emptiness and moves check_for_release(parent) earlier to the end of
cgroup_destroy_locked().  As cgroup_has_live_children() ignores
cgroups marked DEAD, check_for_release() functions correctly as long
as it's called after asserting DEAD.

This makes release notification slightly more timely and more
importantly enables further simplification of cgroup destruction path.

Signed-off-by: Tejun Heo <[email protected]>
Acked-by: Li Zefan <[email protected]>
  • Loading branch information
htejun committed May 14, 2014
1 parent cbc125e commit 9e4173e
Showing 1 changed file with 4 additions and 6 deletions.
10 changes: 4 additions & 6 deletions kernel/cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -4542,6 +4542,9 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
*/
kernfs_remove(cgrp->kn);

set_bit(CGRP_RELEASABLE, &cgrp->parent->flags);
check_for_release(cgrp->parent);

return 0;
};

Expand All @@ -4556,17 +4559,12 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
*/
static void cgroup_destroy_css_killed(struct cgroup *cgrp)
{
struct cgroup *parent = cgrp->parent;

lockdep_assert_held(&cgroup_mutex);

/* delete this cgroup from parent->children */
list_del_rcu(&cgrp->sibling);

cgroup_put(cgrp);

set_bit(CGRP_RELEASABLE, &parent->flags);
check_for_release(parent);
}

static int cgroup_rmdir(struct kernfs_node *kn)
Expand Down Expand Up @@ -5006,7 +5004,7 @@ void cgroup_exit(struct task_struct *tsk)
static void check_for_release(struct cgroup *cgrp)
{
if (cgroup_is_releasable(cgrp) &&
list_empty(&cgrp->cset_links) && list_empty(&cgrp->children)) {
list_empty(&cgrp->cset_links) && !cgroup_has_live_children(cgrp)) {
/*
* Control Group is currently removeable. If it's not
* already queued for a userspace notification, queue
Expand Down

0 comments on commit 9e4173e

Please sign in to comment.