Commit 3df9ca0a authored by Tejun Heo's avatar Tejun Heo

cpuset: migrate memory only for threadgroup leaders

If memory_migrate flag is set, cpuset migrates memory according to the
destnation css's nodemask.  The current implementation migrates memory
whenever any thread of a process is migrated making the behavior
somewhat arbitrary.  Let's tie memory operations to the threadgroup
leader so that memory is migrated only when the leader is migrated.

While this is a behavior change, given the inherent fuziness, this
change is not too likely to be noticed and allows us to clearly define
who owns the memory (always the leader) and helps the planned atomic
multi-process migration.

Note that we're currently migrating memory in migration path proper
while holding all the locks.  In the long term, this should be moved
out to an async work item.
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Acked-by: default avatarZefan Li <lizefan@huawei.com>
parent 472912a2
...@@ -1487,7 +1487,6 @@ static void cpuset_attach(struct cgroup_subsys_state *css, ...@@ -1487,7 +1487,6 @@ static void cpuset_attach(struct cgroup_subsys_state *css,
{ {
/* static buf protected by cpuset_mutex */ /* static buf protected by cpuset_mutex */
static nodemask_t cpuset_attach_nodemask_to; static nodemask_t cpuset_attach_nodemask_to;
struct mm_struct *mm;
struct task_struct *task; struct task_struct *task;
struct task_struct *leader = cgroup_taskset_first(tset); struct task_struct *leader = cgroup_taskset_first(tset);
struct cpuset *cs = css_cs(css); struct cpuset *cs = css_cs(css);
...@@ -1515,26 +1514,31 @@ static void cpuset_attach(struct cgroup_subsys_state *css, ...@@ -1515,26 +1514,31 @@ static void cpuset_attach(struct cgroup_subsys_state *css,
} }
/* /*
* Change mm, possibly for multiple threads in a threadgroup. This is * Change mm, possibly for multiple threads in a threadgroup. This
* expensive and may sleep. * is expensive and may sleep and should be moved outside migration
* path proper.
*/ */
cpuset_attach_nodemask_to = cs->effective_mems; cpuset_attach_nodemask_to = cs->effective_mems;
mm = get_task_mm(leader); if (thread_group_leader(leader)) {
if (mm) { struct mm_struct *mm = get_task_mm(leader);
mpol_rebind_mm(mm, &cpuset_attach_nodemask_to);
if (mm) {
/* mpol_rebind_mm(mm, &cpuset_attach_nodemask_to);
* old_mems_allowed is the same with mems_allowed here, except
* if this task is being moved automatically due to hotplug. /*
* In that case @mems_allowed has been updated and is empty, * old_mems_allowed is the same with mems_allowed
* so @old_mems_allowed is the right nodesets that we migrate * here, except if this task is being moved
* mm from. * automatically due to hotplug. In that case
*/ * @mems_allowed has been updated and is empty, so
if (is_memory_migrate(cs)) { * @old_mems_allowed is the right nodesets that we
cpuset_migrate_mm(mm, &oldcs->old_mems_allowed, * migrate mm from.
&cpuset_attach_nodemask_to); */
if (is_memory_migrate(cs)) {
cpuset_migrate_mm(mm, &oldcs->old_mems_allowed,
&cpuset_attach_nodemask_to);
}
mmput(mm);
} }
mmput(mm);
} }
cs->old_mems_allowed = cpuset_attach_nodemask_to; cs->old_mems_allowed = cpuset_attach_nodemask_to;
......
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