summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/cgroup.c31
1 files changed, 21 insertions, 10 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 8b729c278b64..bcb1755f410a 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -4426,14 +4426,6 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
4426 list_add_tail_rcu(&cgrp->sibling, &cgrp->parent->children); 4426 list_add_tail_rcu(&cgrp->sibling, &cgrp->parent->children);
4427 root->number_of_cgroups++; 4427 root->number_of_cgroups++;
4428 4428
4429 /* each css holds a ref to the cgroup's dentry and the parent css */
4430 for_each_root_subsys(root, ss) {
4431 struct cgroup_subsys_state *css = css_ar[ss->subsys_id];
4432
4433 dget(dentry);
4434 css_get(css->parent);
4435 }
4436
4437 /* hold a ref to the parent's dentry */ 4429 /* hold a ref to the parent's dentry */
4438 dget(parent->dentry); 4430 dget(parent->dentry);
4439 4431
@@ -4445,6 +4437,13 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
4445 if (err) 4437 if (err)
4446 goto err_destroy; 4438 goto err_destroy;
4447 4439
4440 /* each css holds a ref to the cgroup's dentry and parent css */
4441 dget(dentry);
4442 css_get(css->parent);
4443
4444 /* mark it consumed for error path */
4445 css_ar[ss->subsys_id] = NULL;
4446
4448 if (ss->broken_hierarchy && !ss->warned_broken_hierarchy && 4447 if (ss->broken_hierarchy && !ss->warned_broken_hierarchy &&
4449 parent->parent) { 4448 parent->parent) {
4450 pr_warning("cgroup: %s (%d) created nested cgroup for controller \"%s\" which has incomplete hierarchy support. Nested cgroups may change behavior in the future.\n", 4449 pr_warning("cgroup: %s (%d) created nested cgroup for controller \"%s\" which has incomplete hierarchy support. Nested cgroups may change behavior in the future.\n",
@@ -4491,6 +4490,14 @@ err_free_cgrp:
4491 return err; 4490 return err;
4492 4491
4493err_destroy: 4492err_destroy:
4493 for_each_root_subsys(root, ss) {
4494 struct cgroup_subsys_state *css = css_ar[ss->subsys_id];
4495
4496 if (css) {
4497 percpu_ref_cancel_init(&css->refcnt);
4498 ss->css_free(css);
4499 }
4500 }
4494 cgroup_destroy_locked(cgrp); 4501 cgroup_destroy_locked(cgrp);
4495 mutex_unlock(&cgroup_mutex); 4502 mutex_unlock(&cgroup_mutex);
4496 mutex_unlock(&dentry->d_inode->i_mutex); 4503 mutex_unlock(&dentry->d_inode->i_mutex);
@@ -4652,8 +4659,12 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
4652 * will be invoked to perform the rest of destruction once the 4659 * will be invoked to perform the rest of destruction once the
4653 * percpu refs of all css's are confirmed to be killed. 4660 * percpu refs of all css's are confirmed to be killed.
4654 */ 4661 */
4655 for_each_root_subsys(cgrp->root, ss) 4662 for_each_root_subsys(cgrp->root, ss) {
4656 kill_css(cgroup_css(cgrp, ss)); 4663 struct cgroup_subsys_state *css = cgroup_css(cgrp, ss);
4664
4665 if (css)
4666 kill_css(css);
4667 }
4657 4668
4658 /* 4669 /*
4659 * Mark @cgrp dead. This prevents further task migration and child 4670 * Mark @cgrp dead. This prevents further task migration and child