0001
0002
0003
0004
0005 ksft_skip=4
0006
0007 set -e
0008
0009 if [[ $(id -u) -ne 0 ]]; then
0010 echo "This test must be run as root. Skipping..."
0011 exit $ksft_skip
0012 fi
0013
0014 fault_limit_file=limit_in_bytes
0015 reservation_limit_file=rsvd.limit_in_bytes
0016 fault_usage_file=usage_in_bytes
0017 reservation_usage_file=rsvd.usage_in_bytes
0018
0019 if [[ "$1" == "-cgroup-v2" ]]; then
0020 cgroup2=1
0021 fault_limit_file=max
0022 reservation_limit_file=rsvd.max
0023 fault_usage_file=current
0024 reservation_usage_file=rsvd.current
0025 fi
0026
0027 if [[ $cgroup2 ]]; then
0028 cgroup_path=$(mount -t cgroup2 | head -1 | awk -e '{print $3}')
0029 if [[ -z "$cgroup_path" ]]; then
0030 cgroup_path=/dev/cgroup/memory
0031 mount -t cgroup2 none $cgroup_path
0032 do_umount=1
0033 fi
0034 echo "+hugetlb" >$cgroup_path/cgroup.subtree_control
0035 else
0036 cgroup_path=$(mount -t cgroup | grep ",hugetlb" | awk -e '{print $3}')
0037 if [[ -z "$cgroup_path" ]]; then
0038 cgroup_path=/dev/cgroup/memory
0039 mount -t cgroup memory,hugetlb $cgroup_path
0040 do_umount=1
0041 fi
0042 fi
0043 export cgroup_path
0044
0045 function cleanup() {
0046 if [[ $cgroup2 ]]; then
0047 echo $$ >$cgroup_path/cgroup.procs
0048 else
0049 echo $$ >$cgroup_path/tasks
0050 fi
0051
0052 if [[ -e /mnt/huge ]]; then
0053 rm -rf /mnt/huge/*
0054 umount /mnt/huge || echo error
0055 rmdir /mnt/huge
0056 fi
0057 if [[ -e $cgroup_path/hugetlb_cgroup_test ]]; then
0058 rmdir $cgroup_path/hugetlb_cgroup_test
0059 fi
0060 if [[ -e $cgroup_path/hugetlb_cgroup_test1 ]]; then
0061 rmdir $cgroup_path/hugetlb_cgroup_test1
0062 fi
0063 if [[ -e $cgroup_path/hugetlb_cgroup_test2 ]]; then
0064 rmdir $cgroup_path/hugetlb_cgroup_test2
0065 fi
0066 echo 0 >/proc/sys/vm/nr_hugepages
0067 echo CLEANUP DONE
0068 }
0069
0070 function expect_equal() {
0071 local expected="$1"
0072 local actual="$2"
0073 local error="$3"
0074
0075 if [[ "$expected" != "$actual" ]]; then
0076 echo "expected ($expected) != actual ($actual): $3"
0077 cleanup
0078 exit 1
0079 fi
0080 }
0081
0082 function get_machine_hugepage_size() {
0083 hpz=$(grep -i hugepagesize /proc/meminfo)
0084 kb=${hpz:14:-3}
0085 mb=$(($kb / 1024))
0086 echo $mb
0087 }
0088
0089 MB=$(get_machine_hugepage_size)
0090
0091 function setup_cgroup() {
0092 local name="$1"
0093 local cgroup_limit="$2"
0094 local reservation_limit="$3"
0095
0096 mkdir $cgroup_path/$name
0097
0098 echo writing cgroup limit: "$cgroup_limit"
0099 echo "$cgroup_limit" >$cgroup_path/$name/hugetlb.${MB}MB.$fault_limit_file
0100
0101 echo writing reseravation limit: "$reservation_limit"
0102 echo "$reservation_limit" > \
0103 $cgroup_path/$name/hugetlb.${MB}MB.$reservation_limit_file
0104
0105 if [ -e "$cgroup_path/$name/cpuset.cpus" ]; then
0106 echo 0 >$cgroup_path/$name/cpuset.cpus
0107 fi
0108 if [ -e "$cgroup_path/$name/cpuset.mems" ]; then
0109 echo 0 >$cgroup_path/$name/cpuset.mems
0110 fi
0111 }
0112
0113 function wait_for_hugetlb_memory_to_get_depleted() {
0114 local cgroup="$1"
0115 local path="$cgroup_path/$cgroup/hugetlb.${MB}MB.$reservation_usage_file"
0116
0117 while [ $(cat $path) != 0 ]; do
0118 echo Waiting for hugetlb memory to get depleted.
0119 cat $path
0120 sleep 0.5
0121 done
0122 }
0123
0124 function wait_for_hugetlb_memory_to_get_reserved() {
0125 local cgroup="$1"
0126 local size="$2"
0127
0128 local path="$cgroup_path/$cgroup/hugetlb.${MB}MB.$reservation_usage_file"
0129
0130 while [ $(cat $path) != $size ]; do
0131 echo Waiting for hugetlb memory reservation to reach size $size.
0132 cat $path
0133 sleep 0.5
0134 done
0135 }
0136
0137 function wait_for_hugetlb_memory_to_get_written() {
0138 local cgroup="$1"
0139 local size="$2"
0140
0141 local path="$cgroup_path/$cgroup/hugetlb.${MB}MB.$fault_usage_file"
0142
0143 while [ $(cat $path) != $size ]; do
0144 echo Waiting for hugetlb memory to reach size $size.
0145 cat $path
0146 sleep 0.5
0147 done
0148 }
0149
0150 function write_hugetlbfs_and_get_usage() {
0151 local cgroup="$1"
0152 local size="$2"
0153 local populate="$3"
0154 local write="$4"
0155 local path="$5"
0156 local method="$6"
0157 local private="$7"
0158 local expect_failure="$8"
0159 local reserve="$9"
0160
0161
0162 reservation_failed=0
0163 oom_killed=0
0164 hugetlb_difference=0
0165 reserved_difference=0
0166
0167 local hugetlb_usage=$cgroup_path/$cgroup/hugetlb.${MB}MB.$fault_usage_file
0168 local reserved_usage=$cgroup_path/$cgroup/hugetlb.${MB}MB.$reservation_usage_file
0169
0170 local hugetlb_before=$(cat $hugetlb_usage)
0171 local reserved_before=$(cat $reserved_usage)
0172
0173 echo
0174 echo Starting:
0175 echo hugetlb_usage="$hugetlb_before"
0176 echo reserved_usage="$reserved_before"
0177 echo expect_failure is "$expect_failure"
0178
0179 output=$(mktemp)
0180 set +e
0181 if [[ "$method" == "1" ]] || [[ "$method" == 2 ]] ||
0182 [[ "$private" == "-r" ]] && [[ "$expect_failure" != 1 ]]; then
0183
0184 bash write_hugetlb_memory.sh "$size" "$populate" "$write" \
0185 "$cgroup" "$path" "$method" "$private" "-l" "$reserve" 2>&1 | tee $output &
0186
0187 local write_result=$?
0188 local write_pid=$!
0189
0190 until grep -q -i "DONE" $output; do
0191 echo waiting for DONE signal.
0192 if ! ps $write_pid > /dev/null
0193 then
0194 echo "FAIL: The write died"
0195 cleanup
0196 exit 1
0197 fi
0198 sleep 0.5
0199 done
0200
0201 echo ================= write_hugetlb_memory.sh output is:
0202 cat $output
0203 echo ================= end output.
0204
0205 if [[ "$populate" == "-o" ]] || [[ "$write" == "-w" ]]; then
0206 wait_for_hugetlb_memory_to_get_written "$cgroup" "$size"
0207 elif [[ "$reserve" != "-n" ]]; then
0208 wait_for_hugetlb_memory_to_get_reserved "$cgroup" "$size"
0209 else
0210
0211
0212 sleep 0.5
0213 fi
0214
0215 echo write_result is $write_result
0216 else
0217 bash write_hugetlb_memory.sh "$size" "$populate" "$write" \
0218 "$cgroup" "$path" "$method" "$private" "$reserve"
0219 local write_result=$?
0220
0221 if [[ "$reserve" != "-n" ]]; then
0222 wait_for_hugetlb_memory_to_get_reserved "$cgroup" "$size"
0223 fi
0224 fi
0225 set -e
0226
0227 if [[ "$write_result" == 1 ]]; then
0228 reservation_failed=1
0229 fi
0230
0231
0232
0233
0234
0235 if [[ "$write_result" == 135 ]] || [[ "$write_result" == 137 ]]; then
0236 oom_killed=1
0237 fi
0238
0239 local hugetlb_after=$(cat $hugetlb_usage)
0240 local reserved_after=$(cat $reserved_usage)
0241
0242 echo After write:
0243 echo hugetlb_usage="$hugetlb_after"
0244 echo reserved_usage="$reserved_after"
0245
0246 hugetlb_difference=$(($hugetlb_after - $hugetlb_before))
0247 reserved_difference=$(($reserved_after - $reserved_before))
0248 }
0249
0250 function cleanup_hugetlb_memory() {
0251 set +e
0252 local cgroup="$1"
0253 if [[ "$(pgrep -f write_to_hugetlbfs)" != "" ]]; then
0254 echo killing write_to_hugetlbfs
0255 killall -2 write_to_hugetlbfs
0256 wait_for_hugetlb_memory_to_get_depleted $cgroup
0257 fi
0258 set -e
0259
0260 if [[ -e /mnt/huge ]]; then
0261 rm -rf /mnt/huge/*
0262 umount /mnt/huge
0263 rmdir /mnt/huge
0264 fi
0265 }
0266
0267 function run_test() {
0268 local size=$(($1 * ${MB} * 1024 * 1024))
0269 local populate="$2"
0270 local write="$3"
0271 local cgroup_limit=$(($4 * ${MB} * 1024 * 1024))
0272 local reservation_limit=$(($5 * ${MB} * 1024 * 1024))
0273 local nr_hugepages="$6"
0274 local method="$7"
0275 local private="$8"
0276 local expect_failure="$9"
0277 local reserve="${10}"
0278
0279
0280 hugetlb_difference=0
0281 reserved_difference=0
0282 reservation_failed=0
0283 oom_killed=0
0284
0285 echo nr hugepages = "$nr_hugepages"
0286 echo "$nr_hugepages" >/proc/sys/vm/nr_hugepages
0287
0288 setup_cgroup "hugetlb_cgroup_test" "$cgroup_limit" "$reservation_limit"
0289
0290 mkdir -p /mnt/huge
0291 mount -t hugetlbfs -o pagesize=${MB}M,size=256M none /mnt/huge
0292
0293 write_hugetlbfs_and_get_usage "hugetlb_cgroup_test" "$size" "$populate" \
0294 "$write" "/mnt/huge/test" "$method" "$private" "$expect_failure" \
0295 "$reserve"
0296
0297 cleanup_hugetlb_memory "hugetlb_cgroup_test"
0298
0299 local final_hugetlb=$(cat $cgroup_path/hugetlb_cgroup_test/hugetlb.${MB}MB.$fault_usage_file)
0300 local final_reservation=$(cat $cgroup_path/hugetlb_cgroup_test/hugetlb.${MB}MB.$reservation_usage_file)
0301
0302 echo $hugetlb_difference
0303 echo $reserved_difference
0304 expect_equal "0" "$final_hugetlb" "final hugetlb is not zero"
0305 expect_equal "0" "$final_reservation" "final reservation is not zero"
0306 }
0307
0308 function run_multiple_cgroup_test() {
0309 local size1="$1"
0310 local populate1="$2"
0311 local write1="$3"
0312 local cgroup_limit1="$4"
0313 local reservation_limit1="$5"
0314
0315 local size2="$6"
0316 local populate2="$7"
0317 local write2="$8"
0318 local cgroup_limit2="$9"
0319 local reservation_limit2="${10}"
0320
0321 local nr_hugepages="${11}"
0322 local method="${12}"
0323 local private="${13}"
0324 local expect_failure="${14}"
0325 local reserve="${15}"
0326
0327
0328 hugetlb_difference1=0
0329 reserved_difference1=0
0330 reservation_failed1=0
0331 oom_killed1=0
0332
0333 hugetlb_difference2=0
0334 reserved_difference2=0
0335 reservation_failed2=0
0336 oom_killed2=0
0337
0338 echo nr hugepages = "$nr_hugepages"
0339 echo "$nr_hugepages" >/proc/sys/vm/nr_hugepages
0340
0341 setup_cgroup "hugetlb_cgroup_test1" "$cgroup_limit1" "$reservation_limit1"
0342 setup_cgroup "hugetlb_cgroup_test2" "$cgroup_limit2" "$reservation_limit2"
0343
0344 mkdir -p /mnt/huge
0345 mount -t hugetlbfs -o pagesize=${MB}M,size=256M none /mnt/huge
0346
0347 write_hugetlbfs_and_get_usage "hugetlb_cgroup_test1" "$size1" \
0348 "$populate1" "$write1" "/mnt/huge/test1" "$method" "$private" \
0349 "$expect_failure" "$reserve"
0350
0351 hugetlb_difference1=$hugetlb_difference
0352 reserved_difference1=$reserved_difference
0353 reservation_failed1=$reservation_failed
0354 oom_killed1=$oom_killed
0355
0356 local cgroup1_hugetlb_usage=$cgroup_path/hugetlb_cgroup_test1/hugetlb.${MB}MB.$fault_usage_file
0357 local cgroup1_reservation_usage=$cgroup_path/hugetlb_cgroup_test1/hugetlb.${MB}MB.$reservation_usage_file
0358 local cgroup2_hugetlb_usage=$cgroup_path/hugetlb_cgroup_test2/hugetlb.${MB}MB.$fault_usage_file
0359 local cgroup2_reservation_usage=$cgroup_path/hugetlb_cgroup_test2/hugetlb.${MB}MB.$reservation_usage_file
0360
0361 local usage_before_second_write=$(cat $cgroup1_hugetlb_usage)
0362 local reservation_usage_before_second_write=$(cat $cgroup1_reservation_usage)
0363
0364 write_hugetlbfs_and_get_usage "hugetlb_cgroup_test2" "$size2" \
0365 "$populate2" "$write2" "/mnt/huge/test2" "$method" "$private" \
0366 "$expect_failure" "$reserve"
0367
0368 hugetlb_difference2=$hugetlb_difference
0369 reserved_difference2=$reserved_difference
0370 reservation_failed2=$reservation_failed
0371 oom_killed2=$oom_killed
0372
0373 expect_equal "$usage_before_second_write" \
0374 "$(cat $cgroup1_hugetlb_usage)" "Usage changed."
0375 expect_equal "$reservation_usage_before_second_write" \
0376 "$(cat $cgroup1_reservation_usage)" "Reservation usage changed."
0377
0378 cleanup_hugetlb_memory
0379
0380 local final_hugetlb=$(cat $cgroup1_hugetlb_usage)
0381 local final_reservation=$(cat $cgroup1_reservation_usage)
0382
0383 expect_equal "0" "$final_hugetlb" \
0384 "hugetlbt_cgroup_test1 final hugetlb is not zero"
0385 expect_equal "0" "$final_reservation" \
0386 "hugetlbt_cgroup_test1 final reservation is not zero"
0387
0388 local final_hugetlb=$(cat $cgroup2_hugetlb_usage)
0389 local final_reservation=$(cat $cgroup2_reservation_usage)
0390
0391 expect_equal "0" "$final_hugetlb" \
0392 "hugetlb_cgroup_test2 final hugetlb is not zero"
0393 expect_equal "0" "$final_reservation" \
0394 "hugetlb_cgroup_test2 final reservation is not zero"
0395 }
0396
0397 cleanup
0398
0399 for populate in "" "-o"; do
0400 for method in 0 1 2; do
0401 for private in "" "-r"; do
0402 for reserve in "" "-n"; do
0403
0404
0405 if [[ "$method" == 1 ]] && [[ "$private" == "" ]]; then
0406 continue
0407 fi
0408
0409
0410 if [[ "$method" == 2"" ]] && [[ "$populate" == "-o" ]]; then
0411 continue
0412 fi
0413
0414 if [[ "$method" == 2"" ]] && [[ "$reserve" == "-n" ]]; then
0415 continue
0416 fi
0417
0418 cleanup
0419 echo
0420 echo
0421 echo
0422 echo Test normal case.
0423 echo private=$private, populate=$populate, method=$method, reserve=$reserve
0424 run_test 5 "$populate" "" 10 10 10 "$method" "$private" "0" "$reserve"
0425
0426 echo Memory charged to hugtlb=$hugetlb_difference
0427 echo Memory charged to reservation=$reserved_difference
0428
0429 if [[ "$populate" == "-o" ]]; then
0430 expect_equal "$((5 * $MB * 1024 * 1024))" "$hugetlb_difference" \
0431 "Reserved memory charged to hugetlb cgroup."
0432 else
0433 expect_equal "0" "$hugetlb_difference" \
0434 "Reserved memory charged to hugetlb cgroup."
0435 fi
0436
0437 if [[ "$reserve" != "-n" ]] || [[ "$populate" == "-o" ]]; then
0438 expect_equal "$((5 * $MB * 1024 * 1024))" "$reserved_difference" \
0439 "Reserved memory not charged to reservation usage."
0440 else
0441 expect_equal "0" "$reserved_difference" \
0442 "Reserved memory not charged to reservation usage."
0443 fi
0444
0445 echo 'PASS'
0446
0447 cleanup
0448 echo
0449 echo
0450 echo
0451 echo Test normal case with write.
0452 echo private=$private, populate=$populate, method=$method, reserve=$reserve
0453 run_test 5 "$populate" '-w' 5 5 10 "$method" "$private" "0" "$reserve"
0454
0455 echo Memory charged to hugtlb=$hugetlb_difference
0456 echo Memory charged to reservation=$reserved_difference
0457
0458 expect_equal "$((5 * $MB * 1024 * 1024))" "$hugetlb_difference" \
0459 "Reserved memory charged to hugetlb cgroup."
0460
0461 expect_equal "$((5 * $MB * 1024 * 1024))" "$reserved_difference" \
0462 "Reserved memory not charged to reservation usage."
0463
0464 echo 'PASS'
0465
0466 cleanup
0467 continue
0468 echo
0469 echo
0470 echo
0471 echo Test more than reservation case.
0472 echo private=$private, populate=$populate, method=$method, reserve=$reserve
0473
0474 if [ "$reserve" != "-n" ]; then
0475 run_test "5" "$populate" '' "10" "2" "10" "$method" "$private" "1" \
0476 "$reserve"
0477
0478 expect_equal "1" "$reservation_failed" "Reservation succeeded."
0479 fi
0480
0481 echo 'PASS'
0482
0483 cleanup
0484
0485 echo
0486 echo
0487 echo
0488 echo Test more than cgroup limit case.
0489 echo private=$private, populate=$populate, method=$method, reserve=$reserve
0490
0491
0492 if [[ "$method" != 2 ]]; then
0493 run_test 5 "$populate" "-w" 2 10 10 "$method" "$private" "1" "$reserve"
0494
0495 expect_equal "1" "$oom_killed" "Not oom killed."
0496 fi
0497 echo 'PASS'
0498
0499 cleanup
0500
0501 echo
0502 echo
0503 echo
0504 echo Test normal case, multiple cgroups.
0505 echo private=$private, populate=$populate, method=$method, reserve=$reserve
0506 run_multiple_cgroup_test "3" "$populate" "" "10" "10" "5" \
0507 "$populate" "" "10" "10" "10" \
0508 "$method" "$private" "0" "$reserve"
0509
0510 echo Memory charged to hugtlb1=$hugetlb_difference1
0511 echo Memory charged to reservation1=$reserved_difference1
0512 echo Memory charged to hugtlb2=$hugetlb_difference2
0513 echo Memory charged to reservation2=$reserved_difference2
0514
0515 if [[ "$reserve" != "-n" ]] || [[ "$populate" == "-o" ]]; then
0516 expect_equal "3" "$reserved_difference1" \
0517 "Incorrect reservations charged to cgroup 1."
0518
0519 expect_equal "5" "$reserved_difference2" \
0520 "Incorrect reservation charged to cgroup 2."
0521
0522 else
0523 expect_equal "0" "$reserved_difference1" \
0524 "Incorrect reservations charged to cgroup 1."
0525
0526 expect_equal "0" "$reserved_difference2" \
0527 "Incorrect reservation charged to cgroup 2."
0528 fi
0529
0530 if [[ "$populate" == "-o" ]]; then
0531 expect_equal "3" "$hugetlb_difference1" \
0532 "Incorrect hugetlb charged to cgroup 1."
0533
0534 expect_equal "5" "$hugetlb_difference2" \
0535 "Incorrect hugetlb charged to cgroup 2."
0536
0537 else
0538 expect_equal "0" "$hugetlb_difference1" \
0539 "Incorrect hugetlb charged to cgroup 1."
0540
0541 expect_equal "0" "$hugetlb_difference2" \
0542 "Incorrect hugetlb charged to cgroup 2."
0543 fi
0544 echo 'PASS'
0545
0546 cleanup
0547 echo
0548 echo
0549 echo
0550 echo Test normal case with write, multiple cgroups.
0551 echo private=$private, populate=$populate, method=$method, reserve=$reserve
0552 run_multiple_cgroup_test "3" "$populate" "-w" "10" "10" "5" \
0553 "$populate" "-w" "10" "10" "10" \
0554 "$method" "$private" "0" "$reserve"
0555
0556 echo Memory charged to hugtlb1=$hugetlb_difference1
0557 echo Memory charged to reservation1=$reserved_difference1
0558 echo Memory charged to hugtlb2=$hugetlb_difference2
0559 echo Memory charged to reservation2=$reserved_difference2
0560
0561 expect_equal "3" "$hugetlb_difference1" \
0562 "Incorrect hugetlb charged to cgroup 1."
0563
0564 expect_equal "3" "$reserved_difference1" \
0565 "Incorrect reservation charged to cgroup 1."
0566
0567 expect_equal "5" "$hugetlb_difference2" \
0568 "Incorrect hugetlb charged to cgroup 2."
0569
0570 expect_equal "5" "$reserved_difference2" \
0571 "Incorrected reservation charged to cgroup 2."
0572 echo 'PASS'
0573
0574 cleanup
0575
0576 done
0577 done
0578 done
0579 done
0580
0581 if [[ $do_umount ]]; then
0582 umount $cgroup_path
0583 rmdir $cgroup_path
0584 fi