All of lore.kernel.org
 help / color / mirror / Atom feed
From: Li Wang via ltp <ltp@lists.linux.it>
To: ltp@lists.linux.it
Subject: [LTP] [PATCH] mmap22: Improve MAP_DROPPABLE test stability using mincore()
Date: Wed, 17 Sep 2025 15:57:29 +0800	[thread overview]
Message-ID: <20250917075729.30093-1-liwang@redhat.com> (raw)

The current mmap22 test validates MAP_DROPPABLE by writing to the
allocated memory and checking for zero-filled pages under memory
pressure. However, this approach is unreliable because:

  - Child process memory pressure (malloc + single writes) may not
    reliably trigger cgroup memory reclaim.
  - Checking memory content (alloc[i] == 0) is insufficient to
    confirm kernel reclamation, as pages may remain resident but not
    overwritten.
  - Race conditions during child cleanup could leave residual cgroup
    processes.

Error logs:

   command: mmap22
   tst_tmpdir.c:316: TINFO: Using /tmp/LTP_mmaxrtyKb as tmpdir (xfs filesystem)
   tst_test.c:1953: TINFO: LTP version: 20250530
   tst_kconfig.c:88: TINFO: Parsing kernel config '/lib/modules/6.12.0-130.1445_2041086229.el10.x86_64+rt/build/.config'
   tst_test.c:1774: TINFO: Overall timeout per run is 0h 05m 54s
   tst_test.c:1837: TINFO: Killed the leftover descendant processes
   tst_test.c:1846: TINFO: If you are running on slow machine, try exporting LTP_TIMEOUT_MUL > 1
   tst_test.c:1848: TBROK: Test killed! (timeout?)
   tst_cgroup.c:1043: TBROK: unlinkat(5</sys/fs/cgroup/ltp>, 'test-92902', AT_REMOVEDIR): EBUSY (16)
   ...

This patch improves the test in the following ways:

  * Use mincore() to precisely detect if MAP_DROPPABLE pages have
    been reclaimed by the kernel.
  * Replace the old child loop with a stronger memory pressure loop
    (malloc + memset), ensuring cgroup limits are hit quickly.
  * Use SAFE_KILL + SAFE_WAITPID for robust child cleanup.
  * Extend runtime and add short sleeps to reduce busy looping and
    stabilize test results.
  * Record page size during setup for consistent use across functions.

As a result, the test becomes more stable, deterministic, and easier
to reproduce under different kernels and configurations.

Signed-off-by: Li Wang <liwang@redhat.com>
---
 testcases/kernel/syscalls/mmap/mmap22.c | 78 ++++++++++++++++---------
 1 file changed, 52 insertions(+), 26 deletions(-)

diff --git a/testcases/kernel/syscalls/mmap/mmap22.c b/testcases/kernel/syscalls/mmap/mmap22.c
index 1507fdfa7..b9db8e1b6 100644
--- a/testcases/kernel/syscalls/mmap/mmap22.c
+++ b/testcases/kernel/syscalls/mmap/mmap22.c
@@ -9,12 +9,19 @@
  * Test mmap(2) with MAP_DROPPABLE flag.
  *
  * Test base on kernel selftests/mm/droppable.c
+ *
+ * Ensure that memory allocated with MAP_DROPPABLE can be reclaimed
+ * under memory pressure within a cgroup.
  */
 
 #define _GNU_SOURCE
 #include <errno.h>
 #include <stdio.h>
 #include <sys/types.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/wait.h>
 #include "tst_test.h"
 #include "lapi/mmap.h"
 
@@ -22,13 +29,24 @@
 #define ALLOC_SIZE (128 * TST_MB)
 
 static struct tst_cg_group *cg_child;
