+++ /dev/null
-From 40d641241a5399afc93d4eb75d8794f72fe3c0fb Mon Sep 17 00:00:00 2001
-From: Wolfgang Bumiller <w.bumiller@proxmox.com>
-Date: Wed, 21 Dec 2016 15:37:20 +0100
-Subject: [PATCH] cgroup, cpuset: add cpuset.remap_cpus
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Changes a cpuset, recursively remapping all its descendants
-to the new range.
-
-Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
-Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
----
- include/linux/cpumask.h | 17 ++++++++++++++++
- kernel/cpuset.c | 54 +++++++++++++++++++++++++++++++++++++++----------
- 2 files changed, 60 insertions(+), 11 deletions(-)
-
-diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
-index 59915ea..f5487c8 100644
---- a/include/linux/cpumask.h
-+++ b/include/linux/cpumask.h
-@@ -514,6 +514,23 @@ static inline void cpumask_copy(struct cpumask *dstp,
- }
-
- /**
-+ * cpumask_remap - *dstp = map(old, new)(*srcp)
-+ * @dstp: the result
-+ * @srcp: the input cpumask
-+ * @oldp: the old mask
-+ * @newp: the new mask
-+ */
-+static inline void cpumask_remap(struct cpumask *dstp,
-+ const struct cpumask *srcp,
-+ const struct cpumask *oldp,
-+ const struct cpumask *newp)
-+{
-+ bitmap_remap(cpumask_bits(dstp), cpumask_bits(srcp),
-+ cpumask_bits(oldp), cpumask_bits(newp),
-+ nr_cpumask_bits);
-+}
-+
-+/**
- * cpumask_any - pick a "random" cpu from *srcp
- * @srcp: the input cpumask
- *
-diff --git a/kernel/cpuset.c b/kernel/cpuset.c
-index 7e78cfe..ff5ff3a 100644
---- a/kernel/cpuset.c
-+++ b/kernel/cpuset.c
-@@ -462,7 +462,8 @@ static void free_trial_cpuset(struct cpuset *trial)
- * Return 0 if valid, -errno if not.
- */
-
--static int validate_change(struct cpuset *cur, struct cpuset *trial)
-+static int validate_change(struct cpuset *cur, struct cpuset *trial,
-+ int remap)
- {
- struct cgroup_subsys_state *css;
- struct cpuset *c, *par;
-@@ -470,11 +471,13 @@ static int validate_change(struct cpuset *cur, struct cpuset *trial)
-
- rcu_read_lock();
-
-- /* Each of our child cpusets must be a subset of us */
-- ret = -EBUSY;
-- cpuset_for_each_child(c, css, cur)
-- if (!is_cpuset_subset(c, trial))
-- goto out;
-+ if (!remap) {
-+ /* Each of our child cpusets must be a subset of us */
-+ ret = -EBUSY;
-+ cpuset_for_each_child(c, css, cur)
-+ if (!is_cpuset_subset(c, trial))
-+ goto out;
-+ }
-
- /* Remaining checks don't apply to root cpuset */
- ret = 0;
-@@ -937,11 +940,15 @@ static void update_cpumasks_hier(struct cpuset *cs, struct cpumask *new_cpus)
- * @cs: the cpuset to consider
- * @trialcs: trial cpuset
- * @buf: buffer of cpu numbers written to this cpuset
-+ * @remap: recursively remap all child nodes
- */
- static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
-- const char *buf)
-+ const char *buf, int remap)
- {
- int retval;
-+ struct cpuset *cp;
-+ struct cgroup_subsys_state *pos_css;
-+ struct cpumask tempmask;
-
- /* top_cpuset.cpus_allowed tracks cpu_online_mask; it's read-only */
- if (cs == &top_cpuset)
-@@ -969,11 +976,25 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
- if (cpumask_equal(cs->cpus_allowed, trialcs->cpus_allowed))
- return 0;
-
-- retval = validate_change(cs, trialcs);
-+ retval = validate_change(cs, trialcs, remap);
- if (retval < 0)
- return retval;
-
- spin_lock_irq(&callback_lock);
-+ if (remap) {
-+ rcu_read_lock();
-+ cpuset_for_each_descendant_pre(cp, pos_css, cs) {
-+ /* skip empty subtrees */
-+ if (cpumask_empty(cp->cpus_allowed)) {
-+ pos_css = css_rightmost_descendant(pos_css);
-+ continue;
-+ }
-+ cpumask_copy(&tempmask, cp->cpus_allowed);
-+ cpumask_remap(cp->cpus_allowed, &tempmask,
-+ cs->cpus_allowed, trialcs->cpus_allowed);
-+ }
-+ rcu_read_unlock();
-+ }
- cpumask_copy(cs->cpus_allowed, trialcs->cpus_allowed);
- spin_unlock_irq(&callback_lock);
-
-@@ -1250,7 +1271,7 @@ static int update_nodemask(struct cpuset *cs, struct cpuset *trialcs,
- retval = 0; /* Too easy - nothing to do */
- goto done;
- }
-- retval = validate_change(cs, trialcs);
-+ retval = validate_change(cs, trialcs, 0);
- if (retval < 0)
- goto done;
-
-@@ -1337,7 +1358,7 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs,
- else
- clear_bit(bit, &trialcs->flags);
-
-- err = validate_change(cs, trialcs);
-+ err = validate_change(cs, trialcs, 0);
- if (err < 0)
- goto out;
-
-@@ -1596,6 +1617,7 @@ static void cpuset_attach(struct cgroup_taskset *tset)
- typedef enum {
- FILE_MEMORY_MIGRATE,
- FILE_CPULIST,
-+ FILE_REMAP_CPULIST,
- FILE_MEMLIST,
- FILE_EFFECTIVE_CPULIST,
- FILE_EFFECTIVE_MEMLIST,
-@@ -1728,7 +1750,10 @@ static ssize_t cpuset_write_resmask(struct kernfs_open_file *of,
-
- switch (of_cft(of)->private) {
- case FILE_CPULIST:
-- retval = update_cpumask(cs, trialcs, buf);
-+ retval = update_cpumask(cs, trialcs, buf, 0);
-+ break;
-+ case FILE_REMAP_CPULIST:
-+ retval = update_cpumask(cs, trialcs, buf, 1);
- break;
- case FILE_MEMLIST:
- retval = update_nodemask(cs, trialcs, buf);
-@@ -1845,6 +1870,13 @@ static struct cftype files[] = {
- },
-
- {
-+ .name = "remap_cpus",
-+ .write = cpuset_write_resmask,
-+ .max_write_len = (100U + 6 * NR_CPUS),
-+ .private = FILE_REMAP_CPULIST,
-+ },
-+
-+ {
- .name = "mems",
- .seq_show = cpuset_common_seq_show,
- .write = cpuset_write_resmask,
---
-2.1.4
-