1#!/bin/sh 2# SPDX-License-Identifier: GPL-2.0-or-later 3# Copyright (c) 2015 SUSE 4# Author: Cedric Hnyda <chnyda@suse.com> 5# Usage 6# ./pids.sh caseno max 7 8TST_CLEANUP=cleanup 9TST_SETUP=setup 10TST_TESTFUNC=do_test 11TST_POS_ARGS=3 12TST_USAGE=usage 13TST_NEEDS_ROOT=1 14TST_NEEDS_CMDS="killall" 15 16. tst_test.sh 17 18caseno=$1 19max=$2 20subcgroup_num=$3 21mounted=1 22 23usage() 24{ 25 cat << EOF 26usage: $0 caseno max_processes 27 28caseno - testcase number from interval 1-9 29max_processes - maximal number of processes to attach 30 (not applicable to testcase 5) 31subcgroup_num - number of subgroups created in group 32 (only applicable to testcase 7) 33OPTIONS 34EOF 35} 36 37cleanup() 38{ 39 killall -9 pids_task2 >/dev/null 2>&1 40 41 tst_res TINFO "removing created directories" 42 rmdir $testpath 43 if [ "$mounted" -ne "1" ]; then 44 tst_res TINFO "Umounting pids" 45 umount $mount_point 46 rmdir $mount_point 47 fi 48} 49 50setup_cgroupv2() 51{ 52 mount_point=$(grep -w cgroup2 /proc/mounts | cut -f 2 | cut -d " " -f2) 53 if ! grep -q pids "$mount_point"/cgroup.controllers; then 54 tst_res TINFO "pids not supported on cgroup v2." 55 return 56 fi 57 58 testpath="$mount_point/ltp_pids_$caseno" 59 ROD mkdir -p "$testpath" 60 task_list="cgroup.procs" 61 cgroup_v="v2" 62} 63 64setup_cgroupv1() 65{ 66 exist=`grep -w pids /proc/cgroups | cut -f1`; 67 if [ "$exist" = "" ]; then 68 tst_brk TCONF NULL "pids not supported" 69 fi 70 71 mount_point=`grep -w pids /proc/mounts | cut -f 2 | cut -d " " -f2` 72 73 if [ "$mount_point" = "" ]; then 74 mounted=0 75 mount_point=/dev/cgroup 76 fi 77 78 testpath=$mount_point/ltp_pids_$caseno 79 80 if [ "$mounted" -eq "0" ]; then 81 ROD mkdir -p $mount_point 82 ROD mount -t cgroup -o pids none $mount_point 83 fi 84 ROD mkdir -p $testpath 85 task_list="tasks" 86 cgroup_v="v1" 87} 88 89setup() 90{ 91 # If cgroup2 is mounted already, then let's 92 # try to start with cgroup v2. 93 if grep -q cgroup2 /proc/mounts; then 94 setup_cgroupv2 95 fi 96 if [ -z "$cgroup_v" ]; then 97 setup_cgroupv1 98 fi 99 100 tst_res TINFO "test starts with cgroup $cgroup_v" 101} 102 103start_pids_tasks2() 104{ 105 start_pids_tasks2_path $testpath $1 106} 107 108start_pids_tasks2_path() 109{ 110 path=$1 111 nb=$2 112 for i in `seq 1 $nb`; do 113 pids_task2 & 114 echo $! > "$path/$task_list" 115 done 116 117 if [ $(wc -l < "$path/$task_list") -ne "$nb" ]; then 118 tst_brk TBROK "failed to attach process" 119 fi 120} 121 122stop_pids_tasks() 123{ 124 stop_pids_tasks_path $testpath 125} 126 127stop_pids_tasks_path() 128{ 129 local i 130 path=$1 131 132 for i in $(cat "$path/$task_list"); do 133 ROD kill -9 $i 134 wait $i 135 done 136} 137 138case1() 139{ 140 start_pids_tasks2 $max 141 142 # should return 0 because there is no limit 143 pids_task1 "$testpath/$task_list" 144 ret=$? 145 146 if [ "$ret" -eq "2" ]; then 147 tst_res TFAIL "fork failed unexpectedly" 148 elif [ "$ret" -eq "0" ]; then 149 tst_res TPASS "fork didn't fail" 150 else 151 tst_res TBROK "pids_task1 failed" 152 fi 153 154 stop_pids_tasks 155} 156 157case2() 158{ 159 tmp=$((max - 1)) 160 tst_res TINFO "limit the number of pid to $max" 161 ROD echo $max \> $testpath/pids.max 162 163 start_pids_tasks2 $tmp 164 165 # should return 2 because the limit of pids is reached 166 pids_task1 "$testpath/$task_list" 167 ret=$? 168 169 if [ "$ret" -eq "2" ]; then 170 tst_res TPASS "fork failed as expected" 171 elif [ "$ret" -eq "0" ]; then 172 tst_res TFAIL "fork didn't fail despite the limit" 173 else 174 tst_res TBROK "pids_task1 failed" 175 fi 176 177 stop_pids_tasks 178} 179 180case3() 181{ 182 lim=$((max + 2)) 183 tst_res TINFO "limit the number of avalaible pid to $lim" 184 ROD echo $lim \> $testpath/pids.max 185 186 start_pids_tasks2 $max 187 188 pids_task1 "$testpath/$task_list" 189 ret=$? 190 191 if [ "$ret" -eq "2" ]; then 192 tst_res TFAIL "fork failed unexpectedly" 193 elif [ "$ret" -eq "0" ]; then 194 tst_res TPASS "fork worked as expected" 195 else 196 tst_res TBROK "pids_task1 failed" 197 fi 198 199 stop_pids_tasks 200} 201 202case4() 203{ 204 tst_res TINFO "limit the number of avalaible pid to 0" 205 ROD echo 0 \> $testpath/pids.max 206 207 start_pids_tasks2 $max 208 209 tst_res TPASS "all process were attached" 210 211 stop_pids_tasks 212} 213 214case5() 215{ 216 tst_res TINFO "try to limit the number of avalaible pid to -1" 217 echo -1 > $testpath/pids.max 218 219 if [ "$?" -eq "0" ]; then 220 tst_res TFAIL "managed to set the limit to -1" 221 else 222 tst_res TPASS "didn't manage to set the limit to -1" 223 fi 224} 225 226case6() 227{ 228 tst_res TINFO "set a limit that is smaller than current number of pids" 229 start_pids_tasks2 $max 230 231 lim=$((max - 1)) 232 ROD echo $lim \> $testpath/pids.max 233 234 pids_task1 "$testpath/$task_list" 235 ret=$? 236 237 if [ "$ret" -eq "2" ]; then 238 tst_res TPASS "fork failed as expected" 239 elif [ "$ret" -eq "0" ]; then 240 tst_res TFAIL "fork didn't fail despite the limit" 241 else 242 tst_res TBROK "pids_task1 failed" 243 fi 244 245 stop_pids_tasks 246} 247 248case7() 249{ 250 tst_res TINFO "the number of all child cgroup tasks larger than its parent limit" 251 252 lim=$((max / subcgroup_num)) 253 if [ "$((lim * subcgroup_num))" -ne "$max" ]; then 254 tst_res TWARN "input max value must be a multiplier of $subcgroup_num" 255 return 256 fi 257 258 ROD echo $max \> $testpath/pids.max 259 260 for i in `seq 1 $subcgroup_num`; do 261 mkdir $testpath/child$i 262 start_pids_tasks2_path $testpath/child$i $lim 263 done 264 265 pids_task1 "$testpath/$task_list" 266 ret=$? 267 268 if [ "$ret" -eq "2" ]; then 269 tst_res TPASS "parent cgroup fork failed as expected" 270 elif [ "$ret" -eq "0" ]; then 271 tst_res TFAIL "parent cgroup fork didn't fail despite the limit" 272 else 273 tst_res TBROK "parent cgroup pids_task1 failed" 274 fi 275 276 for i in `seq 1 $subcgroup_num`; do 277 pids_task1 "$testpath/child$i/$task_list" 278 ret=$? 279 280 if [ "$ret" -eq "2" ]; then 281 tst_res TPASS "child$i cgroup fork failed as expected" 282 elif [ "$ret" -eq "0" ]; then 283 tst_res TFAIL "child$i cgroup fork didn't fail despite the limit" 284 else 285 tst_res TBROK "child$i cgroup pids_task1 failed" 286 fi 287 done 288 289 for i in `seq 1 $subcgroup_num`; do 290 stop_pids_tasks_path $testpath/child$i 291 rmdir $testpath/child$i 292 done 293 294 stop_pids_tasks 295} 296 297case8() 298{ 299 tst_res TINFO "set child cgroup limit smaller than its parent limit" 300 ROD echo $max \> $testpath/pids.max 301 if [ "$cgroup_v" = "v2" ]; then 302 ROD echo +pids \> "$testpath"/cgroup.subtree_control 303 fi 304 mkdir $testpath/child 305 306 lim=$((max - 1)) 307 ROD echo $lim \> $testpath/child/pids.max 308 tmp=$((max - 2)) 309 start_pids_tasks2_path $testpath/child $tmp 310 311 pids_task1 "$testpath/child/$task_list" 312 ret=$? 313 314 if [ "$ret" -eq "2" ]; then 315 tst_res TPASS "fork failed as expected" 316 elif [ "$ret" -eq "0" ]; then 317 tst_res TFAIL "fork didn't fail despite the limit" 318 else 319 tst_res TBROK "pids_task1 failed" 320 fi 321 322 stop_pids_tasks_path $testpath/child 323 rmdir $testpath/child 324} 325 326case9() 327{ 328 tst_res TINFO "migrate cgroup" 329 lim=$((max - 1)) 330 331 if [ "$cgroup_v" = "v2" ]; then 332 ROD echo +pids \> "$testpath"/cgroup.subtree_control 333 fi 334 for i in 1 2; do 335 mkdir $testpath/child$i 336 ROD echo $max \> $testpath/child$i/pids.max 337 start_pids_tasks2_path $testpath/child$i $lim 338 done 339 340 pid=`head -n 1 "$testpath/child1/$task_list"`; 341 ROD echo $pid \> "$testpath/child2/$task_list" 342 343 if grep -q "$pid" "$testpath/child2/$task_list"; then 344 tst_res TPASS "migrate pid $pid from cgroup1 to cgroup2 as expected" 345 else 346 tst_res TPASS "migrate pid $pid from cgroup1 to cgroup2 failed" 347 fi 348 349 if [ $(cat "$testpath/child1/pids.current") -eq $((lim - 1)) ]; then 350 tst_res TPASS "migrate child1 cgroup as expected" 351 else 352 tst_res TFAIL "migrate child1 cgroup failed" 353 fi 354 355 if [ $(cat "$testpath/child2/pids.current") -eq $((lim + 1)) ]; then 356 tst_res TPASS "migrate child2 cgroup as expected" 357 else 358 tst_res TFAIL "migrate child2 cgroup failed" 359 fi 360 361 pids_task1 "$testpath/child1/$task_list" 362 ret=$? 363 364 if [ "$ret" -eq "2" ]; then 365 tst_res TFAIL "child1 fork failed unexpectedly" 366 elif [ "$ret" -eq "0" ]; then 367 tst_res TPASS "child1 fork worked as expected" 368 else 369 tst_res TBROK "child1 pids_task1 failed" 370 fi 371 372 pids_task1 "$testpath/child2/$task_list" 373 ret=$? 374 375 if [ "$ret" -eq "2" ]; then 376 tst_res TPASS "child2 fork failed as expected" 377 elif [ "$ret" -eq "0" ]; then 378 tst_res TFAIL "child2 fork didn't fail despite the limit" 379 else 380 tst_res TBROK "child2 pids_task1 failed" 381 fi 382 383 for i in 1 2; do 384 stop_pids_tasks_path $testpath/child$i 385 rmdir $testpath/child$i 386 done 387 stop_pids_tasks 388} 389 390do_test() 391{ 392 tst_res TINFO "Running testcase $caseno with $max processes" 393 case$caseno 394} 395 396tst_run 397