Commit e595cd70 authored by Tejun Heo's avatar Tejun Heo

cgroup: track migration context in cgroup_mgctx

cgroup migration is performed in four steps - css_set preloading,
addition of target tasks, actual migration, and clean up.  A list
named preloaded_csets is used to track the preloading.  This is a bit
too restricted and the code is already depending on the subtlety that
all source css_sets appear before destination ones.

Let's create struct cgroup_mgctx which keeps track of everything
during migration.  Currently, it has separate preload lists for source
and destination csets and also embeds cgroup_taskset which is used
during the actual migration.  This moves struct cgroup_taskset
definition to cgroup-internal.h.

This patch doesn't cause any functional changes.
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Acked-by: default avatarZefan Li <lizefan@huawei.com>
parent d8ebf519
...@@ -26,6 +26,61 @@ struct cgrp_cset_link { ...@@ -26,6 +26,61 @@ struct cgrp_cset_link {
struct list_head cgrp_link; struct list_head cgrp_link;
}; };
/* used to track tasks and csets during migration */
struct cgroup_taskset {
/* the src and dst cset list running through cset->mg_node */
struct list_head src_csets;
struct list_head dst_csets;
/* the subsys currently being processed */
int ssid;
/*
* Fields for cgroup_taskset_*() iteration.
*
* Before migration is committed, the target migration tasks are on
* ->mg_tasks of the csets on ->src_csets. After, on ->mg_tasks of
* the csets on ->dst_csets. ->csets point to either ->src_csets
* or ->dst_csets depending on whether migration is committed.
*
* ->cur_csets and ->cur_task point to the current task position
* during iteration.
*/
struct list_head *csets;
struct css_set *cur_cset;
struct task_struct *cur_task;
};
/* migration context also tracks preloading */
struct cgroup_mgctx {
/*
* Preloaded source and destination csets. Used to guarantee
* atomic success or failure on actual migration.
*/
struct list_head preloaded_src_csets;
struct list_head preloaded_dst_csets;
/* tasks and csets to migrate */
struct cgroup_taskset tset;
};
#define CGROUP_TASKSET_INIT(tset) \
{ \
.src_csets = LIST_HEAD_INIT(tset.src_csets), \
.dst_csets = LIST_HEAD_INIT(tset.dst_csets), \
.csets = &tset.src_csets, \
}
#define CGROUP_MGCTX_INIT(name) \
{ \
LIST_HEAD_INIT(name.preloaded_src_csets), \
LIST_HEAD_INIT(name.preloaded_dst_csets), \
CGROUP_TASKSET_INIT(name.tset), \
}
#define DEFINE_CGROUP_MGCTX(name) \
struct cgroup_mgctx name = CGROUP_MGCTX_INIT(name)
struct cgroup_sb_opts { struct cgroup_sb_opts {
u16 subsys_mask; u16 subsys_mask;
unsigned int flags; unsigned int flags;
...@@ -112,13 +167,12 @@ struct dentry *cgroup_do_mount(struct file_system_type *fs_type, int flags, ...@@ -112,13 +167,12 @@ struct dentry *cgroup_do_mount(struct file_system_type *fs_type, int flags,
struct cgroup_namespace *ns); struct cgroup_namespace *ns);
bool cgroup_may_migrate_to(struct cgroup *dst_cgrp); bool cgroup_may_migrate_to(struct cgroup *dst_cgrp);
void cgroup_migrate_finish(struct list_head *preloaded_csets); void cgroup_migrate_finish(struct cgroup_mgctx *mgctx);
void cgroup_migrate_add_src(struct css_set *src_cset, void cgroup_migrate_add_src(struct css_set *src_cset, struct cgroup *dst_cgrp,
struct cgroup *dst_cgrp, struct cgroup_mgctx *mgctx);
struct list_head *preloaded_csets); int cgroup_migrate_prepare_dst(struct cgroup_mgctx *mgctx);
int cgroup_migrate_prepare_dst(struct list_head *preloaded_csets);
int cgroup_migrate(struct task_struct *leader, bool threadgroup, int cgroup_migrate(struct task_struct *leader, bool threadgroup,
struct cgroup_root *root); struct cgroup_mgctx *mgctx, struct cgroup_root *root);
int cgroup_attach_task(struct cgroup *dst_cgrp, struct task_struct *leader, int cgroup_attach_task(struct cgroup *dst_cgrp, struct task_struct *leader,
bool threadgroup); bool threadgroup);
......
...@@ -87,7 +87,7 @@ EXPORT_SYMBOL_GPL(cgroup_attach_task_all); ...@@ -87,7 +87,7 @@ EXPORT_SYMBOL_GPL(cgroup_attach_task_all);
*/ */
int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from) int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from)
{ {
LIST_HEAD(preloaded_csets); DEFINE_CGROUP_MGCTX(mgctx);
struct cgrp_cset_link *link; struct cgrp_cset_link *link;
struct css_task_iter it; struct css_task_iter it;
struct task_struct *task; struct task_struct *task;
...@@ -106,10 +106,10 @@ int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from) ...@@ -106,10 +106,10 @@ int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from)
/* all tasks in @from are being moved, all csets are source */ /* all tasks in @from are being moved, all csets are source */
spin_lock_irq(&css_set_lock); spin_lock_irq(&css_set_lock);
list_for_each_entry(link, &from->cset_links, cset_link) list_for_each_entry(link, &from->cset_links, cset_link)
cgroup_migrate_add_src(link->cset, to, &preloaded_csets); cgroup_migrate_add_src(link->cset, to, &mgctx);
spin_unlock_irq(&css_set_lock); spin_unlock_irq(&css_set_lock);
ret = cgroup_migrate_prepare_dst(&preloaded_csets); ret = cgroup_migrate_prepare_dst(&mgctx);
if (ret) if (ret)
goto out_err; goto out_err;
...@@ -125,14 +125,14 @@ int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from) ...@@ -125,14 +125,14 @@ 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->root); ret = cgroup_migrate(task, false, &mgctx, to->root);
if (!ret) if (!ret)
trace_cgroup_transfer_tasks(to, task, false); trace_cgroup_transfer_tasks(to, task, false);
put_task_struct(task); put_task_struct(task);
} }
} while (task && !ret); } while (task && !ret);
out_err: out_err:
cgroup_migrate_finish(&preloaded_csets); cgroup_migrate_finish(&mgctx);
percpu_up_write(&cgroup_threadgroup_rwsem); percpu_up_write(&cgroup_threadgroup_rwsem);
mutex_unlock(&cgroup_mutex); mutex_unlock(&cgroup_mutex);
return ret; return ret;
......
This diff is collapsed.
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