aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-08-29 20:03:48 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-08-29 20:03:48 -0400
commit41615e811b3031728a003da077005e8dcf9d71cc (patch)
tree53a5418d5157e0e58580bda1dd422765baca6317
parentff497452636f4687e517964817b7e2bd99f4b44b (diff)
parentbb78a92f47696b2da49f2692b6a9fa56d07c444a (diff)
Merge branch 'for-3.11-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup
Pull cgroup fix from Tejun Heo: "During the percpu reference counting update which was merged during v3.11-rc1, the cgroup destruction path was updated so that a cgroup in the process of dying may linger on the children list, which was necessary as the cgroup should still be included in child/descendant iteration while percpu ref is being killed. Unfortunately, I forgot to update cgroup destruction path accordingly and cgroup destruction may fail spuriously with -EBUSY due to lingering dying children even when there's no live child left - e.g. "rmdir parent/child parent" will usually fail. This can be easily fixed by iterating through the children list to verify that there's no live child left. While this is very late in the release cycle, this bug is very visible to userland and I believe the fix is relatively safe. Thanks Hugh for spotting and providing fix for the issue" * 'for-3.11-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup: cgroup: fix rmdir EBUSY regression in 3.11
-rw-r--r--kernel/cgroup.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 781845a013ab..e91963302c0d 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -4480,6 +4480,7 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
4480 struct dentry *d = cgrp->dentry; 4480 struct dentry *d = cgrp->dentry;
4481 struct cgroup_event *event, *tmp; 4481 struct cgroup_event *event, *tmp;
4482 struct cgroup_subsys *ss; 4482 struct cgroup_subsys *ss;
4483 struct cgroup *child;
4483 bool empty; 4484 bool empty;
4484 4485
4485 lockdep_assert_held(&d->d_inode->i_mutex); 4486 lockdep_assert_held(&d->d_inode->i_mutex);
@@ -4490,12 +4491,28 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
4490 * @cgrp from being removed while __put_css_set() is in progress. 4491 * @cgrp from being removed while __put_css_set() is in progress.
4491 */ 4492 */
4492 read_lock(&css_set_lock); 4493 read_lock(&css_set_lock);
4493 empty = list_empty(&cgrp->cset_links) && list_empty(&cgrp->children); 4494 empty = list_empty(&cgrp->cset_links);
4494 read_unlock(&css_set_lock); 4495 read_unlock(&css_set_lock);
4495 if (!empty) 4496 if (!empty)
4496 return -EBUSY; 4497 return -EBUSY;
4497 4498
4498 /* 4499 /*
4500 * Make sure there's no live children. We can't test ->children
4501 * emptiness as dead children linger on it while being destroyed;
4502 * otherwise, "rmdir parent/child parent" may fail with -EBUSY.
4503 */
4504 empty = true;
4505 rcu_read_lock();
4506 list_for_each_entry_rcu(child, &cgrp->children, sibling) {
4507 empty = cgroup_is_dead(child);
4508 if (!empty)
4509 break;
4510 }
4511 rcu_read_unlock();
4512 if (!empty)
4513 return -EBUSY;
4514
4515 /*
4499 * Block new css_tryget() by killing css refcnts. cgroup core 4516 * Block new css_tryget() by killing css refcnts. cgroup core
4500 * guarantees that, by the time ->css_offline() is invoked, no new 4517 * guarantees that, by the time ->css_offline() is invoked, no new
4501 * css reference will be given out via css_tryget(). We can't 4518 * css reference will be given out via css_tryget(). We can't