* [PATCH v2 0/3] cgroup/cpuset: Fix some more bugs in cpuset partition code
@ 2026-10-30 19:06 Waiman Long
2026-10-30 19:06 ` [PATCH v2 1/3] cgroup/cpuset: Fix incorrect CPU accounting with parent's effective_xcpus expansion Waiman Long
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Waiman Long @ 2026-10-30 19:06 UTC (permalink / raw)
To: Ridong Chen, Tejun Heo, Johannes Weiner, Michal Koutný,
Shuah Khan
Cc: cgroups, linux-kernel, linux-kselftest, Guopeng Zhang,
Waiman Long
v2:
- Add two fix patches for problems reported by sashiko and Guopeng.
This is another series of 3 fix patches for bugs in cpuset partition
code.
Waiman Long (3):
cgroup/cpuset: Fix incorrect CPU accounting with parent's
effective_xcpus expansion
cgroup/cpuset: Recompute effective cpumask in update_cpumasks_hier()
after calling update_parent_effective_cpumask()
cgroup/cpuset: Do housekeeping check when isolated child with root
parent may get more xcpus
kernel/cgroup/cpuset.c | 32 ++++++++++++++++---
.../selftests/cgroup/test_cpuset_prs.sh | 25 +++++++++++++--
2 files changed, 51 insertions(+), 6 deletions(-)
--
2.56.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2 1/3] cgroup/cpuset: Fix incorrect CPU accounting with parent's effective_xcpus expansion
2026-10-30 19:06 [PATCH v2 0/3] cgroup/cpuset: Fix some more bugs in cpuset partition code Waiman Long
@ 2026-10-30 19:06 ` Waiman Long
2026-10-30 19:07 ` [PATCH v2 2/3] cgroup/cpuset: Recompute effective cpumask in update_cpumasks_hier() after calling update_parent_effective_cpumask() Waiman Long
2026-10-30 19:07 ` [PATCH v2 3/3] cgroup/cpuset: Do housekeeping check when isolated child with root parent may get more xcpus Waiman Long
2 siblings, 0 replies; 4+ messages in thread
From: Waiman Long @ 2026-10-30 19:06 UTC (permalink / raw)
To: Ridong Chen, Tejun Heo, Johannes Weiner, Michal Koutný,
Shuah Khan
Cc: cgroups, linux-kernel, linux-kselftest, Guopeng Zhang,
Waiman Long
Commit ec0254b9eb49 ("cgroup/cpuset: Release invalid isolated CPUs with
a shrunk root partition parent") fixes incorrect isolated_cpus accounting
when contraction of a parent's effective_xcpus can cause a child partition
to lose isolated CPUs. Expansion of parent's effective_cpus can also allow
a child partition to gain more effective_xcpus. However, the current code
doesn't handle this case correctly leading to incorrect effective_cpus
and isolated_cpus accounting. Fix that by looking for this possible
expansion of effective_xcpus and perform the proper accounting action.
New test cases are added to test this effective_xcpus expansion scenarios.
Reported-by: Guopeng Zhang <guopeng.zhang@linux.dev>
Link: https://lore.kernel.org/lkml/20261027123837.100909-1-guopeng.zhang@linux.dev
Signed-off-by: Waiman Long <longman@redhat.com>
---
kernel/cgroup/cpuset.c | 12 ++++++++++++
tools/testing/selftests/cgroup/test_cpuset_prs.sh | 15 +++++++++++++++
2 files changed, 27 insertions(+)
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 3219f927c35e..39c81a0a8ab9 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -2097,6 +2097,7 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd,
parent->effective_xcpus);
if (!cpumask_empty(tmp->addmask))
isolated_cpus_release(cs, tmp->addmask);
+ /* Expansion of parent's effective_xcpus is handled below */
}
if (nocpu) {
part_error = PERR_NOCPUS;
@@ -2106,11 +2107,22 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd,
parent->effective_xcpus);
} else if ((parent_prs == PRS_ISOLATED) &&
((old_prs == PRS_ROOT) || (old_prs == -PRS_ROOT))) {
+ /* Parent partition state changed to PRS_ISOLATED */
part_error = PERR_ISOPARENT;
if (old_prs == PRS_ROOT) {
cpumask_copy(tmp->addmask, cs->effective_xcpus);
adding = true;
}
+ } else if (is_partition_valid(cs) &&
+ !cpumask_equal(tmp->delmask, cs->effective_xcpus)) {
+ /*
+ * If there is an expansion of parent's effective_xcpus,
+ * we may take more xcpus from parent. The parent's
+ * effective_cpus should still have active CPUs or nocpu
+ * should have been set.
+ */
+ deleting = cpumask_andnot(tmp->delmask, tmp->delmask,
+ cs->effective_xcpus);
} else if (is_partition_invalid(cs)) {
struct cgroup_subsys_state *css;
struct cpuset *child;
diff --git a/tools/testing/selftests/cgroup/test_cpuset_prs.sh b/tools/testing/selftests/cgroup/test_cpuset_prs.sh
index 83ef6c781af3..844efdf029cd 100755
--- a/tools/testing/selftests/cgroup/test_cpuset_prs.sh
+++ b/tools/testing/selftests/cgroup/test_cpuset_prs.sh
@@ -531,6 +531,21 @@ TEST_MATRIX=(
" C1-4:P1 C3-4:P2 . . T:C4-6 . . . 0 A1:5-6|A2:4 A1:P1|A2:P2 4"
" C1-4:P1 C1-2:P2 . . T:C4-6 . . . 0 A1:4-6|A2:4-6 A1:P1|A2:P-2 ."
+ # The extra CPUs gained by a child partition when its parent expands the
+ # exclusive CPUs have to be taken away from the parent.
+ " C2-6:X2-5:P1 CX3-6:P1 \
+ . . X2-6 . . . 0 A1:2|A2:3-6|XA2:3-6 A1:P1|A2:P1 ."
+ " C2-6:X2-5:P1 CX3-6:P2 \
+ . . X2-6 . . . 0 A1:2|A2:3-6|XA2:3-6 A1:P1|A2:P2 3-6"
+
+ # Both expansion and contraction of parent's effective_xcpus will be
+ # correctly handled in child partition and the child can be invalidated
+ # if a populated parent could lose all its effective_cpus.
+ " C2-6:X2-5:P1 CX3,5-6:P2 \
+ . . X4-6 . . . 0 A1:4|A2:5-6|XA2:5-6 A1:P1|A2:P2 5-6"
+ " C2-6:X2-5:P1 CX3-6:P2 \
+ . . T:X4-6 . . . 0 A1:4-6|A2:4-6 A1:P1|A2:P-2 ."
+
#
# old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS
# ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ --------
--
2.56.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v2 2/3] cgroup/cpuset: Recompute effective cpumask in update_cpumasks_hier() after calling update_parent_effective_cpumask()
2026-10-30 19:06 [PATCH v2 0/3] cgroup/cpuset: Fix some more bugs in cpuset partition code Waiman Long
2026-10-30 19:06 ` [PATCH v2 1/3] cgroup/cpuset: Fix incorrect CPU accounting with parent's effective_xcpus expansion Waiman Long
@ 2026-10-30 19:07 ` Waiman Long
2026-10-30 19:07 ` [PATCH v2 3/3] cgroup/cpuset: Do housekeeping check when isolated child with root parent may get more xcpus Waiman Long
2 siblings, 0 replies; 4+ messages in thread
From: Waiman Long @ 2026-10-30 19:07 UTC (permalink / raw)
To: Ridong Chen, Tejun Heo, Johannes Weiner, Michal Koutný,
Shuah Khan
Cc: cgroups, linux-kernel, linux-kselftest, Guopeng Zhang,
Waiman Long
It is reported by sashiko that calling update_parent_effective_cpumask()
may clobber tmp->new_cpus when update_sibling_cpumasks() needs to be
called due to possible change in the parent's effective_cpus value.
Therefore the new effective cpumask has to be recomputed after calling
update_parent_effective_cpumask() to get a correct value back into
tmp->new_cpus.
Fixes: f0af1bfc27b5 ("cgroup/cpuset: Relax constraints to partition & cpus changes")
Signed-off-by: Waiman Long <longman@redhat.com>
---
kernel/cgroup/cpuset.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 39c81a0a8ab9..ed014ecb770c 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -2359,12 +2359,12 @@ static void update_cpumasks_hier(struct cpuset *cs, struct tmpmasks *tmp,
update_parent_effective_cpumask(cp, partcmd_update, NULL, tmp);
/*
* Capture current partition_root_state as it may have
- * changed. Recompute effective cpumask if changed.
+ * changed. Always recompute effective cpumask as tmp->new_cpus
+ * may be clobbered when update_sibling_cpumasks() is called
+ * within update_parent_effective_cpumask().
*/
new_prs = cp->partition_root_state;
- if (new_prs != old_prs) {
- compute_effective_cpumask(tmp->new_cpus, cp, parent);
- }
+ compute_effective_cpumask(tmp->new_cpus, cp, parent);
}
spin_lock_irq(&callback_lock);
--
2.56.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v2 3/3] cgroup/cpuset: Do housekeeping check when isolated child with root parent may get more xcpus
2026-10-30 19:06 [PATCH v2 0/3] cgroup/cpuset: Fix some more bugs in cpuset partition code Waiman Long
2026-10-30 19:06 ` [PATCH v2 1/3] cgroup/cpuset: Fix incorrect CPU accounting with parent's effective_xcpus expansion Waiman Long
2026-10-30 19:07 ` [PATCH v2 2/3] cgroup/cpuset: Recompute effective cpumask in update_cpumasks_hier() after calling update_parent_effective_cpumask() Waiman Long
@ 2026-10-30 19:07 ` Waiman Long
2 siblings, 0 replies; 4+ messages in thread
From: Waiman Long @ 2026-10-30 19:07 UTC (permalink / raw)
To: Ridong Chen, Tejun Heo, Johannes Weiner, Michal Koutný,
Shuah Khan
Cc: cgroups, linux-kernel, linux-kselftest, Guopeng Zhang,
Waiman Long
It is reported by sashiko and Guopeng that when an isolated child with
root parent gets more isolated CPUs from the expansion of the parent's
effective_xcpus, it is possible that all the active housekeeping CPUs
may be gone. So a prstate_housekeeping_conflict() should be performed
when that happens. Add the check to make sure that we can't exhaust
all the active housekeeping CPUs.
Test cases are added to the NOHZ_FULL_TEST_MATRIX of test_cpuset_prs.sh
to test that.
Reported-by: Guopeng Zhang <guopeng.zhang@linux.dev>
Link: https://lore.kernel.org/lkml/ed6fecb4-38e9-4a73-8c1a-7bdd80175a69@linux.dev
Fixes: e2ffe502ba45 ("cgroup/cpuset: Add cpuset.cpus.exclusive for v2")
Signed-off-by: Waiman Long <longman@redhat.com>
---
kernel/cgroup/cpuset.c | 18 +++++++++++++++---
.../selftests/cgroup/test_cpuset_prs.sh | 10 ++++++++--
2 files changed, 23 insertions(+), 5 deletions(-)
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index ed014ecb770c..6e136888fc8e 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -2119,10 +2119,22 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd,
* If there is an expansion of parent's effective_xcpus,
* we may take more xcpus from parent. The parent's
* effective_cpus should still have active CPUs or nocpu
- * should have been set.
+ * should have been set. We also need to do a
+ * housekeeping check for an isolated child with root
+ * parent to make sure that it won't exhaust all the
+ * active housekeeping CPUs.
*/
- deleting = cpumask_andnot(tmp->delmask, tmp->delmask,
- cs->effective_xcpus);
+ cpumask_andnot(tmp->addmask, cs->effective_xcpus, tmp->delmask);
+ if ((parent_prs == PRS_ROOT) && (old_prs == PRS_ISOLATED) &&
+ prstate_housekeeping_conflict(old_prs, parent_prs,
+ tmp->delmask, tmp->addmask)) {
+ adding = cpumask_and(tmp->addmask, cs->effective_xcpus,
+ tmp->delmask);
+ part_error = PERR_HKEEPING;
+ } else {
+ deleting = cpumask_andnot(tmp->delmask, tmp->delmask,
+ cs->effective_xcpus);
+ }
} else if (is_partition_invalid(cs)) {
struct cgroup_subsys_state *css;
struct cpuset *child;
diff --git a/tools/testing/selftests/cgroup/test_cpuset_prs.sh b/tools/testing/selftests/cgroup/test_cpuset_prs.sh
index 844efdf029cd..bdca6c471f87 100755
--- a/tools/testing/selftests/cgroup/test_cpuset_prs.sh
+++ b/tools/testing/selftests/cgroup/test_cpuset_prs.sh
@@ -137,7 +137,8 @@ LAST_PRESENT_CPU=$(cat /sys/devices/system/cpu/present | sed -e "s/.*[,-]//")
# If isolated CPUs have been reserved at boot time (as shown in
# /sys/devices/system/cpu/isolated), these isolated CPUs should be outside of
# CPUs 0-8 that will be used by this script for testing purpose. If not, some
-# of the tests may fail incorrectly.
+# of the tests may fail incorrectly. The first boot isolated CPU should be
+# 10 or above.
#
# The current set of isolated CPUs (as shown in cpuset.cpus.isolated) should
# be the same as the boot value. If not, wait a bit and retry again just in
@@ -156,7 +157,7 @@ TEST_ISOLCPUS=
[[ -n "$BOOT_ISOLCPUS" ]] && {
FIRST_ISOLCPUS=$(echo $BOOT_ISOLCPUS | sed -e "s/[,-].*//")
echo "Boot isolated CPUs: $BOOT_ISOLCPUS"
- [[ $FIRST_ISOLCPUS -le 8 ]] &&
+ [[ $FIRST_ISOLCPUS -le 9 ]] &&
skip_test "Boot isolated CPUs overlap CPUs to be tested"
}
@@ -602,6 +603,7 @@ ISOLCPUS_TEST_MATRIX=(
)
# Test matrix to be run when boot time nohz_full CPUs cover all CPUs except CPUs 0-7
+# This also means that CPU 8 is available and is a nohz_full CPU.
NOHZ_FULL_TEST_MATRIX=(
# old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS
# ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ --------
@@ -610,6 +612,10 @@ NOHZ_FULL_TEST_MATRIX=(
" C2-7:P2 . . . C0-4 . . . 0 A1:0-4 A1:P2 0-4"
" C1-7:P2 C5-7:P2 . . . . . C0:P2 0 A1:1-4|A2:5-7|B1:0
A1:P2|A2:P2|B1:P-2 1-7"
+ # An isolated child partition cannot grow to take over the last
+ # housekeeping CPU when its parent expands the exclusive CPUs.
+ " C0-8:X1-8:P1 CX0-8:P2 . . X0-7 . . . 0 A1:0-7|A2:0-7 A1:P1|A2:P-2 ."
+ " C0-8:X0-6:P1 CX0-8:P2 . . X2-8 . . . 0 A1:|A2:2-8 A1:P1|A2:P2 2-8"
)
#
--
2.56.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-10-30 19:07 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-30 19:06 [PATCH v2 0/3] cgroup/cpuset: Fix some more bugs in cpuset partition code Waiman Long
2026-10-30 19:06 ` [PATCH v2 1/3] cgroup/cpuset: Fix incorrect CPU accounting with parent's effective_xcpus expansion Waiman Long
2026-10-30 19:07 ` [PATCH v2 2/3] cgroup/cpuset: Recompute effective cpumask in update_cpumasks_hier() after calling update_parent_effective_cpumask() Waiman Long
2026-10-30 19:07 ` [PATCH v2 3/3] cgroup/cpuset: Do housekeeping check when isolated child with root parent may get more xcpus Waiman Long
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.