All of lore.kernel.org
 help / color / mirror / Atom feed
* [LTP] [PATCH v5] hugetlb/hugeshmat: Add hugeshmat06 migrated from libhugetlbfs shm-perms
@ 2026-08-20 12:55 Samir Mulani
  2026-08-20 18:40 ` [LTP] " linuxtestproject.agent
  0 siblings, 1 reply; 2+ messages in thread
From: Samir Mulani @ 2026-08-20 12:55 UTC (permalink / raw)
  To: ltp; +Cc: liwang, Samir Mulani

Test shared memory behavior when multiple processes attach to a
hugepage-backed segment with different permissions.

At one point, reservation accounting of free hugepages between the
parent and child processes may become inconsistent during memory
operations. The parent creates a shared memory segment backed by
4 hugepages (permission 0640), attaches it read-write, initialises
each hugepage with a pattern (0x55), then detaches. Child processes
are forked in a loop, each reattaching the segment read-only via
SHM_RDONLY, verifying the data pattern, detaching, and exiting.

If the reservation accounting leaks, repeated read-only attaches
will exhaust the hugepage pool and shmat() will fail. The test
uses raw shmat() in each child and reports this failure as TFAIL.

Signed-off-by: Samir Mulani <samir@linux.ibm.com>
---
Changes in v5:
 1. Use raw shmat() instead of SAFE_SHMAT() and report pool
    exhaustion as TFAIL. HugetlbPages from /proc/<pid>/status
    only tracks mapped pages and can return zero after shmdt()
    even when resv_huge_pages is still leaked, so it is not a
    reliable oracle for this regression. [LTP AI Reviewer]
 2. Remove get_proc_hugetlb_kb() helper and the HugetlbPages
    check as they are no longer needed. [LTP AI Reviewer]
 3. Use IPC_PRIVATE instead of a fixed SEGMENT_KEY to avoid
    accidentally reusing or destroying a pre-existing segment.
    [LTP AI Reviewer]
 4. Drop the deprecated [Description] tag from the /*\ block.
    [LTP AI Reviewer]

Link: https://lore.kernel.org/ltp/49b1dbd9-4c51-414a-806c-1d5cc6b5e1c7@linux.ibm.com/ # v3 
Link: https://lore.kernel.org/ltp/20260820042516.46631-1-samir@linux.ibm.com/ # v4

 runtest/hugetlb                               |   1 +
 testcases/kernel/mem/.gitignore               |   1 +
 .../mem/hugetlb/hugeshmat/hugeshmat06.c       | 152 ++++++++++++++++++
 3 files changed, 154 insertions(+)
 create mode 100644 testcases/kernel/mem/hugetlb/hugeshmat/hugeshmat06.c

diff --git a/runtest/hugetlb b/runtest/hugetlb
index 6b35c1f42..1eb5c3339 100644
--- a/runtest/hugetlb
+++ b/runtest/hugetlb
@@ -49,6 +49,7 @@ hugeshmat02 hugeshmat02 -i 5
 hugeshmat03 hugeshmat03 -i 5
 hugeshmat04 hugeshmat04 -i 5
 hugeshmat05 hugeshmat05 -i 5
+hugeshmat06 hugeshmat06 -i 5
 
 hugeshmctl01 hugeshmctl01 -i 5
 hugeshmctl02 hugeshmctl02 -i 5
diff --git a/testcases/kernel/mem/.gitignore b/testcases/kernel/mem/.gitignore
index e63a6dde7..704f89d5e 100644
--- a/testcases/kernel/mem/.gitignore
+++ b/testcases/kernel/mem/.gitignore
@@ -45,6 +45,7 @@
 /hugetlb/hugeshmat/hugeshmat03
 /hugetlb/hugeshmat/hugeshmat04
 /hugetlb/hugeshmat/hugeshmat05
+/hugetlb/hugeshmat/hugeshmat06
 /hugetlb/hugeshmctl/hugeshmctl01
 /hugetlb/hugeshmctl/hugeshmctl02
 /hugetlb/hugeshmctl/hugeshmctl03
diff --git a/testcases/kernel/mem/hugetlb/hugeshmat/hugeshmat06.c b/testcases/kernel/mem/hugetlb/hugeshmat/hugeshmat06.c
new file mode 100644
index 000000000..440d85672
--- /dev/null
+++ b/testcases/kernel/mem/hugetlb/hugeshmat/hugeshmat06.c
@@ -0,0 +1,152 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2005-2006 IBM Corporation.
+ * Author: David Gibson & Adam Litke
+ */
+
+/*\
+ * Tests shared memory behavior when multiple processes attach to a
+ * hugepage-backed segment with different permissions.
+ *
+ * The parent creates a shared memory segment (permission 0640) backed by
+ * hugepages, attaches it read-write, initialises each hugepage with a
+ * pattern (0x55), then detaches.  A number of child processes are then
+ * forked; each child reattaches the segment read-only (SHM_RDONLY),
+ * verifies the expected pattern in every hugepage, detaches, and exits.
+ *
+ * The original libhugetlbfs shm-perms regression leaked resv_huge_pages
+ * on each read-only attach, eventually exhausting the hugepage reservation
+ * pool.  This is detected by using raw shmat() in each child so that a
+ * pool-exhaustion failure is reported as TFAIL rather than TBROK.
+ */
+
+#include "hugetlb.h"
+#include "tst_safe_sysv_ipc.h"
+
+#define MNTPOINT	"hugetlbfs/"
+#define HPAGES_IN_SEG	4
+#define PATTERN		0x55
+#define MAX_CHILDREN	128
+
+static int global_shmid = -1;
+static long hpage_size;
+static long segment_size;
+
+static void setup(void)
+{
+	int shmid;
+	char *p;
+	int i;
+
+	hpage_size = tst_get_hugepage_size();
+	if (!hpage_size)
+		tst_brk(TCONF, "Hugepages are not supported");
+
+	segment_size = HPAGES_IN_SEG * hpage_size;
+
+	/* Create the hugepage SHM segment with 0640 permissions */
+	shmid = SAFE_SHMGET(IPC_PRIVATE, segment_size,
+			    IPC_CREAT | SHM_HUGETLB | 0640);
+	global_shmid = shmid;
+
+	/* Attach read-write, write a known pattern into each hugepage */
+	p = SAFE_SHMAT(shmid, NULL, 0);
+
+	for (i = 0; i < HPAGES_IN_SEG; i++)
+		memset(p + (i * hpage_size), PATTERN, hpage_size);
+
+	SAFE_SHMDT((const void *)p);
+}
+
+static void cleanup(void)
+{
+	if (global_shmid >= 0)
+		SAFE_SHMCTL(global_shmid, IPC_RMID, NULL);
+}
+
+static void run_test(void)
+{
+	int i, iterations;
+	pid_t pid;
+
+	/*
+	 * Number of attach/detach cycles to exercise reservation accounting.
+	 * Use tst_hugepages (reserved by the framework) but cap at
+	 * MAX_CHILDREN to avoid spawning an unreasonable number of children
+	 * on large-memory machines.
+	 */
+	iterations = MIN((long)tst_hugepages, (long)MAX_CHILDREN);
+
+	tst_res(TINFO, "Running %d child attach/detach iterations", iterations);
+
+	for (i = 0; i < iterations; i++) {
+		pid = SAFE_FORK();
+		if (pid == 0) {
+			/* ---- child ---- */
+			char *shmaddr;
+			int j;
+
+			/*
+			 * Use raw shmat() instead of SAFE_SHMAT() so that a
+			 * failure caused by resv_huge_pages exhaustion is
+			 * reported as TFAIL, not TBROK.
+			 */
+			shmaddr = shmat(global_shmid, NULL, SHM_RDONLY);
+			if (shmaddr == (void *)-1) {
+				tst_res(TFAIL | TERRNO,
+					"Child %d: shmat() failed, hugepage reservation pool may be exhausted",
+					getpid());
+				exit(EXIT_FAILURE);
+			}
+
+			tst_res(TINFO, "Child %d attached segment successfully",
+				getpid());
+
+			/* Verify the pattern written by the parent */
+			for (j = 0; j < HPAGES_IN_SEG; j++) {
+				unsigned char val =
+					*((unsigned char *)shmaddr +
+					  (j * hpage_size));
+
+				if (val != PATTERN) {
+					tst_res(TFAIL,
+						"Child %d: hugepage[%d] data mismatch: got 0x%02x, expected 0x%02x",
+						getpid(), j, (unsigned int)val, PATTERN);
+					SAFE_SHMDT((const void *)shmaddr);
+					exit(EXIT_FAILURE);
+				}
+			}
+
+			SAFE_SHMDT((const void *)shmaddr);
+			exit(EXIT_SUCCESS);
+		}
+	}
+
+	/*
+	 * Wait for all children.  tst_reap_children() calls tst_brk(TBROK)
+	 * if any child exited non-zero, so a TFAIL inside a child is
+	 * automatically promoted to a test-level failure here.
+	 */
+	tst_reap_children();
+
+	tst_res(TPASS,
+		"All %d children attached read-only and verified reservation accounting",
+		iterations);
+}
+
+static struct tst_test test = {
+	.needs_root	 = 1,
+	.mntpoint	 = MNTPOINT,
+	.needs_hugetlbfs = 1,
+	.needs_tmpdir	 = 1,
+	.forks_child	 = 1,
+	.setup		 = setup,
+	.cleanup	 = cleanup,
+	.test_all	 = run_test,
+	/*
+	 * Request HPAGES_IN_SEG hugepages; that is all the test needs.
+	 * TST_NEEDS means the test is skipped if the kernel cannot
+	 * provide them.
+	 */
+	.hugepages	 = {HPAGES_IN_SEG, TST_NEEDS},
+};
-- 
2.52.0


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

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [LTP] hugetlb/hugeshmat: Add hugeshmat06 migrated from libhugetlbfs shm-perms
  2026-08-20 12:55 [LTP] [PATCH v5] hugetlb/hugeshmat: Add hugeshmat06 migrated from libhugetlbfs shm-perms Samir Mulani
@ 2026-08-20 18:40 ` linuxtestproject.agent
  0 siblings, 0 replies; 2+ messages in thread
