From 40d641241a5399afc93d4eb75d8794f72fe3c0fb Mon Sep 17 00:00:00 2001 From: Wolfgang Bumiller 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 Signed-off-by: Fabian Grünbichler --- 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