[PATCH 12/17] cgroup/cpuset: Invalidate children outside the new CPU mask

From: Guopeng Zhang

Date: Thu Aug 20 2026 - 08:45:59 EST


From: Guopeng Zhang <zhangguopeng@xxxxxxxxxx>

When cpuset.cpus changes, compute_partition_effective_cpumask() builds a
new exclusive mask but checks child partitions against
cs->effective_xcpus. That field still contains the old mask, so a child
that no longer fits can remain valid.

Use new_xcpus for the check. A later partcmd_update() may revisit the
newly invalid child. Report PERR_INVCPUS if the child CPUs are outside
the parent effective exclusive mask so that this visit does not make the
child valid again.

Fixes: 0c7f293efc87 ("cgroup/cpuset: Add cpuset.cpus.exclusive.effective for v2")
Signed-off-by: Guopeng Zhang <zhangguopeng@xxxxxxxxxx>
---
kernel/cgroup/cpuset.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index b9faadf4af6d..b3e749ede7d1 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -1987,12 +1987,16 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd,
adding = cpumask_and(tmp->addmask,
cs->effective_xcpus,
parent->effective_xcpus);
- } else if (is_partition_invalid(cs) && !cpumask_empty(xcpus) &&
- cpumask_subset(xcpus, parent->effective_xcpus)) {
+ } else if (is_partition_invalid(cs) && !cpumask_empty(xcpus)) {
struct cgroup_subsys_state *css;
struct cpuset *child;
bool exclusive = true;

+ if (!cpumask_subset(xcpus, parent->effective_xcpus)) {
+ part_error = PERR_INVCPUS;
+ goto write_error;
+ }
+
/*
* Convert invalid partition to valid has to
* pass the cpu exclusivity test.
@@ -2144,7 +2148,7 @@ static void compute_partition_effective_cpumask(struct cpuset *cs,
WARN_ON_ONCE(is_remote_partition(child));
WRITE_ONCE(child->prs_err, 0);
if (!cpumask_subset(child->effective_xcpus,
- cs->effective_xcpus))
+ new_xcpus))
WRITE_ONCE(child->prs_err, PERR_INVCPUS);
else if (populated &&
cpumask_subset(new_ecpus, child->effective_xcpus))
--
2.43.0