[PATCH v2 04/13] selftest/mm: fix cgroup task placement and tolerance in hugetlb_reparenting_test.sh

Sayali Patil
2026-03-12T12:26:28Z

Launch write_to_hugetlbfs as a separate process and move only its PID
into the target cgroup before waiting for completion. This avoids moving
the test shell itself, prevents unintended charging to the shell, and
ensures hugetlb and memcg accounting is attributed only to the intended
workload.

Add a short delay before the hugetlb allocation to avoid a race where
memory may be charged before the task migration takes effect, which
can lead to incorrect accounting and intermittent test failures.

Also increase the assert_with_retry() tolerance from 7MB to 8MB. With
MEMCG_CHARGE_BATCH=64U and a 64K base page size, per-CPU batching can
result in up to 8MB of temporary charge being attributed to the parent.
The previous 7MB threshold could be exceeded, causing false failures;
raise the limit to cover the maximum expected batched charge.

Fixes: 29750f71a9b4 ("hugetlb_cgroup: add hugetlb_cgroup reservation tests")
Signed-off-by: Sayali Patil <sayalip@linux.ibm.com>
---
.../selftests/mm/hugetlb_reparenting_test.sh | 17 ++++++++---------
tools/testing/selftests/mm/write_to_hugetlbfs.c | 5 ++++-
2 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/tools/testing/selftests/mm/hugetlb_reparenting_test.sh b/tools/testing/selftests/mm/hugetlb_reparenting_test.sh
index 073a71fa36b4..9c79ad69e4c6 100755
--- a/tools/testing/selftests/mm/hugetlb_reparenting_test.sh
+++ b/tools/testing/selftests/mm/hugetlb_reparenting_test.sh
@@ -70,7 +70,7 @@ function cleanup() {
function assert_with_retry() {
local actual_path="$1"
local expected="$2"
- local tolerance=$((7 * 1024 * 1024))
+ local tolerance=$((8 * 1024 * 1024))
local timeout=20
local interval=1
local start_time
@@ -153,18 +153,17 @@ write_hugetlbfs() {
local size="$3"

if [[ $cgroup2 ]]; then
- echo $$ >$CGROUP_ROOT/$cgroup/cgroup.procs
+ cg_file="$CGROUP_ROOT/$cgroup/cgroup.procs"
else
echo 0 >$CGROUP_ROOT/$cgroup/cpuset.mems
echo 0 >$CGROUP_ROOT/$cgroup/cpuset.cpus
- echo $$ >"$CGROUP_ROOT/$cgroup/tasks"
- fi
- ./write_to_hugetlbfs -p "$path" -s "$size" -m 0 -o
- if [[ $cgroup2 ]]; then
- echo $$ >$CGROUP_ROOT/cgroup.procs
- else
- echo $$ >"$CGROUP_ROOT/tasks"
+ cg_file="$CGROUP_ROOT/$cgroup/tasks"
fi
+
+ # Spawn write_to_hugetlbfs in a separate task to ensure correct cgroup accounting
+ ./write_to_hugetlbfs -p "$path" -s "$size" -m 0 -o -d & pid=$!
+ echo "$pid" > "$cg_file"
+ wait "$pid"
echo
}

diff --git a/tools/testing/selftests/mm/write_to_hugetlbfs.c b/tools/testing/selftests/mm/write_to_hugetlbfs.c
index ecb5f7619960..6b01b0485bd0 100644
--- a/tools/testing/selftests/mm/write_to_hugetlbfs.c
+++ b/tools/testing/selftests/mm/write_to_hugetlbfs.c
@@ -83,7 +83,7 @@ int main(int argc, char **argv)
setvbuf(stdout, NULL, _IONBF, 0);
self = argv[0];

- while ((c = getopt(argc, argv, "s:p:m:owlrn")) != -1) {
+ while ((c = getopt(argc, argv, "s:p:m:owlrnd")) != -1) {
switch (c) {
case 's':
if (sscanf(optarg, "%zu", &size) != 1) {
@@ -118,6 +118,9 @@ int main(int argc, char **argv)
case 'n':
reserve = 0;
break;
+ case 'd':
+ sleep(1);
+ break;
default:
errno = EINVAL;
perror("Invalid arg");
--
2.52.0