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