xref: /aosp_15_r20/external/ltp/testcases/kernel/controllers/cgroup/cgroup_regression_test.sh (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0-or-later
3# Copyright (c) 2019-2022 Petr Vorel <[email protected]>
4# Copyright (c) 2009 FUJITSU LIMITED
5# Author: Li Zefan <[email protected]>
6
7TST_TESTFUNC=test
8TST_SETUP=do_setup
9TST_CLEANUP=do_cleanup
10TST_CNT=8
11TST_NEEDS_ROOT=1
12TST_NEEDS_TMPDIR=1
13TST_NEEDS_CMDS="awk dmesg find mountpoint rmdir"
14
15do_setup()
16{
17	mkdir cgroup/
18
19	if [ ! -f /proc/cgroups ]; then
20		tst_brk TCONF ignored "Kernel does not support for control groups; skipping testcases";
21	fi
22
23	dmesg -c > /dev/null
24	NR_BUG=`dmesg | grep -c "kernel BUG"`
25	NR_NULL=`dmesg | grep -c "kernel NULL pointer dereference"`
26	NR_WARNING=`dmesg | grep -c "^WARNING"`
27	NR_LOCKDEP=`dmesg | grep -c "possible recursive locking detected"`
28}
29
30do_cleanup()
31{
32	if mountpoint -q cgroup/; then
33		find cgroup/ -maxdepth 1 -depth -exec rmdir {} +
34		umount cgroup/
35		rmdir cgroup
36	fi
37}
38
39check_kernel_bug()
40{
41	local id="$1"
42	local ok_msg="no kernel bug was found"
43	local new_bug=`dmesg | grep -c "kernel BUG"`
44	local new_null=`dmesg | grep -c "kernel NULL pointer dereference"`
45	local new_warning=`dmesg | grep -c "^WARNING"`
46	local new_lockdep=`dmesg | grep -c "possible recursive locking detected"`
47
48	[ "$id" ] && ok_msg="$ok_msg for test $i"
49
50	# no kernel bug is detected
51	if [ $new_bug -eq $NR_BUG -a $new_warning -eq $NR_WARNING -a \
52	     $new_null -eq $NR_NULL -a $new_lockdep -eq $NR_LOCKDEP ]; then
53		tst_res TPASS $ok_msg
54		return 0
55	fi
56
57	# some kernel bug is detected
58	if [ $new_bug -gt $NR_BUG ]; then
59		tst_res TFAIL "kernel BUG was detected!"
60	fi
61	if [ $new_warning -gt $NR_WARNING ]; then
62		tst_res TFAIL "kernel WARNING was detected!"
63	fi
64	if [ $new_null -gt $NR_NULL ]; then
65		tst_res TFAIL "kernel NULL pointer dereference!"
66	fi
67	if [ $new_lockdep -gt $NR_LOCKDEP ]; then
68		tst_res TFAIL "kernel lockdep warning was detected!"
69	fi
70
71	NR_BUG=$new_bug
72	NR_NULL=$new_null
73	NR_WARNING=$new_warning
74	NR_LOCKDEP=$new_lockdep
75
76	tst_res TWARN "BUG FOUND!"
77	dmesg
78	return 1
79}
80
81#---------------------------------------------------------------------------
82# Bug:    There was a race when keeping forking processes and at the same
83#         time cat /cgroup/tasks (should be the very first time to read
84#         /cgroup/tasks, otherwise this bug won't be triggered)
85# Kernel: 2.6.24, 2.6.25-rcX
86# Links:  http://lkml.org/lkml/2007/10/17/224
87#         http://lkml.org/lkml/2008/3/5/332
88#         http://lkml.org/lkml/2008/4/16/493
89# Fix:    commit 0e04388f0189fa1f6812a8e1cb6172136eada87e
90#---------------------------------------------------------------------------
91test1()
92{
93	cgroup_regression_fork_processes &
94	sleep 1
95
96	mount -t cgroup -o none,name=foo cgroup cgroup/
97	if [ $? -ne 0 ]; then
98		tst_res TFAIL "failed to mount cgroup filesystem"
99		kill -TERM $!
100		return
101	fi
102	cat cgroup/tasks > /dev/null
103
104	kill -TERM $!
105	wait $! 2>/dev/null
106	umount cgroup/
107	check_kernel_bug
108}
109
110#---------------------------------------------------------------------------
111# Bug:    a cgroup's notify_on_release flag did not inherit from its parent.
112# Kernel: 2.6.24-rcX
113# Links:  http://lkml.org/lkml/2008/2/25/12
114# Fix:    commit bc231d2a048010d5e0b49ac7fddbfa822fc41109
115#---------------------------------------------------------------------------
116test2()
117{
118	local val1
119	local val2
120
121	mount -t cgroup -o none,name=foo cgroup cgroup/
122	if [ $? -ne 0 ]; then
123		tst_res TFAIL "Failed to mount cgroup filesystem"
124		return
125	fi
126
127	echo 0 > cgroup/notify_on_release
128	mkdir cgroup/0
129	val1=`cat cgroup/0/notify_on_release`
130
131	echo 1 > cgroup/notify_on_release
132	mkdir cgroup/1
133	val2=`cat cgroup/1/notify_on_release`
134
135	if [ $val1 -ne 0 -o $val2 -ne 1 ]; then
136		tst_res TFAIL "wrong notify_on_release value"
137	else
138		tst_res TPASS "notify_on_release is inherited"
139	fi
140
141	rmdir cgroup/0 cgroup/1
142	tst_umount $PWD/cgroup
143}
144
145#---------------------------------------------------------------------------
146# Bug:    Accessing NULL cgrp->dentry when reading /proc/sched_debug
147# Kernel: 2.6.26-2.6.28
148# Links:  http://lkml.org/lkml/2008/10/30/44
149#         http://lkml.org/lkml/2008/12/12/107
150#         http://lkml.org/lkml/2008/12/16/481
151# Fix:    commit a47295e6bc42ad35f9c15ac66f598aa24debd4e2
152#---------------------------------------------------------------------------
153test3()
154{
155	local cpu_subsys_path
156
157	if [ ! -e /proc/sched_debug ]; then
158		tst_res TCONF "CONFIG_SCHED_DEBUG is not enabled"
159		return
160	fi
161
162	if ! grep -q -w "cpu" /proc/cgroups; then
163		tst_res TCONF "CONFIG_CGROUP_SCHED is not enabled"
164		return
165	fi
166
167	cgroup_require "cpu"
168	cpu_subsys_path=$(cgroup_get_mountpoint "cpu")
169
170	cgroup_regression_3_1.sh $cpu_subsys_path &
171	pid1=$!
172	cgroup_regression_3_2.sh &
173	pid2=$!
174
175	sleep 30
176	kill -USR1 $pid1 $pid2
177	wait $pid1 2>/dev/null
178	wait $pid2 2>/dev/null
179
180	rmdir $cpu_subsys_path/0 2> /dev/null
181	cgroup_cleanup
182	check_kernel_bug
183}
184
185#---------------------------------------------------------------------------
186# Bug:    cgroup hierarchy lock's lockdep subclass may overflow
187# Kernel: 2.6.29-rcX
188# Link:   http://lkml.org/lkml/2009/2/4/67
189# Fix:
190#---------------------------------------------------------------------------
191test4()
192{
193	local lines
194
195	if [ ! -e /proc/lockdep ]; then
196		tst_res TCONF "CONFIG_LOCKDEP is not enabled"
197		return
198	fi
199
200	# MAX_LOCKDEP_SUBCLASSES is 8, so number of subsys should be > 8
201	lines=`cat /proc/cgroups | wc -l`
202	if [ $lines -le 9 ]; then
203		tst_res TCONF "require more than 8 cgroup subsystems"
204		return
205	fi
206
207	mount -t cgroup -o none,name=foo cgroup cgroup/
208	mkdir cgroup/0
209	rmdir cgroup/0
210	tst_umount $PWD/cgroup
211
212	if dmesg | grep -q "MAX_LOCKDEP_SUBCLASSES too low"; then
213		tst_res TFAIL "lockdep BUG was found"
214		return
215	fi
216
217	tst_res TPASS "no lockdep BUG was found"
218}
219
220#---------------------------------------------------------------------------
221# Bug:    When running 2 concurrent mount/umount threads, kernel WARNING
222#         may be triggered, but it's VFS' issue but not cgroup.
223# Kernel: 2.6.24 - 2.6.29-rcX
224# Links:  http://lkml.org/lkml/2009/1/4/354
225# Fix:    commit 1a88b5364b535edaa321d70a566e358390ff0872
226#---------------------------------------------------------------------------
227test5()
228{
229	cgroup_regression_5_1.sh &
230	local pid1=$!
231	cgroup_regression_5_2.sh &
232	local pid2=$!
233
234	sleep 30
235	kill -USR1 $pid1 $pid2
236	wait $pid1 2>/dev/null
237	wait $pid2 2>/dev/null
238
239	mount -t cgroup none cgroup 2> /dev/null
240	mkdir cgroup/0
241	rmdir cgroup/0
242	tst_umount $PWD/cgroup
243	check_kernel_bug
244}
245
246#---------------------------------------------------------------------------
247# Bug:    When running 2 concurrent mount/umount threads, lockdep warning
248#         may be triggered, it's a false positive, and it's VFS' issue but
249#         not cgroup.
250# Kernel: 2.6.24 - 2.6.29-rcX
251# Links:  http://lkml.org/lkml/2009/1/4/352
252# Fix:    commit ada723dcd681e2dffd7d73345cc8fda0eb0df9bd
253#---------------------------------------------------------------------------
254test6()
255{
256	cgroup_regression_6_1.sh &
257	local pid1=$!
258	cgroup_regression_6_2.sh &
259	local pid2=$!
260
261	sleep 30
262	kill -USR1 $pid1 $pid2
263	wait $pid1 2>/dev/null
264	wait $pid2 2>/dev/null
265
266	umount cgroup/ 2> /dev/null
267	check_kernel_bug
268}
269
270#---------------------------------------------------------------------------
271# Bug:    There was a bug when remount cgroup fs with some dead subdirs in
272#         it (rmdir()ed but still has some refcnts on it). It caused memory
273#         leak, and may cause oops when cat /proc/sched_debug.
274# Kernel: 2.6.24 - 2.6.27, 2.6.28-rcX
275# Links:  http://lkml.org/lkml/2008/12/10/369
276# Fix:    commit 307257cf475aac25db30b669987f13d90c934e3a
277#---------------------------------------------------------------------------
278test_7_1()
279{
280	local subsys=$1
281	local subsys_path
282	# we should be careful to select a $subsys_path which is related to
283	# cgroup only: if cgroup debugging is enabled a 'debug' $subsys
284	# could be passed here as params and this will lead to ambiguity and
285	# errors when grepping simply for 'debug' in /proc/mounts since we'll
286	# find also /sys/kernel/debug. Helper takes care of this.
287
288	cgroup_require "$subsys"
289	subsys_path=$(cgroup_get_mountpoint "$subsys")
290
291	mkdir $subsys_path/0
292	sleep 100 < $subsys_path/0 &	# add refcnt to this dir
293	rmdir $subsys_path/0
294
295	# remount with new subsystems added
296	# since 2.6.28, this remount will fail
297
298	if [ "$subsys_path" = "cgroup" ]; then
299		mount -t cgroup -o remount xxx cgroup/ 2> /dev/null
300		kill -TERM $!
301		wait $! 2>/dev/null
302		umount cgroup/
303	fi
304
305	cgroup_cleanup
306}
307
308test_7_2()
309{
310	local subsys=$1
311
312	mount -t cgroup -o none,name=foo cgroup cgroup/
313	if [ $? -ne 0 ]; then
314		tst_res TFAIL "failed to mount cgroup"
315		return
316	fi
317
318	mkdir cgroup/0
319	sleep 100 < cgroup/0 &	# add refcnt to this dir
320	rmdir cgroup/0
321
322	# remount with some subsystems removed
323	# since 2.6.28, this remount will fail
324	mount -t cgroup -o remount,$subsys xxx cgroup/ 2> /dev/null
325	kill -TERM $!
326	wait $! 2>/dev/null
327	umount cgroup/
328
329	grep -q -w "cpu" /proc/cgroups
330	if [ $? -ne 0 -o ! -e /proc/sched_debug ]; then
331		tst_res TCONF "skip rest of testing due possible oops triggered by reading /proc/sched_debug"
332		return
333	fi
334
335	tmp=0
336	while [ $tmp -lt 50 ]; do
337		echo 3 > /proc/sys/vm/drop_caches
338		cat /proc/sched_debug > /dev/null
339		tmp=$((tmp+1))
340	done
341}
342
343test7()
344{
345	local lines=`cat /proc/cgroups | wc -l`
346	local subsys
347	local i=1
348
349	if [ $lines -le 2 ]; then
350		tst_res TCONF "require at least 2 cgroup subsystems"
351		slt_result $SLT_Untested
352		return
353	fi
354
355	subsys=`tail -n 1 /proc/cgroups | awk '{ print $1 }'`
356
357	# remount to add new subsystems to the hierarchy
358	while [ $i -le 2 ]; do
359		test_7_$i $subsys || return
360		check_kernel_bug $i || return
361		i=$((i+1))
362	done
363}
364
365#---------------------------------------------------------------------------
366# Bug:    oops when get cgroupstat of a cgroup control file
367# Kernel: 2.6.24 - 2.6.27, 2.6.28-rcX
368# Links:  http://lkml.org/lkml/2008/11/19/53
369# Fix:    commit 33d283bef23132c48195eafc21449f8ba88fce6b
370#---------------------------------------------------------------------------
371test8()
372{
373	mount -t cgroup -o none,name=foo cgroup cgroup/
374	if [ $? -ne 0 ]; then
375		tst_res TFAIL "failed to mount cgroup filesystem"
376		return
377	fi
378
379	if cgroup_regression_getdelays -C cgroup/tasks > /dev/null 2>&1; then
380		tst_res TFAIL "should have failed to get cgroupstat of tasks file"
381	fi
382
383	umount cgroup/
384	check_kernel_bug
385}
386
387. cgroup_lib.sh
388tst_run
389