[PATCH v2] mm/memory-failure: fix refcount leak on soft-offline LBS folio
[email protected] Tue, 4 Aug 2026 11:53:56 +0800
| Newsgroups | org.kvack.linux-mm |
|---|---|
| Message-ID | <[email protected]> |
From: liyouhong <[email protected]> soft_offline_in_use_page() runs with a folio reference taken by get_hwpoison_page(). Soft-offline skips splitting when min_order_for_split() is non-zero, so large folios stay intact. That early return -EBUSY path never drops the reference. The other failure path is fine: try_to_split_thp_page(..., release=true) puts the page when the split itself fails. memory_failure() also puts explicitly on its analogous unsplit path. Handle the new_order != 0 case separately and call folio_put() before returning. Fixes: 689b8986776c ("mm/memory-failure: improve large block size folio handling") Signed-off-by: liyouhong <[email protected]> --- v2: - Add documentation for the folio reference counting convention of soft_offline_in_use_page(). - Remove MF_COUNT_INCREASED related description in commit message to avoid misleading. v1: https://lore.kernel.org/all/[email protected]/ --- mm/memory-failure.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 51508a55c405..3b1e6946821b 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -2776,6 +2776,9 @@ EXPORT_SYMBOL(unpoison_memory); * soft_offline_in_use_page handles hugetlb-pages and non-hugetlb pages. * If the page is a non-dirty unmapped page-cache page, it simply invalidates. * If the page is mapped, it migrates the contents over. + * + * The folio refcount has been incremented before entering this function. + * This folio reference must be released before the function returns on all paths. */ static int soft_offline_in_use_page(struct page *page) { @@ -2801,9 +2804,19 @@ static int soft_offline_in_use_page(struct page *page) * NOTE: if minimizing the number of soft offline pages is * preferred, split it to non-zero new_order like it is done in * memory_failure(). + * + * Drop the reference obtained upon entry; + * try_to_split_thp_page(..., release=true) handles refcounting itself + * when the split fails. */ - if (new_order || try_to_split_thp_page(page, /* new_order= */ 0, - /* release= */ true)) { + if (new_order) { + pr_info("%#lx: order-%d folio cannot soft offline\n", + pfn, new_order); + folio_put(folio); + return -EBUSY; + } + if (try_to_split_thp_page(page, /* new_order= */ 0, + /* release= */ true)) { pr_info("%#lx: thp split failed\n", pfn); return -EBUSY; } -- 2.25.1