aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2014-02-25 10:04:03 -0500
committerTejun Heo <tj@kernel.org>2014-02-25 10:04:03 -0500
commit952aaa125428fae883670a2c2e40ea8044ca1eaa (patch)
tree54c4f846256d192f094dd6004012989b6d9f414c
parent0e1d768f1b1873272ec4e8dc1482bb5281855017 (diff)
cgroup: update cgroup_transfer_tasks() to either succeed or fail
cgroup_transfer_tasks() can currently fail in the middle due to memory allocation failure. When that happens, the function just aborts and returns error code and there's no way to tell how many actually got migrated at the point of failure and or to revert the partial migration. Update it to use cgroup_migrate{_add_src|prepare_dst|migrate|finish}() so that the function either succeeds or fails as a whole as long as ->can_attach() doesn't fail. Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Li Zefan <lizefan@huawei.com>
-rw-r--r--kernel/cgroup.c28
1 files changed, 23 insertions, 5 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index f783af900208..306ad0ed19ef 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -2810,10 +2810,28 @@ void css_task_iter_end(struct css_task_iter *it)
2810 */ 2810 */
2811int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from) 2811int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from)
2812{ 2812{
2813 LIST_HEAD(preloaded_csets);
2814 struct cgrp_cset_link *link;
2813 struct css_task_iter it; 2815 struct css_task_iter it;
2814 struct task_struct *task; 2816 struct task_struct *task;
2815 int ret = 0; 2817 int ret;
2818
2819 mutex_lock(&cgroup_mutex);
2820
2821 /* all tasks in @from are being moved, all csets are source */
2822 down_read(&css_set_rwsem);
2823 list_for_each_entry(link, &from->cset_links, cset_link)
2824 cgroup_migrate_add_src(link->cset, to, &preloaded_csets);
2825 up_read(&css_set_rwsem);
2816 2826
2827 ret = cgroup_migrate_prepare_dst(to, &preloaded_csets);
2828 if (ret)
2829 goto out_err;
2830
2831 /*
2832 * Migrate tasks one-by-one until @form is empty. This fails iff
2833 * ->can_attach() fails.
2834 */
2817 do { 2835 do {
2818 css_task_iter_start(&from->dummy_css, &it); 2836 css_task_iter_start(&from->dummy_css, &it);
2819 task = css_task_iter_next(&it); 2837 task = css_task_iter_next(&it);
@@ -2822,13 +2840,13 @@ int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from)
2822 css_task_iter_end(&it); 2840 css_task_iter_end(&it);
2823 2841
2824 if (task) { 2842 if (task) {
2825 mutex_lock(&cgroup_mutex); 2843 ret = cgroup_migrate(to, task, false);
2826 ret = cgroup_attach_task(to, task, false);
2827 mutex_unlock(&cgroup_mutex);
2828 put_task_struct(task); 2844 put_task_struct(task);
2829 } 2845 }
2830 } while (task && !ret); 2846 } while (task && !ret);
2831 2847out_err:
2848 cgroup_migrate_finish(&preloaded_csets);
2849 mutex_unlock(&cgroup_mutex);
2832 return ret; 2850 return ret;
2833} 2851}
2834 2852