[LTP] [PATCH v2 3/3] hugemmap10: Account for memory policy in private fault checks

Huaisheng Ye yehuaisheng@open-hieco.net
Tue Sep 29 09:24:12 CEST 2026


Kernels without private mmap-time reservations or with flags MAP_NORESERVE
create the reservation when the private VMA first faults. With MPOL_BIND,
globally free hugepages can be outside the allowed nodes, so this fault
can create surplus pages even when the global counters appear sufficient.

    $ numactl --cpunodebind=0 --membind=2 ./hugemmap10 -n
    tst_hugepage.c:84: TINFO: 3 hugepage(s) reserved
    tst_tmpdir.c:308: TINFO: Using /tmp/LTP_hugdeSTgL as tmpdir (xfs filesystem)
    tst_test.c:1218: TINFO: Mounting none to /tmp/LTP_hugdeSTgL/hugetlbfs fstyp=hugetlbfs flags=0
    tst_test.c:2048: TINFO: LTP version: 20260529-237-g132c8b0a8
    tst_test.c:2051: TINFO: Tested kernel: 7.3.0-rc1-test-32+ #33 SMP PREEMPT Mon Sep  7 11:50:02 CST 2026 x86_64
    tst_kconfig.c:90: TINFO: Parsing kernel config '/proc/config.gz'
    tst_test.c:1876: TINFO: Overall timeout per run is 0h 00m 30s
    hugemmap10.c:498: TINFO: Base pool size: 0
    hugemmap10.c:425: TINFO: Clean...
    hugemmap10.c:476: TINFO: OK
    hugemmap10.c:425: TINFO: Untouched, shared...
    hugemmap10.c:476: TINFO: OK
    hugemmap10.c:425: TINFO: Untouched, private...
    hugemmap10.c:476: TINFO: OK
    hugemmap10.c:425: TINFO: Touched, shared...
    hugemmap10.c:476: TINFO: OK
    hugemmap10.c:425: TINFO: Touched, private...
    hugemmap10.c:476: TINFO: OK
    hugemmap10.c:498: TINFO: Base pool size: 1
    hugemmap10.c:425: TINFO: Clean...
    hugemmap10.c:448: TFAIL: While touching the addr after mmap private: Bad HugePages_Total: expected 1, actual 2
    hugemmap10.c:448: TFAIL: While touching the addr after mmap private: Bad HugePages_Free: expected 0, actual 1
    hugemmap10.c:448: TFAIL: While touching the addr after mmap private: Bad HugePages_Surp: expected 0, actual 1

    Summary:
    passed   0
    failed   3
    broken   0
    skipped  0
    warnings 0

Get free hugepages on allowed nodes before touching an unreserved
private mapping and use the maximum of the global and allowed-node
shortfalls to calculate the expected counters.

Signed-off-by: Huaisheng Ye <yehuaisheng@open-hieco.net>
---
 .../kernel/mem/hugetlb/hugemmap/hugemmap10.c  | 21 ++++++++++++-------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap10.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap10.c
index 1a5b0fd2f..bbbdc82ae 100644
--- a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap10.c
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap10.c
@@ -363,7 +363,7 @@ static int unmap_(int s, int hpages, int flags, char *desc, int line)
 	 * reservation.  If those pages were not touched, then they will
 	 * not have been freed by the code above.  Free them here.
 	 */
-	if ((flags & MAP_SHARED) || private_resv) {
+	if (mapping_creates_reservation(flags)) {
 		int unused_surplus = MIN(hpages - touched[s], es);
 
 		et -= unused_surplus;
@@ -378,10 +378,16 @@ static int unmap_(int s, int hpages, int flags, char *desc, int line)
 
 static int touch_(int s, int hpages, int flags, char *desc, int line)
 {
+	unsigned long allowed_free = 0;
 	long et, ef, er, es;
+	int creates_reservation = mapping_creates_reservation(flags);
 	int nr;
 	char *c;
 
+	/* An unreserved private mapping creates its reservation on fault. */
+	if (!creates_reservation)
+		allowed_free = read_allowed_free_hugepages();
+
 	for (c = map_addr[s], nr = hpages;
 			hpages && c < map_addr[s] + map_size[s];
 			c += hpage_size, nr--)
@@ -403,19 +409,18 @@ static int touch_(int s, int hpages, int flags, char *desc, int line)
 	 * which could elevate total, free, and surplus counts.  resv is
 	 * unchanged but free must be decreased.
 	 */
-	if (flags & MAP_SHARED || private_resv) {
+	if (creates_reservation) {
 		et = prev_total;
 		ef = prev_free - hpages;
 		er = prev_resv - hpages;
 		es = prev_surp;
 	} else {
-		if (hpages + prev_resv > prev_free)
-			et = prev_total + (hpages - prev_free + prev_resv);
-		else
-			et = prev_total;
+		unsigned long shortfall = surplus_pages_needed(hpages, allowed_free);
+
+		et = prev_total + shortfall;
 		er = prev_resv;
-		es = prev_surp + et - prev_total;
-		ef = prev_free - hpages + et - prev_total;
+		es = prev_surp + shortfall;
+		ef = prev_free - hpages + shortfall;
 	}
 	return verify_counters(line, desc, et, ef, er, es);
 }
-- 
2.52.0



More information about the ltp mailing list