From: Samir Mulani <samir@linux.ibm.com>
To: ltp@lists.linux.it
Cc: liwang@redhat.com, Samir Mulani <samir@linux.ibm.com>
Subject: [LTP] [PATCH v4] hugetlb/hugeshmat: Add hugeshmat06 migrated from libhugetlbfs shm-perms
Date: Thu, 20 Aug 2026 09:55:15 +0530 [thread overview]
Message-ID: <20260820042516.46631-1-samir@linux.ibm.com> (raw)
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
next reply other threads:[~2026-08-20 9:57 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-20 4:25 Samir Mulani [this message]
2026-08-20 10:33 ` [LTP] hugetlb/hugeshmat: Add hugeshmat06 migrated from libhugetlbfs shm-perms linuxtestproject.agent
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=20260820042516.46631-1-samir@linux.ibm.com \
--to=samir@linux.ibm.com \
--cc=liwang@redhat.com \
--cc=ltp@lists.linux.it \
/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.