* [LTP] [PATCH] hugemmap10: Account for memory policy in counter checks
@ 2026-09-14 3:23 Huaisheng Ye
2026-09-14 12:03 ` [LTP] " linuxtestproject.agent
2026-09-16 8:48 ` [LTP] [PATCH] " Li Wang
0 siblings, 2 replies; 7+ messages in thread
From: Huaisheng Ye @ 2026-09-14 3:23 UTC (permalink / raw)
To: tsahu, pvorel, li.wang; +Cc: ltp
The expected surplus calculation only considers the global free and
reserved hugepage counters. This is insufficient when the task has an
MPOL_BIND policy and some or all globally free hugepages reside outside
the nodes allowed by that policy.
Policy-aware hugetlb reservation accounting allocates surplus pages on
the allowed nodes in this case. For example, with one globally free page
outside the policy and no free pages inside it, reserving one page grows
HugePages_Total, HugePages_Free and HugePages_Surp by one. The current test
expects all three counters to remain unchanged and reports false failures.
Read the current memory policy and cpuset allowed mask with
get_mempolicy(). For MPOL_BIND, intersect both masks; for other policy
modes, use the cpuset mask because they do not impose a hard allocation
constraint. Sum free_hugepages for the resulting nodes before mmap(), and
calculate the expected surplus count as the maximum of the global and
allowed-node shortfalls.
Note that a kernel patch has already been posted for solving Hugetlb
reservations defect. Without that, hugemmap10 would fail when mapping .
https://lore.kernel.org/all/20260909074642.7308-1-yehuaisheng@open-hieco.net/
For example, reproduce it with an eight-node system running 7.3.0-rc1:
# numactl --membind=0-3 ./hugemmap10
tst_hugepage.c:84: TINFO: 3 hugepage(s) reserved
tst_tmpdir.c:308: TINFO: Using /tmp/LTP_hugwmfnRD as tmpdir (xfs filesystem)
tst_test.c:1218: TINFO: Mounting none to /tmp/LTP_hugwmfnRD/hugetlbfs fstyp=hugetlbfs flags=0
tst_test.c:2048: TINFO: LTP version: 20260529-234-g6e966054b
tst_test.c:2051: TINFO: Tested kernel: 7.3.0-rc1+ #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:386: TINFO: Base pool size: 0
hugemmap10.c:313: TINFO: Clean...
hugemmap10.c:364: TINFO: OK
hugemmap10.c:313: TINFO: Untouched, shared...
hugemmap10.c:364: TINFO: OK
hugemmap10.c:313: TINFO: Untouched, private...
hugemmap10.c:364: TINFO: OK
hugemmap10.c:313: TINFO: Touched, shared...
hugemmap10.c:364: TINFO: OK
hugemmap10.c:313: TINFO: Touched, private...
hugemmap10.c:364: TINFO: OK
hugemmap10.c:386: TINFO: Base pool size: 1
hugemmap10.c:313: TINFO: Clean...
hugemmap10.c:319: TFAIL: While doing mmap shared with no touch: Bad HugePages_Total: expected 1, actual 2
hugemmap10.c:319: TFAIL: While doing mmap shared with no touch: Bad HugePages_Free: expected 1, actual 2
hugemmap10.c:319: TFAIL: While doing mmap shared with no touch: Bad HugePages_Surp: expected 0, actual 1
Summary:
passed 0
failed 3
broken 0
skipped 0
warnings 0
# numactl --membind=4-7 ./hugemmap10
tst_hugepage.c:84: TINFO: 3 hugepage(s) reserved
...
hugemmap10.c:364: TINFO: OK
hugemmap10.c:429: TPASS: Hugepages Counters works as expected.
Summary:
passed 1
failed 0
broken 0
skipped 0
warnings 0
In this example, if the free global huge pages are located on Nodes 4-7 while
the memory policy restricts hugemap10 to allocating memory from Nodes 0-3,
the discrepancy in the counters can be observed.
Signed-off-by: Huaisheng Ye <yehuaisheng@open-hieco.net>
---
.../kernel/mem/hugetlb/hugemmap/hugemmap10.c | 73 ++++++++++++++++++-
1 file changed, 72 insertions(+), 1 deletion(-)
diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap10.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap10.c
index 5b5577a0e..6d1cd6241 100644
--- a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap10.c
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap10.c
@@ -13,6 +13,9 @@
*/
#define _GNU_SOURCE
+#include <errno.h>
+#include <linux/mempolicy.h>
+#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/mount.h>
@@ -21,8 +24,10 @@
#include <sys/types.h>
#include "hugetlb.h"
+#include "lapi/syscalls.h"
#define MNTPOINT "hugetlbfs/"
+#define ULONG_BITS (sizeof(unsigned long) * CHAR_BIT)
static long hpage_size;
static int private_resv;
@@ -48,6 +53,63 @@ static void read_meminfo_huge(long *total, long *free, long *resv, long *surp)
*surp = SAFE_READ_MEMINFO(MEMINFO_HPAGE_SURP);
}
+static int node_isset(unsigned long node, const unsigned long *nodemask)
+{
+ return nodemask[node / ULONG_BITS] & (1UL << (node % ULONG_BITS));
+}
+
+static unsigned long read_allowed_free_hugepages(void)
+{
+ char path[PATH_MAX];
+ size_t mask_size = getpagesize();
+ unsigned long allowed_free = 0;
+ unsigned long maxnode = mask_size * CHAR_BIT;
+ unsigned long *policy_nodemask;
+ unsigned long *cpuset_nodemask;
+ unsigned long node, node_free;
+ int mode;
+
+ policy_nodemask = SAFE_CALLOC(1, mask_size);
+ cpuset_nodemask = SAFE_CALLOC(1, mask_size);
+
+ if (syscall(__NR_get_mempolicy, &mode, policy_nodemask,
+ maxnode, NULL, 0)) {
+ if (errno == ENOSYS) {
+ allowed_free = prev_free;
+ goto out;
+ }
+ tst_brk(TBROK | TERRNO, "get_mempolicy() failed");
+ }
+
+ if (syscall(__NR_get_mempolicy, NULL, cpuset_nodemask,
+ maxnode, NULL, MPOL_F_MEMS_ALLOWED))
+ tst_brk(TBROK | TERRNO,
+ "get_mempolicy(MPOL_F_MEMS_ALLOWED) failed");
+
+ mode &= ~MPOL_MODE_FLAGS;
+ for (node = 0; node < maxnode; node++) {
+ if (!node_isset(node, cpuset_nodemask))
+ continue;
+ if (mode == MPOL_BIND && !node_isset(node, policy_nodemask))
+ continue;
+
+ snprintf(path, sizeof(path),
+ "/sys/devices/system/node/node%lu/hugepages/"
+ "hugepages-%ldkB/free_hugepages",
+ node, hpage_size / 1024);
+ if (access(path, R_OK))
+ continue;
+
+ SAFE_FILE_SCANF(path, "%lu", &node_free);
+ allowed_free += node_free;
+ }
+
+out:
+ free(policy_nodemask);
+ free(cpuset_nodemask);
+ return allowed_free;
+}
+
static int kernel_has_private_reservations(void)
{
int fd;
@@ -178,10 +240,14 @@ out:
static int map_(int s, int hpages, int flags, char *desc, int line)
{
+ unsigned long allowed_free = 0;
long et, ef, er, es;
+ int creates_reservation = (flags & MAP_SHARED) || private_resv;
map_fd[s] = tst_creat_unlinked(MNTPOINT, 0, 0600);
map_size[s] = hpages * hpage_size;
+ if (creates_reservation)
+ allowed_free = read_allowed_free_hugepages();
map_addr[s] = SAFE_MMAP(NULL, map_size[s], PROT_READ|PROT_WRITE, flags,
map_fd[s], 0);
touched[s] = 0;
@@ -201,11 +267,16 @@ static int map_(int s, int hpages, int flags, char *desc, int line)
* mappings behave like MAP_SHARED at mmap time. Otherwise,
* no counter updates will occur.
*/
- if ((flags & MAP_SHARED) || private_resv) {
+ if (creates_reservation) {
unsigned long shortfall = 0;
if (hpages + prev_resv > prev_free)
shortfall = hpages - prev_free + prev_resv;
+
+ if ((unsigned long)hpages > allowed_free)
+ shortfall = MAX(shortfall,
+ (unsigned long)hpages - allowed_free);
+
et += shortfall;
ef += shortfall;
er += hpages;
--
2.52.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [LTP] hugemmap10: Account for memory policy in counter checks
2026-09-14 3:23 [LTP] [PATCH] hugemmap10: Account for memory policy in counter checks Huaisheng Ye
@ 2026-09-14 12:03 ` linuxtestproject.agent
2026-09-29 2:19 ` Huaisheng Ye
2026-09-16 8:48 ` [LTP] [PATCH] " Li Wang
1 sibling, 1 reply; 7+ messages in thread
From: linuxtestproject.agent @ 2026-09-14 12:03 UTC (permalink / raw)
To: Huaisheng Ye; +Cc: ltp
Hi Huaisheng,
On Mon Sep 14 11:23:59 2026 +0800, Huaisheng Ye wrote:
> hugemmap10: Account for memory policy in counter checks
> Note that a kernel patch has already been posted for solving Hugetlb
> reservations defect. Without that, hugemmap10 would fail when mapping .
> https://lore.kernel.org/all/20260909074642.7308-1-yehuaisheng@open-hieco.net/
The referenced kernel patch is not merged in mainline or the latest stable
release (7.3). Tests depending on unmerged kernel changes must use the
[STAGING] prefix and reside in runtest/staging rather than modifying
tests in default test suites.
> +static int node_isset(unsigned long node, const unsigned long *nodemask)
> +{
> + return nodemask[node / ULONG_BITS] & (1UL << (node % ULONG_BITS));
> +}
On 64-bit systems, the return value truncates to a 32-bit int, yielding 0
for any node with (node % 64) >= 32. Return !!(...) instead.
> + if ((unsigned long)hpages > allowed_free)
> + shortfall = MAX(shortfall,
> + (unsigned long)hpages - allowed_free);
allowed_free sums sysfs free_hugepages, which includes pages already
reserved by prior mappings. Comparing hpages against allowed_free without
accounting for reservations on those nodes undercalculates the shortfall
when prior reservations exist.
Verdict - Needs revision
Pre-existing issues:
- In per_iteration_cleanup(), map_fd[nr] > 0 is used to check file descriptor
validity instead of != -1.
---
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] 7+ messages in thread* Re: [LTP] hugemmap10: Account for memory policy in counter checks
2026-09-14 12:03 ` [LTP] " linuxtestproject.agent
@ 2026-09-29 2:19 ` Huaisheng Ye
0 siblings, 0 replies; 7+ messages in thread
From: Huaisheng Ye @ 2026-09-29 2:19 UTC (permalink / raw)
To: linuxtestproject.agent; +Cc: ltp
On 9/14/2026 8:03 PM, linuxtestproject.agent@gmail.com wrote:
> Hi Huaisheng,
>
> On Mon Sep 14 11:23:59 2026 +0800, Huaisheng Ye wrote:
>> hugemmap10: Account for memory policy in counter checks
>> Note that a kernel patch has already been posted for solving Hugetlb
>> reservations defect. Without that, hugemmap10 would fail when mapping .
>> https://lore.kernel.org/all/20260909074642.7308-1-yehuaisheng@open-hieco.net/
> The referenced kernel patch is not merged in mainline or the latest stable
> release (7.3). Tests depending on unmerged kernel changes must use the
> [STAGING] prefix and reside in runtest/staging rather than modifying
> tests in default test suites.
It has been merged to AKPM's mm-new branch only.
https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git/commit/?h=mm-new&id=506f9bf248c092fc80df046f9deb26094ea84592
>> +static int node_isset(unsigned long node, const unsigned long *nodemask)
>> +{
>> + return nodemask[node / ULONG_BITS] & (1UL << (node % ULONG_BITS));
>> +}
> On 64-bit systems, the return value truncates to a 32-bit int, yielding 0
> for any node with (node % 64) >= 32. Return !!(...) instead.
Fixed that in V2.
>> + if ((unsigned long)hpages > allowed_free)
>> + shortfall = MAX(shortfall,
>> + (unsigned long)hpages - allowed_free);
> allowed_free sums sysfs free_hugepages, which includes pages already
> reserved by prior mappings. Comparing hpages against allowed_free without
> accounting for reservations on those nodes undercalculates the shortfall
> when prior reservations exist.
That is intended to verify that the requested hugepages cannot be
satisfied by the nodes allowed by the memory policy based on currently
available hugepages.
However, free_hugepages exported via sysfs does include hugepages that
may already be reserved by existing mappings. Therefore
(hpages - allowed_free) cannot provide an exact reservation availability
calculation. So take the larger value of the global_shortfall and
allowed_shortfall, that is taking into account the global reservation.
This is a best-effort check based on per-node free hugepages rather than
exact reservation accounting. And based on our observations that is enough
for LTP testcase hugemmap10.
A fully accurate check would require per-node reservation information,
which is not available from sysfs.
Furthermore, I believe the fundamental reason lies in the lazy page
allocation
principle of MM. Only when page-fault time can the MM determine hugepage
originates from which nodes. So Kernel is unable to provide Per-node
reservation in multi-node numa system.
Huaisheng Ye
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [LTP] [PATCH] hugemmap10: Account for memory policy in counter checks
2026-09-14 3:23 [LTP] [PATCH] hugemmap10: Account for memory policy in counter checks Huaisheng Ye
2026-09-14 12:03 ` [LTP] " linuxtestproject.agent
@ 2026-09-16 8:48 ` Li Wang
2026-09-16 9:37 ` Li Wang
2026-09-17 8:40 ` Huaisheng Ye
1 sibling, 2 replies; 7+ messages in thread
From: Li Wang @ 2026-09-16 8:48 UTC (permalink / raw)
To: Huaisheng Ye; +Cc: tsahu, ltp
Hi Huaisheng,
This patch make sense, minor comments inline below:
> .../kernel/mem/hugetlb/hugemmap/hugemmap10.c | 73 ++++++++++++++++++-
> 1 file changed, 72 insertions(+), 1 deletion(-)
>
> diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap10.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap10.c
> index 5b5577a0e..6d1cd6241 100644
> --- a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap10.c
> +++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap10.c
> @@ -13,6 +13,9 @@
> */
>
> #define _GNU_SOURCE
> +#include <errno.h>
> +#include <linux/mempolicy.h>
> +#include <stdlib.h>
> #include <unistd.h>
> #include <stdio.h>
> #include <sys/mount.h>
> @@ -21,8 +24,10 @@
> #include <sys/types.h>
>
> #include "hugetlb.h"
> +#include "lapi/syscalls.h"
>
> #define MNTPOINT "hugetlbfs/"
> +#define ULONG_BITS (sizeof(unsigned long) * CHAR_BIT)
>
> static long hpage_size;
> static int private_resv;
> @@ -48,6 +53,63 @@ static void read_meminfo_huge(long *total, long *free, long *resv, long *surp)
> *surp = SAFE_READ_MEMINFO(MEMINFO_HPAGE_SURP);
> }
>
> +static int node_isset(unsigned long node, const unsigned long *nodemask)
> +{
> + return nodemask[node / ULONG_BITS] & (1UL << (node % ULONG_BITS));
> +}
> +
> +static unsigned long read_allowed_free_hugepages(void)
> +{
> + char path[PATH_MAX];
> + size_t mask_size = getpagesize();
> + unsigned long allowed_free = 0;
> + unsigned long maxnode = mask_size * CHAR_BIT;
> + unsigned long *policy_nodemask;
> + unsigned long *cpuset_nodemask;
> + unsigned long node, node_free;
> + int mode;
> +
> + policy_nodemask = SAFE_CALLOC(1, mask_size);
> + cpuset_nodemask = SAFE_CALLOC(1, mask_size);
> +
> + if (syscall(__NR_get_mempolicy, &mode, policy_nodemask,
> + maxnode, NULL, 0)) {
> + if (errno == ENOSYS) {
> + allowed_free = prev_free;
> + goto out;
> + }
> + tst_brk(TBROK | TERRNO, "get_mempolicy() failed");
> + }
> +
> + if (syscall(__NR_get_mempolicy, NULL, cpuset_nodemask,
> + maxnode, NULL, MPOL_F_MEMS_ALLOWED))
> + tst_brk(TBROK | TERRNO,
> + "get_mempolicy(MPOL_F_MEMS_ALLOWED) failed");
> +
> + mode &= ~MPOL_MODE_FLAGS;
> + for (node = 0; node < maxnode; node++) {
> + if (!node_isset(node, cpuset_nodemask))
> + continue;
> + if (mode == MPOL_BIND && !node_isset(node, policy_nodemask))
> + continue;
> +
> + snprintf(path, sizeof(path),
> + "/sys/devices/system/node/node%lu/hugepages/"
> + "hugepages-%ldkB/free_hugepages",
> + node, hpage_size / 1024);
> + if (access(path, R_OK))
> + continue;
> +
> + SAFE_FILE_SCANF(path, "%lu", &node_free);
> + allowed_free += node_free;
> + }
> +
> +out:
> + free(policy_nodemask);
> + free(cpuset_nodemask);
> + return allowed_free;
> +}
> +
> static int kernel_has_private_reservations(void)
> {
> int fd;
> @@ -178,10 +240,14 @@ out:
>
> static int map_(int s, int hpages, int flags, char *desc, int line)
> {
> + unsigned long allowed_free = 0;
> long et, ef, er, es;
> + int creates_reservation = (flags & MAP_SHARED) || private_resv;
Maybe we can move this definition into setup() and then replace all the
reservation syntax globally.
>
> map_fd[s] = tst_creat_unlinked(MNTPOINT, 0, 0600);
> map_size[s] = hpages * hpage_size;
> + if (creates_reservation)
> + allowed_free = read_allowed_free_hugepages();
> map_addr[s] = SAFE_MMAP(NULL, map_size[s], PROT_READ|PROT_WRITE, flags,
> map_fd[s], 0);
> touched[s] = 0;
> @@ -201,11 +267,16 @@ static int map_(int s, int hpages, int flags, char *desc, int line)
> * mappings behave like MAP_SHARED at mmap time. Otherwise,
> * no counter updates will occur.
> */
> - if ((flags & MAP_SHARED) || private_resv) {
> + if (creates_reservation) {
> unsigned long shortfall = 0;
>
> if (hpages + prev_resv > prev_free)
> shortfall = hpages - prev_free + prev_resv;
> +
> + if ((unsigned long)hpages > allowed_free)
> + shortfall = MAX(shortfall,
> + (unsigned long)hpages - allowed_free);
> +
> et += shortfall;
> ef += shortfall;
> er += hpages;
> --
> 2.52.0
Aside from this patch, my test encountered new failures on a four-node system.
Without your patch, the surplus failure can be reproduced consistently, so I
suspect it's a different issue.
...
hugemmap10.c:402: TFAIL: While doing munmap shared after touch: Bad HugePages_Total: expected 1, actual 2
hugemmap10.c:402: TFAIL: While doing munmap shared after touch: Bad HugePages_Free: expected 1, actual 2
hugemmap10.c:402: TFAIL: While doing munmap shared after touch: Bad HugePages_Surp: expected 0, actual 1
--
Regards,
Li Wang
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [LTP] [PATCH] hugemmap10: Account for memory policy in counter checks
2026-09-16 8:48 ` [LTP] [PATCH] " Li Wang
@ 2026-09-16 9:37 ` Li Wang
2026-09-17 8:42 ` Huaisheng Ye
2026-09-17 8:40 ` Huaisheng Ye
1 sibling, 1 reply; 7+ messages in thread
From: Li Wang @ 2026-09-16 9:37 UTC (permalink / raw)
To: Huaisheng Ye, tsahu, pvorel, ltp
>
> Aside from this patch, my test encountered new failures on a four-node system.
> Without your patch, the surplus failure can be reproduced consistently, so I
> suspect it's a different issue.
>
> ...
> hugemmap10.c:402: TFAIL: While doing munmap shared after touch: Bad HugePages_Total: expected 1, actual 2
> hugemmap10.c:402: TFAIL: While doing munmap shared after touch: Bad HugePages_Free: expected 1, actual 2
> hugemmap10.c:402: TFAIL: While doing munmap shared after touch: Bad HugePages_Surp: expected 0, actual 1
The test system has four nodes, and only nodes 0 and 2 have memory.
I guess that's what caused the failure when running hugemmap10 during
hugepage allocation.
Something like this:
1. The test pre-allocates 1 hugepage, which defaults to Node 0.
2. When the test runs on Node 2, the kernel dynamically creates a surplus
hugepage on Node 2 to ensure local memory performance.
3. The global hugepage count becomes 2 (1 on Node 0 + 1 surplus on Node 2).
4. The test expects exactly 1 global hugepage, so it reports a failure.
Below are the test results from patched-hugemmap10 on patched-kernel-6.6.
I'll do more investigation tomorrow.
[root@SL26GA ~]# numactl -H
available: 4 nodes (0-3)
node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
node 0 size: 31729 MB
node 0 free: 30582 MB
node 1 cpus: 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
node 1 size: 0 MB
node 1 free: 0 MB
node 2 cpus: 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
node 2 size: 31896 MB
node 2 free: 30627 MB
node 3 cpus: 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
node 3 size: 0 MB
node 3 free: 0 MB
node distances:
node 0 1 2 3
0: 10 15 42 38
1: 15 10 38 33
2: 42 38 10 15
3: 38 33 15 10
[root@SL26GA hugemmap]# numactl --cpunodebind=0 ./hugemmap10
tst_hugepage.c:84: TINFO: 6 hugepage(s) reserved
tst_tmpdir.c:308: TINFO: Using /tmp/LTP_hug9CXa7r as tmpdir (tmpfs filesystem)
tst_test.c:1233: TINFO: Mounting none to /tmp/LTP_hug9CXa7r/hugetlbfs fstyp=hugetlbfs flags=0
tst_test.c:2065: TINFO: LTP version: 20260529
tst_test.c:2068: TINFO: Tested kernel: 6.6.145-9.sl26.x86_64 #1 SMP Thu Sep 3 11:08:39 CST 2026 x86_64
tst_kconfig.c:90: TINFO: Parsing kernel config '/proc/config.gz'
tst_test.c:1893: TINFO: Overall timeout per run is 0h 00m 30s
hugemmap10.c:457: TINFO: Base pool size: 0
hugemmap10.c:384: TINFO: Clean...
hugemmap10.c:435: TINFO: OK
hugemmap10.c:384: TINFO: Untouched, shared...
hugemmap10.c:435: TINFO: OK
hugemmap10.c:384: TINFO: Untouched, private...
hugemmap10.c:435: TINFO: OK
hugemmap10.c:384: TINFO: Touched, shared...
hugemmap10.c:435: TINFO: OK
hugemmap10.c:384: TINFO: Touched, private...
hugemmap10.c:435: TINFO: OK
hugemmap10.c:457: TINFO: Base pool size: 1
hugemmap10.c:384: TINFO: Clean...
hugemmap10.c:435: TINFO: OK
hugemmap10.c:384: TINFO: Untouched, shared...
hugemmap10.c:435: TINFO: OK
hugemmap10.c:384: TINFO: Untouched, private...
hugemmap10.c:435: TINFO: OK
hugemmap10.c:384: TINFO: Touched, shared...
hugemmap10.c:435: TINFO: OK
hugemmap10.c:384: TINFO: Touched, private...
hugemmap10.c:435: TINFO: OK
hugemmap10.c:457: TINFO: Base pool size: 2
hugemmap10.c:384: TINFO: Clean...
hugemmap10.c:435: TINFO: OK
hugemmap10.c:384: TINFO: Untouched, shared...
hugemmap10.c:435: TINFO: OK
hugemmap10.c:384: TINFO: Untouched, private...
hugemmap10.c:435: TINFO: OK
hugemmap10.c:384: TINFO: Touched, shared...
hugemmap10.c:435: TINFO: OK
hugemmap10.c:384: TINFO: Touched, private...
hugemmap10.c:435: TINFO: OK
hugemmap10.c:457: TINFO: Base pool size: 3
hugemmap10.c:384: TINFO: Clean...
hugemmap10.c:435: TINFO: OK
hugemmap10.c:384: TINFO: Untouched, shared...
hugemmap10.c:435: TINFO: OK
hugemmap10.c:384: TINFO: Untouched, private...
hugemmap10.c:435: TINFO: OK
hugemmap10.c:384: TINFO: Touched, shared...
hugemmap10.c:435: TINFO: OK
hugemmap10.c:384: TINFO: Touched, private...
hugemmap10.c:435: TINFO: OK
hugemmap10.c:500: TPASS: Hugepages Counters works as expected.
Summary:
passed 1
failed 0
broken 0
skipped 0
warnings 0
[root@SL26GA hugemmap]# numactl --cpunodebind=2 ./hugemmap10
tst_hugepage.c:84: TINFO: 6 hugepage(s) reserved
tst_tmpdir.c:308: TINFO: Using /tmp/LTP_hugVJVuKk as tmpdir (tmpfs filesystem)
tst_test.c:1233: TINFO: Mounting none to /tmp/LTP_hugVJVuKk/hugetlbfs fstyp=hugetlbfs flags=0
tst_test.c:2065: TINFO: LTP version: 20260529
tst_test.c:2068: TINFO: Tested kernel: 6.6.145-9.sl26.x86_64 #1 SMP Thu Sep 3 11:08:39 CST 2026 x86_64
tst_kconfig.c:90: TINFO: Parsing kernel config '/proc/config.gz'
tst_test.c:1893: TINFO: Overall timeout per run is 0h 00m 30s
hugemmap10.c:457: TINFO: Base pool size: 0
hugemmap10.c:384: TINFO: Clean...
hugemmap10.c:435: TINFO: OK
hugemmap10.c:384: TINFO: Untouched, shared...
hugemmap10.c:435: TINFO: OK
hugemmap10.c:384: TINFO: Untouched, private...
hugemmap10.c:435: TINFO: OK
hugemmap10.c:384: TINFO: Touched, shared...
hugemmap10.c:435: TINFO: OK
hugemmap10.c:384: TINFO: Touched, private...
hugemmap10.c:435: TINFO: OK
hugemmap10.c:457: TINFO: Base pool size: 1
hugemmap10.c:384: TINFO: Clean...
hugemmap10.c:435: TINFO: OK
hugemmap10.c:384: TINFO: Untouched, shared...
hugemmap10.c:402: TFAIL: While doing munmap shared after touch: Bad HugePages_Total: expected 1, actual 2
hugemmap10.c:402: TFAIL: While doing munmap shared after touch: Bad HugePages_Free: expected 1, actual 2
hugemmap10.c:402: TFAIL: While doing munmap shared after touch: Bad HugePages_Surp: expected 0, actual 1
Summary:
passed 0
failed 3
broken 0
skipped 0
warnings 0
--
Regards,
Li Wang
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [LTP] [PATCH] hugemmap10: Account for memory policy in counter checks
2026-09-16 9:37 ` Li Wang
@ 2026-09-17 8:42 ` Huaisheng Ye
0 siblings, 0 replies; 7+ messages in thread
From: Huaisheng Ye @ 2026-09-17 8:42 UTC (permalink / raw)
To: tsahu, pvorel, ltp, li.wang
On 9/16/2026 17:37, Li Wang wrote:
>> Aside from this patch, my test encountered new failures on a four-node system.
>> Without your patch, the surplus failure can be reproduced consistently, so I
>> suspect it's a different issue.
>>
>> ...
>> hugemmap10.c:402: TFAIL: While doing munmap shared after touch: Bad HugePages_Total: expected 1, actual 2
>> hugemmap10.c:402: TFAIL: While doing munmap shared after touch: Bad HugePages_Free: expected 1, actual 2
>> hugemmap10.c:402: TFAIL: While doing munmap shared after touch: Bad HugePages_Surp: expected 0, actual 1
> The test system has four nodes, and only nodes 0 and 2 have memory.
> I guess that's what caused the failure when running hugemmap10 during
> hugepage allocation.
>
> Something like this:
>
> 1. The test pre-allocates 1 hugepage, which defaults to Node 0.
>
> 2. When the test runs on Node 2, the kernel dynamically creates a surplus
> hugepage on Node 2 to ensure local memory performance.
>
> 3. The global hugepage count becomes 2 (1 on Node 0 + 1 surplus on Node 2).
>
> 4. The test expects exactly 1 global hugepage, so it reports a failure.
>
> Below are the test results from patched-hugemmap10 on patched-kernel-6.6.
> I'll do more investigation tomorrow.
Yes, I can reproduce it with stable kernel v6.6.145. However, after backporting
commit d0f14f7ee0e2 ("hugetlb: prioritize surplus allocation from current node"),
the issue is resolved.
Commit d0f14f7ee0e2 was designed to fix the side effect of commit 003af997c8a9,
which had been backported to v6.6 stable to ensure that surplus huge pages come
from mempolicy-allowed nodes.
So you could try v6.6 stable with d0f14f7ee0e2 applied, or upstream v7.3-rc.
Kind Regards,
Huaisheng Ye
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [LTP] [PATCH] hugemmap10: Account for memory policy in counter checks
2026-09-16 8:48 ` [LTP] [PATCH] " Li Wang
2026-09-16 9:37 ` Li Wang
@ 2026-09-17 8:40 ` Huaisheng Ye
1 sibling, 0 replies; 7+ messages in thread
From: Huaisheng Ye @ 2026-09-17 8:40 UTC (permalink / raw)
To: tsahu, pvorel, ltp, li.wang
On 9/16/2026 16:48, Li Wang wrote:
> Hi Huaisheng,
>
> This patch make sense, minor comments inline below:
>
>> .../kernel/mem/hugetlb/hugemmap/hugemmap10.c | 73 ++++++++++++++++++-
>> 1 file changed, 72 insertions(+), 1 deletion(-)
>>
>> diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap10.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap10.c
>> index 5b5577a0e..6d1cd6241 100644
>> --- a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap10.c
>> +++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap10.c
>> @@ -13,6 +13,9 @@
>> */
>>
>> #define _GNU_SOURCE
>> +#include <errno.h>
>> +#include <linux/mempolicy.h>
>> +#include <stdlib.h>
>> #include <unistd.h>
>> #include <stdio.h>
>> #include <sys/mount.h>
>> @@ -21,8 +24,10 @@
>> #include <sys/types.h>
>>
>> #include "hugetlb.h"
>> +#include "lapi/syscalls.h"
>>
>> #define MNTPOINT "hugetlbfs/"
>> +#define ULONG_BITS (sizeof(unsigned long) * CHAR_BIT)
>>
>> static long hpage_size;
>> static int private_resv;
>> @@ -48,6 +53,63 @@ static void read_meminfo_huge(long *total, long *free, long *resv, long *surp)
>> *surp = SAFE_READ_MEMINFO(MEMINFO_HPAGE_SURP);
>> }
>>
>> +static int node_isset(unsigned long node, const unsigned long *nodemask)
>> +{
>> + return nodemask[node / ULONG_BITS] & (1UL << (node % ULONG_BITS));
>> +}
>> +
>> +static unsigned long read_allowed_free_hugepages(void)
>> +{
>> + char path[PATH_MAX];
>> + size_t mask_size = getpagesize();
>> + unsigned long allowed_free = 0;
>> + unsigned long maxnode = mask_size * CHAR_BIT;
>> + unsigned long *policy_nodemask;
>> + unsigned long *cpuset_nodemask;
>> + unsigned long node, node_free;
>> + int mode;
>> +
>> + policy_nodemask = SAFE_CALLOC(1, mask_size);
>> + cpuset_nodemask = SAFE_CALLOC(1, mask_size);
>> +
>> + if (syscall(__NR_get_mempolicy, &mode, policy_nodemask,
>> + maxnode, NULL, 0)) {
>> + if (errno == ENOSYS) {
>> + allowed_free = prev_free;
>> + goto out;
>> + }
>> + tst_brk(TBROK | TERRNO, "get_mempolicy() failed");
>> + }
>> +
>> + if (syscall(__NR_get_mempolicy, NULL, cpuset_nodemask,
>> + maxnode, NULL, MPOL_F_MEMS_ALLOWED))
>> + tst_brk(TBROK | TERRNO,
>> + "get_mempolicy(MPOL_F_MEMS_ALLOWED) failed");
>> +
>> + mode &= ~MPOL_MODE_FLAGS;
>> + for (node = 0; node < maxnode; node++) {
>> + if (!node_isset(node, cpuset_nodemask))
>> + continue;
>> + if (mode == MPOL_BIND && !node_isset(node, policy_nodemask))
>> + continue;
>> +
>> + snprintf(path, sizeof(path),
>> + "/sys/devices/system/node/node%lu/hugepages/"
>> + "hugepages-%ldkB/free_hugepages",
>> + node, hpage_size / 1024);
>> + if (access(path, R_OK))
>> + continue;
>> +
>> + SAFE_FILE_SCANF(path, "%lu", &node_free);
>> + allowed_free += node_free;
>> + }
>> +
>> +out:
>> + free(policy_nodemask);
>> + free(cpuset_nodemask);
>> + return allowed_free;
>> +}
>> +
>> static int kernel_has_private_reservations(void)
>> {
>> int fd;
>> @@ -178,10 +240,14 @@ out:
>>
>> static int map_(int s, int hpages, int flags, char *desc, int line)
>> {
>> + unsigned long allowed_free = 0;
>> long et, ef, er, es;
>> + int creates_reservation = (flags & MAP_SHARED) || private_resv;
> Maybe we can move this definition into setup() and then replace all the
> reservation syntax globally.
Many thanks for comments.
Good suggestion, I will resend V2 later.
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-09-29 2:20 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-14 3:23 [LTP] [PATCH] hugemmap10: Account for memory policy in counter checks Huaisheng Ye
2026-09-14 12:03 ` [LTP] " linuxtestproject.agent
2026-09-29 2:19 ` Huaisheng Ye
2026-09-16 8:48 ` [LTP] [PATCH] " Li Wang
2026-09-16 9:37 ` Li Wang
2026-09-17 8:42 ` Huaisheng Ye
2026-09-17 8:40 ` Huaisheng Ye
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox