Skip to content

Commit c474548

Browse files
torvaldsakpm00
authored andcommitted
mm: mmu_gather: allow more than one batch of delayed rmaps
Commit 5df397d ("mm: delay page_remove_rmap() until after the TLB has been flushed") limited the page batching for the mmu gather operation when a dirty shared page needed to delay rmap removal until after the TLB had been flushed. It did so because it needs to walk that array of pages while still holding the page table lock, and our mmu_gather infrastructure allows for batching quite a lot of pages. We may have thousands on pages queued up for freeing, and we wanted to walk only the last batch if we then added a dirty page to the queue. However, when I limited it to one batch, I didn't think of the degenerate case of the special first batch that is embedded on-stack in the mmu_gather structure (called "local") and that only has eight entries. So with the right pattern, that "limit delayed rmap to just one batch" will trigger over and over in that first small batch, and we'll waste a lot of time flushing TLB's every eight pages. And those right patterns are trivially triggered by just having a shared mappings with lots of adjacent dirty pages. Like the 'page_fault3' subtest of the 'will-it-scale' benchmark, that just maps a shared area, dirties all pages, and unmaps it. Rinse and repeat. We still want to limit the batching, but to fix this (easily triggered) degenerate case, just expand the "only one batch" logic to instead be "only one batch that isn't the special first on-stack ('local') batch". That way, when we need to flush the delayed rmaps, we can still limit our walk to just the last batch - and that first small one. Link: https://lkml.kernel.org/r/CAHk-=whkL5aM1fR7kYUmhHQHBcMUc-bDoFP7EwYjTxy64DGtvw@mail.gmail.com Fixes: 5df397d ("mm: delay page_remove_rmap() until after the TLB has been flushed") Signed-off-by: Linus Torvalds <[email protected]> Reported-by: kernel test robot <[email protected]> Link: https://lore.kernel.org/oe-lkp/[email protected] Tested-by: Huang, Ying <[email protected]> Tested-by: Hugh Dickins <[email protected]> Cc: Feng Tang <[email protected]> Cc: Johannes Weiner <[email protected]> Cc: Nadav Amit <[email protected]> Cc: Xing Zhengjun <[email protected]> Cc: "Yin, Fengwei" <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent c7cdf94 commit c474548

File tree

1 file changed

+20
-16
lines changed

1 file changed

+20
-16
lines changed

mm/mmu_gather.c

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ static bool tlb_next_batch(struct mmu_gather *tlb)
1919
{
2020
struct mmu_gather_batch *batch;
2121

22-
/* No more batching if we have delayed rmaps pending */
23-
if (tlb->delayed_rmap)
22+
/* Limit batching if we have delayed rmaps pending */
23+
if (tlb->delayed_rmap && tlb->active != &tlb->local)
2424
return false;
2525

2626
batch = tlb->active;
@@ -48,31 +48,35 @@ static bool tlb_next_batch(struct mmu_gather *tlb)
4848
}
4949

5050
#ifdef CONFIG_SMP
51+
static void tlb_flush_rmap_batch(struct mmu_gather_batch *batch, struct vm_area_struct *vma)
52+
{
53+
for (int i = 0; i < batch->nr; i++) {
54+
struct encoded_page *enc = batch->encoded_pages[i];
55+
56+
if (encoded_page_flags(enc)) {
57+
struct page *page = encoded_page_ptr(enc);
58+
page_remove_rmap(page, vma, false);
59+
}
60+
}
61+
}
62+
5163
/**
5264
* tlb_flush_rmaps - do pending rmap removals after we have flushed the TLB
5365
* @tlb: the current mmu_gather
5466
*
5567
* Note that because of how tlb_next_batch() above works, we will
56-
* never start new batches with pending delayed rmaps, so we only
57-
* need to walk through the current active batch.
68+
* never start multiple new batches with pending delayed rmaps, so
69+
* we only need to walk through the current active batch and the
70+
* original local one.
5871
*/
5972
void tlb_flush_rmaps(struct mmu_gather *tlb, struct vm_area_struct *vma)
6073
{
61-
struct mmu_gather_batch *batch;
62-
6374
if (!tlb->delayed_rmap)
6475
return;
6576

66-
batch = tlb->active;
67-
for (int i = 0; i < batch->nr; i++) {
68-
struct encoded_page *enc = batch->encoded_pages[i];
69-
70-
if (encoded_page_flags(enc)) {
71-
struct page *page = encoded_page_ptr(enc);
72-
page_remove_rmap(page, vma, false);
73-
}
74-
}
75-
77+
tlb_flush_rmap_batch(&tlb->local, vma);
78+
if (tlb->active != &tlb->local)
79+
tlb_flush_rmap_batch(tlb->active, vma);
7680
tlb->delayed_rmap = 0;
7781
}
7882
#endif

0 commit comments

Comments
 (0)