mm/memfd.c | 6 ++++++ 1 file changed, 6 insertions(+)
From: Hongfu Li <lihongfu@kylinos.cn>
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@kylinos.cn>
---
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
On Mon, 31 Aug 2026 17:06:31 +0800 Hongfu Li <hongfu.li@linux.dev> wrote: > From: Hongfu Li <lihongfu@kylinos.cn> > > 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. Thanks. AI review might have found another bug and it suggests that your proposal only partially fixes this bug: https://sashiko.dev/#/patchset/20260831090631.29227-1-hongfu.li@linux.dev
On 9/1/26 8:35 AM, Andrew Morton wrote: > On Mon, 31 Aug 2026 17:06:31 +0800 Hongfu Li <hongfu.li@linux.dev> wrote: > >> From: Hongfu Li <lihongfu@kylinos.cn> >> >> 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. > Thanks. > > AI review might have found another bug and it suggests that your > proposal only partially fixes this bug: > > https://sashiko.dev/#/patchset/20260831090631.29227-1-hongfu.li@linux.dev Thank you for the reminder. I have carefully gone through the Sashiko review report. The issue it pointed out is valid. I will address this remaining problem and send out a v2 patch shortly. -- Best regards, Hongfu
© 2016 - 2026 Red Hat, Inc.