Skip to contentSkip to conversation

mm/hugetlb: restore subpool used_hpages on alloc_hugetlb_folio error

PATCH In review David Carlier 2 participants 2 messages May 15

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 mm/hugetlb: restore subpool used_hpages on alloc_hugetlb_folio error

Commit a833a693a490 added a !gbl_chg guard around the hugepage_subpool_put_pages() call in alloc_hugetlb_folio()'s out_subpool_put path so a failed allocation wouldn't drive h->resv_huge_pages negative. But hugepage_subpool_get_pages() increments spool->used_hpages whenever max_hpages != -1, regardless of whether the request was satisfied from subpool reserves or needs global pages. When gbl_chg > 0 and a later step fails (cgroup charge, dequeue, buddy alloc), used_hpages is never put back.

Each such failure leaks one count; eventually used_hpages reaches max_hpages and the subpool refuses every further allocation even though no pages are held.

Commit 1d3f9bb4c8af fixed the same defect in hugetlb_reserve_pages(); apply the equivalent restore here, guarded by spool and max_hpages.

Fixes a833a693a490 ("mm: hugetlb: fix incorrect fallback for subpool")
Cc Joshua Hahn <[email protected]>
Cc Wupeng Ma <[email protected]>
Cc Oscar Salvador <[email protected]>
Cc Muchun Song <[email protected]>
Cc David Hildenbrand <[email protected]>
---
 mm/hugetlb.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)
mm/hugetlb.c +16 -3
index cfb7cb2e9806..9614330889de 100644
@@ -3010,9 +3010,22 @@ struct folio *alloc_hugetlb_folio(struct vm_area_struct *vma,
 	 * put page to subpool iff the quota of subpool's rsv_hpages is used
 	 * during hugepage_subpool_get_pages.
 	 */
-	if (map_chg && !gbl_chg) {
-		gbl_reserve = hugepage_subpool_put_pages(spool, 1);
-		hugetlb_acct_memory(h, -gbl_reserve);
+	if (map_chg) {
+		/*
+		 * Put used_hpages back for the global portion of the request that
+		 * was never actually consumed; restore the subpool-reservation
+		 * portion via hugepage_subpool_put_pages() so rsv_hpages is rebuilt.
+		 */
+		if (!gbl_chg) {
+			gbl_reserve = hugepage_subpool_put_pages(spool, 1);
+			hugetlb_acct_memory(h, -gbl_reserve);
+		} else if (spool && spool->max_hpages != -1) {
+			unsigned long flags;
+
+			spin_lock_irqsave(&spool->lock, flags);
+			spool->used_hpages -= 1;
+			unlock_or_release_subpool(spool, flags);
+		}
 	}
 
 
Signature · 1 line
2.53.0
#1 lore raw
Quoted 9 lines · On Fri, 15 May 2026 21:29:02 +0100 David Carlier <[email protected]> wrote:

Commit a833a693a490 added a !gbl_chg guard around the hugepage_subpool_put_pages() call in alloc_hugetlb_folio()'s out_subpool_put path so a failed allocation wouldn't drive h->resv_huge_pages negative. But hugepage_subpool_get_pages() increments spool->used_hpages whenever max_hpages != -1, regardless of whether the request was satisfied from subpool reserves or needs global pages. When gbl_chg > 0 and a later step fails (cgroup charge, dequeue, buddy alloc), used_hpages is never put back.

Quoted 6 lines

Each such failure leaks one count; eventually used_hpages reaches max_hpages and the subpool refuses every further allocation even though no pages are held.

Commit 1d3f9bb4c8af fixed the same defect in hugetlb_reserve_pages(); apply the equivalent restore here, guarded by spool and max_hpages.

Hello David,

Thank you for the patch!

I noticed that this patch is quite similar to Zhao Li's patch [1] which seems to address the same problem. Have you taken a look at his approach? From what I can tell, the code change is also quite similar (except comments and additional guards in the else if branch).

Just wanted to bring it to your attention in case you haven't seen it yet.

Have a great day!
Joshua

[1] https://lore.kernel.org/linux-mm/[email protected]/

Quoted 44 lines
Fixes a833a693a490 ("mm: hugetlb: fix incorrect fallback for subpool")
Cc Joshua Hahn <[email protected]>
Cc Wupeng Ma <[email protected]>
Cc Oscar Salvador <[email protected]>
Cc Muchun Song <[email protected]>
Cc David Hildenbrand <[email protected]>
---
 mm/hugetlb.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)
mm/hugetlb.c +16 -3
index cfb7cb2e9806..9614330889de 100644
@@ -3010,9 +3010,22 @@ struct folio *alloc_hugetlb_folio(struct vm_area_struct *vma,
 	 * put page to subpool iff the quota of subpool's rsv_hpages is used
 	 * during hugepage_subpool_get_pages.
 	 */
-	if (map_chg && !gbl_chg) {
-		gbl_reserve = hugepage_subpool_put_pages(spool, 1);
-		hugetlb_acct_memory(h, -gbl_reserve);
+	if (map_chg) {
+		/*
+		 * Put used_hpages back for the global portion of the request that
+		 * was never actually consumed; restore the subpool-reservation
+		 * portion via hugepage_subpool_put_pages() so rsv_hpages is rebuilt.
+		 */
+		if (!gbl_chg) {
+			gbl_reserve = hugepage_subpool_put_pages(spool, 1);
+			hugetlb_acct_memory(h, -gbl_reserve);
+		} else if (spool && spool->max_hpages != -1) {
+			unsigned long flags;
+
+			spin_lock_irqsave(&spool->lock, flags);
+			spool->used_hpages -= 1;
+			unlock_or_release_subpool(spool, flags);
+		}
 	}
 
 
Signature · 1 line
2.53.0