]> git.proxmox.com Git - pve-kernel-jessie.git/blame - cgroup-cpuset-add-cpuset.remap_cpus.patch
revert buggy NVME setup commit
[pve-kernel-jessie.git] / cgroup-cpuset-add-cpuset.remap_cpus.patch
CommitLineData
0410add4
FG
1From 40d641241a5399afc93d4eb75d8794f72fe3c0fb Mon Sep 17 00:00:00 2001
2From: Wolfgang Bumiller <w.bumiller@proxmox.com>
3Date: Wed, 21 Dec 2016 15:37:20 +0100
4Subject: [PATCH] cgroup, cpuset: add cpuset.remap_cpus
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9Changes a cpuset, recursively remapping all its descendants
10to the new range.
11
12Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
13Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
14---
15 include/linux/cpumask.h | 17 ++++++++++++++++
16 kernel/cpuset.c | 54 +++++++++++++++++++++++++++++++++++++++----------
17 2 files changed, 60 insertions(+), 11 deletions(-)
18
19diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
20index 59915ea..f5487c8 100644
21--- a/include/linux/cpumask.h
22+++ b/include/linux/cpumask.h
23@@ -514,6 +514,23 @@ static inline void cpumask_copy(struct cpumask *dstp,
24 }
25
26 /**
27+ * cpumask_remap - *dstp = map(old, new)(*srcp)
28+ * @dstp: the result
29+ * @srcp: the input cpumask
30+ * @oldp: the old mask
31+ * @newp: the new mask
32+ */
33+static inline void cpumask_remap(struct cpumask *dstp,
34+ const struct cpumask *srcp,
35+ const struct cpumask *oldp,
36+ const struct cpumask *newp)
37+{
38+ bitmap_remap(cpumask_bits(dstp), cpumask_bits(srcp),
39+ cpumask_bits(oldp), cpumask_bits(newp),
40+ nr_cpumask_bits);
41+}
42+
43+/**
44 * cpumask_any - pick a "random" cpu from *srcp
45 * @srcp: the input cpumask
46 *
47diff --git a/kernel/cpuset.c b/kernel/cpuset.c
48index 7e78cfe..ff5ff3a 100644
49--- a/kernel/cpuset.c
50+++ b/kernel/cpuset.c
51@@ -462,7 +462,8 @@ static void free_trial_cpuset(struct cpuset *trial)
52 * Return 0 if valid, -errno if not.
53 */
54
55-static int validate_change(struct cpuset *cur, struct cpuset *trial)
56+static int validate_change(struct cpuset *cur, struct cpuset *trial,
57+ int remap)
58 {
59 struct cgroup_subsys_state *css;
60 struct cpuset *c, *par;
61@@ -470,11 +471,13 @@ static int validate_change(struct cpuset *cur, struct cpuset *trial)
62
63 rcu_read_lock();
64
65- /* Each of our child cpusets must be a subset of us */
66- ret = -EBUSY;
67- cpuset_for_each_child(c, css, cur)
68- if (!is_cpuset_subset(c, trial))
69- goto out;
70+ if (!remap) {
71+ /* Each of our child cpusets must be a subset of us */
72+ ret = -EBUSY;
73+ cpuset_for_each_child(c, css, cur)
74+ if (!is_cpuset_subset(c, trial))
75+ goto out;
76+ }
77
78 /* Remaining checks don't apply to root cpuset */
79 ret = 0;
80@@ -937,11 +940,15 @@ static void update_cpumasks_hier(struct cpuset *cs, struct cpumask *new_cpus)
81 * @cs: the cpuset to consider
82 * @trialcs: trial cpuset
83 * @buf: buffer of cpu numbers written to this cpuset
84+ * @remap: recursively remap all child nodes
85 */
86 static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
87- const char *buf)
88+ const char *buf, int remap)
89 {
90 int retval;
91+ struct cpuset *cp;
92+ struct cgroup_subsys_state *pos_css;
93+ struct cpumask tempmask;
94
95 /* top_cpuset.cpus_allowed tracks cpu_online_mask; it's read-only */
96 if (cs == &top_cpuset)
97@@ -969,11 +976,25 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
98 if (cpumask_equal(cs->cpus_allowed, trialcs->cpus_allowed))
99 return 0;
100
101- retval = validate_change(cs, trialcs);
102+ retval = validate_change(cs, trialcs, remap);
103 if (retval < 0)
104 return retval;
105
106 spin_lock_irq(&callback_lock);
107+ if (remap) {
108+ rcu_read_lock();
109+ cpuset_for_each_descendant_pre(cp, pos_css, cs) {
110+ /* skip empty subtrees */
111+ if (cpumask_empty(cp->cpus_allowed)) {
112+ pos_css = css_rightmost_descendant(pos_css);
113+ continue;
114+ }
115+ cpumask_copy(&tempmask, cp->cpus_allowed);
116+ cpumask_remap(cp->cpus_allowed, &tempmask,
117+ cs->cpus_allowed, trialcs->cpus_allowed);
118+ }
119+ rcu_read_unlock();
120+ }
121 cpumask_copy(cs->cpus_allowed, trialcs->cpus_allowed);
122 spin_unlock_irq(&callback_lock);
123
124@@ -1250,7 +1271,7 @@ static int update_nodemask(struct cpuset *cs, struct cpuset *trialcs,
125 retval = 0; /* Too easy - nothing to do */
126 goto done;
127 }
128- retval = validate_change(cs, trialcs);
129+ retval = validate_change(cs, trialcs, 0);
130 if (retval < 0)
131 goto done;
132
133@@ -1337,7 +1358,7 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs,
134 else
135 clear_bit(bit, &trialcs->flags);
136
137- err = validate_change(cs, trialcs);
138+ err = validate_change(cs, trialcs, 0);
139 if (err < 0)
140 goto out;
141
142@@ -1596,6 +1617,7 @@ static void cpuset_attach(struct cgroup_taskset *tset)
143 typedef enum {
144 FILE_MEMORY_MIGRATE,
145 FILE_CPULIST,
146+ FILE_REMAP_CPULIST,
147 FILE_MEMLIST,
148 FILE_EFFECTIVE_CPULIST,
149 FILE_EFFECTIVE_MEMLIST,
150@@ -1728,7 +1750,10 @@ static ssize_t cpuset_write_resmask(struct kernfs_open_file *of,
151
152 switch (of_cft(of)->private) {
153 case FILE_CPULIST:
154- retval = update_cpumask(cs, trialcs, buf);
155+ retval = update_cpumask(cs, trialcs, buf, 0);
156+ break;
157+ case FILE_REMAP_CPULIST:
158+ retval = update_cpumask(cs, trialcs, buf, 1);
159 break;
160 case FILE_MEMLIST:
161 retval = update_nodemask(cs, trialcs, buf);
162@@ -1845,6 +1870,13 @@ static struct cftype files[] = {
163 },
164
165 {
166+ .name = "remap_cpus",
167+ .write = cpuset_write_resmask,
168+ .max_write_len = (100U + 6 * NR_CPUS),
169+ .private = FILE_REMAP_CPULIST,
170+ },
171+
172+ {
173 .name = "mems",
174 .seq_show = cpuset_common_seq_show,
175 .write = cpuset_write_resmask,
176--
1772.1.4
178