WIP FPC-III support
[linux/fpc-iii.git] / tools / testing / selftests / vm / charge_reserved_hugetlb.sh
blob18d33684faade0a3f6bcb489b190fe9caf37a129
1 #!/bin/sh
2 # SPDX-License-Identifier: GPL-2.0
4 set -e
6 if [[ $(id -u) -ne 0 ]]; then
7 echo "This test must be run as root. Skipping..."
8 exit 0
9 fi
11 fault_limit_file=limit_in_bytes
12 reservation_limit_file=rsvd.limit_in_bytes
13 fault_usage_file=usage_in_bytes
14 reservation_usage_file=rsvd.usage_in_bytes
16 if [[ "$1" == "-cgroup-v2" ]]; then
17 cgroup2=1
18 fault_limit_file=max
19 reservation_limit_file=rsvd.max
20 fault_usage_file=current
21 reservation_usage_file=rsvd.current
24 cgroup_path=/dev/cgroup/memory
25 if [[ ! -e $cgroup_path ]]; then
26 mkdir -p $cgroup_path
27 if [[ $cgroup2 ]]; then
28 mount -t cgroup2 none $cgroup_path
29 else
30 mount -t cgroup memory,hugetlb $cgroup_path
34 if [[ $cgroup2 ]]; then
35 echo "+hugetlb" >/dev/cgroup/memory/cgroup.subtree_control
38 function cleanup() {
39 if [[ $cgroup2 ]]; then
40 echo $$ >$cgroup_path/cgroup.procs
41 else
42 echo $$ >$cgroup_path/tasks
45 if [[ -e /mnt/huge ]]; then
46 rm -rf /mnt/huge/*
47 umount /mnt/huge || echo error
48 rmdir /mnt/huge
50 if [[ -e $cgroup_path/hugetlb_cgroup_test ]]; then
51 rmdir $cgroup_path/hugetlb_cgroup_test
53 if [[ -e $cgroup_path/hugetlb_cgroup_test1 ]]; then
54 rmdir $cgroup_path/hugetlb_cgroup_test1
56 if [[ -e $cgroup_path/hugetlb_cgroup_test2 ]]; then
57 rmdir $cgroup_path/hugetlb_cgroup_test2
59 echo 0 >/proc/sys/vm/nr_hugepages
60 echo CLEANUP DONE
63 function expect_equal() {
64 local expected="$1"
65 local actual="$2"
66 local error="$3"
68 if [[ "$expected" != "$actual" ]]; then
69 echo "expected ($expected) != actual ($actual): $3"
70 cleanup
71 exit 1
75 function get_machine_hugepage_size() {
76 hpz=$(grep -i hugepagesize /proc/meminfo)
77 kb=${hpz:14:-3}
78 mb=$(($kb / 1024))
79 echo $mb
82 MB=$(get_machine_hugepage_size)
84 function setup_cgroup() {
85 local name="$1"
86 local cgroup_limit="$2"
87 local reservation_limit="$3"
89 mkdir $cgroup_path/$name
91 echo writing cgroup limit: "$cgroup_limit"
92 echo "$cgroup_limit" >$cgroup_path/$name/hugetlb.${MB}MB.$fault_limit_file
94 echo writing reseravation limit: "$reservation_limit"
95 echo "$reservation_limit" > \
96 $cgroup_path/$name/hugetlb.${MB}MB.$reservation_limit_file
98 if [ -e "$cgroup_path/$name/cpuset.cpus" ]; then
99 echo 0 >$cgroup_path/$name/cpuset.cpus
101 if [ -e "$cgroup_path/$name/cpuset.mems" ]; then
102 echo 0 >$cgroup_path/$name/cpuset.mems
106 function wait_for_hugetlb_memory_to_get_depleted() {
107 local cgroup="$1"
108 local path="/dev/cgroup/memory/$cgroup/hugetlb.${MB}MB.$reservation_usage_file"
109 # Wait for hugetlbfs memory to get depleted.
110 while [ $(cat $path) != 0 ]; do
111 echo Waiting for hugetlb memory to get depleted.
112 cat $path
113 sleep 0.5
114 done
117 function wait_for_hugetlb_memory_to_get_reserved() {
118 local cgroup="$1"
119 local size="$2"
121 local path="/dev/cgroup/memory/$cgroup/hugetlb.${MB}MB.$reservation_usage_file"
122 # Wait for hugetlbfs memory to get written.
123 while [ $(cat $path) != $size ]; do
124 echo Waiting for hugetlb memory reservation to reach size $size.
125 cat $path
126 sleep 0.5
127 done
130 function wait_for_hugetlb_memory_to_get_written() {
131 local cgroup="$1"
132 local size="$2"
134 local path="/dev/cgroup/memory/$cgroup/hugetlb.${MB}MB.$fault_usage_file"
135 # Wait for hugetlbfs memory to get written.
136 while [ $(cat $path) != $size ]; do
137 echo Waiting for hugetlb memory to reach size $size.
138 cat $path
139 sleep 0.5
140 done
143 function write_hugetlbfs_and_get_usage() {
144 local cgroup="$1"
145 local size="$2"
146 local populate="$3"
147 local write="$4"
148 local path="$5"
149 local method="$6"
150 local private="$7"
151 local expect_failure="$8"
152 local reserve="$9"
154 # Function return values.
155 reservation_failed=0
156 oom_killed=0
157 hugetlb_difference=0
158 reserved_difference=0
160 local hugetlb_usage=$cgroup_path/$cgroup/hugetlb.${MB}MB.$fault_usage_file
161 local reserved_usage=$cgroup_path/$cgroup/hugetlb.${MB}MB.$reservation_usage_file
163 local hugetlb_before=$(cat $hugetlb_usage)
164 local reserved_before=$(cat $reserved_usage)
166 echo
167 echo Starting:
168 echo hugetlb_usage="$hugetlb_before"
169 echo reserved_usage="$reserved_before"
170 echo expect_failure is "$expect_failure"
172 output=$(mktemp)
173 set +e
174 if [[ "$method" == "1" ]] || [[ "$method" == 2 ]] ||
175 [[ "$private" == "-r" ]] && [[ "$expect_failure" != 1 ]]; then
177 bash write_hugetlb_memory.sh "$size" "$populate" "$write" \
178 "$cgroup" "$path" "$method" "$private" "-l" "$reserve" 2>&1 | tee $output &
180 local write_result=$?
181 local write_pid=$!
183 until grep -q -i "DONE" $output; do
184 echo waiting for DONE signal.
185 if ! ps $write_pid > /dev/null
186 then
187 echo "FAIL: The write died"
188 cleanup
189 exit 1
191 sleep 0.5
192 done
194 echo ================= write_hugetlb_memory.sh output is:
195 cat $output
196 echo ================= end output.
198 if [[ "$populate" == "-o" ]] || [[ "$write" == "-w" ]]; then
199 wait_for_hugetlb_memory_to_get_written "$cgroup" "$size"
200 elif [[ "$reserve" != "-n" ]]; then
201 wait_for_hugetlb_memory_to_get_reserved "$cgroup" "$size"
202 else
203 # This case doesn't produce visible effects, but we still have
204 # to wait for the async process to start and execute...
205 sleep 0.5
208 echo write_result is $write_result
209 else
210 bash write_hugetlb_memory.sh "$size" "$populate" "$write" \
211 "$cgroup" "$path" "$method" "$private" "$reserve"
212 local write_result=$?
214 if [[ "$reserve" != "-n" ]]; then
215 wait_for_hugetlb_memory_to_get_reserved "$cgroup" "$size"
218 set -e
220 if [[ "$write_result" == 1 ]]; then
221 reservation_failed=1
224 # On linus/master, the above process gets SIGBUS'd on oomkill, with
225 # return code 135. On earlier kernels, it gets actual oomkill, with return
226 # code 137, so just check for both conditions in case we're testing
227 # against an earlier kernel.
228 if [[ "$write_result" == 135 ]] || [[ "$write_result" == 137 ]]; then
229 oom_killed=1
232 local hugetlb_after=$(cat $hugetlb_usage)
233 local reserved_after=$(cat $reserved_usage)
235 echo After write:
236 echo hugetlb_usage="$hugetlb_after"
237 echo reserved_usage="$reserved_after"
239 hugetlb_difference=$(($hugetlb_after - $hugetlb_before))
240 reserved_difference=$(($reserved_after - $reserved_before))
243 function cleanup_hugetlb_memory() {
244 set +e
245 local cgroup="$1"
246 if [[ "$(pgrep -f write_to_hugetlbfs)" != "" ]]; then
247 echo killing write_to_hugetlbfs
248 killall -2 write_to_hugetlbfs
249 wait_for_hugetlb_memory_to_get_depleted $cgroup
251 set -e
253 if [[ -e /mnt/huge ]]; then
254 rm -rf /mnt/huge/*
255 umount /mnt/huge
256 rmdir /mnt/huge
260 function run_test() {
261 local size=$(($1 * ${MB} * 1024 * 1024))
262 local populate="$2"
263 local write="$3"
264 local cgroup_limit=$(($4 * ${MB} * 1024 * 1024))
265 local reservation_limit=$(($5 * ${MB} * 1024 * 1024))
266 local nr_hugepages="$6"
267 local method="$7"
268 local private="$8"
269 local expect_failure="$9"
270 local reserve="${10}"
272 # Function return values.
273 hugetlb_difference=0
274 reserved_difference=0
275 reservation_failed=0
276 oom_killed=0
278 echo nr hugepages = "$nr_hugepages"
279 echo "$nr_hugepages" >/proc/sys/vm/nr_hugepages
281 setup_cgroup "hugetlb_cgroup_test" "$cgroup_limit" "$reservation_limit"
283 mkdir -p /mnt/huge
284 mount -t hugetlbfs -o pagesize=${MB}M,size=256M none /mnt/huge
286 write_hugetlbfs_and_get_usage "hugetlb_cgroup_test" "$size" "$populate" \
287 "$write" "/mnt/huge/test" "$method" "$private" "$expect_failure" \
288 "$reserve"
290 cleanup_hugetlb_memory "hugetlb_cgroup_test"
292 local final_hugetlb=$(cat $cgroup_path/hugetlb_cgroup_test/hugetlb.${MB}MB.$fault_usage_file)
293 local final_reservation=$(cat $cgroup_path/hugetlb_cgroup_test/hugetlb.${MB}MB.$reservation_usage_file)
295 echo $hugetlb_difference
296 echo $reserved_difference
297 expect_equal "0" "$final_hugetlb" "final hugetlb is not zero"
298 expect_equal "0" "$final_reservation" "final reservation is not zero"
301 function run_multiple_cgroup_test() {
302 local size1="$1"
303 local populate1="$2"
304 local write1="$3"
305 local cgroup_limit1="$4"
306 local reservation_limit1="$5"
308 local size2="$6"
309 local populate2="$7"
310 local write2="$8"
311 local cgroup_limit2="$9"
312 local reservation_limit2="${10}"
314 local nr_hugepages="${11}"
315 local method="${12}"
316 local private="${13}"
317 local expect_failure="${14}"
318 local reserve="${15}"
320 # Function return values.
321 hugetlb_difference1=0
322 reserved_difference1=0
323 reservation_failed1=0
324 oom_killed1=0
326 hugetlb_difference2=0
327 reserved_difference2=0
328 reservation_failed2=0
329 oom_killed2=0
331 echo nr hugepages = "$nr_hugepages"
332 echo "$nr_hugepages" >/proc/sys/vm/nr_hugepages
334 setup_cgroup "hugetlb_cgroup_test1" "$cgroup_limit1" "$reservation_limit1"
335 setup_cgroup "hugetlb_cgroup_test2" "$cgroup_limit2" "$reservation_limit2"
337 mkdir -p /mnt/huge
338 mount -t hugetlbfs -o pagesize=${MB}M,size=256M none /mnt/huge
340 write_hugetlbfs_and_get_usage "hugetlb_cgroup_test1" "$size1" \
341 "$populate1" "$write1" "/mnt/huge/test1" "$method" "$private" \
342 "$expect_failure" "$reserve"
344 hugetlb_difference1=$hugetlb_difference
345 reserved_difference1=$reserved_difference
346 reservation_failed1=$reservation_failed
347 oom_killed1=$oom_killed
349 local cgroup1_hugetlb_usage=$cgroup_path/hugetlb_cgroup_test1/hugetlb.${MB}MB.$fault_usage_file
350 local cgroup1_reservation_usage=$cgroup_path/hugetlb_cgroup_test1/hugetlb.${MB}MB.$reservation_usage_file
351 local cgroup2_hugetlb_usage=$cgroup_path/hugetlb_cgroup_test2/hugetlb.${MB}MB.$fault_usage_file
352 local cgroup2_reservation_usage=$cgroup_path/hugetlb_cgroup_test2/hugetlb.${MB}MB.$reservation_usage_file
354 local usage_before_second_write=$(cat $cgroup1_hugetlb_usage)
355 local reservation_usage_before_second_write=$(cat $cgroup1_reservation_usage)
357 write_hugetlbfs_and_get_usage "hugetlb_cgroup_test2" "$size2" \
358 "$populate2" "$write2" "/mnt/huge/test2" "$method" "$private" \
359 "$expect_failure" "$reserve"
361 hugetlb_difference2=$hugetlb_difference
362 reserved_difference2=$reserved_difference
363 reservation_failed2=$reservation_failed
364 oom_killed2=$oom_killed
366 expect_equal "$usage_before_second_write" \
367 "$(cat $cgroup1_hugetlb_usage)" "Usage changed."
368 expect_equal "$reservation_usage_before_second_write" \
369 "$(cat $cgroup1_reservation_usage)" "Reservation usage changed."
371 cleanup_hugetlb_memory
373 local final_hugetlb=$(cat $cgroup1_hugetlb_usage)
374 local final_reservation=$(cat $cgroup1_reservation_usage)
376 expect_equal "0" "$final_hugetlb" \
377 "hugetlbt_cgroup_test1 final hugetlb is not zero"
378 expect_equal "0" "$final_reservation" \
379 "hugetlbt_cgroup_test1 final reservation is not zero"
381 local final_hugetlb=$(cat $cgroup2_hugetlb_usage)
382 local final_reservation=$(cat $cgroup2_reservation_usage)
384 expect_equal "0" "$final_hugetlb" \
385 "hugetlb_cgroup_test2 final hugetlb is not zero"
386 expect_equal "0" "$final_reservation" \
387 "hugetlb_cgroup_test2 final reservation is not zero"
390 cleanup
392 for populate in "" "-o"; do
393 for method in 0 1 2; do
394 for private in "" "-r"; do
395 for reserve in "" "-n"; do
397 # Skip mmap(MAP_HUGETLB | MAP_SHARED). Doesn't seem to be supported.
398 if [[ "$method" == 1 ]] && [[ "$private" == "" ]]; then
399 continue
402 # Skip populated shmem tests. Doesn't seem to be supported.
403 if [[ "$method" == 2"" ]] && [[ "$populate" == "-o" ]]; then
404 continue
407 if [[ "$method" == 2"" ]] && [[ "$reserve" == "-n" ]]; then
408 continue
411 cleanup
412 echo
413 echo
414 echo
415 echo Test normal case.
416 echo private=$private, populate=$populate, method=$method, reserve=$reserve
417 run_test 5 "$populate" "" 10 10 10 "$method" "$private" "0" "$reserve"
419 echo Memory charged to hugtlb=$hugetlb_difference
420 echo Memory charged to reservation=$reserved_difference
422 if [[ "$populate" == "-o" ]]; then
423 expect_equal "$((5 * $MB * 1024 * 1024))" "$hugetlb_difference" \
424 "Reserved memory charged to hugetlb cgroup."
425 else
426 expect_equal "0" "$hugetlb_difference" \
427 "Reserved memory charged to hugetlb cgroup."
430 if [[ "$reserve" != "-n" ]] || [[ "$populate" == "-o" ]]; then
431 expect_equal "$((5 * $MB * 1024 * 1024))" "$reserved_difference" \
432 "Reserved memory not charged to reservation usage."
433 else
434 expect_equal "0" "$reserved_difference" \
435 "Reserved memory not charged to reservation usage."
438 echo 'PASS'
440 cleanup
441 echo
442 echo
443 echo
444 echo Test normal case with write.
445 echo private=$private, populate=$populate, method=$method, reserve=$reserve
446 run_test 5 "$populate" '-w' 5 5 10 "$method" "$private" "0" "$reserve"
448 echo Memory charged to hugtlb=$hugetlb_difference
449 echo Memory charged to reservation=$reserved_difference
451 expect_equal "$((5 * $MB * 1024 * 1024))" "$hugetlb_difference" \
452 "Reserved memory charged to hugetlb cgroup."
454 expect_equal "$((5 * $MB * 1024 * 1024))" "$reserved_difference" \
455 "Reserved memory not charged to reservation usage."
457 echo 'PASS'
459 cleanup
460 continue
461 echo
462 echo
463 echo
464 echo Test more than reservation case.
465 echo private=$private, populate=$populate, method=$method, reserve=$reserve
467 if [ "$reserve" != "-n" ]; then
468 run_test "5" "$populate" '' "10" "2" "10" "$method" "$private" "1" \
469 "$reserve"
471 expect_equal "1" "$reservation_failed" "Reservation succeeded."
474 echo 'PASS'
476 cleanup
478 echo
479 echo
480 echo
481 echo Test more than cgroup limit case.
482 echo private=$private, populate=$populate, method=$method, reserve=$reserve
484 # Not sure if shm memory can be cleaned up when the process gets sigbus'd.
485 if [[ "$method" != 2 ]]; then
486 run_test 5 "$populate" "-w" 2 10 10 "$method" "$private" "1" "$reserve"
488 expect_equal "1" "$oom_killed" "Not oom killed."
490 echo 'PASS'
492 cleanup
494 echo
495 echo
496 echo
497 echo Test normal case, multiple cgroups.
498 echo private=$private, populate=$populate, method=$method, reserve=$reserve
499 run_multiple_cgroup_test "3" "$populate" "" "10" "10" "5" \
500 "$populate" "" "10" "10" "10" \
501 "$method" "$private" "0" "$reserve"
503 echo Memory charged to hugtlb1=$hugetlb_difference1
504 echo Memory charged to reservation1=$reserved_difference1
505 echo Memory charged to hugtlb2=$hugetlb_difference2
506 echo Memory charged to reservation2=$reserved_difference2
508 if [[ "$reserve" != "-n" ]] || [[ "$populate" == "-o" ]]; then
509 expect_equal "3" "$reserved_difference1" \
510 "Incorrect reservations charged to cgroup 1."
512 expect_equal "5" "$reserved_difference2" \
513 "Incorrect reservation charged to cgroup 2."
515 else
516 expect_equal "0" "$reserved_difference1" \
517 "Incorrect reservations charged to cgroup 1."
519 expect_equal "0" "$reserved_difference2" \
520 "Incorrect reservation charged to cgroup 2."
523 if [[ "$populate" == "-o" ]]; then
524 expect_equal "3" "$hugetlb_difference1" \
525 "Incorrect hugetlb charged to cgroup 1."
527 expect_equal "5" "$hugetlb_difference2" \
528 "Incorrect hugetlb charged to cgroup 2."
530 else
531 expect_equal "0" "$hugetlb_difference1" \
532 "Incorrect hugetlb charged to cgroup 1."
534 expect_equal "0" "$hugetlb_difference2" \
535 "Incorrect hugetlb charged to cgroup 2."
537 echo 'PASS'
539 cleanup
540 echo
541 echo
542 echo
543 echo Test normal case with write, multiple cgroups.
544 echo private=$private, populate=$populate, method=$method, reserve=$reserve
545 run_multiple_cgroup_test "3" "$populate" "-w" "10" "10" "5" \
546 "$populate" "-w" "10" "10" "10" \
547 "$method" "$private" "0" "$reserve"
549 echo Memory charged to hugtlb1=$hugetlb_difference1
550 echo Memory charged to reservation1=$reserved_difference1
551 echo Memory charged to hugtlb2=$hugetlb_difference2
552 echo Memory charged to reservation2=$reserved_difference2
554 expect_equal "3" "$hugetlb_difference1" \
555 "Incorrect hugetlb charged to cgroup 1."
557 expect_equal "3" "$reserved_difference1" \
558 "Incorrect reservation charged to cgroup 1."
560 expect_equal "5" "$hugetlb_difference2" \
561 "Incorrect hugetlb charged to cgroup 2."
563 expect_equal "5" "$reserved_difference2" \
564 "Incorrected reservation charged to cgroup 2."
565 echo 'PASS'
567 cleanup
569 done # reserve
570 done # private
571 done # populate
572 done # method
574 umount $cgroup_path
575 rmdir $cgroup_path