[PATCH] mm/memfd: don't unreserve hugetlb pages on -EEXIST in error path

From: Hongfu Li

Date: Mon Aug 31 2026 - 05:12:29 EST


From: Hongfu Li <lihongfu@xxxxxxxxxx>

If hugetlb_add_to_page_cache() fails with -EEXIST, a concurrent fault has
already instantiated the folio in the page cache, and the reservation now
belongs to that folio. Calling hugetlb_unreserve_pages() in that case
incorrectly removes the region backing the cached folio, and a later
truncate or inode eviction passes a negative (chg - freed) into
hugepage_subpool_put_pages(), corrupting subpool and resv_huge_pages
accounting.

Skip the unreserve on -EEXIST; failures other than -EEXIST leave the
reservation unconsumed and still unreserve it.

Fixes: 717cf9357325 ("mm/memfd: reserve hugetlb folios before allocation")
Signed-off-by: Hongfu Li <lihongfu@xxxxxxxxxx>
---
mm/memfd.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/mm/memfd.c b/mm/memfd.c
index c708d92533f4..1b65bc22fb19 100644
--- a/mm/memfd.c
+++ b/mm/memfd.c
@@ -128,6 +128,12 @@ struct folio *memfd_alloc_folio(struct file *memfd, pgoff_t idx)

if (err) {
folio_put(folio);
+ /*
+ * On -EEXIST, a concurrent fault has cached the folio,
+ * which now owns the reservation; don't unreserve.
+ */
+ if (err == -EEXIST)
+ return ERR_PTR(err);
goto err_unresv;
}

--
2.54.0