FAILED: patch "[PATCH] mm/thp: fix __split_huge_pmd_locked() for migration PMD" failed to apply to 4.19-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 4.19-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From ec0abae6dcdf7ef88607c869bf35a4b63ce1b370 Mon Sep 17 00:00:00 2001
From: Ralph Campbell <[email protected]>
Date: Fri, 18 Sep 2020 21:20:24 -0700
Subject: [PATCH] mm/thp: fix __split_huge_pmd_locked() for migration PMD
A migrating transparent huge page has to already be unmapped. Otherwise, the page could be modified while it is being copied to a new page and data could be lost. The function __split_huge_pmd() checks for a PMD migration entry before calling __split_huge_pmd_locked() leading one to think that __split_huge_pmd_locked() can handle splitting a migrating PMD.
However, the code always increments the page->_mapcount and adjusts the memory control group accounting assuming the page is mapped.
Also, if the PMD entry is a migration PMD entry, the call to is_huge_zero_pmd(*pmd) is incorrect because it calls pmd_pfn(pmd) instead of migration_entry_to_pfn(pmd_to_swp_entry(pmd)). Fix these problems by checking for a PMD migration entry.
mm/huge_memory.c +23 -19
@@ -2022,7 +2022,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,put_page (page);add_mm_counter (mm,mm_counter_file (page), -HPAGE_PMD_NR );return ; - }else if (is_huge_zero_pmd (*pmd)) { + }else if (pmd_trans_huge (*pmd) &&is_huge_zero_pmd (*pmd)) {/* * FIXME: Do we want to invalidate secondary mmu by calling * mmu_notifier_invalidate_range() see comments below inside
@@ -2116,30 +2116,34 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd, pte =pte_offset_map (&_pmd, addr);BUG_ON (!pte_none (*pte));set_pte_at (mm, addr, pte, entry); -atomic_inc (&page[i]._mapcount); -pte_unmap (pte); - } - -/* -* Set PG_double_map before dropping compound_mapcount to avoid -* false-negative page_mapped(). -*/ -if (compound_mapcount (page) >1 && !TestSetPageDoubleMap (page)) { -for (i =0 ; i <HPAGE_PMD_NR ; i++) +if (!pmd_migration)atomic_inc (&page[i]._mapcount); +pte_unmap (pte); } -lock_page_memcg (page); -if (atomic_add_negative (-1 ,compound_mapcount_ptr (page))) { -/* Last compound_mapcount is gone. */ -__dec_lruvec_page_state (page,NR_ANON_THPS ); -if (TestClearPageDoubleMap (page)) { -/* No need in mapcount reference anymore */ +if (!pmd_migration) { +/* +* Set PG_double_map before dropping compound_mapcount to avoid +* false-negative page_mapped(). +*/ +if (compound_mapcount (page) >1 && + !TestSetPageDoubleMap (page)) {for (i =0 ; i <HPAGE_PMD_NR ; i++) -atomic_dec (&page[i]._mapcount); +atomic_inc (&page[i]._mapcount); + } + +lock_page_memcg (page); +if (atomic_add_negative (-1 ,compound_mapcount_ptr (page))) { +/* Last compound_mapcount is gone. */ +__dec_lruvec_page_state (page,NR_ANON_THPS ); +if (TestClearPageDoubleMap (page)) { +/* No need in mapcount reference anymore */ +for (i =0 ; i <HPAGE_PMD_NR ; i++) +atomic_dec (&page[i]._mapcount); + } } +unlock_page_memcg (page); } -unlock_page_memcg (page);smp_wmb ();/* make pte visible before pmd */ pmd_populate (mm, pmd, pgtable);