1 From 5cf1cacb49aee39c3e02ae87068fc3c6430659b0 Mon Sep 17 00:00:00 2001
2 From: Tejun Heo <tj@kernel.org>
3 Date: Thu, 21 Apr 2016 19:06:48 -0400
4 Subject: cgroup, cpuset: replace cpuset_post_attach_flush() with cgroup_subsys->post_attach callback
6 From: Tejun Heo <tj@kernel.org>
8 commit 5cf1cacb49aee39c3e02ae87068fc3c6430659b0 upstream.
10 Since e93ad19d0564 ("cpuset: make mm migration asynchronous"), cpuset
11 kicks off asynchronous NUMA node migration if necessary during task
12 migration and flushes it from cpuset_post_attach_flush() which is
13 called at the end of __cgroup_procs_write(). This is to avoid
14 performing migration with cgroup_threadgroup_rwsem write-locked which
15 can lead to deadlock through dependency on kworker creation.
17 memcg has a similar issue with charge moving, so let's convert it to
18 an official callback rather than the current one-off cpuset specific
19 function. This patch adds cgroup_subsys->post_attach callback and
20 makes cpuset register cpuset_post_attach_flush() as its ->post_attach.
22 The conversion is mostly one-to-one except that the new callback is
23 called under cgroup_mutex. This is to guarantee that no other
24 migration operations are started before ->post_attach callbacks are
25 finished. cgroup_mutex is one of the outermost mutex in the system
26 and has never been and shouldn't be a problem. We can add specialized
27 synchronization around __cgroup_procs_write() but I don't think
28 there's any noticeable benefit.
30 Signed-off-by: Tejun Heo <tj@kernel.org>
31 Cc: Li Zefan <lizefan@huawei.com>
32 Cc: Johannes Weiner <hannes@cmpxchg.org>
33 Cc: Michal Hocko <mhocko@kernel.org>
34 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
37 include/linux/cgroup-defs.h | 1 +
38 include/linux/cpuset.h | 6 ------
39 kernel/cgroup.c | 7 +++++--
40 kernel/cpuset.c | 4 ++--
41 4 files changed, 8 insertions(+), 10 deletions(-)
43 --- a/include/linux/cgroup-defs.h
44 +++ b/include/linux/cgroup-defs.h
45 @@ -434,6 +434,7 @@ struct cgroup_subsys {
46 int (*can_attach)(struct cgroup_taskset *tset);
47 void (*cancel_attach)(struct cgroup_taskset *tset);
48 void (*attach)(struct cgroup_taskset *tset);
49 + void (*post_attach)(void);
50 int (*can_fork)(struct task_struct *task, void **priv_p);
51 void (*cancel_fork)(struct task_struct *task, void *priv);
52 void (*fork)(struct task_struct *task, void *priv);
53 --- a/include/linux/cpuset.h
54 +++ b/include/linux/cpuset.h
55 @@ -137,8 +137,6 @@ static inline void set_mems_allowed(node
59 -extern void cpuset_post_attach_flush(void);
61 #else /* !CONFIG_CPUSETS */
63 static inline bool cpusets_enabled(void) { return false; }
64 @@ -245,10 +243,6 @@ static inline bool read_mems_allowed_ret
68 -static inline void cpuset_post_attach_flush(void)
72 #endif /* !CONFIG_CPUSETS */
74 #endif /* _LINUX_CPUSET_H */
77 @@ -2721,9 +2721,10 @@ static ssize_t __cgroup_procs_write(stru
78 size_t nbytes, loff_t off, bool threadgroup)
80 struct task_struct *tsk;
81 + struct cgroup_subsys *ss;
87 if (kstrtoint(strstrip(buf), 0, &pid) || pid < 0)
89 @@ -2771,8 +2772,10 @@ out_unlock_rcu:
91 out_unlock_threadgroup:
92 percpu_up_write(&cgroup_threadgroup_rwsem);
93 + for_each_subsys(ss, ssid)
94 + if (ss->post_attach)
96 cgroup_kn_unlock(of->kn);
97 - cpuset_post_attach_flush();
101 --- a/kernel/cpuset.c
102 +++ b/kernel/cpuset.c
104 #include <asm/uaccess.h>
105 #include <linux/atomic.h>
106 #include <linux/mutex.h>
107 -#include <linux/workqueue.h>
108 #include <linux/cgroup.h>
109 #include <linux/wait.h>
111 @@ -1015,7 +1014,7 @@ static void cpuset_migrate_mm(struct mm_
115 -void cpuset_post_attach_flush(void)
116 +static void cpuset_post_attach(void)
118 flush_workqueue(cpuset_migrate_mm_wq);
120 @@ -2083,6 +2082,7 @@ struct cgroup_subsys cpuset_cgrp_subsys
121 .can_attach = cpuset_can_attach,
122 .cancel_attach = cpuset_cancel_attach,
123 .attach = cpuset_attach,
124 + .post_attach = cpuset_post_attach,
126 .legacy_cftypes = files,