[PATCH 12/15] mm/hugetlb: keep surplus folios that are reserved
From: David Hildenbrand (Arm)
Date: Wed Oct 28 2026 - 17:01:31 EST
From: Chris Mason <mason@xxxxxxxxxx>
free_huge_folio() may restore a reservation, but still returns the folio
to the page allocator if its node has surplus huge pages.
For example, start with no hugetlb folios and allow one surplus 2 MiB
folio:
1. Mount hugetlbfs with pagesize=2M,min_size=2M. This allocates and
reserves one surplus folio: free=1, reserved=1.
2. Create a 2 MiB file and write to a shared mapping of it. The fault
consumes the folio and its reservation: free=0, reserved=0.
3. Unmap the file and truncate it to zero. The mount's reservation is
restored, but the surplus folio is freed: free=0, reserved=1.
Besides losing a hugetlb folio that is required for a reservation, this
can also make available_huge_pages() underflow and cause other issues.
Keep the folio in the pool if it is needed to cover reservations,
including any reservation we just restored.
Fix generated by an LLM and sent by Chris Mason in private.
Fixes: 07443a85ad90 ("mm, hugetlb: return a reserved page to a reserved pool if failed")
Cc: stable@xxxxxxxxxx
Signed-off-by: Chris Mason <mason@xxxxxxxxxx>
[ david: simplify comment and description ]
Signed-off-by: David Hildenbrand (Arm) <david@xxxxxxxxxx>
---
mm/hugetlb.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 06d2a78c7170..32ecac4e0d3e 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1774,8 +1774,9 @@ void free_huge_folio(struct folio *folio)
remove_hugetlb_folio(h, folio, false);
spin_unlock_irqrestore(&hugetlb_lock, flags);
update_and_free_hugetlb_folio(h, folio, true);
- } else if (h->surplus_huge_pages_node[nid]) {
- /* remove the page from active list */
+ } else if (h->surplus_huge_pages_node[nid] &&
+ h->free_huge_pages >= h->resv_huge_pages) {
+ /* Free this surplus folio that is not required globally. */
remove_hugetlb_folio(h, folio, true);
spin_unlock_irqrestore(&hugetlb_lock, flags);
update_and_free_hugetlb_folio(h, folio, true);
--
2.43.0