Skip to content

Commit c03c696

Browse files
fyin1intel-lab-lkp
authored andcommitted
filemap: Add filemap_map_folio_range()
filemap_map_folio_range() maps partial/full folio. Comparing to original filemap_map_pages(), it updates refcount once per folio instead of per page and gets minor performance improvement for large folio. 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 2% performance gain on a 48C/96T Cascade Lake test box with 96 processes running against xfs. [1]: antonblanchard/will-it-scale#37 Signed-off-by: Yin Fengwei <[email protected]> Signed-off-by: Matthew Wilcox (Oracle) <[email protected]>
1 parent 49a8133 commit c03c696

File tree

1 file changed

+54
-44
lines changed

1 file changed

+54
-44
lines changed

mm/filemap.c

Lines changed: 54 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2200,16 +2200,6 @@ unsigned filemap_get_folios(struct address_space *mapping, pgoff_t *start,
22002200
}
22012201
EXPORT_SYMBOL(filemap_get_folios);
22022202

2203-
static inline
2204-
bool folio_more_pages(struct folio *folio, pgoff_t index, pgoff_t max)
2205-
{
2206-
if (!folio_test_large(folio) || folio_test_hugetlb(folio))
2207-
return false;
2208-
if (index >= max)
2209-
return false;
2210-
return index < folio->index + folio_nr_pages(folio) - 1;
2211-
}
2212-
22132203
/**
22142204
* filemap_get_folios_contig - Get a batch of contiguous folios
22152205
* @mapping: The address_space to search
@@ -3351,6 +3341,53 @@ static inline struct folio *next_map_page(struct address_space *mapping,
33513341
mapping, xas, end_pgoff);
33523342
}
33533343

3344+
/*
3345+
* Map page range [start_page, start_page + nr_pages) of folio.
3346+
* start_page is gotten from start by folio_page(folio, start)
3347+
*/
3348+
static vm_fault_t filemap_map_folio_range(struct vm_fault *vmf,
3349+
struct folio *folio, unsigned long start,
3350+
unsigned long addr, unsigned int nr_pages)
3351+
{
3352+
vm_fault_t ret = 0;
3353+
struct vm_area_struct *vma = vmf->vma;
3354+
struct file *file = vma->vm_file;
3355+
struct page *page = folio_page(folio, start);
3356+
unsigned int mmap_miss = READ_ONCE(file->f_ra.mmap_miss);
3357+
unsigned int ref_count = 0, count = 0;
3358+
3359+
do {
3360+
if (PageHWPoison(page))
3361+
continue;
3362+
3363+
if (mmap_miss > 0)
3364+
mmap_miss--;
3365+
3366+
/*
3367+
* NOTE: If there're PTE markers, we'll leave them to be
3368+
* handled in the specific fault path, and it'll prohibit the
3369+
* fault-around logic.
3370+
*/
3371+
if (!pte_none(*vmf->pte))
3372+
continue;
3373+
3374+
if (vmf->address == addr)
3375+
ret = VM_FAULT_NOPAGE;
3376+
3377+
ref_count++;
3378+
do_set_pte(vmf, page, addr);
3379+
update_mmu_cache(vma, addr, vmf->pte);
3380+
} while (vmf->pte++, page++, addr += PAGE_SIZE, ++count < nr_pages);
3381+
3382+
/* Restore the vmf->pte */
3383+
vmf->pte -= nr_pages;
3384+
3385+
folio_ref_add(folio, ref_count);
3386+
WRITE_ONCE(file->f_ra.mmap_miss, mmap_miss);
3387+
3388+
return ret;
3389+
}
3390+
33543391
vm_fault_t filemap_map_pages(struct vm_fault *vmf,
33553392
pgoff_t start_pgoff, pgoff_t end_pgoff)
33563393
{
@@ -3361,9 +3398,9 @@ vm_fault_t filemap_map_pages(struct vm_fault *vmf,
33613398
unsigned long addr;
33623399
XA_STATE(xas, &mapping->i_pages, start_pgoff);
33633400
struct folio *folio;
3364-
struct page *page;
33653401
unsigned int mmap_miss = READ_ONCE(file->f_ra.mmap_miss);
33663402
vm_fault_t ret = 0;
3403+
int nr_pages = 0;
33673404

33683405
rcu_read_lock();
33693406
folio = first_map_page(mapping, &xas, end_pgoff);
@@ -3378,45 +3415,18 @@ vm_fault_t filemap_map_pages(struct vm_fault *vmf,
33783415
addr = vma->vm_start + ((start_pgoff - vma->vm_pgoff) << PAGE_SHIFT);
33793416
vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd, addr, &vmf->ptl);
33803417
do {
3381-
again:
3382-
page = folio_file_page(folio, xas.xa_index);
3383-
if (PageHWPoison(page))
3384-
goto unlock;
3385-
3386-
if (mmap_miss > 0)
3387-
mmap_miss--;
3418+
unsigned long end;
33883419

33893420
addr += (xas.xa_index - last_pgoff) << PAGE_SHIFT;
33903421
vmf->pte += xas.xa_index - last_pgoff;
33913422
last_pgoff = xas.xa_index;
3423+
end = folio->index + folio_nr_pages(folio) - 1;
3424+
nr_pages = min(end, end_pgoff) - xas.xa_index + 1;
33923425

3393-
/*
3394-
* NOTE: If there're PTE markers, we'll leave them to be
3395-
* handled in the specific fault path, and it'll prohibit the
3396-
* fault-around logic.
3397-
*/
3398-
if (!pte_none(*vmf->pte))
3399-
goto unlock;
3400-
3401-
/* We're about to handle the fault */
3402-
if (vmf->address == addr)
3403-
ret = VM_FAULT_NOPAGE;
3426+
ret |= filemap_map_folio_range(vmf, folio,
3427+
xas.xa_index - folio->index, addr, nr_pages);
3428+
xas.xa_index += nr_pages;
34043429

3405-
do_set_pte(vmf, page, addr);
3406-
/* no need to invalidate: a not-present page won't be cached */
3407-
update_mmu_cache(vma, addr, vmf->pte);
3408-
if (folio_more_pages(folio, xas.xa_index, end_pgoff)) {
3409-
xas.xa_index++;
3410-
folio_ref_inc(folio);
3411-
goto again;
3412-
}
3413-
folio_unlock(folio);
3414-
continue;
3415-
unlock:
3416-
if (folio_more_pages(folio, xas.xa_index, end_pgoff)) {
3417-
xas.xa_index++;
3418-
goto again;
3419-
}
34203430
folio_unlock(folio);
34213431
folio_put(folio);
34223432
} while ((folio = next_map_page(mapping, &xas, end_pgoff)) != NULL);

0 commit comments

Comments
 (0)