From: linuxtestproject.agent @ 2026-08-20 18:40 UTC (permalink / raw)
  To: Samir Mulani; +Cc: ltp

Hi Samir,

On Aug 20, 2026, Samir Mulani wrote:
> hugetlb/hugeshmat: Add hugeshmat06 migrated from libhugetlbfs shm-perms

> #define HPAGES_IN_SEG	4
> #define MAX_CHILDREN	128
>
> 	iterations = MIN((long)tst_hugepages, (long)MAX_CHILDREN);

Could the iteration count retain the original test's exhaustion guarantee?
Each leaked attach reserves HPAGES_IN_SEG pages, so a pool containing N
hugepages requires more than N / HPAGES_IN_SEG attaches to expose the leak.
The original test calculated that value plus one.

With this cap, one execution can pass without detecting the bug when the pool
contains 512 or more hugepages. Even the "-i 5" runtest entry is insufficient
at 2560 or more. Could the count instead be derived from the pool and segment
sizes, including the final attach that exceeds the pool?

> 			if (shmaddr == (void *)-1) {
> 				tst_res(TFAIL | TERRNO,
> 					"Child %d: shmat() failed, hugepage reservation pool may be exhausted",
> 					getpid());
> 				exit(EXIT_FAILURE);
> 			}

Could the child exit successfully after reporting TFAIL?
tst_reap_children() converts this nonzero status into an additional TBROK
("Invalid child exit value") and aborts the parent. LTP already propagates the
child's tst_res() result, so the regression should remain a TFAIL rather than
also becoming a broken-test result.

