Skip to content

Commit 2ba99c5

Browse files
thejhakpm00
authored andcommitted
mm/khugepaged: fix GUP-fast interaction by sending IPI
Since commit 70cbc3c ("mm: gup: fix the fast GUP race against THP collapse"), the lockless_pages_from_mm() fastpath rechecks the pmd_t to ensure that the page table was not removed by khugepaged in between. However, lockless_pages_from_mm() still requires that the page table is not concurrently freed. Fix it by sending IPIs (if the architecture uses semi-RCU-style page table freeing) before freeing/reusing page tables. Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Fixes: ba76149 ("thp: khugepaged") Signed-off-by: Jann Horn <[email protected]> Reviewed-by: Yang Shi <[email protected]> Acked-by: David Hildenbrand <[email protected]> Cc: John Hubbard <[email protected]> Cc: Peter Xu <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 8d3c106 commit 2ba99c5

File tree

3 files changed

+7
-3
lines changed

3 files changed

+7
-3
lines changed

include/asm-generic/tlb.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,12 +222,16 @@ extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
222222
#define tlb_needs_table_invalidate() (true)
223223
#endif
224224

225+
void tlb_remove_table_sync_one(void);
226+
225227
#else
226228

227229
#ifdef tlb_needs_table_invalidate
228230
#error tlb_needs_table_invalidate() requires MMU_GATHER_RCU_TABLE_FREE
229231
#endif
230232

233+
static inline void tlb_remove_table_sync_one(void) { }
234+
231235
#endif /* CONFIG_MMU_GATHER_RCU_TABLE_FREE */
232236

233237

mm/khugepaged.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,6 +1051,7 @@ static int collapse_huge_page(struct mm_struct *mm, unsigned long address,
10511051
_pmd = pmdp_collapse_flush(vma, address, pmd);
10521052
spin_unlock(pmd_ptl);
10531053
mmu_notifier_invalidate_range_end(&range);
1054+
tlb_remove_table_sync_one();
10541055

10551056
spin_lock(pte_ptl);
10561057
result = __collapse_huge_page_isolate(vma, address, pte, cc,
@@ -1410,6 +1411,7 @@ static void collapse_and_free_pmd(struct mm_struct *mm, struct vm_area_struct *v
14101411
lockdep_assert_held_write(&vma->anon_vma->root->rwsem);
14111412

14121413
pmd = pmdp_collapse_flush(vma, addr, pmdp);
1414+
tlb_remove_table_sync_one();
14131415
mm_dec_nr_ptes(mm);
14141416
page_table_check_pte_clear_range(mm, addr, pmd);
14151417
pte_free(mm, pmd_pgtable(pmd));

mm/mmu_gather.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ static void tlb_remove_table_smp_sync(void *arg)
153153
/* Simply deliver the interrupt */
154154
}
155155

156-
static void tlb_remove_table_sync_one(void)
156+
void tlb_remove_table_sync_one(void)
157157
{
158158
/*
159159
* This isn't an RCU grace period and hence the page-tables cannot be
@@ -177,8 +177,6 @@ static void tlb_remove_table_free(struct mmu_table_batch *batch)
177177

178178
#else /* !CONFIG_MMU_GATHER_RCU_TABLE_FREE */
179179

180-
static void tlb_remove_table_sync_one(void) { }
181-
182180
static void tlb_remove_table_free(struct mmu_table_batch *batch)
183181
{
184182
__tlb_remove_table_free(batch);

0 commit comments

Comments
 (0)