Re: [PATCH 1/2] mm/hugetlb: Prefer mempolicy nodes for calcuating surplus hugepage reservation

From: Joshua Hahn

Date: Tue Jul 07 2026 - 15:38:21 EST


On Tue, 7 Jul 2026 12:28:55 -0600 Charles Haithcock <chaithco@xxxxxxxxxx> wrote:

> Currently, reserving surplus hugetlb pages in a mempolicy still use
> global counters for calculating how many hugetlb pages to reserve.
> Modify this to consider the nodes in the mempolicy first but fall back
> to all possible nodes.

Hi Charles, thank you for the patch, this looks good to me!

Personally I like the description of the commit in the cover letter
because it provides a bit more context. Do other reviewers have
thoughts on this? In any case, the code LGTM : -)

Reviewed-by: Joshua Hahn <joshua.hahnjy@xxxxxxxxx>

BTW this is a little strange but Sashiko seems to have failed to apply
this patch [1] which is strange because when applying on the exact
same commit db6ed2a3d3106 "mm/swap, PM: hibernate: atomically replace hibernation pin"
as Sashiko tried, it worked & compiled for me with no errors at all...

[1] https://sashiko.dev/#/patchset/20260707182900.483757-1-chaithco%40redhat.com
Sashiko's error log:

Trying baseline: mm/mm-new (db6ed2a3d31068ca5577466591b2521dee0508ca)
Patch 41962/2 (ID: 108031) failed to apply.
Application failed.

> Suggested-by: Joshua Hahn <joshua.hahnjy@xxxxxxxxx>
> Signed-off-by: Charles Haithcock <chaithco@xxxxxxxxxx>
> ---
>
> - v1: Modified `needed` calculation to use `allowed_mems_nr(h)` in order
> to consider free hugetlb pages in our mempolicy.
> - v2: Folded in Joshua Hahn's recommendation [1] to further modify
> `needed` calculation to take the max of either the available hugetlb
> pages in the mempolicy or the globally available hugetlb pages. Allows
> allocations to prioritize nodes in the mempolicy but can still fall
> back to offnode allocations. Also added selftests to check only for
> the edgecase which caused this to initially be reported and sanity
> checks.
> - v3: Split the change and tests into separate patches and clean up code
> to better align with kernel style guidelines. Likewise, fold in Usama
> Arif's correction [2].
>
> [1] https://lore.kernel.org/all/20260602152022.2673803-1-joshua.hahnjy@xxxxxxxxx/
> [2] https://lore.kernel.org/linux-mm/20260624144600.8159-1-usama.arif@xxxxxxxxx/
>
> mm/hugetlb.c | 42 ++++++++++++++++++++++--------------------
> 1 file changed, 22 insertions(+), 20 deletions(-)
>
> diff --git a/mm/hugetlb.c b/mm/hugetlb.c
> index f24bf49be0..f5e678e997 100644
> --- a/mm/hugetlb.c
> +++ b/mm/hugetlb.c
> @@ -2255,6 +2255,23 @@ static nodemask_t *policy_mbind_nodemask(gfp_t gfp)
> return NULL;
> }
>
> +static unsigned int allowed_mems_nr(struct hstate *h)
> +{
> + int node;
> + unsigned int nr = 0;
> + nodemask_t *mbind_nodemask;
> + unsigned int *array = h->free_huge_pages_node;
> + gfp_t gfp_mask = htlb_alloc_mask(h);
> +
> + mbind_nodemask = policy_mbind_nodemask(gfp_mask);
> + for_each_node_mask(node, cpuset_current_mems_allowed) {
> + if (!mbind_nodemask || node_isset(node, *mbind_nodemask))
> + nr += array[node];
> + }
> +
> + return nr;
> +}
> +
> /*
> * Increase the hugetlb pool such that it can accommodate a reservation
> * of size 'delta'.
> @@ -2277,7 +2294,8 @@ static int gather_surplus_pages(struct hstate *h, long delta)
> alloc_nodemask = cpuset_current_mems_allowed;
>
> lockdep_assert_held(&hugetlb_lock);
> - needed = (h->resv_huge_pages + delta) - h->free_huge_pages;
> + needed = max_t(long, (delta - allowed_mems_nr(h)),
> + ((h->resv_huge_pages + delta) - h->free_huge_pages));
> if (needed <= 0) {
> h->resv_huge_pages += delta;
> return 0;
> @@ -2311,8 +2329,9 @@ static int gather_surplus_pages(struct hstate *h, long delta)
> * because either resv_huge_pages or free_huge_pages may have changed.
> */
> spin_lock_irq(&hugetlb_lock);
> - needed = (h->resv_huge_pages + delta) -
> - (h->free_huge_pages + allocated);
> + needed = max_t(long, ((delta - allowed_mems_nr(h)) - allocated),
> + ((h->resv_huge_pages + delta) -
> + (h->free_huge_pages + allocated)));
> if (needed > 0) {
> if (alloc_ok)
> goto retry;
> @@ -4513,23 +4532,6 @@ static int __init hugepage_alloc_threads_setup(char *s)
> }
> __setup("hugepage_alloc_threads=", hugepage_alloc_threads_setup);
>
> -static unsigned int allowed_mems_nr(struct hstate *h)
> -{
> - int node;
> - unsigned int nr = 0;
> - nodemask_t *mbind_nodemask;
> - unsigned int *array = h->free_huge_pages_node;
> - gfp_t gfp_mask = htlb_alloc_mask(h);
> -
> - mbind_nodemask = policy_mbind_nodemask(gfp_mask);
> - for_each_node_mask(node, cpuset_current_mems_allowed) {
> - if (!mbind_nodemask || node_isset(node, *mbind_nodemask))
> - nr += array[node];
> - }
> -
> - return nr;
> -}
> -
> void hugetlb_report_meminfo(struct seq_file *m)
> {
> struct hstate *h;
> --
> 2.55.0