> static struct tst_test test = {
> 	.needs_root	 = 1,

This is described as a regression test, but the test has no .tags entry.
Could the corresponding linux-git regression fix tag be added?

> +/hugetlb/hugeshmat/hugeshmat06

Could this binary instead be ignored by
testcases/kernel/mem/hugetlb/hugeshmat/.gitignore as /hugeshmat06? New test
binaries should use a leaf-directory .gitignore rather than the shared
testcases/kernel/mem/.gitignore.

> /*\
>  * Tests shared memory behavior when multiple processes attach to a
>  * hugepage-backed segment with different permissions.

Could the exported description explain why root is required? The test sets
.needs_root because the framework adjusts the hugepage pool and mounts
hugetlbfs.

>  * pool.  This is detected by using raw shmat() in each child so that a

Could shmat() use the ":manpage:`shmat(2)`" role here? Syscalls in exported
test descriptions should use their man-page role.

Verdict - Needs revision

---
Note:

The agent can sometimes produce false positives although often its
findings are genuine. If you find issues with the review, please
comment this email or ignore the suggestions.

Regards,
LTP AI Reviewer

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

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-08-20 18:40 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-20 12:55 [LTP] [PATCH v5] hugetlb/hugeshmat: Add hugeshmat06 migrated from libhugetlbfs shm-perms Samir Mulani
2026-08-20 18:40 ` [LTP] " linuxtestproject.agent

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.