* [PATCH v2 0/3] selftests/mm: pagemap_ioctl test fixes and cleanups
@ 2026-09-08 13:41 Zenghui Yu
2026-09-08 13:41 ` [PATCH v2 1/3] selftests/mm: fix size truncation in pagemap_ioctl test Zenghui Yu
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Zenghui Yu @ 2026-09-08 13:41 UTC (permalink / raw)
To: linux-mm, linux-kselftest, linux-kernel
Cc: akpm, david, ljs, liam, vbabka, rppt, surenb, mhocko, shuah,
gourry, Zenghui Yu (Huawei)
From: "Zenghui Yu (Huawei)" <zenghui.yu@linux.dev>
This series fixes a size truncation bug in the pagemap_ioctl test that
breaks it on arm64 systems with 64K base pages, and applies two small
cleanups suggested during the review of the fix.
* From v1 [1]:
- unify all size-related parameters and variables to size_t (David)
- drop Gregory's R-b for patch #1 (as the content has changed too much)
but thank you for that!
- add patch #2 marking file-local symbols static (David)
- add patch #3 initializing page sizes early (Andrew)
[1] https://lore.kernel.org/20260907135613.68692-1-zenghui.yu@linux.dev
Zenghui Yu (Huawei) (3):
selftests/mm: fix size truncation in pagemap_ioctl test
selftests/mm: mark file-local symbols of pagemap_ioctl.c static
selftests/mm: init page sizes early in pagemap_ioctl test
tools/testing/selftests/mm/pagemap_ioctl.c | 94 +++++++++++-----------
1 file changed, 48 insertions(+), 46 deletions(-)
--
2.53.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 1/3] selftests/mm: fix size truncation in pagemap_ioctl test
2026-09-08 13:41 [PATCH v2 0/3] selftests/mm: pagemap_ioctl test fixes and cleanups Zenghui Yu
@ 2026-09-08 13:41 ` Zenghui Yu
2026-09-08 13:43 ` [PATCH v2 2/3] selftests/mm: mark file-local symbols of pagemap_ioctl.c static Zenghui Yu
2026-09-08 13:44 ` [PATCH v2 3/3] selftests/mm: init page sizes early in pagemap_ioctl test Zenghui Yu
2 siblings, 0 replies; 5+ messages in thread
From: Zenghui Yu @ 2026-09-08 13:41 UTC (permalink / raw)
To: linux-mm, linux-kselftest, linux-kernel
Cc: akpm, david, ljs, liam, vbabka, rppt, surenb, mhocko, shuah,
gourry, Zenghui Yu (Huawei)
From: "Zenghui Yu (Huawei)" <zenghui.yu@linux.dev>
On arm64 with 64K base pages, the huge page size is 512 MiB, and
hpage_unit_tests() builds a 5 GiB range (10 * 512 MiB) for its tests. This
exceeds the range of the int size parameters of gethugepage(),
wp_addr_range() and pagemap_ioctl(). The implicit truncation to 1 GiB
makes gethugepage() allocate a too small buffer, while the callers keep
operating on the original 5 GiB range, resulting in spurious failures or
SIGSEGV.
Fix the truncation by changing those size parameters to size_t, and for
consistency, also convert the remaining size-related parameters and
variables that use int, long or unsigned long long to size_t.
Fixes: 46fd75d4a3c9 ("selftests: mm: add pagemap ioctl tests")
Assisted-by: GLM-5.3 OpenCode
Suggested-by: David Hildenbrand (Arm) <david@kernel.org>
Signed-off-by: Zenghui Yu (Huawei) <zenghui.yu@linux.dev>
---
tools/testing/selftests/mm/pagemap_ioctl.c | 55 ++++++++++++----------
1 file changed, 29 insertions(+), 26 deletions(-)
diff --git a/tools/testing/selftests/mm/pagemap_ioctl.c b/tools/testing/selftests/mm/pagemap_ioctl.c
index eadc7159ca5b..3665530eda76 100644
--- a/tools/testing/selftests/mm/pagemap_ioctl.c
+++ b/tools/testing/selftests/mm/pagemap_ioctl.c
@@ -44,7 +44,7 @@ const char *progname;
#define LEN(region) ((region.end - region.start)/page_size)
-static long pagemap_ioctl(void *start, int len, void *vec, int vec_len, int flag,
+static long pagemap_ioctl(void *start, size_t len, void *vec, size_t vec_len, int flag,
int max_pages, long required_mask, long anyof_mask, long excluded_mask,
long return_mask)
{
@@ -65,7 +65,7 @@ static long pagemap_ioctl(void *start, int len, void *vec, int vec_len, int flag
return ioctl(pagemap_fd, PAGEMAP_SCAN, &arg);
}
-static long pagemap_ioc(void *start, int len, void *vec, int vec_len, int flag,
+static long pagemap_ioc(void *start, size_t len, void *vec, size_t vec_len, int flag,
int max_pages, long required_mask, long anyof_mask, long excluded_mask,
long return_mask, long *walk_end)
{
@@ -116,7 +116,7 @@ int init_uffd(void)
return 0;
}
-int wp_init(void *addr, long size)
+int wp_init(void *addr, size_t size)
{
struct uffdio_register uffdio_register;
struct uffdio_writeprotect wp;
@@ -140,7 +140,7 @@ int wp_init(void *addr, long size)
return 0;
}
-int wp_free(void *addr, long size)
+int wp_free(void *addr, size_t size)
{
struct uffdio_register uffdio_register;
@@ -152,7 +152,7 @@ int wp_free(void *addr, long size)
return 0;
}
-int wp_addr_range(void *addr, int size)
+int wp_addr_range(void *addr, size_t size)
{
if (pagemap_ioctl(addr, size, NULL, 0,
PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC,
@@ -162,7 +162,7 @@ int wp_addr_range(void *addr, int size)
return 0;
}
-void *gethugetlb_mem(int size, int *shmid)
+void *gethugetlb_mem(size_t size, int *shmid)
{
char *mem;
@@ -188,7 +188,8 @@ void *gethugetlb_mem(int size, int *shmid)
int userfaultfd_tests(void)
{
- long mem_size, vec_size, written, num_pages = 16;
+ size_t mem_size, vec_size, num_pages = 16;
+ long written;
char *mem, *vec;
mem_size = num_pages * page_size;
@@ -229,9 +230,10 @@ int userfaultfd_tests(void)
return 0;
}
-int get_reads(struct page_region *vec, int vec_size)
+int get_reads(struct page_region *vec, size_t vec_size)
{
- int i, sum = 0;
+ size_t i;
+ int sum = 0;
for (i = 0; i < vec_size; i++)
sum += LEN(vec[i]);
@@ -241,7 +243,7 @@ int get_reads(struct page_region *vec, int vec_size)
int sanity_tests_sd(void)
{
- unsigned long long mem_size, vec_size, i, total_pages = 0;
+ size_t mem_size, vec_size, i, total_pages = 0;
long ret, ret2, ret3;
int num_pages = 1000;
int total_writes, total_reads, reads, count;
@@ -331,7 +333,7 @@ int sanity_tests_sd(void)
if (ret < 0)
ksft_exit_fail_msg("error %ld %d %s\n", ret, errno, strerror(errno));
- ksft_test_result((unsigned long long)ret == mem_size/(page_size * 2),
+ ksft_test_result((size_t)ret == mem_size/(page_size * 2),
"%s Repeated pattern of written and non-written pages\n", __func__);
/* 4. Repeated pattern of written and non-written pages in parts */
@@ -682,9 +684,9 @@ int sanity_tests_sd(void)
return 0;
}
-int base_tests(char *prefix, char *mem, unsigned long long mem_size, int skip)
+int base_tests(char *prefix, char *mem, size_t mem_size, int skip)
{
- unsigned long long vec_size;
+ size_t vec_size;
int written;
struct page_region *vec, *vec2;
@@ -787,7 +789,7 @@ int base_tests(char *prefix, char *mem, unsigned long long mem_size, int skip)
return 0;
}
-void *gethugepage(int map_size)
+void *gethugepage(size_t map_size)
{
int ret;
char *map;
@@ -810,8 +812,8 @@ int hpage_unit_tests(void)
char *map;
int ret, ret2;
size_t num_pages = 10;
- unsigned long long map_size = hpage_size * num_pages;
- unsigned long long vec_size = map_size/page_size;
+ size_t map_size = hpage_size * num_pages;
+ size_t vec_size = map_size/page_size;
struct page_region *vec, *vec2;
vec = calloc(vec_size, sizeof(struct page_region));
@@ -1002,8 +1004,9 @@ int hpage_unit_tests(void)
int unmapped_region_tests(void)
{
void *start = (void *)0x10000000;
- int written, len = 0x00040000;
- long vec_size = len / page_size;
+ int written;
+ size_t len = 0x00040000;
+ size_t vec_size = len / page_size;
struct page_region *vec = calloc(vec_size, sizeof(struct page_region));
if (!vec)
ksft_exit_fail_msg("error nomem\n");
@@ -1072,7 +1075,7 @@ static void test_simple(void)
* with no page table, exercising pagemap_scan_pte_hole(); a base-page range
* leaves pte_none entries.
*/
-static void unpopulated_written_test(const char *name, char *mem, long size,
+static void unpopulated_written_test(const char *name, char *mem, size_t size,
bool use_thp)
{
long npages = size / page_size, fast = 0, slow = 0, ret;
@@ -1115,7 +1118,7 @@ static void unpopulated_written_test(const char *name, char *mem, long size,
static void unpopulated_scan_test(void)
{
- long mem_size = 16 * page_size;
+ size_t mem_size = 16 * page_size;
char *mem;
mem = mmap(NULL, mem_size, PROT_READ | PROT_WRITE,
@@ -1157,8 +1160,8 @@ static void unpopulated_thp_scan_test(void)
int sanity_tests(void)
{
- unsigned long long mem_size, vec_size;
- long ret, fd, i, buf_size, nr_pages;
+ size_t mem_size, vec_size, i, buf_size;
+ long ret, fd, nr_pages;
struct page_region *vec;
char *mem, *fmem;
struct stat sbuf;
@@ -1582,9 +1585,9 @@ static void transact_test(int page_size)
void zeropfn_tests(void)
{
- unsigned long long mem_size;
+ size_t mem_size, i;
struct page_region vec;
- int i, ret;
+ int ret;
char *mmap_mem, *mem;
/* Test with normal memory */
@@ -1642,8 +1645,8 @@ void zeropfn_tests(void)
int main(int __attribute__((unused)) argc, char *argv[])
{
- int shmid, buf_size, fd, i, ret;
- unsigned long long mem_size;
+ int shmid, fd, ret;
+ size_t mem_size, buf_size, i;
char *mem, *map, *fmem;
struct stat sbuf;
--
2.53.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 2/3] selftests/mm: mark file-local symbols of pagemap_ioctl.c static
2026-09-08 13:41 [PATCH v2 0/3] selftests/mm: pagemap_ioctl test fixes and cleanups Zenghui Yu
2026-09-08 13:41 ` [PATCH v2 1/3] selftests/mm: fix size truncation in pagemap_ioctl test Zenghui Yu
@ 2026-09-08 13:43 ` Zenghui Yu
2026-09-08 13:44 ` [PATCH v2 3/3] selftests/mm: init page sizes early in pagemap_ioctl test Zenghui Yu
2 siblings, 0 replies; 5+ messages in thread
From: Zenghui Yu @ 2026-09-08 13:43 UTC (permalink / raw)
To: linux-mm, linux-kselftest, linux-kernel
Cc: akpm, david, ljs, liam, vbabka, rppt, surenb, mhocko, shuah,
gourry, Zenghui Yu (Huawei)
From: "Zenghui Yu (Huawei)" <zenghui.yu@linux.dev>
The file-scope variables (pagemap_fd, uffd, page_size, hpage_size and
progname) and most functions of the pagemap_ioctl test are only used
locally, but lack the static storage class. Mark them static so that the
compiler can catch accidental outer references.
Suggested-by: David Hildenbrand (Arm) <david@kernel.org>
Signed-off-by: Zenghui Yu (Huawei) <zenghui.yu@linux.dev>
---
tools/testing/selftests/mm/pagemap_ioctl.c | 43 +++++++++++-----------
1 file changed, 21 insertions(+), 22 deletions(-)
diff --git a/tools/testing/selftests/mm/pagemap_ioctl.c b/tools/testing/selftests/mm/pagemap_ioctl.c
index 3665530eda76..1a87b7483316 100644
--- a/tools/testing/selftests/mm/pagemap_ioctl.c
+++ b/tools/testing/selftests/mm/pagemap_ioctl.c
@@ -36,11 +36,11 @@
#define TEST_ITERATIONS 100
#define PAGEMAP "/proc/self/pagemap"
-int pagemap_fd;
-int uffd;
-size_t page_size;
-size_t hpage_size;
-const char *progname;
+static int pagemap_fd;
+static int uffd;
+static size_t page_size;
+static size_t hpage_size;
+static const char *progname;
#define LEN(region) ((region.end - region.start)/page_size)
@@ -92,8 +92,7 @@ static long pagemap_ioc(void *start, size_t len, void *vec, size_t vec_len, int
return ret;
}
-
-int init_uffd(void)
+static int init_uffd(void)
{
struct uffdio_api uffdio_api;
@@ -116,7 +115,7 @@ int init_uffd(void)
return 0;
}
-int wp_init(void *addr, size_t size)
+static int wp_init(void *addr, size_t size)
{
struct uffdio_register uffdio_register;
struct uffdio_writeprotect wp;
@@ -140,7 +139,7 @@ int wp_init(void *addr, size_t size)
return 0;
}
-int wp_free(void *addr, size_t size)
+static int wp_free(void *addr, size_t size)
{
struct uffdio_register uffdio_register;
@@ -152,7 +151,7 @@ int wp_free(void *addr, size_t size)
return 0;
}
-int wp_addr_range(void *addr, size_t size)
+static int wp_addr_range(void *addr, size_t size)
{
if (pagemap_ioctl(addr, size, NULL, 0,
PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC,
@@ -162,7 +161,7 @@ int wp_addr_range(void *addr, size_t size)
return 0;
}
-void *gethugetlb_mem(size_t size, int *shmid)
+static void *gethugetlb_mem(size_t size, int *shmid)
{
char *mem;
@@ -186,7 +185,7 @@ void *gethugetlb_mem(size_t size, int *shmid)
return mem;
}
-int userfaultfd_tests(void)
+static int userfaultfd_tests(void)
{
size_t mem_size, vec_size, num_pages = 16;
long written;
@@ -230,7 +229,7 @@ int userfaultfd_tests(void)
return 0;
}
-int get_reads(struct page_region *vec, size_t vec_size)
+static int get_reads(struct page_region *vec, size_t vec_size)
{
size_t i;
int sum = 0;
@@ -241,7 +240,7 @@ int get_reads(struct page_region *vec, size_t vec_size)
return sum;
}
-int sanity_tests_sd(void)
+static int sanity_tests_sd(void)
{
size_t mem_size, vec_size, i, total_pages = 0;
long ret, ret2, ret3;
@@ -684,7 +683,7 @@ int sanity_tests_sd(void)
return 0;
}
-int base_tests(char *prefix, char *mem, size_t mem_size, int skip)
+static int base_tests(char *prefix, char *mem, size_t mem_size, int skip)
{
size_t vec_size;
int written;
@@ -789,7 +788,7 @@ int base_tests(char *prefix, char *mem, size_t mem_size, int skip)
return 0;
}
-void *gethugepage(size_t map_size)
+static void *gethugepage(size_t map_size)
{
int ret;
char *map;
@@ -807,7 +806,7 @@ void *gethugepage(size_t map_size)
return map;
}
-int hpage_unit_tests(void)
+static int hpage_unit_tests(void)
{
char *map;
int ret, ret2;
@@ -1001,7 +1000,7 @@ int hpage_unit_tests(void)
return 0;
}
-int unmapped_region_tests(void)
+static int unmapped_region_tests(void)
{
void *start = (void *)0x10000000;
int written;
@@ -1158,7 +1157,7 @@ static void unpopulated_thp_scan_test(void)
munmap(area, 2 * hpage_size);
}
-int sanity_tests(void)
+static int sanity_tests(void)
{
size_t mem_size, vec_size, i, buf_size;
long ret, fd, nr_pages;
@@ -1330,7 +1329,7 @@ int sanity_tests(void)
return 0;
}
-int mprotect_tests(void)
+static int mprotect_tests(void)
{
int ret;
char *mem, *mem2;
@@ -1450,7 +1449,7 @@ static ssize_t get_dirty_pages_reset(char *mem, unsigned int count,
return cnt;
}
-void *thread_proc(void *mem)
+static void *thread_proc(void *mem)
{
int *m = mem;
long curr_faults, faults;
@@ -1583,7 +1582,7 @@ static void transact_test(int page_size)
extra_thread_faults);
}
-void zeropfn_tests(void)
+static void zeropfn_tests(void)
{
size_t mem_size, i;
struct page_region vec;
--
2.53.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 3/3] selftests/mm: init page sizes early in pagemap_ioctl test
2026-09-08 13:41 [PATCH v2 0/3] selftests/mm: pagemap_ioctl test fixes and cleanups Zenghui Yu
2026-09-08 13:41 ` [PATCH v2 1/3] selftests/mm: fix size truncation in pagemap_ioctl test Zenghui Yu
2026-09-08 13:43 ` [PATCH v2 2/3] selftests/mm: mark file-local symbols of pagemap_ioctl.c static Zenghui Yu
@ 2026-09-08 13:44 ` Zenghui Yu
2026-09-08 13:50 ` Zenghui Yu
2 siblings, 1 reply; 5+ messages in thread
From: Zenghui Yu @ 2026-09-08 13:44 UTC (permalink / raw)
To: linux-mm, linux-kselftest, linux-kernel
Cc: akpm, david, ljs, liam, vbabka, rppt, surenb, mhocko, shuah,
gourry, Zenghui Yu (Huawei)
From: "Zenghui Yu (Huawei)" <zenghui.yu@linux.dev>
Initialize page_size and hpage_size before calling init_uffd(),
hugetlb_setup_default(), etc. That won't fix anything, but it is safer and
saner to get these globals set up before doing other things.
While at it, drop the page_size parameter of transact_test(), which is
actually unnecessary.
Suggested-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Zenghui Yu (Huawei) <zenghui.yu@linux.dev>
---
tools/testing/selftests/mm/pagemap_ioctl.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/tools/testing/selftests/mm/pagemap_ioctl.c b/tools/testing/selftests/mm/pagemap_ioctl.c
index 1a87b7483316..d9a4fb782ecf 100644
--- a/tools/testing/selftests/mm/pagemap_ioctl.c
+++ b/tools/testing/selftests/mm/pagemap_ioctl.c
@@ -1489,7 +1489,7 @@ static void *thread_proc(void *mem)
return NULL;
}
-static void transact_test(int page_size)
+static void transact_test(void)
{
unsigned int i, count, extra_pages;
unsigned int c;
@@ -1653,6 +1653,9 @@ int main(int __attribute__((unused)) argc, char *argv[])
ksft_print_header();
+ page_size = getpagesize();
+ hpage_size = read_pmd_pagesize();
+
if (init_uffd())
ksft_exit_skip("Failed to initialize userfaultfd\n");
@@ -1661,9 +1664,6 @@ int main(int __attribute__((unused)) argc, char *argv[])
ksft_set_plan(119);
- page_size = getpagesize();
- hpage_size = read_pmd_pagesize();
-
pagemap_fd = open(PAGEMAP, O_RDONLY);
if (pagemap_fd < 0)
ksft_exit_fail_msg("Failed to open " PAGEMAP "\n");
@@ -1823,7 +1823,7 @@ int main(int __attribute__((unused)) argc, char *argv[])
mprotect_tests();
/* 13. Transact test */
- transact_test(page_size);
+ transact_test();
/* 14. Sanity testing */
sanity_tests();
--
2.53.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2 3/3] selftests/mm: init page sizes early in pagemap_ioctl test
2026-09-08 13:44 ` [PATCH v2 3/3] selftests/mm: init page sizes early in pagemap_ioctl test Zenghui Yu
@ 2026-09-08 13:50 ` Zenghui Yu
0 siblings, 0 replies; 5+ messages in thread
From: Zenghui Yu @ 2026-09-08 13:50 UTC (permalink / raw)
To: linux-mm, linux-kselftest, linux-kernel
Cc: akpm, david, ljs, liam, vbabka, rppt, surenb, mhocko, shuah, gourry
On 9/8/26 9:44 PM, Zenghui Yu wrote:
> From: "Zenghui Yu (Huawei)" <zenghui.yu@linux.dev>
>
> Initialize page_size and hpage_size before calling init_uffd(),
> hugetlb_setup_default(), etc. That won't fix anything, but it is safer and
> saner to get these globals set up before doing other things.
>
> While at it, drop the page_size parameter of transact_test(), which is
> actually unnecessary.
>
> Suggested-by: Andrew Morton <akpm@linux-foundation.org>
See https://lore.kernel.org/20260628111329.9cfcd9c67925869307020aba@linux-foundation.org/ .
> Signed-off-by: Zenghui Yu (Huawei) <zenghui.yu@linux.dev>
> ---
> tools/testing/selftests/mm/pagemap_ioctl.c | 10 +++++-----
> 1 file changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/tools/testing/selftests/mm/pagemap_ioctl.c b/tools/testing/selftests/mm/pagemap_ioctl.c
> index 1a87b7483316..d9a4fb782ecf 100644
> --- a/tools/testing/selftests/mm/pagemap_ioctl.c
> +++ b/tools/testing/selftests/mm/pagemap_ioctl.c
> @@ -1489,7 +1489,7 @@ static void *thread_proc(void *mem)
> return NULL;
> }
>
> -static void transact_test(int page_size)
> +static void transact_test(void)
> {
> unsigned int i, count, extra_pages;
> unsigned int c;
> @@ -1653,6 +1653,9 @@ int main(int __attribute__((unused)) argc, char *argv[])
>
> ksft_print_header();
>
> + page_size = getpagesize();
> + hpage_size = read_pmd_pagesize();
> +
> if (init_uffd())
> ksft_exit_skip("Failed to initialize userfaultfd\n");
>
> @@ -1661,9 +1664,6 @@ int main(int __attribute__((unused)) argc, char *argv[])
>
> ksft_set_plan(119);
>
> - page_size = getpagesize();
> - hpage_size = read_pmd_pagesize();
> -
> pagemap_fd = open(PAGEMAP, O_RDONLY);
> if (pagemap_fd < 0)
> ksft_exit_fail_msg("Failed to open " PAGEMAP "\n");
> @@ -1823,7 +1823,7 @@ int main(int __attribute__((unused)) argc, char *argv[])
> mprotect_tests();
>
> /* 13. Transact test */
> - transact_test(page_size);
> + transact_test();
>
> /* 14. Sanity testing */
> sanity_tests();
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-09-08 13:51 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-08 13:41 [PATCH v2 0/3] selftests/mm: pagemap_ioctl test fixes and cleanups Zenghui Yu
2026-09-08 13:41 ` [PATCH v2 1/3] selftests/mm: fix size truncation in pagemap_ioctl test Zenghui Yu
2026-09-08 13:43 ` [PATCH v2 2/3] selftests/mm: mark file-local symbols of pagemap_ioctl.c static Zenghui Yu
2026-09-08 13:44 ` [PATCH v2 3/3] selftests/mm: init page sizes early in pagemap_ioctl test Zenghui Yu
2026-09-08 13:50 ` Zenghui Yu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®