Thread (9 messages) 9 messages, 1 author, 23d ago

[PATCH 4/8] rteval: Re-enable cpuset overlap tests for the new behavior

flat view
COLD23d

From: John Kacur <jkacur@redhat.com>
Date: 2026-09-22 22:26:34
Subsystem: the rest · Maintainer: Linus Torvalds

Tests 2, 5, and 8 in the cpuset integration suite were skipped pending
the measurement/load overlap design decision. Re-enable them for the
new behavior:

- Test 2 (same CPUs, no housekeeping): without --measurement-member,
  assert rteval exits non-zero and the error points to
  --measurement-member; with --measurement-member, assert exit 0 and
  partition=member.
- Test 5 (housekeeping without isolcpus): without --measurement-member,
  assert early non-zero exit on the default overlap; with
  --measurement-member, assert exit 0 and the housekeeping cpuset is
  created.
- Test 8 (--measurement-run-on-isolcpus): confine loads to the
  non-isolated CPUs so measurement (isolcpus) and loads are disjoint,
  keeping the measurement cpuset an isolated partition; assert exit 0.
  Still skips when no isolcpus are configured.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: John Kacur <jkacur@redhat.com>
---
 tests/cpusets/test-cpusets.sh | 212 ++++++++++++++++++++--------------
 1 file changed, 127 insertions(+), 85 deletions(-)
