1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3 4# Kselftest framework requirement - SKIP code is 4. 5ksft_skip=4 6 7set -e 8 9if [[ $(id -u) -ne 0 ]]; then 10 echo "This test must be run as root. Skipping..." 11 exit $ksft_skip 12fi 13 14nr_hugepgs=$(cat /proc/sys/vm/nr_hugepages) 15usage_file=usage_in_bytes 16 17if [[ "$1" == "-cgroup-v2" ]]; then 18 cgroup2=1 19 usage_file=current 20fi 21 22 23if [[ $cgroup2 ]]; then 24 CGROUP_ROOT=$(mount -t cgroup2 | head -1 | awk '{print $3}') 25 if [[ -z "$CGROUP_ROOT" ]]; then 26 CGROUP_ROOT=$(mktemp -d) 27 mount -t cgroup2 none $CGROUP_ROOT 28 do_umount=1 29 fi 30 echo "+hugetlb +memory" >$CGROUP_ROOT/cgroup.subtree_control 31else 32 CGROUP_ROOT=$(mount -t cgroup | grep ",hugetlb" | awk '{print $3}') 33 if [[ -z "$CGROUP_ROOT" ]]; then 34 CGROUP_ROOT=/dev/cgroup/memory 35 mount -t cgroup memory,hugetlb $CGROUP_ROOT 36 do_umount=1 37 fi 38fi 39MNT='/mnt/huge' 40 41function get_machine_hugepage_size() { 42 hpz=$(grep -i hugepagesize /proc/meminfo) 43 kb=${hpz:14:-3} 44 mb=$(($kb / 1024)) 45 echo $mb 46} 47 48MB=$(get_machine_hugepage_size) 49 50function cleanup() { 51 echo cleanup 52 set +e 53 rm -rf "$MNT"/* 2>/dev/null 54 umount "$MNT" 2>/dev/null 55 rmdir "$MNT" 2>/dev/null 56 rmdir "$CGROUP_ROOT"/a/b 2>/dev/null 57 rmdir "$CGROUP_ROOT"/a 2>/dev/null 58 rmdir "$CGROUP_ROOT"/test1 2>/dev/null 59 echo $nr_hugepgs >/proc/sys/vm/nr_hugepages 60 set -e 61} 62 63function assert_with_retry() { 64 local actual_path="$1" 65 local expected="$2" 66 local tolerance=$((7 * 1024 * 1024)) 67 local timeout=20 68 local interval=1 69 local start_time 70 local now 71 local elapsed 72 local actual 73 74 start_time=$(date +%s) 75 76 while true; do 77 actual="$(cat "$actual_path")" 78 79 if [[ $actual -ge $(($expected - $tolerance)) ]] && 80 [[ $actual -le $(($expected + $tolerance)) ]]; then 81 return 0 82 fi 83 84 now=$(date +%s) 85 elapsed=$((now - start_time)) 86 87 if [[ $elapsed -ge $timeout ]]; then 88 echo "actual = $((${actual%% *} / 1024 / 1024)) MB" 89 echo "expected = $((${expected%% *} / 1024 / 1024)) MB" 90 cleanup 91 exit 1 92 fi 93 94 sleep $interval 95 done 96} 97 98function assert_state() { 99 local expected_a="$1" 100 local expected_a_hugetlb="$2" 101 local expected_b="" 102 local expected_b_hugetlb="" 103 104 if [ ! -z ${3:-} ] && [ ! -z ${4:-} ]; then 105 expected_b="$3" 106 expected_b_hugetlb="$4" 107 fi 108 109 assert_with_retry "$CGROUP_ROOT/a/memory.$usage_file" "$expected_a" 110 assert_with_retry "$CGROUP_ROOT/a/hugetlb.${MB}MB.$usage_file" "$expected_a_hugetlb" 111 112 if [[ -n "$expected_b" && -n "$expected_b_hugetlb" ]]; then 113 assert_with_retry "$CGROUP_ROOT/a/b/memory.$usage_file" "$expected_b" 114 assert_with_retry "$CGROUP_ROOT/a/b/hugetlb.${MB}MB.$usage_file" "$expected_b_hugetlb" 115 fi 116} 117 118function setup() { 119 echo 100 >/proc/sys/vm/nr_hugepages 120 mkdir "$CGROUP_ROOT"/a 121 sleep 1 122 if [[ $cgroup2 ]]; then 123 echo "+hugetlb +memory" >$CGROUP_ROOT/a/cgroup.subtree_control 124 else 125 echo 0 >$CGROUP_ROOT/a/cpuset.mems 126 echo 0 >$CGROUP_ROOT/a/cpuset.cpus 127 fi 128 129 mkdir "$CGROUP_ROOT"/a/b 130 131 if [[ ! $cgroup2 ]]; then 132 echo 0 >$CGROUP_ROOT/a/b/cpuset.mems 133 echo 0 >$CGROUP_ROOT/a/b/cpuset.cpus 134 fi 135 136 mkdir -p "$MNT" 137 mount -t hugetlbfs none "$MNT" 138} 139 140write_hugetlbfs() { 141 local cgroup="$1" 142 local path="$2" 143 local size="$3" 144 145 if [[ $cgroup2 ]]; then 146 echo $$ >$CGROUP_ROOT/$cgroup/cgroup.procs 147 else 148 echo 0 >$CGROUP_ROOT/$cgroup/cpuset.mems 149 echo 0 >$CGROUP_ROOT/$cgroup/cpuset.cpus 150 echo $$ >"$CGROUP_ROOT/$cgroup/tasks" 151 fi 152 ./write_to_hugetlbfs -p "$path" -s "$size" -m 0 -o 153 if [[ $cgroup2 ]]; then 154 echo $$ >$CGROUP_ROOT/cgroup.procs 155 else 156 echo $$ >"$CGROUP_ROOT/tasks" 157 fi 158 echo 159} 160 161set -e 162 163size=$((${MB} * 1024 * 1024 * 25)) # 50MB = 25 * 2MB hugepages. 164 165cleanup 166 167echo 168echo Test charge, rmdir, uncharge 169setup 170echo mkdir 171mkdir $CGROUP_ROOT/test1 172 173echo write 174write_hugetlbfs test1 "$MNT"/test $size 175 176echo rmdir 177rmdir $CGROUP_ROOT/test1 178mkdir $CGROUP_ROOT/test1 179 180echo uncharge 181rm -rf /mnt/huge/* 182 183cleanup 184 185echo done 186echo 187if [[ ! $cgroup2 ]]; then 188 echo "Test parent and child hugetlb usage" 189 setup 190 191 echo write 192 write_hugetlbfs a "$MNT"/test $size 193 194 echo Assert memory charged correctly for parent use. 195 assert_state 0 $size 0 0 196 197 write_hugetlbfs a/b "$MNT"/test2 $size 198 199 echo Assert memory charged correctly for child use. 200 assert_state 0 $(($size * 2)) 0 $size 201 202 rmdir "$CGROUP_ROOT"/a/b 203 echo Assert memory reparent correctly. 204 assert_state 0 $(($size * 2)) 205 206 rm -rf "$MNT"/* 207 umount "$MNT" 208 echo Assert memory uncharged correctly. 209 assert_state 0 0 210 211 cleanup 212fi 213 214echo 215echo "Test child only hugetlb usage" 216echo setup 217setup 218 219echo write 220write_hugetlbfs a/b "$MNT"/test2 $size 221 222echo Assert memory charged correctly for child only use. 223assert_state 0 $(($size)) 0 $size 224 225rmdir "$CGROUP_ROOT"/a/b 226echo Assert memory reparent correctly. 227assert_state 0 $size 228 229rm -rf "$MNT"/* 230umount "$MNT" 231echo Assert memory uncharged correctly. 232assert_state 0 0 233 234cleanup 235 236echo ALL PASS 237 238if [[ $do_umount ]]; then 239 umount $CGROUP_ROOT 240 rm -rf $CGROUP_ROOT 241fi 242 243echo "$nr_hugepgs" > /proc/sys/vm/nr_hugepages 244