Merge tag 'v6.4-rc4' into wpan-next/staging
[sfrench/cifs-2.6.git] / tools / testing / selftests / cgroup / test_cpuset_prs.sh
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
10 skip_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
20 WAIT_INOTIFY=$(cd $(dirname $0); pwd)/wait_inotify
21
22 # Find cgroup v2 mount point
23 CGROUP2=$(mount -t cgroup2 | head -1 | awk -e '{print $3}')
24 [[ -n "$CGROUP2" ]] || skip_test "Cgroup v2 mount point not found!"
25
26 CPUS=$(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
30 PROG=$1
31 VERBOSE=
32 DELAY_FACTOR=1
33 SCHED_DEBUG=
34 while [[ "$1" = -* ]]
35 do
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
52 done
53
54 # Set sched verbose flag if available when "-v" option is specified
55 if [[ -n "$VERBOSE" && -d /sys/kernel/debug/sched ]]
56 then
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
60 fi
61
62 cd $CGROUP2
63 echo +cpuset > cgroup.subtree_control
64 [[ -d test ]] || mkdir test
65 cd test
66
67 cleanup()
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
78 pause()
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
90 console_msg()
91 {
92         MSG=$1
93         echo "$MSG"
94         echo "" > /dev/console
95         echo "$MSG" > /dev/console
96         pause 0.01
97 }
98
99 test_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
112 test_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
124 test_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 #
140 test_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 #
215 SETUP_A123_PARTITIONS="C1-3:P1:S+ C2-3:P1:S+ C3:P1"
216 TEST_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 #
321 write_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 #
347 set_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
416 set_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
428 online_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 #
441 reset_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
450 dump_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 #
465 check_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 #
485 check_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 #
535 run_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 #
628 wait_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 #
641 test_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
687 trap cleanup 0 2 3 6
688 run_state_test TEST_MATRIX
689 test_isolated
690 test_inotify
691 echo "All tests PASSED."
692 cd ..
693 rmdir test