memcg_lib.sh revision 5ac2d3d2b102464b97d9865055832b9a6414b763
1#! /bin/sh
2
3################################################################################
4##                                                                            ##
5## Copyright (c) 2012 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA    ##
20##                                                                            ##
21## Author: Peng Haitao <penght@cn.fujitsu.com>                                ##
22##                                                                            ##
23################################################################################
24
25if [ "x$(grep -w memory /proc/cgroups | cut -f4)" != "x1" ]; then
26	echo "WARNING:";
27	echo "Either Kernel does not support for memory resource controller or feature not enabled";
28	echo "Skipping all memcgroup testcases....";
29	exit 0
30fi
31
32cd $LTPROOT/testcases/bin
33
34TEST_PATH=$PWD
35PAGESIZE=`./memcg_getpagesize`
36HUGEPAGESIZE=`grep Hugepagesize /proc/meminfo | awk '{ print $2 }'`
37[ -z $HUGEPAGESIZE ] && HUGEPAGESIZE=0
38HUGEPAGESIZE=$(( $HUGEPAGESIZE * 1024 ))
39PASS=0
40FAIL=1
41
42cur_id=0
43failed=0
44
45# Record the test result of a test case
46# $1 - The result of the test case, $PASS or $FAIL
47# $2 - The output information
48result()
49{
50	local pass=$1
51	local info="$2"
52
53	if [ $pass -eq $PASS ]; then
54		tst_resm TPASS "$info"
55	else
56		tst_resm TFAIL "$info"
57		: $(( failed += 1 ))
58	fi
59}
60
61# Check size in memcg
62# $1 - Item name
63# $2 - Expected size
64check_mem_stat()
65{
66	if [ -e $1 ]; then
67		item_size=`cat $1`
68	else
69		item_size=`grep -w $1 memory.stat | cut -d " " -f 2`
70	fi
71
72	if [ "$2" = "$item_size" ]; then
73		pass=$PASS
74	else
75		pass=$FAIL
76	fi
77
78	result $pass "$1=$item_size/$2"
79}
80
81warmup()
82{
83	pid=$1
84
85	echo "Warming up for test: $cur_id, pid: $pid"
86	kill -s USR1 $pid 2> /dev/null
87	sleep 1
88	kill -s USR1 $pid 2> /dev/null
89	sleep 1
90
91	kill -0 $pid
92	if [ $? -ne 0 ]; then
93		result $FAIL "cur_id=$cur_id"
94		return 1
95	else
96		echo "Process is still here after warm up: $pid"
97	fi
98
99	return 0
100}
101
102# Run test cases which checks memory.stat after make
103# some memory allocation
104# $1 - the parameters of 'process', such as --shm
105# $2 - the -s parameter of 'process', such as 4096
106# $3 - item name in memory.stat
107# $4 - the expected size
108# $5 - check after free ?
109test_mem_stat()
110{
111	echo "Running $TEST_PATH/memcg_process $1 -s $2"
112	$TEST_PATH/memcg_process $1 -s $2 &
113	sleep 1
114
115	warmup $!
116	if [ $? -ne 0 ]; then
117		return
118	fi
119
120	echo $! > tasks
121	kill -s USR1 $! 2> /dev/null
122	sleep 1
123
124	check_mem_stat $3 $4
125
126	kill -s USR1 $! 2> /dev/null
127	sleep 1
128	if [ $5 -eq 1 ]; then
129		check_mem_stat $3 0
130	fi
131
132	kill -s INT $! 2> /dev/null
133}
134
135# Run test cases which checks memory.max_usage_in_bytes after make
136# some memory allocation
137# $1 - the parameters of 'process', such as --shm
138# $2 - the -s parameter of 'process', such as 4096
139# $3 - item name
140# $4 - the expected size
141# $5 - check after free ?
142test_max_usage_in_bytes()
143{
144	echo "Running $TEST_PATH/memcg_process $1 -s $2"
145	$TEST_PATH/memcg_process $1 -s $2 &
146	sleep 1
147
148	warmup $!
149	if [ $? -ne 0 ]; then
150		return
151	fi
152
153	echo $! > tasks
154	kill -s USR1 $! 2> /dev/null
155	sleep 1
156
157	kill -s USR1 $! 2> /dev/null
158	sleep 1
159
160	check_mem_stat $3 $4
161
162	if [ $5 -eq 1 ]; then
163		echo 0 > $3
164		check_mem_stat $3 0
165	fi
166
167	kill -s INT $! 2> /dev/null
168}
169
170# make some memory allocation
171# $1 - the parameters of 'process', such as --shm
172# $2 - the -s parameter of 'process', such as 4096
173malloc_free_memory()
174{
175	echo "Running $TEST_PATH/memcg_process $1 -s $2"
176	$TEST_PATH/memcg_process $1 -s $2 &
177	sleep 1
178
179	echo $! > tasks
180	kill -s USR1 $! 2> /dev/null
181	sleep 1
182
183	kill -s USR1 $! 2> /dev/null
184	sleep 1
185
186	kill -s INT $! 2> /dev/null
187}
188
189# Test if failcnt > 0, which means page reclamation occured
190# $1 - item name in memcg
191test_failcnt()
192{
193	failcnt=`cat $1`
194	if [ $failcnt -gt 0 ]; then
195		pass=$PASS
196	else
197		pass=$FAIL
198	fi
199
200	result $pass "$1=$failcnt"
201}
202
203# Test process will be killed due to exceed memory limit
204# $1 - the value of memory.limit_in_bytes
205# $2 - the parameters of 'process', such as --shm
206# $3 - the -s parameter of 'process', such as 4096
207# $4 - use mem+swap limitation
208test_proc_kill()
209{
210	echo $1 > memory.limit_in_bytes
211	if [ $4 -eq 1 ]; then
212		if [ -e memory.memsw.limit_in_bytes ]; then
213			echo $1 > memory.memsw.limit_in_bytes
214		else
215			tst_resm TCONF "mem+swap is not enabled"
216			return
217		fi
218	fi
219
220	$TEST_PATH/memcg_process $2 -s $3 &
221	pid=$!
222	sleep 1
223	echo $pid > tasks
224
225	kill -s USR1 $pid 2> /dev/null
226	sleep 1
227
228	ps -p $pid > /dev/null 2> /dev/null
229	if [ $? -ne 0 ]; then
230		wait $pid
231		if [ $? -eq 1 ]; then
232			result $FAIL "process $pid is killed by error"
233		else
234			result $PASS "process $pid is killed"
235		fi
236	else
237		kill -s INT $pid 2> /dev/null
238		result $FAIL "process $pid is not killed"
239	fi
240}
241
242# Test limit_in_bytes will be aligned to PAGESIZE
243# $1 - user input value
244# $2 - expected value
245# $3 - use mem+swap limitation
246test_limit_in_bytes()
247{
248	echo $1 > memory.limit_in_bytes
249	if [ $3 -eq 1 ]; then
250		if [ -e memory.memsw.limit_in_bytes ]; then
251			echo $1 > memory.memsw.limit_in_bytes
252			limit=`cat memory.memsw.limit_in_bytes`
253		else
254			tst_resm TCONF "mem+swap is not enabled"
255			return
256		fi
257	else
258		limit=`cat memory.limit_in_bytes`
259	fi
260
261	if [ $limit -eq $2 ]; then
262		result $PASS "input=$1, limit_in_bytes=$limit"
263	else
264		result $FAIL "input=$1, limit_in_bytes=$limit"
265	fi
266}
267
268# Test memory controller doesn't charge hugepage
269# $1 - the value of /proc/sys/vm/nr_hugepages
270# $2 - the parameters of 'process', --mmap-file or --shm
271# $3 - the -s parameter of 'process', such as $HUGEPAGESIZE
272# $4 - 0: expected failure, 1: expected success
273test_hugepage()
274{
275	TMP_FILE=$TEST_PATH/tmp
276	nr_hugepages=`cat /proc/sys/vm/nr_hugepages`
277
278	mkdir /hugetlb
279	mount -t hugetlbfs none /hugetlb
280
281	echo $1 > /proc/sys/vm/nr_hugepages
282
283	$TEST_PATH/memcg_process $2 --hugepage -s $3 > $TMP_FILE 2>&1 &
284	sleep 1
285
286	kill -s USR1 $! 2> /dev/null
287	sleep 1
288
289	check_mem_stat "rss" 0
290
291	echo "TMP_FILE:"
292	cat $TMP_FILE
293
294	if [ $4 -eq 0 ]; then
295		test -s $TMP_FILE
296		if [ $? -eq 0 ]; then
297			result $PASS "allocate hugepage failed as expected"
298		else
299			kill -s USR1 $! 2> /dev/null
300			kill -s INT $! 2> /dev/null
301			result $FAIL "allocate hugepage shoud fail"
302		fi
303	else
304		test ! -s $TMP_FILE
305		if [ $? -eq 0 ]; then
306			kill -s USR1 $! 2> /dev/null
307			kill -s INT $! 2> /dev/null
308			result $PASS "allocate hugepage succeeded"
309		else
310			result $FAIL "allocate hugepage failed"
311		fi
312	fi
313
314	sleep 1
315	rm -rf $TMP_FILE
316	umount /hugetlb
317	rmdir /hugetlb
318	echo $nr_hugepages > /proc/sys/vm/nr_hugepages
319}
320
321# Test the memory charge won't move to subgroup
322# $1 - memory.limit_in_bytes in parent group
323# $2 - memory.limit_in_bytes in sub group
324test_subgroup()
325{
326	mkdir subgroup
327	echo $1 > memory.limit_in_bytes
328	echo $2 > subgroup/memory.limit_in_bytes
329
330	echo "Running $TEST_PATH/memcg_process --mmap-anon -s $PAGESIZE"
331	$TEST_PATH/memcg_process --mmap-anon -s $PAGESIZE &
332	sleep 1
333
334	warmup $!
335	if [ $? -ne 0 ]; then
336		return
337	fi
338
339	echo $! > tasks
340	kill -s USR1 $! 2> /dev/null
341	sleep 1
342	check_mem_stat "rss" $PAGESIZE
343
344	cd subgroup
345	echo $! > tasks
346	check_mem_stat "rss" 0
347
348	# cleanup
349	cd ..
350	echo $! > tasks
351	kill -s INT $! 2> /dev/null
352	sleep 1
353	rmdir subgroup
354}
355
356# Run test cases which test memory.move_charge_at_immigrate
357# $1 - the parameters of 'process', such as --shm
358# $2 - the -s parameter of 'process', such as 4096
359# $3 - some positive value, such as 1
360# $4 - the expected size
361# $5 - the expected size
362test_move_charge()
363{
364	mkdir subgroup_a
365
366	$TEST_PATH/memcg_process $1 -s $2 &
367	sleep 1
368	warmup $!
369	if [ $? -ne 0 ]; then
370		rmdir subgroup_a
371		return
372	fi
373
374	echo $! > subgroup_a/tasks
375	kill -s USR1 $!
376	sleep 1
377
378	mkdir subgroup_b
379	echo $3 > subgroup_b/memory.move_charge_at_immigrate
380	echo $! > subgroup_b/tasks
381
382	cd subgroup_b
383	check_mem_stat memory.usage_in_bytes $4
384	cd ../subgroup_a
385	check_mem_stat memory.usage_in_bytes $5
386
387	cd ..
388	echo $! > tasks
389	kill -s USR1 $!
390	kill -s INT $!
391	sleep 1
392	rmdir subgroup_a subgroup_b
393}
394
395cleanup()
396{
397	killall -9 memcg_process 2>/dev/null
398	if [ -e /dev/memcg ]; then
399		umount /dev/memcg 2>/dev/null
400		rmdir /dev/memcg 2>/dev/null
401	fi
402}
403
404do_mount()
405{
406	cleanup
407
408	mkdir /dev/memcg 2> /dev/null
409	mount -t cgroup -omemory memcg /dev/memcg
410}
411