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 --- 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