1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3# 4# Test for cpuset v2 partition root state (PRS) 5# 6# The sched verbose flag is set, if available, so that the console log 7# can be examined for the correct setting of scheduling domain. 8# 9 10skip_test() { 11 echo "$1" 12 echo "Test SKIPPED" 13 exit 0 14} 15 16[[ $(id -u) -eq 0 ]] || skip_test "Test must be run as root!" 17 18# Set sched verbose flag, if available 19if [[ -d /sys/kernel/debug/sched ]] 20then 21 # Used to restore the original setting during cleanup 22 SCHED_DEBUG=$(cat /sys/kernel/debug/sched/verbose) 23 echo Y > /sys/kernel/debug/sched/verbose 24fi 25 26# Get wait_inotify location 27WAIT_INOTIFY=$(cd $(dirname $0); pwd)/wait_inotify 28 29# Find cgroup v2 mount point 30CGROUP2=$(mount -t cgroup2 | head -1 | awk -e '{print $3}') 31[[ -n "$CGROUP2" ]] || skip_test "Cgroup v2 mount point not found!" 32 33CPUS=$(lscpu | grep "^CPU(s):" | sed -e "s/.*:[[:space:]]*//") 34[[ $CPUS -lt 8 ]] && skip_test "Test needs at least 8 cpus available!" 35 36# Set verbose flag and delay factor 37PROG=$1 38VERBOSE= 39DELAY_FACTOR=1 40while [[ "$1" = -* ]] 41do 42 case "$1" in 43 -v) VERBOSE=1 44 break 45 ;; 46 -d) DELAY_FACTOR=$2 47 shift 48 break 49 ;; 50 *) echo "Usage: $PROG [-v] [-d <delay-factor>" 51 exit 52 ;; 53 esac 54 shift 55done 56 57cd $CGROUP2 58echo +cpuset > cgroup.subtree_control 59[[ -d test ]] || mkdir test 60cd test 61 62cleanup() 63{ 64 online_cpus 65 rmdir A1/A2/A3 A1/A2 A1 B1 > /dev/null 2>&1 66 cd .. 67 rmdir test > /dev/null 2>&1 68 echo "$SCHED_DEBUG" > /sys/kernel/debug/sched/verbose 69} 70 71# Pause in ms 72pause() 73{ 74 DELAY=$1 75 LOOP=0 76 while [[ $LOOP -lt $DELAY_FACTOR ]] 77 do 78 sleep $DELAY 79 ((LOOP++)) 80 done 81 return 0 82} 83 84console_msg() 85{ 86 MSG=$1 87 echo "$MSG" 88 echo "" > /dev/console 89 echo "$MSG" > /dev/console 90 pause 0.01 91} 92 93test_partition() 94{ 95 EXPECTED_VAL=$1 96 echo $EXPECTED_VAL > cpuset.cpus.partition 97 [[ $? -eq 0 ]] || exit 1 98 ACTUAL_VAL=$(cat cpuset.cpus.partition) 99 [[ $ACTUAL_VAL != $EXPECTED_VAL ]] && { 100 echo "cpuset.cpus.partition: expect $EXPECTED_VAL, found $EXPECTED_VAL" 101 echo "Test FAILED" 102 exit 1 103 } 104} 105 106test_effective_cpus() 107{ 108 EXPECTED_VAL=$1 109 ACTUAL_VAL=$(cat cpuset.cpus.effective) 110 [[ "$ACTUAL_VAL" != "$EXPECTED_VAL" ]] && { 111 echo "cpuset.cpus.effective: expect '$EXPECTED_VAL', found '$EXPECTED_VAL'" 112 echo "Test FAILED" 113 exit 1 114 } 115} 116 117# Adding current process to cgroup.procs as a test 118test_add_proc() 119{ 120 OUTSTR="$1" 121 ERRMSG=$((echo $$ > cgroup.procs) |& cat) 122 echo $ERRMSG | grep -q "$OUTSTR" 123 [[ $? -ne 0 ]] && { 124 echo "cgroup.procs: expect '$OUTSTR', got '$ERRMSG'" 125 echo "Test FAILED" 126 exit 1 127 } 128 echo $$ > $CGROUP2/cgroup.procs # Move out the task 129} 130 131# 132# Testing the new "isolated" partition root type 133# 134test_isolated() 135{ 136 echo 2-3 > cpuset.cpus 137 TYPE=$(cat cpuset.cpus.partition) 138 [[ $TYPE = member ]] || echo member > cpuset.cpus.partition 139 140 console_msg "Change from member to root" 141 test_partition root 142 143 console_msg "Change from root to isolated" 144 test_partition isolated 145 146 console_msg "Change from isolated to member" 147 test_partition member 148 149 console_msg "Change from member to isolated" 150 test_partition isolated 151 152 console_msg "Change from isolated to root" 153 test_partition root 154 155 console_msg "Change from root to member" 156 test_partition member 157 158 # 159 # Testing partition root with no cpu 160 # 161 console_msg "Distribute all cpus to child partition" 162 echo +cpuset > cgroup.subtree_control 163 test_partition root 164 165 mkdir A1 166 cd A1 167 echo 2-3 > cpuset.cpus 168 test_partition root 169 test_effective_cpus 2-3 170 cd .. 171 test_effective_cpus "" 172 173 console_msg "Moving task to partition test" 174 test_add_proc "No space left" 175 cd A1 176 test_add_proc "" 177 cd .. 178 179 console_msg "Shrink and expand child partition" 180 cd A1 181 echo 2 > cpuset.cpus 182 cd .. 183 test_effective_cpus 3 184 cd A1 185 echo 2-3 > cpuset.cpus 186 cd .. 187 test_effective_cpus "" 188 189 # Cleaning up 190 console_msg "Cleaning up" 191 echo $$ > $CGROUP2/cgroup.procs 192 [[ -d A1 ]] && rmdir A1 193} 194 195# 196# Cpuset controller state transition test matrix. 197# 198# Cgroup test hierarchy 199# 200# test -- A1 -- A2 -- A3 201# \- B1 202# 203# P<v> = set cpus.partition (0:member, 1:root, 2:isolated, -1:root invalid) 204# C<l> = add cpu-list 205# S<p> = use prefix in subtree_control 206# T = put a task into cgroup 207# O<c>-<v> = Write <v> to CPU online file of <c> 208# 209SETUP_A123_PARTITIONS="C1-3:P1:S+ C2-3:P1:S+ C3:P1" 210TEST_MATRIX=( 211 # test old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate 212 # ---- ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ 213 " S+ C0-1 . . C2-3 S+ C4-5 . . 0 A2:0-1" 214 " S+ C0-1 . . C2-3 P1 . . . 0 " 215 " S+ C0-1 . . C2-3 P1:S+ C0-1:P1 . . 0 " 216 " S+ C0-1 . . C2-3 P1:S+ C1:P1 . . 0 " 217 " S+ C0-1:S+ . . C2-3 . . . P1 0 " 218 " S+ C0-1:P1 . . C2-3 S+ C1 . . 0 " 219 " S+ C0-1:P1 . . C2-3 S+ C1:P1 . . 0 " 220 " S+ C0-1:P1 . . C2-3 S+ C1:P1 . P1 0 " 221 " S+ C0-1:P1 . . C2-3 C4-5 . . . 0 A1:4-5" 222 " S+ C0-1:P1 . . C2-3 S+:C4-5 . . . 0 A1:4-5" 223 " S+ C0-1 . . C2-3:P1 . . . C2 0 " 224 " S+ C0-1 . . C2-3:P1 . . . C4-5 0 B1:4-5" 225 " S+ C0-3:P1:S+ C2-3:P1 . . . . . . 0 A1:0-1,A2:2-3" 226 " S+ C0-3:P1:S+ C2-3:P1 . . C1-3 . . . 0 A1:1,A2:2-3" 227 " S+ C2-3:P1:S+ C3:P1 . . C3 . . . 0 A1:,A2:3 A1:P1,A2:P1" 228 " S+ C2-3:P1:S+ C3:P1 . . C3 P0 . . 0 A1:3,A2:3 A1:P1,A2:P0" 229 " S+ C2-3:P1:S+ C2:P1 . . C2-4 . . . 0 A1:3-4,A2:2" 230 " S+ C2-3:P1:S+ C3:P1 . . C3 . . C0-2 0 A1:,B1:0-2 A1:P1,A2:P1" 231 " S+ $SETUP_A123_PARTITIONS . C2-3 . . . 0 A1:,A2:2,A3:3 A1:P1,A2:P1,A3:P1" 232 233 # CPU offlining cases: 234 " S+ C0-1 . . C2-3 S+ C4-5 . O2-0 0 A1:0-1,B1:3" 235 " S+ C0-3:P1:S+ C2-3:P1 . . O2-0 . . . 0 A1:0-1,A2:3" 236 " S+ C0-3:P1:S+ C2-3:P1 . . O2-0 O2-1 . . 0 A1:0-1,A2:2-3" 237 " S+ C0-3:P1:S+ C2-3:P1 . . O1-0 . . . 0 A1:0,A2:2-3" 238 " S+ C0-3:P1:S+ C2-3:P1 . . O1-0 O1-1 . . 0 A1:0-1,A2:2-3" 239 " S+ C2-3:P1:S+ C3:P1 . . O3-0 O3-1 . . 0 A1:2,A2:3 A1:P1,A2:P1" 240 " S+ C2-3:P1:S+ C3:P2 . . O3-0 O3-1 . . 0 A1:2,A2:3 A1:P1,A2:P2" 241 " S+ C2-3:P1:S+ C3:P1 . . O2-0 O2-1 . . 0 A1:2,A2:3 A1:P1,A2:P1" 242 " S+ C2-3:P1:S+ C3:P2 . . O2-0 O2-1 . . 0 A1:2,A2:3 A1:P1,A2:P2" 243 " S+ C2-3:P1:S+ C3:P1 . . O2-0 . . . 0 A1:,A2:3 A1:P1,A2:P1" 244 " S+ C2-3:P1:S+ C3:P1 . . O3-0 . . . 0 A1:2,A2: A1:P1,A2:P1" 245 " S+ C2-3:P1:S+ C3:P1 . . T:O2-0 . . . 0 A1:3,A2:3 A1:P1,A2:P-1" 246 " S+ C2-3:P1:S+ C3:P1 . . . T:O3-0 . . 0 A1:2,A2:2 A1:P1,A2:P-1" 247 " S+ $SETUP_A123_PARTITIONS . O1-0 . . . 0 A1:,A2:2,A3:3 A1:P1,A2:P1,A3:P1" 248 " S+ $SETUP_A123_PARTITIONS . O2-0 . . . 0 A1:1,A2:,A3:3 A1:P1,A2:P1,A3:P1" 249 " S+ $SETUP_A123_PARTITIONS . O3-0 . . . 0 A1:1,A2:2,A3: A1:P1,A2:P1,A3:P1" 250 " S+ $SETUP_A123_PARTITIONS . T:O1-0 . . . 0 A1:2-3,A2:2-3,A3:3 A1:P1,A2:P-1,A3:P-1" 251 " S+ $SETUP_A123_PARTITIONS . . T:O2-0 . . 0 A1:1,A2:3,A3:3 A1:P1,A2:P1,A3:P-1" 252 " S+ $SETUP_A123_PARTITIONS . . . T:O3-0 . 0 A1:1,A2:2,A3:2 A1:P1,A2:P1,A3:P-1" 253 " S+ $SETUP_A123_PARTITIONS . T:O1-0 O1-1 . . 0 A1:1,A2:2,A3:3 A1:P1,A2:P1,A3:P1" 254 " S+ $SETUP_A123_PARTITIONS . . T:O2-0 O2-1 . 0 A1:1,A2:2,A3:3 A1:P1,A2:P1,A3:P1" 255 " S+ $SETUP_A123_PARTITIONS . . . T:O3-0 O3-1 0 A1:1,A2:2,A3:3 A1:P1,A2:P1,A3:P1" 256 " S+ $SETUP_A123_PARTITIONS . T:O1-0 O2-0 O1-1 . 0 A1:1,A2:,A3:3 A1:P1,A2:P1,A3:P1" 257 " S+ $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" 258 259 # test old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate 260 # ---- ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ 261 # 262 # Incorrect change to cpuset.cpus invalidates partition root 263 # 264 # Adding CPUs to partition root that are not in parent's 265 # cpuset.cpus is allowed, but those extra CPUs are ignored. 266 " S+ C2-3:P1:S+ C3:P1 . . . C2-4 . . 0 A1:,A2:2-3 A1:P1,A2:P1" 267 268 # Taking away all CPUs from parent or itself if there are tasks 269 # will make the partition invalid. 270 " S+ C2-3:P1:S+ C3:P1 . . T C2-3 . . 0 A1:2-3,A2:2-3 A1:P1,A2:P-1" 271 " S+ C3:P1:S+ C3 . . T P1 . . 0 A1:3,A2:3 A1:P1,A2:P-1" 272 " S+ $SETUP_A123_PARTITIONS . T:C2-3 . . . 0 A1:2-3,A2:2-3,A3:3 A1:P1,A2:P-1,A3:P-1" 273 " S+ $SETUP_A123_PARTITIONS . T:C2-3:C1-3 . . . 0 A1:1,A2:2,A3:3 A1:P1,A2:P1,A3:P1" 274 275 # Changing a partition root to member makes child partitions invalid 276 " S+ C2-3:P1:S+ C3:P1 . . P0 . . . 0 A1:2-3,A2:3 A1:P0,A2:P-1" 277 " S+ $SETUP_A123_PARTITIONS . C2-3 P0 . . 0 A1:2-3,A2:2-3,A3:3 A1:P1,A2:P0,A3:P-1" 278 279 # cpuset.cpus can contains cpus not in parent's cpuset.cpus as long 280 # as they overlap. 281 " S+ C2-3:P1:S+ . . . . C3-4:P1 . . 0 A1:2,A2:3 A1:P1,A2:P1" 282 283 # Deletion of CPUs distributed to child cgroup is allowed. 284 " S+ C0-1:P1:S+ C1 . C2-3 C4-5 . . . 0 A1:4-5,A2:4-5" 285 286 # To become a valid partition root, cpuset.cpus must overlap parent's 287 # cpuset.cpus. 288 " S+ C0-1:P1 . . C2-3 S+ C4-5:P1 . . 0 A1:0-1,A2:0-1 A1:P1,A2:P-1" 289 290 # Enabling partition with child cpusets is allowed 291 " S+ C0-1:S+ C1 . C2-3 P1 . . . 0 A1:0-1,A2:1 A1:P1" 292 293 # A partition root with non-partition root parent is invalid, but it 294 # can be made valid if its parent becomes a partition root too. 295 " S+ C0-1:S+ C1 . C2-3 . P2 . . 0 A1:0-1,A2:1 A1:P0,A2:P-2" 296 " S+ C0-1:S+ C1:P2 . C2-3 P1 . . . 0 A1:0,A2:1 A1:P1,A2:P2" 297 298 # A non-exclusive cpuset.cpus change will invalidate partition and its siblings 299 " S+ C0-1:P1 . . C2-3 C0-2 . . . 0 A1:0-2,B1:2-3 A1:P-1,B1:P0" 300 " S+ C0-1:P1 . . P1:C2-3 C0-2 . . . 0 A1:0-2,B1:2-3 A1:P-1,B1:P-1" 301 " S+ C0-1 . . P1:C2-3 C0-2 . . . 0 A1:0-2,B1:2-3 A1:P0,B1:P-1" 302 303 # test old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate 304 # ---- ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ 305 # Failure cases: 306 307 # A task cannot be added to a partition with no cpu 308 " S+ C2-3:P1:S+ C3:P1 . . O2-0:T . . . 1 A1:,A2:3 A1:P1,A2:P1" 309) 310 311# 312# Write to the cpu online file 313# $1 - <c>-<v> where <c> = cpu number, <v> value to be written 314# 315write_cpu_online() 316{ 317 CPU=${1%-*} 318 VAL=${1#*-} 319 CPUFILE=//sys/devices/system/cpu/cpu${CPU}/online 320 if [[ $VAL -eq 0 ]] 321 then 322 OFFLINE_CPUS="$OFFLINE_CPUS $CPU" 323 else 324 [[ -n "$OFFLINE_CPUS" ]] && { 325 OFFLINE_CPUS=$(echo $CPU $CPU $OFFLINE_CPUS | fmt -1 |\ 326 sort | uniq -u) 327 } 328 fi 329 echo $VAL > $CPUFILE 330 pause 0.01 331} 332 333# 334# Set controller state 335# $1 - cgroup directory 336# $2 - state 337# $3 - showerr 338# 339# The presence of ":" in state means transition from one to the next. 340# 341set_ctrl_state() 342{ 343 TMPMSG=/tmp/.msg_$$ 344 CGRP=$1 345 STATE=$2 346 SHOWERR=${3}${VERBOSE} 347 CTRL=${CTRL:=$CONTROLLER} 348 HASERR=0 349 REDIRECT="2> $TMPMSG" 350 [[ -z "$STATE" || "$STATE" = '.' ]] && return 0 351 352 rm -f $TMPMSG 353 for CMD in $(echo $STATE | sed -e "s/:/ /g") 354 do 355 TFILE=$CGRP/cgroup.procs 356 SFILE=$CGRP/cgroup.subtree_control 357 PFILE=$CGRP/cpuset.cpus.partition 358 CFILE=$CGRP/cpuset.cpus 359 S=$(expr substr $CMD 1 1) 360 if [[ $S = S ]] 361 then 362 PREFIX=${CMD#?} 363 COMM="echo ${PREFIX}${CTRL} > $SFILE" 364 eval $COMM $REDIRECT 365 elif [[ $S = C ]] 366 then 367 CPUS=${CMD#?} 368 COMM="echo $CPUS > $CFILE" 369 eval $COMM $REDIRECT 370 elif [[ $S = P ]] 371 then 372 VAL=${CMD#?} 373 case $VAL in 374 0) VAL=member 375 ;; 376 1) VAL=root 377 ;; 378 2) VAL=isolated 379 ;; 380 *) 381 echo "Invalid partition state - $VAL" 382 exit 1 383 ;; 384 esac 385 COMM="echo $VAL > $PFILE" 386 eval $COMM $REDIRECT 387 elif [[ $S = O ]] 388 then 389 VAL=${CMD#?} 390 write_cpu_online $VAL 391 elif [[ $S = T ]] 392 then 393 COMM="echo 0 > $TFILE" 394 eval $COMM $REDIRECT 395 fi 396 RET=$? 397 [[ $RET -ne 0 ]] && { 398 [[ -n "$SHOWERR" ]] && { 399 echo "$COMM" 400 cat $TMPMSG 401 } 402 HASERR=1 403 } 404 pause 0.01 405 rm -f $TMPMSG 406 done 407 return $HASERR 408} 409 410set_ctrl_state_noerr() 411{ 412 CGRP=$1 413 STATE=$2 414 [[ -d $CGRP ]] || mkdir $CGRP 415 set_ctrl_state $CGRP $STATE 1 416 [[ $? -ne 0 ]] && { 417 echo "ERROR: Failed to set $2 to cgroup $1!" 418 exit 1 419 } 420} 421 422online_cpus() 423{ 424 [[ -n "OFFLINE_CPUS" ]] && { 425 for C in $OFFLINE_CPUS 426 do 427 write_cpu_online ${C}-1 428 done 429 } 430} 431 432# 433# Return 1 if the list of effective cpus isn't the same as the initial list. 434# 435reset_cgroup_states() 436{ 437 echo 0 > $CGROUP2/cgroup.procs 438 online_cpus 439 rmdir A1/A2/A3 A1/A2 A1 B1 > /dev/null 2>&1 440 set_ctrl_state . S- 441 pause 0.01 442} 443 444dump_states() 445{ 446 for DIR in A1 A1/A2 A1/A2/A3 B1 447 do 448 ECPUS=$DIR/cpuset.cpus.effective 449 PRS=$DIR/cpuset.cpus.partition 450 [[ -e $ECPUS ]] && echo "$ECPUS: $(cat $ECPUS)" 451 [[ -e $PRS ]] && echo "$PRS: $(cat $PRS)" 452 done 453} 454 455# 456# Check effective cpus 457# $1 - check string, format: <cgroup>:<cpu-list>[,<cgroup>:<cpu-list>]* 458# 459check_effective_cpus() 460{ 461 CHK_STR=$1 462 for CHK in $(echo $CHK_STR | sed -e "s/,/ /g") 463 do 464 set -- $(echo $CHK | sed -e "s/:/ /g") 465 CGRP=$1 466 CPUS=$2 467 [[ $CGRP = A2 ]] && CGRP=A1/A2 468 [[ $CGRP = A3 ]] && CGRP=A1/A2/A3 469 FILE=$CGRP/cpuset.cpus.effective 470 [[ -e $FILE ]] || return 1 471 [[ $CPUS = $(cat $FILE) ]] || return 1 472 done 473} 474 475# 476# Check cgroup states 477# $1 - check string, format: <cgroup>:<state>[,<cgroup>:<state>]* 478# 479check_cgroup_states() 480{ 481 CHK_STR=$1 482 for CHK in $(echo $CHK_STR | sed -e "s/,/ /g") 483 do 484 set -- $(echo $CHK | sed -e "s/:/ /g") 485 CGRP=$1 486 STATE=$2 487 FILE= 488 EVAL=$(expr substr $STATE 2 2) 489 [[ $CGRP = A2 ]] && CGRP=A1/A2 490 [[ $CGRP = A3 ]] && CGRP=A1/A2/A3 491 492 case $STATE in 493 P*) FILE=$CGRP/cpuset.cpus.partition 494 ;; 495 *) echo "Unknown state: $STATE!" 496 exit 1 497 ;; 498 esac 499 VAL=$(cat $FILE) 500 501 case "$VAL" in 502 member) VAL=0 503 ;; 504 root) VAL=1 505 ;; 506 isolated) 507 VAL=2 508 ;; 509 "root invalid"*) 510 VAL=-1 511 ;; 512 "isolated invalid"*) 513 VAL=-2 514 ;; 515 esac 516 [[ $EVAL != $VAL ]] && return 1 517 done 518 return 0 519} 520 521# 522# Run cpuset state transition test 523# $1 - test matrix name 524# 525# This test is somewhat fragile as delays (sleep x) are added in various 526# places to make sure state changes are fully propagated before the next 527# action. These delays may need to be adjusted if running in a slower machine. 528# 529run_state_test() 530{ 531 TEST=$1 532 CONTROLLER=cpuset 533 CPULIST=0-6 534 I=0 535 eval CNT="\${#$TEST[@]}" 536 537 reset_cgroup_states 538 echo $CPULIST > cpuset.cpus 539 echo root > cpuset.cpus.partition 540 console_msg "Running state transition test ..." 541 542 while [[ $I -lt $CNT ]] 543 do 544 echo "Running test $I ..." > /dev/console 545 eval set -- "\${$TEST[$I]}" 546 ROOT=$1 547 OLD_A1=$2 548 OLD_A2=$3 549 OLD_A3=$4 550 OLD_B1=$5 551 NEW_A1=$6 552 NEW_A2=$7 553 NEW_A3=$8 554 NEW_B1=$9 555 RESULT=${10} 556 ECPUS=${11} 557 STATES=${12} 558 559 set_ctrl_state_noerr . $ROOT 560 set_ctrl_state_noerr A1 $OLD_A1 561 set_ctrl_state_noerr A1/A2 $OLD_A2 562 set_ctrl_state_noerr A1/A2/A3 $OLD_A3 563 set_ctrl_state_noerr B1 $OLD_B1 564 RETVAL=0 565 set_ctrl_state A1 $NEW_A1; ((RETVAL += $?)) 566 set_ctrl_state A1/A2 $NEW_A2; ((RETVAL += $?)) 567 set_ctrl_state A1/A2/A3 $NEW_A3; ((RETVAL += $?)) 568 set_ctrl_state B1 $NEW_B1; ((RETVAL += $?)) 569 570 [[ $RETVAL -ne $RESULT ]] && { 571 echo "Test $TEST[$I] failed result check!" 572 eval echo \"\${$TEST[$I]}\" 573 dump_states 574 online_cpus 575 exit 1 576 } 577 578 [[ -n "$ECPUS" && "$ECPUS" != . ]] && { 579 check_effective_cpus $ECPUS 580 [[ $? -ne 0 ]] && { 581 echo "Test $TEST[$I] failed effective CPU check!" 582 eval echo \"\${$TEST[$I]}\" 583 echo 584 dump_states 585 online_cpus 586 exit 1 587 } 588 } 589 590 [[ -n "$STATES" ]] && { 591 check_cgroup_states $STATES 592 [[ $? -ne 0 ]] && { 593 echo "FAILED: Test $TEST[$I] failed states check!" 594 eval echo \"\${$TEST[$I]}\" 595 echo 596 dump_states 597 online_cpus 598 exit 1 599 } 600 } 601 602 reset_cgroup_states 603 # 604 # Check to see if effective cpu list changes 605 # 606 pause 0.05 607 NEWLIST=$(cat cpuset.cpus.effective) 608 [[ $NEWLIST != $CPULIST ]] && { 609 echo "Effective cpus changed to $NEWLIST after test $I!" 610 exit 1 611 } 612 [[ -n "$VERBOSE" ]] && echo "Test $I done." 613 ((I++)) 614 done 615 echo "All $I tests of $TEST PASSED." 616 617 echo member > cpuset.cpus.partition 618} 619 620# 621# Wait for inotify event for the given file and read it 622# $1: cgroup file to wait for 623# $2: file to store the read result 624# 625wait_inotify() 626{ 627 CGROUP_FILE=$1 628 OUTPUT_FILE=$2 629 630 $WAIT_INOTIFY $CGROUP_FILE 631 cat $CGROUP_FILE > $OUTPUT_FILE 632} 633 634# 635# Test if inotify events are properly generated when going into and out of 636# invalid partition state. 637# 638test_inotify() 639{ 640 ERR=0 641 PRS=/tmp/.prs_$$ 642 [[ -f $WAIT_INOTIFY ]] || { 643 echo "wait_inotify not found, inotify test SKIPPED." 644 return 645 } 646 647 pause 0.01 648 echo 1 > cpuset.cpus 649 echo 0 > cgroup.procs 650 echo root > cpuset.cpus.partition 651 pause 0.01 652 rm -f $PRS 653 wait_inotify $PWD/cpuset.cpus.partition $PRS & 654 pause 0.01 655 set_ctrl_state . "O1-0" 656 pause 0.01 657 check_cgroup_states ".:P-1" 658 if [[ $? -ne 0 ]] 659 then 660 echo "FAILED: Inotify test - partition not invalid" 661 ERR=1 662 elif [[ ! -f $PRS ]] 663 then 664 echo "FAILED: Inotify test - event not generated" 665 ERR=1 666 kill %1 667 elif [[ $(cat $PRS) != "root invalid"* ]] 668 then 669 echo "FAILED: Inotify test - incorrect state" 670 cat $PRS 671 ERR=1 672 fi 673 online_cpus 674 echo member > cpuset.cpus.partition 675 echo 0 > ../cgroup.procs 676 if [[ $ERR -ne 0 ]] 677 then 678 exit 1 679 else 680 echo "Inotify test PASSED" 681 fi 682} 683 684trap cleanup 0 2 3 6 685run_state_test TEST_MATRIX 686test_isolated 687test_inotify 688echo "All tests PASSED." 689cd .. 690rmdir test 691