2 # SPDX-License-Identifier: GPL-2.0
6 if [[ $
(id
-u) -ne 0 ]]; then
7 echo "This test must be run as root. Skipping..."
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
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
27 if [[ $cgroup2 ]]; then
28 mount
-t cgroup2 none
$cgroup_path
30 mount
-t cgroup memory
,hugetlb
$cgroup_path
34 if [[ $cgroup2 ]]; then
35 echo "+hugetlb" >/dev
/cgroup
/memory
/cgroup.subtree_control
39 if [[ $cgroup2 ]]; then
40 echo $$
>$cgroup_path/cgroup.procs
42 echo $$
>$cgroup_path/tasks
45 if [[ -e /mnt
/huge
]]; then
47 umount
/mnt
/huge ||
echo error
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
63 function expect_equal
() {
68 if [[ "$expected" != "$actual" ]]; then
69 echo "expected ($expected) != actual ($actual): $3"
75 function get_machine_hugepage_size
() {
76 hpz
=$
(grep -i hugepagesize
/proc
/meminfo
)
82 MB
=$
(get_machine_hugepage_size
)
84 function setup_cgroup
() {
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
() {
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.
117 function wait_for_hugetlb_memory_to_get_reserved
() {
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.
130 function wait_for_hugetlb_memory_to_get_written
() {
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.
143 function write_hugetlbfs_and_get_usage
() {
151 local expect_failure
="$8"
154 # Function return values.
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)
168 echo hugetlb_usage
="$hugetlb_before"
169 echo reserved_usage
="$reserved_before"
170 echo expect_failure is
"$expect_failure"
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
=$?
183 until grep -q -i "DONE" $output; do
184 echo waiting
for DONE signal.
185 if ! ps
$write_pid > /dev
/null
187 echo "FAIL: The write died"
194 echo ================= write_hugetlb_memory.sh output is
:
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"
203 # This case doesn't produce visible effects, but we still have
204 # to wait for the async process to start and execute...
208 echo write_result is
$write_result
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"
220 if [[ "$write_result" == 1 ]]; then
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
232 local hugetlb_after
=$
(cat $hugetlb_usage)
233 local reserved_after
=$
(cat $reserved_usage)
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
() {
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
253 if [[ -e /mnt
/huge
]]; then
260 function run_test
() {
261 local size
=$
(($1 * ${MB} * 1024 * 1024))
264 local cgroup_limit
=$
(($4 * ${MB} * 1024 * 1024))
265 local reservation_limit
=$
(($5 * ${MB} * 1024 * 1024))
266 local nr_hugepages
="$6"
269 local expect_failure
="$9"
270 local reserve
="${10}"
272 # Function return values.
274 reserved_difference
=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"
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" \
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
() {
305 local cgroup_limit1
="$4"
306 local reservation_limit1
="$5"
311 local cgroup_limit2
="$9"
312 local reservation_limit2
="${10}"
314 local nr_hugepages
="${11}"
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
326 hugetlb_difference2
=0
327 reserved_difference2
=0
328 reservation_failed2
=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"
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_test
1/hugetlb.
${MB}MB.
$fault_usage_file
350 local cgroup1_reservation_usage
=$cgroup_path/hugetlb_cgroup_test
1/hugetlb.
${MB}MB.
$reservation_usage_file
351 local cgroup2_hugetlb_usage
=$cgroup_path/hugetlb_cgroup_test
2/hugetlb.
${MB}MB.
$fault_usage_file
352 local cgroup2_reservation_usage
=$cgroup_path/hugetlb_cgroup_test
2/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"
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
402 # Skip populated shmem tests. Doesn't seem to be supported.
403 if [[ "$method" == 2"" ]] && [[ "$populate" == "-o" ]]; then
407 if [[ "$method" == 2"" ]] && [[ "$reserve" == "-n" ]]; then
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."
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."
434 expect_equal
"0" "$reserved_difference" \
435 "Reserved memory not charged to reservation usage."
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."
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" \
471 expect_equal
"1" "$reservation_failed" "Reservation succeeded."
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."
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."
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."
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."
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."