Path: blob/master/tools/testing/selftests/cgroup/test_cpuset_prs.sh
50950 views
#!/bin/bash1# SPDX-License-Identifier: GPL-2.02#3# Test for cpuset v2 partition root state (PRS)4#5# The sched verbose flag can be optionally set so that the console log6# can be examined for the correct setting of scheduling domain.7#89skip_test() {10echo "$1"11echo "Test SKIPPED"12exit 4 # ksft_skip13}1415[[ $(id -u) -eq 0 ]] || skip_test "Test must be run as root!"161718# Get wait_inotify location19WAIT_INOTIFY=$(cd $(dirname $0); pwd)/wait_inotify2021# Find cgroup v2 mount point22CGROUP2=$(mount -t cgroup2 | head -1 | awk -e '{print $3}')23[[ -n "$CGROUP2" ]] || skip_test "Cgroup v2 mount point not found!"24SUBPARTS_CPUS=$CGROUP2/.__DEBUG__.cpuset.cpus.subpartitions25CPULIST=$(cat $CGROUP2/cpuset.cpus.effective)2627NR_CPUS=$(lscpu | grep "^CPU(s):" | sed -e "s/.*:[[:space:]]*//")28[[ $NR_CPUS -lt 8 ]] && skip_test "Test needs at least 8 cpus available!"2930# Check to see if /dev/console exists and is writable31if [[ -c /dev/console && -w /dev/console ]]32then33CONSOLE=/dev/console34else35CONSOLE=/dev/null36fi3738# Set verbose flag and delay factor39PROG=$140VERBOSE=041DELAY_FACTOR=142SCHED_DEBUG=43while [[ "$1" = -* ]]44do45case "$1" in46-v) ((VERBOSE++))47# Enable sched/verbose can slow thing down48[[ $DELAY_FACTOR -eq 1 ]] &&49DELAY_FACTOR=250;;51-d) DELAY_FACTOR=$252shift53;;54*) echo "Usage: $PROG [-v] [-d <delay-factor>"55exit56;;57esac58shift59done6061# Set sched verbose flag if available when "-v" option is specified62if [[ $VERBOSE -gt 0 && -d /sys/kernel/debug/sched ]]63then64# Used to restore the original setting during cleanup65SCHED_DEBUG=$(cat /sys/kernel/debug/sched/verbose)66echo Y > /sys/kernel/debug/sched/verbose67fi6869cd $CGROUP270echo +cpuset > cgroup.subtree_control7172#73# If cpuset has been set up and used in child cgroups, we may not be able to74# create partition under root cgroup because of the CPU exclusivity rule.75# So we are going to skip the test if this is the case.76#77[[ -d test ]] || mkdir test78echo 0-6 > test/cpuset.cpus79echo root > test/cpuset.cpus.partition80cat test/cpuset.cpus.partition | grep -q invalid81RESULT=$?82echo member > test/cpuset.cpus.partition83echo "" > test/cpuset.cpus84[[ $RESULT -eq 0 ]] && skip_test "Child cgroups are using cpuset!"8586#87# If isolated CPUs have been reserved at boot time (as shown in88# cpuset.cpus.isolated), these isolated CPUs should be outside of CPUs 0-889# that will be used by this script for testing purpose. If not, some of90# the tests may fail incorrectly. Wait a bit and retry again just in case91# these isolated CPUs are leftover from previous run and have just been92# cleaned up earlier in this script.93#94# These pre-isolated CPUs should stay in an isolated state throughout the95# testing process for now.96#97BOOT_ISOLCPUS=$(cat $CGROUP2/cpuset.cpus.isolated)98[[ -n "$BOOT_ISOLCPUS" ]] && {99sleep 0.5100BOOT_ISOLCPUS=$(cat $CGROUP2/cpuset.cpus.isolated)101}102if [[ -n "$BOOT_ISOLCPUS" ]]103then104[[ $(echo $BOOT_ISOLCPUS | sed -e "s/[,-].*//") -le 8 ]] &&105skip_test "Pre-isolated CPUs ($BOOT_ISOLCPUS) overlap CPUs to be tested"106echo "Pre-isolated CPUs: $BOOT_ISOLCPUS"107fi108109cleanup()110{111online_cpus112cd $CGROUP2113rmdir A1/A2/A3 A1/A2 A1 B1 test/A1 test/B1 test > /dev/null 2>&1114rmdir rtest/p1/c11 rtest/p1/c12 rtest/p2/c21 \115rtest/p2/c22 rtest/p1 rtest/p2 rtest > /dev/null 2>&1116[[ -n "$SCHED_DEBUG" ]] &&117echo "$SCHED_DEBUG" > /sys/kernel/debug/sched/verbose118}119120# Pause in ms121pause()122{123DELAY=$1124LOOP=0125while [[ $LOOP -lt $DELAY_FACTOR ]]126do127sleep $DELAY128((LOOP++))129done130return 0131}132133console_msg()134{135MSG=$1136echo "$MSG"137echo "" > $CONSOLE138echo "$MSG" > $CONSOLE139pause 0.01140}141142test_partition()143{144EXPECTED_VAL=$1145echo $EXPECTED_VAL > cpuset.cpus.partition146[[ $? -eq 0 ]] || exit 1147ACTUAL_VAL=$(cat cpuset.cpus.partition)148[[ $ACTUAL_VAL != $EXPECTED_VAL ]] && {149echo "cpuset.cpus.partition: expect $EXPECTED_VAL, found $ACTUAL_VAL"150echo "Test FAILED"151exit 1152}153}154155test_effective_cpus()156{157EXPECTED_VAL=$1158ACTUAL_VAL=$(cat cpuset.cpus.effective)159[[ "$ACTUAL_VAL" != "$EXPECTED_VAL" ]] && {160echo "cpuset.cpus.effective: expect '$EXPECTED_VAL', found '$ACTUAL_VAL'"161echo "Test FAILED"162exit 1163}164}165166# Adding current process to cgroup.procs as a test167test_add_proc()168{169OUTSTR="$1"170ERRMSG=$((echo $$ > cgroup.procs) |& cat)171echo $ERRMSG | grep -q "$OUTSTR"172[[ $? -ne 0 ]] && {173echo "cgroup.procs: expect '$OUTSTR', got '$ERRMSG'"174echo "Test FAILED"175exit 1176}177echo $$ > $CGROUP2/cgroup.procs # Move out the task178}179180#181# Cpuset controller state transition test matrix.182#183# Cgroup test hierarchy184#185# root186# |187# +------+------+188# | |189# A1 B1190# |191# A2192# |193# A3194#195# P<v> = set cpus.partition (0:member, 1:root, 2:isolated)196# C<l> = add cpu-list to cpuset.cpus197# X<l> = add cpu-list to cpuset.cpus.exclusive198# S<p> = use prefix in subtree_control199# T = put a task into cgroup200# CX<l> = add cpu-list to both cpuset.cpus and cpuset.cpus.exclusive201# O<c>=<v> = Write <v> to CPU online file of <c>202#203# ECPUs - effective CPUs of cpusets204# Pstate - partition root state205# ISOLCPUS - isolated CPUs (<icpus>[,<icpus2>])206#207# Note that if there are 2 fields in ISOLCPUS, the first one is for208# sched-debug matching which includes offline CPUs and single-CPU partitions209# while the second one is for matching cpuset.cpus.isolated.210#211SETUP_A123_PARTITIONS="C1-3:P1:S+ C2-3:P1:S+ C3:P1"212TEST_MATRIX=(213# old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS214# ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ --------215" C0-1 . . C2-3 S+ C4-5 . . 0 A2:0-1"216" C0-1 . . C2-3 P1 . . . 0 "217" C0-1 . . C2-3 P1:S+ C0-1:P1 . . 0 "218" C0-1 . . C2-3 P1:S+ C1:P1 . . 0 "219" C0-1:S+ . . C2-3 . . . P1 0 "220" C0-1:P1 . . C2-3 S+ C1 . . 0 "221" C0-1:P1 . . C2-3 S+ C1:P1 . . 0 "222" C0-1:P1 . . C2-3 S+ C1:P1 . P1 0 "223" C0-1:P1 . . C2-3 C4-5 . . . 0 A1:4-5"224" C0-1:P1 . . C2-3 S+:C4-5 . . . 0 A1:4-5"225" C0-1 . . C2-3:P1 . . . C2 0 "226" C0-1 . . C2-3:P1 . . . C4-5 0 B1:4-5"227"C0-3:P1:S+ C2-3:P1 . . . . . . 0 A1:0-1|A2:2-3|XA2:2-3"228"C0-3:P1:S+ C2-3:P1 . . C1-3 . . . 0 A1:1|A2:2-3|XA2:2-3"229"C2-3:P1:S+ C3:P1 . . C3 . . . 0 A1:|A2:3|XA2:3 A1:P1|A2:P1"230"C2-3:P1:S+ C3:P1 . . C3 P0 . . 0 A1:3|A2:3 A1:P1|A2:P0"231"C2-3:P1:S+ C2:P1 . . C2-4 . . . 0 A1:3-4|A2:2"232"C2-3:P1:S+ C3:P1 . . C3 . . C0-2 0 A1:|B1:0-2 A1:P1|A2:P1"233"$SETUP_A123_PARTITIONS . C2-3 . . . 0 A1:|A2:2|A3:3 A1:P1|A2:P1|A3:P1"234235# CPU offlining cases:236" C0-1 . . C2-3 S+ C4-5 . O2=0 0 A1:0-1|B1:3"237"C0-3:P1:S+ C2-3:P1 . . O2=0 . . . 0 A1:0-1|A2:3"238"C0-3:P1:S+ C2-3:P1 . . O2=0 O2=1 . . 0 A1:0-1|A2:2-3"239"C0-3:P1:S+ C2-3:P1 . . O1=0 . . . 0 A1:0|A2:2-3"240"C0-3:P1:S+ C2-3:P1 . . O1=0 O1=1 . . 0 A1:0-1|A2:2-3"241"C2-3:P1:S+ C3:P1 . . O3=0 O3=1 . . 0 A1:2|A2:3 A1:P1|A2:P1"242"C2-3:P1:S+ C3:P2 . . O3=0 O3=1 . . 0 A1:2|A2:3 A1:P1|A2:P2"243"C2-3:P1:S+ C3:P1 . . O2=0 O2=1 . . 0 A1:2|A2:3 A1:P1|A2:P1"244"C2-3:P1:S+ C3:P2 . . O2=0 O2=1 . . 0 A1:2|A2:3 A1:P1|A2:P2"245"C2-3:P1:S+ C3:P1 . . O2=0 . . . 0 A1:|A2:3 A1:P1|A2:P1"246"C2-3:P1:S+ C3:P1 . . O3=0 . . . 0 A1:2|A2: A1:P1|A2:P1"247"C2-3:P1:S+ C3:P1 . . T:O2=0 . . . 0 A1:3|A2:3 A1:P1|A2:P-1"248"C2-3:P1:S+ C3:P1 . . . T:O3=0 . . 0 A1:2|A2:2 A1:P1|A2:P-1"249"$SETUP_A123_PARTITIONS . O1=0 . . . 0 A1:|A2:2|A3:3 A1:P1|A2:P1|A3:P1"250"$SETUP_A123_PARTITIONS . O2=0 . . . 0 A1:1|A2:|A3:3 A1:P1|A2:P1|A3:P1"251"$SETUP_A123_PARTITIONS . O3=0 . . . 0 A1:1|A2:2|A3: A1:P1|A2:P1|A3:P1"252"$SETUP_A123_PARTITIONS . T:O1=0 . . . 0 A1:2-3|A2:2-3|A3:3 A1:P1|A2:P-1|A3:P-1"253"$SETUP_A123_PARTITIONS . . T:O2=0 . . 0 A1:1|A2:3|A3:3 A1:P1|A2:P1|A3:P-1"254"$SETUP_A123_PARTITIONS . . . T:O3=0 . 0 A1:1|A2:2|A3:2 A1:P1|A2:P1|A3:P-1"255"$SETUP_A123_PARTITIONS . T:O1=0 O1=1 . . 0 A1:1|A2:2|A3:3 A1:P1|A2:P1|A3:P1"256"$SETUP_A123_PARTITIONS . . T:O2=0 O2=1 . 0 A1:1|A2:2|A3:3 A1:P1|A2:P1|A3:P1"257"$SETUP_A123_PARTITIONS . . . T:O3=0 O3=1 0 A1:1|A2:2|A3:3 A1:P1|A2:P1|A3:P1"258"$SETUP_A123_PARTITIONS . T:O1=0 O2=0 O1=1 . 0 A1:1|A2:|A3:3 A1:P1|A2:P1|A3:P1"259"$SETUP_A123_PARTITIONS . T:O1=0 O2=0 O2=1 . 0 A1:2-3|A2:2-3|A3:3 A1:P1|A2:P-1|A3:P-1"260261# old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS262# ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ --------263#264# Remote partition and cpuset.cpus.exclusive tests265#266" C0-3:S+ C1-3:S+ C2-3 . X2-3 . . . 0 A1:0-3|A2:1-3|A3:2-3|XA1:2-3"267" C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3:P2 . . 0 A1:0-1|A2:2-3|A3:2-3 A1:P0|A2:P2 2-3"268" C0-3:S+ C1-3:S+ C2-3 . X2-3 X3:P2 . . 0 A1:0-2|A2:3|A3:3 A1:P0|A2:P2 3"269" C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3 X2-3:P2 . 0 A1:0-1|A2:1|A3:2-3 A1:P0|A3:P2 2-3"270" C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3 X2-3:P2:C3 . 0 A1:0-1|A2:1|A3:2-3 A1:P0|A3:P2 2-3"271" C0-3:S+ C1-3:S+ C2-3 C2-3 . . . P2 0 A1:0-1|A2:1|A3:1|B1:2-3 A1:P0|A3:P0|B1:P2"272" C0-3:S+ C1-3:S+ C2-3 C4-5 . . . P2 0 B1:4-5 B1:P2 4-5"273" C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3 X2-3:P2 P2 0 A3:2-3|B1:4 A3:P2|B1:P2 2-4"274" C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3 X2-3:P2:C1-3 P2 0 A3:2-3|B1:4 A3:P2|B1:P2 2-4"275" C0-3:S+ C1-3:S+ C2-3 C4 X1-3 X1-3:P2 P2 . 0 A2:1|A3:2-3 A2:P2|A3:P2 1-3"276" C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3 X2-3:P2 P2:C4-5 0 A3:2-3|B1:4-5 A3:P2|B1:P2 2-5"277" C4:X0-3:S+ X1-3:S+ X2-3 . . P2 . . 0 A1:4|A2:1-3|A3:1-3 A2:P2 1-3"278" C4:X0-3:S+ X1-3:S+ X2-3 . . . P2 . 0 A1:4|A2:4|A3:2-3 A3:P2 2-3"279280# Nested remote/local partition tests281" C0-3:S+ C1-3:S+ C2-3 C4-5 X2-3 X2-3:P1 P2 P1 0 A1:0-1|A2:|A3:2-3|B1:4-5 \282A1:P0|A2:P1|A3:P2|B1:P1 2-3"283" C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3:P1 P2 P1 0 A1:0-1|A2:|A3:2-3|B1:4 \284A1:P0|A2:P1|A3:P2|B1:P1 2-4|2-3"285" C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3:P1 . P1 0 A1:0-1|A2:2-3|A3:2-3|B1:4 \286A1:P0|A2:P1|A3:P0|B1:P1"287" C0-3:S+ C1-3:S+ C3 C4 X2-3 X2-3:P1 P2 P1 0 A1:0-1|A2:2|A3:3|B1:4 \288A1:P0|A2:P1|A3:P2|B1:P1 2-4|3"289" C0-4:S+ C1-4:S+ C2-4 . X2-4 X2-4:P2 X4:P1 . 0 A1:0-1|A2:2-3|A3:4 \290A1:P0|A2:P2|A3:P1 2-4|2-3"291" C0-4:S+ C1-4:S+ C2-4 . X2-4 X2-4:P2 X3-4:P1 . 0 A1:0-1|A2:2|A3:3-4 \292A1:P0|A2:P2|A3:P1 2"293" C0-4:X2-4:S+ C1-4:X2-4:S+:P2 C2-4:X4:P1 \294. . X5 . . 0 A1:0-4|A2:1-4|A3:2-4 \295A1:P0|A2:P-2|A3:P-1 ."296" C0-4:X2-4:S+ C1-4:X2-4:S+:P2 C2-4:X4:P1 \297. . . X1 . 0 A1:0-1|A2:2-4|A3:2-4 \298A1:P0|A2:P2|A3:P-1 2-4"299300# Remote partition offline tests301" C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3 X2-3:P2:O2=0 . 0 A1:0-1|A2:1|A3:3 A1:P0|A3:P2 2-3"302" C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3 X2-3:P2:O2=0 O2=1 0 A1:0-1|A2:1|A3:2-3 A1:P0|A3:P2 2-3"303" C0-3:S+ C1-3:S+ C3 . X2-3 X2-3 P2:O3=0 . 0 A1:0-2|A2:1-2|A3: A1:P0|A3:P2 3"304" C0-3:S+ C1-3:S+ C3 . X2-3 X2-3 T:P2:O3=0 . 0 A1:0-2|A2:1-2|A3:1-2 A1:P0|A3:P-2 3|"305306# An invalidated remote partition cannot self-recover from hotplug307" C0-3:S+ C1-3:S+ C2 . X2-3 X2-3 T:P2:O2=0 O2=1 0 A1:0-3|A2:1-3|A3:2 A1:P0|A3:P-2 ."308309# cpus.exclusive.effective clearing test310" C0-3:S+ C1-3:S+ C2 . X2-3:X . . . 0 A1:0-3|A2:1-3|A3:2|XA1:"311312# Invalid to valid remote partition transition test313" C0-3:S+ C1-3 . . . X3:P2 . . 0 A1:0-3|A2:1-3|XA2: A2:P-2 ."314" C0-3:S+ C1-3:X3:P2315. . X2-3 P2 . . 0 A1:0-2|A2:3|XA2:3 A2:P2 3"316317# Invalid to valid local partition direct transition tests318" C1-3:S+:P2 X4:P2 . . . . . . 0 A1:1-3|XA1:1-3|A2:1-3:XA2: A1:P2|A2:P-2 1-3"319" C1-3:S+:P2 X4:P2 . . . X3:P2 . . 0 A1:1-2|XA1:1-3|A2:3:XA2:3 A1:P2|A2:P2 1-3"320" C0-3:P2 . . C4-6 C0-4 . . . 0 A1:0-4|B1:5-6 A1:P2|B1:P0"321" C0-3:P2 . . C4-6 C0-4:C0-3 . . . 0 A1:0-3|B1:4-6 A1:P2|B1:P0 0-3"322323# Local partition invalidation tests324" C0-3:X1-3:S+:P2 C1-3:X2-3:S+:P2 C2-3:X3:P2 \325. . . . . 0 A1:1|A2:2|A3:3 A1:P2|A2:P2|A3:P2 1-3"326" C0-3:X1-3:S+:P2 C1-3:X2-3:S+:P2 C2-3:X3:P2 \327. . X4 . . 0 A1:1-3|A2:1-3|A3:2-3|XA2:|XA3: A1:P2|A2:P-2|A3:P-2 1-3"328" C0-3:X1-3:S+:P2 C1-3:X2-3:S+:P2 C2-3:X3:P2 \329. . C4:X . . 0 A1:1-3|A2:1-3|A3:2-3|XA2:|XA3: A1:P2|A2:P-2|A3:P-2 1-3"330# Local partition CPU change tests331" C0-5:S+:P2 C4-5:S+:P1 . . . C3-5 . . 0 A1:0-2|A2:3-5 A1:P2|A2:P1 0-2"332" C0-5:S+:P2 C4-5:S+:P1 . . C1-5 . . . 0 A1:1-3|A2:4-5 A1:P2|A2:P1 1-3"333334# cpus_allowed/exclusive_cpus update tests335" C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3 \336. X:C4 . P2 . 0 A1:4|A2:4|XA2:|XA3:|A3:4 \337A1:P0|A3:P-2 ."338" C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3 \339. X1 . P2 . 0 A1:0-3|A2:1-3|XA1:1|XA2:|XA3:|A3:2-3 \340A1:P0|A3:P-2 ."341" C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3 \342. . X3 P2 . 0 A1:0-2|A2:1-2|XA2:3|XA3:3|A3:3 \343A1:P0|A3:P2 3"344" C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3:P2 \345. . X3 . . 0 A1:0-2|A2:1-2|XA2:3|XA3:3|A3:3|XA3:3 \346A1:P0|A3:P2 3"347" C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3:P2 \348. X4 . . . 0 A1:0-3|A2:1-3|A3:2-3|XA1:4|XA2:|XA3 \349A1:P0|A3:P-2"350351# old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS352# ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ --------353#354# Incorrect change to cpuset.cpus[.exclusive] invalidates partition root355#356# Adding CPUs to partition root that are not in parent's357# cpuset.cpus is allowed, but those extra CPUs are ignored.358"C2-3:P1:S+ C3:P1 . . . C2-4 . . 0 A1:|A2:2-3 A1:P1|A2:P1"359360# Taking away all CPUs from parent or itself if there are tasks361# will make the partition invalid.362"C2-3:P1:S+ C3:P1 . . T C2-3 . . 0 A1:2-3|A2:2-3 A1:P1|A2:P-1"363" C3:P1:S+ C3 . . T P1 . . 0 A1:3|A2:3 A1:P1|A2:P-1"364"$SETUP_A123_PARTITIONS . T:C2-3 . . . 0 A1:2-3|A2:2-3|A3:3 A1:P1|A2:P-1|A3:P-1"365"$SETUP_A123_PARTITIONS . T:C2-3:C1-3 . . . 0 A1:1|A2:2|A3:3 A1:P1|A2:P1|A3:P1"366367# Changing a partition root to member makes child partitions invalid368"C2-3:P1:S+ C3:P1 . . P0 . . . 0 A1:2-3|A2:3 A1:P0|A2:P-1"369"$SETUP_A123_PARTITIONS . C2-3 P0 . . 0 A1:2-3|A2:2-3|A3:3 A1:P1|A2:P0|A3:P-1"370371# cpuset.cpus can contains cpus not in parent's cpuset.cpus as long372# as they overlap.373"C2-3:P1:S+ . . . . C3-4:P1 . . 0 A1:2|A2:3 A1:P1|A2:P1"374375# Deletion of CPUs distributed to child cgroup is allowed.376"C0-1:P1:S+ C1 . C2-3 C4-5 . . . 0 A1:4-5|A2:4-5"377378# To become a valid partition root, cpuset.cpus must overlap parent's379# cpuset.cpus.380" C0-1:P1 . . C2-3 S+ C4-5:P1 . . 0 A1:0-1|A2:0-1 A1:P1|A2:P-1"381382# Enabling partition with child cpusets is allowed383" C0-1:S+ C1 . C2-3 P1 . . . 0 A1:0-1|A2:1 A1:P1"384385# A partition root with non-partition root parent is invalid| but it386# can be made valid if its parent becomes a partition root too.387" C0-1:S+ C1 . C2-3 . P2 . . 0 A1:0-1|A2:1 A1:P0|A2:P-2"388" C0-1:S+ C1:P2 . C2-3 P1 . . . 0 A1:0|A2:1 A1:P1|A2:P2 0-1|1"389390# A non-exclusive cpuset.cpus change will not invalidate its siblings partition.391" C0-1:P1 . . C2-3 C0-2 . . . 0 A1:0-2|B1:3 A1:P1|B1:P0"392" C0-1:P1 . . P1:C2-3 C0-2 . . . 0 A1:0-1|XA1:0-1|B1:2-3 A1:P1|B1:P1"393" C0-1 . . P1:C2-3 C0-2 . . . 0 A1:0-1|B1:2-3 A1:P0|B1:P1"394395# cpuset.cpus can overlap with sibling cpuset.cpus.exclusive but not subsumed by it396" C0-3 . . C4-5 X5 . . . 0 A1:0-3|B1:4-5"397398# Child partition root that try to take all CPUs from parent partition399# with tasks will remain invalid.400" C1-4:P1:S+ P1 . . . . . . 0 A1:1-4|A2:1-4 A1:P1|A2:P-1"401" C1-4:P1:S+ P1 . . . C1-4 . . 0 A1|A2:1-4 A1:P1|A2:P1"402" C1-4:P1:S+ P1 . . T C1-4 . . 0 A1:1-4|A2:1-4 A1:P1|A2:P-1"403404# Clearing of cpuset.cpus with a preset cpuset.cpus.exclusive shouldn't405# affect cpuset.cpus.exclusive.effective.406" C1-4:X3:S+ C1:X3 . . . C . . 0 A2:1-4|XA2:3"407408# cpuset.cpus can contain CPUs that overlap a sibling cpuset with cpus.exclusive409# but creating a local partition out of it is not allowed. Similarly and change410# in cpuset.cpus of a local partition that overlaps sibling exclusive CPUs will411# invalidate it.412" CX1-4:S+ CX2-4:P2 . C5-6 . . . P1 0 A1:1|A2:2-4|B1:5-6|XB1:5-6 \413A1:P0|A2:P2:B1:P1 2-4"414" CX1-4:S+ CX2-4:P2 . C3-6 . . . P1 0 A1:1|A2:2-4|B1:5-6 \415A1:P0|A2:P2:B1:P-1 2-4"416" CX1-4:S+ CX2-4:P2 . C5-6 . . . P1:C3-6 0 A1:1|A2:2-4|B1:5-6 \417A1:P0|A2:P2:B1:P-1 2-4"418419# When multiple partitions with conflicting cpuset.cpus are created, the420# latter created ones will only get what are left of the available exclusive421# CPUs.422" C1-3:P1 . . . . . . C3-5:P1 0 A1:1-3|B1:4-5:XB1:4-5 A1:P1|B1:P1"423424# cpuset.cpus can be set to a subset of sibling's cpuset.cpus.exclusive425" C1-3:X1-3 . . C4-5 . . . C1-2 0 A1:1-3|B1:1-2"426427# cpuset.cpus can become empty with task in it as it inherits parent's effective CPUs428" C1-3:S+ C2 . . . T:C . . 0 A1:1-3|A2:1-3"429430# old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS431# ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ --------432# Failure cases:433434# A task cannot be added to a partition with no cpu435"C2-3:P1:S+ C3:P1 . . O2=0:T . . . 1 A1:|A2:3 A1:P1|A2:P1"436437# Changes to cpuset.cpus.exclusive that violate exclusivity rule is rejected438" C0-3 . . C4-5 X0-3 . . X3-5 1 A1:0-3|B1:4-5"439440# cpuset.cpus.exclusive cannot be set to a superset of sibling's cpuset.cpus441" C0-3 . . C4-5 X3-5 . . . 1 A1:0-3|B1:4-5"442)443444#445# Cpuset controller remote partition test matrix.446#447# Cgroup test hierarchy448#449# root450# |451# rtest (cpuset.cpus.exclusive=1-7)452# |453# +------+------+454# | |455# p1 p2456# +--+--+ +--+--+457# | | | |458# c11 c12 c21 c22459#460# REMOTE_TEST_MATRIX uses the same notational convention as TEST_MATRIX.461# Only CPUs 1-7 should be used.462#463REMOTE_TEST_MATRIX=(464# old-p1 old-p2 old-c11 old-c12 old-c21 old-c22465# new-p1 new-p2 new-c11 new-c12 new-c21 new-c22 ECPUs Pstate ISOLCPUS466# ------ ------ ------- ------- ------- ------- ----- ------ --------467" X1-3:S+ X4-6:S+ X1-2 X3 X4-5 X6 \468. . P2 P2 P2 P2 c11:1-2|c12:3|c21:4-5|c22:6 \469c11:P2|c12:P2|c21:P2|c22:P2 1-6"470" CX1-4:S+ . X1-2:P2 C3 . . \471. . . C3-4 . . p1:3-4|c11:1-2|c12:3-4 \472p1:P0|c11:P2|c12:P0 1-2"473" CX1-4:S+ . X1-2:P2 . . . \474X2-4 . . . . . p1:1,3-4|c11:2 \475p1:P0|c11:P2 2"476" CX1-5:S+ . X1-2:P2 X3-5:P1 . . \477X2-4 . . . . . p1:1,5|c11:2|c12:3-4 \478p1:P0|c11:P2|c12:P1 2"479" CX1-4:S+ . X1-2:P2 X3-4:P1 . . \480. . X2 . . . p1:1|c11:2|c12:3-4 \481p1:P0|c11:P2|c12:P1 2"482# p1 as member, will get its effective CPUs from its parent rtest483" CX1-4:S+ . X1-2:P2 X3-4:P1 . . \484. . X1 CX2-4 . . p1:5-7|c11:1|c12:2-4 \485p1:P0|c11:P2|c12:P1 1"486" CX1-4:S+ X5-6:P1:S+ . . . . \487. . X1-2:P2 X4-5:P1 . X1-7:P2 p1:3|c11:1-2|c12:4:c22:5-6 \488p1:P0|p2:P1|c11:P2|c12:P1|c22:P2 \4891-2,4-6|1-2,5-6"490# c12 whose cpuset.cpus CPUs are all granted to c11 will become invalid partition491" C1-5:P1:S+ . C1-4:P1 C2-3 . . \492. . . P1 . . p1:5|c11:1-4|c12:5 \493p1:P1|c11:P1|c12:P-1"494)495496#497# Write to the cpu online file498# $1 - <c>=<v> where <c> = cpu number, <v> value to be written499#500write_cpu_online()501{502CPU=${1%=*}503VAL=${1#*=}504CPUFILE=//sys/devices/system/cpu/cpu${CPU}/online505if [[ $VAL -eq 0 ]]506then507OFFLINE_CPUS="$OFFLINE_CPUS $CPU"508else509[[ -n "$OFFLINE_CPUS" ]] && {510OFFLINE_CPUS=$(echo $CPU $CPU $OFFLINE_CPUS | fmt -1 |\511sort | uniq -u)512}513fi514echo $VAL > $CPUFILE515pause 0.05516}517518#519# Set controller state520# $1 - cgroup directory521# $2 - state522# $3 - showerr523#524# The presence of ":" in state means transition from one to the next.525#526set_ctrl_state()527{528TMPMSG=/tmp/.msg_$$529CGRP=$1530STATE=$2531SHOWERR=${3}532CTRL=${CTRL:=$CONTROLLER}533HASERR=0534REDIRECT="2> $TMPMSG"535[[ -z "$STATE" || "$STATE" = '.' ]] && return 0536[[ $VERBOSE -gt 0 ]] && SHOWERR=1537538rm -f $TMPMSG539for CMD in $(echo $STATE | sed -e "s/:/ /g")540do541TFILE=$CGRP/cgroup.procs542SFILE=$CGRP/cgroup.subtree_control543PFILE=$CGRP/cpuset.cpus.partition544CFILE=$CGRP/cpuset.cpus545XFILE=$CGRP/cpuset.cpus.exclusive546case $CMD in547S*) PREFIX=${CMD#?}548COMM="echo ${PREFIX}${CTRL} > $SFILE"549eval $COMM $REDIRECT550;;551X*)552CPUS=${CMD#?}553COMM="echo $CPUS > $XFILE"554eval $COMM $REDIRECT555;;556CX*)557CPUS=${CMD#??}558COMM="echo $CPUS > $CFILE; echo $CPUS > $XFILE"559eval $COMM $REDIRECT560;;561C*) CPUS=${CMD#?}562COMM="echo $CPUS > $CFILE"563eval $COMM $REDIRECT564;;565P*) VAL=${CMD#?}566case $VAL in5670) VAL=member568;;5691) VAL=root570;;5712) VAL=isolated572;;573*)574echo "Invalid partition state - $VAL"575exit 1576;;577esac578COMM="echo $VAL > $PFILE"579eval $COMM $REDIRECT580;;581O*) VAL=${CMD#?}582write_cpu_online $VAL583;;584T*) COMM="echo 0 > $TFILE"585eval $COMM $REDIRECT586;;587*) echo "Unknown command: $CMD"588exit 1589;;590esac591RET=$?592[[ $RET -ne 0 ]] && {593[[ -n "$SHOWERR" ]] && {594echo "$COMM"595cat $TMPMSG596}597HASERR=1598}599pause 0.01600rm -f $TMPMSG601done602return $HASERR603}604605set_ctrl_state_noerr()606{607CGRP=$1608STATE=$2609[[ -d $CGRP ]] || mkdir $CGRP610set_ctrl_state $CGRP $STATE 1611[[ $? -ne 0 ]] && {612echo "ERROR: Failed to set $2 to cgroup $1!"613exit 1614}615}616617online_cpus()618{619[[ -n "OFFLINE_CPUS" ]] && {620for C in $OFFLINE_CPUS621do622write_cpu_online ${C}=1623done624}625}626627#628# Remove all the test cgroup directories629#630reset_cgroup_states()631{632echo 0 > $CGROUP2/cgroup.procs633online_cpus634rmdir $RESET_LIST > /dev/null 2>&1635}636637dump_states()638{639for DIR in $CGROUP_LIST640do641CPUS=$DIR/cpuset.cpus642ECPUS=$DIR/cpuset.cpus.effective643XCPUS=$DIR/cpuset.cpus.exclusive644XECPUS=$DIR/cpuset.cpus.exclusive.effective645PRS=$DIR/cpuset.cpus.partition646PCPUS=$DIR/.__DEBUG__.cpuset.cpus.subpartitions647ISCPUS=$DIR/cpuset.cpus.isolated648[[ -e $CPUS ]] && echo "$CPUS: $(cat $CPUS)"649[[ -e $XCPUS ]] && echo "$XCPUS: $(cat $XCPUS)"650[[ -e $ECPUS ]] && echo "$ECPUS: $(cat $ECPUS)"651[[ -e $XECPUS ]] && echo "$XECPUS: $(cat $XECPUS)"652[[ -e $PRS ]] && echo "$PRS: $(cat $PRS)"653[[ -e $PCPUS ]] && echo "$PCPUS: $(cat $PCPUS)"654[[ -e $ISCPUS ]] && echo "$ISCPUS: $(cat $ISCPUS)"655done656}657658#659# Set the actual cgroup directory into $CGRP_DIR660# $1 - cgroup name661#662set_cgroup_dir()663{664CGRP_DIR=$1665[[ $CGRP_DIR = A2 ]] && CGRP_DIR=A1/A2666[[ $CGRP_DIR = A3 ]] && CGRP_DIR=A1/A2/A3667[[ $CGRP_DIR = c11 ]] && CGRP_DIR=p1/c11668[[ $CGRP_DIR = c12 ]] && CGRP_DIR=p1/c12669[[ $CGRP_DIR = c21 ]] && CGRP_DIR=p2/c21670[[ $CGRP_DIR = c22 ]] && CGRP_DIR=p2/c22671}672673#674# Check effective cpus675# $1 - check string, format: <cgroup>:<cpu-list>[|<cgroup>:<cpu-list>]*676#677check_effective_cpus()678{679CHK_STR=$1680for CHK in $(echo $CHK_STR | sed -e "s/|/ /g")681do682set -- $(echo $CHK | sed -e "s/:/ /g")683CGRP=$1684EXPECTED_CPUS=$2685ACTUAL_CPUS=686if [[ $CGRP = X* ]]687then688CGRP=${CGRP#X}689FILE=cpuset.cpus.exclusive.effective690else691FILE=cpuset.cpus.effective692fi693set_cgroup_dir $CGRP694[[ -e $CGRP_DIR/$FILE ]] || return 1695ACTUAL_CPUS=$(cat $CGRP_DIR/$FILE)696[[ $EXPECTED_CPUS = $ACTUAL_CPUS ]] || return 1697done698}699700#701# Check cgroup states702# $1 - check string, format: <cgroup>:<state>[|<cgroup>:<state>]*703#704check_cgroup_states()705{706CHK_STR=$1707for CHK in $(echo $CHK_STR | sed -e "s/|/ /g")708do709set -- $(echo $CHK | sed -e "s/:/ /g")710CGRP=$1711EXPECTED_STATE=$2712FILE=713EVAL=$(expr substr $EXPECTED_STATE 2 2)714715set_cgroup_dir $CGRP716case $EXPECTED_STATE in717P*) FILE=$CGRP_DIR/cpuset.cpus.partition718;;719*) echo "Unknown state: $EXPECTED_STATE!"720exit 1721;;722esac723ACTUAL_STATE=$(cat $FILE)724725case "$ACTUAL_STATE" in726member) VAL=0727;;728root) VAL=1729;;730isolated)731VAL=2732;;733"root invalid"*)734VAL=-1735;;736"isolated invalid"*)737VAL=-2738;;739esac740[[ $EVAL != $VAL ]] && return 1741742#743# For root partition, dump sched-domains info to console if744# verbose mode set for manual comparison with sched debug info.745#746[[ $VAL -eq 1 && $VERBOSE -gt 0 ]] && {747DOMS=$(cat $CGRP_DIR/cpuset.cpus.effective)748[[ -n "$DOMS" ]] &&749echo " [$CGRP_DIR] sched-domain: $DOMS" > $CONSOLE750}751done752return 0753}754755#756# Get isolated (including offline) CPUs by looking at757# /sys/kernel/debug/sched/domains and cpuset.cpus.isolated control file,758# if available, and compare that with the expected value.759#760# Note that isolated CPUs from the sched/domains context include offline761# CPUs as well as CPUs in non-isolated 1-CPU partition. Those CPUs may762# not be included in the cpuset.cpus.isolated control file which contains763# only CPUs in isolated partitions as well as those that are isolated at764# boot time.765#766# $1 - expected isolated cpu list(s) <isolcpus1>{,<isolcpus2>}767# <isolcpus1> - expected sched/domains value768# <isolcpus2> - cpuset.cpus.isolated value = <isolcpus1> if not defined769#770check_isolcpus()771{772EXPECTED_ISOLCPUS=$1773ISCPUS=${CGROUP2}/cpuset.cpus.isolated774ISOLCPUS=$(cat $ISCPUS)775LASTISOLCPU=776SCHED_DOMAINS=/sys/kernel/debug/sched/domains777if [[ $EXPECTED_ISOLCPUS = . ]]778then779EXPECTED_ISOLCPUS=780EXPECTED_SDOMAIN=781elif [[ $(expr $EXPECTED_ISOLCPUS : ".*|.*") > 0 ]]782then783set -- $(echo $EXPECTED_ISOLCPUS | sed -e "s/|/ /g")784EXPECTED_ISOLCPUS=$2785EXPECTED_SDOMAIN=$1786else787EXPECTED_SDOMAIN=$EXPECTED_ISOLCPUS788fi789790#791# Appending pre-isolated CPUs792# Even though CPU #8 isn't used for testing, it can't be pre-isolated793# to make appending those CPUs easier.794#795[[ -n "$BOOT_ISOLCPUS" ]] && {796EXPECTED_ISOLCPUS=${EXPECTED_ISOLCPUS:+${EXPECTED_ISOLCPUS},}${BOOT_ISOLCPUS}797EXPECTED_SDOMAIN=${EXPECTED_SDOMAIN:+${EXPECTED_SDOMAIN},}${BOOT_ISOLCPUS}798}799800#801# Check cpuset.cpus.isolated cpumask802#803[[ "$EXPECTED_ISOLCPUS" != "$ISOLCPUS" ]] && {804# Take a 50ms pause and try again805pause 0.05806ISOLCPUS=$(cat $ISCPUS)807}808[[ "$EXPECTED_ISOLCPUS" != "$ISOLCPUS" ]] && return 1809ISOLCPUS=810EXPECTED_ISOLCPUS=$EXPECTED_SDOMAIN811812#813# Use the sched domain in debugfs to check isolated CPUs, if available814#815[[ -d $SCHED_DOMAINS ]] || return 0816817for ((CPU=0; CPU < $NR_CPUS; CPU++))818do819[[ -n "$(ls ${SCHED_DOMAINS}/cpu$CPU)" ]] && continue820821if [[ -z "$LASTISOLCPU" ]]822then823ISOLCPUS=$CPU824LASTISOLCPU=$CPU825elif [[ "$LASTISOLCPU" -eq $((CPU - 1)) ]]826then827echo $ISOLCPUS | grep -q "\<$LASTISOLCPU\$"828if [[ $? -eq 0 ]]829then830ISOLCPUS=${ISOLCPUS}-831fi832LASTISOLCPU=$CPU833else834if [[ $ISOLCPUS = *- ]]835then836ISOLCPUS=${ISOLCPUS}$LASTISOLCPU837fi838ISOLCPUS=${ISOLCPUS},$CPU839LASTISOLCPU=$CPU840fi841done842[[ "$ISOLCPUS" = *- ]] && ISOLCPUS=${ISOLCPUS}$LASTISOLCPU843844[[ "$EXPECTED_SDOMAIN" = "$ISOLCPUS" ]]845}846847test_fail()848{849TESTNUM=$1850TESTTYPE=$2851ADDINFO=$3852echo "Test $TEST[$TESTNUM] failed $TESTTYPE check!"853[[ -n "$ADDINFO" ]] && echo "*** $ADDINFO ***"854eval echo \${$TEST[$I]}855echo856dump_states857exit 1858}859860#861# Check to see if there are unexpected isolated CPUs left beyond the boot862# time isolated ones.863#864null_isolcpus_check()865{866[[ $VERBOSE -gt 0 ]] || return 0867# Retry a few times before printing error868RETRY=0869while [[ $RETRY -lt 8 ]]870do871pause 0.02872check_isolcpus "."873[[ $? -eq 0 ]] && return 0874((RETRY++))875done876echo "Unexpected isolated CPUs: $ISOLCPUS"877dump_states878exit 1879}880881#882# Check state transition test result883# $1 - Test number884# $2 - Expected effective CPU values885# $3 - Expected partition states886# $4 - Expected isolated CPUs887#888check_test_results()889{890_NR=$1891_ECPUS="$2"892_PSTATES="$3"893_ISOLCPUS="$4"894895[[ -n "$_ECPUS" && "$_ECPUS" != . ]] && {896check_effective_cpus $_ECPUS897[[ $? -ne 0 ]] && test_fail $_NR "effective CPU" \898"Cgroup $CGRP: expected $EXPECTED_CPUS, got $ACTUAL_CPUS"899}900901[[ -n "$_PSTATES" && "$_PSTATES" != . ]] && {902check_cgroup_states $_PSTATES903[[ $? -ne 0 ]] && test_fail $_NR states \904"Cgroup $CGRP: expected $EXPECTED_STATE, got $ACTUAL_STATE"905}906907# Compare the expected isolated CPUs with the actual ones,908# if available909[[ -n "$_ISOLCPUS" ]] && {910check_isolcpus $_ISOLCPUS911[[ $? -ne 0 ]] && {912[[ -n "$BOOT_ISOLCPUS" ]] && _ISOLCPUS=${_ISOLCPUS},${BOOT_ISOLCPUS}913test_fail $_NR "isolated CPU" \914"Expect $_ISOLCPUS, get $ISOLCPUS instead"915}916}917reset_cgroup_states918#919# Check to see if effective cpu list changes920#921_NEWLIST=$(cat $CGROUP2/cpuset.cpus.effective)922RETRY=0923while [[ $_NEWLIST != $CPULIST && $RETRY -lt 8 ]]924do925# Wait a bit longer & recheck a few times926pause 0.02927((RETRY++))928_NEWLIST=$(cat $CGROUP2/cpuset.cpus.effective)929done930[[ $_NEWLIST != $CPULIST ]] && {931echo "Effective cpus changed to $_NEWLIST after test $_NR!"932exit 1933}934null_isolcpus_check935[[ $VERBOSE -gt 0 ]] && echo "Test $I done."936}937938#939# Run cpuset state transition test940# $1 - test matrix name941#942# This test is somewhat fragile as delays (sleep x) are added in various943# places to make sure state changes are fully propagated before the next944# action. These delays may need to be adjusted if running in a slower machine.945#946run_state_test()947{948TEST=$1949CONTROLLER=cpuset950CGROUP_LIST=". A1 A1/A2 A1/A2/A3 B1"951RESET_LIST="A1/A2/A3 A1/A2 A1 B1"952I=0953eval CNT="\${#$TEST[@]}"954955reset_cgroup_states956console_msg "Running state transition test ..."957958while [[ $I -lt $CNT ]]959do960echo "Running test $I ..." > $CONSOLE961[[ $VERBOSE -gt 1 ]] && {962echo ""963eval echo \${$TEST[$I]}964}965eval set -- "\${$TEST[$I]}"966OLD_A1=$1967OLD_A2=$2968OLD_A3=$3969OLD_B1=$4970NEW_A1=$5971NEW_A2=$6972NEW_A3=$7973NEW_B1=$8974RESULT=$9975ECPUS=${10}976STATES=${11}977ICPUS=${12}978979set_ctrl_state_noerr A1 $OLD_A1980set_ctrl_state_noerr A1/A2 $OLD_A2981set_ctrl_state_noerr A1/A2/A3 $OLD_A3982set_ctrl_state_noerr B1 $OLD_B1983984RETVAL=0985set_ctrl_state A1 $NEW_A1; ((RETVAL += $?))986set_ctrl_state A1/A2 $NEW_A2; ((RETVAL += $?))987set_ctrl_state A1/A2/A3 $NEW_A3; ((RETVAL += $?))988set_ctrl_state B1 $NEW_B1; ((RETVAL += $?))989990[[ $RETVAL -ne $RESULT ]] && test_fail $I result991992check_test_results $I "$ECPUS" "$STATES" "$ICPUS"993((I++))994done995echo "All $I tests of $TEST PASSED."996}997998#999# Run cpuset remote partition state transition test1000# $1 - test matrix name1001#1002run_remote_state_test()1003{1004TEST=$11005CONTROLLER=cpuset1006[[ -d rtest ]] || mkdir rtest1007cd rtest1008echo +cpuset > cgroup.subtree_control1009echo "1-7" > cpuset.cpus1010echo "1-7" > cpuset.cpus.exclusive1011CGROUP_LIST=".. . p1 p2 p1/c11 p1/c12 p2/c21 p2/c22"1012RESET_LIST="p1/c11 p1/c12 p2/c21 p2/c22 p1 p2"1013I=01014eval CNT="\${#$TEST[@]}"10151016reset_cgroup_states1017console_msg "Running remote partition state transition test ..."10181019while [[ $I -lt $CNT ]]1020do1021echo "Running test $I ..." > $CONSOLE1022[[ $VERBOSE -gt 1 ]] && {1023echo ""1024eval echo \${$TEST[$I]}1025}1026eval set -- "\${$TEST[$I]}"1027OLD_p1=$11028OLD_p2=$21029OLD_c11=$31030OLD_c12=$41031OLD_c21=$51032OLD_c22=$61033NEW_p1=$71034NEW_p2=$81035NEW_c11=$91036NEW_c12=${10}1037NEW_c21=${11}1038NEW_c22=${12}1039ECPUS=${13}1040STATES=${14}1041ICPUS=${15}10421043set_ctrl_state_noerr p1 $OLD_p11044set_ctrl_state_noerr p2 $OLD_p21045set_ctrl_state_noerr p1/c11 $OLD_c111046set_ctrl_state_noerr p1/c12 $OLD_c121047set_ctrl_state_noerr p2/c21 $OLD_c211048set_ctrl_state_noerr p2/c22 $OLD_c2210491050RETVAL=01051set_ctrl_state p1 $NEW_p1 ; ((RETVAL += $?))1052set_ctrl_state p2 $NEW_p2 ; ((RETVAL += $?))1053set_ctrl_state p1/c11 $NEW_c11; ((RETVAL += $?))1054set_ctrl_state p1/c12 $NEW_c12; ((RETVAL += $?))1055set_ctrl_state p2/c21 $NEW_c21; ((RETVAL += $?))1056set_ctrl_state p2/c22 $NEW_c22; ((RETVAL += $?))10571058[[ $RETVAL -ne 0 ]] && test_fail $I result10591060check_test_results $I "$ECPUS" "$STATES" "$ICPUS"1061((I++))1062done1063cd ..1064rmdir rtest1065echo "All $I tests of $TEST PASSED."1066}10671068#1069# Testing the new "isolated" partition root type1070#1071test_isolated()1072{1073cd $CGROUP2/test1074echo 2-3 > cpuset.cpus1075TYPE=$(cat cpuset.cpus.partition)1076[[ $TYPE = member ]] || echo member > cpuset.cpus.partition10771078console_msg "Change from member to root"1079test_partition root10801081console_msg "Change from root to isolated"1082test_partition isolated10831084console_msg "Change from isolated to member"1085test_partition member10861087console_msg "Change from member to isolated"1088test_partition isolated10891090console_msg "Change from isolated to root"1091test_partition root10921093console_msg "Change from root to member"1094test_partition member10951096#1097# Testing partition root with no cpu1098#1099console_msg "Distribute all cpus to child partition"1100echo +cpuset > cgroup.subtree_control1101test_partition root11021103mkdir A11104cd A11105echo 2-3 > cpuset.cpus1106test_partition root1107test_effective_cpus 2-31108cd ..1109test_effective_cpus ""11101111console_msg "Moving task to partition test"1112test_add_proc "No space left"1113cd A11114test_add_proc ""1115cd ..11161117console_msg "Shrink and expand child partition"1118cd A11119echo 2 > cpuset.cpus1120cd ..1121test_effective_cpus 31122cd A11123echo 2-3 > cpuset.cpus1124cd ..1125test_effective_cpus ""11261127# Cleaning up1128console_msg "Cleaning up"1129echo $$ > $CGROUP2/cgroup.procs1130[[ -d A1 ]] && rmdir A11131null_isolcpus_check1132pause 0.051133}11341135#1136# Wait for inotify event for the given file and read it1137# $1: cgroup file to wait for1138# $2: file to store the read result1139#1140wait_inotify()1141{1142CGROUP_FILE=$11143OUTPUT_FILE=$211441145$WAIT_INOTIFY $CGROUP_FILE1146cat $CGROUP_FILE > $OUTPUT_FILE1147}11481149#1150# Test if inotify events are properly generated when going into and out of1151# invalid partition state.1152#1153test_inotify()1154{1155ERR=01156PRS=/tmp/.prs_$$1157cd $CGROUP2/test1158[[ -f $WAIT_INOTIFY ]] || {1159echo "wait_inotify not found, inotify test SKIPPED."1160return1161}11621163pause 0.011164echo 1 > cpuset.cpus1165echo 0 > cgroup.procs1166echo root > cpuset.cpus.partition1167pause 0.011168rm -f $PRS1169wait_inotify $PWD/cpuset.cpus.partition $PRS &1170pause 0.011171set_ctrl_state . "O1=0"1172pause 0.011173check_cgroup_states ".:P-1"1174if [[ $? -ne 0 ]]1175then1176echo "FAILED: Inotify test - partition not invalid"1177ERR=11178elif [[ ! -f $PRS ]]1179then1180echo "FAILED: Inotify test - event not generated"1181ERR=11182kill %11183elif [[ $(cat $PRS) != "root invalid"* ]]1184then1185echo "FAILED: Inotify test - incorrect state"1186cat $PRS1187ERR=11188fi1189online_cpus1190echo member > cpuset.cpus.partition1191echo 0 > ../cgroup.procs1192if [[ $ERR -ne 0 ]]1193then1194exit 11195else1196echo "Inotify test PASSED"1197fi1198echo member > cpuset.cpus.partition1199echo "" > cpuset.cpus1200}12011202trap cleanup 0 2 3 61203run_state_test TEST_MATRIX1204run_remote_state_test REMOTE_TEST_MATRIX1205test_isolated1206test_inotify1207echo "All tests PASSED."120812091210