[PATCH 14/17] cgroup/cpuset: Publish cpus_allowed before partition updates

From: Guopeng Zhang

Date: Thu Aug 20 2026 - 08:46:47 EST


From: Guopeng Zhang <zhangguopeng@xxxxxxxxxx>

update_cpumask() calls partition_cpus_change() before copying the new
cpus_allowed mask. A remote partition update can propagate through an
ancestor and revisit the cpuset while the old mask is still visible. The
second visit then adds back CPUs that the first visit released, leaving
them allocated after the cpuset is removed.

Copy cpus_allowed before partition_cpus_change(). All checks and
allocations that can fail have completed by this point, and cpuset_mutex
remains held for the rest of the update, so the early copy needs no
rollback. Keep effective_xcpus unchanged until afterward so the partition
code can still calculate the old-to-new difference.

Fixes: f62a5d39368e ("cgroup/cpuset: Remove remote_partition_check() & make update_cpumasks_hier() handle remote partition")
Signed-off-by: Guopeng Zhang <zhangguopeng@xxxxxxxxxx>
---
kernel/cgroup/cpuset.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index b3e749ede7d1..9e13fc962f41 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -2555,10 +2555,17 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
*/
force = !cpumask_equal(cs->effective_xcpus, trialcs->effective_xcpus);

+ /*
+ * remote_cpus_update() can propagate through an ancestor and revisit
+ * this cpuset. Make sure that it sees the new configured CPU mask.
+ */
+ spin_lock_irq(&callback_lock);
+ cpumask_copy(cs->cpus_allowed, trialcs->cpus_allowed);
+ spin_unlock_irq(&callback_lock);
+
partition_cpus_change(cs, trialcs, &tmp);

spin_lock_irq(&callback_lock);
- cpumask_copy(cs->cpus_allowed, trialcs->cpus_allowed);
cpumask_copy(cs->effective_xcpus, trialcs->effective_xcpus);
if ((old_prs > 0) && !is_partition_valid(cs))
reset_partition_data(cs);
--
2.43.0