Commit 37ff9f8f authored by Tejun Heo's avatar Tejun Heo

cgroup: make cgroup[_taskset]_migrate() take cgroup_root instead of cgroup

On the default hierarchy, a migration can be multi-source and/or
multi-destination.  cgroup_taskest_migrate() used to incorrectly
assume single destination cgroup but the bug has been fixed by
1f7dd3e5 ("cgroup: fix handling of multi-destination migration
from subtree_control enabling").

Since the commit, @dst_cgrp to cgroup[_taskset]_migrate() is only used
to determine which subsystems are affected or which cgroup_root the
migration is taking place in.  As such, @dst_cgrp is misleading.  This
patch replaces @dst_cgrp with @root.
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
parent 6c694c88
...@@ -2355,38 +2355,38 @@ struct task_struct *cgroup_taskset_next(struct cgroup_taskset *tset, ...@@ -2355,38 +2355,38 @@ struct task_struct *cgroup_taskset_next(struct cgroup_taskset *tset,
} }
/** /**
* cgroup_taskset_migrate - migrate a taskset to a cgroup * cgroup_taskset_migrate - migrate a taskset
* @tset: taget taskset * @tset: taget taskset
* @dst_cgrp: destination cgroup * @root: cgroup root the migration is taking place on
* *
* Migrate tasks in @tset to @dst_cgrp. This function fails iff one of the * Migrate tasks in @tset as setup by migration preparation functions.
* ->can_attach callbacks fails and guarantees that either all or none of * This function fails iff one of the ->can_attach callbacks fails and
* the tasks in @tset are migrated. @tset is consumed regardless of * guarantees that either all or none of the tasks in @tset are migrated.
* success. * @tset is consumed regardless of success.
*/ */
static int cgroup_taskset_migrate(struct cgroup_taskset *tset, static int cgroup_taskset_migrate(struct cgroup_taskset *tset,
struct cgroup *dst_cgrp) struct cgroup_root *root)
{ {
struct cgroup_subsys_state *css, *failed_css = NULL; struct cgroup_subsys *ss;
struct task_struct *task, *tmp_task; struct task_struct *task, *tmp_task;
struct css_set *cset, *tmp_cset; struct css_set *cset, *tmp_cset;
int i, ret; int ssid, failed_ssid, ret;
/* methods shouldn't be called if no task is actually migrating */ /* methods shouldn't be called if no task is actually migrating */
if (list_empty(&tset->src_csets)) if (list_empty(&tset->src_csets))
return 0; return 0;
/* check that we can legitimately attach to the cgroup */ /* check that we can legitimately attach to the cgroup */
for_each_e_css(css, i, dst_cgrp) { do_each_subsys_mask(ss, ssid, root->subsys_mask) {
if (css->ss->can_attach) { if (ss->can_attach) {
tset->ssid = i; tset->ssid = ssid;
ret = css->ss->can_attach(tset); ret = ss->can_attach(tset);
if (ret) { if (ret) {
failed_css = css; failed_ssid = ssid;
goto out_cancel_attach; goto out_cancel_attach;
} }
} }
} } while_each_subsys_mask();
/* /*
* Now that we're guaranteed success, proceed to move all tasks to * Now that we're guaranteed success, proceed to move all tasks to
...@@ -2413,25 +2413,25 @@ static int cgroup_taskset_migrate(struct cgroup_taskset *tset, ...@@ -2413,25 +2413,25 @@ static int cgroup_taskset_migrate(struct cgroup_taskset *tset,
*/ */
tset->csets = &tset->dst_csets; tset->csets = &tset->dst_csets;
for_each_e_css(css, i, dst_cgrp) { do_each_subsys_mask(ss, ssid, root->subsys_mask) {
if (css->ss->attach) { if (ss->attach) {
tset->ssid = i; tset->ssid = ssid;
css->ss->attach(tset); ss->attach(tset);
} }
} } while_each_subsys_mask();
ret = 0; ret = 0;
goto out_release_tset; goto out_release_tset;
out_cancel_attach: out_cancel_attach:
for_each_e_css(css, i, dst_cgrp) { do_each_subsys_mask(ss, ssid, root->subsys_mask) {
if (css == failed_css) if (ssid == failed_ssid)
break; break;
if (css->ss->cancel_attach) { if (ss->cancel_attach) {
tset->ssid = i; tset->ssid = ssid;
css->ss->cancel_attach(tset); ss->cancel_attach(tset);
} }
} } while_each_subsys_mask();
out_release_tset: out_release_tset:
spin_lock_bh(&css_set_lock); spin_lock_bh(&css_set_lock);
list_splice_init(&tset->dst_csets, &tset->src_csets); list_splice_init(&tset->dst_csets, &tset->src_csets);
...@@ -2586,11 +2586,11 @@ static int cgroup_migrate_prepare_dst(struct cgroup *dst_cgrp, ...@@ -2586,11 +2586,11 @@ static int cgroup_migrate_prepare_dst(struct cgroup *dst_cgrp,
* cgroup_migrate - migrate a process or task to a cgroup * cgroup_migrate - migrate a process or task to a cgroup
* @leader: the leader of the process or the task to migrate * @leader: the leader of the process or the task to migrate
* @threadgroup: whether @leader points to the whole process or a single task * @threadgroup: whether @leader points to the whole process or a single task
* @cgrp: the destination cgroup * @root: cgroup root migration is taking place on
* *
* Migrate a process or task denoted by @leader to @cgrp. If migrating a * Migrate a process or task denoted by @leader. If migrating a process,
* process, the caller must be holding cgroup_threadgroup_rwsem. The * the caller must be holding cgroup_threadgroup_rwsem. The caller is also
* caller is also responsible for invoking cgroup_migrate_add_src() and * responsible for invoking cgroup_migrate_add_src() and
* cgroup_migrate_prepare_dst() on the targets before invoking this * cgroup_migrate_prepare_dst() on the targets before invoking this
* function and following up with cgroup_migrate_finish(). * function and following up with cgroup_migrate_finish().
* *
...@@ -2601,7 +2601,7 @@ static int cgroup_migrate_prepare_dst(struct cgroup *dst_cgrp, ...@@ -2601,7 +2601,7 @@ static int cgroup_migrate_prepare_dst(struct cgroup *dst_cgrp,
* actually starting migrating. * actually starting migrating.
*/ */
static int cgroup_migrate(struct task_struct *leader, bool threadgroup, static int cgroup_migrate(struct task_struct *leader, bool threadgroup,
struct cgroup *cgrp) struct cgroup_root *root)
{ {
struct cgroup_taskset tset = CGROUP_TASKSET_INIT(tset); struct cgroup_taskset tset = CGROUP_TASKSET_INIT(tset);
struct task_struct *task; struct task_struct *task;
...@@ -2622,7 +2622,7 @@ static int cgroup_migrate(struct task_struct *leader, bool threadgroup, ...@@ -2622,7 +2622,7 @@ static int cgroup_migrate(struct task_struct *leader, bool threadgroup,
rcu_read_unlock(); rcu_read_unlock();
spin_unlock_bh(&css_set_lock); spin_unlock_bh(&css_set_lock);
return cgroup_taskset_migrate(&tset, cgrp); return cgroup_taskset_migrate(&tset, root);
} }
/** /**
...@@ -2659,7 +2659,7 @@ static int cgroup_attach_task(struct cgroup *dst_cgrp, ...@@ -2659,7 +2659,7 @@ static int cgroup_attach_task(struct cgroup *dst_cgrp,
/* prepare dst csets and commit */ /* prepare dst csets and commit */
ret = cgroup_migrate_prepare_dst(dst_cgrp, &preloaded_csets); ret = cgroup_migrate_prepare_dst(dst_cgrp, &preloaded_csets);
if (!ret) if (!ret)
ret = cgroup_migrate(leader, threadgroup, dst_cgrp); ret = cgroup_migrate(leader, threadgroup, dst_cgrp->root);
cgroup_migrate_finish(&preloaded_csets); cgroup_migrate_finish(&preloaded_csets);
return ret; return ret;
...@@ -2934,7 +2934,7 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp) ...@@ -2934,7 +2934,7 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp)
} }
spin_unlock_bh(&css_set_lock); spin_unlock_bh(&css_set_lock);
ret = cgroup_taskset_migrate(&tset, cgrp); ret = cgroup_taskset_migrate(&tset, cgrp->root);
out_finish: out_finish:
cgroup_migrate_finish(&preloaded_csets); cgroup_migrate_finish(&preloaded_csets);
percpu_up_write(&cgroup_threadgroup_rwsem); percpu_up_write(&cgroup_threadgroup_rwsem);
...@@ -4172,7 +4172,7 @@ int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from) ...@@ -4172,7 +4172,7 @@ int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from)
css_task_iter_end(&it); css_task_iter_end(&it);
if (task) { if (task) {
ret = cgroup_migrate(task, false, to); ret = cgroup_migrate(task, false, to->root);
put_task_struct(task); put_task_struct(task);
} }
} while (task && !ret); } while (task && !ret);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment