* [PATCH -next RFC 00/11] Refactor cpus mask setting
@ 2025-08-28 12:56 Chen Ridong
2025-08-28 12:56 ` [PATCH -next RFC 01/11] cpuset: move the root cpuset write check earlier Chen Ridong
` (10 more replies)
0 siblings, 11 replies; 23+ messages in thread
From: Chen Ridong @ 2025-08-28 12:56 UTC (permalink / raw)
To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong
From: Chen Ridong <chenridong@huawei.com>
This patch series refactors the CPU mask configuration logic for both
cpuset.cpus and cpuset.cpus.exclusive settings. The primary goal is to
improve code readability through comprehensive function restructuring.
The CPU mask update process follows these steps:
1. Parse user input
2. Skip processing if no actual change to CPU mask
3. Compute trial cpuset's effective exclusive CPUs
4. Validate changes and return error if invalid
5. Handle partition state changes resulting from CPU mask modifications
6. Apply new CPU mask to the cpuset
7. Propagate changes through the hierarchy
The series is organized as follows:
patches 1-3: Code cleanup and preparation for refactoring
patches 4-9: Refactoring of cpuset.cpus configuration logic
patches 10-11: Refactoring of cpuset.cpus.exclusive configuration logic
Chen Ridong (11):
cpuset: move the root cpuset write check earlier
cpuset: remove unused assignment to trialcs->partition_root_state
cpuset: change return type of is_partition_[in]valid to bool
cpuset: Refactor exclusive CPU mask computation logic
cpuset: refactor CPU mask buffer parsing logic
cpuset: introduce cpus_excl_conflict and mems_excl_conflict helpers
cpuset: refactor out invalidate_cs_partition
cpuset: refactor acpus_validate_change
cpuset: refactor partition_cpus_change
cpuset: use parse_cpulist for setting cpus.exclusive
cpuset: use partition_cpus_change for setting exclusive cpus
kernel/cgroup/cpuset.c | 443 ++++++++++++++++++++++-------------------
1 file changed, 239 insertions(+), 204 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH -next RFC 01/11] cpuset: move the root cpuset write check earlier
2025-08-28 12:56 [PATCH -next RFC 00/11] Refactor cpus mask setting Chen Ridong
@ 2025-08-28 12:56 ` Chen Ridong
2025-08-29 19:21 ` Waiman Long
2025-08-28 12:56 ` [PATCH -next RFC 02/11] cpuset: remove unused assignment to trialcs->partition_root_state Chen Ridong
` (9 subsequent siblings)
10 siblings, 1 reply; 23+ messages in thread
From: Chen Ridong @ 2025-08-28 12:56 UTC (permalink / raw)
To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong
From: Chen Ridong <chenridong@huawei.com>
The 'cpus' or 'mems' lists of the top_cpuset cannot be modified.
This check can be moved before acquiring any locks as a common code
block to improve efficiency and maintainability.
Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
kernel/cgroup/cpuset.c | 22 +++++++++-------------
1 file changed, 9 insertions(+), 13 deletions(-)
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index a78ccd11ce9b..7e6a40e361ea 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -337,6 +337,11 @@ static inline bool cpuset_v2(void)
cgroup_subsys_on_dfl(cpuset_cgrp_subsys);
}
+static inline bool cpuset_is_root(struct cpuset *cs)
+{
+ return (cs == &top_cpuset);
+}
+
/*
* Cgroup v2 behavior is used on the "cpus" and "mems" control files when
* on default hierarchy or when the cpuset_v2_mode flag is set by mounting
@@ -2334,10 +2339,6 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
bool force = false;
int old_prs = cs->partition_root_state;
- /* top_cpuset.cpus_allowed tracks cpu_active_mask; it's read-only */
- if (cs == &top_cpuset)
- return -EACCES;
-
/*
* An empty cpus_allowed is ok only if the cpuset has no tasks.
* Since cpulist_parse() fails on an empty mask, we special case
@@ -2783,15 +2784,6 @@ static int update_nodemask(struct cpuset *cs, struct cpuset *trialcs,
{
int retval;
- /*
- * top_cpuset.mems_allowed tracks node_stats[N_MEMORY];
- * it's read-only
- */
- if (cs == &top_cpuset) {
- retval = -EACCES;
- goto done;
- }
-
/*
* An empty mems_allowed is ok iff there are no tasks in the cpuset.
* Since nodelist_parse() fails on an empty mask, we special case
@@ -3257,6 +3249,10 @@ ssize_t cpuset_write_resmask(struct kernfs_open_file *of,
struct cpuset *trialcs;
int retval = -ENODEV;
+ /* root is read-only */
+ if (cpuset_is_root(cs))
+ return -EACCES;
+
buf = strstrip(buf);
cpuset_full_lock();
if (!is_cpuset_online(cs))
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH -next RFC 02/11] cpuset: remove unused assignment to trialcs->partition_root_state
2025-08-28 12:56 [PATCH -next RFC 00/11] Refactor cpus mask setting Chen Ridong
2025-08-28 12:56 ` [PATCH -next RFC 01/11] cpuset: move the root cpuset write check earlier Chen Ridong
@ 2025-08-28 12:56 ` Chen Ridong
2025-08-28 12:56 ` [PATCH -next RFC 03/11] cpuset: change return type of is_partition_[in]valid to bool Chen Ridong
` (8 subsequent siblings)
10 siblings, 0 replies; 23+ messages in thread
From: Chen Ridong @ 2025-08-28 12:56 UTC (permalink / raw)
To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong
From: Chen Ridong <chenridong@huawei.com>
The trialcs->partition_root_state field is not used during the
configuration of 'cpuset.cpus' or 'cpuset.cpus.exclusive'. Therefore,
the assignment of values to this field can be safely removed.
Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
kernel/cgroup/cpuset.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 7e6a40e361ea..6fc25fd2300b 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -2364,7 +2364,6 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
* trialcs->effective_xcpus is used as a temporary cpumask
* for checking validity of the partition root.
*/
- trialcs->partition_root_state = PRS_MEMBER;
if (!cpumask_empty(trialcs->exclusive_cpus) || is_partition_valid(cs))
compute_effective_exclusive_cpumask(trialcs, NULL, cs);
}
@@ -2498,7 +2497,6 @@ static int update_exclusive_cpumask(struct cpuset *cs, struct cpuset *trialcs,
return 0;
if (*buf) {
- trialcs->partition_root_state = PRS_MEMBER;
/*
* Reject the change if there is exclusive CPUs conflict with
* the siblings.
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH -next RFC 03/11] cpuset: change return type of is_partition_[in]valid to bool
2025-08-28 12:56 [PATCH -next RFC 00/11] Refactor cpus mask setting Chen Ridong
2025-08-28 12:56 ` [PATCH -next RFC 01/11] cpuset: move the root cpuset write check earlier Chen Ridong
2025-08-28 12:56 ` [PATCH -next RFC 02/11] cpuset: remove unused assignment to trialcs->partition_root_state Chen Ridong
@ 2025-08-28 12:56 ` Chen Ridong
2025-08-28 12:56 ` [PATCH -next RFC 04/11] cpuset: Refactor exclusive CPU mask computation logic Chen Ridong
` (7 subsequent siblings)
10 siblings, 0 replies; 23+ messages in thread
From: Chen Ridong @ 2025-08-28 12:56 UTC (permalink / raw)
To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong
From: Chen Ridong <chenridong@huawei.com>
The functions is_partition_valid() and is_partition_invalid() logically
return boolean values, but were previously declared with return type
'int'. This patch changes their return type to 'bool' to better reflect
their semantic meaning and improve type safety.
Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
kernel/cgroup/cpuset.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 6fc25fd2300b..595a8346f823 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -159,12 +159,12 @@ void dec_dl_tasks_cs(struct task_struct *p)
cs->nr_deadline_tasks--;
}
-static inline int is_partition_valid(const struct cpuset *cs)
+static inline bool is_partition_valid(const struct cpuset *cs)
{
return cs->partition_root_state > 0;
}
-static inline int is_partition_invalid(const struct cpuset *cs)
+static inline bool is_partition_invalid(const struct cpuset *cs)
{
return cs->partition_root_state < 0;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH -next RFC 04/11] cpuset: Refactor exclusive CPU mask computation logic
2025-08-28 12:56 [PATCH -next RFC 00/11] Refactor cpus mask setting Chen Ridong
` (2 preceding siblings ...)
2025-08-28 12:56 ` [PATCH -next RFC 03/11] cpuset: change return type of is_partition_[in]valid to bool Chen Ridong
@ 2025-08-28 12:56 ` Chen Ridong
2025-08-28 12:56 ` [PATCH -next RFC 05/11] cpuset: refactor CPU mask buffer parsing logic Chen Ridong
` (6 subsequent siblings)
10 siblings, 0 replies; 23+ messages in thread
From: Chen Ridong @ 2025-08-28 12:56 UTC (permalink / raw)
To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong
From: Chen Ridong <chenridong@huawei.com>
The current compute_effective_exclusive_cpumask function handles multiple
scenarios with different input parameters, making the code difficult to
follow. This patch refactors it into two separate functions:
compute_excpus and compute_trialcs_excpus.
The compute_excpus function calculates the exclusive CPU mask for a given
input and excludes exclusive CPUs from sibling cpusets when cs's
exclusive_cpus is not explicitly set.
The compute_trialcs_excpus function specifically handles exclusive CPU
computation for trial cpusets used during CPU mask configuration updates,
and always excludes exclusive CPUs from sibling cpusets.
This refactoring significantly improves code readability and clarity,
making it explicit which function to call for each use case and what
parameters should be provided.
Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
kernel/cgroup/cpuset.c | 103 ++++++++++++++++++++++++++---------------
1 file changed, 65 insertions(+), 38 deletions(-)
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 595a8346f823..fc367ae741cf 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -1402,38 +1402,25 @@ bool cpuset_cpu_is_isolated(int cpu)
}
EXPORT_SYMBOL_GPL(cpuset_cpu_is_isolated);
-/*
- * compute_effective_exclusive_cpumask - compute effective exclusive CPUs
- * @cs: cpuset
- * @xcpus: effective exclusive CPUs value to be set
- * @real_cs: the real cpuset (can be NULL)
- * Return: 0 if there is no sibling conflict, > 0 otherwise
+/**
+ * rm_siblings_excl_cpus - Remove exclusive CPUs that are used by sibling cpusets
+ * @parent: Parent cpuset containing all siblings
+ * @cs: Current cpuset (will be skipped)
+ * @excpus: exclusive effective CPU mask to modify
*
- * If exclusive_cpus isn't explicitly set or a real_cs is provided, we have to
- * scan the sibling cpusets and exclude their exclusive_cpus or effective_xcpus
- * as well. The provision of real_cs means that a cpumask is being changed and
- * the given cs is a trial one.
+ * This function ensures the given @excpus mask doesn't include any CPUs that
+ * are exclusively allocated to sibling cpusets. It walks through all siblings
+ * of @cs under @parent and removes their exclusive CPUs from @excpus.
*/
-static int compute_effective_exclusive_cpumask(struct cpuset *cs,
- struct cpumask *xcpus,
- struct cpuset *real_cs)
+static int rm_siblings_excl_cpus(struct cpuset *parent, struct cpuset *cs,
+ struct cpumask *excpus)
{
struct cgroup_subsys_state *css;
- struct cpuset *parent = parent_cs(cs);
struct cpuset *sibling;
int retval = 0;
- if (!xcpus)
- xcpus = cs->effective_xcpus;
-
- cpumask_and(xcpus, user_xcpus(cs), parent->effective_xcpus);
-
- if (!real_cs) {
- if (!cpumask_empty(cs->exclusive_cpus))
- return 0;
- } else {
- cs = real_cs;
- }
+ if (cpumask_empty(excpus))
+ return retval;
/*
* Exclude exclusive CPUs from siblings
@@ -1443,20 +1430,60 @@ static int compute_effective_exclusive_cpumask(struct cpuset *cs,
if (sibling == cs)
continue;
- if (cpumask_intersects(xcpus, sibling->exclusive_cpus)) {
- cpumask_andnot(xcpus, xcpus, sibling->exclusive_cpus);
+ if (cpumask_intersects(excpus, sibling->exclusive_cpus)) {
+ cpumask_andnot(excpus, excpus, sibling->exclusive_cpus);
retval++;
continue;
}
- if (cpumask_intersects(xcpus, sibling->effective_xcpus)) {
- cpumask_andnot(xcpus, xcpus, sibling->effective_xcpus);
+ if (cpumask_intersects(excpus, sibling->effective_xcpus)) {
+ cpumask_andnot(excpus, excpus, sibling->effective_xcpus);
retval++;
}
}
rcu_read_unlock();
+
return retval;
}
+/*
+ * compute_excpus - compute effective exclusive CPUs
+ * @cs: cpuset
+ * @xcpus: effective exclusive CPUs value to be set
+ * Return: 0 if there is no sibling conflict, > 0 otherwise
+ *
+ * If exclusive_cpus isn't explicitly set , we have to scan the sibling cpusets
+ * and exclude their exclusive_cpus or effective_xcpus as well.
+ */
+static int compute_excpus(struct cpuset *cs, struct cpumask *excpus)
+{
+ struct cpuset *parent = parent_cs(cs);
+
+ cpumask_and(excpus, user_xcpus(cs), parent->effective_xcpus);
+
+ if (!cpumask_empty(cs->exclusive_cpus))
+ return 0;
+
+ return rm_siblings_excl_cpus(parent, cs, excpus);
+}
+
+/*
+ * compute_trialcs_excpus - Compute effective exclusive CPUs for a trial cpuset
+ * @trialcs: The trial cpuset containing the proposed new configuration
+ * @cs: The original cpuset that the trial configuration is based on
+ * Return: 0 if successful with no sibling conflict, >0 if a conflict is found
+ *
+ * Computes the effective_xcpus for a trial configuration. @cs is provided to represent
+ * the real cs.
+ */
+static int compute_trialcs_excpus(struct cpuset *trialcs, struct cpuset *cs)
+{
+ struct cpuset *parent = parent_cs(trialcs);
+ struct cpumask *excpus = trialcs->effective_xcpus;
+
+ cpumask_and(excpus, user_xcpus(trialcs), parent->effective_xcpus);
+ return rm_siblings_excl_cpus(parent, cs, excpus);
+}
+
static inline bool is_remote_partition(struct cpuset *cs)
{
return !list_empty(&cs->remote_sibling);
@@ -1498,7 +1525,7 @@ static int remote_partition_enable(struct cpuset *cs, int new_prs,
* Note that creating a remote partition with any local partition root
* above it or remote partition root underneath it is not allowed.
*/
- compute_effective_exclusive_cpumask(cs, tmp->new_cpus, NULL);
+ compute_excpus(cs, tmp->new_cpus);
WARN_ON_ONCE(cpumask_intersects(tmp->new_cpus, subpartitions_cpus));
if (!cpumask_intersects(tmp->new_cpus, cpu_active_mask) ||
cpumask_subset(top_cpuset.effective_cpus, tmp->new_cpus))
@@ -1547,7 +1574,7 @@ static void remote_partition_disable(struct cpuset *cs, struct tmpmasks *tmp)
cs->partition_root_state = PRS_MEMBER;
/* effective_xcpus may need to be changed */
- compute_effective_exclusive_cpumask(cs, NULL, NULL);
+ compute_excpus(cs, cs->effective_xcpus);
reset_partition_data(cs);
spin_unlock_irq(&callback_lock);
update_unbound_workqueue_cpumask(isolcpus_updated);
@@ -1748,12 +1775,12 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd,
if ((cmd == partcmd_enable) || (cmd == partcmd_enablei)) {
/*
- * Need to call compute_effective_exclusive_cpumask() in case
+ * Need to call compute_excpus() in case
* exclusive_cpus not set. Sibling conflict should only happen
* if exclusive_cpus isn't set.
*/
xcpus = tmp->delmask;
- if (compute_effective_exclusive_cpumask(cs, xcpus, NULL))
+ if (compute_excpus(cs, xcpus))
WARN_ON_ONCE(!cpumask_empty(cs->exclusive_cpus));
/*
@@ -2035,7 +2062,7 @@ static void compute_partition_effective_cpumask(struct cpuset *cs,
* 2) All the effective_cpus will be used up and cp
* has tasks
*/
- compute_effective_exclusive_cpumask(cs, new_ecpus, NULL);
+ compute_excpus(cs, new_ecpus);
cpumask_and(new_ecpus, new_ecpus, cpu_active_mask);
rcu_read_lock();
@@ -2114,7 +2141,7 @@ static void update_cpumasks_hier(struct cpuset *cs, struct tmpmasks *tmp,
* its value is being processed.
*/
if (remote && (cp != cs)) {
- compute_effective_exclusive_cpumask(cp, tmp->new_cpus, NULL);
+ compute_excpus(cp, tmp->new_cpus);
if (cpumask_equal(cp->effective_xcpus, tmp->new_cpus)) {
pos_css = css_rightmost_descendant(pos_css);
continue;
@@ -2216,7 +2243,7 @@ static void update_cpumasks_hier(struct cpuset *cs, struct tmpmasks *tmp,
cpumask_copy(cp->effective_cpus, tmp->new_cpus);
cp->partition_root_state = new_prs;
if (!cpumask_empty(cp->exclusive_cpus) && (cp != cs))
- compute_effective_exclusive_cpumask(cp, NULL, NULL);
+ compute_excpus(cp, cp->effective_xcpus);
/*
* Make sure effective_xcpus is properly set for a valid
@@ -2365,7 +2392,7 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
* for checking validity of the partition root.
*/
if (!cpumask_empty(trialcs->exclusive_cpus) || is_partition_valid(cs))
- compute_effective_exclusive_cpumask(trialcs, NULL, cs);
+ compute_trialcs_excpus(trialcs, cs);
}
/* Nothing to do if the cpus didn't change */
@@ -2501,7 +2528,7 @@ static int update_exclusive_cpumask(struct cpuset *cs, struct cpuset *trialcs,
* Reject the change if there is exclusive CPUs conflict with
* the siblings.
*/
- if (compute_effective_exclusive_cpumask(trialcs, NULL, cs))
+ if (compute_trialcs_excpus(trialcs, cs))
return -EINVAL;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH -next RFC 05/11] cpuset: refactor CPU mask buffer parsing logic
2025-08-28 12:56 [PATCH -next RFC 00/11] Refactor cpus mask setting Chen Ridong
` (3 preceding siblings ...)
2025-08-28 12:56 ` [PATCH -next RFC 04/11] cpuset: Refactor exclusive CPU mask computation logic Chen Ridong
@ 2025-08-28 12:56 ` Chen Ridong
2025-08-28 12:56 ` [PATCH -next RFC 06/11] cpuset: introduce cpus_excl_conflict and mems_excl_conflict helpers Chen Ridong
` (5 subsequent siblings)
10 siblings, 0 replies; 23+ messages in thread
From: Chen Ridong @ 2025-08-28 12:56 UTC (permalink / raw)
To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong
From: Chen Ridong <chenridong@huawei.com>
The existing cpulist_parse() function already handles empty masks
correctly, eliminating the need for special-case handling of empty
inputs.
Adds a parse_cpulist() helper function to centralize the parsing of
CPU list inputs.
Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
kernel/cgroup/cpuset.c | 59 +++++++++++++++++++++---------------------
1 file changed, 30 insertions(+), 29 deletions(-)
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index fc367ae741cf..5dd1e9552000 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -169,6 +169,11 @@ static inline bool is_partition_invalid(const struct cpuset *cs)
return cs->partition_root_state < 0;
}
+static inline bool cs_is_member(const struct cpuset *cs)
+{
+ return cs->partition_root_state == PRS_MEMBER;
+}
+
/*
* Callers should hold callback_lock to modify partition_root_state.
*/
@@ -1480,7 +1485,13 @@ static int compute_trialcs_excpus(struct cpuset *trialcs, struct cpuset *cs)
struct cpuset *parent = parent_cs(trialcs);
struct cpumask *excpus = trialcs->effective_xcpus;
- cpumask_and(excpus, user_xcpus(trialcs), parent->effective_xcpus);
+ /* trialcs is member, cpuset.cpus has no impact to xcpus */
+ if (cs_is_member(cs))
+ cpumask_and(excpus, trialcs->exclusive_cpus,
+ parent->effective_xcpus);
+ else
+ cpumask_and(excpus, user_xcpus(trialcs), parent->effective_xcpus);
+
return rm_siblings_excl_cpus(parent, cs, excpus);
}
@@ -2350,6 +2361,19 @@ static void update_sibling_cpumasks(struct cpuset *parent, struct cpuset *cs,
rcu_read_unlock();
}
+static int parse_cpulist(const char *buf, struct cpumask *out_mask)
+{
+ int retval;
+
+ retval = cpulist_parse(buf, out_mask);
+ if (retval < 0)
+ return retval;
+ if (!cpumask_subset(out_mask, top_cpuset.cpus_allowed))
+ return -EINVAL;
+
+ return 0;
+}
+
/**
* update_cpumask - update the cpus_allowed mask of a cpuset and all tasks in it
* @cs: the cpuset to consider
@@ -2366,34 +2390,9 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
bool force = false;
int old_prs = cs->partition_root_state;
- /*
- * An empty cpus_allowed is ok only if the cpuset has no tasks.
- * Since cpulist_parse() fails on an empty mask, we special case
- * that parsing. The validate_change() call ensures that cpusets
- * with tasks have cpus.
- */
- if (!*buf) {
- cpumask_clear(trialcs->cpus_allowed);
- if (cpumask_empty(trialcs->exclusive_cpus))
- cpumask_clear(trialcs->effective_xcpus);
- } else {
- retval = cpulist_parse(buf, trialcs->cpus_allowed);
- if (retval < 0)
- return retval;
-
- if (!cpumask_subset(trialcs->cpus_allowed,
- top_cpuset.cpus_allowed))
- return -EINVAL;
-
- /*
- * When exclusive_cpus isn't explicitly set, it is constrained
- * by cpus_allowed and parent's effective_xcpus. Otherwise,
- * trialcs->effective_xcpus is used as a temporary cpumask
- * for checking validity of the partition root.
- */
- if (!cpumask_empty(trialcs->exclusive_cpus) || is_partition_valid(cs))
- compute_trialcs_excpus(trialcs, cs);
- }
+ retval = parse_cpulist(buf, trialcs->cpus_allowed);
+ if (retval < 0)
+ return retval;
/* Nothing to do if the cpus didn't change */
if (cpumask_equal(cs->cpus_allowed, trialcs->cpus_allowed))
@@ -2402,6 +2401,8 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
if (alloc_tmpmasks(&tmp))
return -ENOMEM;
+ compute_trialcs_excpus(trialcs, cs);
+
if (old_prs) {
if (is_partition_valid(cs) &&
cpumask_empty(trialcs->effective_xcpus)) {
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH -next RFC 06/11] cpuset: introduce cpus_excl_conflict and mems_excl_conflict helpers
2025-08-28 12:56 [PATCH -next RFC 00/11] Refactor cpus mask setting Chen Ridong
` (4 preceding siblings ...)
2025-08-28 12:56 ` [PATCH -next RFC 05/11] cpuset: refactor CPU mask buffer parsing logic Chen Ridong
@ 2025-08-28 12:56 ` Chen Ridong
2025-08-29 19:29 ` Waiman Long
2025-08-28 12:56 ` [PATCH -next RFC 07/11] cpuset: refactor out invalidate_cs_partition Chen Ridong
` (4 subsequent siblings)
10 siblings, 1 reply; 23+ messages in thread
From: Chen Ridong @ 2025-08-28 12:56 UTC (permalink / raw)
To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong
From: Chen Ridong <chenridong@huawei.com>
This patch adds cpus_excl_conflict() and mems_excl_conflict() helper
functions to improve code readability and maintainability. The exclusive
conflict checking follows these rules:
1. If either cpuset has the 'exclusive' flag set, their user_xcpus must
not have any overlap.
2. If both cpusets are non-exclusive, their 'cpuset.cpus.exclusive' values
must not intersect.
3. The 'cpuset.cpus' of one cpuset must not form a subset of another
cpuset's 'cpuset.cpus.exclusive'.
Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
kernel/cgroup/cpuset.c | 62 ++++++++++++++++++++++--------------------
1 file changed, 32 insertions(+), 30 deletions(-)
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 5dd1e9552000..5cfc53fe717c 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -584,6 +584,35 @@ static inline bool cpusets_are_exclusive(struct cpuset *cs1, struct cpuset *cs2)
return true;
}
+static inline bool cpus_excl_conflict(struct cpuset *cs1, struct cpuset *cs2)
+{
+ /* One is exclusive, they must be exclusive */
+ if (is_cpu_exclusive(cs1) || is_cpu_exclusive(cs2))
+ return !cpusets_are_exclusive(cs1, cs2);
+
+ /* Exclusive_cpus can not have intersects*/
+ if (cpumask_intersects(cs1->exclusive_cpus, cs2->exclusive_cpus))
+ return true;
+
+ /* One cpus_allowed can not be a subset of another's cpuset.effective_cpus */
+ if (!cpumask_empty(cs1->cpus_allowed) &&
+ cpumask_subset(cs1->cpus_allowed, cs2->exclusive_cpus))
+ return true;
+
+ if (!cpumask_empty(cs2->cpus_allowed) &&
+ cpumask_subset(cs2->cpus_allowed, cs1->exclusive_cpus))
+ return true;
+
+ return false;
+}
+
+static inline bool mems_excl_conflict(struct cpuset *cs1, struct cpuset *cs2)
+{
+ if ((is_mem_exclusive(cs1) || is_mem_exclusive(cs2)))
+ return nodes_intersects(cs1->mems_allowed, cs2->mems_allowed);
+ return false;
+}
+
/*
* validate_change() - Used to validate that any proposed cpuset change
* follows the structural rules for cpusets.
@@ -665,38 +694,11 @@ static int validate_change(struct cpuset *cur, struct cpuset *trial)
*/
ret = -EINVAL;
cpuset_for_each_child(c, css, par) {
- bool txset, cxset; /* Are exclusive_cpus set? */
-
if (c == cur)
continue;
-
- txset = !cpumask_empty(trial->exclusive_cpus);
- cxset = !cpumask_empty(c->exclusive_cpus);
- if (is_cpu_exclusive(trial) || is_cpu_exclusive(c) ||
- (txset && cxset)) {
- if (!cpusets_are_exclusive(trial, c))
- goto out;
- } else if (txset || cxset) {
- struct cpumask *xcpus, *acpus;
-
- /*
- * When just one of the exclusive_cpus's is set,
- * cpus_allowed of the other cpuset, if set, cannot be
- * a subset of it or none of those CPUs will be
- * available if these exclusive CPUs are activated.
- */
- if (txset) {
- xcpus = trial->exclusive_cpus;
- acpus = c->cpus_allowed;
- } else {
- xcpus = c->exclusive_cpus;
- acpus = trial->cpus_allowed;
- }
- if (!cpumask_empty(acpus) && cpumask_subset(acpus, xcpus))
- goto out;
- }
- if ((is_mem_exclusive(trial) || is_mem_exclusive(c)) &&
- nodes_intersects(trial->mems_allowed, c->mems_allowed))
+ if (cpus_excl_conflict(trial, c))
+ goto out;
+ if (mems_excl_conflict(trial, c))
goto out;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH -next RFC 07/11] cpuset: refactor out invalidate_cs_partition
2025-08-28 12:56 [PATCH -next RFC 00/11] Refactor cpus mask setting Chen Ridong
` (5 preceding siblings ...)
2025-08-28 12:56 ` [PATCH -next RFC 06/11] cpuset: introduce cpus_excl_conflict and mems_excl_conflict helpers Chen Ridong
@ 2025-08-28 12:56 ` Chen Ridong
2025-08-29 19:56 ` Waiman Long
2025-08-28 12:56 ` [PATCH -next RFC 08/11] cpuset: refactor acpus_validate_change Chen Ridong
` (3 subsequent siblings)
10 siblings, 1 reply; 23+ messages in thread
From: Chen Ridong @ 2025-08-28 12:56 UTC (permalink / raw)
To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong
From: Chen Ridong <chenridong@huawei.com>
Refactor the invalidate_cs_partition function to handle cpuset partition
invalidation when modifying cpuset.cpus. This refactoring also makes the
function reusable for handling cpuset.cpus.exclusive updates in subsequent
patches.
Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
kernel/cgroup/cpuset.c | 49 +++++++++++++++++++++++++++++++-----------
1 file changed, 36 insertions(+), 13 deletions(-)
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 5cfc53fe717c..71190f142700 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -2376,6 +2376,40 @@ static int parse_cpulist(const char *buf, struct cpumask *out_mask)
return 0;
}
+/**
+ * invalidate_cs_partition - Validate and mark the validity of a cpuset partition configuration
+ * @cs: The cpuset to validate
+ * This function checks multiple constraints for a cpuset partition configuration.
+ * If any check fails, it sets the appropriate error code in the cpuset and returns true.
+ * Mainly used to ensure correctness and consistency of partition configurations.
+ * Return: true if the configuration is invalid, false if valid.
+ */
+static bool invalidate_cs_partition(struct cpuset *cs)
+{
+ struct cpuset *parent = parent_cs(cs);
+
+ if (cs_is_member(cs))
+ return false;
+
+ if (cpumask_empty(cs->effective_xcpus)) {
+ cs->prs_err = PERR_INVCPUS;
+ return true;
+ }
+
+ if (prstate_housekeeping_conflict(cs->partition_root_state,
+ cs->effective_xcpus)) {
+ cs->prs_err = PERR_HKEEPING;
+ return true;
+ }
+
+ if (tasks_nocpu_error(parent, cs, cs->effective_xcpus)) {
+ cs->prs_err = PERR_NOCPUS;
+ return true;
+ }
+
+ return false;
+}
+
/**
* update_cpumask - update the cpus_allowed mask of a cpuset and all tasks in it
* @cs: the cpuset to consider
@@ -2405,19 +2439,8 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
compute_trialcs_excpus(trialcs, cs);
- if (old_prs) {
- if (is_partition_valid(cs) &&
- cpumask_empty(trialcs->effective_xcpus)) {
- invalidate = true;
- cs->prs_err = PERR_INVCPUS;
- } else if (prstate_housekeeping_conflict(old_prs, trialcs->effective_xcpus)) {
- invalidate = true;
- cs->prs_err = PERR_HKEEPING;
- } else if (tasks_nocpu_error(parent, cs, trialcs->effective_xcpus)) {
- invalidate = true;
- cs->prs_err = PERR_NOCPUS;
- }
- }
+ invalidate = invalidate_cs_partition(trialcs);
+ cs->prs_err = trialcs->prs_err;
/*
* Check all the descendants in update_cpumasks_hier() if
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH -next RFC 08/11] cpuset: refactor acpus_validate_change
2025-08-28 12:56 [PATCH -next RFC 00/11] Refactor cpus mask setting Chen Ridong
` (6 preceding siblings ...)
2025-08-28 12:56 ` [PATCH -next RFC 07/11] cpuset: refactor out invalidate_cs_partition Chen Ridong
@ 2025-08-28 12:56 ` Chen Ridong
2025-08-29 20:12 ` Waiman Long
2025-08-28 12:56 ` [PATCH -next RFC 09/11] cpuset: refactor partition_cpus_change Chen Ridong
` (2 subsequent siblings)
10 siblings, 1 reply; 23+ messages in thread
From: Chen Ridong @ 2025-08-28 12:56 UTC (permalink / raw)
To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong
From: Chen Ridong <chenridong@huawei.com>
Refactor acpus_validate_change to handle the special case where
cpuset.cpus can be set even when violating partition sibling CPU
exclusivity rules. This differs from the general validation logic in
validate_change. Add a wrapper function to properly handle this
exceptional case.
Since partition invalidation status can be determined by trialcs->prs_err,
the local variable 'bool invalidate' can be removed.
Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
kernel/cgroup/cpuset.c | 83 +++++++++++++++++++++++-------------------
1 file changed, 45 insertions(+), 38 deletions(-)
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 71190f142700..75ad18ab40ae 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -2410,43 +2410,11 @@ static bool invalidate_cs_partition(struct cpuset *cs)
return false;
}
-/**
- * update_cpumask - update the cpus_allowed mask of a cpuset and all tasks in it
- * @cs: the cpuset to consider
- * @trialcs: trial cpuset
- * @buf: buffer of cpu numbers written to this cpuset
- */
-static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
- const char *buf)
+static int acpus_validate_change(struct cpuset *cs, struct cpuset *trialcs,
+ struct tmpmasks *tmp)
{
int retval;
- struct tmpmasks tmp;
struct cpuset *parent = parent_cs(cs);
- bool invalidate = false;
- bool force = false;
- int old_prs = cs->partition_root_state;
-
- retval = parse_cpulist(buf, trialcs->cpus_allowed);
- if (retval < 0)
- return retval;
-
- /* Nothing to do if the cpus didn't change */
- if (cpumask_equal(cs->cpus_allowed, trialcs->cpus_allowed))
- return 0;
-
- if (alloc_tmpmasks(&tmp))
- return -ENOMEM;
-
- compute_trialcs_excpus(trialcs, cs);
-
- invalidate = invalidate_cs_partition(trialcs);
- cs->prs_err = trialcs->prs_err;
-
- /*
- * Check all the descendants in update_cpumasks_hier() if
- * effective_xcpus is to be changed.
- */
- force = !cpumask_equal(cs->effective_xcpus, trialcs->effective_xcpus);
retval = validate_change(cs, trialcs);
@@ -2461,7 +2429,7 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
* partition. However, any conflicting sibling partitions
* have to be marked as invalid too.
*/
- invalidate = true;
+ trialcs->prs_err = PERR_NOTEXCL;
rcu_read_lock();
cpuset_for_each_child(cp, css, parent) {
struct cpumask *xcpus = user_xcpus(trialcs);
@@ -2469,19 +2437,58 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
if (is_partition_valid(cp) &&
cpumask_intersects(xcpus, cp->effective_xcpus)) {
rcu_read_unlock();
- update_parent_effective_cpumask(cp, partcmd_invalidate, NULL, &tmp);
+ update_parent_effective_cpumask(cp, partcmd_invalidate, NULL, tmp);
rcu_read_lock();
}
}
rcu_read_unlock();
retval = 0;
}
+ return retval;
+}
+/**
+ * update_cpumask - update the cpus_allowed mask of a cpuset and all tasks in it
+ * @cs: the cpuset to consider
+ * @trialcs: trial cpuset
+ * @buf: buffer of cpu numbers written to this cpuset
+ */
+static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
+ const char *buf)
+{
+ int retval;
+ struct tmpmasks tmp;
+ bool force = false;
+ int old_prs = cs->partition_root_state;
+
+ retval = parse_cpulist(buf, trialcs->cpus_allowed);
if (retval < 0)
+ return retval;
+
+ /* Nothing to do if the cpus didn't change */
+ if (cpumask_equal(cs->cpus_allowed, trialcs->cpus_allowed))
+ return 0;
+
+ if (alloc_tmpmasks(&tmp))
+ return -ENOMEM;
+
+ compute_trialcs_excpus(trialcs, cs);
+
+ trialcs->prs_err = PERR_NONE;
+ if (acpus_validate_change(cs, trialcs, &tmp) < 0)
goto out_free;
+ /*
+ * Check all the descendants in update_cpumasks_hier() if
+ * effective_xcpus is to be changed.
+ */
+ force = !cpumask_equal(cs->effective_xcpus, trialcs->effective_xcpus);
+
+ invalidate_cs_partition(trialcs);
+ if (trialcs->prs_err)
+ cs->prs_err = trialcs->prs_err;
if (is_partition_valid(cs) ||
- (is_partition_invalid(cs) && !invalidate)) {
+ (is_partition_invalid(cs) && !trialcs->prs_err)) {
struct cpumask *xcpus = trialcs->effective_xcpus;
if (cpumask_empty(xcpus) && is_partition_invalid(cs))
@@ -2492,7 +2499,7 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
*/
if (is_remote_partition(cs))
remote_cpus_update(cs, NULL, xcpus, &tmp);
- else if (invalidate)
+ else if (trialcs->prs_err)
update_parent_effective_cpumask(cs, partcmd_invalidate,
NULL, &tmp);
else
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH -next RFC 09/11] cpuset: refactor partition_cpus_change
2025-08-28 12:56 [PATCH -next RFC 00/11] Refactor cpus mask setting Chen Ridong
` (7 preceding siblings ...)
2025-08-28 12:56 ` [PATCH -next RFC 08/11] cpuset: refactor acpus_validate_change Chen Ridong
@ 2025-08-28 12:56 ` Chen Ridong
2025-08-29 20:32 ` Waiman Long
2025-08-28 12:56 ` [PATCH -next RFC 10/11] cpuset: use parse_cpulist for setting cpus.exclusive Chen Ridong
2025-08-28 12:56 ` [PATCH -next RFC 11/11] cpuset: use partition_cpus_change for setting exclusive cpus Chen Ridong
10 siblings, 1 reply; 23+ messages in thread
From: Chen Ridong @ 2025-08-28 12:56 UTC (permalink / raw)
To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong
From: Chen Ridong <chenridong@huawei.com>
Refactor the partition_cpus_change function to handle both regular CPU
set updates and exclusive CPU modifications, either of which may trigger
partition state changes. This generalized function will also be utilized
for exclusive CPU updates in subsequent patches.
Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
kernel/cgroup/cpuset.c | 59 ++++++++++++++++++++++++++----------------
1 file changed, 36 insertions(+), 23 deletions(-)
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 75ad18ab40ae..e3eb87a33b12 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -2447,6 +2447,41 @@ static int acpus_validate_change(struct cpuset *cs, struct cpuset *trialcs,
return retval;
}
+/**
+ * partition_cpus_change - Handle partition state changes due to CPU mask updates
+ * @cs: The target cpuset being modified
+ * @trialcs: The trial cpuset containing proposed configuration changes
+ * @tmp: Temporary masks for intermediate calculations
+ *
+ * This function handles partition state transitions triggered by CPU mask changes.
+ * CPU modifications may cause a partition to be disabled or require state updates.
+ */
+static void partition_cpus_change(struct cpuset *cs, struct cpuset *trialcs,
+ struct tmpmasks *tmp)
+{
+ if (cs_is_member(cs))
+ return;
+
+ invalidate_cs_partition(trialcs);
+ if (trialcs->prs_err)
+ cs->prs_err = trialcs->prs_err;
+
+ if (is_remote_partition(cs)) {
+ if (trialcs->prs_err)
+ remote_partition_disable(cs, tmp);
+ else
+ remote_cpus_update(cs, trialcs->exclusive_cpus,
+ trialcs->effective_xcpus, tmp);
+ } else {
+ if (trialcs->prs_err)
+ update_parent_effective_cpumask(cs, partcmd_invalidate,
+ NULL, tmp);
+ else
+ update_parent_effective_cpumask(cs, partcmd_update,
+ trialcs->effective_xcpus, tmp);
+ }
+}
+
/**
* update_cpumask - update the cpus_allowed mask of a cpuset and all tasks in it
* @cs: the cpuset to consider
@@ -2483,29 +2518,7 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
*/
force = !cpumask_equal(cs->effective_xcpus, trialcs->effective_xcpus);
- invalidate_cs_partition(trialcs);
- if (trialcs->prs_err)
- cs->prs_err = trialcs->prs_err;
-
- if (is_partition_valid(cs) ||
- (is_partition_invalid(cs) && !trialcs->prs_err)) {
- struct cpumask *xcpus = trialcs->effective_xcpus;
-
- if (cpumask_empty(xcpus) && is_partition_invalid(cs))
- xcpus = trialcs->cpus_allowed;
-
- /*
- * Call remote_cpus_update() to handle valid remote partition
- */
- if (is_remote_partition(cs))
- remote_cpus_update(cs, NULL, xcpus, &tmp);
- else if (trialcs->prs_err)
- update_parent_effective_cpumask(cs, partcmd_invalidate,
- NULL, &tmp);
- else
- update_parent_effective_cpumask(cs, partcmd_update,
- xcpus, &tmp);
- }
+ partition_cpus_change(cs, trialcs, &tmp);
spin_lock_irq(&callback_lock);
cpumask_copy(cs->cpus_allowed, trialcs->cpus_allowed);
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH -next RFC 10/11] cpuset: use parse_cpulist for setting cpus.exclusive
2025-08-28 12:56 [PATCH -next RFC 00/11] Refactor cpus mask setting Chen Ridong
` (8 preceding siblings ...)
2025-08-28 12:56 ` [PATCH -next RFC 09/11] cpuset: refactor partition_cpus_change Chen Ridong
@ 2025-08-28 12:56 ` Chen Ridong
2025-08-28 12:56 ` [PATCH -next RFC 11/11] cpuset: use partition_cpus_change for setting exclusive cpus Chen Ridong
10 siblings, 0 replies; 23+ messages in thread
From: Chen Ridong @ 2025-08-28 12:56 UTC (permalink / raw)
To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong
From: Chen Ridong <chenridong@huawei.com>
Previous patches made parse_cpulist handle empty cpu mask input.
Now use this helper for exclusive cpus setting. Also, compute_trialcs_xcpus
can be called with empty cpus and handles it correctly.
Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
kernel/cgroup/cpuset.c | 25 +++++++++----------------
1 file changed, 9 insertions(+), 16 deletions(-)
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index e3eb87a33b12..774dabc86429 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -2556,27 +2556,20 @@ static int update_exclusive_cpumask(struct cpuset *cs, struct cpuset *trialcs,
bool force = false;
int old_prs = cs->partition_root_state;
- if (!*buf) {
- cpumask_clear(trialcs->exclusive_cpus);
- cpumask_clear(trialcs->effective_xcpus);
- } else {
- retval = cpulist_parse(buf, trialcs->exclusive_cpus);
- if (retval < 0)
- return retval;
- }
+ retval = parse_cpulist(buf, trialcs->exclusive_cpus);
+ if (retval < 0)
+ return retval;
/* Nothing to do if the CPUs didn't change */
if (cpumask_equal(cs->exclusive_cpus, trialcs->exclusive_cpus))
return 0;
- if (*buf) {
- /*
- * Reject the change if there is exclusive CPUs conflict with
- * the siblings.
- */
- if (compute_trialcs_excpus(trialcs, cs))
- return -EINVAL;
- }
+ /*
+ * Reject the change if there is exclusive CPUs conflict with
+ * the siblings.
+ */
+ if (compute_trialcs_excpus(trialcs, cs))
+ return -EINVAL;
/*
* Check all the descendants in update_cpumasks_hier() if
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH -next RFC 11/11] cpuset: use partition_cpus_change for setting exclusive cpus
2025-08-28 12:56 [PATCH -next RFC 00/11] Refactor cpus mask setting Chen Ridong
` (9 preceding siblings ...)
2025-08-28 12:56 ` [PATCH -next RFC 10/11] cpuset: use parse_cpulist for setting cpus.exclusive Chen Ridong
@ 2025-08-28 12:56 ` Chen Ridong
10 siblings, 0 replies; 23+ messages in thread
From: Chen Ridong @ 2025-08-28 12:56 UTC (permalink / raw)
To: longman, tj, hannes, mkoutny; +Cc: cgroups, linux-kernel, lujialin4, chenridong
From: Chen Ridong <chenridong@huawei.com>
Previous patches have refactored partition_cpus_change. Now replace the
exclusive cpus setting logic with this helper function.
Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
kernel/cgroup/cpuset.c | 29 ++---------------------------
1 file changed, 2 insertions(+), 27 deletions(-)
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 774dabc86429..950daa2d4b2b 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -2551,8 +2551,6 @@ static int update_exclusive_cpumask(struct cpuset *cs, struct cpuset *trialcs,
{
int retval;
struct tmpmasks tmp;
- struct cpuset *parent = parent_cs(cs);
- bool invalidate = false;
bool force = false;
int old_prs = cs->partition_root_state;
@@ -2584,32 +2582,9 @@ static int update_exclusive_cpumask(struct cpuset *cs, struct cpuset *trialcs,
if (alloc_tmpmasks(&tmp))
return -ENOMEM;
- if (old_prs) {
- if (cpumask_empty(trialcs->effective_xcpus)) {
- invalidate = true;
- cs->prs_err = PERR_INVCPUS;
- } else if (prstate_housekeeping_conflict(old_prs, trialcs->effective_xcpus)) {
- invalidate = true;
- cs->prs_err = PERR_HKEEPING;
- } else if (tasks_nocpu_error(parent, cs, trialcs->effective_xcpus)) {
- invalidate = true;
- cs->prs_err = PERR_NOCPUS;
- }
+ trialcs->prs_err = PERR_NONE;
+ partition_cpus_change(cs, trialcs, &tmp);
- if (is_remote_partition(cs)) {
- if (invalidate)
- remote_partition_disable(cs, &tmp);
- else
- remote_cpus_update(cs, trialcs->exclusive_cpus,
- trialcs->effective_xcpus, &tmp);
- } else if (invalidate) {
- update_parent_effective_cpumask(cs, partcmd_invalidate,
- NULL, &tmp);
- } else {
- update_parent_effective_cpumask(cs, partcmd_update,
- trialcs->effective_xcpus, &tmp);
- }
- }
spin_lock_irq(&callback_lock);
cpumask_copy(cs->exclusive_cpus, trialcs->exclusive_cpus);
cpumask_copy(cs->effective_xcpus, trialcs->effective_xcpus);
--
2.34.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH -next RFC 01/11] cpuset: move the root cpuset write check earlier
2025-08-28 12:56 ` [PATCH -next RFC 01/11] cpuset: move the root cpuset write check earlier Chen Ridong
@ 2025-08-29 19:21 ` Waiman Long
2025-08-30 1:11 ` Chen Ridong
0 siblings, 1 reply; 23+ messages in thread
From: Waiman Long @ 2025-08-29 19:21 UTC (permalink / raw)
To: Chen Ridong, tj, hannes, mkoutny
Cc: cgroups, linux-kernel, lujialin4, chenridong
On 8/28/25 8:56 AM, Chen Ridong wrote:
> From: Chen Ridong <chenridong@huawei.com>
>
> The 'cpus' or 'mems' lists of the top_cpuset cannot be modified.
> This check can be moved before acquiring any locks as a common code
> block to improve efficiency and maintainability.
>
> Signed-off-by: Chen Ridong <chenridong@huawei.com>
> ---
> kernel/cgroup/cpuset.c | 22 +++++++++-------------
> 1 file changed, 9 insertions(+), 13 deletions(-)
>
> diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
> index a78ccd11ce9b..7e6a40e361ea 100644
> --- a/kernel/cgroup/cpuset.c
> +++ b/kernel/cgroup/cpuset.c
> @@ -337,6 +337,11 @@ static inline bool cpuset_v2(void)
> cgroup_subsys_on_dfl(cpuset_cgrp_subsys);
> }
>
> +static inline bool cpuset_is_root(struct cpuset *cs)
> +{
> + return (cs == &top_cpuset);
> +}
> +
> /*
> * Cgroup v2 behavior is used on the "cpus" and "mems" control files when
> * on default hierarchy or when the cpuset_v2_mode flag is set by mounting
> @@ -2334,10 +2339,6 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
> bool force = false;
> int old_prs = cs->partition_root_state;
>
> - /* top_cpuset.cpus_allowed tracks cpu_active_mask; it's read-only */
> - if (cs == &top_cpuset)
> - return -EACCES;
> -
> /*
> * An empty cpus_allowed is ok only if the cpuset has no tasks.
> * Since cpulist_parse() fails on an empty mask, we special case
> @@ -2783,15 +2784,6 @@ static int update_nodemask(struct cpuset *cs, struct cpuset *trialcs,
> {
> int retval;
>
> - /*
> - * top_cpuset.mems_allowed tracks node_stats[N_MEMORY];
> - * it's read-only
> - */
> - if (cs == &top_cpuset) {
> - retval = -EACCES;
> - goto done;
> - }
> -
> /*
> * An empty mems_allowed is ok iff there are no tasks in the cpuset.
> * Since nodelist_parse() fails on an empty mask, we special case
> @@ -3257,6 +3249,10 @@ ssize_t cpuset_write_resmask(struct kernfs_open_file *of,
> struct cpuset *trialcs;
> int retval = -ENODEV;
>
> + /* root is read-only */
> + if (cpuset_is_root(cs))
> + return -EACCES;
> +
> buf = strstrip(buf);
> cpuset_full_lock();
> if (!is_cpuset_online(cs))
The (cs == &top_cpuset) check is pretty straight forward. So if the
cpuset_is_root() helper is only used once, I don't think we need a new
helper here.
Cheers,
Longman
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH -next RFC 06/11] cpuset: introduce cpus_excl_conflict and mems_excl_conflict helpers
2025-08-28 12:56 ` [PATCH -next RFC 06/11] cpuset: introduce cpus_excl_conflict and mems_excl_conflict helpers Chen Ridong
@ 2025-08-29 19:29 ` Waiman Long
2025-08-30 1:27 ` Chen Ridong
0 siblings, 1 reply; 23+ messages in thread
From: Waiman Long @ 2025-08-29 19:29 UTC (permalink / raw)
To: Chen Ridong, tj, hannes, mkoutny
Cc: cgroups, linux-kernel, lujialin4, chenridong
On 8/28/25 8:56 AM, Chen Ridong wrote:
> From: Chen Ridong <chenridong@huawei.com>
>
> This patch adds cpus_excl_conflict() and mems_excl_conflict() helper
> functions to improve code readability and maintainability. The exclusive
> conflict checking follows these rules:
>
> 1. If either cpuset has the 'exclusive' flag set, their user_xcpus must
> not have any overlap.
> 2. If both cpusets are non-exclusive, their 'cpuset.cpus.exclusive' values
> must not intersect.
Do you mean "both cpusets are exclusive"?
> 3. The 'cpuset.cpus' of one cpuset must not form a subset of another
> cpuset's 'cpuset.cpus.exclusive'.
>
> Signed-off-by: Chen Ridong <chenridong@huawei.com>
> ---
> kernel/cgroup/cpuset.c | 62 ++++++++++++++++++++++--------------------
> 1 file changed, 32 insertions(+), 30 deletions(-)
>
> diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
> index 5dd1e9552000..5cfc53fe717c 100644
> --- a/kernel/cgroup/cpuset.c
> +++ b/kernel/cgroup/cpuset.c
> @@ -584,6 +584,35 @@ static inline bool cpusets_are_exclusive(struct cpuset *cs1, struct cpuset *cs2)
> return true;
> }
>
> +static inline bool cpus_excl_conflict(struct cpuset *cs1, struct cpuset *cs2)
> +{
> + /* One is exclusive, they must be exclusive */
The comment is hard to understand. Basically, if one cpuset has
exclusive flag set (a v1 feature), they must be exclusive wrt each other.
> + if (is_cpu_exclusive(cs1) || is_cpu_exclusive(cs2))
> + return !cpusets_are_exclusive(cs1, cs2);
> +
> + /* Exclusive_cpus can not have intersects*/
Grammatical mistake, better wording - "exclusive_cpus cannot intersect"
> + if (cpumask_intersects(cs1->exclusive_cpus, cs2->exclusive_cpus))
> + return true;
> +
> + /* One cpus_allowed can not be a subset of another's cpuset.effective_cpus */
"cpus_allowed of one cpuset cannot be a subset of another cpuset's
exclusive_cpus"
> + if (!cpumask_empty(cs1->cpus_allowed) &&
> + cpumask_subset(cs1->cpus_allowed, cs2->exclusive_cpus))
> + return true;
> +
> + if (!cpumask_empty(cs2->cpus_allowed) &&
> + cpumask_subset(cs2->cpus_allowed, cs1->exclusive_cpus))
> + return true;
> +
> + return false;
> +}
> +
Cheers,
Longman
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH -next RFC 07/11] cpuset: refactor out invalidate_cs_partition
2025-08-28 12:56 ` [PATCH -next RFC 07/11] cpuset: refactor out invalidate_cs_partition Chen Ridong
@ 2025-08-29 19:56 ` Waiman Long
2025-08-30 1:33 ` Chen Ridong
0 siblings, 1 reply; 23+ messages in thread
From: Waiman Long @ 2025-08-29 19:56 UTC (permalink / raw)
To: Chen Ridong, tj, hannes, mkoutny
Cc: cgroups, linux-kernel, lujialin4, chenridong
On 8/28/25 8:56 AM, Chen Ridong wrote:
> From: Chen Ridong <chenridong@huawei.com>
>
> Refactor the invalidate_cs_partition function to handle cpuset partition
> invalidation when modifying cpuset.cpus. This refactoring also makes the
> function reusable for handling cpuset.cpus.exclusive updates in subsequent
> patches.
>
> Signed-off-by: Chen Ridong <chenridong@huawei.com>
> ---
> kernel/cgroup/cpuset.c | 49 +++++++++++++++++++++++++++++++-----------
> 1 file changed, 36 insertions(+), 13 deletions(-)
>
> diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
> index 5cfc53fe717c..71190f142700 100644
> --- a/kernel/cgroup/cpuset.c
> +++ b/kernel/cgroup/cpuset.c
> @@ -2376,6 +2376,40 @@ static int parse_cpulist(const char *buf, struct cpumask *out_mask)
> return 0;
> }
>
> +/**
> + * invalidate_cs_partition - Validate and mark the validity of a cpuset partition configuration
The function name has "invalidate", but the description uses validate.
It is confusing.
My suggestion
validate_partition - Check the validity of a cpuset partition
configuration
Return 0 if valid, a non-zero prs_errcode otherwise
Cheers,
Longman
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH -next RFC 08/11] cpuset: refactor acpus_validate_change
2025-08-28 12:56 ` [PATCH -next RFC 08/11] cpuset: refactor acpus_validate_change Chen Ridong
@ 2025-08-29 20:12 ` Waiman Long
2025-08-30 1:42 ` Chen Ridong
0 siblings, 1 reply; 23+ messages in thread
From: Waiman Long @ 2025-08-29 20:12 UTC (permalink / raw)
To: Chen Ridong, tj, hannes, mkoutny
Cc: cgroups, linux-kernel, lujialin4, chenridong
On 8/28/25 8:56 AM, Chen Ridong wrote:
> From: Chen Ridong <chenridong@huawei.com>
>
> Refactor acpus_validate_change to handle the special case where
> cpuset.cpus can be set even when violating partition sibling CPU
> exclusivity rules. This differs from the general validation logic in
> validate_change. Add a wrapper function to properly handle this
> exceptional case.
>
> Since partition invalidation status can be determined by trialcs->prs_err,
> the local variable 'bool invalidate' can be removed.
>
> Signed-off-by: Chen Ridong <chenridong@huawei.com>
> ---
> kernel/cgroup/cpuset.c | 83 +++++++++++++++++++++++-------------------
> 1 file changed, 45 insertions(+), 38 deletions(-)
>
> diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
> index 71190f142700..75ad18ab40ae 100644
> --- a/kernel/cgroup/cpuset.c
> +++ b/kernel/cgroup/cpuset.c
> @@ -2410,43 +2410,11 @@ static bool invalidate_cs_partition(struct cpuset *cs)
> return false;
> }
>
> -/**
> - * update_cpumask - update the cpus_allowed mask of a cpuset and all tasks in it
> - * @cs: the cpuset to consider
> - * @trialcs: trial cpuset
> - * @buf: buffer of cpu numbers written to this cpuset
> - */
> -static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
> - const char *buf)
> +static int acpus_validate_change(struct cpuset *cs, struct cpuset *trialcs,
> + struct tmpmasks *tmp)
What does "acpu" stand for? I suppose it means cpus_allowed. I will
suggest to use a more descriptive name even if it is longer. I did use
xcpus for exclusive_cpus, but 'x' is a seldomly used English alphabet
that can associate with exclusive_cpus rather easily, but 'a' is not.
Cheers,
Longman
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH -next RFC 09/11] cpuset: refactor partition_cpus_change
2025-08-28 12:56 ` [PATCH -next RFC 09/11] cpuset: refactor partition_cpus_change Chen Ridong
@ 2025-08-29 20:32 ` Waiman Long
2025-08-30 2:01 ` Chen Ridong
0 siblings, 1 reply; 23+ messages in thread
From: Waiman Long @ 2025-08-29 20:32 UTC (permalink / raw)
To: Chen Ridong, tj, hannes, mkoutny
Cc: cgroups, linux-kernel, lujialin4, chenridong
On 8/28/25 8:56 AM, Chen Ridong wrote:
> From: Chen Ridong <chenridong@huawei.com>
>
> Refactor the partition_cpus_change function to handle both regular CPU
> set updates and exclusive CPU modifications, either of which may trigger
> partition state changes. This generalized function will also be utilized
> for exclusive CPU updates in subsequent patches.
>
> Signed-off-by: Chen Ridong <chenridong@huawei.com>
> ---
> kernel/cgroup/cpuset.c | 59 ++++++++++++++++++++++++++----------------
> 1 file changed, 36 insertions(+), 23 deletions(-)
>
> diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
> index 75ad18ab40ae..e3eb87a33b12 100644
> --- a/kernel/cgroup/cpuset.c
> +++ b/kernel/cgroup/cpuset.c
> @@ -2447,6 +2447,41 @@ static int acpus_validate_change(struct cpuset *cs, struct cpuset *trialcs,
> return retval;
> }
>
> +/**
> + * partition_cpus_change - Handle partition state changes due to CPU mask updates
> + * @cs: The target cpuset being modified
> + * @trialcs: The trial cpuset containing proposed configuration changes
> + * @tmp: Temporary masks for intermediate calculations
> + *
> + * This function handles partition state transitions triggered by CPU mask changes.
> + * CPU modifications may cause a partition to be disabled or require state updates.
> + */
> +static void partition_cpus_change(struct cpuset *cs, struct cpuset *trialcs,
> + struct tmpmasks *tmp)
> +{
> + if (cs_is_member(cs))
> + return;
> +
> + invalidate_cs_partition(trialcs);
> + if (trialcs->prs_err)
> + cs->prs_err = trialcs->prs_err;
> +
> + if (is_remote_partition(cs)) {
> + if (trialcs->prs_err)
> + remote_partition_disable(cs, tmp);
> + else
> + remote_cpus_update(cs, trialcs->exclusive_cpus,
> + trialcs->effective_xcpus, tmp);
> + } else {
> + if (trialcs->prs_err)
> + update_parent_effective_cpumask(cs, partcmd_invalidate,
> + NULL, tmp);
> + else
> + update_parent_effective_cpumask(cs, partcmd_update,
> + trialcs->effective_xcpus, tmp);
> + }
> +}
> +
> /**
> * update_cpumask - update the cpus_allowed mask of a cpuset and all tasks in it
> * @cs: the cpuset to consider
> @@ -2483,29 +2518,7 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
> */
> force = !cpumask_equal(cs->effective_xcpus, trialcs->effective_xcpus);
>
> - invalidate_cs_partition(trialcs);
> - if (trialcs->prs_err)
> - cs->prs_err = trialcs->prs_err;
> -
> - if (is_partition_valid(cs) ||
> - (is_partition_invalid(cs) && !trialcs->prs_err)) {
> - struct cpumask *xcpus = trialcs->effective_xcpus;
> -
> - if (cpumask_empty(xcpus) && is_partition_invalid(cs))
> - xcpus = trialcs->cpus_allowed;
This if statement was added in commit 46c521bac592 ("cgroup/cpuset:
Enable invalid to valid local partition transition") that is missing in
your new partition_cpus_change() function. Have you run the
test_cpuset_prs.sh selftest with a patched kernel to make sure that
there is no test failure?
Cheers,
Longman
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH -next RFC 01/11] cpuset: move the root cpuset write check earlier
2025-08-29 19:21 ` Waiman Long
@ 2025-08-30 1:11 ` Chen Ridong
0 siblings, 0 replies; 23+ messages in thread
From: Chen Ridong @ 2025-08-30 1:11 UTC (permalink / raw)
To: Waiman Long, tj, hannes, mkoutny
Cc: cgroups, linux-kernel, lujialin4, chenridong
On 2025/8/30 3:21, Waiman Long wrote:
> On 8/28/25 8:56 AM, Chen Ridong wrote:
>> From: Chen Ridong <chenridong@huawei.com>
>>
>> The 'cpus' or 'mems' lists of the top_cpuset cannot be modified.
>> This check can be moved before acquiring any locks as a common code
>> block to improve efficiency and maintainability.
>>
>> Signed-off-by: Chen Ridong <chenridong@huawei.com>
>> ---
>> kernel/cgroup/cpuset.c | 22 +++++++++-------------
>> 1 file changed, 9 insertions(+), 13 deletions(-)
>>
>> diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
>> index a78ccd11ce9b..7e6a40e361ea 100644
>> --- a/kernel/cgroup/cpuset.c
>> +++ b/kernel/cgroup/cpuset.c
>> @@ -337,6 +337,11 @@ static inline bool cpuset_v2(void)
>> cgroup_subsys_on_dfl(cpuset_cgrp_subsys);
>> }
>> +static inline bool cpuset_is_root(struct cpuset *cs)
>> +{
>> + return (cs == &top_cpuset);
>> +}
>> +
>> /*
>> * Cgroup v2 behavior is used on the "cpus" and "mems" control files when
>> * on default hierarchy or when the cpuset_v2_mode flag is set by mounting
>> @@ -2334,10 +2339,6 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
>> bool force = false;
>> int old_prs = cs->partition_root_state;
>> - /* top_cpuset.cpus_allowed tracks cpu_active_mask; it's read-only */
>> - if (cs == &top_cpuset)
>> - return -EACCES;
>> -
>> /*
>> * An empty cpus_allowed is ok only if the cpuset has no tasks.
>> * Since cpulist_parse() fails on an empty mask, we special case
>> @@ -2783,15 +2784,6 @@ static int update_nodemask(struct cpuset *cs, struct cpuset *trialcs,
>> {
>> int retval;
>> - /*
>> - * top_cpuset.mems_allowed tracks node_stats[N_MEMORY];
>> - * it's read-only
>> - */
>> - if (cs == &top_cpuset) {
>> - retval = -EACCES;
>> - goto done;
>> - }
>> -
>> /*
>> * An empty mems_allowed is ok iff there are no tasks in the cpuset.
>> * Since nodelist_parse() fails on an empty mask, we special case
>> @@ -3257,6 +3249,10 @@ ssize_t cpuset_write_resmask(struct kernfs_open_file *of,
>> struct cpuset *trialcs;
>> int retval = -ENODEV;
>> + /* root is read-only */
>> + if (cpuset_is_root(cs))
>> + return -EACCES;
>> +
>> buf = strstrip(buf);
>> cpuset_full_lock();
>> if (!is_cpuset_online(cs))
>
> The (cs == &top_cpuset) check is pretty straight forward. So if the cpuset_is_root() helper is only
> used once, I don't think we need a new helper here.
>
> Cheers,
> Longman
Thanks you Longman,
There are several places where cs == &top_cpuset could be replaced with the helper function
cpuset_is_root. However, since this series focuses on refactoring the CPU settings, I did not make
those replacements. Would it be acceptable to submit a separate patch that introduces this helper?
--
Best regards,
Ridong
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH -next RFC 06/11] cpuset: introduce cpus_excl_conflict and mems_excl_conflict helpers
2025-08-29 19:29 ` Waiman Long
@ 2025-08-30 1:27 ` Chen Ridong
0 siblings, 0 replies; 23+ messages in thread
From: Chen Ridong @ 2025-08-30 1:27 UTC (permalink / raw)
To: Waiman Long, tj, hannes, mkoutny
Cc: cgroups, linux-kernel, lujialin4, chenridong
On 2025/8/30 3:29, Waiman Long wrote:
>
> On 8/28/25 8:56 AM, Chen Ridong wrote:
>> From: Chen Ridong <chenridong@huawei.com>
>>
>> This patch adds cpus_excl_conflict() and mems_excl_conflict() helper
>> functions to improve code readability and maintainability. The exclusive
>> conflict checking follows these rules:
>>
>> 1. If either cpuset has the 'exclusive' flag set, their user_xcpus must
>> not have any overlap.
>> 2. If both cpusets are non-exclusive, their 'cpuset.cpus.exclusive' values
>> must not intersect.
> Do you mean "both cpusets are exclusive"?
Thank you Longman.
I meant that neither of the two cpusets has the "exclusive" flag set. Case 1 already handles
situations where one or both cpusets have the exclusive flag enabled.
>> 3. The 'cpuset.cpus' of one cpuset must not form a subset of another
>> cpuset's 'cpuset.cpus.exclusive'.
>>
>> Signed-off-by: Chen Ridong <chenridong@huawei.com>
>> ---
>> kernel/cgroup/cpuset.c | 62 ++++++++++++++++++++++--------------------
>> 1 file changed, 32 insertions(+), 30 deletions(-)
>>
>> diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
>> index 5dd1e9552000..5cfc53fe717c 100644
>> --- a/kernel/cgroup/cpuset.c
>> +++ b/kernel/cgroup/cpuset.c
>> @@ -584,6 +584,35 @@ static inline bool cpusets_are_exclusive(struct cpuset *cs1, struct cpuset *cs2)
>> return true;
>> }
>> +static inline bool cpus_excl_conflict(struct cpuset *cs1, struct cpuset *cs2)
>> +{
>> + /* One is exclusive, they must be exclusive */
> The comment is hard to understand. Basically, if one cpuset has exclusive flag set (a v1 feature),
> they must be exclusive wrt each other.
My apologies for the earlier comment.
To quote your remark:
"Basically, if one cpuset has the exclusive flag set (a v1 feature), they must be exclusive with
wrt to each other."
That is exactly what I meant. Although cpuset v2 does not expose a user interface to explicitly set
the exclusive flag, the flag will still be set internally when a partition is enabled with
update_partition_exclusive_flag function.
>> + if (is_cpu_exclusive(cs1) || is_cpu_exclusive(cs2))
>> + return !cpusets_are_exclusive(cs1, cs2);
>> +
>> + /* Exclusive_cpus can not have intersects*/
> Grammatical mistake, better wording - "exclusive_cpus cannot intersect"
>> + if (cpumask_intersects(cs1->exclusive_cpus, cs2->exclusive_cpus))
>> + return true;
>> +
>> + /* One cpus_allowed can not be a subset of another's cpuset.effective_cpus */
> "cpus_allowed of one cpuset cannot be a subset of another cpuset's exclusive_cpus"
Will update with next version.
>> + if (!cpumask_empty(cs1->cpus_allowed) &&
>> + cpumask_subset(cs1->cpus_allowed, cs2->exclusive_cpus))
>> + return true;
>> +
>> + if (!cpumask_empty(cs2->cpus_allowed) &&
>> + cpumask_subset(cs2->cpus_allowed, cs1->exclusive_cpus))
>> + return true;
>> +
>> + return false;
>> +}
>> +
> Cheers,
> Longman
--
Best regards,
Ridong
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH -next RFC 07/11] cpuset: refactor out invalidate_cs_partition
2025-08-29 19:56 ` Waiman Long
@ 2025-08-30 1:33 ` Chen Ridong
0 siblings, 0 replies; 23+ messages in thread
From: Chen Ridong @ 2025-08-30 1:33 UTC (permalink / raw)
To: Waiman Long, tj, hannes, mkoutny
Cc: cgroups, linux-kernel, lujialin4, chenridong
On 2025/8/30 3:56, Waiman Long wrote:
>
> On 8/28/25 8:56 AM, Chen Ridong wrote:
>> From: Chen Ridong <chenridong@huawei.com>
>>
>> Refactor the invalidate_cs_partition function to handle cpuset partition
>> invalidation when modifying cpuset.cpus. This refactoring also makes the
>> function reusable for handling cpuset.cpus.exclusive updates in subsequent
>> patches.
>>
>> Signed-off-by: Chen Ridong <chenridong@huawei.com>
>> ---
>> kernel/cgroup/cpuset.c | 49 +++++++++++++++++++++++++++++++-----------
>> 1 file changed, 36 insertions(+), 13 deletions(-)
>>
>> diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
>> index 5cfc53fe717c..71190f142700 100644
>> --- a/kernel/cgroup/cpuset.c
>> +++ b/kernel/cgroup/cpuset.c
>> @@ -2376,6 +2376,40 @@ static int parse_cpulist(const char *buf, struct cpumask *out_mask)
>> return 0;
>> }
>> +/**
>> + * invalidate_cs_partition - Validate and mark the validity of a cpuset partition configuration
>
> The function name has "invalidate", but the description uses validate. It is confusing.
>
> My suggestion
>
> validate_partition - Check the validity of a cpuset partition configuration
>
> Return 0 if valid, a non-zero prs_errcode otherwise
>
> Cheers,
> Longman
Thank you Longman,
I originally used that name for a local value 'invalidated' within update_cpumask. However, since
subsequent patches have removed the invalidated, validate_partition would be a much more appropriate
name. I will update it accordingly.
--
Best regards,
Ridong
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH -next RFC 08/11] cpuset: refactor acpus_validate_change
2025-08-29 20:12 ` Waiman Long
@ 2025-08-30 1:42 ` Chen Ridong
0 siblings, 0 replies; 23+ messages in thread
From: Chen Ridong @ 2025-08-30 1:42 UTC (permalink / raw)
To: Waiman Long, tj, hannes, mkoutny
Cc: cgroups, linux-kernel, lujialin4, chenridong
On 2025/8/30 4:12, Waiman Long wrote:
> On 8/28/25 8:56 AM, Chen Ridong wrote:
>> From: Chen Ridong <chenridong@huawei.com>
>>
>> Refactor acpus_validate_change to handle the special case where
>> cpuset.cpus can be set even when violating partition sibling CPU
>> exclusivity rules. This differs from the general validation logic in
>> validate_change. Add a wrapper function to properly handle this
>> exceptional case.
>>
>> Since partition invalidation status can be determined by trialcs->prs_err,
>> the local variable 'bool invalidate' can be removed.
>>
>> Signed-off-by: Chen Ridong <chenridong@huawei.com>
>> ---
>> kernel/cgroup/cpuset.c | 83 +++++++++++++++++++++++-------------------
>> 1 file changed, 45 insertions(+), 38 deletions(-)
>>
>> diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
>> index 71190f142700..75ad18ab40ae 100644
>> --- a/kernel/cgroup/cpuset.c
>> +++ b/kernel/cgroup/cpuset.c
>> @@ -2410,43 +2410,11 @@ static bool invalidate_cs_partition(struct cpuset *cs)
>> return false;
>> }
>> -/**
>> - * update_cpumask - update the cpus_allowed mask of a cpuset and all tasks in it
>> - * @cs: the cpuset to consider
>> - * @trialcs: trial cpuset
>> - * @buf: buffer of cpu numbers written to this cpuset
>> - */
>> -static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
>> - const char *buf)
>> +static int acpus_validate_change(struct cpuset *cs, struct cpuset *trialcs,
>> + struct tmpmasks *tmp)
>
> What does "acpu" stand for? I suppose it means cpus_allowed. I will suggest to use a more
> descriptive name even if it is longer. I did use xcpus for exclusive_cpus, but 'x' is a seldomly
> used English alphabet that can associate with exclusive_cpus rather easily, but 'a' is not.
>
> Cheers,
> Longman
>
Thanks Longman,
The term acpus refers to cpus_allowed.
My original naming convention was intended as follows:
acpus --> cpus_allowed (allowed cpus)
ecpus --> effective_cpus
xcpus --> exclusive_cpus
excpus --> effective_xcpus
--
Best regards,
Ridong
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH -next RFC 09/11] cpuset: refactor partition_cpus_change
2025-08-29 20:32 ` Waiman Long
@ 2025-08-30 2:01 ` Chen Ridong
2025-09-02 13:30 ` Waiman Long
0 siblings, 1 reply; 23+ messages in thread
From: Chen Ridong @ 2025-08-30 2:01 UTC (permalink / raw)
To: Waiman Long, tj, hannes, mkoutny
Cc: cgroups, linux-kernel, lujialin4, chenridong
On 2025/8/30 4:32, Waiman Long wrote:
> On 8/28/25 8:56 AM, Chen Ridong wrote:
>> From: Chen Ridong <chenridong@huawei.com>
>>
>> Refactor the partition_cpus_change function to handle both regular CPU
>> set updates and exclusive CPU modifications, either of which may trigger
>> partition state changes. This generalized function will also be utilized
>> for exclusive CPU updates in subsequent patches.
>>
>> Signed-off-by: Chen Ridong <chenridong@huawei.com>
>> ---
>> kernel/cgroup/cpuset.c | 59 ++++++++++++++++++++++++++----------------
>> 1 file changed, 36 insertions(+), 23 deletions(-)
>>
>> diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
>> index 75ad18ab40ae..e3eb87a33b12 100644
>> --- a/kernel/cgroup/cpuset.c
>> +++ b/kernel/cgroup/cpuset.c
>> @@ -2447,6 +2447,41 @@ static int acpus_validate_change(struct cpuset *cs, struct cpuset *trialcs,
>> return retval;
>> }
>> +/**
>> + * partition_cpus_change - Handle partition state changes due to CPU mask updates
>> + * @cs: The target cpuset being modified
>> + * @trialcs: The trial cpuset containing proposed configuration changes
>> + * @tmp: Temporary masks for intermediate calculations
>> + *
>> + * This function handles partition state transitions triggered by CPU mask changes.
>> + * CPU modifications may cause a partition to be disabled or require state updates.
>> + */
>> +static void partition_cpus_change(struct cpuset *cs, struct cpuset *trialcs,
>> + struct tmpmasks *tmp)
>> +{
>> + if (cs_is_member(cs))
>> + return;
>> +
>> + invalidate_cs_partition(trialcs);
>> + if (trialcs->prs_err)
>> + cs->prs_err = trialcs->prs_err;
>> +
>> + if (is_remote_partition(cs)) {
>> + if (trialcs->prs_err)
>> + remote_partition_disable(cs, tmp);
>> + else
>> + remote_cpus_update(cs, trialcs->exclusive_cpus,
>> + trialcs->effective_xcpus, tmp);
>> + } else {
>> + if (trialcs->prs_err)
>> + update_parent_effective_cpumask(cs, partcmd_invalidate,
>> + NULL, tmp);
>> + else
>> + update_parent_effective_cpumask(cs, partcmd_update,
>> + trialcs->effective_xcpus, tmp);
>> + }
>> +}
>> +
>> /**
>> * update_cpumask - update the cpus_allowed mask of a cpuset and all tasks in it
>> * @cs: the cpuset to consider
>> @@ -2483,29 +2518,7 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
>> */
>> force = !cpumask_equal(cs->effective_xcpus, trialcs->effective_xcpus);
>> - invalidate_cs_partition(trialcs);
>> - if (trialcs->prs_err)
>> - cs->prs_err = trialcs->prs_err;
>> -
>> - if (is_partition_valid(cs) ||
>> - (is_partition_invalid(cs) && !trialcs->prs_err)) {
>> - struct cpumask *xcpus = trialcs->effective_xcpus;
>> -
>> - if (cpumask_empty(xcpus) && is_partition_invalid(cs))
>> - xcpus = trialcs->cpus_allowed;
>
> This if statement was added in commit 46c521bac592 ("cgroup/cpuset: Enable invalid to valid local
> partition transition") that is missing in your new partition_cpus_change() function. Have you run
> the test_cpuset_prs.sh selftest with a patched kernel to make sure that there is no test failure?
>
> Cheers,
> Longman
Thank you Longman,
I did run the self-test for every patch, and I appreciate the test script test_cpuset_prs.sh you
provided.
The trialcs->effective_xcpus will be updated using compute_trialcs_excpus, which was introduced in
Patch 4. The corresponding logic was then added in Patch 5:
- cpumask_and(excpus, user_xcpus(trialcs), parent->effective_xcpus);
+ /* trialcs is member, cpuset.cpus has no impact to excpus */
+ if (cs_is_member(cs))
+ cpumask_and(excpus, trialcs->exclusive_cpus,
+ parent->effective_xcpus);
+ else
+ cpumask_and(excpus, user_xcpus(trialcs), parent->effective_xcpus);
+
Therefore, as long as excpus is computed correctly, I believe this implementation can handle the
scenario appropriately.
--
Best regards,
Ridong
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH -next RFC 09/11] cpuset: refactor partition_cpus_change
2025-08-30 2:01 ` Chen Ridong
@ 2025-09-02 13:30 ` Waiman Long
0 siblings, 0 replies; 23+ messages in thread
From: Waiman Long @ 2025-09-02 13:30 UTC (permalink / raw)
To: Chen Ridong, Waiman Long, tj, hannes, mkoutny
Cc: cgroups, linux-kernel, lujialin4, chenridong
On 8/29/25 10:01 PM, Chen Ridong wrote:
>
> On 2025/8/30 4:32, Waiman Long wrote:
>> On 8/28/25 8:56 AM, Chen Ridong wrote:
>>> From: Chen Ridong <chenridong@huawei.com>
>>>
>>> Refactor the partition_cpus_change function to handle both regular CPU
>>> set updates and exclusive CPU modifications, either of which may trigger
>>> partition state changes. This generalized function will also be utilized
>>> for exclusive CPU updates in subsequent patches.
>>>
>>> Signed-off-by: Chen Ridong <chenridong@huawei.com>
>>> ---
>>> kernel/cgroup/cpuset.c | 59 ++++++++++++++++++++++++++----------------
>>> 1 file changed, 36 insertions(+), 23 deletions(-)
>>>
>>> diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
>>> index 75ad18ab40ae..e3eb87a33b12 100644
>>> --- a/kernel/cgroup/cpuset.c
>>> +++ b/kernel/cgroup/cpuset.c
>>> @@ -2447,6 +2447,41 @@ static int acpus_validate_change(struct cpuset *cs, struct cpuset *trialcs,
>>> return retval;
>>> }
>>> +/**
>>> + * partition_cpus_change - Handle partition state changes due to CPU mask updates
>>> + * @cs: The target cpuset being modified
>>> + * @trialcs: The trial cpuset containing proposed configuration changes
>>> + * @tmp: Temporary masks for intermediate calculations
>>> + *
>>> + * This function handles partition state transitions triggered by CPU mask changes.
>>> + * CPU modifications may cause a partition to be disabled or require state updates.
>>> + */
>>> +static void partition_cpus_change(struct cpuset *cs, struct cpuset *trialcs,
>>> + struct tmpmasks *tmp)
>>> +{
>>> + if (cs_is_member(cs))
>>> + return;
>>> +
>>> + invalidate_cs_partition(trialcs);
>>> + if (trialcs->prs_err)
>>> + cs->prs_err = trialcs->prs_err;
>>> +
>>> + if (is_remote_partition(cs)) {
>>> + if (trialcs->prs_err)
>>> + remote_partition_disable(cs, tmp);
>>> + else
>>> + remote_cpus_update(cs, trialcs->exclusive_cpus,
>>> + trialcs->effective_xcpus, tmp);
>>> + } else {
>>> + if (trialcs->prs_err)
>>> + update_parent_effective_cpumask(cs, partcmd_invalidate,
>>> + NULL, tmp);
>>> + else
>>> + update_parent_effective_cpumask(cs, partcmd_update,
>>> + trialcs->effective_xcpus, tmp);
>>> + }
>>> +}
>>> +
>>> /**
>>> * update_cpumask - update the cpus_allowed mask of a cpuset and all tasks in it
>>> * @cs: the cpuset to consider
>>> @@ -2483,29 +2518,7 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
>>> */
>>> force = !cpumask_equal(cs->effective_xcpus, trialcs->effective_xcpus);
>>> - invalidate_cs_partition(trialcs);
>>> - if (trialcs->prs_err)
>>> - cs->prs_err = trialcs->prs_err;
>>> -
>>> - if (is_partition_valid(cs) ||
>>> - (is_partition_invalid(cs) && !trialcs->prs_err)) {
>>> - struct cpumask *xcpus = trialcs->effective_xcpus;
>>> -
>>> - if (cpumask_empty(xcpus) && is_partition_invalid(cs))
>>> - xcpus = trialcs->cpus_allowed;
>> This if statement was added in commit 46c521bac592 ("cgroup/cpuset: Enable invalid to valid local
>> partition transition") that is missing in your new partition_cpus_change() function. Have you run
>> the test_cpuset_prs.sh selftest with a patched kernel to make sure that there is no test failure?
>>
>> Cheers,
>> Longman
> Thank you Longman,
>
> I did run the self-test for every patch, and I appreciate the test script test_cpuset_prs.sh you
> provided.
>
> The trialcs->effective_xcpus will be updated using compute_trialcs_excpus, which was introduced in
> Patch 4. The corresponding logic was then added in Patch 5:
>
> - cpumask_and(excpus, user_xcpus(trialcs), parent->effective_xcpus);
> + /* trialcs is member, cpuset.cpus has no impact to excpus */
> + if (cs_is_member(cs))
> + cpumask_and(excpus, trialcs->exclusive_cpus,
> + parent->effective_xcpus);
> + else
> + cpumask_and(excpus, user_xcpus(trialcs), parent->effective_xcpus);
> +
>
> Therefore, as long as excpus is computed correctly, I believe this implementation can handle the
> scenario appropriately.
It will be helpful to put down a note in the commit log that the missing
logic will be re-introduced in a subsequent patch.
Thanks,
Longman
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2025-09-02 13:30 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-28 12:56 [PATCH -next RFC 00/11] Refactor cpus mask setting Chen Ridong
2025-08-28 12:56 ` [PATCH -next RFC 01/11] cpuset: move the root cpuset write check earlier Chen Ridong
2025-08-29 19:21 ` Waiman Long
2025-08-30 1:11 ` Chen Ridong
2025-08-28 12:56 ` [PATCH -next RFC 02/11] cpuset: remove unused assignment to trialcs->partition_root_state Chen Ridong
2025-08-28 12:56 ` [PATCH -next RFC 03/11] cpuset: change return type of is_partition_[in]valid to bool Chen Ridong
2025-08-28 12:56 ` [PATCH -next RFC 04/11] cpuset: Refactor exclusive CPU mask computation logic Chen Ridong
2025-08-28 12:56 ` [PATCH -next RFC 05/11] cpuset: refactor CPU mask buffer parsing logic Chen Ridong
2025-08-28 12:56 ` [PATCH -next RFC 06/11] cpuset: introduce cpus_excl_conflict and mems_excl_conflict helpers Chen Ridong
2025-08-29 19:29 ` Waiman Long
2025-08-30 1:27 ` Chen Ridong
2025-08-28 12:56 ` [PATCH -next RFC 07/11] cpuset: refactor out invalidate_cs_partition Chen Ridong
2025-08-29 19:56 ` Waiman Long
2025-08-30 1:33 ` Chen Ridong
2025-08-28 12:56 ` [PATCH -next RFC 08/11] cpuset: refactor acpus_validate_change Chen Ridong
2025-08-29 20:12 ` Waiman Long
2025-08-30 1:42 ` Chen Ridong
2025-08-28 12:56 ` [PATCH -next RFC 09/11] cpuset: refactor partition_cpus_change Chen Ridong
2025-08-29 20:32 ` Waiman Long
2025-08-30 2:01 ` Chen Ridong
2025-09-02 13:30 ` Waiman Long
2025-08-28 12:56 ` [PATCH -next RFC 10/11] cpuset: use parse_cpulist for setting cpus.exclusive Chen Ridong
2025-08-28 12:56 ` [PATCH -next RFC 11/11] cpuset: use partition_cpus_change for setting exclusive cpus Chen Ridong
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).