1#! /bin/sh 2# SPDX-License-Identifier: GPL-2.0-or-later 3# Copyright (c) 2009 FUJITSU LIMITED 4# Author: Li Zefan <[email protected]> 5# Added memcg enable/disable functionality: Rishikesh K Rajak <[email protected]> 6 7TST_ID="memcg_regression_test" 8TST_CLEANUP=cleanup 9TST_SETUP=setup 10TST_TESTFUNC=test_ 11TST_NEEDS_ROOT=1 12TST_NEEDS_CMDS="killall kill" 13TST_CNT=4 14 15#buffer can rotate and number of found bugs can actually go down 16#so clear the buffer to avoid this 17dmesg -c > /dev/null 18nr_bug=0 19nr_null=0 20nr_warning=0 21nr_lockdep=0 22 23# check_kernel_bug - check if some kind of kernel bug happened 24check_kernel_bug() 25{ 26 new_bug=`dmesg | grep -c "kernel BUG"` 27 new_null=`dmesg | grep -c "kernel NULL pointer dereference"` 28 new_warning=`dmesg | grep -c "^WARNING"` 29 new_lockdep=`dmesg | grep -c "possible recursive locking detected"` 30 31 # no kernel bug is detected 32 if [ $new_bug -eq $nr_bug -a $new_warning -eq $nr_warning -a \ 33 $new_null -eq $nr_null -a $new_lockdep -eq $nr_lockdep ]; then 34 return 1 35 fi 36 37 # some kernel bug is detected 38 if [ $new_bug -gt $nr_bug ]; then 39 tst_res TFAIL "kernel BUG was detected!" 40 fi 41 if [ $new_warning -gt $nr_warning ]; then 42 tst_res TFAIL "kernel WARNING was detected!" 43 fi 44 if [ $new_null -gt $nr_null ]; then 45 tst_res TWARN "kernel NULL pointer dereference!" 46 fi 47 if [ $new_lockdep -gt $nr_lockdep ]; then 48 tst_res TWARN "kernel lockdep warning was detected!" 49 fi 50 51 nr_bug=$new_bug 52 nr_null=$new_null 53 nr_warning=$new_warning 54 nr_lockdep=$new_lockdep 55 56 echo "check_kernel_bug found something!" 57 dmesg 58 return 0 59} 60 61setup() 62{ 63 cgroup_require "memory" 64 cgroup_version=$(cgroup_get_version "memory") 65 mount_point=$(cgroup_get_mountpoint "memory") 66 test_dir=$(cgroup_get_test_path "memory") 67 task_list=$(cgroup_get_task_list "memory") 68 if [ "$cgroup_version" = "2" ]; then 69 memory_limit="memory.max" 70 else 71 memory_limit="memory.limit_in_bytes" 72 fi 73 74 [ "$cgroup_version" = "2" ] && ROD echo "+memory" \> "$test_dir/cgroup.subtree_control" 75 76 tst_res TINFO "test starts with cgroup version $cgroup_version" 77} 78 79cleanup() 80{ 81 cleanup_testpath "$test_dir/0" 82 cgroup_cleanup 83} 84 85create_testpath() 86{ 87 local path="$1" 88 [ ! -e "$path" ] && ROD mkdir "$path" 89} 90 91cleanup_testpath() 92{ 93 local path="$1" 94 [ -e "$path" ] && ROD rmdir "$path" 95} 96 97#--------------------------------------------------------------------------- 98# Bug: The bug was, while forking mass processes, trigger memcgroup OOM, 99# then NULL pointer dereference may be hit. 100# Kernel: 2.6.25-rcX 101# Links: http://lkml.org/lkml/2008/4/14/38 102# Fix: commit e115f2d89253490fb2dbf304b627f8d908df26f1 103#--------------------------------------------------------------------------- 104test_1() 105{ 106 local test_path 107 test_path="$test_dir/0" 108 109 create_testpath "$test_path" 110 ROD echo 0 \> "$test_path/$memory_limit" 111 112 ./memcg_test_1 "$test_path/$task_list" 113 114 cleanup_testpath "$test_path" 115 116 check_kernel_bug 117 if [ $? -eq 1 ]; then 118 tst_res TPASS "no kernel bug was found" 119 fi 120} 121 122#--------------------------------------------------------------------------- 123# Bug: Shrink memory might never return, unless send signal to stop it. 124# Kernel: 2.6.29 125# Links: http://marc.info/?t=123199973900003&r=1&w=2 126# http://lkml.org/lkml/2009/2/3/72 127# Fix: 81d39c20f5ee2437d71709beb82597e2a38efbbc 128#--------------------------------------------------------------------------- 129test_2() 130{ 131 local test_path 132 133 # for cgroup2 writing to memory.max first checks the new limit against the 134 # current usage and will start killing processes if oom, therefore we do not 135 # expect EBUSY to be returned by the shrink operation. 136 if [ "$cgroup_version" = "2" ]; then 137 tst_res TCONF "Cgroup v2 found, skipping test" 138 return 139 fi 140 141 test_path="$test_dir/0" 142 143 ./memcg_test_2 & 144 pid1=$! 145 sleep 1 146 147 create_testpath "$test_path" 148 ROD echo $pid1 \> "$test_path"/tasks 149 150 # let pid1 'test_2' allocate memory 151 /bin/kill -SIGUSR1 $pid1 152 sleep 1 153 154 # shrink memory 155 echo 1 > "$test_path"/memory.limit_in_bytes 2>&1 & 156 pid2=$! 157 158 # check if 'echo' will exit and exit with failure 159 for tmp in $(seq 0 4); do 160 sleep 1 161 ps -p $! > /dev/null 162 if [ $? -ne 0 ]; then 163 wait $pid2 164 if [ $? -eq 0 ]; then 165 tst_res TFAIL "echo should return failure" 166 kill -9 $pid1 $pid2 > /dev/null 2>&1 167 wait $pid1 $pid2 168 cleanup_testpath "$test_path" 169 return 170 fi 171 break 172 fi 173 done 174 175 if [ $tmp -eq 5 ]; then 176 tst_res TFAIL "'echo' doesn't exit!" 177 else 178 tst_res TPASS "EBUSY was returned as expected" 179 fi 180 181 kill -9 $pid1 $pid2 > /dev/null 2>&1 182 wait $pid1 $pid2 > /dev/null 2>&1 183 cleanup_testpath "$test_path" 184} 185 186#--------------------------------------------------------------------------- 187# Bug: crash when rmdir a cgroup on IA64 188# Kernel: 2.6.29-rcX 189# Links: http://marc.info/?t=123235660300001&r=1&w=2 190# Fix: commit 299b4eaa302138426d5a9ecd954de1f565d76c94 191#--------------------------------------------------------------------------- 192test_3() 193{ 194 local test_path 195 test_path="$test_dir/0" 196 create_testpath "$test_path" 197 198 for pid in $(cat "$mount_point/$task_list"); do 199 echo $pid > "$test_path/$task_list" 2> /dev/null 200 done 201 202 for pid in $(cat "$test_path/$task_list"); do 203 echo $pid > "$mount_point/$task_list" 2> /dev/null 204 done 205 cleanup_testpath "$test_path" 206 207 check_kernel_bug 208 if [ $? -eq 1 ]; then 209 tst_res TPASS "no kernel bug was found" 210 fi 211} 212 213#--------------------------------------------------------------------------- 214# Bug: the memcg's refcnt handling at swapoff was wrong, causing crash 215# Kernel: 2.6.29-rcX 216# Links: http://marc.info/?t=123208656300004&r=1&w=2 217# Fix: commit 85d9fc89fb0f0703df6444f260187c088a8d59ff 218#--------------------------------------------------------------------------- 219test_4() 220{ 221 local test_path 222 test_path="$test_dir/0" 223 create_testpath "$test_path" 224 swaps=$(cut -F1 /proc/swaps | tail -n +2) 225 226 ./memcg_test_4.sh "$cgroup_version" "$mount_point" "$test_path" 227 228 check_kernel_bug 229 if [ $? -eq 1 ]; then 230 tst_res TPASS "no kernel bug was found" 231 fi 232 233 # test_4.sh might be killed by oom, so do clean up here 234 killall -9 memcg_test_4 2> /dev/null 235 killall -9 memcg_test_4.sh 2> /dev/null 236 237 # if test_4.sh gets killed, it won't clean cgroup it created 238 cleanup_testpath "$test_path" 239 240 for s in $swaps; do 241 swapon $s 242 done 243} 244 245. cgroup_lib.sh 246tst_run 247