[PATCH for 7.4-rc2+ 7/7] mm/rmap: re-enable discarding lazyfree THPs at PMD level

From: Zi Yan

Date: Thu Oct 15 2026 - 14:41:28 EST


The patch "mm/rmap: don't discard lazyfree THPs at PMD level" disabled
the PMD-level discard, because it cleared the PMD before checking whether
the folio could be discarded, and munmap() or mremap() could skip that
transiently none PMD.

__discard_anon_folio_pmd_locked() now keeps the PMD invalidated, not
cleared, until the discard is committed, GUP-fast no longer follows an
invalidated PMD on any architecture, powerpc page table check no longer
counts an invalidated PMD as mapped, and sparc64 keeps thp_pte_count
balanced when an invalidated PMD is set again or cleared. Discard lazyfree
THPs at PMD level again.

Assisted-by: LLM
Signed-off-by: Zi Yan <ziy@xxxxxxxxxx>
To: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
To: David Hildenbrand <david@xxxxxxxxxx>
To: Lorenzo Stoakes <ljs@xxxxxxxxxx>
Cc: Rik van Riel <riel@xxxxxxxxxxx>
Cc: "Liam R. Howlett" <liam@xxxxxxxxxxxxx>
Cc: Vlastimil Babka <vbabka@xxxxxxxxxx>
Cc: Harry Yoo <harry@xxxxxxxxxx>
Cc: Jann Horn <jannh@xxxxxxxxxx>
Cc: Lance Yang <lance.yang@xxxxxxxxx>
Cc: Kyle Zeng <kylebot@xxxxxxxxxx>
Cc: linux-mm@xxxxxxxxx
Cc: linux-kernel@xxxxxxxxxxxxxxx
---
mm/rmap.c | 11 +++++++++++
1 file changed, 11 insertions(+)

diff --git a/mm/rmap.c b/mm/rmap.c
index 1131b76bbbc28..805db93fe0428 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -2275,6 +2275,17 @@ static bool try_to_unmap_one(struct folio *folio, struct vm_area_struct *vma,
}

if (!pvmw.pte) {
+ if (folio_test_lazyfree(folio)) {
+ if (unmap_huge_pmd_locked(vma, pvmw.address, pvmw.pmd, folio))
+ goto walk_done;
+ /*
+ * unmap_huge_pmd_locked has either already marked
+ * the folio as swap-backed or decided to retain it
+ * due to GUP or speculative references.
+ */
+ goto walk_abort;
+ }
+
if (flags & TTU_SPLIT_HUGE_PMD) {
/*
* We temporarily have to drop the PTL and

--
2.53.0