diff options
-rw-r--r-- | kernel/cgroup.c | 28 |
1 files changed, 23 insertions, 5 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index f783af9..306ad0e 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -2810,10 +2810,28 @@ void css_task_iter_end(struct css_task_iter *it) */ int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from) { + LIST_HEAD(preloaded_csets); + struct cgrp_cset_link *link; struct css_task_iter it; struct task_struct *task; - int ret = 0; + int ret; + + mutex_lock(&cgroup_mutex); + + /* all tasks in @from are being moved, all csets are source */ + down_read(&css_set_rwsem); + list_for_each_entry(link, &from->cset_links, cset_link) + cgroup_migrate_add_src(link->cset, to, &preloaded_csets); + up_read(&css_set_rwsem); + ret = cgroup_migrate_prepare_dst(to, &preloaded_csets); + if (ret) + goto out_err; + + /* + * Migrate tasks one-by-one until @form is empty. This fails iff + * ->can_attach() fails. + */ do { css_task_iter_start(&from->dummy_css, &it); task = css_task_iter_next(&it); @@ -2822,13 +2840,13 @@ int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from) css_task_iter_end(&it); if (task) { - mutex_lock(&cgroup_mutex); - ret = cgroup_attach_task(to, task, false); - mutex_unlock(&cgroup_mutex); + ret = cgroup_migrate(to, task, false); put_task_struct(task); } } while (task && !ret); - +out_err: + cgroup_migrate_finish(&preloaded_csets); + mutex_unlock(&cgroup_mutex); return ret; } |