diff options
author | Tejun Heo <tj@kernel.org> | 2012-11-19 11:13:38 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2012-11-19 11:13:38 -0500 |
commit | 4b8b47eb0001a89f271d671d959b235faa8f03e2 (patch) | |
tree | 611245ac0c36952a3b3e4af19514baf2be3d9104 /kernel/cgroup.c | |
parent | b8a2df6a5b576d04f78f54abf254c283527d8bbc (diff) |
cgroup: update cgroup_create() failure path
cgroup_create() was ignoring failure of cgroupfs files. Update it
such that, if file creation fails, it rolls back by calling
cgroup_destroy_locked() and returns failure.
Note that error out goto labels are renamed. The labels are a bit
confusing but will become better w/ later cgroup operation renames.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Li Zefan <lizefan@huawei.com>
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r-- | kernel/cgroup.c | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index c53f42e31704..027b66e66698 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -4107,7 +4107,7 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, | |||
4107 | */ | 4107 | */ |
4108 | if (!cgroup_lock_live_group(parent)) { | 4108 | if (!cgroup_lock_live_group(parent)) { |
4109 | err = -ENODEV; | 4109 | err = -ENODEV; |
4110 | goto err_free; | 4110 | goto err_free_cgrp; |
4111 | } | 4111 | } |
4112 | 4112 | ||
4113 | /* Grab a reference on the superblock so the hierarchy doesn't | 4113 | /* Grab a reference on the superblock so the hierarchy doesn't |
@@ -4135,13 +4135,13 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, | |||
4135 | css = ss->create(cgrp); | 4135 | css = ss->create(cgrp); |
4136 | if (IS_ERR(css)) { | 4136 | if (IS_ERR(css)) { |
4137 | err = PTR_ERR(css); | 4137 | err = PTR_ERR(css); |
4138 | goto err_destroy; | 4138 | goto err_free_all; |
4139 | } | 4139 | } |
4140 | init_cgroup_css(css, ss, cgrp); | 4140 | init_cgroup_css(css, ss, cgrp); |
4141 | if (ss->use_id) { | 4141 | if (ss->use_id) { |
4142 | err = alloc_css_id(ss, parent, cgrp); | 4142 | err = alloc_css_id(ss, parent, cgrp); |
4143 | if (err) | 4143 | if (err) |
4144 | goto err_destroy; | 4144 | goto err_free_all; |
4145 | } | 4145 | } |
4146 | /* At error, ->destroy() callback has to free assigned ID. */ | 4146 | /* At error, ->destroy() callback has to free assigned ID. */ |
4147 | if (clone_children(parent) && ss->post_clone) | 4147 | if (clone_children(parent) && ss->post_clone) |
@@ -4164,7 +4164,7 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, | |||
4164 | */ | 4164 | */ |
4165 | err = cgroup_create_file(dentry, S_IFDIR | mode, sb); | 4165 | err = cgroup_create_file(dentry, S_IFDIR | mode, sb); |
4166 | if (err < 0) | 4166 | if (err < 0) |
4167 | goto err_destroy; | 4167 | goto err_free_all; |
4168 | lockdep_assert_held(&dentry->d_inode->i_mutex); | 4168 | lockdep_assert_held(&dentry->d_inode->i_mutex); |
4169 | 4169 | ||
4170 | /* allocation complete, commit to creation */ | 4170 | /* allocation complete, commit to creation */ |
@@ -4183,14 +4183,15 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, | |||
4183 | } | 4183 | } |
4184 | 4184 | ||
4185 | err = cgroup_populate_dir(cgrp, true, root->subsys_mask); | 4185 | err = cgroup_populate_dir(cgrp, true, root->subsys_mask); |
4186 | /* If err < 0, we have a half-filled directory - oh well ;) */ | 4186 | if (err) |
4187 | goto err_destroy; | ||
4187 | 4188 | ||
4188 | mutex_unlock(&cgroup_mutex); | 4189 | mutex_unlock(&cgroup_mutex); |
4189 | mutex_unlock(&cgrp->dentry->d_inode->i_mutex); | 4190 | mutex_unlock(&cgrp->dentry->d_inode->i_mutex); |
4190 | 4191 | ||
4191 | return 0; | 4192 | return 0; |
4192 | 4193 | ||
4193 | err_destroy: | 4194 | err_free_all: |
4194 | for_each_subsys(root, ss) { | 4195 | for_each_subsys(root, ss) { |
4195 | if (cgrp->subsys[ss->subsys_id]) | 4196 | if (cgrp->subsys[ss->subsys_id]) |
4196 | ss->destroy(cgrp); | 4197 | ss->destroy(cgrp); |
@@ -4198,9 +4199,15 @@ err_destroy: | |||
4198 | mutex_unlock(&cgroup_mutex); | 4199 | mutex_unlock(&cgroup_mutex); |
4199 | /* Release the reference count that we took on the superblock */ | 4200 | /* Release the reference count that we took on the superblock */ |
4200 | deactivate_super(sb); | 4201 | deactivate_super(sb); |
4201 | err_free: | 4202 | err_free_cgrp: |
4202 | kfree(cgrp); | 4203 | kfree(cgrp); |
4203 | return err; | 4204 | return err; |
4205 | |||
4206 | err_destroy: | ||
4207 | cgroup_destroy_locked(cgrp); | ||
4208 | mutex_unlock(&cgroup_mutex); | ||
4209 | mutex_unlock(&dentry->d_inode->i_mutex); | ||
4210 | return err; | ||
4204 | } | 4211 | } |
4205 | 4212 | ||
4206 | static int cgroup_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | 4213 | static int cgroup_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) |