* [LTP] [PATCH v4] hugetlb/hugeshmat: Add hugeshmat06 migrated from libhugetlbfs shm-perms
@ 2026-08-20 4:25 Samir Mulani
2026-08-20 10:33 ` [LTP] " linuxtestproject.agent
0 siblings, 1 reply; 2+ messages in thread
From: Samir Mulani @ 2026-08-20 4:25 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.
Per-process HugetlbPages: from /proc/<pid>/status is checked before
and after each child's attach/detach cycle. A non-zero value after
detach indicates a reservation accounting leak. Using a per-process
counter instead of the system-wide HugePages_Free: from /proc/meminfo
avoids false failures from concurrent hugepage users on the system.
Signed-off-by: Samir Mulani <samir@linux.ibm.com>
---
Changes in v4:
1. Replace HugePages_Free: (system-wide /proc/meminfo) with
HugetlbPages: (per-process /proc/<pid>/status) for reservation
accounting check to avoid false failures when other processes
use hugepages concurrently. [Cyril Hrubis]
2. Use tst_hugepages directly instead of re-reading
MEMINFO_HPAGE_TOTAL since the LTP framework already stores
the reserved count. [Li Wang]
3. Cap iteration count with MIN(tst_hugepages, MAX_CHILDREN)
instead of computing it from total hugepages * hpage_size
to avoid spawning excessive children on large-memory machines.
[Li Wang]
4. Reduce .hugepages request from 32 to HPAGES_IN_SEG (4) since
only 4 hugepages are ever needed. [Li Wang]
5. Move all child-local variables into the child process block to
fix variable aliasing between the outer fork loop index and the
inner hugepage read loop index. [Li Wang]
6. Add data coherence check: each child verifies every hugepage
contains the expected 0x55 pattern written by the parent,
since children attach with SHM_RDONLY. [Li Wang]
7. Move segment creation and pattern initialisation into setup()
to keep run_test() focused on attach/verify/detach/accounting.
8. Add TINFO message per child reporting successful attach.
[Li Wang]
9. Fix checkpatch.pl quoted string split across lines warnings.
Link:
https://lore.kernel.org/ltp/49b1dbd9-4c51-414a-806c-1d5cc6b5e1c7@linux.ibm.com/ # v3
runtest/hugetlb | 1 +
testcases/kernel/mem/.gitignore | 1 +
.../mem/hugetlb/hugeshmat/hugeshmat06.c | 187 ++++++++++++++++++
3 files changed, 189 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..b8c40cea0
--- /dev/null
+++ b/testcases/kernel/mem/hugetlb/hugeshmat/hugeshmat06.c
@@ -0,0 +1,187 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2005-2006 IBM Corporation.
+ * Author: David Gibson & Adam Litke
+ */
+
+/*\
+ * [Description]
+ *
+ * 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 test validates two things:
+ * 1. Per-process HugetlbPages accounting (from /proc/self/status) must
+ * return to zero after the child detaches — catching reservation-
+ * accounting leaks described in the original libhugetlbfs shm-perms
+ * test.
+ * 2. Read-only children can successfully read the data written by the
+ * parent (data coherence check).
+ *
+ * Using per-process /proc/self/status HugetlbPages: rather than the
+ * system-wide HugePages_Free: counter avoids false failures caused by
+ * concurrent users of hugepages on the system.
+ */
+
+#include "hugetlb.h"
+#include "tst_safe_sysv_ipc.h"
+
+#define SEGMENT_KEY (0x82ba15ff)
+#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;
+
+/*
+ * get_proc_hugetlb_kb - return HugetlbPages value (in kB) for a given pid
+ * as reported by /proc/<pid>/status.
+ */
+static long get_proc_hugetlb_kb(pid_t pid)
+{
+ return SAFE_READ_PROC_STATUS(pid, "HugetlbPages:");
+}
+
+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(SEGMENT_KEY, 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;
+ long hugetlb_before, hugetlb_after;
+ int j;
+
+ /*
+ * HugetlbPages should be 0 before we attach
+ * (no hugepages mapped in this fresh child).
+ */
+ hugetlb_before = get_proc_hugetlb_kb(getpid());
+ if (hugetlb_before != 0) {
+ tst_res(TWARN,
+ "Child %d: HugetlbPages before attach is %ld kB (expected 0)",
+ getpid(), hugetlb_before);
+ }
+
+ /* Re-open existing segment (size 0 = use existing) */
+ shmaddr = SAFE_SHMAT(global_shmid, NULL, SHM_RDONLY);
+
+ 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);
+
+ /*
+ * After detaching, HugetlbPages must drop back to 0.
+ * A non-zero value indicates a reservation accounting
+ * leak.
+ */
+ hugetlb_after = get_proc_hugetlb_kb(getpid());
+ if (hugetlb_after != 0) {
+ tst_res(TFAIL,
+ "Child %d: HugetlbPages after detach is %ld kB (expected 0), reservation accounting leak",
+ getpid(), hugetlb_after);
+ exit(EXIT_FAILURE);
+ }
+
+ 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 4:25 [LTP] [PATCH v4] hugetlb/hugeshmat: Add hugeshmat06 migrated from libhugetlbfs shm-perms Samir Mulani
@ 2026-08-20 10:33 ` linuxtestproject.agent
0 siblings, 0 replies; 2+ messages in thread
From: linuxtestproject.agent @ 2026-08-20 10:33 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
> hugetlb_after = get_proc_hugetlb_kb(getpid());
> if (hugetlb_after != 0) {
> tst_res(TFAIL,
> "Child %d: HugetlbPages after detach is %ld kB (expected 0), reservation accounting leak",
Could this use an oracle tied to reservation state instead? In Linux 7.2,
HugetlbPages reports mm->hugetlb_usage, which is incremented when a huge
page is mapped and decremented when it is unmapped. The original regression
leaked hstate->resv_huge_pages, so HugetlbPages can return to zero after
shmdt() while that reservation remains leaked.
The original test exposed this by making enough read-only attachments to
exhaust the pool. Here, an eventual shmat() failure would also be handled by
SAFE_SHMAT() as TBROK rather than reported as a failure of the operation
under test. Could the original reservation-leak oracle be retained and the
regression reported as TFAIL?
> #define SEGMENT_KEY (0x82ba15ff)
> shmid = SAFE_SHMGET(SEGMENT_KEY, segment_size,
> IPC_CREAT | SHM_HUGETLB | 0640);
Could this segment use IPC_PRIVATE? IPC_CREAT without IPC_EXCL returns an
accessible pre-existing segment for this key when it is large enough.
setup() would then overwrite that segment, and cleanup() would remove
another process's IPC object with IPC_RMID.
> /*\
> * [Description]
Could the deprecated [Description] header be dropped?
> static struct tst_test test = {
> .needs_root = 1,
Could the high-level description explain why root is required, namely that
the framework modifies the system huge-page pool to reserve pages?
> +/hugetlb/hugeshmat/hugeshmat06
Could this entry be placed in
testcases/kernel/mem/hugetlb/hugeshmat/.gitignore instead? New test binaries
belong in the .gitignore in their own directory.
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 10:33 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-20 4:25 [LTP] [PATCH v4] hugetlb/hugeshmat: Add hugeshmat06 migrated from libhugetlbfs shm-perms Samir Mulani
2026-08-20 10:33 ` [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.