Re: [PATCH v2 3/4] selftests: mm: implement the mTHP-sized hugepage check helpers

"Zi Yan" <[email protected]>
Newsgroups gmane.linux.kernel,gmane.linux.kernel.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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.