Re: [PATCH v5 2/3] mm: hugetlb: Move mpol interpretation out of alloc_buddy_hugetlb_folio_with_mpol()

Gregory Price <[email protected]> Mon, 3 Aug 2026 10:55:52 -0400
Newsgroups org.kvack.linux-mm,org.kernel.vger.linux-kernel
Message-ID <anCqmhFw_D29uiuo@gourry-fedora-PF4VCD3F>
On Mon, Aug 03, 2026 at 06:37:59AM -0700, Ackerley Tng wrote:
> Move memory policy interpretation out of
> alloc_buddy_hugetlb_folio_with_mpol() and into alloc_hugetlb_folio() to
> separate reading and interpretation of memory policy from actual
> allocation.
> 
> This will later allow memory policy to be interpreted outside of the
> process of allocating a hugetlb folio entirely. This opens doors for other
> callers of the HugeTLB folio allocation function, such as guest_memfd,
> where memory may not always be mapped and hence may not have an associated
> vma.
> 
> Introduce struct mempolicy_interpreted to hold all the components of an
> interpreted memory policy.
> 
> Rename alloc_buddy_hugetlb_folio_with_mpol() to alloc_buddy_hugetlb_folio()
> since the function no longer interprets memory policy.
> 
> No functional change intended.
> 
> Reviewed-by: James Houghton <[email protected]>
> Acked-by: Oscar Salvador <[email protected]>
> Signed-off-by: Ackerley Tng <[email protected]>
> ---
>  include/uapi/linux/mempolicy.h |  2 +-
>  mm/hugetlb.c                   | 54 ++++++++++++++++++++++++++++--------------
>  2 files changed, 37 insertions(+), 19 deletions(-)
> 
> --- a/mm/hugetlb.c
> +++ b/mm/hugetlb.c
> @@ -1317,6 +1317,12 @@ static unsigned long available_huge_pages(struct hstate *h)
>  	return h->free_huge_pages - h->resv_huge_pages;
>  }
>  
> +struct mempolicy_interpreted {
> +	int nid;
> +	nodemask_t *nodemask;
        ^^ const please (mempolicy owns it, it should never change)

> +	enum mempolicy_mode mode;
> +};
> +

Is this intended to be an ephemeral struct that will eventually be
removed?  Because it feels like mempolicy.c should just be handling this
directly instead of needing this cached structure.

>  static struct folio *dequeue_hugetlb_folio_vma(struct hstate *h,
>  				struct vm_area_struct *vma,
>  				unsigned long address)
> @@ -2138,32 +2144,28 @@ static struct folio *alloc_migrate_hugetlb_folio(struct hstate *h, gfp_t gfp_mas
>  	return folio;
>  }
>  
... snip ...
> @@ -2926,8 +2928,24 @@ struct folio *alloc_hugetlb_folio(struct vm_area_struct *vma,
>  		folio = dequeue_hugetlb_folio_vma(h, vma, addr);
>  
>  	if (!folio) {
> +		struct mempolicy_interpreted mpoli;
> +		struct mempolicy *mpol;
> +		nodemask_t *nodemask;
> +		int nid;
> +
>  		spin_unlock_irq(&hugetlb_lock);
> -		folio = alloc_buddy_hugetlb_folio_with_mpol(h, vma, addr);
> +		nid = huge_node(vma, addr, gfp, &mpol, &nodemask);
> +		mpoli = (struct mempolicy_interpreted){
> +			.nid = nid,
> +#ifdef CONFIG_NUMA
> +			.mode = mpol ? mpol->mode : MPOL_DEFAULT,
> +#else
> +			.mode = MPOL_DEFAULT,
> +#endif

This is not great, and tells me this interaction should probably
be sunk into mempolicy instead of pulling ifdef/else into hugetlb.

> +			.nodemask = nodemask,
> +		};
> +		folio = alloc_buddy_hugetlb_folio(h, gfp, &mpoli);
> +		mpol_cond_put(mpol);
>  		if (!folio)
>  			goto out_uncharge_cgroup;
>  		spin_lock_irq(&hugetlb_lock);