Subject: Revert "mm: numa: defer TLB flush for THP migration as long as possible" From: Nadav Amit Date: Tue, 1 Aug 2017 17:08:14 -0700 While deferring TLB flushes is a good practice, the reverted patch caused pending TLB flushes to be checked while the page-table lock is not taken. As a result, in architectures with weak memory model (PPC), Linux may miss a memory-barrier, miss the fact TLB flushes are pending, and cause (in theory) a memory corruption. Since the alternative of using smp_mb__after_unlock_lock() was considered a bit open-coded, and the performance impact is expected to be small, the previous patch is reverted. This reverts commit b0943d61b8fa420180f92f64ef67662b4f6cc493. Cc: Cc: Sergey Senozhatsky Cc: CC: Cc: Minchan Kim Cc: Andy Lutomirski Suggested-by: Mel Gorman Signed-off-by: Nadav Amit Acked-by: Mel Gorman Acked-by: Rik van Riel Signed-off-by: Peter Zijlstra (Intel) Link: http://lkml.kernel.org/r/20170802000818.4760-4-namit@vmware.com --- mm/huge_memory.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1410,7 +1410,6 @@ int do_huge_pmd_numa_page(struct vm_faul unsigned long haddr = vmf->address & HPAGE_PMD_MASK; int page_nid = -1, this_nid = numa_node_id(); int target_nid, last_cpupid = -1; - bool need_flush = false; bool page_locked; bool migrated = false; bool was_writable; @@ -1503,9 +1502,12 @@ int do_huge_pmd_numa_page(struct vm_faul * * Must be done under PTL such that we'll observe the relevant * set_tlb_flush_pending(). + * + * We are not sure a pending tlb flush here is for a huge page + * mapping or not. Hence use the tlb range variant */ if (mm_tlb_flush_pending(vma->vm_mm)) - need_flush = true; + flush_tlb_range(vma, haddr, haddr + HPAGE_PMD_SIZE); /* * Migrate the THP to the requested node, returns with page unlocked @@ -1513,13 +1515,6 @@ int do_huge_pmd_numa_page(struct vm_faul */ spin_unlock(vmf->ptl); - /* - * We are not sure a pending tlb flush here is for a huge page - * mapping or not. Hence use the tlb range variant - */ - if (need_flush) - flush_tlb_range(vma, haddr, haddr + HPAGE_PMD_SIZE); - migrated = migrate_misplaced_transhuge_page(vma->vm_mm, vma, vmf->pmd, pmd, vmf->address, page, target_nid); if (migrated) {