diff --git a/tests/cpusets/test-cpusets.sh b/tests/cpusets/test-cpusets.sh
index 5e1293532aca..39f837c177ae 100755
--- a/tests/cpusets/test-cpusets.sh
+++ b/tests/cpusets/test-cpusets.sh
@@ -208,38 +208,42 @@ test_prerequisites() {
 
 test_same_cpus_no_housekeeping() {
     ((TESTS_RUN++)) || true
-    print_test "Same CPUs - No Housekeeping (Measurement Cpuset Only)"
+    print_test "Same CPUs - Overlap Handling (isolated fails, --measurement-member works)"
 
     cleanup_cpusets
 
-    # TODO: Temporarily skipped pending a design decision (see below).
-    # This runs measurement and loads on the SAME CPUs. The measurement cpuset
-    # is created as an isolated partition, which removes those CPUs from the root
-    # cgroup; the taskset-bound loads then cannot run there and kcompile fails,
-    # so rteval exits non-zero. (This test currently does not check rteval's exit
-    # code, so it silently "passes" today.) The fix - the measurement cpuset
-    # partition type / load CPU placement when measurement and loads overlap -
-    # is still under discussion. Re-enable (and add an rteval exit-code check)
-    # once that is resolved.
-    print_info "SKIPPED: pending design decision on measurement cpuset partition/overlap behavior"
-    ((TESTS_PASSED++)) || true
-    return 0
-
     local cpus=$(get_test_cpus)
     local msr_cpus=$(echo $cpus | awk '{print $2}')
 
-    print_info "Running: $RTEVAL_CMD --cpusets --measurement-cpulist $msr_cpus --loads-cpulist $msr_cpus -d $TEST_DURATION"
+    local all_good=true
 
-    # Run rteval in background
-    timeout 60s $RTEVAL_CMD --cpusets --measurement-cpulist "$msr_cpus" --loads-cpulist "$msr_cpus" -d "$TEST_DURATION" >> "$LOG_FILE" 2>&1 &
+    # Flavor A: overlap with the default isolated measurement partition must
+    # fail early, because isolating those CPUs would leave the taskset loads
+    # with nowhere to run.
+    print_info "Running (expect early exit): $RTEVAL_CMD --cpusets --measurement-cpulist $msr_cpus --loads-cpulist $msr_cpus -d $TEST_DURATION"
+    if timeout 60s $RTEVAL_CMD --cpusets --measurement-cpulist "$msr_cpus" --loads-cpulist "$msr_cpus" -d "$TEST_DURATION" >> "$LOG_FILE" 2>&1; then
+        print_fail "rteval succeeded, but overlap with an isolated measurement partition should fail early"
+        all_good=false
+    else
+        print_info "rteval exited non-zero on overlap: OK"
+        if grep -q -- "--measurement-member" "$LOG_FILE" 2>/dev/null; then
+            print_info "Error message points to --measurement-member: OK"
+        else
+            print_fail "Overlap error message missing guidance"
+            all_good=false
+        fi
+    fi
+
+    cleanup_cpusets
+
+    # Flavor B: the same overlap with --measurement-member co-locates loads and
+    # measurement on a member partition and succeeds.
+    print_info "Running (expect success): $RTEVAL_CMD --cpusets --measurement-member --measurement-cpulist $msr_cpus --loads-cpulist $msr_cpus -d $TEST_DURATION"
+    timeout 60s $RTEVAL_CMD --cpusets --measurement-member --measurement-cpulist "$msr_cpus" --loads-cpulist "$msr_cpus" -d "$TEST_DURATION" >> "$LOG_FILE" 2>&1 &
     local rteval_pid=$!
 
-    # Wait for cpusets to be created
     sleep 2
 
-    # Check during execution
-    local all_good=true
-
     if check_cpuset_exists "rteval_measurement"; then
         print_info "rteval_measurement cpuset created: OK"
     else
@@ -247,31 +251,22 @@ test_same_cpus_no_housekeeping() {
         all_good=false
     fi
 
-    if ! check_cpuset_exists "rteval_loads"; then
-        print_info "No rteval_loads cpuset (loads use taskset): OK"
-    else
-        print_fail "Unexpected rteval_loads cpuset found"
-        all_good=false
-    fi
-
-    if check_cpuset_cpus "rteval_measurement" "$msr_cpus"; then
-        print_info "Measurement CPU assignment correct: OK"
+    if check_cpuset_partition "rteval_measurement" "member"; then
+        print_info "Partition type is 'member': OK"
     else
-        print_fail "Measurement CPU assignment incorrect"
+        print_fail "Partition type is not 'member'"
         all_good=false
     fi
 
-    if check_cpuset_partition "rteval_measurement" "isolated"; then
-        print_info "Partition type is 'isolated': OK"
+    wait $rteval_pid
+    local rc=$?
+    if [ "$rc" -eq 0 ]; then
+        print_info "rteval exited 0 with --measurement-member: OK"
     else
-        print_fail "Partition type is not 'isolated'"
+        print_fail "rteval exited $rc with --measurement-member (expected 0)"
         all_good=false
     fi
 
-    # Wait for rteval to finish
-    wait $rteval_pid
-
-    # Check cleanup
     sleep 1
     if check_no_cpusets; then
         print_info "Cleanup successful: OK"
@@ -282,9 +277,9 @@ test_same_cpus_no_housekeeping() {
     fi
 
     if [ "$all_good" = true ]; then
-        print_pass "Measurement cpuset test"
+        print_pass "Same-CPU overlap handling test"
     else
-        print_fail "Measurement cpuset test"
+        print_fail "Same-CPU overlap handling test"
     fi
 }
 
@@ -439,18 +434,6 @@ test_housekeeping_without_isolcpus() {
 
     cleanup_cpusets
 
-    # TODO: Temporarily skipped pending a design decision.
-    # With '--cpusets --housekeeping' and no explicit --measurement-cpulist,
-    # the measurement cpuset defaults to all non-housekeeping CPUs as an
-    # isolated partition, which removes them from the root cgroup. The
-    # taskset-bound loads then have nowhere to run and kcompile fails, so
-    # rteval exits non-zero. The fix (measurement cpuset partition type /
-    # load CPU placement when measurement and loads overlap) is still under
-    # discussion. Re-enable this test once that is resolved.
-    print_info "SKIPPED: pending design decision on measurement cpuset partition/overlap behavior"
-    ((TESTS_PASSED++)) || true
-    return 0
-
     # Check if system has isolcpus
     local isolated=$(cat /sys/devices/system/cpu/isolated 2>/dev/null || echo "")
     print_info "System isolated CPUs: ${isolated:-none}"
@@ -458,22 +441,65 @@ test_housekeeping_without_isolcpus() {
     local cpus=$(get_test_cpus)
     local hk_cpus=$(echo $cpus | awk '{print $1}')
 
-    print_info "Running: $RTEVAL_CMD --cpusets --housekeeping $hk_cpus -d $TEST_DURATION"
+    local all_good=true
 
-    # This should succeed even if housekeeping CPUs are not in isolcpus
+    # Flavor A: with only --housekeeping, measurement and loads both default to
+    # the non-housekeeping CPUs, so the isolated measurement partition overlaps
+    # the loads and rteval must fail early.
+    print_info "Running (expect early exit): $RTEVAL_CMD --cpusets --housekeeping $hk_cpus -d $TEST_DURATION"
     if timeout 60s $RTEVAL_CMD --cpusets --housekeeping "$hk_cpus" -d "$TEST_DURATION" >> "$LOG_FILE" 2>&1; then
-        print_info "rteval succeeded with housekeeping without isolcpus requirement: OK"
-        sleep 1
+        print_fail "rteval succeeded, but default overlap with an isolated measurement partition should fail early"
+        all_good=false
+    else
+        print_info "rteval exited non-zero on default overlap: OK"
+    fi
 
-        if check_no_cpusets; then
-            print_info "Cleanup successful: OK"
-            print_pass "Housekeeping without isolcpus test"
-        else
-            print_fail "Cpusets not cleaned up"
-            cleanup_cpusets
-        fi
+    cleanup_cpusets
+
+    # Flavor B: adding --measurement-member co-locates loads and measurement on
+    # the non-housekeeping CPUs, so housekeeping without isolcpus succeeds.
+    print_info "Running (expect success): $RTEVAL_CMD --cpusets --housekeeping $hk_cpus --measurement-member -d $TEST_DURATION"
+    timeout 60s $RTEVAL_CMD --cpusets --housekeeping "$hk_cpus" --measurement-member -d "$TEST_DURATION" >> "$LOG_FILE" 2>&1 &
+    local rteval_pid=$!
+
+    sleep 2
+
+    if check_cpuset_exists "rteval_housekeeping"; then
+        print_info "rteval_housekeeping cpuset created (no isolcpus required): OK"
     else
-        print_fail "rteval failed with housekeeping (should work with cpusets)"
+        print_fail "rteval_housekeeping cpuset not created"
+        all_good=false
+    fi
+
+    if check_cpuset_cpus "rteval_housekeeping" "$hk_cpus"; then
+        print_info "Housekeeping CPU assignment correct: OK"
+    else
+        print_fail "Housekeeping CPU assignment incorrect"
+        all_good=false
+    fi
+
+    wait $rteval_pid
+    local rc=$?
+    if [ "$rc" -eq 0 ]; then
+        print_info "rteval exited 0 with housekeeping + --measurement-member: OK"
+    else
+        print_fail "rteval exited $rc (expected 0)"
+        all_good=false
+    fi
+
+    sleep 1
+    if check_no_cpusets; then
+        print_info "Cleanup successful: OK"
+    else
+        print_fail "Cpusets not cleaned up"
+        all_good=false
+        cleanup_cpusets
+    fi
+
+    if [ "$all_good" = true ]; then
+        print_pass "Housekeeping without isolcpus test"
+    else
+        print_fail "Housekeeping without isolcpus test"
     fi
 }
 
@@ -545,20 +571,10 @@ test_cleanup_on_interrupt() {
 
 test_measurement_run_on_isolcpus() {
     ((TESTS_RUN++)) || true
-    print_test "Measurement Run on isolcpus Flag"
+    print_test "Measurement Run on isolcpus Flag (disjoint loads)"
 
     cleanup_cpusets
 
-    # TODO: Temporarily skipped pending a design decision.
-    # On hosts WITH isolcpus this shares the same unresolved issue as tests 2
-    # and 5: the isolated measurement cpuset (affinity + isolcpus) removes its
-    # CPUs from the root cgroup, so taskset-bound loads on the affinity subset
-    # fail and rteval exits non-zero. Re-enable once the measurement cpuset
-    # partition type / load CPU placement (overlap) design decision is made.
-    print_info "SKIPPED: pending design decision on measurement cpuset partition/overlap behavior"
-    ((TESTS_PASSED++)) || true
-    return 0
-
     # Check if system has isolcpus
     local isolated=$(cat /sys/devices/system/cpu/isolated 2>/dev/null || echo "")
     if [ -z "$isolated" ]; then
@@ -569,34 +585,60 @@ test_measurement_run_on_isolcpus() {
 
     print_info "System isolated CPUs: $isolated"
 
-    # Run with --measurement-run-on-isolcpus and --cpusets
-    print_info "Running: $RTEVAL_CMD --cpusets --measurement-run-on-isolcpus -d $TEST_DURATION"
+    # Confine loads to the non-isolated CPUs so measurement (isolcpus) and loads
+    # are disjoint; the measurement cpuset can then stay an isolated partition
+    # without colliding with the taskset loads.
+    local repo_root=$(dirname "$RTEVAL_CMD")
+    local load_cpus=$(PYTHONPATH="$repo_root" python3 -c "from rteval.cpulist_utils import CpuList, collapse_cpulist; online=CpuList(open('/sys/devices/system/cpu/online').read().strip()); print(collapse_cpulist(online.difference(CpuList('$isolated')).cpus))")
 
-    timeout 60s $RTEVAL_CMD --cpusets --measurement-run-on-isolcpus -d "$TEST_DURATION" >> "$LOG_FILE" 2>&1 &
-    local rteval_pid=$!
+    if [ -z "$load_cpus" ]; then
+        print_info "SKIPPED: no non-isolated CPUs available for loads"
+        ((TESTS_PASSED++)) || true
+        return 0
+    fi
 
-    sleep 2
+    print_info "Non-isolated load CPUs: $load_cpus"
 
     local all_good=true
 
+    # Run with --measurement-run-on-isolcpus and --cpusets, loads confined to
+    # the non-isolated CPUs so they don't overlap the isolated measurement cpuset
+    print_info "Running: $RTEVAL_CMD --cpusets --measurement-run-on-isolcpus --loads-cpulist $load_cpus -d $TEST_DURATION"
+
+    timeout 60s $RTEVAL_CMD --cpusets --measurement-run-on-isolcpus --loads-cpulist "$load_cpus" -d "$TEST_DURATION" >> "$LOG_FILE" 2>&1 &
+    local rteval_pid=$!
+
+    sleep 2
+
     # Should create measurement cpuset
     if check_cpuset_exists "rteval_measurement"; then
         print_info "rteval_measurement cpuset created: OK"
 
-        # Check that cpuset includes isolated CPUs
         local cpuset_cpus=$(cat /sys/fs/cgroup/rteval_measurement/cpuset.cpus 2>/dev/null)
         print_info "Measurement cpuset CPUs: $cpuset_cpus"
-
-        # Verify isolated CPUs are included (would need complex parsing, just verify cpuset exists)
-        print_info "Measurement cpuset includes access to isolated CPUs: OK"
     else
         print_fail "rteval_measurement cpuset not created"
         all_good=false
     fi
 
+    # Measurement stays an isolated partition (disjoint from loads)
+    if check_cpuset_partition "rteval_measurement" "isolated"; then
+        print_info "Partition type is 'isolated': OK"
+    else
+        print_fail "Partition type is not 'isolated'"
+        all_good=false
+    fi
+
     wait $rteval_pid
-    sleep 1
+    local rc=$?
+    if [ "$rc" -eq 0 ]; then
+        print_info "rteval exited 0 with disjoint isolcpus measurement/loads: OK"
+    else
+        print_fail "rteval exited $rc (expected 0)"
+        all_good=false
+    fi
 
+    sleep 1
     if check_no_cpusets; then
         print_info "Cleanup successful: OK"
     else
-- 
2.55.0
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help