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