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

From: Lance Yang

Date: Sun Sep 13 2026 - 01:22:02 EST




On 2026/9/12 15:37, Lance Yang wrote:

On Sat, Aug 29, 2026 at 02:33:14AM +0800, Yin Tirui wrote:
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);

Staring at this ... I think we're missing raw PFN mappings of the huge
zero folio ...

static bool has_deposited_pgtable(struct vm_area_struct *vma, pmd_t pmdval,
struct folio *folio)
{
/* Some architectures require unconditional depositing. */
if (arch_needs_pgtable_deposit())
return true;

...
if (is_huge_zero_pmd(pmdval))
return !vma_is_dax(vma);

...
return folio && folio_test_anon(folio);
}

If a non-DAX raw PFN mapping on x86 (say, via mshv_vtl_low) matches
huge_zero_pfn, vmf_insert_pfn_pmd() won't deposit a page table, but
has_deposited_pgtable() will return true ...

Before this patch, arch_needs_pgtable_deposit() skips withdrawal when
splitting this mapping on x86. The new check would instead reach
pgtable_trans_huge_withdraw() and dereference NULL through pgtable->lru
if pmd_huge_pte(mm, pmd) is NULL.

The helper already causes the same bug in zap_huge_pmd(), but extending
it to split is a regression introduced by this patch. I'll send a separate
fix, and we need it landed first :D

https://lore.kernel.org/linux-mm/20260913051942.40889-1-lance.yang@xxxxxxxxx/T/#u