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