* [PATCH 0/4] Fix bugs on HugeTLB folio allocation failure paths
@ 2026-07-07 20:46 Ackerley Tng via B4 Relay
2026-07-07 20:46 ` [PATCH 1/4] mm: hugetlb: Fix subpool usage leak on allocation failure Ackerley Tng via B4 Relay
` (3 more replies)
0 siblings, 4 replies; 8+ messages in thread
From: Ackerley Tng via B4 Relay @ 2026-07-07 20:46 UTC (permalink / raw)
To: Muchun Song, Oscar Salvador, David Hildenbrand, Joshua Hahn,
Shakeel Butt, Nhat Pham, Andrew Morton, Peter Xu, Wupeng Ma, fvdl,
rientjes
Cc: vannapurve, erdemaktas, linux-mm, linux-kernel, Ackerley Tng
When mem_cgroup_charge_hugetlb() fails (e.g. when hitting memcg limits),
the HugeTLB allocation path currently handles the errors incorrectly.
This series fixes 4 issues related to HugeTLB allocation failure paths.
Some of these issues were pointed out by Sashiko while I was working on
[1].
1. Fix subpool usage leak on allocation failure: (Sashiko pointed this out
in [2])
When alloc_hugetlb_folio() fails early (e.g. buddy allocation failure or
hugetlb cgroup charging failure) and gbl_chg == 1, the error path skips
restoring the page to the subpool, leaking the subpool's used_hpages
counter. Fix this by calling hugepage_subpool_put_pages()
unconditionally if map_chg is true.
(1.) above could technically be a separate patch series, but I'm relying on that
for fix (4.) below.
2. Fix folio refcount mismatch on memcg charge failure: (Sashiko pointed this
out in [3])
The error path in alloc_hugetlb_folio() calls free_huge_folio() directly
on a folio with a refcount of 1 (set via folio_ref_unfreeze() earlier).
This triggers VM_BUG_ON_FOLIO(folio_ref_count(folio), folio) if
CONFIG_DEBUG_VM is enabled, and can corrupt allocator state otherwise.
Fix this by using folio_put() instead of free_huge_folio() to correctly
drop the refcount before freeing.
While fixing the above, the reproducer (I'll send these separately) was causing
an infinite loop during allocation, unveiling issue (3.).
3. Return -ENOSPC on memcg charge failure to prevent infinite loop:
alloc_hugetlb_folio() propagates -ENOMEM on charge failure, which maps
to VM_FAULT_OOM. Because HugeTLB physical allocations are high-order and
use __GFP_RETRY_MAYFAIL, the OOM killer is bypassed. Returning
VM_FAULT_OOM leaks to the #PF handler, which cannot make progress and
retries the faulting instruction indefinitely. Fix this by returning
-ENOSPC instead of -ENOMEM on charge failure, which maps to
VM_FAULT_SIGBUS, terminating the process cleanly.
And while running the reproducer, I checked this routinely
head /sys/kernel/mm/hugepages/hugepages-2048kB/*
and found that there was a resv_hugepages leakm, 1 per execution of the
reproducer, unveiling (4.) below.
4. Move memcg charge earlier to prevent reservation leak:
When mem_cgroup_charge_hugetlb() fails, the error path historically
bypassed vma_end_reservation(). Since the reservation had already been
committed via vma_commit_reservation(), this left the reservation map in
an inconsistent state, leaking resv_huge_pages when the process
exited. Fix this by moving mem_cgroup_charge_hugetlb() earlier in
alloc_hugetlb_folio(), before vma_commit_reservation() is called.
Testing:
+ libhugetlbfs tests pass
+ ./tools/testing/selftests/mm/ksft_hugetlb.sh passes
The series [1] has some changes that are dependent on these fixes, so I'll wait
for your reviews before continuing on [1].
Thank you!
[1] https://lore.kernel.org/all/20260702-hugetlb-open-up-v4-0-d53cefcccf34@google.com/T/
[2] https://sashiko.dev/#/patchset/20260518-hugetlb-open-up-v3-0-e14b302477f8%40google.com?part=5
[3] https://sashiko.dev/#/patchset/20260702-hugetlb-open-up-v4-0-d53cefcccf34%40google.com?part=6
Signed-off-by: Ackerley Tng <ackerleytng@google.com>
---
Ackerley Tng (4):
mm: hugetlb: Fix subpool usage leak on allocation failure
mm: hugetlb: Fix folio refcount mismatch on memcg charge failure
mm: hugetlb: Return -ENOSPC on memcg charge failure
mm: hugetlb: Move memcg charge earlier to prevent reservation leak
mm/hugetlb.c | 57 ++++++++++++++++++++++++++++++++++++---------------------
1 file changed, 36 insertions(+), 21 deletions(-)
---
base-commit: 0e35b9b6ec0ffcc5e23cbdec09f5c622ad532b53
change-id: 20260706-hugetlb-alloc-failure-fixes-c7f775eca29f
Best regards,
--
Ackerley Tng <ackerleytng@google.com>
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/4] mm: hugetlb: Fix subpool usage leak on allocation failure
2026-07-07 20:46 [PATCH 0/4] Fix bugs on HugeTLB folio allocation failure paths Ackerley Tng via B4 Relay
@ 2026-07-07 20:46 ` Ackerley Tng via B4 Relay
2026-07-07 23:43 ` Ackerley Tng
2026-07-07 20:46 ` [PATCH 2/4] mm: hugetlb: Fix folio refcount mismatch on memcg charge failure Ackerley Tng via B4 Relay
` (2 subsequent siblings)
3 siblings, 1 reply; 8+ messages in thread
From: Ackerley Tng via B4 Relay @ 2026-07-07 20:46 UTC (permalink / raw)
To: Muchun Song, Oscar Salvador, David Hildenbrand, Joshua Hahn,
Shakeel Butt, Nhat Pham, Andrew Morton, Peter Xu, Wupeng Ma, fvdl,
rientjes
Cc: vannapurve, erdemaktas, linux-mm, linux-kernel, Ackerley Tng
From: Ackerley Tng <ackerleytng@google.com>
When alloc_hugetlb_folio() fails early (e.g. buddy allocation failure or
hugetlb cgroup charging failure) and gbl_chg == 1 (meaning a reservation
was not used, but a global page was allocated instead), the subpool page
acquired via hugepage_subpool_get_pages() must still be returned.
Currently, the error path out_subpool_put: only calls
hugepage_subpool_put_pages() if !gbl_chg is true. If gbl_chg is 1, it
skips it, permanently leaking the subpool's used_hpages counter.
Fix this by calling hugepage_subpool_put_pages() unconditionally if
map_chg is true. Only call hugetlb_acct_memory() to adjust global
reservations if !gbl_chg is true, to prevent underflowing the global
resv_huge_pages counter.
Fixes: a833a693a490e ("mm: hugetlb: fix incorrect fallback for subpool")
Signed-off-by: Ackerley Tng <ackerleytng@google.com>
---
mm/hugetlb.c | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 571212b80835e..e607dcbb2fc3e 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -2858,7 +2858,7 @@ struct folio *alloc_hugetlb_folio(struct vm_area_struct *vma,
struct hugepage_subpool *spool = subpool_vma(vma);
struct hstate *h = hstate_vma(vma);
struct folio *folio;
- long retval, gbl_chg, gbl_reserve;
+ long retval, gbl_chg;
map_chg_state map_chg;
int ret, idx;
struct hugetlb_cgroup *h_cg = NULL;
@@ -3009,13 +3009,11 @@ struct folio *alloc_hugetlb_folio(struct vm_area_struct *vma,
hugetlb_cgroup_uncharge_cgroup_rsvd(idx, pages_per_huge_page(h),
h_cg_rsvd);
out_subpool_put:
- /*
- * 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) {
+ long gbl_reserve = hugepage_subpool_put_pages(spool, 1);
+
+ if (!gbl_chg)
+ hugetlb_acct_memory(h, -gbl_reserve);
}
--
2.55.0.795.g602f6c329a-goog
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/4] mm: hugetlb: Fix folio refcount mismatch on memcg charge failure
2026-07-07 20:46 [PATCH 0/4] Fix bugs on HugeTLB folio allocation failure paths Ackerley Tng via B4 Relay
2026-07-07 20:46 ` [PATCH 1/4] mm: hugetlb: Fix subpool usage leak on allocation failure Ackerley Tng via B4 Relay
@ 2026-07-07 20:46 ` Ackerley Tng via B4 Relay
2026-07-08 6:59 ` Muchun Song
2026-07-07 20:46 ` [PATCH 3/4] mm: hugetlb: Return -ENOSPC " Ackerley Tng via B4 Relay
2026-07-07 20:46 ` [PATCH 4/4] mm: hugetlb: Move memcg charge earlier to prevent reservation leak Ackerley Tng via B4 Relay
3 siblings, 1 reply; 8+ messages in thread
From: Ackerley Tng via B4 Relay @ 2026-07-07 20:46 UTC (permalink / raw)
To: Muchun Song, Oscar Salvador, David Hildenbrand, Joshua Hahn,
Shakeel Butt, Nhat Pham, Andrew Morton, Peter Xu, Wupeng Ma, fvdl,
rientjes
Cc: vannapurve, erdemaktas, linux-mm, linux-kernel, Ackerley Tng
From: Ackerley Tng <ackerleytng@google.com>
When mem_cgroup_charge_hugetlb(folio, gfp) returns -ENOMEM, the folio has
its refcount set to 1 via folio_ref_unfreeze(folio, 1).
The error path calls free_huge_folio(folio) directly, which expects a
refcount of 0. Hence, VM_BUG_ON_FOLIO(folio_ref_count(folio), folio) is
triggered.
Even with CONFIG_DEBUG_VM disabled, returning a folio with refcount 1 to
the freelist can corrupt allocator state later.
Use folio_put(folio) instead of free_huge_folio(folio) to properly drop the
reference before freeing it.
Fixes: 991135774c0e0 ("memcg/hugetlb: introduce mem_cgroup_charge_hugetlb")
Signed-off-by: Ackerley Tng <ackerleytng@google.com>
---
mm/hugetlb.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index e607dcbb2fc3e..46e8dfffcfa5d 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -2996,7 +2996,7 @@ struct folio *alloc_hugetlb_folio(struct vm_area_struct *vma,
lruvec_stat_mod_folio(folio, NR_HUGETLB, pages_per_huge_page(h));
if (ret == -ENOMEM) {
- free_huge_folio(folio);
+ folio_put(folio);
return ERR_PTR(-ENOMEM);
}
--
2.55.0.795.g602f6c329a-goog
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/4] mm: hugetlb: Return -ENOSPC on memcg charge failure
2026-07-07 20:46 [PATCH 0/4] Fix bugs on HugeTLB folio allocation failure paths Ackerley Tng via B4 Relay
2026-07-07 20:46 ` [PATCH 1/4] mm: hugetlb: Fix subpool usage leak on allocation failure Ackerley Tng via B4 Relay
2026-07-07 20:46 ` [PATCH 2/4] mm: hugetlb: Fix folio refcount mismatch on memcg charge failure Ackerley Tng via B4 Relay
@ 2026-07-07 20:46 ` Ackerley Tng via B4 Relay
2026-07-08 7:04 ` Muchun Song
2026-07-07 20:46 ` [PATCH 4/4] mm: hugetlb: Move memcg charge earlier to prevent reservation leak Ackerley Tng via B4 Relay
3 siblings, 1 reply; 8+ messages in thread
From: Ackerley Tng via B4 Relay @ 2026-07-07 20:46 UTC (permalink / raw)
To: Muchun Song, Oscar Salvador, David Hildenbrand, Joshua Hahn,
Shakeel Butt, Nhat Pham, Andrew Morton, Peter Xu, Wupeng Ma, fvdl,
rientjes
Cc: vannapurve, erdemaktas, linux-mm, linux-kernel, Ackerley Tng
From: Ackerley Tng <ackerleytng@google.com>
When mem_cgroup_charge_hugetlb() fails with -ENOMEM, alloc_hugetlb_folio()
currently propagates this error. This results in the page fault handler
returning VM_FAULT_OOM.
Because HugeTLB allocations are high-order and use __GFP_RETRY_MAYFAIL,
they bypass the OOM killer. Returning VM_FAULT_OOM to the #PF handler
without triggering the OOM killer (or having it make progress) leads to
an infinite loop of retrying the fault.
Avoid this loop by returning -ENOSPC when charging fails, which maps to
VM_FAULT_SIGBUS, terminating the process cleanly.
Make mem_cgroup_charge_hugetlb() fault handling use a common error handling
path, the same handling used for hugetlb_cgroup_uncharge_cgroup{,_rsvd}(),
which also don't trigger the OOM killer and hence opt to terminate the
process with a SIGBUS.
Fixes: 991135774c0e0 ("memcg/hugetlb: introduce mem_cgroup_charge_hugetlb")
Signed-off-by: Ackerley Tng <ackerleytng@google.com>
---
mm/hugetlb.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 46e8dfffcfa5d..e42049e2c038b 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -2997,7 +2997,7 @@ struct folio *alloc_hugetlb_folio(struct vm_area_struct *vma,
if (ret == -ENOMEM) {
folio_put(folio);
- return ERR_PTR(-ENOMEM);
+ goto err;
}
return folio;
@@ -3020,6 +3020,17 @@ struct folio *alloc_hugetlb_folio(struct vm_area_struct *vma,
out_end_reservation:
if (map_chg != MAP_CHG_ENFORCED)
vma_end_reservation(h, vma, addr);
+err:
+ /*
+ * Return -ENOSPC when this function fails to allocate or
+ * charge a huge page. If a standard (PAGE_SIZE) page
+ * allocation fails, the OOM killer is given a chance to run,
+ * which may resolve the failure on retry. However, for
+ * HugeTLB allocations, the OOM killer is not triggered.
+ * Returning -ENOMEM (or anything resulting in VM_FAULT_OOM)
+ * would leak to the #PF handler, causing it to loop
+ * indefinitely retrying the fault.
+ */
return ERR_PTR(-ENOSPC);
}
--
2.55.0.795.g602f6c329a-goog
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/4] mm: hugetlb: Move memcg charge earlier to prevent reservation leak
2026-07-07 20:46 [PATCH 0/4] Fix bugs on HugeTLB folio allocation failure paths Ackerley Tng via B4 Relay
` (2 preceding siblings ...)
2026-07-07 20:46 ` [PATCH 3/4] mm: hugetlb: Return -ENOSPC " Ackerley Tng via B4 Relay
@ 2026-07-07 20:46 ` Ackerley Tng via B4 Relay
3 siblings, 0 replies; 8+ messages in thread
From: Ackerley Tng via B4 Relay @ 2026-07-07 20:46 UTC (permalink / raw)
To: Muchun Song, Oscar Salvador, David Hildenbrand, Joshua Hahn,
Shakeel Butt, Nhat Pham, Andrew Morton, Peter Xu, Wupeng Ma, fvdl,
rientjes
Cc: vannapurve, erdemaktas, linux-mm, linux-kernel, Ackerley Tng
From: Ackerley Tng <ackerleytng@google.com>
When mem_cgroup_charge_hugetlb() fails, alloc_hugetlb_folio() clears the
charges and frees the folio. The reservation committed via
vma_commit_reservation() was not undone, leaving the reservation map in an
inconsistent state, causing resv_huge_pages to leak when the process
exited.
Fix this by moving the mem_cgroup_charge_hugetlb() call earlier in
alloc_hugetlb_folio(), before vma_commit_reservation() is called.
If the charge fails now, the reservation is not yet committed. Jump to
out_subpool_put, which will then call vma_end_reservation() to abort the
reservation and keep the reservation map and resv_huge_pages counter
consistent.
Fixes: 991135774c0e0 ("memcg/hugetlb: introduce mem_cgroup_charge_hugetlb")
Signed-off-by: Ackerley Tng <ackerleytng@google.com>
---
mm/hugetlb.c | 34 ++++++++++++++++++++--------------
1 file changed, 20 insertions(+), 14 deletions(-)
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index e42049e2c038b..6e4acb1f021a5 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -2960,6 +2960,25 @@ struct folio *alloc_hugetlb_folio(struct vm_area_struct *vma,
spin_unlock_irq(&hugetlb_lock);
+ ret = mem_cgroup_charge_hugetlb(folio, gfp);
+ /*
+ * Unconditionally increment NR_HUGETLB here. If it turns out that
+ * mem_cgroup_charge_hugetlb failed, then immediately free the page and
+ * decrement NR_HUGETLB.
+ */
+ lruvec_stat_mod_folio(folio, NR_HUGETLB, pages_per_huge_page(h));
+
+ if (ret == -ENOMEM) {
+ folio_put(folio);
+ /*
+ * Charges to hugetlb_cgroup for usage and
+ * reservations were already committed, so folio_put()
+ * would have uncharged those. Go straight to undoing
+ * subpool charges.
+ */
+ goto out_subpool_put;
+ }
+
hugetlb_set_folio_subpool(folio, spool);
if (map_chg != MAP_CHG_ENFORCED) {
@@ -2987,19 +3006,6 @@ struct folio *alloc_hugetlb_folio(struct vm_area_struct *vma,
}
}
- ret = mem_cgroup_charge_hugetlb(folio, gfp);
- /*
- * Unconditionally increment NR_HUGETLB here. If it turns out that
- * mem_cgroup_charge_hugetlb failed, then immediately free the page and
- * decrement NR_HUGETLB.
- */
- lruvec_stat_mod_folio(folio, NR_HUGETLB, pages_per_huge_page(h));
-
- if (ret == -ENOMEM) {
- folio_put(folio);
- goto err;
- }
-
return folio;
out_uncharge_cgroup:
@@ -3020,7 +3026,7 @@ struct folio *alloc_hugetlb_folio(struct vm_area_struct *vma,
out_end_reservation:
if (map_chg != MAP_CHG_ENFORCED)
vma_end_reservation(h, vma, addr);
-err:
+
/*
* Return -ENOSPC when this function fails to allocate or
* charge a huge page. If a standard (PAGE_SIZE) page
--
2.55.0.795.g602f6c329a-goog
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 1/4] mm: hugetlb: Fix subpool usage leak on allocation failure
2026-07-07 20:46 ` [PATCH 1/4] mm: hugetlb: Fix subpool usage leak on allocation failure Ackerley Tng via B4 Relay
@ 2026-07-07 23:43 ` Ackerley Tng
0 siblings, 0 replies; 8+ messages in thread
From: Ackerley Tng @ 2026-07-07 23:43 UTC (permalink / raw)
To: Ackerley Tng via B4 Relay, Muchun Song, Oscar Salvador,
David Hildenbrand, Joshua Hahn, Shakeel Butt, Nhat Pham,
Andrew Morton, Peter Xu, Wupeng Ma, fvdl, rientjes
Cc: vannapurve, erdemaktas, linux-mm, linux-kernel
Ackerley Tng via B4 Relay <devnull+ackerleytng.google.com@kernel.org>
writes:
> From: Ackerley Tng <ackerleytng@google.com>
>
> When alloc_hugetlb_folio() fails early (e.g. buddy allocation failure or
> hugetlb cgroup charging failure) and gbl_chg == 1 (meaning a reservation
> was not used, but a global page was allocated instead), the subpool page
> acquired via hugepage_subpool_get_pages() must still be returned.
>
> Currently, the error path out_subpool_put: only calls
> hugepage_subpool_put_pages() if !gbl_chg is true. If gbl_chg is 1, it
> skips it, permanently leaking the subpool's used_hpages counter.
>
> Fix this by calling hugepage_subpool_put_pages() unconditionally if
> map_chg is true. Only call hugetlb_acct_memory() to adjust global
> reservations if !gbl_chg is true, to prevent underflowing the global
> resv_huge_pages counter.
>
> Fixes: a833a693a490e ("mm: hugetlb: fix incorrect fallback for subpool")
My bad. This isn't the right fix, I'm kind of re-introducing the bug
that a833a693a490e tried to fix. Let me think about a better fix.
This is what Sashiko had to say:
Can this unconditional call to hugepage_subpool_put_pages() lead to
resv_huge_pages underflowing?
If a hugetlbfs mount is configured with a minimum size but no maximum size
(so max_hpages == -1), spool->used_hpages remains 0. When the subpool's
reserve is exhausted, the next allocation will use a global page
(gbl_chg == 1).
If that allocation fails later in alloc_hugetlb_folio() (for example, hitting
a cgroup limit), we now reach this error path and call
hugepage_subpool_put_pages(spool, 1).
Because spool->used_hpages < spool->min_hpages, hugepage_subpool_put_pages()
will increment spool->rsv_hpages. However, because gbl_chg == 1, we skip
calling hugetlb_acct_memory().
This appears to leave the new subpool reservation without backing from the
global counter. When the successfully allocated pages are eventually freed,
won't resv_huge_pages be decremented out of balance, eventually underflowing
to ULONG_MAX and causing gather_surplus_pages() to exhaust system memory?
> Signed-off-by: Ackerley Tng <ackerleytng@google.com>
> ---
> mm/hugetlb.c | 14 ++++++--------
> 1 file changed, 6 insertions(+), 8 deletions(-)
>
> diff --git a/mm/hugetlb.c b/mm/hugetlb.c
> index 571212b80835e..e607dcbb2fc3e 100644
> --- a/mm/hugetlb.c
> +++ b/mm/hugetlb.c
> @@ -2858,7 +2858,7 @@ struct folio *alloc_hugetlb_folio(struct vm_area_struct *vma,
> struct hugepage_subpool *spool = subpool_vma(vma);
> struct hstate *h = hstate_vma(vma);
> struct folio *folio;
> - long retval, gbl_chg, gbl_reserve;
> + long retval, gbl_chg;
> map_chg_state map_chg;
> int ret, idx;
> struct hugetlb_cgroup *h_cg = NULL;
> @@ -3009,13 +3009,11 @@ struct folio *alloc_hugetlb_folio(struct vm_area_struct *vma,
> hugetlb_cgroup_uncharge_cgroup_rsvd(idx, pages_per_huge_page(h),
> h_cg_rsvd);
> out_subpool_put:
> - /*
> - * 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) {
> + long gbl_reserve = hugepage_subpool_put_pages(spool, 1);
> +
> + if (!gbl_chg)
> + hugetlb_acct_memory(h, -gbl_reserve);
> }
>
>
>
> --
> 2.55.0.795.g602f6c329a-goog
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/4] mm: hugetlb: Fix folio refcount mismatch on memcg charge failure
2026-07-07 20:46 ` [PATCH 2/4] mm: hugetlb: Fix folio refcount mismatch on memcg charge failure Ackerley Tng via B4 Relay
@ 2026-07-08 6:59 ` Muchun Song
0 siblings, 0 replies; 8+ messages in thread
From: Muchun Song @ 2026-07-08 6:59 UTC (permalink / raw)
To: ackerleytng
Cc: Oscar Salvador, David Hildenbrand, Joshua Hahn, Shakeel Butt,
Nhat Pham, Andrew Morton, Peter Xu, Wupeng Ma, fvdl, rientjes,
vannapurve, erdemaktas, linux-mm, linux-kernel
> On Jul 8, 2026, at 04:46, Ackerley Tng via B4 Relay <devnull+ackerleytng.google.com@kernel.org> wrote:
>
> From: Ackerley Tng <ackerleytng@google.com>
>
> When mem_cgroup_charge_hugetlb(folio, gfp) returns -ENOMEM, the folio has
> its refcount set to 1 via folio_ref_unfreeze(folio, 1).
>
> The error path calls free_huge_folio(folio) directly, which expects a
> refcount of 0. Hence, VM_BUG_ON_FOLIO(folio_ref_count(folio), folio) is
> triggered.
>
> Even with CONFIG_DEBUG_VM disabled, returning a folio with refcount 1 to
> the freelist can corrupt allocator state later.
>
> Use folio_put(folio) instead of free_huge_folio(folio) to properly drop the
> reference before freeing it.
>
> Fixes: 991135774c0e0 ("memcg/hugetlb: introduce mem_cgroup_charge_hugetlb")
> Signed-off-by: Ackerley Tng <ackerleytng@google.com>
Yes, a real issue, I think we should cc stable as well.
Reviewed-by: Muchun Song <muchun.song@linux.dev>
Thanks.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 3/4] mm: hugetlb: Return -ENOSPC on memcg charge failure
2026-07-07 20:46 ` [PATCH 3/4] mm: hugetlb: Return -ENOSPC " Ackerley Tng via B4 Relay
@ 2026-07-08 7:04 ` Muchun Song
0 siblings, 0 replies; 8+ messages in thread
From: Muchun Song @ 2026-07-08 7:04 UTC (permalink / raw)
To: ackerleytng
Cc: Oscar Salvador, David Hildenbrand, Joshua Hahn, Shakeel Butt,
Nhat Pham, Andrew Morton, Peter Xu, Wupeng Ma, fvdl, rientjes,
vannapurve, erdemaktas, linux-mm, linux-kernel
> On Jul 8, 2026, at 04:46, Ackerley Tng via B4 Relay <devnull+ackerleytng.google.com@kernel.org> wrote:
>
> From: Ackerley Tng <ackerleytng@google.com>
>
> When mem_cgroup_charge_hugetlb() fails with -ENOMEM, alloc_hugetlb_folio()
> currently propagates this error. This results in the page fault handler
> returning VM_FAULT_OOM.
>
> Because HugeTLB allocations are high-order and use __GFP_RETRY_MAYFAIL,
> they bypass the OOM killer. Returning VM_FAULT_OOM to the #PF handler
> without triggering the OOM killer (or having it make progress) leads to
> an infinite loop of retrying the fault.
>
> Avoid this loop by returning -ENOSPC when charging fails, which maps to
> VM_FAULT_SIGBUS, terminating the process cleanly.
>
> Make mem_cgroup_charge_hugetlb() fault handling use a common error handling
> path, the same handling used for hugetlb_cgroup_uncharge_cgroup{,_rsvd}(),
> which also don't trigger the OOM killer and hence opt to terminate the
> process with a SIGBUS.
>
> Fixes: 991135774c0e0 ("memcg/hugetlb: introduce mem_cgroup_charge_hugetlb")
> Signed-off-by: Ackerley Tng <ackerleytng@google.com>
Please cc stable as well.
Reviewed-by: Muchun Song <muchun.song@linux.dev>
Thanks.
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-07-08 7:04 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-07 20:46 [PATCH 0/4] Fix bugs on HugeTLB folio allocation failure paths Ackerley Tng via B4 Relay
2026-07-07 20:46 ` [PATCH 1/4] mm: hugetlb: Fix subpool usage leak on allocation failure Ackerley Tng via B4 Relay
2026-07-07 23:43 ` Ackerley Tng
2026-07-07 20:46 ` [PATCH 2/4] mm: hugetlb: Fix folio refcount mismatch on memcg charge failure Ackerley Tng via B4 Relay
2026-07-08 6:59 ` Muchun Song
2026-07-07 20:46 ` [PATCH 3/4] mm: hugetlb: Return -ENOSPC " Ackerley Tng via B4 Relay
2026-07-08 7:04 ` Muchun Song
2026-07-07 20:46 ` [PATCH 4/4] mm: hugetlb: Move memcg charge earlier to prevent reservation leak Ackerley Tng via B4 Relay
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox