Skip to content

Commit 2fac2df

Browse files
author
Fox Snowpatch
committed
1 parent 4f37907 commit 2fac2df

10 files changed

Lines changed: 181 additions & 108 deletions

tools/testing/selftests/cgroup/test_hugetlb_memcg.c

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,15 @@
1212

1313
#define ADDR ((void *)(0x0UL))
1414
#define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB)
15-
/* mapping 8 MBs == 4 hugepages */
16-
#define LENGTH (8UL*1024*1024)
1715
#define PROTECTION (PROT_READ | PROT_WRITE)
1816

17+
/*
18+
* This value matches the kernel's MEMCG_CHARGE_BATCH definition:
19+
* see include/linux/memcontrol.h. If the kernel value changes, this
20+
* test constant must be updated accordingly to stay consistent.
21+
*/
22+
#define MEMCG_CHARGE_BATCH 64U
23+
1924
/* borrowed from mm/hmm-tests.c */
2025
static long get_hugepage_size(void)
2126
{
@@ -84,38 +89,43 @@ static unsigned int check_first(char *addr)
8489
return *(unsigned int *)addr;
8590
}
8691

87-
static void write_data(char *addr)
92+
static void write_data(char *addr, size_t length)
8893
{
8994
unsigned long i;
9095

91-
for (i = 0; i < LENGTH; i++)
96+
for (i = 0; i < length; i++)
9297
*(addr + i) = (char)i;
9398
}
9499

