]> git.proxmox.com Git - pve-kernel-jessie.git/blob - cgroup-cpuset-add-cpuset.remap_cpus.patch
revert buggy NVME setup commit
[pve-kernel-jessie.git] / cgroup-cpuset-add-cpuset.remap_cpus.patch
1 From 40d641241a5399afc93d4eb75d8794f72fe3c0fb Mon Sep 17 00:00:00 2001
2 From: Wolfgang Bumiller <w.bumiller@proxmox.com>
3 Date: Wed, 21 Dec 2016 15:37:20 +0100
4 Subject: [PATCH] cgroup, cpuset: add cpuset.remap_cpus
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 Changes a cpuset, recursively remapping all its descendants
10 to the new range.
11
12 Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
13 Signed-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
19 diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
20 index 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 *
47 diff --git a/kernel/cpuset.c b/kernel/cpuset.c
48 index 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 --
177 2.1.4
178