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: 1. split_pte_mapped_thp: the test already uses kpageflags to check; 2. split_file_backed_thp: no vaddr available.
Signed-off-by: Zi Yan ziy@nvidia.com --- .../selftests/mm/split_huge_page_test.c | 67 +++++++++++++------ 1 file changed, 46 insertions(+), 21 deletions(-)
diff --git a/tools/testing/selftests/mm/split_huge_page_test.c b/tools/testing/selftests/mm/split_huge_page_test.c index 3c761228e451..cd34000279fe 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" @@ -38,6 +42,11 @@ uint64_t pmd_pagesize; #define KPF_THP (1UL<<22) #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; @@ -153,6 +162,7 @@ void split_pmd_thp_to_order(int order) char *one_page; size_t len = 4 * pmd_pagesize; size_t i; + int orders[NR_ORDERS];
one_page = memalign(pmd_pagesize, len); if (!one_page) @@ -174,6 +184,12 @@ 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); + orders[order] = 4 << (pmd_order - order); + if (check_folio_orders((uint64_t)one_page >> pageshift, + len >> pageshift, pagemap_fd, kpageflags_fd, + orders, NR_ORDERS)) + ksft_exit_fail_msg("Unexpected THP split\n");
if (!check_huge_anon(one_page, 0, pmd_pagesize)) ksft_exit_fail_msg("Still AnonHugePages not split\n"); @@ -188,22 +204,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) - ksft_exit_fail_msg("read kpageflags: %s\n", strerror(errno));
one_page = mmap((void *)(1UL << 30), len, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); @@ -261,8 +261,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) @@ -471,6 +469,7 @@ void split_thp_in_pagecache_to_order_at(size_t fd_size, const char *fs_loc, size_t i; char testfile[INPUT_MAX]; int err = 0; + int orders[NR_ORDERS];
err = snprintf(testfile, INPUT_MAX, "%s/test", fs_loc);
@@ -482,12 +481,21 @@ void split_thp_in_pagecache_to_order_at(size_t fd_size, const char *fs_loc, return; err = 0;
- if (offset == -1) + memset(orders, 0, sizeof(int) * NR_ORDERS); + if (offset == -1) { write_debugfs(PID_FMT, getpid(), (uint64_t)addr, (uint64_t)addr + fd_size, order); - else + orders[order] = fd_size / (pagesize << order); + } else { + int times = fd_size / pmd_pagesize; + write_debugfs(PID_FMT_OFFSET, getpid(), (uint64_t)addr, (uint64_t)addr + fd_size, order, offset); + 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) { @@ -496,6 +504,12 @@ void split_thp_in_pagecache_to_order_at(size_t fd_size, const char *fs_loc, goto out; }
+ if (check_folio_orders((uint64_t)addr >> pageshift, + fd_size >> pageshift, pagemap_fd, kpageflags_fd, + orders, NR_ORDERS)) + ksft_exit_fail_msg("Unexpected THP split\n"); + + if (!check_huge_file(addr, 0, pmd_pagesize)) { ksft_print_msg("Still FilePmdMapped not split\n"); err = EXIT_FAILURE; @@ -526,7 +540,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;
@@ -543,6 +556,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); if (!pmd_pagesize) ksft_exit_fail_msg("Reading PMD pagesize failed\n");
@@ -551,6 +565,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(); @@ -575,6 +597,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;