+static pid_t child;
+static int page_size;
+
+static void stress_child(void)
+{
+	for (;;) {
+		char *buf = malloc(page_size);
+		if (!buf)
+			exit(1);
+		memset(buf, 'B', page_size);
+	}
+}
 
 static void test_mmap(void)
 {
-	size_t alloc_size = ALLOC_SIZE;
-	size_t page_size = getpagesize();
 	char *alloc;
-	pid_t child;
+	unsigned char *vec;
+	size_t npages = ALLOC_SIZE / page_size;
 
 	cg_child = tst_cg_group_mk(tst_cg, "child");
 	SAFE_CG_PRINTF(tst_cg, "memory.max", "%d", MEM_LIMIT);
@@ -38,38 +56,45 @@ static void test_mmap(void)
 		SAFE_CG_PRINTF(tst_cg, "memory.swap.max", "%d", MEM_LIMIT);
 	SAFE_CG_PRINTF(cg_child, "cgroup.procs", "%d", getpid());
 
-	alloc = SAFE_MMAP(0, alloc_size, PROT_READ | PROT_WRITE,
+	alloc = SAFE_MMAP(0, ALLOC_SIZE, PROT_READ | PROT_WRITE,
 			MAP_ANONYMOUS | MAP_DROPPABLE, -1, 0);
 
-	memset(alloc, 'A', alloc_size);
-	for (size_t i = 0; i < alloc_size; i += page_size) {
-		if (alloc[i]  != 'A')
-			tst_res(TFAIL, "memset failed");
-	}
+	memset(alloc, 'A', ALLOC_SIZE);
+
+	vec = SAFE_MALLOC(npages);
 
 	child = SAFE_FORK();
-	if (!child) {
-		for (;;)
-			*(char *)malloc(page_size) = 'B';
-	}
+	if (!child)
+		stress_child();
 
-	while (1) {
-		for (size_t i = 0; i < alloc_size; i += page_size) {
-			if (!tst_remaining_runtime()) {
-				tst_res(TFAIL, "MAP_DROPPABLE did not drop memory within the timeout period.");
-				goto kill_child;
-			}
-			if (!alloc[i]) {
-				tst_res(TPASS, "MAP_DROPPABLE test pass.");
-				goto kill_child;
+	for (;;) {
+		if (!tst_remaining_runtime()) {
+			tst_res(TFAIL, "MAP_DROPPABLE did not drop pages within timeout");
+			goto cleanup;
+		}
+
+		if (mincore(alloc, ALLOC_SIZE, vec) == -1)
+			tst_brk(TBROK | TERRNO, "mincore failed");
+
+		for (size_t i = 0; i < npages; i++) {
+			if (!(vec[i] & 1)) {
+				tst_res(TPASS, "MAP_DROPPABLE page reclaimed by kernel");
+				goto cleanup;
 			}
 		}
+
+		usleep(100000);
 	}
 
-kill_child:
-	SAFE_KILL(child, SIGKILL);
-	SAFE_WAITPID(child, NULL, 0);
-	SAFE_MUNMAP(alloc, alloc_size);
+cleanup:
+	if (child > 0) {
+		SAFE_KILL(child, SIGKILL);
+		SAFE_WAITPID(child, NULL, 0);
+	}
+	SAFE_MUNMAP(alloc, ALLOC_SIZE);
+	free(vec);
+	SAFE_CG_PRINTF(tst_cg_drain, "cgroup.procs", "%d", getpid());
+	cg_child = tst_cg_group_rm(cg_child);
 }
 
 static void setup(void)
@@ -84,6 +109,7 @@ static void setup(void)
 		tst_brk(TBROK | TERRNO, "mmap() MAP_DROPPABLE failed");
 
 	SAFE_MUNMAP(addr, 1);
+	page_size = getpagesize();
 }
 
 static void cleanup(void)
-- 
2.51.0


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

             reply	other threads:[~2025-09-17  7:58 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-09-17  7:57 Li Wang via ltp [this message]
2025-09-23 11:07 ` [LTP] [PATCH] mmap22: Improve MAP_DROPPABLE test stability using mincore() Petr Vorel
2025-09-24  0:43   ` Li Wang via ltp

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250917075729.30093-1-liwang@redhat.com \
    --to=ltp@lists.linux.it \
    --cc=liwang@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.