On 3.11-rc we are seeing cgroup directories left behind when they should have been removed. Here's a trivial reproducer:
cd /sys/fs/cgroup/memory mkdir parent parent/child; rmdir parent/child parent rmdir: failed to remove `parent': Device or resource busy It's because cgroup_destroy_locked() (step 1 of destruction) leaves cgroup on parent's children list, letting cgroup_offline_fn() (step 2 of destruction) remove it; but step 2 is run by work queue, which may not yet have removed the children when parent destruction checks the list. Fix that by checking through a non-empty list of children: if every one of them has already been marked CGRP_DEAD, then it's safe to proceed: those children are invisible to userspace, and should not obstruct rmdir. (I didn't see any reason to keep the cgrp->children checks under the unrelated css_set_lock, so moved them out.) Signed-off-by: Hugh Dickins <hu...@google.com> --- kernel/cgroup.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) --- 3.11-rc7/kernel/cgroup.c 2013-08-11 23:38:33.096579188 -0700 +++ linux/kernel/cgroup.c 2013-08-28 15:44:06.952564071 -0700 @@ -4490,8 +4490,23 @@ static int cgroup_destroy_locked(struct * @cgrp from being removed while __put_css_set() is in progress. */ read_lock(&css_set_lock); - empty = list_empty(&cgrp->cset_links) && list_empty(&cgrp->children); + empty = list_empty(&cgrp->cset_links); read_unlock(&css_set_lock); + + if (empty && !list_empty(&cgrp->children)) { + struct cgroup *child; + /* + * We need "rmdir parent/child parent" to succeed, + * but our children may not have reached step 2 yet. + */ + rcu_read_lock(); + list_for_each_entry_rcu(child, &cgrp->children, sibling) { + empty = cgroup_is_dead(child); + if (!empty) + break; + } + rcu_read_unlock(); + } if (!empty) return -EBUSY; -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/