[PATCH RFC 5/9] mm/huge_memory: dispatch on the folio when splitting a huge PMD

From: Yin Tirui

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


Only anonymous folios carry the anon rmap and PageAnonExclusive() state
needed when rebuilding PTEs, so decide the split path from
folio_test_anon() rather than vma_is_anonymous(). Treat a NULL folio as
nothing to rebuild.

This only changes behavior for folio/VMA mismatches, which are not produced
by any in-tree path.

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

diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index b2ede9a6ae5d..1cd8878edc1d 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -3244,7 +3244,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
if (unlikely(!is_present && !folio))
return;

- if (!vma_is_anonymous(vma)) {
+ if (!folio || !folio_test_anon(folio)) {
unmap_huge_pmd_entry(vma, haddr, pmd, folio, is_present);
return;
}
@@ -3254,14 +3254,12 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,

entry = softleaf_from_pmd(old_pmd);
page = softleaf_to_page(entry);
- folio = page_folio(page);

soft_dirty = pmd_swp_soft_dirty(old_pmd);
uffd_wp = pmd_swp_uffd(old_pmd);

write = softleaf_is_migration_write(entry);
- if (PageAnon(page))
- anon_exclusive = softleaf_is_migration_read_exclusive(entry);
+ anon_exclusive = softleaf_is_migration_read_exclusive(entry);
young = softleaf_is_migration_young(entry);
dirty = softleaf_is_migration_dirty(entry);
} else if (pmd_is_device_private_entry(old_pmd)) {
@@ -3269,7 +3267,6 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,

entry = softleaf_from_pmd(old_pmd);
page = softleaf_to_page(entry);
- folio = page_folio(page);

soft_dirty = pmd_swp_soft_dirty(old_pmd);
uffd_wp = pmd_swp_uffd(old_pmd);
@@ -3321,7 +3318,6 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
*/
old_pmd = pmdp_invalidate(vma, haddr, pmd);
page = pmd_page(old_pmd);
- folio = page_folio(page);
if (pmd_dirty(old_pmd)) {
dirty = true;
folio_set_dirty(folio);
@@ -3332,7 +3328,6 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
uffd_wp = pmd_uffd(old_pmd);

VM_WARN_ON_FOLIO(!folio_ref_count(folio), folio);
- VM_WARN_ON_FOLIO(!folio_test_anon(folio), folio);

/*
* Without "freeze", we'll simply split the PMD, propagating the
--
2.34.1