95100
static int hugetlb_test_program(const char *cgroup, void *arg)
96101
{
97102
char *test_group = (char *)arg;
98103
void *addr;
104+
long hpage_size = get_hugepage_size() * 1024;
99105
long old_current, expected_current, current;
100106
int ret = EXIT_FAILURE;
107+
size_t length = 4 * hpage_size;
108+
int pagesize, nr_pages;
109+
110+
pagesize = getpagesize();
101111

102112
old_current = cg_read_long(test_group, "memory.current");
103113
set_nr_hugepages(20);
104114
current = cg_read_long(test_group, "memory.current");
105-
if (current - old_current >= MB(2)) {
115+
if (current - old_current >= hpage_size) {
106116
ksft_print_msg(
107117
"setting nr_hugepages should not increase hugepage usage.\n");
108118
ksft_print_msg("before: %ld, after: %ld\n", old_current, current);
109119
return EXIT_FAILURE;
110120
}
111121

112-
addr = mmap(ADDR, LENGTH, PROTECTION, FLAGS, 0, 0);
122+
addr = mmap(ADDR, length, PROTECTION, FLAGS, 0, 0);
113123
if (addr == MAP_FAILED) {
114124
ksft_print_msg("fail to mmap.\n");
115125
return EXIT_FAILURE;
116126
}
117127
current = cg_read_long(test_group, "memory.current");
118-
if (current - old_current >= MB(2)) {
128+
if (current - old_current >= hpage_size) {
119129
ksft_print_msg("mmap should not increase hugepage usage.\n");
120130
ksft_print_msg("before: %ld, after: %ld\n", old_current, current);
121131
goto out_failed_munmap;
@@ -124,30 +134,44 @@ static int hugetlb_test_program(const char *cgroup, void *arg)
124134

125135
/* read the first page */
126136
check_first(addr);
127-
expected_current = old_current + MB(2);
137+
nr_pages = hpage_size / pagesize;
138+
expected_current = old_current + hpage_size;
128139
current = cg_read_long(test_group, "memory.current");
129-
if (!values_close(expected_current, current, 5)) {
130-
ksft_print_msg("memory usage should increase by around 2MB.\n");
140+
if (nr_pages < MEMCG_CHARGE_BATCH && current == old_current) {
141+
/*
142+
* Memory cgroup charging uses per-CPU stocks and batched updates to the
143+
* memcg usage counters. For hugetlb allocations, the number of pages
144+
* that memcg charges is expressed in base pages (nr_pages), not
145+
* in hugepage units. When the charge for an allocation is smaller than
146+
* the internal batching threshold (nr_pages < MEMCG_CHARGE_BATCH),
147+
* it may be fully satisfied from the CPU’s local stock. In such
148+
* cases memory.current does not necessarily
149+
* increase.
150+
* Therefore, Treat a zero delta as valid behaviour here.
151+
*/
152+
ksft_print_msg("no visible memcg charge, allocation consumed from local stock.\n");
153+
} else if (!values_close(expected_current, current, 5)) {
154+
ksft_print_msg("memory usage should increase by ~1 huge page.\n");
131155
ksft_print_msg(
132156
"expected memory: %ld, actual memory: %ld\n",
133157
expected_current, current);
134158
goto out_failed_munmap;
135159
}
136160

137161
/* write to the whole range */
138-
write_data(addr);
162+
write_data(addr, length);
139163
current = cg_read_long(test_group, "memory.current");
140-
expected_current = old_current + MB(8);
164+
expected_current = old_current + length;
141165
if (!values_close(expected_current, current, 5)) {
142-
ksft_print_msg("memory usage should increase by around 8MB.\n");
166+
ksft_print_msg("memory usage should increase by around 4 huge pages.\n");
143167
ksft_print_msg(
144168
"expected memory: %ld, actual memory: %ld\n",
145169
expected_current, current);
146170
goto out_failed_munmap;
147171
}
148172

149173
/* unmap the whole range */
150-
munmap(addr, LENGTH);
174+
munmap(addr, length);
151175
current = cg_read_long(test_group, "memory.current");
152176
expected_current = old_current;
153177
if (!values_close(expected_current, current, 5)) {
@@ -162,13 +186,15 @@ static int hugetlb_test_program(const char *cgroup, void *arg)
162186
return ret;
163187

164188
out_failed_munmap:
165-
munmap(addr, LENGTH);
189+
munmap(addr, length);
166190
return ret;
167191
}
168192

169193
static int test_hugetlb_memcg(char *root)
170194
{
171195
int ret = KSFT_FAIL;
196+
int num_pages = 20;
197+
long hpage_size = get_hugepage_size();
172198
char *test_group;
173199

174200
test_group = cg_name(root, "hugetlb_memcg_test");
@@ -177,7 +203,7 @@ static int test_hugetlb_memcg(char *root)
177203
goto out;
178204
}
179205

180-
if (cg_write(test_group, "memory.max", "100M")) {
206+
if (cg_write_numeric(test_group, "memory.max", num_pages * hpage_size * 1024)) {
181207
ksft_print_msg("fail to set cgroup memory limit.\n");
182208
goto out;
183209
}
@@ -200,6 +226,7 @@ int main(int argc, char **argv)
200226
{
201227
char root[PATH_MAX];
202228
int ret = EXIT_SUCCESS, has_memory_hugetlb_acc;
229+
long val;
203230

204231
has_memory_hugetlb_acc = proc_mount_contains("memory_hugetlb_accounting");
205232
if (has_memory_hugetlb_acc < 0)
@@ -208,12 +235,15 @@ int main(int argc, char **argv)
208235
ksft_exit_skip("memory hugetlb accounting is disabled\n");
209236

210237
/* Unit is kB! */
211-
if (get_hugepage_size() != 2048) {
212-
ksft_print_msg("test_hugetlb_memcg requires 2MB hugepages\n");
238+
val = get_hugepage_size();
239+
if (val < 0) {
240+
ksft_print_msg("Failed to read hugepage size\n");
213241
ksft_test_result_skip("test_hugetlb_memcg\n");
214242
return ret;
215243
}
216244

245+
ksft_print_msg("Hugepage size: %ld kB\n", val);
246+
217247
if (cg_find_unified_root(root, sizeof(root), NULL))
218248
ksft_exit_skip("cgroup v2 isn't mounted\n");
219249

tools/testing/selftests/mm/charge_reserved_hugetlb.sh

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ function cleanup() {
6565
if [[ -e $cgroup_path/hugetlb_cgroup_test2 ]]; then
6666
rmdir $cgroup_path/hugetlb_cgroup_test2
6767
fi
68-
echo 0 >/proc/sys/vm/nr_hugepages
68+
echo "$nr_hugepgs" > /proc/sys/vm/nr_hugepages
6969
echo CLEANUP DONE
7070
}
7171

@@ -89,6 +89,15 @@ function get_machine_hugepage_size() {
8989
}
9090

9191
MB=$(get_machine_hugepage_size)
92+
if (( MB >= 1024 )); then
93+
# For 1GB hugepages
94+
UNIT="GB"
95+
MB_DISPLAY=$((MB / 1024))
96+
else
97+
# For 2MB hugepages
98+
UNIT="MB"
99+
MB_DISPLAY=$MB
100+
fi
92101

93102
function setup_cgroup() {
94103
local name="$1"
@@ -98,11 +107,12 @@ function setup_cgroup() {
98107
mkdir $cgroup_path/$name
99108

100109
echo writing cgroup limit: "$cgroup_limit"
101-
echo "$cgroup_limit" >$cgroup_path/$name/hugetlb.${MB}MB.$fault_limit_file
110+
echo "$cgroup_limit" > \
111+
$cgroup_path/$name/hugetlb.${MB_DISPLAY}${UNIT}.$fault_limit_file
102112

103113
echo writing reservation limit: "$reservation_limit"
104114
echo "$reservation_limit" > \
105-
$cgroup_path/$name/hugetlb.${MB}MB.$reservation_limit_file
115+
$cgroup_path/$name/hugetlb.${MB_DISPLAY}${UNIT}.$reservation_limit_file
106116

107117
if [ -e "$cgroup_path/$name/cpuset.cpus" ]; then
108118
echo 0 >$cgroup_path/$name/cpuset.cpus
@@ -137,23 +147,23 @@ function wait_for_file_value() {
137147

138148
function wait_for_hugetlb_memory_to_get_depleted() {
139149
local cgroup="$1"
140-
local path="$cgroup_path/$cgroup/hugetlb.${MB}MB.$reservation_usage_file"
150+
local path="$cgroup_path/$cgroup/hugetlb.${MB_DISPLAY}${UNIT}.$reservation_usage_file"
141151

142152
wait_for_file_value "$path" "0"
143153
}
144154

145155
function wait_for_hugetlb_memory_to_get_reserved() {
146156
local cgroup="$1"
147157
local size="$2"
148-
local path="$cgroup_path/$cgroup/hugetlb.${MB}MB.$reservation_usage_file"
158+
local path="$cgroup_path/$cgroup/hugetlb.${MB_DISPLAY}${UNIT}.$reservation_usage_file"
149159

150160
wait_for_file_value "$path" "$size"
151161
}
152162

153163
function wait_for_hugetlb_memory_to_get_written() {
154164
local cgroup="$1"
155165
local size="$2"
156-
local path="$cgroup_path/$cgroup/hugetlb.${MB}MB.$fault_usage_file"
166+
local path="$cgroup_path/$cgroup/hugetlb.${MB_DISPLAY}${UNIT}.$fault_usage_file"
157167

158168
wait_for_file_value "$path" "$size"
159169
}
@@ -175,8 +185,8 @@ function write_hugetlbfs_and_get_usage() {
175185
hugetlb_difference=0
176186
reserved_difference=0
177187

178-
local hugetlb_usage=$cgroup_path/$cgroup/hugetlb.${MB}MB.$fault_usage_file
179-
local reserved_usage=$cgroup_path/$cgroup/hugetlb.${MB}MB.$reservation_usage_file
188+
local hugetlb_usage=$cgroup_path/$cgroup/hugetlb.${MB_DISPLAY}${UNIT}.$fault_usage_file
189+
local reserved_usage=$cgroup_path/$cgroup/hugetlb.${MB_DISPLAY}${UNIT}.$reservation_usage_file
180190

181191
local hugetlb_before=$(cat $hugetlb_usage)
182192
local reserved_before=$(cat $reserved_usage)
@@ -307,8 +317,10 @@ function run_test() {
307317

308318
cleanup_hugetlb_memory "hugetlb_cgroup_test"
309319

310-
local final_hugetlb=$(cat $cgroup_path/hugetlb_cgroup_test/hugetlb.${MB}MB.$fault_usage_file)
311-
local final_reservation=$(cat $cgroup_path/hugetlb_cgroup_test/hugetlb.${MB}MB.$reservation_usage_file)
320+
local final_hugetlb=$(cat \
321+
$cgroup_path/hugetlb_cgroup_test/hugetlb.${MB_DISPLAY}${UNIT}.$fault_usage_file)
322+
local final_reservation=$(cat \
323+
$cgroup_path/hugetlb_cgroup_test/hugetlb.${MB_DISPLAY}${UNIT}.$reservation_usage_file)
312324

313325
echo $hugetlb_difference
314326
echo $reserved_difference
@@ -364,10 +376,14 @@ function run_multiple_cgroup_test() {
364376
reservation_failed1=$reservation_failed
365377
oom_killed1=$oom_killed
366378

367-
local cgroup1_hugetlb_usage=$cgroup_path/hugetlb_cgroup_test1/hugetlb.${MB}MB.$fault_usage_file
368-
local cgroup1_reservation_usage=$cgroup_path/hugetlb_cgroup_test1/hugetlb.${MB}MB.$reservation_usage_file
369-
local cgroup2_hugetlb_usage=$cgroup_path/hugetlb_cgroup_test2/hugetlb.${MB}MB.$fault_usage_file
370-
local cgroup2_reservation_usage=$cgroup_path/hugetlb_cgroup_test2/hugetlb.${MB}MB.$reservation_usage_file
379+
local cgroup1_hugetlb_usage=\
380+
$cgroup_path/hugetlb_cgroup_test1/hugetlb.${MB_DISPLAY}${UNIT}.$fault_usage_file
381+
local cgroup1_reservation_usage=\
382+
$cgroup_path/hugetlb_cgroup_test1/hugetlb.${MB_DISPLAY}${UNIT}.$reservation_usage_file
383+
local cgroup2_hugetlb_usage=\
384+
$cgroup_path/hugetlb_cgroup_test2/hugetlb.${MB_DISPLAY}${UNIT}.$fault_usage_file
385+
local cgroup2_reservation_usage=\
386+
$cgroup_path/hugetlb_cgroup_test2/hugetlb.${MB_DISPLAY}${UNIT}.$reservation_usage_file
371387

372388
local usage_before_second_write=$(cat $cgroup1_hugetlb_usage)
373389
local reservation_usage_before_second_write=$(cat $cgroup1_reservation_usage)

tools/testing/selftests/mm/compaction_test.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -263,9 +263,6 @@ int main(int argc, char **argv)
263263

264264
for (entry = list; entry != NULL; entry = entry->next) {
265265
munmap(entry->map, MAP_SIZE);
266-
if (!entry->next)
267-
break;
268-
entry = entry->next;
269266
}
270267

271268
if (check_compaction(mem_free, hugepage_size,

tools/testing/selftests/mm/hugepage-mremap.c

Lines changed: 9 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
#define MB_TO_BYTES(x) (x * 1024 * 1024)
3232

3333
#define PROTECTION (PROT_READ | PROT_WRITE | PROT_EXEC)
34-
#define FLAGS (MAP_SHARED | MAP_ANONYMOUS)
34+
#define FLAGS (MAP_HUGETLB | MAP_SHARED | MAP_POPULATE)
3535

3636
static void check_bytes(char *addr)
3737
{
@@ -85,25 +85,14 @@ static void register_region_with_uffd(char *addr, size_t len)
8585
if (ioctl(uffd, UFFDIO_API, &uffdio_api) == -1)
8686
ksft_exit_fail_msg("ioctl-UFFDIO_API: %s\n", strerror(errno));
8787

88-
/* Create a private anonymous mapping. The memory will be
89-
* demand-zero paged--that is, not yet allocated. When we
90-
* actually touch the memory, it will be allocated via
91-
* the userfaultfd.
92-
*/
93-
94-
addr = mmap(NULL, len, PROT_READ | PROT_WRITE,
95-
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
96-
if (addr == MAP_FAILED)
97-
ksft_exit_fail_msg("mmap: %s\n", strerror(errno));
98-
99-
ksft_print_msg("Address returned by mmap() = %p\n", addr);
100-
101-
/* Register the memory range of the mapping we just created for
102-
* handling by the userfaultfd object. In mode, we request to track
103-
* missing pages (i.e., pages that have not yet been faulted in).
88+
/* Register the passed memory range for handling by the userfaultfd object.
89+
* In mode, we request to track missing pages
90+
* (i.e., pages that have not yet been faulted in).
10491
*/
10592
if (uffd_register(uffd, addr, len, true, false, false))
10693
ksft_exit_fail_msg("ioctl-UFFDIO_REGISTER: %s\n", strerror(errno));
94+
95+
ksft_print_msg("Registered memory at address %p with userfaultfd\n", addr);
10796
}
10897

10998
int main(int argc, char *argv[])
@@ -132,23 +121,20 @@ int main(int argc, char *argv[])
132121

133122
/* mmap to a PUD aligned address to hopefully trigger pmd sharing. */
134123
unsigned long suggested_addr = 0x7eaa40000000;
135-
void *haddr = mmap((void *)suggested_addr, length, PROTECTION,
136-
MAP_HUGETLB | MAP_SHARED | MAP_POPULATE, fd, 0);
124+
void *haddr = mmap((void *)suggested_addr, length, PROTECTION, FLAGS, fd, 0);
137125
ksft_print_msg("Map haddr: Returned address is %p\n", haddr);
138126
if (haddr == MAP_FAILED)
139127
ksft_exit_fail_msg("mmap1: %s\n", strerror(errno));
140128

141129
/* mmap again to a dummy address to hopefully trigger pmd sharing. */
142130
suggested_addr = 0x7daa40000000;
143-
void *daddr = mmap((void *)suggested_addr, length, PROTECTION,
144-
MAP_HUGETLB | MAP_SHARED | MAP_POPULATE, fd, 0);
131+
void *daddr = mmap((void *)suggested_addr, length, PROTECTION, FLAGS, fd, 0);
145132
ksft_print_msg("Map daddr: Returned address is %p\n", daddr);
146133
if (daddr == MAP_FAILED)
147134
ksft_exit_fail_msg("mmap3: %s\n", strerror(errno));
148135

149136
suggested_addr = 0x7faa40000000;
150-
void *vaddr =
151-
mmap((void *)suggested_addr, length, PROTECTION, FLAGS, -1, 0);
137+
void *vaddr = mmap((void *)suggested_addr, length, PROTECTION, FLAGS, fd, 0);
152138
ksft_print_msg("Map vaddr: Returned address is %p\n", vaddr);
153139
if (vaddr == MAP_FAILED)
154140
ksft_exit_fail_msg("mmap2: %s\n", strerror(errno));

0 commit comments

Comments
 (0)