aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/cgroup.c61
1 files changed, 35 insertions, 26 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 49bfd7b0bbda..5a1ddecc3cfa 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -4379,13 +4379,8 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
4379 4379
4380 /* 4380 /*
4381 * Block new css_tryget() by deactivating refcnt and mark @cgrp 4381 * Block new css_tryget() by deactivating refcnt and mark @cgrp
4382 * removed. This makes future css_tryget() and child creation 4382 * removed. This makes future css_tryget() attempts fail which we
4383 * attempts fail thus maintaining the removal conditions verified 4383 * guarantee to ->css_offline() callbacks.
4384 * above.
4385 *
4386 * Note that CGRP_DEAD assertion is depended upon by
4387 * cgroup_next_sibling() to resume iteration after dropping RCU
4388 * read lock. See cgroup_next_sibling() for details.
4389 */ 4384 */
4390 for_each_subsys(cgrp->root, ss) { 4385 for_each_subsys(cgrp->root, ss) {
4391 struct cgroup_subsys_state *css = cgrp->subsys[ss->subsys_id]; 4386 struct cgroup_subsys_state *css = cgrp->subsys[ss->subsys_id];
@@ -4393,8 +4388,41 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
4393 WARN_ON(atomic_read(&css->refcnt) < 0); 4388 WARN_ON(atomic_read(&css->refcnt) < 0);
4394 atomic_add(CSS_DEACT_BIAS, &css->refcnt); 4389 atomic_add(CSS_DEACT_BIAS, &css->refcnt);
4395 } 4390 }
4391
4392 /*
4393 * Mark @cgrp dead. This prevents further task migration and child
4394 * creation by disabling cgroup_lock_live_group(). Note that
4395 * CGRP_DEAD assertion is depended upon by cgroup_next_sibling() to
4396 * resume iteration after dropping RCU read lock. See
4397 * cgroup_next_sibling() for details.
4398 */
4396 set_bit(CGRP_DEAD, &cgrp->flags); 4399 set_bit(CGRP_DEAD, &cgrp->flags);
4397 4400
4401 /* CGRP_DEAD is set, remove from ->release_list for the last time */
4402 raw_spin_lock(&release_list_lock);
4403 if (!list_empty(&cgrp->release_list))
4404 list_del_init(&cgrp->release_list);
4405 raw_spin_unlock(&release_list_lock);
4406
4407 /*
4408 * Remove @cgrp directory. The removal puts the base ref but we
4409 * aren't quite done with @cgrp yet, so hold onto it.
4410 */
4411 dget(d);
4412 cgroup_d_remove_dir(d);
4413
4414 /*
4415 * Unregister events and notify userspace.
4416 * Notify userspace about cgroup removing only after rmdir of cgroup
4417 * directory to avoid race between userspace and kernelspace.
4418 */
4419 spin_lock(&cgrp->event_list_lock);
4420 list_for_each_entry_safe(event, tmp, &cgrp->event_list, list) {
4421 list_del_init(&event->list);
4422 schedule_work(&event->remove);
4423 }
4424 spin_unlock(&cgrp->event_list_lock);
4425
4398 /* tell subsystems to initate destruction */ 4426 /* tell subsystems to initate destruction */
4399 for_each_subsys(cgrp->root, ss) 4427 for_each_subsys(cgrp->root, ss)
4400 offline_css(ss, cgrp); 4428 offline_css(ss, cgrp);
@@ -4409,34 +4437,15 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
4409 for_each_subsys(cgrp->root, ss) 4437 for_each_subsys(cgrp->root, ss)
4410 css_put(cgrp->subsys[ss->subsys_id]); 4438 css_put(cgrp->subsys[ss->subsys_id]);
4411 4439
4412 raw_spin_lock(&release_list_lock);
4413 if (!list_empty(&cgrp->release_list))
4414 list_del_init(&cgrp->release_list);
4415 raw_spin_unlock(&release_list_lock);
4416
4417 /* delete this cgroup from parent->children */ 4440 /* delete this cgroup from parent->children */
4418 list_del_rcu(&cgrp->sibling); 4441 list_del_rcu(&cgrp->sibling);
4419 list_del_init(&cgrp->allcg_node); 4442 list_del_init(&cgrp->allcg_node);
4420 4443
4421 dget(d);
4422 cgroup_d_remove_dir(d);
4423 dput(d); 4444 dput(d);
4424 4445
4425 set_bit(CGRP_RELEASABLE, &parent->flags); 4446 set_bit(CGRP_RELEASABLE, &parent->flags);
4426 check_for_release(parent); 4447 check_for_release(parent);
4427 4448
4428 /*
4429 * Unregister events and notify userspace.
4430 * Notify userspace about cgroup removing only after rmdir of cgroup
4431 * directory to avoid race between userspace and kernelspace.
4432 */
4433 spin_lock(&cgrp->event_list_lock);
4434 list_for_each_entry_safe(event, tmp, &cgrp->event_list, list) {
4435 list_del_init(&event->list);
4436 schedule_work(&event->remove);
4437 }
4438 spin_unlock(&cgrp->event_list_lock);
4439
4440 return 0; 4449 return 0;
4441} 4450}
4442 4451