Skip to content

Commit ca7eaeb

Browse files
fyin1akpm00
authored andcommitted
filemap: batch PTE mappings
Call set_pte_range() once per contiguous range of the folio instead of once per page. This batches the updates to mm counters and the rmap. With a will-it-scale.page_fault3 like app (change file write fault testing to read fault testing. Trying to upstream it to will-it-scale at [1]) got 15% performance gain on a 48C/96T Cascade Lake test box with 96 processes running against xfs. Perf data collected before/after the change: 18.73%--page_add_file_rmap | --11.60%--__mod_lruvec_page_state | |--7.40%--__mod_memcg_lruvec_state | | | --5.58%--cgroup_rstat_updated | --2.53%--__mod_lruvec_state | --1.48%--__mod_node_page_state 9.93%--page_add_file_rmap_range | --2.67%--__mod_lruvec_page_state | |--1.95%--__mod_memcg_lruvec_state | | | --1.57%--cgroup_rstat_updated | --0.61%--__mod_lruvec_state | --0.54%--__mod_node_page_state The running time of __mode_lruvec_page_state() is reduced about 9%. [1]: antonblanchard/will-it-scale#37 Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Yin Fengwei <[email protected]> Signed-off-by: Matthew Wilcox (Oracle) <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 1c9a1e9 commit ca7eaeb

File tree

1 file changed

+29
-14
lines changed

1 file changed

+29
-14
lines changed

mm/filemap.c

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3480,11 +3480,12 @@ static vm_fault_t filemap_map_folio_range(struct vm_fault *vmf,
34803480
struct file *file = vma->vm_file;
34813481
struct page *page = folio_page(folio, start);
34823482
unsigned int mmap_miss = READ_ONCE(file->f_ra.mmap_miss);
3483-
unsigned int ref_count = 0, count = 0;
3483+
unsigned int count = 0;
3484+
pte_t *old_ptep = vmf->pte;
34843485

34853486
do {
3486-
if (PageHWPoison(page))
3487-
continue;
3487+
if (PageHWPoison(page + count))
3488+
goto skip;
34883489

34893490
if (mmap_miss > 0)
34903491
mmap_miss--;
@@ -3494,20 +3495,34 @@ static vm_fault_t filemap_map_folio_range(struct vm_fault *vmf,
34943495
* handled in the specific fault path, and it'll prohibit the
34953496
* fault-around logic.
34963497
*/
3497-
if (!pte_none(*vmf->pte))
3498-
continue;
3499-
3500-
if (vmf->address == addr)
3501-
ret = VM_FAULT_NOPAGE;
3498+
if (!pte_none(vmf->pte[count]))
3499+
goto skip;
35023500

3503-
ref_count++;
3504-
set_pte_range(vmf, folio, page, 1, addr);
3505-
} while (vmf->pte++, page++, addr += PAGE_SIZE, ++count < nr_pages);
3501+
count++;
3502+
continue;
3503+
skip:
3504+
if (count) {
3505+
set_pte_range(vmf, folio, page, count, addr);
3506+
folio_ref_add(folio, count);
3507+
if (in_range(vmf->address, addr, count))
3508+
ret = VM_FAULT_NOPAGE;
3509+
}
35063510

3507-
/* Restore the vmf->pte */
3508-
vmf->pte -= nr_pages;
3511+
count++;
3512+
page += count;
3513+
vmf->pte += count;
3514+
addr += count * PAGE_SIZE;
3515+
count = 0;
3516+
} while (--nr_pages > 0);
3517+
3518+
if (count) {
3519+
set_pte_range(vmf, folio, page, count, addr);
3520+
folio_ref_add(folio, count);
3521+
if (in_range(vmf->address, addr, count))
3522+
ret = VM_FAULT_NOPAGE;
3523+
}
35093524

3510-
folio_ref_add(folio, ref_count);
3525+
vmf->pte = old_ptep;
35113526
WRITE_ONCE(file->f_ra.mmap_miss, mmap_miss);
35123527

35133528
return ret;

0 commit comments

Comments
 (0)