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