diff options
author | Tejun Heo <tj@kernel.org> | 2013-12-06 21:09:27 +0100 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2013-12-06 21:09:27 +0100 |
commit | e58e1ca438a51e7e5a28f8c9fb342d6f908d92c6 (patch) | |
tree | 5179ded8d8fecbf1ccd0d5149817b4489d5371bd /kernel/cgroup.c | |
parent | cgroup: unify pidlist and other file handling (diff) | |
parent | cgroup: fix cgroup_create() error handling path (diff) | |
download | linux-e58e1ca438a51e7e5a28f8c9fb342d6f908d92c6.tar.xz linux-e58e1ca438a51e7e5a28f8c9fb342d6f908d92c6.zip |
Merge branch 'for-3.13-fixes' into for-3.14
Pulling in as patches depending on 266ccd505e8a ("cgroup: fix
cgroup_create() error handling path") are scheduled.
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'kernel/cgroup.c')
-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 f9ae38a95af2..2e5fbf9d63e9 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -4162,14 +4162,6 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, list_add_tail_rcu(&cgrp->sibling, &cgrp->parent->children); root->number_of_cgroups++; - /* each css holds a ref to the cgroup's dentry and the parent css */ - for_each_root_subsys(root, ss) { - struct cgroup_subsys_state *css = css_ar[ss->subsys_id]; - - dget(dentry); - css_get(css->parent); - } - /* hold a ref to the parent's dentry */ dget(parent->dentry); @@ -4181,6 +4173,13 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, if (err) goto err_destroy; + /* each css holds a ref to the cgroup's dentry and parent css */ + dget(dentry); + css_get(css->parent); + + /* mark it consumed for error path */ + css_ar[ss->subsys_id] = NULL; + if (ss->broken_hierarchy && !ss->warned_broken_hierarchy && parent->parent) { 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", @@ -4227,6 +4226,14 @@ err_free_cgrp: return err; err_destroy: + for_each_root_subsys(root, ss) { + struct cgroup_subsys_state *css = css_ar[ss->subsys_id]; + + if (css) { + percpu_ref_cancel_init(&css->refcnt); + ss->css_free(css); + } + } cgroup_destroy_locked(cgrp); mutex_unlock(&cgroup_mutex); mutex_unlock(&dentry->d_inode->i_mutex); @@ -4387,8 +4394,12 @@ static int cgroup_destroy_locked(struct cgroup *cgrp) * will be invoked to perform the rest of destruction once the * percpu refs of all css's are confirmed to be killed. */ - for_each_root_subsys(cgrp->root, ss) - kill_css(cgroup_css(cgrp, ss)); + for_each_root_subsys(cgrp->root, ss) { + struct cgroup_subsys_state *css = cgroup_css(cgrp, ss); + + if (css) + kill_css(css); + } /* * Mark @cgrp dead. This prevents further task migration and child |