* [PATCH 1/3] selftests/mm/write_to_hugetlbfs: parse -s with strtoull and use size_t
2025-12-20 11:16 [PATCH 0/3] selftests/mm: hugetlb cgroup charging: robustness fixes Li Wang
@ 2025-12-20 11:16 ` Li Wang
2025-12-20 18:58 ` Andrew Morton
2025-12-20 11:16 ` [PATCH 2/3] selftests/mm/charge_reserved_hugetlb.sh: add waits with timeout helper Li Wang
2025-12-20 11:16 ` [PATCH 3/3] selftests/mm/charge_reserved_hugetlb: fix hugetlbfs mount size for large hugepages Li Wang
2 siblings, 1 reply; 5+ messages in thread
From: Li Wang @ 2025-12-20 11:16 UTC (permalink / raw)
To: linux-kselftest, akpm, linux-kernel, linux-mm
Cc: David Hildenbrand, Mark Brown, Shuah Khan, Waiman Long
write_to_hugetlbfs currently parses the -s size argument with atoi()
into an int. This silently accepts malformed input, cannot report overflow,
and can truncate large sizes.
--- Error log ---
# uname -r
6.12.0-xxx.el10.aarch64+64k
# ls /sys/kernel/mm/hugepages/hugepages-*
hugepages-16777216kB/ hugepages-2048kB/ hugepages-524288kB/
#./charge_reserved_hugetlb.sh -cgroup-v2
# -----------------------------------------
...
# nr hugepages = 10
# writing cgroup limit: 5368709120
# writing reseravation limit: 5368709120
...
# Writing to this path: /mnt/huge/test
# Writing this size: -1610612736 <--------
Switch size to size_t and parse -s using strtoull() with proper validation.
Also print the size using %zu.
This makes the test utility more robust and avoids undefined/incorrect
behavior with large or invalid -s values.
Signed-off-by: Li Wang <liwang@redhat.com>
Cc: David Hildenbrand <david@kernel.org>
Cc: Mark Brown <broonie@kernel.org>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Waiman Long <longman@redhat.com>
---
.../testing/selftests/mm/write_to_hugetlbfs.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/mm/write_to_hugetlbfs.c b/tools/testing/selftests/mm/write_to_hugetlbfs.c
index 34c91f7e6128..61f34b35dc27 100644
--- a/tools/testing/selftests/mm/write_to_hugetlbfs.c
+++ b/tools/testing/selftests/mm/write_to_hugetlbfs.c
@@ -68,7 +68,7 @@ int main(int argc, char **argv)
int key = 0;
int *ptr = NULL;
int c = 0;
- int size = 0;
+ size_t size = 0;
char path[256] = "";
enum method method = MAX_METHOD;
int want_sleep = 0, private = 0;
@@ -86,7 +86,20 @@ int main(int argc, char **argv)
while ((c = getopt(argc, argv, "s:p:m:owlrn")) != -1) {
switch (c) {
case 's':
- size = atoi(optarg);
+ errno = 0;
+ char *end = NULL;
+ unsigned long long tmp = strtoull(optarg, &end, 10);
+ if (errno || end == optarg || *end != '\0') {
+ errno = EINVAL;
+ perror("Invalid -s size");
+ exit_usage();
+ }
+ if (tmp == 0) {
+ errno = EINVAL;
+ perror("size not found");
+ exit_usage();
+ }
+ size = (size_t)tmp;
break;
case 'p':
strncpy(path, optarg, sizeof(path) - 1);
@@ -131,7 +144,7 @@ int main(int argc, char **argv)
}
if (size != 0) {
- printf("Writing this size: %d\n", size);
+ printf("Writing this size: %zu\n", size);
} else {
errno = EINVAL;
perror("size not found");
--
2.49.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH 1/3] selftests/mm/write_to_hugetlbfs: parse -s with strtoull and use size_t
2025-12-20 11:16 ` [PATCH 1/3] selftests/mm/write_to_hugetlbfs: parse -s with strtoull and use size_t Li Wang
@ 2025-12-20 18:58 ` Andrew Morton
0 siblings, 0 replies; 5+ messages in thread
From: Andrew Morton @ 2025-12-20 18:58 UTC (permalink / raw)
To: Li Wang
Cc: linux-kselftest, linux-kernel, linux-mm, David Hildenbrand,
Mark Brown, Shuah Khan, Waiman Long
On Sat, 20 Dec 2025 19:16:43 +0800 Li Wang <liwang@redhat.com> wrote:
> write_to_hugetlbfs currently parses the -s size argument with atoi()
> into an int. This silently accepts malformed input, cannot report overflow,
> and can truncate large sizes.
>
> --- Error log ---
> # uname -r
> 6.12.0-xxx.el10.aarch64+64k
>
> # ls /sys/kernel/mm/hugepages/hugepages-*
> hugepages-16777216kB/ hugepages-2048kB/ hugepages-524288kB/
>
> #./charge_reserved_hugetlb.sh -cgroup-v2
> # -----------------------------------------
> ...
> # nr hugepages = 10
> # writing cgroup limit: 5368709120
> # writing reseravation limit: 5368709120
Can we fix that typo while we're in there? "reservation".
> ...
> # Writing to this path: /mnt/huge/test
> # Writing this size: -1610612736 <--------
>
> Switch size to size_t and parse -s using strtoull() with proper validation.
> Also print the size using %zu.
>
> This makes the test utility more robust and avoids undefined/incorrect
> behavior with large or invalid -s values.
>
> ...
>
> --- a/tools/testing/selftests/mm/write_to_hugetlbfs.c
> +++ b/tools/testing/selftests/mm/write_to_hugetlbfs.c
> @@ -68,7 +68,7 @@ int main(int argc, char **argv)
> int key = 0;
> int *ptr = NULL;
> int c = 0;
> - int size = 0;
> + size_t size = 0;
> char path[256] = "";
> enum method method = MAX_METHOD;
> int want_sleep = 0, private = 0;
> @@ -86,7 +86,20 @@ int main(int argc, char **argv)
> while ((c = getopt(argc, argv, "s:p:m:owlrn")) != -1) {
> switch (c) {
> case 's':
> - size = atoi(optarg);
> + errno = 0;
> + char *end = NULL;
> + unsigned long long tmp = strtoull(optarg, &end, 10);
Coding-style nits: we do accept c99-style definitions nowadays but I do
think our eyes prefer the less surprising "definitions come before
code" style. So the above could be
char *end = NULL;
unsigned long long tmp = strtoull(optarg, &end, 10);
errno = 0;
Also, `errno' belongs to libc. It seems wrong to be altering it from
within our client code.
> + if (errno || end == optarg || *end != '\0') {
> + errno = EINVAL;
> + perror("Invalid -s size");
> + exit_usage();
> + }
> + if (tmp == 0) {
> + errno = EINVAL;
> + perror("size not found");
> + exit_usage();
> + }
> + size = (size_t)tmp;
> break;
I'm not really clear on what problems we're trying to solve here, but
this all seems like a lot of fuss. Can we just do
if (sscanf(optarg, "%zu", &size) != 1)
?
> case 'p':
> strncpy(path, optarg, sizeof(path) - 1);
> @@ -131,7 +144,7 @@ int main(int argc, char **argv)
> }
>
> if (size != 0) {
> - printf("Writing this size: %d\n", size);
> + printf("Writing this size: %zu\n", size);
> } else {
> errno = EINVAL;
> perror("size not found");
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 2/3] selftests/mm/charge_reserved_hugetlb.sh: add waits with timeout helper
2025-12-20 11:16 [PATCH 0/3] selftests/mm: hugetlb cgroup charging: robustness fixes Li Wang
2025-12-20 11:16 ` [PATCH 1/3] selftests/mm/write_to_hugetlbfs: parse -s with strtoull and use size_t Li Wang
@ 2025-12-20 11:16 ` Li Wang
2025-12-20 11:16 ` [PATCH 3/3] selftests/mm/charge_reserved_hugetlb: fix hugetlbfs mount size for large hugepages Li Wang
2 siblings, 0 replies; 5+ messages in thread
From: Li Wang @ 2025-12-20 11:16 UTC (permalink / raw)
To: linux-kselftest, akpm, linux-kernel, linux-mm
Cc: David Hildenbrand, Mark Brown, Shuah Khan, Waiman Long
The hugetlb cgroup usage wait loops in charge_reserved_hugetlb.sh were
unbounded and could hang forever if the expected cgroup file value never
appears (e.g. due to bugs, timing issues, or unexpected behavior).
--- Error log ---
# uname -r
6.12.0-xxx.el10.aarch64+64k
# ls /sys/kernel/mm/hugepages/hugepages-*
hugepages-16777216kB/ hugepages-2048kB/ hugepages-524288kB/
#./charge_reserved_hugetlb.sh -cgroup-v2
# -----------------------------------------
...
# nr hugepages = 10
# writing cgroup limit: 5368709120
# writing reseravation limit: 5368709120
...
# write_to_hugetlbfs: Error mapping the file: Cannot allocate memory
# Waiting for hugetlb memory reservation to reach size 2684354560.
# 0
# Waiting for hugetlb memory reservation to reach size 2684354560.
# 0
# Waiting for hugetlb memory reservation to reach size 2684354560.
# 0
# Waiting for hugetlb memory reservation to reach size 2684354560.
# 0
# Waiting for hugetlb memory reservation to reach size 2684354560.
# 0
# Waiting for hugetlb memory reservation to reach size 2684354560.
# 0
...
Introduce a small helper, wait_for_file_value(), and use it for:
- waiting for reservation usage to drop to 0,
- waiting for reservation usage to reach a given size,
- waiting for fault usage to reach a given size.
This makes the waits consistent and adds a hard timeout (120 tries with
0.5s sleep) so the test fails instead of stalling indefinitely.
Signed-off-by: Li Wang <liwang@redhat.com>
Cc: David Hildenbrand <david@kernel.org>
Cc: Mark Brown <broonie@kernel.org>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Waiman Long <longman@redhat.com>
---
.../selftests/mm/charge_reserved_hugetlb.sh | 45 ++++++++++---------
1 file changed, 25 insertions(+), 20 deletions(-)
diff --git a/tools/testing/selftests/mm/charge_reserved_hugetlb.sh b/tools/testing/selftests/mm/charge_reserved_hugetlb.sh
index e1fe16bcbbe8..6aa4ce66922c 100755
--- a/tools/testing/selftests/mm/charge_reserved_hugetlb.sh
+++ b/tools/testing/selftests/mm/charge_reserved_hugetlb.sh
@@ -112,41 +112,46 @@ function setup_cgroup() {
fi
}
+function wait_for_file_value() {
+ local path="$1"
+ local expect="$2"
+ local max_tries="120"
+
+ local i cur
+ for ((i=1; i<=max_tries; i++)); do
+ cur="$(cat "$path")"
+ if [[ "$cur" == "$expect" ]]; then
+ return 0
+ fi
+ echo "Waiting for $path to become '$expect' (current: '$cur') (try $i/$max_tries)"
+ sleep 0.5
+ done
+
+ echo "ERROR: timeout waiting for $path to become '$expect' (last: '$cur')"
+ return 1
+}
+
function wait_for_hugetlb_memory_to_get_depleted() {
local cgroup="$1"
local path="$cgroup_path/$cgroup/hugetlb.${MB}MB.$reservation_usage_file"
- # Wait for hugetlbfs memory to get depleted.
- while [ $(cat $path) != 0 ]; do
- echo Waiting for hugetlb memory to get depleted.
- cat $path
- sleep 0.5
- done
+
+ wait_for_file_value "$path" "0"
}
function wait_for_hugetlb_memory_to_get_reserved() {
local cgroup="$1"
local size="$2"
-
local path="$cgroup_path/$cgroup/hugetlb.${MB}MB.$reservation_usage_file"
- # Wait for hugetlbfs memory to get written.
- while [ $(cat $path) != $size ]; do
- echo Waiting for hugetlb memory reservation to reach size $size.
- cat $path
- sleep 0.5
- done
+
+ wait_for_file_value "$path" "$size"
}
function wait_for_hugetlb_memory_to_get_written() {
local cgroup="$1"
local size="$2"
-
local path="$cgroup_path/$cgroup/hugetlb.${MB}MB.$fault_usage_file"
- # Wait for hugetlbfs memory to get written.
- while [ $(cat $path) != $size ]; do
- echo Waiting for hugetlb memory to reach size $size.
- cat $path
- sleep 0.5
- done
+
+ wait_for_file_value "$path" "$size"
}
function write_hugetlbfs_and_get_usage() {
--
2.49.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH 3/3] selftests/mm/charge_reserved_hugetlb: fix hugetlbfs mount size for large hugepages
2025-12-20 11:16 [PATCH 0/3] selftests/mm: hugetlb cgroup charging: robustness fixes Li Wang
2025-12-20 11:16 ` [PATCH 1/3] selftests/mm/write_to_hugetlbfs: parse -s with strtoull and use size_t Li Wang
2025-12-20 11:16 ` [PATCH 2/3] selftests/mm/charge_reserved_hugetlb.sh: add waits with timeout helper Li Wang
@ 2025-12-20 11:16 ` Li Wang
2 siblings, 0 replies; 5+ messages in thread
From: Li Wang @ 2025-12-20 11:16 UTC (permalink / raw)
To: linux-kselftest, akpm, linux-kernel, linux-mm
Cc: David Hildenbrand, Mark Brown, Shuah Khan, Waiman Long
charge_reserved_hugetlb.sh mounts a hugetlbfs instance at /mnt/huge with
a fixed size of 256M. On systems with large base hugepages (e.g. 512MB),
this is smaller than a single hugepage, so the hugetlbfs mount ends up
with effectively zero capacity (often visible as size=0 in mount output).
As a result, write_to_hugetlbfs fails with ENOMEM and the test can hang
waiting for progress.
--- Error log ---
# uname -r
6.12.0-xxx.el10.aarch64+64k
#./charge_reserved_hugetlb.sh -cgroup-v2
# -----------------------------------------
...
# nr hugepages = 10
# writing cgroup limit: 5368709120
# writing reseravation limit: 5368709120
...
# write_to_hugetlbfs: Error mapping the file: Cannot allocate memory
# Waiting for hugetlb memory reservation to reach size 2684354560.
# 0
# Waiting for hugetlb memory reservation to reach size 2684354560.
# 0
...
# mount |grep /mnt/huge
none on /mnt/huge type hugetlbfs (rw,relatime,seclabel,pagesize=512M,size=0)
# grep -i huge /proc/meminfo
...
HugePages_Total: 10
HugePages_Free: 10
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 524288 kB
Hugetlb: 5242880 kB
Mount hugetlbfs with size=${size}, the number of bytes the test will
reserve/write, so the filesystem capacity is sufficient regardless of
HugeTLB page size.
Signed-off-by: Li Wang <liwang@redhat.com>
Cc: David Hildenbrand <david@kernel.org>
Cc: Mark Brown <broonie@kernel.org>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Waiman Long <longman@redhat.com>
---
tools/testing/selftests/mm/charge_reserved_hugetlb.sh | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/mm/charge_reserved_hugetlb.sh b/tools/testing/selftests/mm/charge_reserved_hugetlb.sh
index 6aa4ce66922c..9deb3dc2cbce 100755
--- a/tools/testing/selftests/mm/charge_reserved_hugetlb.sh
+++ b/tools/testing/selftests/mm/charge_reserved_hugetlb.sh
@@ -295,7 +295,7 @@ function run_test() {
setup_cgroup "hugetlb_cgroup_test" "$cgroup_limit" "$reservation_limit"
mkdir -p /mnt/huge
- mount -t hugetlbfs -o pagesize=${MB}M,size=256M none /mnt/huge
+ mount -t hugetlbfs -o pagesize=${MB}M,size=${size} none /mnt/huge
write_hugetlbfs_and_get_usage "hugetlb_cgroup_test" "$size" "$populate" \
"$write" "/mnt/huge/test" "$method" "$private" "$expect_failure" \
@@ -349,7 +349,7 @@ function run_multiple_cgroup_test() {
setup_cgroup "hugetlb_cgroup_test2" "$cgroup_limit2" "$reservation_limit2"
mkdir -p /mnt/huge
- mount -t hugetlbfs -o pagesize=${MB}M,size=256M none /mnt/huge
+ mount -t hugetlbfs -o pagesize=${MB}M,size=${size} none /mnt/huge
write_hugetlbfs_and_get_usage "hugetlb_cgroup_test1" "$size1" \
"$populate1" "$write1" "/mnt/huge/test1" "$method" "$private" \
--
2.49.0
^ permalink raw reply related [flat|nested] 5+ messages in thread