1#! /bin/sh
2
3################################################################################
4##                                                                            ##
5## Copyright (c) 2009 FUJITSU LIMITED                                         ##
6##                                                                            ##
7## This program is free software;  you can redistribute it and#or modify      ##
8## it under the terms of the GNU General Public License as published by       ##
9## the Free Software Foundation; either version 2 of the License, or          ##
10## (at your option) any later version.                                        ##
11##                                                                            ##
12## This program is distributed in the hope that it will be useful, but        ##
13## WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ##
14## or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License   ##
15## for more details.                                                          ##
16##                                                                            ##
17## You should have received a copy of the GNU General Public License          ##
18## along with this program;  if not, write to the Free Software               ##
19## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA    ##
20##                                                                            ##
21## Author: Li Zefan <lizf@cn.fujitsu.com>                                     ##
22## Added memcg enable/disable functinality: Rishikesh K Rajak                 ##
23##                                              <risrajak@linux.vnet.ibm.com  ##
24##                                                                            ##
25################################################################################
26
27cd $LTPROOT/testcases/bin
28
29export TCID="memcg_regression_test"
30export TST_TOTAL=4
31export TST_COUNT=1
32
33if [ "$(id -ru)" != 0 ]; then
34	tst_brkm TBROK ignored "Test must be run as root"
35	exit 0
36fi
37
38if [ "x$(grep -w memory /proc/cgroups | cut -f4)" != "x1" ]; then
39	tst_resm TCONF "Either memory resource controller kernel support absent"
40	tst_resm TCONF "or feature is not enabled; skipping all memcgroup testcases."
41        exit 0
42fi
43
44if tst_kvcmp -lt "2.6.30"; then
45	tst_brkm TBROK ignored "Test should be run with kernel 2.6.30 or newer"
46	exit 0
47fi
48
49#buffer can rotate and number of found bugs can actually go down
50#so clear the buffer to avoid this
51dmesg -c > /dev/null
52nr_bug=0
53nr_null=0
54nr_warning=0
55nr_lockdep=0
56
57# check_kernel_bug - check if some kind of kernel bug happened
58check_kernel_bug()
59{
60	new_bug=`dmesg | grep -c "kernel BUG"`
61	new_null=`dmesg | grep -c "kernel NULL pointer dereference"`
62	new_warning=`dmesg | grep -c "^WARNING"`
63	new_lockdep=`dmesg | grep -c "possible recursive locking detected"`
64
65	# no kernel bug is detected
66	if [ $new_bug -eq $nr_bug -a $new_warning -eq $nr_warning -a \
67	     $new_null -eq $nr_null -a $new_lockdep -eq $nr_lockdep ]; then
68		return 1
69	fi
70
71	# some kernel bug is detected
72	if [ $new_bug -gt $nr_bug ]; then
73		tst_resm TFAIL "kernel BUG was detected!"
74	fi
75	if [ $new_warning -gt $nr_warning ]; then
76		tst_resm TFAIL "kernel WARNING was detected!"
77	fi
78	if [ $new_null -gt $nr_null ]; then
79		tst_resm "kernel NULL pointer dereference!"
80	fi
81	if [ $new_lockdep -gt $nr_lockdep ]; then
82		tst_resm "kernel lockdep warning was detected!"
83	fi
84
85	nr_bug=$new_bug
86	nr_null=$new_null
87	nr_warning=$new_warning
88	nr_lockdep=$new_lockdep
89
90	echo "check_kernel_bug found something!"
91	dmesg
92	failed=1
93	return 0
94}
95
96#---------------------------------------------------------------------------
97# Bug:    The bug was, while forking mass processes, trigger memcgroup OOM,
98#         then NULL pointer dereference may be hit.
99# Kernel: 2.6.25-rcX
100# Links:  http://lkml.org/lkml/2008/4/14/38
101# Fix:    commit e115f2d89253490fb2dbf304b627f8d908df26f1
102#---------------------------------------------------------------------------
103test_1()
104{
105	mkdir memcg/0/
106	echo 0 > memcg/0/memory.limit_in_bytes
107
108	./memcg_test_1
109
110	rmdir memcg/0/
111
112	check_kernel_bug
113	if [ $? -eq 1 ]; then
114		tst_resm TPASS "no kernel bug was found"
115	fi
116}
117
118#---------------------------------------------------------------------------
119# Bug:    Shrink memory might never return, unless send signal to stop it.
120# Kernel: 2.6.29
121# Links:  http://marc.info/?t=123199973900003&r=1&w=2
122#         http://lkml.org/lkml/2009/2/3/72
123# Fix:    81d39c20f5ee2437d71709beb82597e2a38efbbc
124#---------------------------------------------------------------------------
125test_2()
126{
127	./memcg_test_2 &
128	pid1=$!
129	sleep 1
130
131	mkdir memcg/0
132	echo $pid1 > memcg/0/tasks
133
134	# let pid1 'test_2' allocate memory
135	/bin/kill -SIGUSR1 $pid1
136	sleep 1
137
138	# shrink memory
139	echo 1 > memcg/0/memory.limit_in_bytes 2>&1 &
140	pid2=$!
141
142	# check if 'echo' will exit and exit with failure
143	for tmp in $(seq 0 4); do
144		sleep 1
145		ps -p $! > /dev/null
146		if [ $? -ne 0 ]; then
147			wait $pid2
148			if [ $? -eq 0 ]; then
149				tst_resm TFAIL "echo should return failure"
150				failed=1
151				kill -9 $pid1 $pid2 > /dev/null 2>&1
152				wait $pid1 $pid2
153				rmdir memcg/0
154			fi
155			break
156		fi
157	done
158
159	if [ $tmp -eq 5 ]; then
160		tst_resm TFAIL "'echo' doesn't exit!"
161		failed=1
162	else
163		tst_resm TPASS "EBUSY was returned as expected"
164	fi
165
166	kill -9 $pid1 $pid2 > /dev/null 2>&1
167	wait $pid1 $pid2 > /dev/null 2>&1
168	rmdir memcg/0
169}
170
171#---------------------------------------------------------------------------
172# Bug:    crash when rmdir a cgroup on IA64
173# Kernel: 2.6.29-rcX
174# Links:  http://marc.info/?t=123235660300001&r=1&w=2
175# Fix:    commit 299b4eaa302138426d5a9ecd954de1f565d76c94
176#---------------------------------------------------------------------------
177test_3()
178{
179	mkdir memcg/0
180	for pid in `cat memcg/tasks`; do
181		echo $pid > memcg/0/tasks 2> /dev/null
182	done
183
184	for pid in `cat memcg/0/tasks`; do
185		echo $pid > memcg/tasks 2> /dev/null
186	done
187	rmdir memcg/0
188
189	check_kernel_bug
190	if [ $? -eq 1 ]; then
191		tst_resm TPASS "no kernel bug was found"
192	fi
193}
194
195#---------------------------------------------------------------------------
196# Bug:    the memcg's refcnt handling at swapoff was wrong, causing crash
197# Kernel: 2.6.29-rcX
198# Links:  http://marc.info/?t=123208656300004&r=1&w=2
199# Fix:    commit 85d9fc89fb0f0703df6444f260187c088a8d59ff
200#---------------------------------------------------------------------------
201test_4()
202{
203	./memcg_test_4.sh
204
205	check_kernel_bug
206	if [ $? -eq 1 ]; then
207		tst_resm TPASS "no kernel bug was found"
208	fi
209
210	# test_4.sh might be killed by oom, so do clean up here
211	killall -9 memcg_test_4 2> /dev/null
212	killall -9 memcg_test_4.sh 2> /dev/null
213
214	# if test_4.sh gets killed, it won't clean cgroup it created
215	rmdir memcg/0 2> /dev/null
216
217	swapon -a
218}
219
220# main
221failed=0
222mkdir memcg/
223
224for cur in $(seq 1 $TST_TOTAL); do
225	export TST_COUNT=$cur
226
227	mount -t cgroup -o memory xxx memcg/
228	if [ $? -ne 0 ]; then
229		tst_resm TFAIL "failed to mount memory subsystem"
230		failed=1
231		continue
232	fi
233
234	test_$cur
235
236	umount memcg/
237done
238
239rmdir memcg/
240
241exit $failed
242
243