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 (at] cn.fujitsu.com> ## 22 ## ## 23 ################################################################################ 24 25 if [ "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 30 fi 31 32 cd $LTPROOT/testcases/bin 33 34 TEST_PATH=$PWD 35 PAGESIZE=`./memcg_getpagesize` 36 HUGEPAGESIZE=`grep Hugepagesize /proc/meminfo | awk '{ print $2 }'` 37 [ -z $HUGEPAGESIZE ] && HUGEPAGESIZE=0 38 HUGEPAGESIZE=$(( $HUGEPAGESIZE * 1024 )) 39 PASS=0 40 FAIL=1 41 orig_memory_use_hierarchy="" 42 43 cur_id=0 44 failed=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 49 result() 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 65 check_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 82 warmup() 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 ? 110 test_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 ? 143 test_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 174 malloc_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 192 test_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 209 test_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 249 test_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 279 test_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 330 test_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 368 test_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 403 cleanup() 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 422 do_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