From: "Kiryl Shutsemau (Meta)" <[email protected]> A PTE that is none and one that maps the shared zeropage both stand for a page of zeroes the mapping does not own. Code that cares only about the contents can treat the two alike.
Move khugepaged's local helper for that test to pgtable.h, below the is_zero_pfn() it is built on. migrate_vma_insert_page() open-codes the same test on the slot it is about to fill. Convert it. It still tells none from the zeropage, but only to decide whether there is an old mapping to flush. No functional change intended. Assisted-by: Claude-Code:claude-opus-5 Signed-off-by: Kiryl Shutsemau (Meta) <[email protected]> --- include/linux/pgtable.h | 17 +++++++++++++++++ mm/khugepaged.c | 7 ------- mm/migrate_device.c | 9 ++------- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/include/linux/pgtable.h b/include/linux/pgtable.h index 8c093c119e5a..bbee6d31f015 100644 --- a/include/linux/pgtable.h +++ b/include/linux/pgtable.h @@ -2064,6 +2064,23 @@ static inline struct page *_zero_page(unsigned long addr) #ifdef CONFIG_MMU +/** + * pte_none_or_zero - Does this PTE map nothing, or the shared zeropage? + * @pte: The page table entry to test. + * + * A PTE that is none and one that maps the shared zeropage both stand for a + * page of zeroes the mapping does not own, so code that only cares about the + * contents can treat them alike. + * + * Return: %true if @pte is none or maps the shared zeropage. + */ +static inline bool pte_none_or_zero(pte_t pte) +{ + if (pte_none(pte)) + return true; + return pte_present(pte) && is_zero_pfn(pte_pfn(pte)); +} + #ifndef CONFIG_TRANSPARENT_HUGEPAGE static inline int pmd_trans_huge(pmd_t pmd) { diff --git a/mm/khugepaged.c b/mm/khugepaged.c index 5a06e3942e88..5f7126cf42f5 100644 --- a/mm/khugepaged.c +++ b/mm/khugepaged.c @@ -348,13 +348,6 @@ struct attribute_group khugepaged_attr_group = { }; #endif /* CONFIG_SYSFS */ -static bool pte_none_or_zero(pte_t pte) -{ - if (pte_none(pte)) - return true; - return pte_present(pte) && is_zero_pfn(pte_pfn(pte)); -} - /** * collapse_max_ptes_none - Calculate maximum allowed empty PTEs or PTEs mapping * the shared zeropage for the given collapse operation. diff --git a/mm/migrate_device.c b/mm/migrate_device.c index 9a346162c688..60afa556b994 100644 --- a/mm/migrate_device.c +++ b/mm/migrate_device.c @@ -1067,14 +1067,9 @@ static void migrate_vma_insert_page(struct migrate_vma *migrate, if (check_stable_address_space(mm)) goto unlock_abort; - if (pte_present(orig_pte)) { - unsigned long pfn = pte_pfn(orig_pte); - - if (!is_zero_pfn(pfn)) - goto unlock_abort; - flush = true; - } else if (!pte_none(orig_pte)) + if (!pte_none_or_zero(orig_pte)) goto unlock_abort; + flush = pte_present(orig_pte); /* * Check for userfaultfd but do not deliver the fault. Instead, -- 2.54.0
