From: Andrew Morton <akpm@linux-foundation.org>
To: mm-commits@vger.kernel.org,ziy@nvidia.com,usama.arif@linux.dev,
tz2294@columbia.edu,stable@vger.kernel.org,ryan.roberts@arm.com,
richard.weiyang@gmail.com,nico.pache@linux.dev,nao.horiguchi@gmail.com,
mcgrof@kernel.org,ljs@kernel.org,liyouhong@kylinos.cn,linmiaohe@huawei.com,
liam@infradead.org,lance.yang@linux.dev,dev.jain@arm.com,
baolin.wang@linux.alibaba.com,baohua@kernel.org,david@kernel.org,
akpm@linux-foundation.org
Subject: [merged mm-hotfixes-stable] mm-memory-failure-fix-folio-refcount-leak-and-min_order_for_split-locking.patch removed from -mm tree
Date: Mon, 09 Nov 2026 22:45:28 -0800 [thread overview]
Message-ID: <20261110064529.5D7921F0089F@smtp.kernel.org> (raw)
The quilt patch titled
Subject: mm/memory-failure: fix folio refcount leak and min_order_for_split() locking
has been removed from the -mm tree. Its filename was
mm-memory-failure-fix-folio-refcount-leak-and-min_order_for_split-locking.patch
This patch was dropped because it was merged into the mm-hotfixes-stable branch
of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
------------------------------------------------------
From: "David Hildenbrand (Arm)" <david@kernel.org>
Subject: mm/memory-failure: fix folio refcount leak and min_order_for_split() locking
Date: Fri, 30 Oct 2026 23:29:13 +0100
hwpoison code can end up calling min_order_for_split() without holding the
folio lock. There isn't really something that would prevent concurrent
truncation. Consequently folio->mapping can get set to NULL after
checking for "!folio->mapping", and if the compiler reloads
folio->mapping, mapping_min_folio_order() would try to dereference NULL.
While very unlikely to happen in practice, let's just enforce that
min_order_for_split() is called with the folio lock held. We can
significantly cleanup the calling hwpoison code, and just get rid of
try_to_split_thp_page() to hold the folio lock for a bit longer.
Just work on folios now, which further cleans up the code. We just have
to be careful about doing the page_folio() after splitting, which we have
to do already either way. Do not change the way we split for now, this
needs more thought and should be done separately.
Cleaning this up we fix another issue: in soft_offline_in_use_page(), we
would currently have leaked a folio reference.
In min_order_for_split(), document and assert that we need the folio lock.
Drop the questionable VM_BUG_ON_PAGE(!page_count(p), p) check entirely.
While updating the comment in soft_offline_in_use_page(), just drop the
"NOTE" part that does not add any value to current code.
The folio->mapping problem was identified by Sashiko, and Li Youhong
reported it by sending a proposal fix.
This likely does not really warrant CCing stable, but I expect little
conflicts when doing the backport, so let's just CC stable because of the
refcount leak.
Link: https://lore.kernel.org/20261030-try_to_split_thp_page-v2-1-c957c9b42eab@kernel.org
Fixes: 689b8986776c ("mm/memory-failure: improve large block size folio handling")
Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Reported-by: Li Youhong <liyouhong@kylinos.cn>
Closes: https://lore.kernel.org/r/20260804035828.2684059-1-dayou5941@163.com
Acked-by: Usama Arif <usama.arif@linux.dev>
Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
Reviewed-by: Zi Yan <ziy@nvidia.com>
Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
Acked-by: Miaohe Lin <linmiaohe@huawei.com>
Cc: Liam R. Howlett <liam@infradead.org>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Cc: Dev Jain <dev.jain@arm.com>
Cc: Barry Song <baohua@kernel.org>
Cc: Lance Yang <lance.yang@linux.dev>
Cc: Naoya Horiguchi <nao.horiguchi@gmail.com>
Cc: Wei Yang <richard.weiyang@gmail.com>
Cc: Nico Pache <nico.pache@linux.dev>
Cc: Luis Chamberlain <mcgrof@kernel.org>
Cc: Tal Zussman <tz2294@columbia.edu>
Cc: <stable@vger.kernel.org>
---
mm/huge_memory.c | 4 ++
mm/memory-failure.c | 63 ++++++++++++++----------------------------
2 files changed, 25 insertions(+), 42 deletions(-)
--- a/mm/huge_memory.c~mm-memory-failure-fix-folio-refcount-leak-and-min_order_for_split-locking
+++ a/mm/huge_memory.c
@@ -4551,10 +4551,14 @@ int folio_split(struct folio *folio, uns
* If a file-backed folio is truncated, 0 will be returned. Any subsequent
* split attempt should get -EBUSY from split checking code.
*
+ * Context: @folio must be locked.
+ *
* Return: @folio's minimum order for split
*/
unsigned int min_order_for_split(struct folio *folio)
{
+ VM_WARN_ON_ONCE_FOLIO(!folio_test_locked(folio), folio);
+
if (folio_test_anon(folio))
return 0;
--- a/mm/memory-failure.c~mm-memory-failure-fix-folio-refcount-leak-and-min_order_for_split-locking
+++ a/mm/memory-failure.c
@@ -1744,26 +1744,6 @@ static int identify_page_state(unsigned
return page_action(ps, p, pfn);
}
-/*
- * When 'release' is 'false', it means that if thp split has failed,
- * there is still more to do, hence the page refcount we took earlier
- * is still needed.
- */
-static int try_to_split_thp_page(struct page *page, unsigned int new_order,
- bool release)
-{
- int ret;
-
- lock_page(page);
- ret = split_huge_page_to_order(page, new_order);
- unlock_page(page);
-
- if (ret && release)
- put_page(page);
-
- return ret;
-}
-
static void unmap_and_kill(struct list_head *to_kill, unsigned long pfn,
struct address_space *mapping, pgoff_t index, int flags)
{
@@ -2548,9 +2528,6 @@ try_again:
folio_unlock(folio);
if (folio_test_large(folio)) {
- const int new_order = min_order_for_split(folio);
- int err;
-
/*
* The flag must be set after the refcount is bumped
* otherwise it may race with THP split.
@@ -2565,24 +2542,25 @@ try_again:
* page is a valid handlable page.
*/
folio_set_has_hwpoisoned(folio);
- err = try_to_split_thp_page(p, new_order, /* release= */ false);
+
+ folio_lock(folio);
+ split_huge_page_to_order(p, min_order_for_split(folio));
+ folio = page_folio(p);
+ folio_unlock(folio);
+
/*
* If splitting a folio to order-0 fails, kill the process.
* Split the folio regardless to minimize unusable pages.
* Because the memory failure code cannot handle large
* folios, this split is always treated as if it failed.
*/
- if (err || new_order) {
- /* get folio again in case the original one is split */
- folio = page_folio(p);
+ if (folio_test_large(folio)) {
res = -EHWPOISON;
kill_procs_now(p, pfn, flags, folio);
- put_page(p);
+ folio_put(folio);
action_result(pfn, MF_MSG_UNSPLIT_THP, MF_FAILED);
goto unlock_mutex;
}
- VM_BUG_ON_PAGE(!page_count(p), p);
- folio = page_folio(p);
}
/*
@@ -2900,25 +2878,26 @@ static int soft_offline_in_use_page(stru
.reason = MR_MEMORY_FAILURE,
};
+ folio_lock(folio);
if (!huge && folio_test_large(folio)) {
- const int new_order = min_order_for_split(folio);
-
/*
- * If new_order (target split order) is not 0, do not split the
- * folio at all to retain the still accessible large folio.
- * 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().
+ * If we cannot split to order-0, do not split the folio at all
+ * to retain the still accessible large folio.
*/
- if (new_order || try_to_split_thp_page(page, /* new_order= */ 0,
- /* release= */ true)) {
+ if (!min_order_for_split(folio))
+ ret = split_huge_page_to_order(page, 0) ? -EBUSY : 0;
+ else
+ ret = -EBUSY;
+ folio = page_folio(page);
+
+ if (ret) {
+ folio_unlock(folio);
+ folio_put(folio);
pr_info("%#lx: thp split failed\n", pfn);
- return -EBUSY;
+ return ret;
}
- folio = page_folio(page);
}
- folio_lock(folio);
if (!huge)
folio_wait_writeback(folio);
if (PageHWPoison(page)) {
_
Patches currently in -mm which might be from david@kernel.org are
mm-mprotect-dont-skip-uffd-marker-install-when-racing-with-pte-table-reclaim.patch
mm-khugepaged-free-unused-page-table-when-setting-a-huge-pmd-fails.patch
reply other threads:[~2026-11-10 6:45 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261110064529.5D7921F0089F@smtp.kernel.org \
--to=akpm@linux-foundation.org \
--cc=baohua@kernel.org \
--cc=baolin.wang@linux.alibaba.com \
--cc=david@kernel.org \
--cc=dev.jain@arm.com \
--cc=lance.yang@linux.dev \
--cc=liam@infradead.org \
--cc=linmiaohe@huawei.com \
--cc=liyouhong@kylinos.cn \
--cc=ljs@kernel.org \
--cc=mcgrof@kernel.org \
--cc=mm-commits@vger.kernel.org \
--cc=nao.horiguchi@gmail.com \
--cc=nico.pache@linux.dev \
--cc=richard.weiyang@gmail.com \
--cc=ryan.roberts@arm.com \
--cc=stable@vger.kernel.org \
--cc=tz2294@columbia.edu \
--cc=usama.arif@linux.dev \
--cc=ziy@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox