Commit e4857982 authored by Tejun Heo's avatar Tejun Heo

cgroup: use css_set->mg_dst_cgrp for the migration target cgroup

Migration can be multi-target on the default hierarchy when a
controller is enabled - processes belonging to each child cgroup have
to be moved to the child cgroup itself to refresh css association.

This isn't a problem for cgroup_migrate_add_src() as each source
css_set still maps to single source and target cgroups; however,
cgroup_migrate_prepare_dst() is called once after all source css_sets
are added and thus might not have a single destination cgroup.  This
is currently worked around by specifying NULL for @dst_cgrp and using
the source's default cgroup as destination as the only multi-target
migration in use is self-targetting.  While this works, it's subtle
and clunky.

As all taget cgroups are already specified while preparing the source
css_sets, this clunkiness can easily be removed by recording the
target cgroup in each source css_set.  This patch adds
css_set->mg_dst_cgrp which is recorded on cgroup_migrate_src() and
used by cgroup_migrate_prepare_dst().  This also makes migration code
ready for arbitrary multi-target migration.
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
parent 37ff9f8f
...@@ -191,12 +191,13 @@ struct css_set { ...@@ -191,12 +191,13 @@ struct css_set {
/* /*
* If this cset is acting as the source of migration the following * If this cset is acting as the source of migration the following
* two fields are set. mg_src_cgrp is the source cgroup of the * two fields are set. mg_src_cgrp and mg_dst_cgrp are
* on-going migration and mg_dst_cset is the destination cset the * respectively the source and destination cgroups of the on-going
* target tasks on this cset should be migrated to. Protected by * migration. mg_dst_cset is the destination cset the target tasks
* cgroup_mutex. * on this cset should be migrated to. Protected by cgroup_mutex.
*/ */
struct cgroup *mg_src_cgrp; struct cgroup *mg_src_cgrp;
struct cgroup *mg_dst_cgrp;
struct css_set *mg_dst_cset; struct css_set *mg_dst_cset;
/* /*
......
...@@ -2473,6 +2473,7 @@ static void cgroup_migrate_finish(struct list_head *preloaded_csets) ...@@ -2473,6 +2473,7 @@ static void cgroup_migrate_finish(struct list_head *preloaded_csets)
spin_lock_bh(&css_set_lock); spin_lock_bh(&css_set_lock);
list_for_each_entry_safe(cset, tmp_cset, preloaded_csets, mg_preload_node) { list_for_each_entry_safe(cset, tmp_cset, preloaded_csets, mg_preload_node) {
cset->mg_src_cgrp = NULL; cset->mg_src_cgrp = NULL;
cset->mg_dst_cgrp = NULL;
cset->mg_dst_cset = NULL; cset->mg_dst_cset = NULL;
list_del_init(&cset->mg_preload_node); list_del_init(&cset->mg_preload_node);
put_css_set_locked(cset); put_css_set_locked(cset);
...@@ -2511,32 +2512,31 @@ static void cgroup_migrate_add_src(struct css_set *src_cset, ...@@ -2511,32 +2512,31 @@ static void cgroup_migrate_add_src(struct css_set *src_cset,
return; return;
WARN_ON(src_cset->mg_src_cgrp); WARN_ON(src_cset->mg_src_cgrp);
WARN_ON(src_cset->mg_dst_cgrp);
WARN_ON(!list_empty(&src_cset->mg_tasks)); WARN_ON(!list_empty(&src_cset->mg_tasks));
WARN_ON(!list_empty(&src_cset->mg_node)); WARN_ON(!list_empty(&src_cset->mg_node));
src_cset->mg_src_cgrp = src_cgrp; src_cset->mg_src_cgrp = src_cgrp;
src_cset->mg_dst_cgrp = dst_cgrp;
get_css_set(src_cset); get_css_set(src_cset);
list_add(&src_cset->mg_preload_node, preloaded_csets); list_add(&src_cset->mg_preload_node, preloaded_csets);
} }
/** /**
* cgroup_migrate_prepare_dst - prepare destination css_sets for migration * cgroup_migrate_prepare_dst - prepare destination css_sets for migration
* @dst_cgrp: the destination cgroup (may be %NULL)
* @preloaded_csets: list of preloaded source css_sets * @preloaded_csets: list of preloaded source css_sets
* *
* Tasks are about to be moved to @dst_cgrp and all the source css_sets * Tasks are about to be moved and all the source css_sets have been
* have been preloaded to @preloaded_csets. This function looks up and * preloaded to @preloaded_csets. This function looks up and pins all
* pins all destination css_sets, links each to its source, and append them * destination css_sets, links each to its source, and append them to
* to @preloaded_csets. If @dst_cgrp is %NULL, the destination of each * @preloaded_csets.
* source css_set is assumed to be its cgroup on the default hierarchy.
* *
* This function must be called after cgroup_migrate_add_src() has been * This function must be called after cgroup_migrate_add_src() has been
* called on each migration source css_set. After migration is performed * called on each migration source css_set. After migration is performed
* using cgroup_migrate(), cgroup_migrate_finish() must be called on * using cgroup_migrate(), cgroup_migrate_finish() must be called on
* @preloaded_csets. * @preloaded_csets.
*/ */
static int cgroup_migrate_prepare_dst(struct cgroup *dst_cgrp, static int cgroup_migrate_prepare_dst(struct list_head *preloaded_csets)
struct list_head *preloaded_csets)
{ {
LIST_HEAD(csets); LIST_HEAD(csets);
struct css_set *src_cset, *tmp_cset; struct css_set *src_cset, *tmp_cset;
...@@ -2547,8 +2547,7 @@ static int cgroup_migrate_prepare_dst(struct cgroup *dst_cgrp, ...@@ -2547,8 +2547,7 @@ static int cgroup_migrate_prepare_dst(struct cgroup *dst_cgrp,
list_for_each_entry_safe(src_cset, tmp_cset, preloaded_csets, mg_preload_node) { list_for_each_entry_safe(src_cset, tmp_cset, preloaded_csets, mg_preload_node) {
struct css_set *dst_cset; struct css_set *dst_cset;
dst_cset = find_css_set(src_cset, dst_cset = find_css_set(src_cset, src_cset->mg_dst_cgrp);
dst_cgrp ?: src_cset->dfl_cgrp);
if (!dst_cset) if (!dst_cset)
goto err; goto err;
...@@ -2561,6 +2560,7 @@ static int cgroup_migrate_prepare_dst(struct cgroup *dst_cgrp, ...@@ -2561,6 +2560,7 @@ static int cgroup_migrate_prepare_dst(struct cgroup *dst_cgrp,
*/ */
if (src_cset == dst_cset) { if (src_cset == dst_cset) {
src_cset->mg_src_cgrp = NULL; src_cset->mg_src_cgrp = NULL;
src_cset->mg_dst_cgrp = NULL;
list_del_init(&src_cset->mg_preload_node); list_del_init(&src_cset->mg_preload_node);
put_css_set(src_cset); put_css_set(src_cset);
put_css_set(dst_cset); put_css_set(dst_cset);
...@@ -2657,7 +2657,7 @@ static int cgroup_attach_task(struct cgroup *dst_cgrp, ...@@ -2657,7 +2657,7 @@ static int cgroup_attach_task(struct cgroup *dst_cgrp,
spin_unlock_bh(&css_set_lock); spin_unlock_bh(&css_set_lock);
/* prepare dst csets and commit */ /* prepare dst csets and commit */
ret = cgroup_migrate_prepare_dst(dst_cgrp, &preloaded_csets); ret = cgroup_migrate_prepare_dst(&preloaded_csets);
if (!ret) if (!ret)
ret = cgroup_migrate(leader, threadgroup, dst_cgrp->root); ret = cgroup_migrate(leader, threadgroup, dst_cgrp->root);
...@@ -2916,7 +2916,7 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp) ...@@ -2916,7 +2916,7 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp)
spin_unlock_bh(&css_set_lock); spin_unlock_bh(&css_set_lock);
/* NULL dst indicates self on default hierarchy */ /* NULL dst indicates self on default hierarchy */
ret = cgroup_migrate_prepare_dst(NULL, &preloaded_csets); ret = cgroup_migrate_prepare_dst(&preloaded_csets);
if (ret) if (ret)
goto out_finish; goto out_finish;
...@@ -4156,7 +4156,7 @@ int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from) ...@@ -4156,7 +4156,7 @@ int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from)
cgroup_migrate_add_src(link->cset, to, &preloaded_csets); cgroup_migrate_add_src(link->cset, to, &preloaded_csets);
spin_unlock_bh(&css_set_lock); spin_unlock_bh(&css_set_lock);
ret = cgroup_migrate_prepare_dst(to, &preloaded_csets); ret = cgroup_migrate_prepare_dst(&preloaded_csets);
if (ret) if (ret)
goto out_err; goto out_err;
......
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