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