add anon mTHP collapse test cases
Subsystems (5)
Baolin Wang
reviewerPATCH v2 4/4 selftests: mm: add mTHP collapse test cases
In reply to Baolin WangAdded a new command 'mthp_khugepaged' for mTHP collapse, along with the '-c' parameter to specify the collapse order. Additionally, added mTHP collapse test cases for 'collapse_full', 'collapse_empty', and 'collapse_single_mthp' for anonymous folios. All khugepaged test cases passed.
--- tools/testing/selftests/mm/khugepaged.c | 130 ++++++++++++++++++---- tools/testing/selftests/mm/run_vmtests.sh | 2 + 2 files changed, 113 insertions(+), 19 deletions(-)
tools/testing/selftests/mm/khugepaged.c +111 -19
@@ -26,9 +26,11 @@#define BASE_ADDR ((void *)(1UL << 30))static unsigned long hpage_pmd_size; +static int hpage_pmd_order;static unsigned long page_size;static int hpage_pmd_nr;static int anon_order; +static int collapse_order;#define PID_SMAPS "/proc/self/smaps"#define TEST_FILE "collapse_test_file"
@@ -69,6 +71,7 @@ struct collapse_context { };static struct collapse_context *khugepaged_context; +static struct collapse_context *mthp_khugepaged_context;static struct collapse_context *madvise_context;struct file_info {
@@ -554,25 +557,25 @@ static void madvise_collapse(const char *msg, char *p, int nr_hpages, }#define TICK 500000 -static bool wait_for_scan (const char *msg,char *p,int nr_hpages, -struct mem_ops *ops) +static bool wait_for_scan (const char *msg,char *p,unsigned long size, +int nr_hpages,int collap_order,struct mem_ops *ops) { -unsigned long size = nr_hpages * hpage_pmd_size; +unsigned long hpage_size = page_size << collap_order;int full_scans;int timeout =6 ;/* 3 seconds */ /* Sanity check */ -if (!ops->check_huge (p, size,0 , hpage_pmd_size)) +if (!ops->check_huge (p, size,0 , hpage_size))ksft_exit_fail_msg ("Unexpected huge page\n" ); -madvise (p, nr_hpages * hpage_pmd_size,MADV_HUGEPAGE ); +madvise (p, size,MADV_HUGEPAGE );/* Wait until the second full_scan completed */ full_scans =thp_read_num ("khugepaged/full_scans" ) +2 ;ksft_print_msg ("%s..." , msg);while (timeout--) { -if (ops->check_huge (p, size, nr_hpages, hpage_pmd_size)) +if (ops->check_huge (p, size, nr_hpages, hpage_size))break ;if (thp_read_num ("khugepaged/full_scans" ) >= full_scans)break ;
@@ -595,7 +598,7 @@ static void khugepaged_collapse(const char *msg, char *p, int nr_hpages,if (!is_tmpfs (ops) && ops == &__read_write_file_write_ops) expect = false; -if (wait_for_scan (msg, p, nr_hpages, ops)) { +if (wait_for_scan (msg, p, size, nr_hpages, hpage_pmd_order, ops)) {if (expect)fail ("Timeout" );else
@@ -617,12 +620,62 @@ static void khugepaged_collapse(const char *msg, char *p, int nr_hpages,fail ("Fail" ); } +static void mthp_khugepaged_collapse (const char *msg,char *p,int nr_hpages, +struct mem_ops *ops,bool expect) +{ +unsigned long hpage_size = page_size << collapse_order; +struct thp_settings settings = *thp_current_settings (); +/* mTHP collpase only allocates PMD sized memory */ +unsigned long size = hpage_pmd_size; + +/* Set mTHP setting for mTHP collapse */ +if (ops == &__anon_ops) { + settings.thp_enabled =THP_NEVER ; + settings.hugepages[collapse_order].enabled =THP_MADVISE ; + } + +thp_push_settings (&settings); + +if (wait_for_scan (msg, p, size, nr_hpages, collapse_order, ops)) { +if (expect) +fail ("Timeout" ); +else +success ("OK" ); + +/* Restore THP settings for mTHP collapse. */ +thp_pop_settings (); +return ; + } + +/* +* For file and shmem memory, khugepaged only retracts pte entries after +* putting the new hugepage in the page cache. The hugepage must be +* subsequently refaulted to install the pmd mapping for the mm. +*/ +if (ops != &__anon_ops) + ops->fault (p,0 , nr_hpages * hpage_size); + +if (ops->check_huge (p, size, expect ? nr_hpages :0 , hpage_size)) +success ("OK" ); +else +fail ("Fail" ); + +/* Restore THP settings for mTHP collapse. */ +thp_pop_settings (); +} +static struct collapse_context __khugepaged_context = { .collapse = &khugepaged_collapse, .enforce_pte_scan_limits = true, .name ="khugepaged" , }; +static struct collapse_context __mthp_khugepaged_context = { + .collapse = &mthp_khugepaged_collapse, + .enforce_pte_scan_limits = true, + .name ="mthp_khugepaged" , +}; +static struct collapse_context __madvise_context = { .collapse = &madvise_collapse, .enforce_pte_scan_limits = false,
@@ -661,10 +714,17 @@ static void alloc_at_fault(void)static void collapse_full (struct collapse_context *c,struct mem_ops *ops) {void *p; -int nr_hpages =4 ; +int nr_pmds =4 , nr_hpages =4 ;unsigned long size = nr_hpages * hpage_pmd_size; - p = ops->setup_area (nr_hpages); +/* Only try 1 PMD sized range for mTHP collapse. */ +if (c == &__mthp_khugepaged_context) { + nr_pmds =1 ; + nr_hpages =1 << (hpage_pmd_order - collapse_order); + size = hpage_pmd_size; + } + + p = ops->setup_area (nr_pmds); ops->fault (p,0 , size); c->collapse ("Collapse multiple fully populated PTE table" , p, nr_hpages, ops, true);
@@ -676,10 +736,31 @@ static void collapse_full(struct collapse_context *c, struct mem_ops *ops)static void collapse_empty (struct collapse_context *c,struct mem_ops *ops) { +int nr_hpages =1 ; +void *p; + +if (c == &__mthp_khugepaged_context) + nr_hpages =1 << (hpage_pmd_order - collapse_order); + + p = ops->setup_area (1 ); + c->collapse ("Do not collapse empty PTE table" , p, nr_hpages, ops, false); + ops->cleanup_area (p, hpage_pmd_size); +ksft_test_result_report (exit_status,"%s\n" , __func__); +} + +static void collapse_single_mthp (struct collapse_context *c,struct mem_ops *ops) +{ +unsigned long hpage_size = page_size << collapse_order;void *p; p = ops->setup_area (1 ); - c->collapse ("Do not collapse empty PTE table" , p,1 , ops, false); +/* +* Only fault collapse_order sized ranges, and only check 1 +* collapse_order sized huge page. +*/ + ops->fault (p,0 , hpage_size); + c->collapse ("Collapse PTE table with half PTE entries present" , + p,1 , ops, true); ops->cleanup_area (p, hpage_pmd_size);ksft_test_result_report (exit_status,"%s\n" , __func__); }
@@ -1081,8 +1162,8 @@ static void madvise_retracted_page_tables(struct collapse_context *c, ops->fault (p,0 , size);/* Let khugepaged collapse and leave pmd cleared */ -if (wait_for_scan ("Collapse and leave PMD cleared" , p, nr_hpages, - ops)) { +if (wait_for_scan ("Collapse and leave PMD cleared" , p, size, nr_hpages, + hpage_pmd_order, ops)) {fail ("Timeout" );return ; }
@@ -1098,7 +1179,7 @@ static void usage(void) {fprintf (stderr,"\nUsage: ./khugepaged [OPTIONS] <test type> [dir]\n\n" );fprintf (stderr,"\t<test type>\t: <context>:<mem_type>\n" ); -fprintf (stderr,"\t<context>\t: [all|khugepaged|madvise]\n" ); +fprintf (stderr,"\t<context>\t: [all|khugepaged|mthp_khugepaged|madvise]\n" );fprintf (stderr,"\t<mem_type>\t: [all|anon|file|shmem]\n" );fprintf (stderr,"\n\t\"file,all\" mem_type requires [dir] argument\n" );fprintf (stderr,"\n\t\"file,all\" mem_type requires a file system\n" );
@@ -1109,6 +1190,7 @@ static void usage(void)fprintf (stderr,"\t\t-h: This help message.\n" );fprintf (stderr,"\t\t-s: mTHP size, expressed as page order.\n" );fprintf (stderr,"\t\t Defaults to 0. Use this size for anon or shmem allocations.\n" ); +fprintf (stderr,"\t\t-c: collapse order for mTHP collapse, expressed as page order.\n" );exit (1 ); }
@@ -1118,11 +1200,14 @@ static void parse_test_type(int argc, char **argv)char *buf;const char *token; -while ((opt =getopt (argc, argv,"s:h" )) !=-1 ) { +while ((opt =getopt (argc, argv,"s:c:h" )) !=-1 ) {switch (opt) {case 's' : anon_order =atoi (optarg);break ; +case 'c' : + collapse_order =atoi (optarg); +break ;case 'h' :default :usage ();
@@ -1148,6 +1233,10 @@ static void parse_test_type(int argc, char **argv) madvise_context = &__madvise_context; }else if (!strcmp (token,"khugepaged" )) { khugepaged_context = &__khugepaged_context; + }else if (!strcmp (token,"mthp_khugepaged" )) { + mthp_khugepaged_context = &__mthp_khugepaged_context; +if (collapse_order <=0 || collapse_order >= hpage_pmd_order) +usage (); }else if (!strcmp (token,"madvise" )) { madvise_context = &__madvise_context; }else {
@@ -1213,7 +1302,6 @@ static int nr_test_cases;int main (int argc,char **argv) { -int hpage_pmd_order;struct thp_settings default_settings = { .thp_enabled =THP_MADVISE , .thp_defrag =THP_DEFRAG_ALWAYS ,
@@ -1239,10 +1327,6 @@ int main(int argc, char **argv)if (!thp_is_enabled ())ksft_exit_skip ("Transparent Hugepages not available\n" ); -parse_test_type (argc, argv); - -setbuf (stdout,NULL ); - page_size =getpagesize (); hpage_pmd_size =read_pmd_pagesize ();if (!hpage_pmd_size)
@@ -1250,6 +1334,10 @@ int main(int argc, char **argv) hpage_pmd_nr = hpage_pmd_size / page_size; hpage_pmd_order =__builtin_ctz (hpage_pmd_nr); +parse_test_type (argc, argv); + +setbuf (stdout,NULL ); + default_settings.khugepaged.max_ptes_none = hpage_pmd_nr -1 ; default_settings.khugepaged.max_ptes_swap = hpage_pmd_nr /8 ; default_settings.khugepaged.max_ptes_shared = hpage_pmd_nr /2 ;
@@ -1267,6 +1355,7 @@ int main(int argc, char **argv)TEST (collapse_full, khugepaged_context, read_write_file_read_ops);TEST (collapse_full, khugepaged_context, read_write_file_write_ops);TEST (collapse_full, khugepaged_context, shmem_ops); +TEST (collapse_full, mthp_khugepaged_context, anon_ops);TEST (collapse_full, madvise_context, anon_ops);TEST (collapse_full, madvise_context, read_only_file_ops);TEST (collapse_full, madvise_context, read_write_file_read_ops);
@@ -1274,8 +1363,11 @@ int main(int argc, char **argv)TEST (collapse_full, madvise_context, shmem_ops);TEST (collapse_empty, khugepaged_context, anon_ops); +TEST (collapse_empty, mthp_khugepaged_context, anon_ops);TEST (collapse_empty, madvise_context, anon_ops); +TEST (collapse_single_mthp, mthp_khugepaged_context, anon_ops); +TEST (collapse_single_pte_entry, khugepaged_context, anon_ops);TEST (collapse_single_pte_entry, khugepaged_context, read_only_file_ops);TEST (collapse_single_pte_entry, khugepaged_context, read_write_file_read_ops);
tools/testing/selftests/mm/run_vmtests.sh +2 -0
@@ -410,6 +410,8 @@ CATEGORY="thp" run_test ./khugepaged all:shmem CATEGORY="thp" run_test ./khugepaged -s 4 all:shmem +CATEGORY="thp" run_test ./khugepaged -c 4 mthp_khugepaged:anon + # Try to create XFS if not provided if [ -z "${SPLIT_HUGE_PAGE_TEST_XFS_PATH}" ]; then if test_selected "thp"; then
Signature · 1 line
2.47.3
Baolin Wang
reviewerv2 cover add anon mTHP collapse test cases
This patchset is split from the previous shmem mTHP collapse patchset[1], which only adds anon mTHP collapse selftests. All khugepaged test cases can pass.
[1] https://lore.kernel.org/all/[email protected]/
Changes from v1:
- Add order and hpage_size check (per Sashiko).
- Change to use THP_MADVISE for mTHP collapse (per Sashiko).
Baolin Wang (4):
selftests: mm: extend the check_huge() to support mTHP check
selftests: mm: move gather_after_split_folio_orders() into vm_util.c
file
selftests: mm: implement the mTHP-sized hugepage check helpers
selftests: mm: add mTHP collapse test cases
.../selftests/mm/folio_split_race_test.c | 2 +- tools/testing/selftests/mm/khugepaged.c | 190 +++++++++++++----- tools/testing/selftests/mm/pagemap_ioctl.c | 2 +- .../testing/selftests/mm/prctl_thp_disable.c | 2 +- tools/testing/selftests/mm/run_vmtests.sh | 2 + tools/testing/selftests/mm/soft-dirty.c | 2 +- .../selftests/mm/split_huge_page_test.c | 139 +------------ tools/testing/selftests/mm/uffd-common.c | 4 +- tools/testing/selftests/mm/vm_util.c | 185 ++++++++++++++++- tools/testing/selftests/mm/vm_util.h | 8 +- 10 files changed, 344 insertions(+), 192 deletions(-)
Signature · 1 line
2.47.3
Baolin Wang
reviewerPATCH v2 2/4 selftests: mm: move gather_after_split_folio_orders() into vm_util.c file
Move gather_after_split_folio_orders() to vm_util.c as a helper function in preparation for implementing checks for mTHP collapse. While we are at it, rename this function to indicate that it is not only used for large folio splits.
No functional changes.
--- .../selftests/mm/split_huge_page_test.c | 125 +----------------- tools/testing/selftests/mm/vm_util.c | 119 +++++++++++++++++ tools/testing/selftests/mm/vm_util.h | 2 + 3 files changed, 122 insertions(+), 124 deletions(-)
tools/testing/selftests/mm/split_huge_page_test.c +1 -124
@@ -104,129 +104,6 @@ static bool is_backed_by_folio(char *vaddr, int order, int pagemap_fd,return false; } -static int vaddr_pageflags_get (char *vaddr,int pagemap_fd,int kpageflags_fd, -uint64_t *flags) -{ -unsigned long pfn; - - pfn =pagemap_get_pfn (pagemap_fd, vaddr); - -/* non-present PFN */ -if (pfn ==-1UL ) -return 1 ; - -if (pageflags_get (pfn, kpageflags_fd, flags)) -return -1 ; - -return 0 ; -} - -/* -* gather_after_split_folio_orders - scan through [vaddr_start, len) and record -* folio orders -* -* @vaddr_start: start vaddr -* @len: range length -* @pagemap_fd: file descriptor to /proc/<pid>/pagemap -* @kpageflags_fd: file descriptor to /proc/kpageflags -* @orders: output folio order array -* @nr_orders: folio order array size -* -* gather_after_split_folio_orders() scan through [vaddr_start, len) and check -* all folios within the range and record their orders. All order-0 pages will -* be recorded. Non-present vaddr is skipped. -* -* NOTE: the function is used to check folio orders after a split is performed, -* so it assumes [vaddr_start, len) fully maps to after-split folios within that -* range. -* -* Return: 0 - no error, -1 - unhandled cases -*/ -static int gather_after_split_folio_orders (char *vaddr_start,size_t len, -int pagemap_fd,int kpageflags_fd,int orders[],int nr_orders) -{ -uint64_t page_flags =0 ; -int cur_order =-1 ; -char *vaddr; - -if (pagemap_fd ==-1 || kpageflags_fd ==-1 ) -return -1 ; -if (!orders) -return -1 ; -if (nr_orders <=0 ) -return -1 ; - -for (vaddr = vaddr_start; vaddr < vaddr_start + len;) { -char *next_folio_vaddr; -int status; - - status =vaddr_pageflags_get (vaddr, pagemap_fd, kpageflags_fd, - &page_flags); -if (status <0 ) -return -1 ; - -/* skip non present vaddr */ -if (status ==1 ) { - vaddr +=psize (); -continue ; - } - -/* all order-0 pages with possible false postive (non folio) */ -if (!(page_flags & (KPF_COMPOUND_HEAD |KPF_COMPOUND_TAIL ))) { - orders[0 ]++; - vaddr +=psize (); -continue ; - } - -/* skip non thp compound pages */ -if (!(page_flags &KPF_THP )) { - vaddr +=psize (); -continue ; - } - -/* vpn points to part of a THP at this point */ -if (page_flags &KPF_COMPOUND_HEAD ) - cur_order =1 ; -else { - vaddr +=psize (); -continue ; - } - - next_folio_vaddr = vaddr + (1UL << (cur_order +pshift ())); - -if (next_folio_vaddr >= vaddr_start + len) -break ; - -while ((status =vaddr_pageflags_get (next_folio_vaddr, - pagemap_fd, kpageflags_fd, - &page_flags)) >=0 ) { -/* -* non present vaddr, next compound head page, or -* order-0 page -*/ -if (status ==1 || - (page_flags &KPF_COMPOUND_HEAD ) || - !(page_flags & (KPF_COMPOUND_HEAD |KPF_COMPOUND_TAIL ))) { -if (cur_order < nr_orders) { - orders[cur_order]++; - cur_order =-1 ; - vaddr = next_folio_vaddr; - } -break ; - } - - cur_order++; - next_folio_vaddr = vaddr + (1UL << (cur_order +pshift ())); - } - -if (status <0 ) -return status; - } -if (cur_order >0 && cur_order < nr_orders) - orders[cur_order]++; -return 0 ; -} -static int check_after_split_folio_orders (char *vaddr_start,size_t len,int pagemap_fd,int kpageflags_fd,int orders[],int nr_orders) {
@@ -240,7 +117,7 @@ static int check_after_split_folio_orders(char *vaddr_start, size_t len,ksft_exit_fail_msg ("Cannot allocate memory for vaddr_orders" );memset (vaddr_orders,0 ,sizeof (int ) * nr_orders); - status =gather_after_split_folio_orders (vaddr_start, len, pagemap_fd, + status =gather_folio_orders (vaddr_start, len, pagemap_fd, kpageflags_fd, vaddr_orders, nr_orders);if (status)ksft_exit_fail_msg ("gather folio info failed\n" );
tools/testing/selftests/mm/vm_util.c +119 -0
125 lines not on this page · raw message
tools/testing/selftests/mm/vm_util.h +2 -0
@@ -95,6 +95,8 @@ bool check_huge_file(void *addr, unsigned long size, int nr_hpages, uint64_t hpabool check_huge_shmem (void *addr,unsigned long size,int nr_hpages,uint64_t hpage_size);int64_t allocate_transhuge (void *ptr,int pagemap_fd);int pageflags_get (unsigned long pfn,int kpageflags_fd,uint64_t *flags); +int gather_folio_orders (char *vaddr_start,size_t len, +int pagemap_fd,int kpageflags_fd,int orders[],int nr_orders);int uffd_register (int uffd,void *addr,uint64_t len,bool miss,bool wp,bool minor);
Signature · 1 line
2.47.3
Baolin Wang
reviewerPATCH v2 1/4 selftests: mm: extend the check_huge() to support mTHP check
In reply to Baolin WangTo support checking for various sized mTHPs during mTHP collapse, extend the check_huge() function prototype to accept two new parameters specifying the address range and mTHP size, in preparation for the following patches.
No functional changes.
--- .../selftests/mm/folio_split_race_test.c | 2 +- tools/testing/selftests/mm/khugepaged.c | 66 ++++++++++--------- tools/testing/selftests/mm/pagemap_ioctl.c | 2 +- .../testing/selftests/mm/prctl_thp_disable.c | 2 +- tools/testing/selftests/mm/soft-dirty.c | 2 +- .../selftests/mm/split_huge_page_test.c | 14 ++-- tools/testing/selftests/mm/uffd-common.c | 4 +- tools/testing/selftests/mm/vm_util.c | 6 +- tools/testing/selftests/mm/vm_util.h | 6 +- 9 files changed, 56 insertions(+), 48 deletions(-)
tools/testing/selftests/mm/folio_split_race_test.c +1 -1
@@ -182,7 +182,7 @@ static uint64_t run_iteration(void)for (i =0 ; i <TOTAL_PAGES ; i++)fill_page (mmap_base, i); -if (!check_huge_shmem (mmap_base,NR_PMD_PAGE , pmd_pagesize)) +if (!check_huge_shmem (mmap_base,FILE_SIZE ,NR_PMD_PAGE , pmd_pagesize))ksft_exit_fail_msg ("No shmem THP is allocated\n" );if (pthread_barrier_init (&ctl.barrier,NULL ,NUM_READER_THREADS +1 ) !=0 )
tools/testing/selftests/mm/khugepaged.c +36 -30
238 lines not on this page · raw message
tools/testing/selftests/mm/pagemap_ioctl.c +1 -1
@@ -1085,7 +1085,7 @@ static void unpopulated_written_test(const char *name, char *mem, long size,memset (mem,1 , size);if (use_thp && (madvise (mem, size,MADV_COLLAPSE ) || - !check_huge_anon (mem, size / hpage_size, hpage_size))) { + !check_huge_anon (mem, size, size / hpage_size, hpage_size))) {ksft_test_result_skip ("%s could not form a THP\n" , name); goto out; }
tools/testing/selftests/mm/prctl_thp_disable.c +1 -1
@@ -67,7 +67,7 @@ static int test_mmap_thp(enum thp_collapse_type madvise_buf, size_t pmdsize)/* HACK: make sure we have a separate VMA that we can check reliably. */ mprotect (mem, pmdsize,PROT_READ ); - ret =check_huge_anon (mem,1 , pmdsize); + ret =check_huge_anon (mem, pmdsize,1 , pmdsize);munmap (mmap_mem, mmap_size);return ret; }
tools/testing/selftests/mm/soft-dirty.c +1 -1
@@ -103,7 +103,7 @@ static void test_hugepage(int pagemap_fd, int pagesize)for (i =0 ; i < hpage_len; i++) map[i] = (char )i; -if (check_huge_anon (map,1 , hpage_len)) { +if (check_huge_anon (map, hpage_len,1 , hpage_len)) {ksft_test_result_pass ("Test %s huge page allocation\n" , __func__);clear_softdirty ();
tools/testing/selftests/mm/split_huge_page_test.c +7 -7
@@ -296,7 +296,7 @@ static void verify_rss_anon_split_huge_page_all_zeroes(char *one_page, int nr_hpunsigned long rss_anon_before, rss_anon_after;size_t i; -if (!check_huge_anon (one_page, nr_hpages, pmd_pagesize)) +if (!check_huge_anon (one_page, nr_hpages * pmd_pagesize, nr_hpages, pmd_pagesize))ksft_exit_fail_msg ("No THP is allocated\n" ); rss_anon_before =rss_anon ();
@@ -311,7 +311,7 @@ static void verify_rss_anon_split_huge_page_all_zeroes(char *one_page, int nr_hpif (one_page[i] != (char )0 )ksft_exit_fail_msg ("%ld byte corrupted\n" , i); -if (!check_huge_anon (one_page,0 , pmd_pagesize)) +if (!check_huge_anon (one_page, nr_hpages * pmd_pagesize,0 , pmd_pagesize))ksft_exit_fail_msg ("Still AnonHugePages not split\n" ); rss_anon_after =rss_anon ();
@@ -347,7 +347,7 @@ static void split_pmd_thp_to_order(int order)for (i =0 ; i < len; i++) one_page[i] = (char )i; -if (!check_huge_anon (one_page,4 , pmd_pagesize)) +if (!check_huge_anon (one_page,4 * pmd_pagesize,4 , pmd_pagesize))ksft_exit_fail_msg ("No THP is allocated\n" );/* split all THPs */
@@ -366,7 +366,7 @@ static void split_pmd_thp_to_order(int order) (pmd_order + 1)))ksft_exit_fail_msg ("Unexpected THP split\n" ); -if (!check_huge_anon (one_page,0 , pmd_pagesize)) +if (!check_huge_anon (one_page,4 * pmd_pagesize,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);
@@ -393,7 +393,7 @@ static void split_pte_mapped_thp(void)for (i =0 ; i < thp_area_size; i++) thp_area[i] = (char )i; -if (!check_huge_anon (thp_area, nr_thps, pmd_pagesize)) { +if (!check_huge_anon (thp_area, nr_thps * pmd_pagesize, nr_thps, pmd_pagesize)) {ksft_test_result_skip ("Not all THPs allocated\n" ); goto out; }
@@ -657,7 +657,7 @@ static int create_pagecache_thp_and_fd(const char *testfile, size_t fd_size,force_read_pages (*addr, fd_size / pmd_pagesize, pmd_pagesize); -if (!check_huge_file (*addr, fd_size / pmd_pagesize, pmd_pagesize)) { +if (!check_huge_file (*addr, fd_size, fd_size / pmd_pagesize, pmd_pagesize)) {ksft_print_msg ("No large pagecache folio generated, please provide a filesystem supporting large folio\n" );munmap (*addr, fd_size);close (*fd);
@@ -735,7 +735,7 @@ static void split_thp_in_pagecache_to_order_at(size_t fd_size, goto out; } -if (!check_huge_file (addr,0 , pmd_pagesize)) { +if (!check_huge_file (addr, fd_size,0 , pmd_pagesize)) {ksft_print_msg ("Still FilePmdMapped not split\n" ); err =EXIT_FAILURE ; goto out;
tools/testing/selftests/mm/uffd-common.c +3 -1
@@ -194,7 +194,9 @@ static void shmem_alias_mapping(uffd_global_test_opts_t *gopts, __u64 *start,static void shmem_check_pmd_mapping (uffd_global_test_opts_t *gopts,void *p,int expect_nr_hpages) { -if (!check_huge_shmem (gopts->area_dst_alias, expect_nr_hpages, +unsigned long size = expect_nr_hpages *read_pmd_pagesize (); + +if (!check_huge_shmem (gopts->area_dst_alias, size, expect_nr_hpages,read_pmd_pagesize ()))err ("Did not find expected %d number of hugepages" , expect_nr_hpages);
tools/testing/selftests/mm/vm_util.c +3 -3
@@ -247,17 +247,17 @@ bool __check_huge(void *addr, char *pattern, int nr_hpages,return thp == (nr_hpages * (hpage_size >>10 )); } -bool check_huge_anon (void *addr,int nr_hpages,uint64_t hpage_size) +bool check_huge_anon (void *addr,unsigned long size,int nr_hpages,uint64_t hpage_size) {return __check_huge (addr,"AnonHugePages: " , nr_hpages, hpage_size); } -bool check_huge_file (void *addr,int nr_hpages,uint64_t hpage_size) +bool check_huge_file (void *addr,unsigned long size,int nr_hpages,uint64_t hpage_size) {return __check_huge (addr,"FilePmdMapped:" , nr_hpages, hpage_size); } -bool check_huge_shmem (void *addr,int nr_hpages,uint64_t hpage_size) +bool check_huge_shmem (void *addr,unsigned long size,int nr_hpages,uint64_t hpage_size) {return __check_huge (addr,"ShmemPmdMapped:" , nr_hpages, hpage_size); }
tools/testing/selftests/mm/vm_util.h +3 -3
@@ -90,9 +90,9 @@ void clear_softdirty(void);bool check_for_pattern (FILE *fp,const char *pattern,char *buf,size_t len);uint64_t read_pmd_pagesize (void );unsigned long rss_anon (void ); -bool check_huge_anon (void *addr,int nr_hpages,uint64_t hpage_size); -bool check_huge_file (void *addr,int nr_hpages,uint64_t hpage_size); -bool check_huge_shmem (void *addr,int nr_hpages,uint64_t hpage_size); +bool check_huge_anon (void *addr,unsigned long size,int nr_hpages,uint64_t hpage_size); +bool check_huge_file (void *addr,unsigned long size,int nr_hpages,uint64_t hpage_size); +bool check_huge_shmem (void *addr,unsigned long size,int nr_hpages,uint64_t hpage_size);int64_t allocate_transhuge (void *ptr,int pagemap_fd);int pageflags_get (unsigned long pfn,int kpageflags_fd,uint64_t *flags);
Signature · 1 line
2.47.3
Baolin Wang
reviewerPATCH v2 3/4 selftests: mm: implement the mTHP-sized hugepage check helpers
In reply to Baolin WangImplement mTHP-sized hugepage checking helpers using gather_folio_orders(). Also rename the existing PMD-sized huge page check function to __check_pmd_huge() for clarity.
--- tools/testing/selftests/mm/vm_util.c | 60 ++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 4 deletions(-)
tools/testing/selftests/mm/vm_util.c +56 -4
@@ -15,6 +15,10 @@#define SMAP_FILE_PATH "/proc/self/smaps"#define STATUS_FILE_PATH "/proc/self/status"#define MAX_LINE_LENGTH 500 +#define PAGEMAP_PATH "/proc/self/pagemap" +#define KPAGEFLAGS_PATH "/proc/kpageflags" +#define GET_ORDER (nr_pages) (31 - __builtin_clz(nr_pages)) +#define NR_ORDERS 20unsigned int __page_size;unsigned int __page_shift;
@@ -348,7 +352,7 @@ char *__get_smap_entry(void *addr, const char *pattern, char *buf, size_t len)return entry; } -bool __check_huge (void *addr,char *pattern,int nr_hpages, +static bool __check_pmd_huge (void *addr,char *pattern,int nr_hpages,uint64_t hpage_size) {char buffer[MAX_LINE_LENGTH ];
@@ -366,19 +370,67 @@ bool __check_huge(void *addr, char *pattern, int nr_hpages,return thp == (nr_hpages * (hpage_size >>10 )); } +static bool check_large_folios (void *addr,unsigned long size,int nr_hpages,uint64_t hpage_size) +{ +int order =0 , pagesize =getpagesize (); +int nr_pages = hpage_size / pagesize; +int pagemap_fd, kpageflags_fd; +int orders[NR_ORDERS ], status; +bool ret = false; + +if (nr_pages >0 ) + order =GET_ORDER (nr_pages); + +if (!order || order >=NR_ORDERS ) +ksft_exit_fail_msg ("invalid order\n" ); + +memset (orders,0 ,sizeof (int ) *NR_ORDERS ); + pagemap_fd =open (PAGEMAP_PATH ,O_RDONLY ); +if (pagemap_fd ==-1 ) +ksft_exit_fail_msg ("read pagemap fail\n" ); + + kpageflags_fd =open (KPAGEFLAGS_PATH ,O_RDONLY ); +if (kpageflags_fd ==-1 ) { +close (pagemap_fd); +ksft_exit_fail_msg ("read kpageflags fail\n" ); + } + + status =gather_folio_orders (addr, size, pagemap_fd, + kpageflags_fd, orders,NR_ORDERS ); +if (status) + goto out; + +if (orders[order] == nr_hpages) + ret = true; + +out: +close (pagemap_fd); +close (kpageflags_fd); +return ret; +} +bool check_huge_anon (void *addr,unsigned long size,int nr_hpages,uint64_t hpage_size) { -return __check_huge (addr,"AnonHugePages: " , nr_hpages, hpage_size); +if (hpage_size ==read_pmd_pagesize ()) +return __check_pmd_huge (addr,"AnonHugePages: " , nr_hpages, hpage_size); + +return check_large_folios (addr, size, nr_hpages, hpage_size); }bool check_huge_file (void *addr,unsigned long size,int nr_hpages,uint64_t hpage_size) { -return __check_huge (addr,"FilePmdMapped:" , nr_hpages, hpage_size); +if (hpage_size ==read_pmd_pagesize ()) +return __check_pmd_huge (addr,"FilePmdMapped:" , nr_hpages, hpage_size); + +return check_large_folios (addr, size, nr_hpages, hpage_size); }bool check_huge_shmem (void *addr,unsigned long size,int nr_hpages,uint64_t hpage_size) { -return __check_huge (addr,"ShmemPmdMapped:" , nr_hpages, hpage_size); +if (hpage_size ==read_pmd_pagesize ()) +return __check_pmd_huge (addr,"ShmemPmdMapped:" , nr_hpages, hpage_size); + +return check_large_folios (addr, size, nr_hpages, hpage_size); }int64_t allocate_transhuge (void *ptr,int pagemap_fd)
Signature · 1 line
2.47.3
Quoted 3 lines
This patchset is split from the previous shmem mTHP collapse patchset[1], which only adds anon mTHP collapse selftests. All khugepaged test cases can pass.
Thank you for sending this out :) I played around with it and it seems to be working. This lays good groundwork to expand khugepaged mTHP testing in the future too.
Signature · 1 line
Nico Pache (Red Hat) <[email protected]>
Re: [PATCH v2 1/4] selftests: mm: extend the check_huge() to support mTHP check
In reply to Baolin WangQuoted 7 lines
To support checking for various sized mTHPs during mTHP collapse, extend the
check_huge()function prototype to accept two new parameters specifying the address range and mTHP size, in preparation for the following patches.No functional changes.
Signed-off-by Baolin Wang <[email protected]>
LGTM!
Signature · 1 line
Nico Pache (Red Hat) <[email protected]>
Re: [PATCH v2 2/4] selftests: mm: move gather_after_split_folio_orders() into vm_util.c file
In reply to Baolin WangQuoted 8 lines
Move
gather_after_split_folio_orders()tovm_util.cas a helper function in preparation for implementing checks for mTHP collapse. While we are at it, rename this function to indicate that it is not only used for large folio splits.No functional changes.
Signed-off-by Baolin Wang <[email protected]>
LGTM!
Signature · 1 line
Nico Pache (Red Hat) <[email protected]>
Re: [PATCH v2 3/4] selftests: mm: implement the mTHP-sized hugepage check helpers
In reply to Baolin WangQuoted 5 lines
Implement mTHP-sized hugepage checking helpers using
gather_folio_orders(). Also rename the existing PMD-sized huge page check function to__check_pmd_huge()for clarity.Signed-off-by Baolin Wang <[email protected]>
LGTM!
Signature · 1 line
Nico Pache (Red Hat) <[email protected]>
Re: [PATCH v2 4/4] selftests: mm: add mTHP collapse test cases
In reply to Baolin WangQuoted 6 lines
Added a new command '
mthp_khugepaged' for mTHP collapse, along with the '-c' parameter to specify the collapse order. Additionally, added mTHP collapse test cases for 'collapse_full', 'collapse_empty', and 'collapse_single_mthp' for anonymous folios. All khugepaged test cases passed.Signed-off-by Baolin Wang <[email protected]>
LGTM! I will try to come up with more test cases, and send a followup in the future.
Thank you for working on this :)
Signature · 1 line
Nico Pache (Red Hat) <[email protected]>
Baolin Wang
reviewerQuoted 9 lines · Nico Pache (Red Hat)
Quoted 3 lines
This patchset is split from the previous shmem mTHP collapse patchset[1], which only adds anon mTHP collapse selftests. All khugepaged test cases can pass.
Thank you for sending this out :) I played around with it and it seems to be working. This lays good groundwork to expand khugepaged mTHP testing in the future too.
Tested-by Nico Pache (Red Hat) <[email protected]>
Thanks Nico :)
Quoted 3 lines · Baolin Wang
This patchset is split from the previous shmem mTHP collapse patchset[1], which only adds anon mTHP collapse selftests. All khugepaged test cases can pass.
The patchset looks good to me:
Thanks for doing this.
Signature · 1 line
Kiryl Shutsemau / Kirill A. Shutemov
Re: [PATCH v2 1/4] selftests: mm: extend the check_huge() to support mTHP check
In reply to Baolin WangQuoted 19 lines · Baolin Wang
To support checking for various sized mTHPs during mTHP collapse, extend the
check_huge()function prototype to accept two new parameters specifying the address range and mTHP size, in preparation for the following patches.No functional changes.
Signed-off-by Baolin Wang <[email protected]>--- .../selftests/mm/folio_split_race_test.c | 2 +- tools/testing/selftests/mm/khugepaged.c | 66 ++++++++++--------- tools/testing/selftests/mm/pagemap_ioctl.c | 2 +- .../testing/selftests/mm/prctl_thp_disable.c | 2 +- tools/testing/selftests/mm/soft-dirty.c | 2 +- .../selftests/mm/split_huge_page_test.c | 14 ++-- tools/testing/selftests/mm/uffd-common.c | 4 +- tools/testing/selftests/mm/vm_util.c | 6 +- tools/testing/selftests/mm/vm_util.h | 6 +- 9 files changed, 56 insertions(+), 48 deletions(-)
<snip>
Quoted 7 lines
tools/testing/selftests/mm/vm_util.h +0
-0@@ -90,9 +90,9 @@ void clear_softdirty(void);bool check_for_pattern (FILE *fp,const char *pattern,char *buf,size_t len);uint64_t read_pmd_pagesize (void );
tools/testing/selftests/mm/vm_util.h void clear_softdirty(void); · line 98
Quoted 10 lines
tools/testing/selftests/mm/vm_util.h +3
-3unsigned long rss_anon (void ); -bool check_huge_anon (void *addr,int nr_hpages,uint64_t hpage_size); -bool check_huge_file (void *addr,int nr_hpages,uint64_t hpage_size); -bool check_huge_shmem (void *addr,int nr_hpages,uint64_t hpage_size); +bool check_huge_anon (void *addr,unsigned long size,int nr_hpages,uint64_t hpage_size); +bool check_huge_file (void *addr,unsigned long size,int nr_hpages,uint64_t hpage_size); +bool check_huge_shmem (void *addr,unsigned long size,int nr_hpages,uint64_t hpage_size);int64_t allocate_transhuge (void *ptr,int pagemap_fd);int pageflags_get (unsigned long pfn,int kpageflags_fd,uint64_t *flags);
I get what "size" means only after I see Patch 3 where gather_after_split_folio_orders() is used. I think len is a better name if not addr_len and its type should be size_t to match gather_after_split_folio_orders()'s signature. The rest patches should have the same rename and type change. Thanks.
Otherwise, LGTM.
Signature · 2 lines
Best Regards, Yan, Zi
Re: [PATCH v2 2/4] selftests: mm: move gather_after_split_folio_orders() into vm_util.c file
In reply to Baolin WangQuoted 5 lines · Baolin Wang
Move
gather_after_split_folio_orders()tovm_util.cas a helper function in preparation for implementing checks for mTHP collapse. While we are at it, rename this function to indicate that it is not only used for large folio splits.
Quoted 9 lines
No functional changes.
Signed-off-by Baolin Wang <[email protected]>--- .../selftests/mm/split_huge_page_test.c | 125 +----------------- tools/testing/selftests/mm/vm_util.c | 119 +++++++++++++++++ tools/testing/selftests/mm/vm_util.h | 2 + 3 files changed, 122 insertions(+), 124 deletions(-)
Signature · 2 lines
Best Regards, Yan, Zi
Zi Yan
reviewerRe: [PATCH v2 3/4] selftests: mm: implement the mTHP-sized hugepage check helpers
In reply to Baolin WangQuoted 14 lines · Baolin Wang
Implement mTHP-sized hugepage checking helpers using
gather_folio_orders(). Also rename the existing PMD-sized huge page check function to__check_pmd_huge()for clarity.Signed-off-by Baolin Wang <[email protected]>--- tools/testing/selftests/mm/vm_util.c | 60 ++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 4 deletions(-)tools/testing/selftests/mm/vm_util.c +0
-0
tools/testing/selftests/mm/vm_util.c line 20
Quoted 6 lines
tools/testing/selftests/mm/vm_util.c +3
-0@@ -15,6 +15,10 @@#define SMAP_FILE_PATH "/proc/self/smaps"#define STATUS_FILE_PATH "/proc/self/status"#define MAX_LINE_LENGTH 500 +#define PAGEMAP_PATH "/proc/self/pagemap" +#define KPAGEFLAGS_PATH "/proc/kpageflags" +#define GET_ORDER (nr_pages) (31 - __builtin_clz(nr_pages))
This is a fast way of getting log2, but there is no check of the type of nr_pages. What prevents one using it on a long variable?
At least you can convert nr_pages to unsigned int and add a comment.
tools/testing/selftests/mm/vm_util.c line 21
Quoted 1 line
tools/testing/selftests/mm/vm_util.c +1
-0+#define NR_ORDERS 20
Why 20? mTHP orders can only be in [1, pmd_order - 1] and different arch has different pmd_orders. check_large_folios() probably should just cap NR_ORDERS at pmd_order.
Quoted 13 lines
tools/testing/selftests/mm/vm_util.c +1
-1unsigned int __page_size;unsigned int __page_shift;@@ -348,7 +352,7 @@ char *__get_smap_entry(void *addr, const char *pattern, char *buf, size_t len)return entry; } -bool __check_huge (void *addr,char *pattern,int nr_hpages, +static bool __check_pmd_huge (void *addr,char *pattern,int nr_hpages,uint64_t hpage_size) {char buffer[MAX_LINE_LENGTH ];
tools/testing/selftests/mm/vm_util.c bool __check_huge(void *addr, char *pattern, int nr_hpages, · line 378
Quoted 9 lines
tools/testing/selftests/mm/vm_util.c +6
-0@@ -366,19 +370,67 @@ bool __check_huge(void *addr, char *pattern, int nr_hpages,return thp == (nr_hpages * (hpage_size >>10 )); } +static bool check_large_folios (void *addr,unsigned long size,int nr_hpages,uint64_t hpage_size) +{ +int order =0 , pagesize =getpagesize (); +int nr_pages = hpage_size / pagesize; +int pagemap_fd, kpageflags_fd; +int orders[NR_ORDERS ], status;
NR_ORDERS is a constant, so you can put orders on stack. I think you can rename it to MAX_NR_ORDERS, use 20, and check pmd_order is not bigger than MAX_NR_ORDERS.
tools/testing/selftests/mm/vm_util.c bool __check_huge(void *addr, char *pattern, int nr_hpages, · line 382
Quoted 4 lines
tools/testing/selftests/mm/vm_util.c +4
-0+bool ret = false; + +if (nr_pages >0 ) + order =GET_ORDER (nr_pages);
This funciton can fail early if nr_pages is 0.
tools/testing/selftests/mm/vm_util.c bool __check_huge(void *addr, char *pattern, int nr_hpages, · line 385
Quoted 3 lines
tools/testing/selftests/mm/vm_util.c +3
-0+ +if (!order || order >=NR_ORDERS ) +ksft_exit_fail_msg ("invalid order\n" );
It should check against pmd_order.
Quoted 20 lines
tools/testing/selftests/mm/vm_util.c +20
-0+ +memset (orders,0 ,sizeof (int ) *NR_ORDERS ); + pagemap_fd =open (PAGEMAP_PATH ,O_RDONLY ); +if (pagemap_fd ==-1 ) +ksft_exit_fail_msg ("read pagemap fail\n" ); + + kpageflags_fd =open (KPAGEFLAGS_PATH ,O_RDONLY ); +if (kpageflags_fd ==-1 ) { +close (pagemap_fd); +ksft_exit_fail_msg ("read kpageflags fail\n" ); + } + + status =gather_folio_orders (addr, size, pagemap_fd, + kpageflags_fd, orders,NR_ORDERS ); +if (status) + goto out; + +if (orders[order] == nr_hpages) + ret = true; +
tools/testing/selftests/mm/vm_util.c bool __check_huge(void *addr, char *pattern, int nr_hpages, · line 414
Quoted 10 lines
tools/testing/selftests/mm/vm_util.c +7
-1+out: +close (pagemap_fd); +close (kpageflags_fd); +return ret; +} +bool check_huge_anon (void *addr,unsigned long size,int nr_hpages,uint64_t hpage_size) { -return __check_huge (addr,"AnonHugePages: " , nr_hpages, hpage_size); +if (hpage_size ==read_pmd_pagesize ())
read_pmd_pagesize() can fail and return 0. Either you need a check here or add a ksft_exit_fail_msg() in read_pmd_pagesize() to remove the burden from all callers.
Quoted 14 lines
tools/testing/selftests/mm/vm_util.c +7
-1+return __check_pmd_huge (addr,"AnonHugePages: " , nr_hpages, hpage_size); + +return check_large_folios (addr, size, nr_hpages, hpage_size); }bool check_huge_file (void *addr,unsigned long size,int nr_hpages,uint64_t hpage_size) { -return __check_huge (addr,"FilePmdMapped:" , nr_hpages, hpage_size); +if (hpage_size ==read_pmd_pagesize ()) +return __check_pmd_huge (addr,"FilePmdMapped:" , nr_hpages, hpage_size); + +return check_large_folios (addr, size, nr_hpages, hpage_size); }
tools/testing/selftests/mm/vm_util.c bool __check_huge(void *addr, char *pattern, int nr_hpages, · line 436
Quoted 10 lines
tools/testing/selftests/mm/vm_util.c +4
-1bool check_huge_shmem (void *addr,unsigned long size,int nr_hpages,uint64_t hpage_size) { -return __check_huge (addr,"ShmemPmdMapped:" , nr_hpages, hpage_size); +if (hpage_size ==read_pmd_pagesize ()) +return __check_pmd_huge (addr,"ShmemPmdMapped:" , nr_hpages, hpage_size); + +return check_large_folios (addr, size, nr_hpages, hpage_size); }int64_t allocate_transhuge (void *ptr,int pagemap_fd)
All read_pmd_pagesize()s above need to be handled.
Signature · 2 lines
Best Regards, Yan, Zi
Zi Yan
reviewerRe: [PATCH v2 4/4] selftests: mm: add mTHP collapse test cases
In reply to Baolin WangQuoted 24 lines · Baolin Wang
Added a new command '
mthp_khugepaged' for mTHP collapse, along with the '-c' parameter to specify the collapse order. Additionally, added mTHP collapse test cases for 'collapse_full', 'collapse_empty', and 'collapse_single_mthp' for anonymous folios. All khugepaged test cases passed.Signed-off-by Baolin Wang <[email protected]>--- tools/testing/selftests/mm/khugepaged.c | 130 ++++++++++++++++++---- tools/testing/selftests/mm/run_vmtests.sh | 2 + 2 files changed, 113 insertions(+), 19 deletions(-)tools/testing/selftests/mm/khugepaged.c +2
-0@@ -26,9 +26,11 @@#define BASE_ADDR ((void *)(1UL << 30))static unsigned long hpage_pmd_size; +static int hpage_pmd_order;static unsigned long page_size;static int hpage_pmd_nr;static int anon_order; +static int collapse_order;
<snip>
tools/testing/selftests/mm/run_vmtests.sh CATEGORY="thp" run_test ./khugepaged all:shmem · line 413
Quoted 10 lines
tools/testing/selftests/mm/run_vmtests.sh +1
-0@@ -410,6 +410,8 @@ CATEGORY="thp" run_test ./khugepaged all:shmem CATEGORY="thp" run_test ./khugepaged -s 4 all:shmem +CATEGORY="thp" run_test ./khugepaged -c 4 mthp_khugepaged:anon
Why only testing collapse_order == 4? It is more useful to test all possible mTHP orders. -c can accept common separated order and a range.
Why only testing mthp_khugepaged:anon? IIRC, file and shmem are not supported, so khugepaged should reject them, right?
Quoted 4 lines
tools/testing/selftests/mm/run_vmtests.sh +1
-0+ # Try to create XFS if not provided if [ -z "${SPLIT_HUGE_PAGE_TEST_XFS_PATH}" ]; then if test_selected "thp"; then
Signature · 2 lines
Best Regards, Yan, Zi
Baolin Wang
reviewerRe: [PATCH v2 1/4] selftests: mm: extend the check_huge() to support mTHP check
In reply to Zi YanQuoted 38 lines · Zi Yan
Quoted 19 lines · Baolin Wang
To support checking for various sized mTHPs during mTHP collapse, extend the
check_huge()function prototype to accept two new parameters specifying the address range and mTHP size, in preparation for the following patches.No functional changes.
Signed-off-by Baolin Wang <[email protected]>--- .../selftests/mm/folio_split_race_test.c | 2 +- tools/testing/selftests/mm/khugepaged.c | 66 ++++++++++--------- tools/testing/selftests/mm/pagemap_ioctl.c | 2 +- .../testing/selftests/mm/prctl_thp_disable.c | 2 +- tools/testing/selftests/mm/soft-dirty.c | 2 +- .../selftests/mm/split_huge_page_test.c | 14 ++-- tools/testing/selftests/mm/uffd-common.c | 4 +- tools/testing/selftests/mm/vm_util.c | 6 +- tools/testing/selftests/mm/vm_util.h | 6 +- 9 files changed, 56 insertions(+), 48 deletions(-)<snip>
Quoted 15 lines
tools/testing/selftests/mm/vm_util.h +3
-3@@ -90,9 +90,9 @@ void clear_softdirty(void);bool check_for_pattern (FILE *fp,const char *pattern,char *buf,size_t len);uint64_t read_pmd_pagesize (void );unsigned long rss_anon (void ); -bool check_huge_anon (void *addr,int nr_hpages,uint64_t hpage_size); -bool check_huge_file (void *addr,int nr_hpages,uint64_t hpage_size); -bool check_huge_shmem (void *addr,int nr_hpages,uint64_t hpage_size); +bool check_huge_anon (void *addr,unsigned long size,int nr_hpages,uint64_t hpage_size); +bool check_huge_file (void *addr,unsigned long size,int nr_hpages,uint64_t hpage_size); +bool check_huge_shmem (void *addr,unsigned long size,int nr_hpages,uint64_t hpage_size);int64_t allocate_transhuge (void *ptr,int pagemap_fd);
Quoted 8 lines
tools/testing/selftests/mm/vm_util.h void clear_softdirty(void); · line 98
Quoted 2 lines
tools/testing/selftests/mm/vm_util.h +0
-0int pageflags_get (unsigned long pfn,int kpageflags_fd,uint64_t *flags);I get what "size" means only after I see Patch 3 where
gather_after_split_folio_orders()is used. I think len is a better name if notaddr_lenand its type should besize_tto match gather_after_split_folio_orders()'s signature. The rest patches should have the same rename and type change. Thanks.
Will do.
Quoted 3 lines
Otherwise, LGTM.
Acked-by Zi Yan <[email protected]>
Thanks.
Baolin Wang
reviewerRe: [PATCH v2 3/4] selftests: mm: implement the mTHP-sized hugepage check helpers
In reply to Zi YanQuoted 25 lines · Zi Yan
Quoted 14 lines · Baolin Wang
Implement mTHP-sized hugepage checking helpers using
gather_folio_orders(). Also rename the existing PMD-sized huge page check function to__check_pmd_huge()for clarity.Signed-off-by Baolin Wang <[email protected]>--- tools/testing/selftests/mm/vm_util.c | 60 ++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 4 deletions(-)tools/testing/selftests/mm/vm_util.c +0
-0tools/testing/selftests/mm/vm_util.c line 20
Quoted 6 lines
tools/testing/selftests/mm/vm_util.c +3
-0@@ -15,6 +15,10 @@#define SMAP_FILE_PATH "/proc/self/smaps"#define STATUS_FILE_PATH "/proc/self/status"#define MAX_LINE_LENGTH 500 +#define PAGEMAP_PATH "/proc/self/pagemap" +#define KPAGEFLAGS_PATH "/proc/kpageflags" +#define GET_ORDER (nr_pages) (31 - __builtin_clz(nr_pages))This is a fast way of getting log2, but there is no check of the type of
nr_pages. What prevents one using it on a long variable?
Quoted 1 line
At least you can convert
nr_pagesto unsigned int and add a comment.
Good point. Ack.
Quoted 5 lines
tools/testing/selftests/mm/vm_util.c line 21
Quoted 1 line
tools/testing/selftests/mm/vm_util.c +1
-0+#define NR_ORDERS 20Why 20? mTHP orders can only be in [1,
pmd_order- 1] and different arch has differentpmd_orders.check_large_folios()probably should just capNR_ORDERSatpmd_order.
I followed the NR_ORDERS definition in selftests/mm/hugepage_settings.h, and I think this function is not only for mTHP. Other test cases may also call it to get the count of large folios beyond PMD order in the future.
Quoted 15 lines
Quoted 15 lines
tools/testing/selftests/mm/vm_util.c +1
-1unsigned int __page_size;unsigned int __page_shift;@@ -348,7 +352,7 @@ char *__get_smap_entry(void *addr, const char *pattern, char *buf, size_t len)return entry; } -bool __check_huge (void *addr,char *pattern,int nr_hpages, +static bool __check_pmd_huge (void *addr,char *pattern,int nr_hpages,uint64_t hpage_size) {char buffer[MAX_LINE_LENGTH ];@@ -366,19 +370,67 @@ bool __check_huge(void *addr, char *pattern, int nr_hpages,return thp == (nr_hpages * (hpage_size >>10 )); }
Quoted 9 lines
tools/testing/selftests/mm/vm_util.c bool __check_huge(void *addr, char *pattern, int nr_hpages, · line 378
Quoted 6 lines
tools/testing/selftests/mm/vm_util.c +6
-0+static bool check_large_folios (void *addr,unsigned long size,int nr_hpages,uint64_t hpage_size) +{ +int order =0 , pagesize =getpagesize (); +int nr_pages = hpage_size / pagesize; +int pagemap_fd, kpageflags_fd; +int orders[NR_ORDERS ], status;
NR_ORDERSis a constant, so you can put orders on stack. I think you can rename it toMAX_NR_ORDERS, use 20,
Sure.
and check pmd_order is not bigger
Quoted 1 line
than
MAX_NR_ORDERS.
I don't think we need this. As I mentioned above, I hope this function can also be used in the future to get the number of large folios beyond PMD order.
Quoted 6 lines
tools/testing/selftests/mm/vm_util.c bool __check_huge(void *addr, char *pattern, int nr_hpages, · line 382
Quoted 4 lines
tools/testing/selftests/mm/vm_util.c +4
-0+bool ret = false; + +if (nr_pages >0 ) + order =GET_ORDER (nr_pages);This funciton can fail early if
nr_pagesis 0.
Ack.
Quoted 5 lines
tools/testing/selftests/mm/vm_util.c bool __check_huge(void *addr, char *pattern, int nr_hpages, · line 385
Quoted 3 lines
tools/testing/selftests/mm/vm_util.c +3
-0+ +if (!order || order >=NR_ORDERS ) +ksft_exit_fail_msg ("invalid order\n" );It should check against
pmd_order.
Ditto.
Quoted 27 lines
Quoted 27 lines
tools/testing/selftests/mm/vm_util.c +26
-0+ +memset (orders,0 ,sizeof (int ) *NR_ORDERS ); + pagemap_fd =open (PAGEMAP_PATH ,O_RDONLY ); +if (pagemap_fd ==-1 ) +ksft_exit_fail_msg ("read pagemap fail\n" ); + + kpageflags_fd =open (KPAGEFLAGS_PATH ,O_RDONLY ); +if (kpageflags_fd ==-1 ) { +close (pagemap_fd); +ksft_exit_fail_msg ("read kpageflags fail\n" ); + } + + status =gather_folio_orders (addr, size, pagemap_fd, + kpageflags_fd, orders,NR_ORDERS ); +if (status) + goto out; + +if (orders[order] == nr_hpages) + ret = true; + +out: +close (pagemap_fd); +close (kpageflags_fd); +return ret; +} +
Quoted 8 lines
tools/testing/selftests/mm/vm_util.c bool __check_huge(void *addr, char *pattern, int nr_hpages, · line 414
Quoted 4 lines
tools/testing/selftests/mm/vm_util.c +1
-1bool check_huge_anon (void *addr,unsigned long size,int nr_hpages,uint64_t hpage_size) { -return __check_huge (addr,"AnonHugePages: " , nr_hpages, hpage_size); +if (hpage_size ==read_pmd_pagesize ())
read_pmd_pagesize()can fail and return 0. Either you need a check here or add aksft_exit_fail_msg()inread_pmd_pagesize()to remove the burden from all callers.
Ack.
Quoted 24 lines
Quoted 24 lines
tools/testing/selftests/mm/vm_util.c +11
-2+return __check_pmd_huge (addr,"AnonHugePages: " , nr_hpages, hpage_size); + +return check_large_folios (addr, size, nr_hpages, hpage_size); }bool check_huge_file (void *addr,unsigned long size,int nr_hpages,uint64_t hpage_size) { -return __check_huge (addr,"FilePmdMapped:" , nr_hpages, hpage_size); +if (hpage_size ==read_pmd_pagesize ()) +return __check_pmd_huge (addr,"FilePmdMapped:" , nr_hpages, hpage_size); + +return check_large_folios (addr, size, nr_hpages, hpage_size); }bool check_huge_shmem (void *addr,unsigned long size,int nr_hpages,uint64_t hpage_size) { -return __check_huge (addr,"ShmemPmdMapped:" , nr_hpages, hpage_size); +if (hpage_size ==read_pmd_pagesize ()) +return __check_pmd_huge (addr,"ShmemPmdMapped:" , nr_hpages, hpage_size); + +return check_large_folios (addr, size, nr_hpages, hpage_size); }
Quoted 3 lines
tools/testing/selftests/mm/vm_util.c bool __check_huge(void *addr, char *pattern, int nr_hpages, · line 436
Quoted 1 line
tools/testing/selftests/mm/vm_util.c +0
-0int64_t allocate_transhuge (void *ptr,int pagemap_fd)All read_pmd_pagesize()s above need to be handled.
Sure. Thanks for taking a look.
Baolin Wang
reviewerRe: [PATCH v2 4/4] selftests: mm: add mTHP collapse test cases
In reply to Zi YanQuoted 35 lines · Zi Yan
Quoted 24 lines · Baolin Wang
Added a new command '
mthp_khugepaged' for mTHP collapse, along with the '-c' parameter to specify the collapse order. Additionally, added mTHP collapse test cases for 'collapse_full', 'collapse_empty', and 'collapse_single_mthp' for anonymous folios. All khugepaged test cases passed.Signed-off-by Baolin Wang <[email protected]>--- tools/testing/selftests/mm/khugepaged.c | 130 ++++++++++++++++++---- tools/testing/selftests/mm/run_vmtests.sh | 2 + 2 files changed, 113 insertions(+), 19 deletions(-)tools/testing/selftests/mm/khugepaged.c +2
-0@@ -26,9 +26,11 @@#define BASE_ADDR ((void *)(1UL << 30))static unsigned long hpage_pmd_size; +static int hpage_pmd_order;static unsigned long page_size;static int hpage_pmd_nr;static int anon_order; +static int collapse_order;<snip>
Quoted 7 lines
tools/testing/selftests/mm/run_vmtests.sh +0
-0@@ -410,6 +410,8 @@ CATEGORY="thp" run_test ./khugepaged all:shmem
Quoted 6 lines
tools/testing/selftests/mm/run_vmtests.sh CATEGORY="thp" run_test ./khugepaged all:shmem · line 413
Quoted 3 lines
tools/testing/selftests/mm/run_vmtests.sh +1
-0CATEGORY="thp" run_test ./khugepaged -s 4 all:shmem +CATEGORY="thp" run_test ./khugepaged -c 4 mthp_khugepaged:anonWhy only testing
collapse_order== 4? It is more useful to test all possible mTHP orders. -c can accept common separated order and a range.
This also follows the previous '-s' parameter configuration, which is used to specify the mTHP order allocation.
I think specifying a single order size already tests the overall mTHP collapse flow, so I'm not sure whether testing all orders is worthwhile. Maybe I can add a few more orders? ./khugepaged -c 2 mthp_khugepaged:anon
./khugepaged -c 4 mthp_khugepaged:anon
./khugepaged -c 8 mthp_khugepaged:anon
Quoted 2 lines
Why only testing mthp_khugepaged:anon? IIRC, file and shmem are not supported, so khugepaged should reject them, right?
Currently, I have not added test cases for shmem mTHP collapse, so adding file or shmem would be no-ops and might mislead others. I will add the shmem/file mTHP collapse feature and test cases in a following patchset.
Baolin Wang
reviewerQuoted 8 lines · Kiryl Shutsemau
Quoted 3 lines · Baolin Wang
This patchset is split from the previous shmem mTHP collapse patchset[1], which only adds anon mTHP collapse selftests. All khugepaged test cases can pass.
The patchset looks good to me:
Thanks Kiryl.
Zi Yan
reviewerRe: [PATCH v2 4/4] selftests: mm: add mTHP collapse test cases
In reply to Baolin WangQuoted 39 lines · Baolin Wang
Quoted 27 lines · Zi Yan
Quoted 23 lines · Baolin Wang
Added a new command '
mthp_khugepaged' for mTHP collapse, along with the '-c' parameter to specify the collapse order. Additionally, added mTHP collapse test cases for 'collapse_full', 'collapse_empty', and 'collapse_single_mthp' for anonymous folios. All khugepaged test cases passed.Signed-off-by Baolin Wang <[email protected]>--- tools/testing/selftests/mm/khugepaged.c | 130 ++++++++++++++++++---- tools/testing/selftests/mm/run_vmtests.sh | 2 + 2 files changed, 113 insertions(+), 19 deletions(-)tools/testing/selftests/mm/khugepaged.c +2
-0@@ -26,9 +26,11 @@#define BASE_ADDR ((void *)(1UL << 30))static unsigned long hpage_pmd_size; +static int hpage_pmd_order;static unsigned long page_size;static int hpage_pmd_nr;static int anon_order; +static int collapse_order;<snip>
Quoted 10 lines
tools/testing/selftests/mm/run_vmtests.sh CATEGORY="thp" run_test ./khugepaged all:shmem · line 411
Quoted 7 lines
diff --git
a/tools/testing/selftests/mm/run_vmtests.shb/tools/testing/selftests/mm/run_vmtests.sh
index687d115e3bd8..d09f9f6a384e100755tools/testing/selftests/mm/run_vmtests.sh +0
-0@@ -410,6 +410,8 @@ CATEGORY="thp" run_test ./khugepaged all:shmem CATEGORY="thp" run_test ./khugepaged -s 4 all:shmem +CATEGORY="thp" run_test ./khugepaged -c 4 mthp_khugepaged:anonWhy only testing
collapse_order== 4? It is more useful to test all possible mTHP orders. -c can accept common separated order and a range.
Quoted 3 lines
This also follows the previous '-s' parameter configuration, which is used to specify the mTHP order allocation.
I think specifying a single order size already tests the overall mTHP collapse
Got it. If a single order covers the flow, I am fine with it.
Quoted 9 lines
flow, so I'm not sure whether testing all orders is worthwhile. Maybe I can add a few more orders? ./khugepaged -c 2 mthp_khugepaged:anon
./khugepaged -c 4 mthp_khugepaged:anon
./khugepaged -c 8 mthp_khugepaged:anonQuoted 2 lines
Why only testing mthp_khugepaged:anon? IIRC, file and shmem are not supported, so khugepaged should reject them, right?
Currently, I have not added test cases for shmem mTHP collapse, so adding file or shmem would be no-ops and might mislead others. I will add the shmem/file mTHP collapse feature and test cases in a following patchset.
Right. I mean when one specifies ./khugepaged mthp_khugepaged:file/shmem, the program should show some error like “file/shmem not supported”.
Best Regards,
Yan, Zi
Baolin Wang
reviewerRe: [PATCH v2 4/4] selftests: mm: add mTHP collapse test cases
Quoted 52 lines · Zi Yan
Quoted 39 lines · Baolin Wang
Quoted 27 lines · Zi Yan
Quoted 23 lines · Baolin Wang
Added a new command '
mthp_khugepaged' for mTHP collapse, along with the '-c' parameter to specify the collapse order. Additionally, added mTHP collapse test cases for 'collapse_full', 'collapse_empty', and 'collapse_single_mthp' for anonymous folios. All khugepaged test cases passed.Signed-off-by Baolin Wang <[email protected]>--- tools/testing/selftests/mm/khugepaged.c | 130 ++++++++++++++++++---- tools/testing/selftests/mm/run_vmtests.sh | 2 + 2 files changed, 113 insertions(+), 19 deletions(-)tools/testing/selftests/mm/khugepaged.c +2
-0@@ -26,9 +26,11 @@#define BASE_ADDR ((void *)(1UL << 30))static unsigned long hpage_pmd_size; +static int hpage_pmd_order;static unsigned long page_size;static int hpage_pmd_nr;static int anon_order; +static int collapse_order;<snip>
Quoted 10 lines
tools/testing/selftests/mm/run_vmtests.sh CATEGORY="thp" run_test ./khugepaged all:shmem · line 411
Quoted 7 lines
diff --git
a/tools/testing/selftests/mm/run_vmtests.shb/tools/testing/selftests/mm/run_vmtests.sh
index687d115e3bd8..d09f9f6a384e100755tools/testing/selftests/mm/run_vmtests.sh +0
-0@@ -410,6 +410,8 @@ CATEGORY="thp" run_test ./khugepaged all:shmem CATEGORY="thp" run_test ./khugepaged -s 4 all:shmem +CATEGORY="thp" run_test ./khugepaged -c 4 mthp_khugepaged:anonWhy only testing
collapse_order== 4? It is more useful to test all possible mTHP orders. -c can accept common separated order and a range.Quoted 3 lines
This also follows the previous '-s' parameter configuration, which is used to specify the mTHP order allocation.
I think specifying a single order size already tests the overall mTHP collapse
Got it. If a single order covers the flow, I am fine with it.
Quoted 5 lines
flow, so I'm not sure whether testing all orders is worthwhile. Maybe I can add a few more orders? ./khugepaged -c 2 mthp_khugepaged:anon
./khugepaged -c 4 mthp_khugepaged:anon
./khugepaged -c 8 mthp_khugepaged:anon
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
Why only testing mthp_khugepaged:anon? IIRC, file and shmem are not supported, so khugepaged should reject them, right?
Currently, I have not added test cases for shmem mTHP collapse, so adding file or shmem would be no-ops and might mislead others. I will add the shmem/file mTHP collapse feature and test cases in a following patchset.
Right. I mean when one specifies ./khugepaged mthp_khugepaged:file/shmem, the program should show some error like “file/shmem not supported”.
Yes, that works too. I still prefer to add the corresponding test cases after I add shmem mTHP collapse support:)
But if you have a strong opinion on this, I can also add a "not supported" message first.
Zi Yan
reviewerRe: [PATCH v2 4/4] selftests: mm: add mTHP collapse test cases
Quoted 56 lines · Baolin Wang
Quoted 55 lines · Zi Yan
Quoted 39 lines · Baolin Wang
Quoted 27 lines · Zi Yan
Quoted 23 lines · Baolin Wang
Added a new command '
mthp_khugepaged' for mTHP collapse, along with the '-c' parameter to specify the collapse order. Additionally, added mTHP collapse test cases for 'collapse_full', 'collapse_empty', and 'collapse_single_mthp' for anonymous folios. All khugepaged test cases passed.Signed-off-by Baolin Wang <[email protected]>--- tools/testing/selftests/mm/khugepaged.c | 130 ++++++++++++++++++---- tools/testing/selftests/mm/run_vmtests.sh | 2 + 2 files changed, 113 insertions(+), 19 deletions(-)tools/testing/selftests/mm/khugepaged.c +2
-0@@ -26,9 +26,11 @@#define BASE_ADDR ((void *)(1UL << 30))static unsigned long hpage_pmd_size; +static int hpage_pmd_order;static unsigned long page_size;static int hpage_pmd_nr;static int anon_order; +static int collapse_order;<snip>
Quoted 10 lines
tools/testing/selftests/mm/run_vmtests.sh CATEGORY="thp" run_test ./khugepaged all:shmem · line 411
Quoted 7 lines
diff --git
a/tools/testing/selftests/mm/run_vmtests.shb/tools/testing/selftests/mm/run_vmtests.sh
index687d115e3bd8..d09f9f6a384e100755tools/testing/selftests/mm/run_vmtests.sh +0
-0@@ -410,6 +410,8 @@ CATEGORY="thp" run_test ./khugepaged all:shmem CATEGORY="thp" run_test ./khugepaged -s 4 all:shmem +CATEGORY="thp" run_test ./khugepaged -c 4 mthp_khugepaged:anonWhy only testing
collapse_order== 4? It is more useful to test all possible mTHP orders. -c can accept common separated order and a range.Quoted 3 lines
This also follows the previous '-s' parameter configuration, which is used to specify the mTHP order allocation.
I think specifying a single order size already tests the overall mTHP collapse
Got it. If a single order covers the flow, I am fine with it.
Quoted 8 lines
flow, so I'm not sure whether testing all orders is worthwhile. Maybe I can add a few more orders? ./khugepaged -c 2 mthp_khugepaged:anon
./khugepaged -c 4 mthp_khugepaged:anon
./khugepaged -c 8 mthp_khugepaged:anonQuoted 2 lines
Why only testing mthp_khugepaged:anon? IIRC, file and shmem are not supported, so khugepaged should reject them, right?
Quoted 6 lines
Quoted 4 lines
Quoted 1 line
Currently, I have not added test cases for shmem mTHP collapse, so adding file or shmem would be no-ops and might mislead others. I will add the shmem/file mTHP collapse feature and test cases in a following patchset.
Right. I mean when one specifies ./khugepaged mthp_khugepaged:file/shmem, the program should show some error like “file/shmem not supported”.
Yes, that works too. I still prefer to add the corresponding test cases after I add shmem mTHP collapse support:)
Sure. Or update usage() to print “mthp_khugepaged only supports anon”. You can remove that after you add other support types.
Quoted 2 lines
But if you have a strong opinion on this, I can also add a "not supported" message first.
Best Regards,
Yan, Zi
Baolin Wang
reviewerRe: [PATCH v2 4/4] selftests: mm: add mTHP collapse test cases
Quoted 60 lines · Zi Yan
Quoted 58 lines · Baolin Wang
Quoted 57 lines · Zi Yan
Quoted 39 lines · Baolin Wang
Quoted 27 lines · Zi Yan
Quoted 23 lines · Baolin Wang
Added a new command '
mthp_khugepaged' for mTHP collapse, along with the '-c' parameter to specify the collapse order. Additionally, added mTHP collapse test cases for 'collapse_full', 'collapse_empty', and 'collapse_single_mthp' for anonymous folios. All khugepaged test cases passed.Signed-off-by Baolin Wang <[email protected]>--- tools/testing/selftests/mm/khugepaged.c | 130 ++++++++++++++++++---- tools/testing/selftests/mm/run_vmtests.sh | 2 + 2 files changed, 113 insertions(+), 19 deletions(-)tools/testing/selftests/mm/khugepaged.c +2
-0@@ -26,9 +26,11 @@#define BASE_ADDR ((void *)(1UL << 30))static unsigned long hpage_pmd_size; +static int hpage_pmd_order;static unsigned long page_size;static int hpage_pmd_nr;static int anon_order; +static int collapse_order;<snip>
Quoted 10 lines
tools/testing/selftests/mm/run_vmtests.sh CATEGORY="thp" run_test ./khugepaged all:shmem · line 411
Quoted 7 lines
diff --git a/tools/testing/selftests/mm/run_vmtests.sh b/tools/testing/selftests/mm/run_vmtests.shindex
687d115e3bd8..d09f9f6a384e100755tools/testing/selftests/mm/run_vmtests.sh +0
-0@@ -410,6 +410,8 @@ CATEGORY="thp" run_test ./khugepaged all:shmem CATEGORY="thp" run_test ./khugepaged -s 4 all:shmem +CATEGORY="thp" run_test ./khugepaged -c 4 mthp_khugepaged:anonWhy only testing
collapse_order== 4? It is more useful to test all possible mTHP orders. -c can accept common separated order and a range.Quoted 3 lines
This also follows the previous '-s' parameter configuration, which is used to specify the mTHP order allocation.
I think specifying a single order size already tests the overall mTHP collapse
Got it. If a single order covers the flow, I am fine with it.
Quoted 9 lines
flow, so I'm not sure whether testing all orders is worthwhile. Maybe I can add a few more orders? ./khugepaged -c 2 mthp_khugepaged:anon
./khugepaged -c 4 mthp_khugepaged:anon
./khugepaged -c 8 mthp_khugepaged:anonQuoted 2 lines
Why only testing mthp_khugepaged:anon? IIRC, file and shmem are not supported, so khugepaged should reject them, right?
Currently, I have not added test cases for shmem mTHP collapse, so adding file or shmem would be no-ops and might mislead others. I will add the shmem/file mTHP collapse feature and test cases in a following patchset.
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
Right. I mean when one specifies ./khugepaged mthp_khugepaged:file/shmem, the program should show some error like “file/shmem not supported”.
Yes, that works too. I still prefer to add the corresponding test cases after I add shmem mTHP collapse support:)
Sure. Or update
usage()to print “mthp_khugepaged only supports anon”. You can remove that after you add other support types.
Ack. Thanks for all your valuable input:)