diff options
author | Tejun Heo <tj@kernel.org> | 2013-06-28 19:24:10 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2013-07-12 15:34:01 -0400 |
commit | b1f28d3109349899e87377e89f9d8ab5bc95ec57 (patch) | |
tree | 817a277b89882a82e5e52fd3911d81b819709c41 | |
parent | 8f89140ae41ccd9c63344e6823faa862aa7435e3 (diff) |
cgroup: fix error path of cgroup_addrm_files()
cgroup_addrm_files() mishandled error return value from
cgroup_add_file() and returns error iff the last file fails to create.
As we're in the process of cleaning up file add/rm error handling and
will reliably propagate file creation failures, there's no point in
keeping adding files after a failure.
Replace the broken error collection logic with immediate error return.
While at it, add lockdep assertions and function comment.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Li Zefan <lizefan@huawei.com>
-rw-r--r-- | kernel/cgroup.c | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 09bfa870e698..9b16d75bec63 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -2780,11 +2780,26 @@ out: | |||
2780 | return error; | 2780 | return error; |
2781 | } | 2781 | } |
2782 | 2782 | ||
2783 | /** | ||
2784 | * cgroup_addrm_files - add or remove files to a cgroup directory | ||
2785 | * @cgrp: the target cgroup | ||
2786 | * @subsys: the subsystem of files to be added | ||
2787 | * @cfts: array of cftypes to be added | ||
2788 | * @is_add: whether to add or remove | ||
2789 | * | ||
2790 | * Depending on @is_add, add or remove files defined by @cfts on @cgrp. | ||
2791 | * All @cfts should belong to @subsys. For removals, this function never | ||
2792 | * fails. If addition fails, this function doesn't remove files already | ||
2793 | * added. The caller is responsible for cleaning up. | ||
2794 | */ | ||
2783 | static int cgroup_addrm_files(struct cgroup *cgrp, struct cgroup_subsys *subsys, | 2795 | static int cgroup_addrm_files(struct cgroup *cgrp, struct cgroup_subsys *subsys, |
2784 | struct cftype cfts[], bool is_add) | 2796 | struct cftype cfts[], bool is_add) |
2785 | { | 2797 | { |
2786 | struct cftype *cft; | 2798 | struct cftype *cft; |
2787 | int err, ret = 0; | 2799 | int ret; |
2800 | |||
2801 | lockdep_assert_held(&cgrp->dentry->d_inode->i_mutex); | ||
2802 | lockdep_assert_held(&cgroup_mutex); | ||
2788 | 2803 | ||
2789 | for (cft = cfts; cft->name[0] != '\0'; cft++) { | 2804 | for (cft = cfts; cft->name[0] != '\0'; cft++) { |
2790 | /* does cft->flags tell us to skip this file on @cgrp? */ | 2805 | /* does cft->flags tell us to skip this file on @cgrp? */ |
@@ -2796,16 +2811,17 @@ static int cgroup_addrm_files(struct cgroup *cgrp, struct cgroup_subsys *subsys, | |||
2796 | continue; | 2811 | continue; |
2797 | 2812 | ||
2798 | if (is_add) { | 2813 | if (is_add) { |
2799 | err = cgroup_add_file(cgrp, subsys, cft); | 2814 | ret = cgroup_add_file(cgrp, subsys, cft); |
2800 | if (err) | 2815 | if (ret) { |
2801 | pr_warn("cgroup_addrm_files: failed to add %s, err=%d\n", | 2816 | pr_warn("cgroup_addrm_files: failed to add %s, err=%d\n", |
2802 | cft->name, err); | 2817 | cft->name, ret); |
2803 | ret = err; | 2818 | return ret; |
2819 | } | ||
2804 | } else { | 2820 | } else { |
2805 | cgroup_rm_file(cgrp, cft); | 2821 | cgroup_rm_file(cgrp, cft); |
2806 | } | 2822 | } |
2807 | } | 2823 | } |
2808 | return ret; | 2824 | return 0; |
2809 | } | 2825 | } |
2810 | 2826 | ||
2811 | static void cgroup_cfts_prepare(void) | 2827 | static void cgroup_cfts_prepare(void) |