v1 2026-08-29

重构 THP PMD 拆分判定逻辑 · v1

重构 __split_huge_pmd_locked(),由 PMD 项/folio 决定拆分与回收分类,分离 present 与非 present 路径,消除与 zap_huge_pmd 的判定不一致。

原始补丁链接

子 Patch(9)

1/9
mm/huge_memory: read the huge PMD entry once when splitting it
__split_huge_pmd_locked() re-reads *pmd several times to classify the same entry. The PMD page table lock is held throughout, so read it once into old_pmd and classify from that. No functional change
2/9
mm/huge_memory: add and use huge_zero_pmd_can_split()
Only a huge zero PMD in an anonymous VMA is split, into a page table of shared zero page mappings. Any other huge zero PMD is simply unmapped. vm_normal_folio_pmd() returns NULL for a huge zero PMD,
3/9
mm/huge_memory: add and use unmap_huge_pmd_entry()
Only a huge PMD entry mapping an anonymous folio is split. Everything else is unmapped and comes back on the next fault. Put that in unmap_huge_pmd_entry(). Old and new differ only for a device priva
4/9
mm/huge_memory: use normal_or_softleaf_folio_pmd() in the PMD split path
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 dr
5/9
mm/huge_memory: dispatch on the folio when splitting a huge PMD
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
6/9
mm/huge_memory: add and use split_huge_pmd_anon_rmap()
The anon-exclusive handling and the PTE-level rmap conversion are written twice, once for present entries and once for device private ones. Factor them into one helper. It returns whether the mapping
7/9
mm/huge_memory: add struct split_pmd_state
Put the state read out of the entry being split into one descriptor, so the read and write paths can be separated without passing a long argument list between them. No functional change intended. Si
8/9
mm/huge_memory: split present and non-present huge PMDs separately
Move the shared PTE rebuild into split_huge_pmd_to_ptes(), then add split_present_huge_pmd() and split_non_present_huge_pmd() on top of it to separate the present and non-present cases in __split_huge
9/9
mm/huge_memory: unify the migration and device private PTE loops
When splitting a huge PMD into non-present PTEs, one loop installs migration entries while the other installs device private entries. They differ only in the leaf entry they build. Build the entry in