diff options
| author | Milosz Tanski <milosz@adfin.com> | 2013-09-06 16:41:20 +0000 |
|---|---|---|
| committer | Milosz Tanski <milosz@adfin.com> | 2013-09-06 16:41:20 +0000 |
| commit | cd0a2df681ec2af45f50c555c2a39dc92a4dff71 (patch) | |
| tree | 35d2278a9494582025f3dac08feb2266adef6a4d /kernel/cgroup.c | |
| parent | c35455791c1131e7ccbf56ea6fbdd562401c2ce2 (diff) | |
| parent | 5a6f282a2052bb13171b53f03b34501cf72c33f1 (diff) | |
Merge tag 'fscache-fixes-for-ceph' into wip-fscache
Patches for Ceph FS-Cache support
Diffstat (limited to 'kernel/cgroup.c')
| -rw-r--r-- | kernel/cgroup.c | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 781845a013a..e91963302c0 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -4480,6 +4480,7 @@ static int cgroup_destroy_locked(struct cgroup *cgrp) struct dentry *d = cgrp->dentry; struct cgroup_event *event, *tmp; struct cgroup_subsys *ss; + struct cgroup *child; bool empty; lockdep_assert_held(&d->d_inode->i_mutex); @@ -4490,12 +4491,28 @@ static int cgroup_destroy_locked(struct cgroup *cgrp) * @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) return -EBUSY; /* + * Make sure there's no live children. We can't test ->children + * emptiness as dead children linger on it while being destroyed; + * otherwise, "rmdir parent/child parent" may fail with -EBUSY. + */ + empty = true; + 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; + + /* * Block new css_tryget() by killing css refcnts. cgroup core * guarantees that, by the time ->css_offline() is invoked, no new * css reference will be given out via css_tryget(). We can't |
