Linux Test Project
 help / color / mirror / Atom feed
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

             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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox