Path: blob/master/tools/testing/selftests/cgroup/test_cpuset_prs.sh
26285 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-3|A2:1-3|A3:2-3|B1:2-3 A1:P0|A3:P0|B1:P-2"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:4-6 A1:P-2|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 invalidate partition and its siblings391" C0-1:P1 . . C2-3 C0-2 . . . 0 A1:0-2|B1:2-3 A1:P-1|B1:P0"392" C0-1:P1 . . P1:C2-3 C0-2 . . . 0 A1:0-2|B1:2-3 A1:P-1|B1:P-1"393" C0-1 . . P1:C2-3 C0-2 . . . 0 A1:0-2|B1:2-3 A1:P0|B1:P-1"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# old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS420# ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ --------421# Failure cases:422423# A task cannot be added to a partition with no cpu424"C2-3:P1:S+ C3:P1 . . O2=0:T . . . 1 A1:|A2:3 A1:P1|A2:P1"425426# Changes to cpuset.cpus.exclusive that violate exclusivity rule is rejected427" C0-3 . . C4-5 X0-3 . . X3-5 1 A1:0-3|B1:4-5"428429# cpuset.cpus cannot be a subset of sibling cpuset.cpus.exclusive430" C0-3 . . C4-5 X3-5 . . . 1 A1:0-3|B1:4-5"431)432433#434# Cpuset controller remote partition test matrix.435#436# Cgroup test hierarchy437#438# root439# |440# rtest (cpuset.cpus.exclusive=1-7)441# |442# +------+------+443# | |444# p1 p2445# +--+--+ +--+--+446# | | | |447# c11 c12 c21 c22448#449# REMOTE_TEST_MATRIX uses the same notational convention as TEST_MATRIX.450# Only CPUs 1-7 should be used.451#452REMOTE_TEST_MATRIX=(453# old-p1 old-p2 old-c11 old-c12 old-c21 old-c22454# new-p1 new-p2 new-c11 new-c12 new-c21 new-c22 ECPUs Pstate ISOLCPUS455# ------ ------ ------- ------- ------- ------- ----- ------ --------456" X1-3:S+ X4-6:S+ X1-2 X3 X4-5 X6 \457. . P2 P2 P2 P2 c11:1-2|c12:3|c21:4-5|c22:6 \458c11:P2|c12:P2|c21:P2|c22:P2 1-6"459" CX1-4:S+ . X1-2:P2 C3 . . \460. . . C3-4 . . p1:3-4|c11:1-2|c12:3-4 \461p1:P0|c11:P2|c12:P0 1-2"462" CX1-4:S+ . X1-2:P2 . . . \463X2-4 . . . . . p1:1,3-4|c11:2 \464p1:P0|c11:P2 2"465" CX1-5:S+ . X1-2:P2 X3-5:P1 . . \466X2-4 . . . . . p1:1,5|c11:2|c12:3-4 \467p1:P0|c11:P2|c12:P1 2"468" CX1-4:S+ . X1-2:P2 X3-4:P1 . . \469. . X2 . . . p1:1|c11:2|c12:3-4 \470p1:P0|c11:P2|c12:P1 2"471# p1 as member, will get its effective CPUs from its parent rtest472" CX1-4:S+ . X1-2:P2 X3-4:P1 . . \473. . X1 CX2-4 . . p1:5-7|c11:1|c12:2-4 \474p1:P0|c11:P2|c12:P1 1"475" CX1-4:S+ X5-6:P1:S+ . . . . \476. . X1-2:P2 X4-5:P1 . X1-7:P2 p1:3|c11:1-2|c12:4:c22:5-6 \477p1:P0|p2:P1|c11:P2|c12:P1|c22:P2 \4781-2,4-6|1-2,5-6"479)480481#482# Write to the cpu online file483# $1 - <c>=<v> where <c> = cpu number, <v> value to be written484#485write_cpu_online()486{487CPU=${1%=*}488VAL=${1#*=}489CPUFILE=//sys/devices/system/cpu/cpu${CPU}/online490if [[ $VAL -eq 0 ]]491then492OFFLINE_CPUS="$OFFLINE_CPUS $CPU"493else494[[ -n "$OFFLINE_CPUS" ]] && {495OFFLINE_CPUS=$(echo $CPU $CPU $OFFLINE_CPUS | fmt -1 |\496sort | uniq -u)497}498fi499echo $VAL > $CPUFILE500pause 0.05501}502503#504# Set controller state505# $1 - cgroup directory506# $2 - state507# $3 - showerr508#509# The presence of ":" in state means transition from one to the next.510#511set_ctrl_state()512{513TMPMSG=/tmp/.msg_$$514CGRP=$1515STATE=$2516SHOWERR=${3}517CTRL=${CTRL:=$CONTROLLER}518HASERR=0519REDIRECT="2> $TMPMSG"520[[ -z "$STATE" || "$STATE" = '.' ]] && return 0521[[ $VERBOSE -gt 0 ]] && SHOWERR=1522523rm -f $TMPMSG524for CMD in $(echo $STATE | sed -e "s/:/ /g")525do526TFILE=$CGRP/cgroup.procs527SFILE=$CGRP/cgroup.subtree_control528PFILE=$CGRP/cpuset.cpus.partition529CFILE=$CGRP/cpuset.cpus530XFILE=$CGRP/cpuset.cpus.exclusive531case $CMD in532S*) PREFIX=${CMD#?}533COMM="echo ${PREFIX}${CTRL} > $SFILE"534eval $COMM $REDIRECT535;;536X*)537CPUS=${CMD#?}538COMM="echo $CPUS > $XFILE"539eval $COMM $REDIRECT540;;541CX*)542CPUS=${CMD#??}543COMM="echo $CPUS > $CFILE; echo $CPUS > $XFILE"544eval $COMM $REDIRECT545;;546C*) CPUS=${CMD#?}547COMM="echo $CPUS > $CFILE"548eval $COMM $REDIRECT549;;550P*) VAL=${CMD#?}551case $VAL in5520) VAL=member553;;5541) VAL=root555;;5562) VAL=isolated557;;558*)559echo "Invalid partition state - $VAL"560exit 1561;;562esac563COMM="echo $VAL > $PFILE"564eval $COMM $REDIRECT565;;566O*) VAL=${CMD#?}567write_cpu_online $VAL568;;569T*) COMM="echo 0 > $TFILE"570eval $COMM $REDIRECT571;;572*) echo "Unknown command: $CMD"573exit 1574;;575esac576RET=$?577[[ $RET -ne 0 ]] && {578[[ -n "$SHOWERR" ]] && {579echo "$COMM"580cat $TMPMSG581}582HASERR=1583}584pause 0.01585rm -f $TMPMSG586done587return $HASERR588}589590set_ctrl_state_noerr()591{592CGRP=$1593STATE=$2594[[ -d $CGRP ]] || mkdir $CGRP595set_ctrl_state $CGRP $STATE 1596[[ $? -ne 0 ]] && {597echo "ERROR: Failed to set $2 to cgroup $1!"598exit 1599}600}601602online_cpus()603{604[[ -n "OFFLINE_CPUS" ]] && {605for C in $OFFLINE_CPUS606do607write_cpu_online ${C}=1608done609}610}611612#613# Remove all the test cgroup directories614#615reset_cgroup_states()616{617echo 0 > $CGROUP2/cgroup.procs618online_cpus619rmdir $RESET_LIST > /dev/null 2>&1620}621622dump_states()623{624for DIR in $CGROUP_LIST625do626CPUS=$DIR/cpuset.cpus627ECPUS=$DIR/cpuset.cpus.effective628XCPUS=$DIR/cpuset.cpus.exclusive629XECPUS=$DIR/cpuset.cpus.exclusive.effective630PRS=$DIR/cpuset.cpus.partition631PCPUS=$DIR/.__DEBUG__.cpuset.cpus.subpartitions632ISCPUS=$DIR/cpuset.cpus.isolated633[[ -e $CPUS ]] && echo "$CPUS: $(cat $CPUS)"634[[ -e $XCPUS ]] && echo "$XCPUS: $(cat $XCPUS)"635[[ -e $ECPUS ]] && echo "$ECPUS: $(cat $ECPUS)"636[[ -e $XECPUS ]] && echo "$XECPUS: $(cat $XECPUS)"637[[ -e $PRS ]] && echo "$PRS: $(cat $PRS)"638[[ -e $PCPUS ]] && echo "$PCPUS: $(cat $PCPUS)"639[[ -e $ISCPUS ]] && echo "$ISCPUS: $(cat $ISCPUS)"640done641}642643#644# Set the actual cgroup directory into $CGRP_DIR645# $1 - cgroup name646#647set_cgroup_dir()648{649CGRP_DIR=$1650[[ $CGRP_DIR = A2 ]] && CGRP_DIR=A1/A2651[[ $CGRP_DIR = A3 ]] && CGRP_DIR=A1/A2/A3652[[ $CGRP_DIR = c11 ]] && CGRP_DIR=p1/c11653[[ $CGRP_DIR = c12 ]] && CGRP_DIR=p1/c12654[[ $CGRP_DIR = c21 ]] && CGRP_DIR=p2/c21655[[ $CGRP_DIR = c22 ]] && CGRP_DIR=p2/c22656}657658#659# Check effective cpus660# $1 - check string, format: <cgroup>:<cpu-list>[|<cgroup>:<cpu-list>]*661#662check_effective_cpus()663{664CHK_STR=$1665for CHK in $(echo $CHK_STR | sed -e "s/|/ /g")666do667set -- $(echo $CHK | sed -e "s/:/ /g")668CGRP=$1669EXPECTED_CPUS=$2670ACTUAL_CPUS=671if [[ $CGRP = X* ]]672then673CGRP=${CGRP#X}674FILE=cpuset.cpus.exclusive.effective675else676FILE=cpuset.cpus.effective677fi678set_cgroup_dir $CGRP679[[ -e $CGRP_DIR/$FILE ]] || return 1680ACTUAL_CPUS=$(cat $CGRP_DIR/$FILE)681[[ $EXPECTED_CPUS = $ACTUAL_CPUS ]] || return 1682done683}684685#686# Check cgroup states687# $1 - check string, format: <cgroup>:<state>[|<cgroup>:<state>]*688#689check_cgroup_states()690{691CHK_STR=$1692for CHK in $(echo $CHK_STR | sed -e "s/|/ /g")693do694set -- $(echo $CHK | sed -e "s/:/ /g")695CGRP=$1696EXPECTED_STATE=$2697FILE=698EVAL=$(expr substr $EXPECTED_STATE 2 2)699700set_cgroup_dir $CGRP701case $EXPECTED_STATE in702P*) FILE=$CGRP_DIR/cpuset.cpus.partition703;;704*) echo "Unknown state: $EXPECTED_STATE!"705exit 1706;;707esac708ACTUAL_STATE=$(cat $FILE)709710case "$ACTUAL_STATE" in711member) VAL=0712;;713root) VAL=1714;;715isolated)716VAL=2717;;718"root invalid"*)719VAL=-1720;;721"isolated invalid"*)722VAL=-2723;;724esac725[[ $EVAL != $VAL ]] && return 1726727#728# For root partition, dump sched-domains info to console if729# verbose mode set for manual comparison with sched debug info.730#731[[ $VAL -eq 1 && $VERBOSE -gt 0 ]] && {732DOMS=$(cat $CGRP_DIR/cpuset.cpus.effective)733[[ -n "$DOMS" ]] &&734echo " [$CGRP_DIR] sched-domain: $DOMS" > $CONSOLE735}736done737return 0738}739740#741# Get isolated (including offline) CPUs by looking at742# /sys/kernel/debug/sched/domains and cpuset.cpus.isolated control file,743# if available, and compare that with the expected value.744#745# Note that isolated CPUs from the sched/domains context include offline746# CPUs as well as CPUs in non-isolated 1-CPU partition. Those CPUs may747# not be included in the cpuset.cpus.isolated control file which contains748# only CPUs in isolated partitions as well as those that are isolated at749# boot time.750#751# $1 - expected isolated cpu list(s) <isolcpus1>{,<isolcpus2>}752# <isolcpus1> - expected sched/domains value753# <isolcpus2> - cpuset.cpus.isolated value = <isolcpus1> if not defined754#755check_isolcpus()756{757EXPECTED_ISOLCPUS=$1758ISCPUS=${CGROUP2}/cpuset.cpus.isolated759ISOLCPUS=$(cat $ISCPUS)760LASTISOLCPU=761SCHED_DOMAINS=/sys/kernel/debug/sched/domains762if [[ $EXPECTED_ISOLCPUS = . ]]763then764EXPECTED_ISOLCPUS=765EXPECTED_SDOMAIN=766elif [[ $(expr $EXPECTED_ISOLCPUS : ".*|.*") > 0 ]]767then768set -- $(echo $EXPECTED_ISOLCPUS | sed -e "s/|/ /g")769EXPECTED_ISOLCPUS=$2770EXPECTED_SDOMAIN=$1771else772EXPECTED_SDOMAIN=$EXPECTED_ISOLCPUS773fi774775#776# Appending pre-isolated CPUs777# Even though CPU #8 isn't used for testing, it can't be pre-isolated778# to make appending those CPUs easier.779#780[[ -n "$BOOT_ISOLCPUS" ]] && {781EXPECTED_ISOLCPUS=${EXPECTED_ISOLCPUS:+${EXPECTED_ISOLCPUS},}${BOOT_ISOLCPUS}782EXPECTED_SDOMAIN=${EXPECTED_SDOMAIN:+${EXPECTED_SDOMAIN},}${BOOT_ISOLCPUS}783}784785#786# Check cpuset.cpus.isolated cpumask787#788[[ "$EXPECTED_ISOLCPUS" != "$ISOLCPUS" ]] && {789# Take a 50ms pause and try again790pause 0.05791ISOLCPUS=$(cat $ISCPUS)792}793[[ "$EXPECTED_ISOLCPUS" != "$ISOLCPUS" ]] && return 1794ISOLCPUS=795EXPECTED_ISOLCPUS=$EXPECTED_SDOMAIN796797#798# Use the sched domain in debugfs to check isolated CPUs, if available799#800[[ -d $SCHED_DOMAINS ]] || return 0801802for ((CPU=0; CPU < $NR_CPUS; CPU++))803do804[[ -n "$(ls ${SCHED_DOMAINS}/cpu$CPU)" ]] && continue805806if [[ -z "$LASTISOLCPU" ]]807then808ISOLCPUS=$CPU809LASTISOLCPU=$CPU810elif [[ "$LASTISOLCPU" -eq $((CPU - 1)) ]]811then812echo $ISOLCPUS | grep -q "\<$LASTISOLCPU\$"813if [[ $? -eq 0 ]]814then815ISOLCPUS=${ISOLCPUS}-816fi817LASTISOLCPU=$CPU818else819if [[ $ISOLCPUS = *- ]]820then821ISOLCPUS=${ISOLCPUS}$LASTISOLCPU822fi823ISOLCPUS=${ISOLCPUS},$CPU824LASTISOLCPU=$CPU825fi826done827[[ "$ISOLCPUS" = *- ]] && ISOLCPUS=${ISOLCPUS}$LASTISOLCPU828829[[ "$EXPECTED_SDOMAIN" = "$ISOLCPUS" ]]830}831832test_fail()833{834TESTNUM=$1835TESTTYPE=$2836ADDINFO=$3837echo "Test $TEST[$TESTNUM] failed $TESTTYPE check!"838[[ -n "$ADDINFO" ]] && echo "*** $ADDINFO ***"839eval echo \${$TEST[$I]}840echo841dump_states842exit 1843}844845#846# Check to see if there are unexpected isolated CPUs left beyond the boot847# time isolated ones.848#849null_isolcpus_check()850{851[[ $VERBOSE -gt 0 ]] || return 0852# Retry a few times before printing error853RETRY=0854while [[ $RETRY -lt 8 ]]855do856pause 0.02857check_isolcpus "."858[[ $? -eq 0 ]] && return 0859((RETRY++))860done861echo "Unexpected isolated CPUs: $ISOLCPUS"862dump_states863exit 1864}865866#867# Check state transition test result868# $1 - Test number869# $2 - Expected effective CPU values870# $3 - Expected partition states871# $4 - Expected isolated CPUs872#873check_test_results()874{875_NR=$1876_ECPUS="$2"877_PSTATES="$3"878_ISOLCPUS="$4"879880[[ -n "$_ECPUS" && "$_ECPUS" != . ]] && {881check_effective_cpus $_ECPUS882[[ $? -ne 0 ]] && test_fail $_NR "effective CPU" \883"Cgroup $CGRP: expected $EXPECTED_CPUS, got $ACTUAL_CPUS"884}885886[[ -n "$_PSTATES" && "$_PSTATES" != . ]] && {887check_cgroup_states $_PSTATES888[[ $? -ne 0 ]] && test_fail $_NR states \889"Cgroup $CGRP: expected $EXPECTED_STATE, got $ACTUAL_STATE"890}891892# Compare the expected isolated CPUs with the actual ones,893# if available894[[ -n "$_ISOLCPUS" ]] && {895check_isolcpus $_ISOLCPUS896[[ $? -ne 0 ]] && {897[[ -n "$BOOT_ISOLCPUS" ]] && _ISOLCPUS=${_ISOLCPUS},${BOOT_ISOLCPUS}898test_fail $_NR "isolated CPU" \899"Expect $_ISOLCPUS, get $ISOLCPUS instead"900}901}902reset_cgroup_states903#904# Check to see if effective cpu list changes905#906_NEWLIST=$(cat $CGROUP2/cpuset.cpus.effective)907RETRY=0908while [[ $_NEWLIST != $CPULIST && $RETRY -lt 8 ]]909do910# Wait a bit longer & recheck a few times911pause 0.02912((RETRY++))913_NEWLIST=$(cat $CGROUP2/cpuset.cpus.effective)914done915[[ $_NEWLIST != $CPULIST ]] && {916echo "Effective cpus changed to $_NEWLIST after test $_NR!"917exit 1918}919null_isolcpus_check920[[ $VERBOSE -gt 0 ]] && echo "Test $I done."921}922923#924# Run cpuset state transition test925# $1 - test matrix name926#927# This test is somewhat fragile as delays (sleep x) are added in various928# places to make sure state changes are fully propagated before the next929# action. These delays may need to be adjusted if running in a slower machine.930#931run_state_test()932{933TEST=$1934CONTROLLER=cpuset935CGROUP_LIST=". A1 A1/A2 A1/A2/A3 B1"936RESET_LIST="A1/A2/A3 A1/A2 A1 B1"937I=0938eval CNT="\${#$TEST[@]}"939940reset_cgroup_states941console_msg "Running state transition test ..."942943while [[ $I -lt $CNT ]]944do945echo "Running test $I ..." > $CONSOLE946[[ $VERBOSE -gt 1 ]] && {947echo ""948eval echo \${$TEST[$I]}949}950eval set -- "\${$TEST[$I]}"951OLD_A1=$1952OLD_A2=$2953OLD_A3=$3954OLD_B1=$4955NEW_A1=$5956NEW_A2=$6957NEW_A3=$7958NEW_B1=$8959RESULT=$9960ECPUS=${10}961STATES=${11}962ICPUS=${12}963964set_ctrl_state_noerr A1 $OLD_A1965set_ctrl_state_noerr A1/A2 $OLD_A2966set_ctrl_state_noerr A1/A2/A3 $OLD_A3967set_ctrl_state_noerr B1 $OLD_B1968969RETVAL=0970set_ctrl_state A1 $NEW_A1; ((RETVAL += $?))971set_ctrl_state A1/A2 $NEW_A2; ((RETVAL += $?))972set_ctrl_state A1/A2/A3 $NEW_A3; ((RETVAL += $?))973set_ctrl_state B1 $NEW_B1; ((RETVAL += $?))974975[[ $RETVAL -ne $RESULT ]] && test_fail $I result976977check_test_results $I "$ECPUS" "$STATES" "$ICPUS"978((I++))979done980echo "All $I tests of $TEST PASSED."981}982983#984# Run cpuset remote partition state transition test985# $1 - test matrix name986#987run_remote_state_test()988{989TEST=$1990CONTROLLER=cpuset991[[ -d rtest ]] || mkdir rtest992cd rtest993echo +cpuset > cgroup.subtree_control994echo "1-7" > cpuset.cpus995echo "1-7" > cpuset.cpus.exclusive996CGROUP_LIST=".. . p1 p2 p1/c11 p1/c12 p2/c21 p2/c22"997RESET_LIST="p1/c11 p1/c12 p2/c21 p2/c22 p1 p2"998I=0999eval CNT="\${#$TEST[@]}"10001001reset_cgroup_states1002console_msg "Running remote partition state transition test ..."10031004while [[ $I -lt $CNT ]]1005do1006echo "Running test $I ..." > $CONSOLE1007[[ $VERBOSE -gt 1 ]] && {1008echo ""1009eval echo \${$TEST[$I]}1010}1011eval set -- "\${$TEST[$I]}"1012OLD_p1=$11013OLD_p2=$21014OLD_c11=$31015OLD_c12=$41016OLD_c21=$51017OLD_c22=$61018NEW_p1=$71019NEW_p2=$81020NEW_c11=$91021NEW_c12=${10}1022NEW_c21=${11}1023NEW_c22=${12}1024ECPUS=${13}1025STATES=${14}1026ICPUS=${15}10271028set_ctrl_state_noerr p1 $OLD_p11029set_ctrl_state_noerr p2 $OLD_p21030set_ctrl_state_noerr p1/c11 $OLD_c111031set_ctrl_state_noerr p1/c12 $OLD_c121032set_ctrl_state_noerr p2/c21 $OLD_c211033set_ctrl_state_noerr p2/c22 $OLD_c2210341035RETVAL=01036set_ctrl_state p1 $NEW_p1 ; ((RETVAL += $?))1037set_ctrl_state p2 $NEW_p2 ; ((RETVAL += $?))1038set_ctrl_state p1/c11 $NEW_c11; ((RETVAL += $?))1039set_ctrl_state p1/c12 $NEW_c12; ((RETVAL += $?))1040set_ctrl_state p2/c21 $NEW_c21; ((RETVAL += $?))1041set_ctrl_state p2/c22 $NEW_c22; ((RETVAL += $?))10421043[[ $RETVAL -ne 0 ]] && test_fail $I result10441045check_test_results $I "$ECPUS" "$STATES" "$ICPUS"1046((I++))1047done1048cd ..1049rmdir rtest1050echo "All $I tests of $TEST PASSED."1051}10521053#1054# Testing the new "isolated" partition root type1055#1056test_isolated()1057{1058cd $CGROUP2/test1059echo 2-3 > cpuset.cpus1060TYPE=$(cat cpuset.cpus.partition)1061[[ $TYPE = member ]] || echo member > cpuset.cpus.partition10621063console_msg "Change from member to root"1064test_partition root10651066console_msg "Change from root to isolated"1067test_partition isolated10681069console_msg "Change from isolated to member"1070test_partition member10711072console_msg "Change from member to isolated"1073test_partition isolated10741075console_msg "Change from isolated to root"1076test_partition root10771078console_msg "Change from root to member"1079test_partition member10801081#1082# Testing partition root with no cpu1083#1084console_msg "Distribute all cpus to child partition"1085echo +cpuset > cgroup.subtree_control1086test_partition root10871088mkdir A11089cd A11090echo 2-3 > cpuset.cpus1091test_partition root1092test_effective_cpus 2-31093cd ..1094test_effective_cpus ""10951096console_msg "Moving task to partition test"1097test_add_proc "No space left"1098cd A11099test_add_proc ""1100cd ..11011102console_msg "Shrink and expand child partition"1103cd A11104echo 2 > cpuset.cpus1105cd ..1106test_effective_cpus 31107cd A11108echo 2-3 > cpuset.cpus1109cd ..1110test_effective_cpus ""11111112# Cleaning up1113console_msg "Cleaning up"1114echo $$ > $CGROUP2/cgroup.procs1115[[ -d A1 ]] && rmdir A11116null_isolcpus_check1117pause 0.051118}11191120#1121# Wait for inotify event for the given file and read it1122# $1: cgroup file to wait for1123# $2: file to store the read result1124#1125wait_inotify()1126{1127CGROUP_FILE=$11128OUTPUT_FILE=$211291130$WAIT_INOTIFY $CGROUP_FILE1131cat $CGROUP_FILE > $OUTPUT_FILE1132}11331134#1135# Test if inotify events are properly generated when going into and out of1136# invalid partition state.1137#1138test_inotify()1139{1140ERR=01141PRS=/tmp/.prs_$$1142cd $CGROUP2/test1143[[ -f $WAIT_INOTIFY ]] || {1144echo "wait_inotify not found, inotify test SKIPPED."1145return1146}11471148pause 0.011149echo 1 > cpuset.cpus1150echo 0 > cgroup.procs1151echo root > cpuset.cpus.partition1152pause 0.011153rm -f $PRS1154wait_inotify $PWD/cpuset.cpus.partition $PRS &1155pause 0.011156set_ctrl_state . "O1=0"1157pause 0.011158check_cgroup_states ".:P-1"1159if [[ $? -ne 0 ]]1160then1161echo "FAILED: Inotify test - partition not invalid"1162ERR=11163elif [[ ! -f $PRS ]]1164then1165echo "FAILED: Inotify test - event not generated"1166ERR=11167kill %11168elif [[ $(cat $PRS) != "root invalid"* ]]1169then1170echo "FAILED: Inotify test - incorrect state"1171cat $PRS1172ERR=11173fi1174online_cpus1175echo member > cpuset.cpus.partition1176echo 0 > ../cgroup.procs1177if [[ $ERR -ne 0 ]]1178then1179exit 11180else1181echo "Inotify test PASSED"1182fi1183echo member > cpuset.cpus.partition1184echo "" > cpuset.cpus1185}11861187trap cleanup 0 2 3 61188run_state_test TEST_MATRIX1189run_remote_state_test REMOTE_TEST_MATRIX1190test_isolated1191test_inotify1192echo "All tests PASSED."119311941195