cgroup: update error handling in cgroup_populate_dir()
authorTejun Heo <tj@kernel.org>
Fri, 28 Jun 2013 23:24:11 +0000 (16:24 -0700)
committerTejun Heo <tj@kernel.org>
Fri, 12 Jul 2013 19:34:01 +0000 (12:34 -0700)
cgroup_populate_dir() didn't use to check whether the actual file
creations were successful and could return success with only subset of
the requested files created, which is nasty.

This patch udpates cgroup_populate_dir() so that it either succeeds
with all files or fails with no file.

v2: The original patch also converted for_each_root_subsys() usages to
    for_each_subsys() without explaining why.  That part has been
    moved to a separate patch.

Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Li Zefan <lizefan@huawei.com>
kernel/cgroup.c

index 9835a097f3c0d3c8c21191e78fdf41611ece9ff4..6b7324431b997c883b7c7d73e39a9df04ae5d236 100644 (file)
@@ -4171,10 +4171,13 @@ static struct cftype cgroup_base_files[] = {
  * cgroup_populate_dir - create subsys files in a cgroup directory
  * @cgrp: target cgroup
  * @subsys_mask: mask of the subsystem ids whose files should be added
+ *
+ * On failure, no file is added.
  */
 static int cgroup_populate_dir(struct cgroup *cgrp, unsigned long subsys_mask)
 {
        struct cgroup_subsys *ss;
+       int ret = 0;
 
        /* process cftsets of each subsystem */
        for_each_root_subsys(cgrp->root, ss) {
@@ -4182,8 +4185,11 @@ static int cgroup_populate_dir(struct cgroup *cgrp, unsigned long subsys_mask)
                if (!test_bit(ss->subsys_id, &subsys_mask))
                        continue;
 
-               list_for_each_entry(set, &ss->cftsets, node)
-                       cgroup_addrm_files(cgrp, ss, set->cfts, true);
+               list_for_each_entry(set, &ss->cftsets, node) {
+                       ret = cgroup_addrm_files(cgrp, ss, set->cfts, true);
+                       if (ret < 0)
+                               goto err;
+               }
        }
 
        /* This cgroup is ready now */
@@ -4201,6 +4207,9 @@ static int cgroup_populate_dir(struct cgroup *cgrp, unsigned long subsys_mask)
        }
 
        return 0;
+err:
+       cgroup_clear_dir(cgrp, subsys_mask);
+       return ret;
 }
 
 static void css_dput_fn(struct work_struct *work)