|
@@ -326,11 +326,46 @@ static int mem_cgroup_populate(struct cgroup_subsys *ss,
|
|
|
ARRAY_SIZE(mem_cgroup_files));
|
|
|
}
|
|
|
|
|
|
+static void mem_cgroup_move_task(struct cgroup_subsys *ss,
|
|
|
+ struct cgroup *cont,
|
|
|
+ struct cgroup *old_cont,
|
|
|
+ struct task_struct *p)
|
|
|
+{
|
|
|
+ struct mm_struct *mm;
|
|
|
+ struct mem_cgroup *mem, *old_mem;
|
|
|
+
|
|
|
+ mm = get_task_mm(p);
|
|
|
+ if (mm == NULL)
|
|
|
+ return;
|
|
|
+
|
|
|
+ mem = mem_cgroup_from_cont(cont);
|
|
|
+ old_mem = mem_cgroup_from_cont(old_cont);
|
|
|
+
|
|
|
+ if (mem == old_mem)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Only thread group leaders are allowed to migrate, the mm_struct is
|
|
|
+ * in effect owned by the leader
|
|
|
+ */
|
|
|
+ if (p->tgid != p->pid)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ css_get(&mem->css);
|
|
|
+ rcu_assign_pointer(mm->mem_cgroup, mem);
|
|
|
+ css_put(&old_mem->css);
|
|
|
+
|
|
|
+out:
|
|
|
+ mmput(mm);
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
struct cgroup_subsys mem_cgroup_subsys = {
|
|
|
.name = "memory",
|
|
|
.subsys_id = mem_cgroup_subsys_id,
|
|
|
.create = mem_cgroup_create,
|
|
|
.destroy = mem_cgroup_destroy,
|
|
|
.populate = mem_cgroup_populate,
|
|
|
+ .attach = mem_cgroup_move_task,
|
|
|
.early_init = 1,
|
|
|
};
|