[PATCH 02/15] mm/hugetlb: compare against persistent count when freeing lowmem folios
From: David Hildenbrand (Arm)
Date: Wed Oct 28 2026 - 17:24:39 EST
try_to_free_low() gets a target number of persistent folios, but
compares it with "nr_huge_pages", which includes surplus folios. As a
result, it can free lowmem folios below that target.
For example, with two persistent folios and one surplus folio, a target
of two can still end up freeing one persistent folio.
Compare against persistent_huge_pages() instead. Convert the macro to a
helper function and place it before try_to_free_low().
Fixes: 7893d1d505d5 ("hugetlb: Try to grow hugetlb pool for MAP_PRIVATE mappings")
Cc: stable@xxxxxxxxxx
Signed-off-by: David Hildenbrand (Arm) <david@xxxxxxxxxx>
---
mm/hugetlb.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index da5d04edf7c1..3a94ea1c9457 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1335,6 +1335,11 @@ static unsigned long available_huge_pages(struct hstate *h)
return h->free_huge_pages - h->resv_huge_pages;
}
+static unsigned long persistent_huge_pages(struct hstate *h)
+{
+ return h->nr_huge_pages - h->surplus_huge_pages;
+}
+
static struct folio *dequeue_hugetlb_folio(struct hstate *h, gfp_t gfp_mask,
struct mempolicy_interpreted *mpoli)
{
@@ -3719,7 +3724,7 @@ static void try_to_free_low(struct hstate *h, unsigned long count,
struct folio *folio, *next;
struct list_head *freel = &h->hugepage_freelists[i];
list_for_each_entry_safe(folio, next, freel, lru) {
- if (count >= h->nr_huge_pages)
+ if (count >= persistent_huge_pages(h))
goto out;
if (folio_test_highmem(folio))
continue;
@@ -3773,7 +3778,6 @@ static int adjust_pool_surplus(struct hstate *h, nodemask_t *nodes_allowed,
return 1;
}
-#define persistent_huge_pages(h) (h->nr_huge_pages - h->surplus_huge_pages)
static int set_max_huge_pages(struct hstate *h, unsigned long count, int nid,
nodemask_t *nodes_allowed)
{
--
2.43.0