diff --git a/tools/testing/selftests/mm/run_vmtests.sh b/tools/testing/selftests/mm/run_vmtests.sh index fe140a9f4f9d..22e45207cf6b 100755 --- a/tools/testing/selftests/mm/run_vmtests.sh +++ b/tools/testing/selftests/mm/run_vmtests.sh @@ -412,7 +412,7 @@ CATEGORY="thp" run_test ./khugepaged -s 2 CATEGORY="thp" run_test ./transhuge-stress -d 20 -CATEGORY="thp" run_test ./split_huge_page_test +CATEGORY="thp" run_test ./split_huge_page_test ${SPLIT_HUGE_PAGE_TEST_XFS_PATH} CATEGORY="migration" run_test ./migration diff --git a/tools/testing/selftests/mm/split_huge_page_test.c b/tools/testing/selftests/mm/split_huge_page_test.c index cf09fdc9ef22..047883473b84 100644 --- a/tools/testing/selftests/mm/split_huge_page_test.c +++ b/tools/testing/selftests/mm/split_huge_page_test.c @@ -26,7 +26,6 @@ uint64_t pmd_pagesize; #define SPLIT_DEBUGFS "/sys/kernel/debug/split_huge_pages" #define SMAP_PATH "/proc/self/smaps" -#define THP_FS_PATH "/mnt/thp_fs" #define INPUT_MAX 80 #define PID_FMT "%d,0x%lx,0x%lx,%d" @@ -268,7 +267,45 @@ void split_file_backed_thp(void) ksft_exit_fail_msg("Error occurred\n"); } -void create_pagecache_thp_and_fd(const char *testfile, size_t fd_size, int *fd, char **addr) +bool prepare_thp_fs(const char *xfs_dev_loc, char *thp_fs_template, + const char **thp_fs_loc) +{ + bool mounted = false; + + *thp_fs_loc = mkdtemp(thp_fs_template); + + if (!*thp_fs_loc) + ksft_exit_fail_msg("cannot create temp folder\n"); + + if (xfs_dev_loc) { + int status = mount(xfs_dev_loc, *thp_fs_loc, "xfs", 0, NULL); + + if (status) + ksft_exit_fail_msg("Unable to mount xfs for testing\n"); + mounted = true; + } + return mounted; +} + +void cleanup_thp_fs(const char *thp_fs_loc, bool mounted) +{ + int status; + + if (mounted) { + status = umount(thp_fs_loc); + if (status) + ksft_exit_fail_msg("Unable to umount %s\n", + thp_fs_loc); + } + + status = rmdir(thp_fs_loc); + if (status) + ksft_exit_fail_msg("cannot remove tmp dir: %s\n", + strerror(errno)); +} + +int create_pagecache_thp_and_fd(const char *testfile, size_t fd_size, int *fd, + char **addr) { size_t i; int dummy; @@ -277,7 +314,7 @@ void create_pagecache_thp_and_fd(const char *testfile, size_t fd_size, int *fd, *fd = open(testfile, O_CREAT | O_RDWR, 0664); if (*fd == -1) - ksft_exit_fail_msg("Failed to create a file at "THP_FS_PATH); + ksft_exit_fail_msg("Failed to create a file at %s\n", testfile); for (i = 0; i < fd_size; i++) { unsigned char byte = (unsigned char)i; @@ -299,7 +336,7 @@ void create_pagecache_thp_and_fd(const char *testfile, size_t fd_size, int *fd, *fd = open(testfile, O_RDWR); if (*fd == -1) { - ksft_perror("Failed to open a file at "THP_FS_PATH); + ksft_perror("Failed to open testfile\n"); goto err_out_unlink; } @@ -314,26 +351,37 @@ void create_pagecache_thp_and_fd(const char *testfile, size_t fd_size, int *fd, dummy += *(*addr + i); if (!check_huge_file(*addr, fd_size / pmd_pagesize, pmd_pagesize)) { - ksft_print_msg("No large pagecache folio generated, please mount a filesystem supporting large folio at "THP_FS_PATH"\n"); - goto err_out_close; + ksft_print_msg("No large pagecache folio generated, please provide a filesystem supporting large folio\n"); + unlink(testfile); + ksft_test_result_skip("Pagecache folio split skipped\n"); + return -2; } - return; + return 0; err_out_close: close(*fd); err_out_unlink: unlink(testfile); ksft_exit_fail_msg("Failed to create large pagecache folios\n"); + return -1; } -void split_thp_in_pagecache_to_order(size_t fd_size, int order) +void split_thp_in_pagecache_to_order(size_t fd_size, int order, const char *fs_loc) { int fd; char *addr; size_t i; - const char testfile[] = THP_FS_PATH "/test"; + char testfile[INPUT_MAX]; int err = 0; - create_pagecache_thp_and_fd(testfile, fd_size, &fd, &addr); + err = snprintf(testfile, INPUT_MAX, "%s/test", fs_loc); + + if (err < 0) + ksft_exit_fail_msg("cannot generate right test file name\n"); + + err = create_pagecache_thp_and_fd(testfile, fd_size, &fd, &addr); + if (err) + return; + err = 0; write_debugfs(PID_FMT, getpid(), (uint64_t)addr, (uint64_t)addr + fd_size, order); @@ -351,6 +399,7 @@ void split_thp_in_pagecache_to_order(size_t fd_size, int order) } out: + munmap(addr, fd_size); close(fd); unlink(testfile); if (err) @@ -360,8 +409,11 @@ void split_thp_in_pagecache_to_order(size_t fd_size, int order) int main(int argc, char **argv) { - int i; + int i, mounted; size_t fd_size; + char *optional_xfs_dev_loc = NULL; + char fs_loc_template[] = "/tmp/thp_fs_XXXXXX"; + const char *fs_loc; ksft_print_header(); @@ -370,6 +422,9 @@ int main(int argc, char **argv) ksft_finished(); } + if (argc > 1) + optional_xfs_dev_loc = argv[1]; + ksft_set_plan(3+9); pagesize = getpagesize(); @@ -384,8 +439,11 @@ int main(int argc, char **argv) split_pte_mapped_thp(); split_file_backed_thp(); + mounted = prepare_thp_fs(optional_xfs_dev_loc, fs_loc_template, + &fs_loc); for (i = 8; i >= 0; i--) - split_thp_in_pagecache_to_order(fd_size, i); + split_thp_in_pagecache_to_order(fd_size, i, fs_loc); + cleanup_thp_fs(fs_loc, mounted); ksft_finished();