diff options
-rw-r--r-- | kernel/cgroup.c | 31 |
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 | ||
4493 | err_destroy: | 4492 | err_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 |