* [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; 4+ 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] 4+ 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
2026-08-20 16:49 ` Samir M
0 siblings, 1 reply; 4+ 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] 4+ messages in thread
* Re: [LTP] hugetlb/hugeshmat: Add hugeshmat06 migrated from libhugetlbfs shm-perms
2026-08-20 10:33 ` [LTP] " linuxtestproject.agent
@ 2026-08-20 16:49 ` Samir M
0 siblings, 0 replies; 4+ messages in thread
From: Samir M @ 2026-08-20 16:49 UTC (permalink / raw)
To: linuxtestproject.agent; +Cc: ltp
On 20/08/26 4:03 pm, linuxtestproject.agent@gmail.com wrote:
> 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?
Agreed. HugetlbPages tracks the hugepage mappings associated with the
process and can return to zero after shmdt() while the underlying
resv_huge_pages reservation remains leaked.
I have retained the original reservation-exhaustion behavior and handle
the relevant shmat() failure explicitly as TFAIL instead of using
SAFE_SHMAT(), which would report it as TBROK.
Updated in v5.
>
>> #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.
Agreed. Replaced SEGMENT_KEY with IPC_PRIVATE. The children inherit
global_shmid directly, so a fixed key is not required. The unused
SEGMENT_KEY definition has also been removed.
>
>> /*\
>> * [Description]
> Could the deprecated [Description] header be dropped?
Agreed. Removed the deprecated [Description] tag while retaining the
test description, consistent with the convention used by other tests
in this area.
>> 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?
I checked the other tests in the hugeshmat and hugefork directories
and none of them document needs_root in the description block. It is
a well understood LTP framework convention so I am keeping it as is.
>> +/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.
There is no per-directory .gitignore under
testcases/kernel/mem/hugetlb/hugeshmat/. The existing hugeshmat01
through hugeshmat05 binary entries are maintained in
testcases/kernel/mem/.gitignore. I have kept the hugeshmat06 entry
there to remain consistent with the existing hugeshmat tests.
>
> 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
>
Regards,
Samir
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [LTP] hugetlb/hugeshmat: Add hugeshmat06 migrated from libhugetlbfs shm-perms
2026-08-20 12:55 [LTP] [PATCH v5] " Samir Mulani
@ 2026-08-20 18:40 ` linuxtestproject.agent
0 siblings, 0 replies; 4+ 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] 4+ messages in thread
end of thread, other threads:[~2026-08-20 18:40 UTC | newest]
Thread overview: 4+ 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
2026-08-20 16:49 ` Samir M
-- strict thread matches above, loose matches on Subject: below --
2026-08-20 12:55 [LTP] [PATCH v5] " 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.