[LTP] [PATCH] [PATCH V2] memcg/memcontrol04: Fix race in pagecache allocation measurement
Pavithra
pavrampu@linux.ibm.com
Mon May 25 17:33:52 CEST 2026
The test was failing with memory.current values much lower than expected:
TFAIL: (A/B/C memory.current=6684672) ~= 34603008
TFAIL: (A/B/D memory.current=5373952) ~= 17825792
Root cause:
Child processes allocating pagecache were exiting immediately after
allocation (via tst_reap_children()), causing the pagecache to be
freed before the test could measure memory.current values.
Fix:
Modified alloc_pagecache_in_child() to keep children alive during test:
- Added TEST_DONE checkpoint for child lifecycle coordination
- Parent waits for CHILD_IDLE checkpoint before proceeding
- Child signals CHILD_IDLE after allocation and fsync
- Child waits for TEST_DONE to keep memory allocated during test
- Modified cleanup_sub_groups() to wake waiting children before cleanup
- Changed alloc_anon_in_child() to use SAFE_WAITPID() for specific child
- Added num_children_spawned tracking for accurate cleanup
Signed-off-by: Sachin Sant <sachinp@linux.ibm.com>
Signed-off-by: Pavithra <pavrampu@linux.ibm.com>
---
v2:
- Added num_children_spawned counter to track spawned children
- Fixed cleanup_sub_groups() to wake correct number of children
Link to v2: https://lore.kernel.org/ltp/20260427171734.621893-1-pavrampu@linux.ibm.com/
v1:
- Initial fix for child process lifecycle coordination
- Added TEST_DONE and CHILD_IDLE checkpoint synchronization
Link to v1: https://lore.kernel.org/ltp/20260330050105.258630-1-pavrampu@linux.ibm.com/
---
.../kernel/controllers/memcg/memcontrol04.c | 21 ++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/testcases/kernel/controllers/memcg/memcontrol04.c b/testcases/kernel/controllers/memcg/memcontrol04.c
index 715cc5bcd..15d8f891c 100644
--- a/testcases/kernel/controllers/memcg/memcontrol04.c
+++ b/testcases/kernel/controllers/memcg/memcontrol04.c
@@ -45,9 +45,11 @@
static struct tst_cg_group *trunk_cg[3];
static struct tst_cg_group *leaf_cg[4];
static int fd = -1;
+static unsigned int num_children_spawned;
enum checkpoints {
- CHILD_IDLE
+ CHILD_IDLE,
+ TEST_DONE,
};
enum trunk_cg {
@@ -67,6 +69,12 @@ static void cleanup_sub_groups(void)
{
size_t i;
+ if (num_children_spawned > 0) {
+ TST_CHECKPOINT_WAKE2(TEST_DONE, num_children_spawned);
+ tst_reap_children();
+ num_children_spawned = 0;
+ }
+
for (i = ARRAY_SIZE(leaf_cg); i > 0; i--) {
if (!leaf_cg[i - 1])
continue;
@@ -88,7 +96,7 @@ static void alloc_anon_in_child(const struct tst_cg_group *const cg,
const pid_t pid = SAFE_FORK();
if (pid) {
- tst_reap_children();
+ SAFE_WAITPID(pid, NULL, 0);
return;
}
@@ -107,7 +115,8 @@ static void alloc_pagecache_in_child(const struct tst_cg_group *const cg,
const pid_t pid = SAFE_FORK();
if (pid) {
- tst_reap_children();
+ num_children_spawned++;
+ TST_CHECKPOINT_WAIT(CHILD_IDLE);
return;
}
@@ -117,6 +126,11 @@ static void alloc_pagecache_in_child(const struct tst_cg_group *const cg,
getpid(), tst_cg_group_name(cg), size);
alloc_pagecache(fd, size);
+ SAFE_FSYNC(fd);
+
+ TST_CHECKPOINT_WAKE(CHILD_IDLE);
+ TST_CHECKPOINT_WAIT(TEST_DONE);
+
exit(0);
}
@@ -125,6 +139,7 @@ static void test_memcg_low(void)
long c[4];
unsigned int i;
+ num_children_spawned = 0;
fd = SAFE_OPEN(TMPDIR"/tmpfile", O_RDWR | O_CREAT, 0600);
trunk_cg[A] = tst_cg_group_mk(tst_cg, "trunk_A");
--
2.54.0
More information about the ltp
mailing list