|
@@ -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;
|
|
|
}
|
|
|
|