Re: [PATCH v2 3/4] selftests: mm: implement the mTHP-sized hugepage check helpers
"Zi Yan" <[email protected]> Wed, 05 Aug 2026 11:59:55 -0400
| Newsgroups | org.kernel.vger.linux-kselftest,org.kernel.vger.linux-kernel,org.kvack.linux-mm |
|---|---|
| Message-ID | <[email protected]> |
On Sat Aug 1, 2026 at 2:26 AM EDT, Baolin Wang wrote: > 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(-) > > diff --git a/tools/testing/selftests/mm/vm_util.c b/tools/testing/selftests/mm/vm_util.c > index 09e5d5cabe21..1240d783669c 100644 > --- a/tools/testing/selftests/mm/vm_util.c > +++ b/tools/testing/selftests/mm/vm_util.c > @@ -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. > +#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. > > unsigned 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; 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. > + bool ret = false; > + > + if (nr_pages > 0) > + order = GET_ORDER(nr_pages); This funciton can fail early if nr_pages is 0. > + > + if (!order || order >= NR_ORDERS) > + ksft_exit_fail_msg("invalid order\n"); It should check against pmd_order. > + > + 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()) 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. > + 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) All read_pmd_pagesize()s above need to be handled. -- Best Regards, Yan, Zi