cgroup/cpuset: Prevent leakage of isolated CPUs into sched domains

Isolated CPUs are not allowed to be used in a non-isolated partition.
The only exception is the top cpuset which is allowed to contain boot
time isolated CPUs.

Commit ccac8e8de9 ("cgroup/cpuset: Fix remote root partition creation
problem") introduces a simplified scheme of including only partition
roots in sched domain generation. However, it does not properly account
for this exception case. This can result in leakage of isolated CPUs
into a sched domain.

Fix it by making sure that isolated CPUs are excluded from the top
cpuset before generating sched domains.

Also update the way the boot time isolated CPUs are handled in
test_cpuset_prs.sh to make sure that those isolated CPUs are really
isolated instead of just skipping them in the tests.

Fixes: ccac8e8de9 ("cgroup/cpuset: Fix remote root partition creation problem")
Signed-off-by: Waiman Long <longman@redhat.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
This commit is contained in:
Waiman Long 2024-12-05 14:51:01 -05:00 committed by Tejun Heo
parent eb1dd15fb2
commit 9b496a8bbe
2 changed files with 28 additions and 15 deletions

View File

@ -885,6 +885,14 @@ static int generate_sched_domains(cpumask_var_t **domains,
*/ */
if (cgrpv2) { if (cgrpv2) {
for (i = 0; i < ndoms; i++) { for (i = 0; i < ndoms; i++) {
/*
* The top cpuset may contain some boot time isolated
* CPUs that need to be excluded from the sched domain.
*/
if (csa[i] == &top_cpuset)
cpumask_and(doms[i], csa[i]->effective_cpus,
housekeeping_cpumask(HK_TYPE_DOMAIN));
else
cpumask_copy(doms[i], csa[i]->effective_cpus); cpumask_copy(doms[i], csa[i]->effective_cpus);
if (dattr) if (dattr)
dattr[i] = SD_ATTR_INIT; dattr[i] = SD_ATTR_INIT;

View File

@ -86,15 +86,15 @@ echo "" > test/cpuset.cpus
# #
# If isolated CPUs have been reserved at boot time (as shown in # If isolated CPUs have been reserved at boot time (as shown in
# cpuset.cpus.isolated), these isolated CPUs should be outside of CPUs 0-7 # cpuset.cpus.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 # that will be used by this script for testing purpose. If not, some of
# the tests may fail incorrectly. These isolated CPUs will also be removed # the tests may fail incorrectly. These pre-isolated CPUs should stay in
# before being compared with the expected results. # an isolated state throughout the testing process for now.
# #
BOOT_ISOLCPUS=$(cat $CGROUP2/cpuset.cpus.isolated) BOOT_ISOLCPUS=$(cat $CGROUP2/cpuset.cpus.isolated)
if [[ -n "$BOOT_ISOLCPUS" ]] if [[ -n "$BOOT_ISOLCPUS" ]]
then then
[[ $(echo $BOOT_ISOLCPUS | sed -e "s/[,-].*//") -le 7 ]] && [[ $(echo $BOOT_ISOLCPUS | sed -e "s/[,-].*//") -le 8 ]] &&
skip_test "Pre-isolated CPUs ($BOOT_ISOLCPUS) overlap CPUs to be tested" skip_test "Pre-isolated CPUs ($BOOT_ISOLCPUS) overlap CPUs to be tested"
echo "Pre-isolated CPUs: $BOOT_ISOLCPUS" echo "Pre-isolated CPUs: $BOOT_ISOLCPUS"
fi fi
@ -683,15 +683,19 @@ check_isolcpus()
EXPECT_VAL2=$EXPECT_VAL EXPECT_VAL2=$EXPECT_VAL
fi fi
#
# Appending pre-isolated CPUs
# Even though CPU #8 isn't used for testing, it can't be pre-isolated
# to make appending those CPUs easier.
#
[[ -n "$BOOT_ISOLCPUS" ]] && {
EXPECT_VAL=${EXPECT_VAL:+${EXPECT_VAL},}${BOOT_ISOLCPUS}
EXPECT_VAL2=${EXPECT_VAL2:+${EXPECT_VAL2},}${BOOT_ISOLCPUS}
}
# #
# Check cpuset.cpus.isolated cpumask # Check cpuset.cpus.isolated cpumask
# #
if [[ -z "$BOOT_ISOLCPUS" ]]
then
ISOLCPUS=$(cat $ISCPUS)
else
ISOLCPUS=$(cat $ISCPUS | sed -e "s/,*$BOOT_ISOLCPUS//")
fi
[[ "$EXPECT_VAL2" != "$ISOLCPUS" ]] && { [[ "$EXPECT_VAL2" != "$ISOLCPUS" ]] && {
# Take a 50ms pause and try again # Take a 50ms pause and try again
pause 0.05 pause 0.05
@ -731,8 +735,6 @@ check_isolcpus()
fi fi
done done
[[ "$ISOLCPUS" = *- ]] && ISOLCPUS=${ISOLCPUS}$LASTISOLCPU [[ "$ISOLCPUS" = *- ]] && ISOLCPUS=${ISOLCPUS}$LASTISOLCPU
[[ -n "BOOT_ISOLCPUS" ]] &&
ISOLCPUS=$(echo $ISOLCPUS | sed -e "s/,*$BOOT_ISOLCPUS//")
[[ "$EXPECT_VAL" = "$ISOLCPUS" ]] [[ "$EXPECT_VAL" = "$ISOLCPUS" ]]
} }
@ -836,9 +838,12 @@ run_state_test()
# if available # if available
[[ -n "$ICPUS" ]] && { [[ -n "$ICPUS" ]] && {
check_isolcpus $ICPUS check_isolcpus $ICPUS
[[ $? -ne 0 ]] && test_fail $I "isolated CPU" \ [[ $? -ne 0 ]] && {
[[ -n "$BOOT_ISOLCPUS" ]] && ICPUS=${ICPUS},${BOOT_ISOLCPUS}
test_fail $I "isolated CPU" \
"Expect $ICPUS, get $ISOLCPUS instead" "Expect $ICPUS, get $ISOLCPUS instead"
} }
}
reset_cgroup_states reset_cgroup_states
# #
# Check to see if effective cpu list changes # Check to see if effective cpu list changes