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