lkml.org 
[lkml]   [2023]   [Jul]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v5 36/38] mm: Convert do_set_pte() to set_pte_range()
    Date
    From: Yin Fengwei <fengwei.yin@intel.com>

    set_pte_range() allows to setup page table entries for a specific
    range. It takes advantage of batched rmap update for large folio.
    It now takes care of calling update_mmu_cache_range().

    Signed-off-by: Yin Fengwei <fengwei.yin@intel.com>
    Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
    ---
    Documentation/filesystems/locking.rst | 2 +-
    include/linux/mm.h | 3 ++-
    mm/filemap.c | 3 +--
    mm/memory.c | 37 +++++++++++++++++----------
    4 files changed, 28 insertions(+), 17 deletions(-)

    diff --git a/Documentation/filesystems/locking.rst b/Documentation/filesystems/locking.rst
    index ed148919e11a..211a03053992 100644
    --- a/Documentation/filesystems/locking.rst
    +++ b/Documentation/filesystems/locking.rst
    @@ -661,7 +661,7 @@ locked. The VM will unlock the page.
    Filesystem should find and map pages associated with offsets from "start_pgoff"
    till "end_pgoff". ->map_pages() is called with the RCU lock held and must
    not block. If it's not possible to reach a page without blocking,
    -filesystem should skip it. Filesystem should use do_set_pte() to setup
    +filesystem should skip it. Filesystem should use set_pte_range() to setup
    page table entry. Pointer to entry associated with the page is passed in
    "pte" field in vm_fault structure. Pointers to entries for other offsets
    should be calculated relative to "pte".
    diff --git a/include/linux/mm.h b/include/linux/mm.h
    index 9687b48dfb1b..525a7e16850a 100644
    --- a/include/linux/mm.h
    +++ b/include/linux/mm.h
    @@ -1314,7 +1314,8 @@ static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma)
    }

    vm_fault_t do_set_pmd(struct vm_fault *vmf, struct page *page);
    -void do_set_pte(struct vm_fault *vmf, struct page *page, unsigned long addr);
    +void set_pte_range(struct vm_fault *vmf, struct folio *folio,
    + struct page *page, unsigned int nr, unsigned long addr);

    vm_fault_t finish_fault(struct vm_fault *vmf);
    vm_fault_t finish_mkwrite_fault(struct vm_fault *vmf);
    diff --git a/mm/filemap.c b/mm/filemap.c
    index bdc1e0b811bf..c06e9d331416 100644
    --- a/mm/filemap.c
    +++ b/mm/filemap.c
    @@ -3501,8 +3501,7 @@ static vm_fault_t filemap_map_folio_range(struct vm_fault *vmf,
    ret = VM_FAULT_NOPAGE;

    ref_count++;
    - do_set_pte(vmf, page, addr);
    - update_mmu_cache(vma, addr, vmf->pte);
    + set_pte_range(vmf, folio, page, 1, addr);
    } while (vmf->pte++, page++, addr += PAGE_SIZE, ++count < nr_pages);

    /* Restore the vmf->pte */
    diff --git a/mm/memory.c b/mm/memory.c
    index ebb4138acdb2..e712e5fda56e 100644
    --- a/mm/memory.c
    +++ b/mm/memory.c
    @@ -4323,15 +4323,24 @@ vm_fault_t do_set_pmd(struct vm_fault *vmf, struct page *page)
    }
    #endif

    -void do_set_pte(struct vm_fault *vmf, struct page *page, unsigned long addr)
    +/**
    + * set_pte_range - Set a range of PTEs to point to pages in a folio.
    + * @vmf: Fault decription.
    + * @folio: The folio that contains @page.
    + * @page: The first page to create a PTE for.
    + * @nr: The number of PTEs to create.
    + * @addr: The first address to create a PTE for.
    + */
    +void set_pte_range(struct vm_fault *vmf, struct folio *folio,
    + struct page *page, unsigned int nr, unsigned long addr)
    {
    struct vm_area_struct *vma = vmf->vma;
    bool uffd_wp = vmf_orig_pte_uffd_wp(vmf);
    bool write = vmf->flags & FAULT_FLAG_WRITE;
    - bool prefault = vmf->address != addr;
    + bool prefault = in_range(vmf->address, addr, nr * PAGE_SIZE);
    pte_t entry;

    - flush_icache_page(vma, page);
    + flush_icache_pages(vma, page, nr);
    entry = mk_pte(page, vma->vm_page_prot);

    if (prefault && arch_wants_old_prefaulted_pte())
    @@ -4345,14 +4354,18 @@ void do_set_pte(struct vm_fault *vmf, struct page *page, unsigned long addr)
    entry = pte_mkuffd_wp(entry);
    /* copy-on-write page */
    if (write && !(vma->vm_flags & VM_SHARED)) {
    - inc_mm_counter(vma->vm_mm, MM_ANONPAGES);
    - page_add_new_anon_rmap(page, vma, addr);
    - lru_cache_add_inactive_or_unevictable(page, vma);
    + add_mm_counter(vma->vm_mm, MM_ANONPAGES, nr);
    + VM_BUG_ON_FOLIO(nr != 1, folio);
    + folio_add_new_anon_rmap(folio, vma, addr);
    + folio_add_lru_vma(folio, vma);
    } else {
    - inc_mm_counter(vma->vm_mm, mm_counter_file(page));
    - page_add_file_rmap(page, vma, false);
    + add_mm_counter(vma->vm_mm, mm_counter_file(page), nr);
    + folio_add_file_rmap_range(folio, page, nr, vma, false);
    }
    - set_pte_at(vma->vm_mm, addr, vmf->pte, entry);
    + set_ptes(vma->vm_mm, addr, vmf->pte, entry, nr);
    +
    + /* no need to invalidate: a not-present page won't be cached */
    + update_mmu_cache_range(vmf, vma, addr, vmf->pte, nr);
    }

    static bool vmf_pte_changed(struct vm_fault *vmf)
    @@ -4420,11 +4433,9 @@ vm_fault_t finish_fault(struct vm_fault *vmf)

    /* Re-check under ptl */
    if (likely(!vmf_pte_changed(vmf))) {
    - do_set_pte(vmf, page, vmf->address);
    -
    - /* no need to invalidate: a not-present page won't be cached */
    - update_mmu_cache(vma, vmf->address, vmf->pte);
    + struct folio *folio = page_folio(page);

    + set_pte_range(vmf, folio, page, 1, vmf->address);
    ret = 0;
    } else {
    update_mmu_tlb(vma, vmf->address, vmf->pte);
    --
    2.39.2
    \
     
     \ /
      Last update: 2023-07-10 22:47    [W:2.781 / U:0.028 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site