aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2013-12-06 15:11:56 -0500
committerTejun Heo <tj@kernel.org>2013-12-06 15:11:56 -0500
commit0d80255e42b54419cfc6b10a3ec74b60fe04b8d7 (patch)
tree05ca0985fc0797e2d8c607417a658f05d39cd7d9
parent780cd8b347b52584704438e599274f25c0a0fd13 (diff)
cgroup: reorder operations in cgroup_create()
cgroup_create() currently does the followings. 1. alloc cgroup 2. alloc css's 3. create the directory and commit to cgroup creation 4. online css's 5. create cgroup and css files The sequence performs allocations before other operations but it doesn't buy anything because each of the above steps may fail and should be unrollable. Reorganize the sequence such that cgroup operations are done before css operations. 1. alloc cgroup 2. create the directory and files and commit to cgroup creation 3. alloc css's 4. create files for and online css's This simplifies the code a bit and enables further simplification and separating out css creation from cgroup creation which is necessary for the planned unified hierarchy where css's will be created and destroyed dynamically across the lifetime of a cgroup. Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Li Zefan <lizefan@huawei.com>
-rw-r--r--kernel/cgroup.c70
1 files changed, 33 insertions, 37 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 4a7fb4043cff..30a2670df3cf 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -4144,23 +4144,6 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
4144 if (test_bit(CGRP_CPUSET_CLONE_CHILDREN, &parent->flags)) 4144 if (test_bit(CGRP_CPUSET_CLONE_CHILDREN, &parent->flags))
4145 set_bit(CGRP_CPUSET_CLONE_CHILDREN, &cgrp->flags); 4145 set_bit(CGRP_CPUSET_CLONE_CHILDREN, &cgrp->flags);
4146 4146
4147 for_each_root_subsys(root, ss) {
4148 struct cgroup_subsys_state *css;
4149
4150 css = ss->css_alloc(cgroup_css(parent, ss));
4151 if (IS_ERR(css)) {
4152 err = PTR_ERR(css);
4153 goto err_free_all;
4154 }
4155 css_ar[ss->subsys_id] = css;
4156
4157 err = percpu_ref_init(&css->refcnt, css_release);
4158 if (err)
4159 goto err_free_all;
4160
4161 init_css(css, ss, cgrp);
4162 }
4163
4164 /* 4147 /*
4165 * Create directory. cgroup_create_file() returns with the new 4148 * Create directory. cgroup_create_file() returns with the new
4166 * directory locked on success so that it can be populated without 4149 * directory locked on success so that it can be populated without
@@ -4168,7 +4151,7 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
4168 */ 4151 */
4169 err = cgroup_create_file(dentry, S_IFDIR | mode, sb); 4152 err = cgroup_create_file(dentry, S_IFDIR | mode, sb);
4170 if (err < 0) 4153 if (err < 0)
4171 goto err_free_all; 4154 goto err_unlock;
4172 lockdep_assert_held(&dentry->d_inode->i_mutex); 4155 lockdep_assert_held(&dentry->d_inode->i_mutex);
4173 4156
4174 cgrp->serial_nr = cgroup_serial_nr_next++; 4157 cgrp->serial_nr = cgroup_serial_nr_next++;
@@ -4180,10 +4163,41 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
4180 /* hold a ref to the parent's dentry */ 4163 /* hold a ref to the parent's dentry */
4181 dget(parent->dentry); 4164 dget(parent->dentry);
4182 4165
4166 /*
4167 * @cgrp is now fully operational. If something fails after this
4168 * point, it'll be released via the normal destruction path.
4169 */
4170 idr_replace(&root->cgroup_idr, cgrp, cgrp->id);
4171
4172 err = cgroup_addrm_files(cgrp, cgroup_base_files, true);
4173 if (err)
4174 goto err_destroy;
4175
4176 for_each_root_subsys(root, ss) {
4177 struct cgroup_subsys_state *css;
4178
4179 css = ss->css_alloc(cgroup_css(parent, ss));
4180 if (IS_ERR(css)) {
4181 err = PTR_ERR(css);
4182 goto err_destroy;
4183 }
4184 css_ar[ss->subsys_id] = css;
4185
4186 err = percpu_ref_init(&css->refcnt, css_release);
4187 if (err)
4188 goto err_destroy;
4189
4190 init_css(css, ss, cgrp);
4191 }
4192
4183 /* creation succeeded, notify subsystems */ 4193 /* creation succeeded, notify subsystems */
4184 for_each_root_subsys(root, ss) { 4194 for_each_root_subsys(root, ss) {
4185 struct cgroup_subsys_state *css = css_ar[ss->subsys_id]; 4195 struct cgroup_subsys_state *css = css_ar[ss->subsys_id];
4186 4196
4197 err = cgroup_populate_dir(cgrp, 1 << ss->subsys_id);
4198 if (err)
4199 goto err_destroy;
4200
4187 err = online_css(css); 4201 err = online_css(css);
4188 if (err) 4202 if (err)
4189 goto err_destroy; 4203 goto err_destroy;
@@ -4205,30 +4219,12 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
4205 } 4219 }
4206 } 4220 }
4207 4221
4208 idr_replace(&root->cgroup_idr, cgrp, cgrp->id);
4209
4210 err = cgroup_addrm_files(cgrp, cgroup_base_files, true);
4211 if (err)
4212 goto err_destroy;
4213
4214 err = cgroup_populate_dir(cgrp, root->subsys_mask);
4215 if (err)
4216 goto err_destroy;
4217
4218 mutex_unlock(&cgroup_mutex); 4222 mutex_unlock(&cgroup_mutex);
4219 mutex_unlock(&cgrp->dentry->d_inode->i_mutex); 4223 mutex_unlock(&cgrp->dentry->d_inode->i_mutex);
4220 4224
4221 return 0; 4225 return 0;
4222 4226
4223err_free_all: 4227err_unlock:
4224 for_each_root_subsys(root, ss) {
4225 struct cgroup_subsys_state *css = css_ar[ss->subsys_id];
4226
4227 if (css) {
4228 percpu_ref_cancel_init(&css->refcnt);
4229 ss->css_free(css);
4230 }
4231 }
4232 mutex_unlock(&cgroup_mutex); 4228 mutex_unlock(&cgroup_mutex);
4233 /* Release the reference count that we took on the superblock */ 4229 /* Release the reference count that we took on the superblock */
4234 deactivate_super(sb); 4230 deactivate_super(sb);