On 10 Aug 2025, at 12:53, Donet Tom wrote:
On 8/9/25 12:31 AM, Zi Yan wrote:
Instead of just checking the existence of PMD folios before and after folio split tests, use check_folio_orders() to check after-split folio orders.
The following tests are not changed:
- split_pte_mapped_thp: the test already uses kpageflags to check;
- split_file_backed_thp: no vaddr available.
Signed-off-by: Zi Yan ziy@nvidia.com
.../selftests/mm/split_huge_page_test.c | 98 ++++++++++++++----- 1 file changed, 72 insertions(+), 26 deletions(-)
diff --git a/tools/testing/selftests/mm/split_huge_page_test.c b/tools/testing/selftests/mm/split_huge_page_test.c index 5ab488fab1cd..161108717f1c 100644 --- a/tools/testing/selftests/mm/split_huge_page_test.c +++ b/tools/testing/selftests/mm/split_huge_page_test.c @@ -25,6 +25,10 @@ uint64_t pagesize; unsigned int pageshift; uint64_t pmd_pagesize; +unsigned int pmd_order; +unsigned int max_order;
+#define NR_ORDERS (max_order + 1) #define SPLIT_DEBUGFS "/sys/kernel/debug/split_huge_pages" #define SMAP_PATH "/proc/self/smaps" @@ -36,6 +40,11 @@ uint64_t pmd_pagesize; #define GET_ORDER(nr_pages) (31 - __builtin_clz(nr_pages)) +const char *pagemap_proc = "/proc/self/pagemap"; +const char *kpageflags_proc = "/proc/kpageflags"; +int pagemap_fd; +int kpageflags_fd;
- int is_backed_by_thp(char *vaddr, int pagemap_file, int kpageflags_file) { uint64_t paddr;
@@ -151,6 +160,11 @@ void split_pmd_thp_to_order(int order) char *one_page; size_t len = 4 * pmd_pagesize; size_t i;
- int *orders;
- orders = (int *)malloc(sizeof(int) * NR_ORDERS);
- if (!orders)
one_page = memalign(pmd_pagesize, len); if (!one_page)ksft_exit_fail_msg("Fail to allocate memory: %s\n", strerror(errno));
@@ -172,12 +186,20 @@ void split_pmd_thp_to_order(int order) if (one_page[i] != (char)i) ksft_exit_fail_msg("%ld byte corrupted\n", i);
- memset(orders, 0, sizeof(int) * NR_ORDERS);
- /* set expected orders */
- orders[order] = 4 << (pmd_order - order);
- if (check_folio_orders(one_page, len, pagemap_fd, kpageflags_fd,
orders, NR_ORDERS))
if (!check_huge_anon(one_page, 0, pmd_pagesize)) ksft_exit_fail_msg("Still AnonHugePages not split\n"); ksft_test_result_pass("Split huge pages to order %d successful\n", order); free(one_page);ksft_exit_fail_msg("Unexpected THP split\n");
- free(orders); } void split_pte_mapped_thp(void)
@@ -186,22 +208,6 @@ void split_pte_mapped_thp(void) size_t len = 4 * pmd_pagesize; uint64_t thp_size; size_t i;
- const char *pagemap_template = "/proc/%d/pagemap";
- const char *kpageflags_proc = "/proc/kpageflags";
- char pagemap_proc[255];
- int pagemap_fd;
- int kpageflags_fd;
- if (snprintf(pagemap_proc, 255, pagemap_template, getpid()) < 0)
ksft_exit_fail_msg("get pagemap proc error: %s\n", strerror(errno));
- pagemap_fd = open(pagemap_proc, O_RDONLY);
- if (pagemap_fd == -1)
ksft_exit_fail_msg("read pagemap: %s\n", strerror(errno));
- kpageflags_fd = open(kpageflags_proc, O_RDONLY);
- if (kpageflags_fd == -1)
one_page = mmap((void *)(1UL << 30), len, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);ksft_exit_fail_msg("read kpageflags: %s\n", strerror(errno));
@@ -259,8 +265,6 @@ void split_pte_mapped_thp(void) ksft_test_result_pass("Split PTE-mapped huge pages successful\n"); munmap(one_page, len);
- close(pagemap_fd);
- close(kpageflags_fd); } void split_file_backed_thp(int order)
@@ -463,10 +467,16 @@ void split_thp_in_pagecache_to_order_at(size_t fd_size, const char *fs_loc, int order, int offset) { int fd;
- char *split_addr; char *addr; size_t i; char testfile[INPUT_MAX]; int err = 0;
- int *orders;
- orders = (int *)malloc(sizeof(int) * NR_ORDERS);
- if (!orders)
err = snprintf(testfile, INPUT_MAX, "%s/test", fs_loc);ksft_exit_fail_msg("Fail to allocate memory: %s\n", strerror(errno));
@@ -474,16 +484,32 @@ void split_thp_in_pagecache_to_order_at(size_t fd_size, const char *fs_loc, ksft_exit_fail_msg("cannot generate right test file name\n"); err = create_pagecache_thp_and_fd(testfile, fd_size, &fd, &addr);
- if (err)
- if (err) {
return;free(orders);
- } err = 0;
- if (offset == -1)
write_debugfs(PID_FMT, getpid(), (uint64_t)addr,
(uint64_t)addr + fd_size, order);
- else
write_debugfs(PID_FMT_OFFSET, getpid(), (uint64_t)addr,
(uint64_t)addr + fd_size, order, offset);
- memset(orders, 0, sizeof(int) * NR_ORDERS);
- if (offset == -1) {
for (split_addr = addr; split_addr < addr + fd_size; split_addr += pmd_pagesize)
write_debugfs(PID_FMT, getpid(), (uint64_t)split_addr,
(uint64_t)split_addr + pagesize, order);
/* set expected orders */
orders[order] = fd_size / (pagesize << order);
- } else {
int times = fd_size / pmd_pagesize;
for (split_addr = addr; split_addr < addr + fd_size; split_addr += pmd_pagesize)
write_debugfs(PID_FMT_OFFSET, getpid(), (uint64_t)split_addr,
(uint64_t)split_addr + pagesize, order, offset);
/* set expected orders */
for (i = order + 1; i < pmd_order; i++)
orders[i] = times;
orders[order] = 2 * times;
- } for (i = 0; i < fd_size; i++) if (*(addr + i) != (char)i) {
@@ -492,6 +518,14 @@ void split_thp_in_pagecache_to_order_at(size_t fd_size, const char *fs_loc, goto out; }
- if (check_folio_orders(addr, fd_size, pagemap_fd, kpageflags_fd, orders,
NR_ORDERS)) {
ksft_print_msg("Unexpected THP split\n");
err = 1;
goto out;
- }
- if (!check_huge_file(addr, 0, pmd_pagesize)) { ksft_print_msg("Still FilePmdMapped not split\n"); err = EXIT_FAILURE;
@@ -499,6 +533,7 @@ void split_thp_in_pagecache_to_order_at(size_t fd_size, const char *fs_loc, } out:
- free(orders); munmap(addr, fd_size); close(fd); unlink(testfile);
@@ -522,7 +557,6 @@ int main(int argc, char **argv) const char *fs_loc; bool created_tmp; int offset;
- unsigned int max_order; unsigned int nr_pages; unsigned int tests;
@@ -539,6 +573,7 @@ int main(int argc, char **argv) pagesize = getpagesize(); pageshift = ffs(pagesize) - 1; pmd_pagesize = read_pmd_pagesize();
- pmd_order = GET_ORDER(pmd_pagesize / pagesize);
I think max_order is also same as pmd_order
nr_pages = pmd_pagesize / pagesize; max_order = GET_ORDER(nr_pages);
Can we use one?
Sure. Will rename max_order to pmd_order. Thanks.
if (!pmd_pagesize) ksft_exit_fail_msg("Reading PMD pagesize failed\n"); @@ -547,6 +582,14 @@ int main(int argc, char **argv) tests = 2 + (max_order - 1) + (2 * max_order) + (max_order - 1) * 4 + 2; ksft_set_plan(tests);
- pagemap_fd = open(pagemap_proc, O_RDONLY);
- if (pagemap_fd == -1)
ksft_exit_fail_msg("read pagemap: %s\n", strerror(errno));
- kpageflags_fd = open(kpageflags_proc, O_RDONLY);
- if (kpageflags_fd == -1)
ksft_exit_fail_msg("read kpageflags: %s\n", strerror(errno));
- fd_size = 2 * pmd_pagesize; split_pmd_zero_pages();
@@ -571,6 +614,9 @@ int main(int argc, char **argv) split_thp_in_pagecache_to_order_at(fd_size, fs_loc, i, offset); cleanup_thp_fs(fs_loc, created_tmp);
- close(pagemap_fd);
- close(kpageflags_fd);
- ksft_finished(); return 0;
Best Regards, Yan, Zi