Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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