Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/testing/selftests/cgroup/test_cpuset_prs.sh
50950 views
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 can be optionally set 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 4 # ksft_skip
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
SUBPARTS_CPUS=$CGROUP2/.__DEBUG__.cpuset.cpus.subpartitions
26
CPULIST=$(cat $CGROUP2/cpuset.cpus.effective)
27
28
NR_CPUS=$(lscpu | grep "^CPU(s):" | sed -e "s/.*:[[:space:]]*//")
29
[[ $NR_CPUS -lt 8 ]] && skip_test "Test needs at least 8 cpus available!"
30
31
# Check to see if /dev/console exists and is writable
32
if [[ -c /dev/console && -w /dev/console ]]
33
then
34
CONSOLE=/dev/console
35
else
36
CONSOLE=/dev/null
37
fi
38
39
# Set verbose flag and delay factor
40
PROG=$1
41
VERBOSE=0
42
DELAY_FACTOR=1
43
SCHED_DEBUG=
44
while [[ "$1" = -* ]]
45
do
46
case "$1" in
47
-v) ((VERBOSE++))
48
# Enable sched/verbose can slow thing down
49
[[ $DELAY_FACTOR -eq 1 ]] &&
50
DELAY_FACTOR=2
51
;;
52
-d) DELAY_FACTOR=$2
53
shift
54
;;
55
*) echo "Usage: $PROG [-v] [-d <delay-factor>"
56
exit
57
;;
58
esac
59
shift
60
done
61
62
# Set sched verbose flag if available when "-v" option is specified
63
if [[ $VERBOSE -gt 0 && -d /sys/kernel/debug/sched ]]
64
then
65
# Used to restore the original setting during cleanup
66
SCHED_DEBUG=$(cat /sys/kernel/debug/sched/verbose)
67
echo Y > /sys/kernel/debug/sched/verbose
68
fi
69
70
cd $CGROUP2
71
echo +cpuset > cgroup.subtree_control
72
73
#
74
# If cpuset has been set up and used in child cgroups, we may not be able to
75
# create partition under root cgroup because of the CPU exclusivity rule.
76
# So we are going to skip the test if this is the case.
77
#
78
[[ -d test ]] || mkdir test
79
echo 0-6 > test/cpuset.cpus
80
echo root > test/cpuset.cpus.partition
81
cat test/cpuset.cpus.partition | grep -q invalid
82
RESULT=$?
83
echo member > test/cpuset.cpus.partition
84
echo "" > test/cpuset.cpus
85
[[ $RESULT -eq 0 ]] && skip_test "Child cgroups are using cpuset!"
86
87
#
88
# If isolated CPUs have been reserved at boot time (as shown in
89
# cpuset.cpus.isolated), these isolated CPUs should be outside of CPUs 0-8
90
# that will be used by this script for testing purpose. If not, some of
91
# the tests may fail incorrectly. Wait a bit and retry again just in case
92
# these isolated CPUs are leftover from previous run and have just been
93
# cleaned up earlier in this script.
94
#
95
# These pre-isolated CPUs should stay in an isolated state throughout the
96
# testing process for now.
97
#
98
BOOT_ISOLCPUS=$(cat $CGROUP2/cpuset.cpus.isolated)
99
[[ -n "$BOOT_ISOLCPUS" ]] && {
100
sleep 0.5
101
BOOT_ISOLCPUS=$(cat $CGROUP2/cpuset.cpus.isolated)
102
}
103
if [[ -n "$BOOT_ISOLCPUS" ]]
104
then
105
[[ $(echo $BOOT_ISOLCPUS | sed -e "s/[,-].*//") -le 8 ]] &&
106
skip_test "Pre-isolated CPUs ($BOOT_ISOLCPUS) overlap CPUs to be tested"
107
echo "Pre-isolated CPUs: $BOOT_ISOLCPUS"
108
fi
109
110
cleanup()
111
{
112
online_cpus
113
cd $CGROUP2
114
rmdir A1/A2/A3 A1/A2 A1 B1 test/A1 test/B1 test > /dev/null 2>&1
115
rmdir rtest/p1/c11 rtest/p1/c12 rtest/p2/c21 \
116
rtest/p2/c22 rtest/p1 rtest/p2 rtest > /dev/null 2>&1
117
[[ -n "$SCHED_DEBUG" ]] &&
118
echo "$SCHED_DEBUG" > /sys/kernel/debug/sched/verbose
119
}
120
121
# Pause in ms
122
pause()
123
{
124
DELAY=$1
125
LOOP=0
126
while [[ $LOOP -lt $DELAY_FACTOR ]]
127
do
128
sleep $DELAY
129
((LOOP++))
130
done
131
return 0
132
}
133
134
console_msg()
135
{
136
MSG=$1
137
echo "$MSG"
138
echo "" > $CONSOLE
139
echo "$MSG" > $CONSOLE
140
pause 0.01
141
}
142
143
test_partition()
144
{
145
EXPECTED_VAL=$1
146
echo $EXPECTED_VAL > cpuset.cpus.partition
147
[[ $? -eq 0 ]] || exit 1
148
ACTUAL_VAL=$(cat cpuset.cpus.partition)
149
[[ $ACTUAL_VAL != $EXPECTED_VAL ]] && {
150
echo "cpuset.cpus.partition: expect $EXPECTED_VAL, found $ACTUAL_VAL"
151
echo "Test FAILED"
152
exit 1
153
}
154
}
155
156
test_effective_cpus()
157
{
158
EXPECTED_VAL=$1
159
ACTUAL_VAL=$(cat cpuset.cpus.effective)
160
[[ "$ACTUAL_VAL" != "$EXPECTED_VAL" ]] && {
161
echo "cpuset.cpus.effective: expect '$EXPECTED_VAL', found '$ACTUAL_VAL'"
162
echo "Test FAILED"
163
exit 1
164
}
165
}
166
167
# Adding current process to cgroup.procs as a test
168
test_add_proc()
169
{
170
OUTSTR="$1"
171
ERRMSG=$((echo $$ > cgroup.procs) |& cat)
172
echo $ERRMSG | grep -q "$OUTSTR"
173
[[ $? -ne 0 ]] && {
174
echo "cgroup.procs: expect '$OUTSTR', got '$ERRMSG'"
175
echo "Test FAILED"
176
exit 1
177
}
178
echo $$ > $CGROUP2/cgroup.procs # Move out the task
179
}
180
181
#
182
# Cpuset controller state transition test matrix.
183
#
184
# Cgroup test hierarchy
185
#
186
# root
187
# |
188
# +------+------+
189
# | |
190
# A1 B1
191
# |
192
# A2
193
# |
194
# A3
195
#
196
# P<v> = set cpus.partition (0:member, 1:root, 2:isolated)
197
# C<l> = add cpu-list to cpuset.cpus
198
# X<l> = add cpu-list to cpuset.cpus.exclusive
199
# S<p> = use prefix in subtree_control
200
# T = put a task into cgroup
201
# CX<l> = add cpu-list to both cpuset.cpus and cpuset.cpus.exclusive
202
# O<c>=<v> = Write <v> to CPU online file of <c>
203
#
204
# ECPUs - effective CPUs of cpusets
205
# Pstate - partition root state
206
# ISOLCPUS - isolated CPUs (<icpus>[,<icpus2>])
207
#
208
# Note that if there are 2 fields in ISOLCPUS, the first one is for
209
# sched-debug matching which includes offline CPUs and single-CPU partitions
210
# while the second one is for matching cpuset.cpus.isolated.
211
#
212
SETUP_A123_PARTITIONS="C1-3:P1:S+ C2-3:P1:S+ C3:P1"
213
TEST_MATRIX=(
214
# old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS
215
# ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ --------
216
" C0-1 . . C2-3 S+ C4-5 . . 0 A2:0-1"
217
" C0-1 . . C2-3 P1 . . . 0 "
218
" C0-1 . . C2-3 P1:S+ C0-1:P1 . . 0 "
219
" C0-1 . . C2-3 P1:S+ C1:P1 . . 0 "
220
" C0-1:S+ . . C2-3 . . . P1 0 "
221
" C0-1:P1 . . C2-3 S+ C1 . . 0 "
222
" C0-1:P1 . . C2-3 S+ C1:P1 . . 0 "
223
" C0-1:P1 . . C2-3 S+ C1:P1 . P1 0 "
224
" C0-1:P1 . . C2-3 C4-5 . . . 0 A1:4-5"
225
" C0-1:P1 . . C2-3 S+:C4-5 . . . 0 A1:4-5"
226
" C0-1 . . C2-3:P1 . . . C2 0 "
227
" C0-1 . . C2-3:P1 . . . C4-5 0 B1:4-5"
228
"C0-3:P1:S+ C2-3:P1 . . . . . . 0 A1:0-1|A2:2-3|XA2:2-3"
229
"C0-3:P1:S+ C2-3:P1 . . C1-3 . . . 0 A1:1|A2:2-3|XA2:2-3"
230
"C2-3:P1:S+ C3:P1 . . C3 . . . 0 A1:|A2:3|XA2:3 A1:P1|A2:P1"
231
"C2-3:P1:S+ C3:P1 . . C3 P0 . . 0 A1:3|A2:3 A1:P1|A2:P0"
232
"C2-3:P1:S+ C2:P1 . . C2-4 . . . 0 A1:3-4|A2:2"
233
"C2-3:P1:S+ C3:P1 . . C3 . . C0-2 0 A1:|B1:0-2 A1:P1|A2:P1"
234
"$SETUP_A123_PARTITIONS . C2-3 . . . 0 A1:|A2:2|A3:3 A1:P1|A2:P1|A3:P1"
235
236
# CPU offlining cases:
237
" C0-1 . . C2-3 S+ C4-5 . O2=0 0 A1:0-1|B1:3"
238
"C0-3:P1:S+ C2-3:P1 . . O2=0 . . . 0 A1:0-1|A2:3"
239
"C0-3:P1:S+ C2-3:P1 . . O2=0 O2=1 . . 0 A1:0-1|A2:2-3"
240
"C0-3:P1:S+ C2-3:P1 . . O1=0 . . . 0 A1:0|A2:2-3"
241
"C0-3:P1:S+ C2-3:P1 . . O1=0 O1=1 . . 0 A1:0-1|A2:2-3"
242
"C2-3:P1:S+ C3:P1 . . O3=0 O3=1 . . 0 A1:2|A2:3 A1:P1|A2:P1"
243
"C2-3:P1:S+ C3:P2 . . O3=0 O3=1 . . 0 A1:2|A2:3 A1:P1|A2:P2"
244
"C2-3:P1:S+ C3:P1 . . O2=0 O2=1 . . 0 A1:2|A2:3 A1:P1|A2:P1"
245
"C2-3:P1:S+ C3:P2 . . O2=0 O2=1 . . 0 A1:2|A2:3 A1:P1|A2:P2"
246
"C2-3:P1:S+ C3:P1 . . O2=0 . . . 0 A1:|A2:3 A1:P1|A2:P1"
247
"C2-3:P1:S+ C3:P1 . . O3=0 . . . 0 A1:2|A2: A1:P1|A2:P1"
248
"C2-3:P1:S+ C3:P1 . . T:O2=0 . . . 0 A1:3|A2:3 A1:P1|A2:P-1"
249
"C2-3:P1:S+ C3:P1 . . . T:O3=0 . . 0 A1:2|A2:2 A1:P1|A2:P-1"
250
"$SETUP_A123_PARTITIONS . O1=0 . . . 0 A1:|A2:2|A3:3 A1:P1|A2:P1|A3:P1"
251
"$SETUP_A123_PARTITIONS . O2=0 . . . 0 A1:1|A2:|A3:3 A1:P1|A2:P1|A3:P1"
252
"$SETUP_A123_PARTITIONS . O3=0 . . . 0 A1:1|A2:2|A3: A1:P1|A2:P1|A3:P1"
253
"$SETUP_A123_PARTITIONS . T:O1=0 . . . 0 A1:2-3|A2:2-3|A3:3 A1:P1|A2:P-1|A3:P-1"
254
"$SETUP_A123_PARTITIONS . . T:O2=0 . . 0 A1:1|A2:3|A3:3 A1:P1|A2:P1|A3:P-1"
255
"$SETUP_A123_PARTITIONS . . . T:O3=0 . 0 A1:1|A2:2|A3:2 A1:P1|A2:P1|A3:P-1"
256
"$SETUP_A123_PARTITIONS . T:O1=0 O1=1 . . 0 A1:1|A2:2|A3:3 A1:P1|A2:P1|A3:P1"
257
"$SETUP_A123_PARTITIONS . . T:O2=0 O2=1 . 0 A1:1|A2:2|A3:3 A1:P1|A2:P1|A3:P1"
258
"$SETUP_A123_PARTITIONS . . . T:O3=0 O3=1 0 A1:1|A2:2|A3:3 A1:P1|A2:P1|A3:P1"
259
"$SETUP_A123_PARTITIONS . T:O1=0 O2=0 O1=1 . 0 A1:1|A2:|A3:3 A1:P1|A2:P1|A3:P1"
260
"$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"
261
262
# old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS
263
# ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ --------
264
#
265
# Remote partition and cpuset.cpus.exclusive tests
266
#
267
" C0-3:S+ C1-3:S+ C2-3 . X2-3 . . . 0 A1:0-3|A2:1-3|A3:2-3|XA1:2-3"
268
" 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"
269
" 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"
270
" 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"
271
" 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"
272
" C0-3:S+ C1-3:S+ C2-3 C2-3 . . . P2 0 A1:0-1|A2:1|A3:1|B1:2-3 A1:P0|A3:P0|B1:P2"
273
" C0-3:S+ C1-3:S+ C2-3 C4-5 . . . P2 0 B1:4-5 B1:P2 4-5"
274
" 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"
275
" 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"
276
" 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"
277
" 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"
278
" C4:X0-3:S+ X1-3:S+ X2-3 . . P2 . . 0 A1:4|A2:1-3|A3:1-3 A2:P2 1-3"
279
" C4:X0-3:S+ X1-3:S+ X2-3 . . . P2 . 0 A1:4|A2:4|A3:2-3 A3:P2 2-3"
280
281
# Nested remote/local partition tests
282
" 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 \
283
A1:P0|A2:P1|A3:P2|B1:P1 2-3"
284
" 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 \
285
A1:P0|A2:P1|A3:P2|B1:P1 2-4|2-3"
286
" 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 \
287
A1:P0|A2:P1|A3:P0|B1:P1"
288
" 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 \
289
A1:P0|A2:P1|A3:P2|B1:P1 2-4|3"
290
" C0-4:S+ C1-4:S+ C2-4 . X2-4 X2-4:P2 X4:P1 . 0 A1:0-1|A2:2-3|A3:4 \
291
A1:P0|A2:P2|A3:P1 2-4|2-3"
292
" 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 \
293
A1:P0|A2:P2|A3:P1 2"
294
" C0-4:X2-4:S+ C1-4:X2-4:S+:P2 C2-4:X4:P1 \
295
. . X5 . . 0 A1:0-4|A2:1-4|A3:2-4 \
296
A1:P0|A2:P-2|A3:P-1 ."
297
" C0-4:X2-4:S+ C1-4:X2-4:S+:P2 C2-4:X4:P1 \
298
. . . X1 . 0 A1:0-1|A2:2-4|A3:2-4 \
299
A1:P0|A2:P2|A3:P-1 2-4"
300
301
# Remote partition offline tests
302
" 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"
303
" 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"
304
" 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"
305
" 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|"
306
307
# An invalidated remote partition cannot self-recover from hotplug
308
" 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 ."
309
310
# cpus.exclusive.effective clearing test
311
" C0-3:S+ C1-3:S+ C2 . X2-3:X . . . 0 A1:0-3|A2:1-3|A3:2|XA1:"
312
313
# Invalid to valid remote partition transition test
314
" C0-3:S+ C1-3 . . . X3:P2 . . 0 A1:0-3|A2:1-3|XA2: A2:P-2 ."
315
" C0-3:S+ C1-3:X3:P2
316
. . X2-3 P2 . . 0 A1:0-2|A2:3|XA2:3 A2:P2 3"
317
318
# Invalid to valid local partition direct transition tests
319
" C1-3:S+:P2 X4:P2 . . . . . . 0 A1:1-3|XA1:1-3|A2:1-3:XA2: A1:P2|A2:P-2 1-3"
320
" 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"
321
" C0-3:P2 . . C4-6 C0-4 . . . 0 A1:0-4|B1:5-6 A1:P2|B1:P0"
322
" C0-3:P2 . . C4-6 C0-4:C0-3 . . . 0 A1:0-3|B1:4-6 A1:P2|B1:P0 0-3"
323
324
# Local partition invalidation tests
325
" C0-3:X1-3:S+:P2 C1-3:X2-3:S+:P2 C2-3:X3:P2 \
326
. . . . . 0 A1:1|A2:2|A3:3 A1:P2|A2:P2|A3:P2 1-3"
327
" C0-3:X1-3:S+:P2 C1-3:X2-3:S+:P2 C2-3:X3:P2 \
328
. . X4 . . 0 A1:1-3|A2:1-3|A3:2-3|XA2:|XA3: A1:P2|A2:P-2|A3:P-2 1-3"
329
" C0-3:X1-3:S+:P2 C1-3:X2-3:S+:P2 C2-3:X3:P2 \
330
. . C4:X . . 0 A1:1-3|A2:1-3|A3:2-3|XA2:|XA3: A1:P2|A2:P-2|A3:P-2 1-3"
331
# Local partition CPU change tests
332
" C0-5:S+:P2 C4-5:S+:P1 . . . C3-5 . . 0 A1:0-2|A2:3-5 A1:P2|A2:P1 0-2"
333
" C0-5:S+:P2 C4-5:S+:P1 . . C1-5 . . . 0 A1:1-3|A2:4-5 A1:P2|A2:P1 1-3"
334
335
# cpus_allowed/exclusive_cpus update tests
336
" C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3 \
337
. X:C4 . P2 . 0 A1:4|A2:4|XA2:|XA3:|A3:4 \
338
A1:P0|A3:P-2 ."
339
" C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3 \
340
. X1 . P2 . 0 A1:0-3|A2:1-3|XA1:1|XA2:|XA3:|A3:2-3 \
341
A1:P0|A3:P-2 ."
342
" C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3 \
343
. . X3 P2 . 0 A1:0-2|A2:1-2|XA2:3|XA3:3|A3:3 \
344
A1:P0|A3:P2 3"
345
" C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3:P2 \
346
. . X3 . . 0 A1:0-2|A2:1-2|XA2:3|XA3:3|A3:3|XA3:3 \
347
A1:P0|A3:P2 3"
348
" C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3:P2 \
349
. X4 . . . 0 A1:0-3|A2:1-3|A3:2-3|XA1:4|XA2:|XA3 \
350
A1:P0|A3:P-2"
351
352
# old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS
353
# ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ --------
354
#
355
# Incorrect change to cpuset.cpus[.exclusive] invalidates partition root
356
#
357
# Adding CPUs to partition root that are not in parent's
358
# cpuset.cpus is allowed, but those extra CPUs are ignored.
359
"C2-3:P1:S+ C3:P1 . . . C2-4 . . 0 A1:|A2:2-3 A1:P1|A2:P1"
360
361
# Taking away all CPUs from parent or itself if there are tasks
362
# will make the partition invalid.
363
"C2-3:P1:S+ C3:P1 . . T C2-3 . . 0 A1:2-3|A2:2-3 A1:P1|A2:P-1"
364
" C3:P1:S+ C3 . . T P1 . . 0 A1:3|A2:3 A1:P1|A2:P-1"
365
"$SETUP_A123_PARTITIONS . T:C2-3 . . . 0 A1:2-3|A2:2-3|A3:3 A1:P1|A2:P-1|A3:P-1"
366
"$SETUP_A123_PARTITIONS . T:C2-3:C1-3 . . . 0 A1:1|A2:2|A3:3 A1:P1|A2:P1|A3:P1"
367
368
# Changing a partition root to member makes child partitions invalid
369
"C2-3:P1:S+ C3:P1 . . P0 . . . 0 A1:2-3|A2:3 A1:P0|A2:P-1"
370
"$SETUP_A123_PARTITIONS . C2-3 P0 . . 0 A1:2-3|A2:2-3|A3:3 A1:P1|A2:P0|A3:P-1"
371
372
# cpuset.cpus can contains cpus not in parent's cpuset.cpus as long
373
# as they overlap.
374
"C2-3:P1:S+ . . . . C3-4:P1 . . 0 A1:2|A2:3 A1:P1|A2:P1"
375
376
# Deletion of CPUs distributed to child cgroup is allowed.
377
"C0-1:P1:S+ C1 . C2-3 C4-5 . . . 0 A1:4-5|A2:4-5"
378
379
# To become a valid partition root, cpuset.cpus must overlap parent's
380
# cpuset.cpus.
381
" C0-1:P1 . . C2-3 S+ C4-5:P1 . . 0 A1:0-1|A2:0-1 A1:P1|A2:P-1"
382
383
# Enabling partition with child cpusets is allowed
384
" C0-1:S+ C1 . C2-3 P1 . . . 0 A1:0-1|A2:1 A1:P1"
385
386
# A partition root with non-partition root parent is invalid| but it
387
# can be made valid if its parent becomes a partition root too.
388
" C0-1:S+ C1 . C2-3 . P2 . . 0 A1:0-1|A2:1 A1:P0|A2:P-2"
389
" C0-1:S+ C1:P2 . C2-3 P1 . . . 0 A1:0|A2:1 A1:P1|A2:P2 0-1|1"
390
391
# A non-exclusive cpuset.cpus change will not invalidate its siblings partition.
392
" C0-1:P1 . . C2-3 C0-2 . . . 0 A1:0-2|B1:3 A1:P1|B1:P0"
393
" C0-1:P1 . . P1:C2-3 C0-2 . . . 0 A1:0-1|XA1:0-1|B1:2-3 A1:P1|B1:P1"
394
" C0-1 . . P1:C2-3 C0-2 . . . 0 A1:0-1|B1:2-3 A1:P0|B1:P1"
395
396
# cpuset.cpus can overlap with sibling cpuset.cpus.exclusive but not subsumed by it
397
" C0-3 . . C4-5 X5 . . . 0 A1:0-3|B1:4-5"
398
399
# Child partition root that try to take all CPUs from parent partition
400
# with tasks will remain invalid.
401
" C1-4:P1:S+ P1 . . . . . . 0 A1:1-4|A2:1-4 A1:P1|A2:P-1"
402
" C1-4:P1:S+ P1 . . . C1-4 . . 0 A1|A2:1-4 A1:P1|A2:P1"
403
" C1-4:P1:S+ P1 . . T C1-4 . . 0 A1:1-4|A2:1-4 A1:P1|A2:P-1"
404
405
# Clearing of cpuset.cpus with a preset cpuset.cpus.exclusive shouldn't
406
# affect cpuset.cpus.exclusive.effective.
407
" C1-4:X3:S+ C1:X3 . . . C . . 0 A2:1-4|XA2:3"
408
409
# cpuset.cpus can contain CPUs that overlap a sibling cpuset with cpus.exclusive
410
# but creating a local partition out of it is not allowed. Similarly and change
411
# in cpuset.cpus of a local partition that overlaps sibling exclusive CPUs will
412
# invalidate it.
413
" CX1-4:S+ CX2-4:P2 . C5-6 . . . P1 0 A1:1|A2:2-4|B1:5-6|XB1:5-6 \
414
A1:P0|A2:P2:B1:P1 2-4"
415
" CX1-4:S+ CX2-4:P2 . C3-6 . . . P1 0 A1:1|A2:2-4|B1:5-6 \
416
A1:P0|A2:P2:B1:P-1 2-4"
417
" CX1-4:S+ CX2-4:P2 . C5-6 . . . P1:C3-6 0 A1:1|A2:2-4|B1:5-6 \
418
A1:P0|A2:P2:B1:P-1 2-4"
419
420
# When multiple partitions with conflicting cpuset.cpus are created, the
421
# latter created ones will only get what are left of the available exclusive
422
# CPUs.
423
" C1-3:P1 . . . . . . C3-5:P1 0 A1:1-3|B1:4-5:XB1:4-5 A1:P1|B1:P1"
424
425
# cpuset.cpus can be set to a subset of sibling's cpuset.cpus.exclusive
426
" C1-3:X1-3 . . C4-5 . . . C1-2 0 A1:1-3|B1:1-2"
427
428
# cpuset.cpus can become empty with task in it as it inherits parent's effective CPUs
429
" C1-3:S+ C2 . . . T:C . . 0 A1:1-3|A2:1-3"
430
431
# old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS
432
# ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ --------
433
# Failure cases:
434
435
# A task cannot be added to a partition with no cpu
436
"C2-3:P1:S+ C3:P1 . . O2=0:T . . . 1 A1:|A2:3 A1:P1|A2:P1"
437
438
# Changes to cpuset.cpus.exclusive that violate exclusivity rule is rejected
439
" C0-3 . . C4-5 X0-3 . . X3-5 1 A1:0-3|B1:4-5"
440
441
# cpuset.cpus.exclusive cannot be set to a superset of sibling's cpuset.cpus
442
" C0-3 . . C4-5 X3-5 . . . 1 A1:0-3|B1:4-5"
443
)
444
445
#
446
# Cpuset controller remote partition test matrix.
447
#
448
# Cgroup test hierarchy
449
#
450
# root
451
# |
452
# rtest (cpuset.cpus.exclusive=1-7)
453
# |
454
# +------+------+
455
# | |
456
# p1 p2
457
# +--+--+ +--+--+
458
# | | | |
459
# c11 c12 c21 c22
460
#
461
# REMOTE_TEST_MATRIX uses the same notational convention as TEST_MATRIX.
462
# Only CPUs 1-7 should be used.
463
#
464
REMOTE_TEST_MATRIX=(
465
# old-p1 old-p2 old-c11 old-c12 old-c21 old-c22
466
# new-p1 new-p2 new-c11 new-c12 new-c21 new-c22 ECPUs Pstate ISOLCPUS
467
# ------ ------ ------- ------- ------- ------- ----- ------ --------
468
" X1-3:S+ X4-6:S+ X1-2 X3 X4-5 X6 \
469
. . P2 P2 P2 P2 c11:1-2|c12:3|c21:4-5|c22:6 \
470
c11:P2|c12:P2|c21:P2|c22:P2 1-6"
471
" CX1-4:S+ . X1-2:P2 C3 . . \
472
. . . C3-4 . . p1:3-4|c11:1-2|c12:3-4 \
473
p1:P0|c11:P2|c12:P0 1-2"
474
" CX1-4:S+ . X1-2:P2 . . . \
475
X2-4 . . . . . p1:1,3-4|c11:2 \
476
p1:P0|c11:P2 2"
477
" CX1-5:S+ . X1-2:P2 X3-5:P1 . . \
478
X2-4 . . . . . p1:1,5|c11:2|c12:3-4 \
479
p1:P0|c11:P2|c12:P1 2"
480
" CX1-4:S+ . X1-2:P2 X3-4:P1 . . \
481
. . X2 . . . p1:1|c11:2|c12:3-4 \
482
p1:P0|c11:P2|c12:P1 2"
483
# p1 as member, will get its effective CPUs from its parent rtest
484
" CX1-4:S+ . X1-2:P2 X3-4:P1 . . \
485
. . X1 CX2-4 . . p1:5-7|c11:1|c12:2-4 \
486
p1:P0|c11:P2|c12:P1 1"
487
" CX1-4:S+ X5-6:P1:S+ . . . . \
488
. . X1-2:P2 X4-5:P1 . X1-7:P2 p1:3|c11:1-2|c12:4:c22:5-6 \
489
p1:P0|p2:P1|c11:P2|c12:P1|c22:P2 \
490
1-2,4-6|1-2,5-6"
491
# c12 whose cpuset.cpus CPUs are all granted to c11 will become invalid partition
492
" C1-5:P1:S+ . C1-4:P1 C2-3 . . \
493
. . . P1 . . p1:5|c11:1-4|c12:5 \
494
p1:P1|c11:P1|c12:P-1"
495
)
496
497
#
498
# Write to the cpu online file
499
# $1 - <c>=<v> where <c> = cpu number, <v> value to be written
500
#
501
write_cpu_online()
502
{
503
CPU=${1%=*}
504
VAL=${1#*=}
505
CPUFILE=//sys/devices/system/cpu/cpu${CPU}/online
506
if [[ $VAL -eq 0 ]]
507
then
508
OFFLINE_CPUS="$OFFLINE_CPUS $CPU"
509
else
510
[[ -n "$OFFLINE_CPUS" ]] && {
511
OFFLINE_CPUS=$(echo $CPU $CPU $OFFLINE_CPUS | fmt -1 |\
512
sort | uniq -u)
513
}
514
fi
515
echo $VAL > $CPUFILE
516
pause 0.05
517
}
518
519
#
520
# Set controller state
521
# $1 - cgroup directory
522
# $2 - state
523
# $3 - showerr
524
#
525
# The presence of ":" in state means transition from one to the next.
526
#
527
set_ctrl_state()
528
{
529
TMPMSG=/tmp/.msg_$$
530
CGRP=$1
531
STATE=$2
532
SHOWERR=${3}
533
CTRL=${CTRL:=$CONTROLLER}
534
HASERR=0
535
REDIRECT="2> $TMPMSG"
536
[[ -z "$STATE" || "$STATE" = '.' ]] && return 0
537
[[ $VERBOSE -gt 0 ]] && SHOWERR=1
538
539
rm -f $TMPMSG
540
for CMD in $(echo $STATE | sed -e "s/:/ /g")
541
do
542
TFILE=$CGRP/cgroup.procs
543
SFILE=$CGRP/cgroup.subtree_control
544
PFILE=$CGRP/cpuset.cpus.partition
545
CFILE=$CGRP/cpuset.cpus
546
XFILE=$CGRP/cpuset.cpus.exclusive
547
case $CMD in
548
S*) PREFIX=${CMD#?}
549
COMM="echo ${PREFIX}${CTRL} > $SFILE"
550
eval $COMM $REDIRECT
551
;;
552
X*)
553
CPUS=${CMD#?}
554
COMM="echo $CPUS > $XFILE"
555
eval $COMM $REDIRECT
556
;;
557
CX*)
558
CPUS=${CMD#??}
559
COMM="echo $CPUS > $CFILE; echo $CPUS > $XFILE"
560
eval $COMM $REDIRECT
561
;;
562
C*) CPUS=${CMD#?}
563
COMM="echo $CPUS > $CFILE"
564
eval $COMM $REDIRECT
565
;;
566
P*) VAL=${CMD#?}
567
case $VAL in
568
0) VAL=member
569
;;
570
1) VAL=root
571
;;
572
2) VAL=isolated
573
;;
574
*)
575
echo "Invalid partition state - $VAL"
576
exit 1
577
;;
578
esac
579
COMM="echo $VAL > $PFILE"
580
eval $COMM $REDIRECT
581
;;
582
O*) VAL=${CMD#?}
583
write_cpu_online $VAL
584
;;
585
T*) COMM="echo 0 > $TFILE"
586
eval $COMM $REDIRECT
587
;;
588
*) echo "Unknown command: $CMD"
589
exit 1
590
;;
591
esac
592
RET=$?
593
[[ $RET -ne 0 ]] && {
594
[[ -n "$SHOWERR" ]] && {
595
echo "$COMM"
596
cat $TMPMSG
597
}
598
HASERR=1
599
}
600
pause 0.01
601
rm -f $TMPMSG
602
done
603
return $HASERR
604
}
605
606
set_ctrl_state_noerr()
607
{
608
CGRP=$1
609
STATE=$2
610
[[ -d $CGRP ]] || mkdir $CGRP
611
set_ctrl_state $CGRP $STATE 1
612
[[ $? -ne 0 ]] && {
613
echo "ERROR: Failed to set $2 to cgroup $1!"
614
exit 1
615
}
616
}
617
618
online_cpus()
619
{
620
[[ -n "OFFLINE_CPUS" ]] && {
621
for C in $OFFLINE_CPUS
622
do
623
write_cpu_online ${C}=1
624
done
625
}
626
}
627
628
#
629
# Remove all the test cgroup directories
630
#
631
reset_cgroup_states()
632
{
633
echo 0 > $CGROUP2/cgroup.procs
634
online_cpus
635
rmdir $RESET_LIST > /dev/null 2>&1
636
}
637
638
dump_states()
639
{
640
for DIR in $CGROUP_LIST
641
do
642
CPUS=$DIR/cpuset.cpus
643
ECPUS=$DIR/cpuset.cpus.effective
644
XCPUS=$DIR/cpuset.cpus.exclusive
645
XECPUS=$DIR/cpuset.cpus.exclusive.effective
646
PRS=$DIR/cpuset.cpus.partition
647
PCPUS=$DIR/.__DEBUG__.cpuset.cpus.subpartitions
648
ISCPUS=$DIR/cpuset.cpus.isolated
649
[[ -e $CPUS ]] && echo "$CPUS: $(cat $CPUS)"
650
[[ -e $XCPUS ]] && echo "$XCPUS: $(cat $XCPUS)"
651
[[ -e $ECPUS ]] && echo "$ECPUS: $(cat $ECPUS)"
652
[[ -e $XECPUS ]] && echo "$XECPUS: $(cat $XECPUS)"
653
[[ -e $PRS ]] && echo "$PRS: $(cat $PRS)"
654
[[ -e $PCPUS ]] && echo "$PCPUS: $(cat $PCPUS)"
655
[[ -e $ISCPUS ]] && echo "$ISCPUS: $(cat $ISCPUS)"
656
done
657
}
658
659
#
660
# Set the actual cgroup directory into $CGRP_DIR
661
# $1 - cgroup name
662
#
663
set_cgroup_dir()
664
{
665
CGRP_DIR=$1
666
[[ $CGRP_DIR = A2 ]] && CGRP_DIR=A1/A2
667
[[ $CGRP_DIR = A3 ]] && CGRP_DIR=A1/A2/A3
668
[[ $CGRP_DIR = c11 ]] && CGRP_DIR=p1/c11
669
[[ $CGRP_DIR = c12 ]] && CGRP_DIR=p1/c12
670
[[ $CGRP_DIR = c21 ]] && CGRP_DIR=p2/c21
671
[[ $CGRP_DIR = c22 ]] && CGRP_DIR=p2/c22
672
}
673
674
#
675
# Check effective cpus
676
# $1 - check string, format: <cgroup>:<cpu-list>[|<cgroup>:<cpu-list>]*
677
#
678
check_effective_cpus()
679
{
680
CHK_STR=$1
681
for CHK in $(echo $CHK_STR | sed -e "s/|/ /g")
682
do
683
set -- $(echo $CHK | sed -e "s/:/ /g")
684
CGRP=$1
685
EXPECTED_CPUS=$2
686
ACTUAL_CPUS=
687
if [[ $CGRP = X* ]]
688
then
689
CGRP=${CGRP#X}
690
FILE=cpuset.cpus.exclusive.effective
691
else
692
FILE=cpuset.cpus.effective
693
fi
694
set_cgroup_dir $CGRP
695
[[ -e $CGRP_DIR/$FILE ]] || return 1
696
ACTUAL_CPUS=$(cat $CGRP_DIR/$FILE)
697
[[ $EXPECTED_CPUS = $ACTUAL_CPUS ]] || return 1
698
done
699
}
700
701
#
702
# Check cgroup states
703
# $1 - check string, format: <cgroup>:<state>[|<cgroup>:<state>]*
704
#
705
check_cgroup_states()
706
{
707
CHK_STR=$1
708
for CHK in $(echo $CHK_STR | sed -e "s/|/ /g")
709
do
710
set -- $(echo $CHK | sed -e "s/:/ /g")
711
CGRP=$1
712
EXPECTED_STATE=$2
713
FILE=
714
EVAL=$(expr substr $EXPECTED_STATE 2 2)
715
716
set_cgroup_dir $CGRP
717
case $EXPECTED_STATE in
718
P*) FILE=$CGRP_DIR/cpuset.cpus.partition
719
;;
720
*) echo "Unknown state: $EXPECTED_STATE!"
721
exit 1
722
;;
723
esac
724
ACTUAL_STATE=$(cat $FILE)
725
726
case "$ACTUAL_STATE" in
727
member) VAL=0
728
;;
729
root) VAL=1
730
;;
731
isolated)
732
VAL=2
733
;;
734
"root invalid"*)
735
VAL=-1
736
;;
737
"isolated invalid"*)
738
VAL=-2
739
;;
740
esac
741
[[ $EVAL != $VAL ]] && return 1
742
743
#
744
# For root partition, dump sched-domains info to console if
745
# verbose mode set for manual comparison with sched debug info.
746
#
747
[[ $VAL -eq 1 && $VERBOSE -gt 0 ]] && {
748
DOMS=$(cat $CGRP_DIR/cpuset.cpus.effective)
749
[[ -n "$DOMS" ]] &&
750
echo " [$CGRP_DIR] sched-domain: $DOMS" > $CONSOLE
751
}
752
done
753
return 0
754
}
755
756
#
757
# Get isolated (including offline) CPUs by looking at
758
# /sys/kernel/debug/sched/domains and cpuset.cpus.isolated control file,
759
# if available, and compare that with the expected value.
760
#
761
# Note that isolated CPUs from the sched/domains context include offline
762
# CPUs as well as CPUs in non-isolated 1-CPU partition. Those CPUs may
763
# not be included in the cpuset.cpus.isolated control file which contains
764
# only CPUs in isolated partitions as well as those that are isolated at
765
# boot time.
766
#
767
# $1 - expected isolated cpu list(s) <isolcpus1>{,<isolcpus2>}
768
# <isolcpus1> - expected sched/domains value
769
# <isolcpus2> - cpuset.cpus.isolated value = <isolcpus1> if not defined
770
#
771
check_isolcpus()
772
{
773
EXPECTED_ISOLCPUS=$1
774
ISCPUS=${CGROUP2}/cpuset.cpus.isolated
775
ISOLCPUS=$(cat $ISCPUS)
776
LASTISOLCPU=
777
SCHED_DOMAINS=/sys/kernel/debug/sched/domains
778
if [[ $EXPECTED_ISOLCPUS = . ]]
779
then
780
EXPECTED_ISOLCPUS=
781
EXPECTED_SDOMAIN=
782
elif [[ $(expr $EXPECTED_ISOLCPUS : ".*|.*") > 0 ]]
783
then
784
set -- $(echo $EXPECTED_ISOLCPUS | sed -e "s/|/ /g")
785
EXPECTED_ISOLCPUS=$2
786
EXPECTED_SDOMAIN=$1
787
else
788
EXPECTED_SDOMAIN=$EXPECTED_ISOLCPUS
789
fi
790
791
#
792
# Appending pre-isolated CPUs
793
# Even though CPU #8 isn't used for testing, it can't be pre-isolated
794
# to make appending those CPUs easier.
795
#
796
[[ -n "$BOOT_ISOLCPUS" ]] && {
797
EXPECTED_ISOLCPUS=${EXPECTED_ISOLCPUS:+${EXPECTED_ISOLCPUS},}${BOOT_ISOLCPUS}
798
EXPECTED_SDOMAIN=${EXPECTED_SDOMAIN:+${EXPECTED_SDOMAIN},}${BOOT_ISOLCPUS}
799
}
800
801
#
802
# Check cpuset.cpus.isolated cpumask
803
#
804
[[ "$EXPECTED_ISOLCPUS" != "$ISOLCPUS" ]] && {
805
# Take a 50ms pause and try again
806
pause 0.05
807
ISOLCPUS=$(cat $ISCPUS)
808
}
809
[[ "$EXPECTED_ISOLCPUS" != "$ISOLCPUS" ]] && return 1
810
ISOLCPUS=
811
EXPECTED_ISOLCPUS=$EXPECTED_SDOMAIN
812
813
#
814
# Use the sched domain in debugfs to check isolated CPUs, if available
815
#
816
[[ -d $SCHED_DOMAINS ]] || return 0
817
818
for ((CPU=0; CPU < $NR_CPUS; CPU++))
819
do
820
[[ -n "$(ls ${SCHED_DOMAINS}/cpu$CPU)" ]] && continue
821
822
if [[ -z "$LASTISOLCPU" ]]
823
then
824
ISOLCPUS=$CPU
825
LASTISOLCPU=$CPU
826
elif [[ "$LASTISOLCPU" -eq $((CPU - 1)) ]]
827
then
828
echo $ISOLCPUS | grep -q "\<$LASTISOLCPU\$"
829
if [[ $? -eq 0 ]]
830
then
831
ISOLCPUS=${ISOLCPUS}-
832
fi
833
LASTISOLCPU=$CPU
834
else
835
if [[ $ISOLCPUS = *- ]]
836
then
837
ISOLCPUS=${ISOLCPUS}$LASTISOLCPU
838
fi
839
ISOLCPUS=${ISOLCPUS},$CPU
840
LASTISOLCPU=$CPU
841
fi
842
done
843
[[ "$ISOLCPUS" = *- ]] && ISOLCPUS=${ISOLCPUS}$LASTISOLCPU
844
845
[[ "$EXPECTED_SDOMAIN" = "$ISOLCPUS" ]]
846
}
847
848
test_fail()
849
{
850
TESTNUM=$1
851
TESTTYPE=$2
852
ADDINFO=$3
853
echo "Test $TEST[$TESTNUM] failed $TESTTYPE check!"
854
[[ -n "$ADDINFO" ]] && echo "*** $ADDINFO ***"
855
eval echo \${$TEST[$I]}
856
echo
857
dump_states
858
exit 1
859
}
860
861
#
862
# Check to see if there are unexpected isolated CPUs left beyond the boot
863
# time isolated ones.
864
#
865
null_isolcpus_check()
866
{
867
[[ $VERBOSE -gt 0 ]] || return 0
868
# Retry a few times before printing error
869
RETRY=0
870
while [[ $RETRY -lt 8 ]]
871
do
872
pause 0.02
873
check_isolcpus "."
874
[[ $? -eq 0 ]] && return 0
875
((RETRY++))
876
done
877
echo "Unexpected isolated CPUs: $ISOLCPUS"
878
dump_states
879
exit 1
880
}
881
882
#
883
# Check state transition test result
884
# $1 - Test number
885
# $2 - Expected effective CPU values
886
# $3 - Expected partition states
887
# $4 - Expected isolated CPUs
888
#
889
check_test_results()
890
{
891
_NR=$1
892
_ECPUS="$2"
893
_PSTATES="$3"
894
_ISOLCPUS="$4"
895
896
[[ -n "$_ECPUS" && "$_ECPUS" != . ]] && {
897
check_effective_cpus $_ECPUS
898
[[ $? -ne 0 ]] && test_fail $_NR "effective CPU" \
899
"Cgroup $CGRP: expected $EXPECTED_CPUS, got $ACTUAL_CPUS"
900
}
901
902
[[ -n "$_PSTATES" && "$_PSTATES" != . ]] && {
903
check_cgroup_states $_PSTATES
904
[[ $? -ne 0 ]] && test_fail $_NR states \
905
"Cgroup $CGRP: expected $EXPECTED_STATE, got $ACTUAL_STATE"
906
}
907
908
# Compare the expected isolated CPUs with the actual ones,
909
# if available
910
[[ -n "$_ISOLCPUS" ]] && {
911
check_isolcpus $_ISOLCPUS
912
[[ $? -ne 0 ]] && {
913
[[ -n "$BOOT_ISOLCPUS" ]] && _ISOLCPUS=${_ISOLCPUS},${BOOT_ISOLCPUS}
914
test_fail $_NR "isolated CPU" \
915
"Expect $_ISOLCPUS, get $ISOLCPUS instead"
916
}
917
}
918
reset_cgroup_states
919
#
920
# Check to see if effective cpu list changes
921
#
922
_NEWLIST=$(cat $CGROUP2/cpuset.cpus.effective)
923
RETRY=0
924
while [[ $_NEWLIST != $CPULIST && $RETRY -lt 8 ]]
925
do
926
# Wait a bit longer & recheck a few times
927
pause 0.02
928
((RETRY++))
929
_NEWLIST=$(cat $CGROUP2/cpuset.cpus.effective)
930
done
931
[[ $_NEWLIST != $CPULIST ]] && {
932
echo "Effective cpus changed to $_NEWLIST after test $_NR!"
933
exit 1
934
}
935
null_isolcpus_check
936
[[ $VERBOSE -gt 0 ]] && echo "Test $I done."
937
}
938
939
#
940
# Run cpuset state transition test
941
# $1 - test matrix name
942
#
943
# This test is somewhat fragile as delays (sleep x) are added in various
944
# places to make sure state changes are fully propagated before the next
945
# action. These delays may need to be adjusted if running in a slower machine.
946
#
947
run_state_test()
948
{
949
TEST=$1
950
CONTROLLER=cpuset
951
CGROUP_LIST=". A1 A1/A2 A1/A2/A3 B1"
952
RESET_LIST="A1/A2/A3 A1/A2 A1 B1"
953
I=0
954
eval CNT="\${#$TEST[@]}"
955
956
reset_cgroup_states
957
console_msg "Running state transition test ..."
958
959
while [[ $I -lt $CNT ]]
960
do
961
echo "Running test $I ..." > $CONSOLE
962
[[ $VERBOSE -gt 1 ]] && {
963
echo ""
964
eval echo \${$TEST[$I]}
965
}
966
eval set -- "\${$TEST[$I]}"
967
OLD_A1=$1
968
OLD_A2=$2
969
OLD_A3=$3
970
OLD_B1=$4
971
NEW_A1=$5
972
NEW_A2=$6
973
NEW_A3=$7
974
NEW_B1=$8
975
RESULT=$9
976
ECPUS=${10}
977
STATES=${11}
978
ICPUS=${12}
979
980
set_ctrl_state_noerr A1 $OLD_A1
981
set_ctrl_state_noerr A1/A2 $OLD_A2
982
set_ctrl_state_noerr A1/A2/A3 $OLD_A3
983
set_ctrl_state_noerr B1 $OLD_B1
984
985
RETVAL=0
986
set_ctrl_state A1 $NEW_A1; ((RETVAL += $?))
987
set_ctrl_state A1/A2 $NEW_A2; ((RETVAL += $?))
988
set_ctrl_state A1/A2/A3 $NEW_A3; ((RETVAL += $?))
989
set_ctrl_state B1 $NEW_B1; ((RETVAL += $?))
990
991
[[ $RETVAL -ne $RESULT ]] && test_fail $I result
992
993
check_test_results $I "$ECPUS" "$STATES" "$ICPUS"
994
((I++))
995
done
996
echo "All $I tests of $TEST PASSED."
997
}
998
999
#
1000
# Run cpuset remote partition state transition test
1001
# $1 - test matrix name
1002
#
1003
run_remote_state_test()
1004
{
1005
TEST=$1
1006
CONTROLLER=cpuset
1007
[[ -d rtest ]] || mkdir rtest
1008
cd rtest
1009
echo +cpuset > cgroup.subtree_control
1010
echo "1-7" > cpuset.cpus
1011
echo "1-7" > cpuset.cpus.exclusive
1012
CGROUP_LIST=".. . p1 p2 p1/c11 p1/c12 p2/c21 p2/c22"
1013
RESET_LIST="p1/c11 p1/c12 p2/c21 p2/c22 p1 p2"
1014
I=0
1015
eval CNT="\${#$TEST[@]}"
1016
1017
reset_cgroup_states
1018
console_msg "Running remote partition state transition test ..."
1019
1020
while [[ $I -lt $CNT ]]
1021
do
1022
echo "Running test $I ..." > $CONSOLE
1023
[[ $VERBOSE -gt 1 ]] && {
1024
echo ""
1025
eval echo \${$TEST[$I]}
1026
}
1027
eval set -- "\${$TEST[$I]}"
1028
OLD_p1=$1
1029
OLD_p2=$2
1030
OLD_c11=$3
1031
OLD_c12=$4
1032
OLD_c21=$5
1033
OLD_c22=$6
1034
NEW_p1=$7
1035
NEW_p2=$8
1036
NEW_c11=$9
1037
NEW_c12=${10}
1038
NEW_c21=${11}
1039
NEW_c22=${12}
1040
ECPUS=${13}
1041
STATES=${14}
1042
ICPUS=${15}
1043
1044
set_ctrl_state_noerr p1 $OLD_p1
1045
set_ctrl_state_noerr p2 $OLD_p2
1046
set_ctrl_state_noerr p1/c11 $OLD_c11
1047
set_ctrl_state_noerr p1/c12 $OLD_c12
1048
set_ctrl_state_noerr p2/c21 $OLD_c21
1049
set_ctrl_state_noerr p2/c22 $OLD_c22
1050
1051
RETVAL=0
1052
set_ctrl_state p1 $NEW_p1 ; ((RETVAL += $?))
1053
set_ctrl_state p2 $NEW_p2 ; ((RETVAL += $?))
1054
set_ctrl_state p1/c11 $NEW_c11; ((RETVAL += $?))
1055
set_ctrl_state p1/c12 $NEW_c12; ((RETVAL += $?))
1056
set_ctrl_state p2/c21 $NEW_c21; ((RETVAL += $?))
1057
set_ctrl_state p2/c22 $NEW_c22; ((RETVAL += $?))
1058
1059
[[ $RETVAL -ne 0 ]] && test_fail $I result
1060
1061
check_test_results $I "$ECPUS" "$STATES" "$ICPUS"
1062
((I++))
1063
done
1064
cd ..
1065
rmdir rtest
1066
echo "All $I tests of $TEST PASSED."
1067
}
1068
1069
#
1070
# Testing the new "isolated" partition root type
1071
#
1072
test_isolated()
1073
{
1074
cd $CGROUP2/test
1075
echo 2-3 > cpuset.cpus
1076
TYPE=$(cat cpuset.cpus.partition)
1077
[[ $TYPE = member ]] || echo member > cpuset.cpus.partition
1078
1079
console_msg "Change from member to root"
1080
test_partition root
1081
1082
console_msg "Change from root to isolated"
1083
test_partition isolated
1084
1085
console_msg "Change from isolated to member"
1086
test_partition member
1087
1088
console_msg "Change from member to isolated"
1089
test_partition isolated
1090
1091
console_msg "Change from isolated to root"
1092
test_partition root
1093
1094
console_msg "Change from root to member"
1095
test_partition member
1096
1097
#
1098
# Testing partition root with no cpu
1099
#
1100
console_msg "Distribute all cpus to child partition"
1101
echo +cpuset > cgroup.subtree_control
1102
test_partition root
1103
1104
mkdir A1
1105
cd A1
1106
echo 2-3 > cpuset.cpus
1107
test_partition root
1108
test_effective_cpus 2-3
1109
cd ..
1110
test_effective_cpus ""
1111
1112
console_msg "Moving task to partition test"
1113
test_add_proc "No space left"
1114
cd A1
1115
test_add_proc ""
1116
cd ..
1117
1118
console_msg "Shrink and expand child partition"
1119
cd A1
1120
echo 2 > cpuset.cpus
1121
cd ..
1122
test_effective_cpus 3
1123
cd A1
1124
echo 2-3 > cpuset.cpus
1125
cd ..
1126
test_effective_cpus ""
1127
1128
# Cleaning up
1129
console_msg "Cleaning up"
1130
echo $$ > $CGROUP2/cgroup.procs
1131
[[ -d A1 ]] && rmdir A1
1132
null_isolcpus_check
1133
pause 0.05
1134
}
1135
1136
#
1137
# Wait for inotify event for the given file and read it
1138
# $1: cgroup file to wait for
1139
# $2: file to store the read result
1140
#
1141
wait_inotify()
1142
{
1143
CGROUP_FILE=$1
1144
OUTPUT_FILE=$2
1145
1146
$WAIT_INOTIFY $CGROUP_FILE
1147
cat $CGROUP_FILE > $OUTPUT_FILE
1148
}
1149
1150
#
1151
# Test if inotify events are properly generated when going into and out of
1152
# invalid partition state.
1153
#
1154
test_inotify()
1155
{
1156
ERR=0
1157
PRS=/tmp/.prs_$$
1158
cd $CGROUP2/test
1159
[[ -f $WAIT_INOTIFY ]] || {
1160
echo "wait_inotify not found, inotify test SKIPPED."
1161
return
1162
}
1163
1164
pause 0.01
1165
echo 1 > cpuset.cpus
1166
echo 0 > cgroup.procs
1167
echo root > cpuset.cpus.partition
1168
pause 0.01
1169
rm -f $PRS
1170
wait_inotify $PWD/cpuset.cpus.partition $PRS &
1171
pause 0.01
1172
set_ctrl_state . "O1=0"
1173
pause 0.01
1174
check_cgroup_states ".:P-1"
1175
if [[ $? -ne 0 ]]
1176
then
1177
echo "FAILED: Inotify test - partition not invalid"
1178
ERR=1
1179
elif [[ ! -f $PRS ]]
1180
then
1181
echo "FAILED: Inotify test - event not generated"
1182
ERR=1
1183
kill %1
1184
elif [[ $(cat $PRS) != "root invalid"* ]]
1185
then
1186
echo "FAILED: Inotify test - incorrect state"
1187
cat $PRS
1188
ERR=1
1189
fi
1190
online_cpus
1191
echo member > cpuset.cpus.partition
1192
echo 0 > ../cgroup.procs
1193
if [[ $ERR -ne 0 ]]
1194
then
1195
exit 1
1196
else
1197
echo "Inotify test PASSED"
1198
fi
1199
echo member > cpuset.cpus.partition
1200
echo "" > cpuset.cpus
1201
}
1202
1203
trap cleanup 0 2 3 6
1204
run_state_test TEST_MATRIX
1205
run_remote_state_test REMOTE_TEST_MATRIX
1206
test_isolated
1207
test_inotify
1208
echo "All tests PASSED."
1209
1210