[PATCH RFC 4/9] mm/huge_memory: use normal_or_softleaf_folio_pmd() in the PMD split path

From: Yin Tirui

Date: Fri Aug 28 2026 - 14:42:24 EST


Get the folio once with normal_or_softleaf_folio_pmd() and decide the
deposit once with has_deposited_pgtable(), as zap_huge_pmd() does. That
makes split and zap classify an entry the same way, and drops
vma_is_special_huge() from this path.

Behaviour changes only where the entry and the VMA flags disagree, which no
in-tree path produces.

Signed-off-by: Yin Tirui <yintirui@xxxxxxxxx>
---
mm/huge_memory.c | 21 ++++++++++++---------
1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index aefd62827139..b2ede9a6ae5d 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -3172,7 +3172,7 @@ static void unmap_huge_pmd_entry(struct vm_area_struct *vma,
* We are going to unmap this huge page. So
* just go ahead and zap it
*/
- if (arch_needs_pgtable_deposit())
+ if (has_deposited_pgtable(vma, old_pmd, folio))
zap_deposited_table(mm, pmd);

if (!folio)
@@ -3199,6 +3199,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
{
struct mm_struct *mm = vma->vm_mm;
pmd_t old_pmd = *pmd;
+ const bool is_present = pmd_present(old_pmd);
struct folio *folio;
struct page *page;
pgtable_t pgtable;
@@ -3232,16 +3233,18 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
return;
}

- if (!vma_is_anonymous(vma)) {
- const bool is_present = pmd_present(old_pmd);
+ folio = normal_or_softleaf_folio_pmd(vma, haddr, old_pmd, is_present);

- if (vma_is_special_huge(vma) || is_huge_zero_pmd(old_pmd))
- folio = NULL;
- else if (is_present)
- folio = page_folio(pmd_page(old_pmd));
- else
- folio = softleaf_to_folio(softleaf_from_pmd(old_pmd));
+ /*
+ * A non-present entry which is neither a migration nor a device
+ * private entry is corrupt, and pmd_to_softleaf_folio() has already
+ * warned about it. Leave it alone rather than act on a PFN which
+ * means nothing.
+ */
+ if (unlikely(!is_present && !folio))
+ return;

+ if (!vma_is_anonymous(vma)) {
unmap_huge_pmd_entry(vma, haddr, pmd, folio, is_present);
return;
}
--
2.34.1