mm/gup: Cache dev_pagemap while pinning pages
Subsystems (5)
PATCH v3 1/1 mm/gup: Cache dev_pagemap while pinning pages
Getting pages from ZONE_DEVICE memory needs to check the backing device's live-ness, which is tracked in the device's dev_pagemap metadata. This metadata is stored in a radix tree and looking it up adds measurable software overhead.
This patch avoids repeating this relatively costly operation when dev_pagemap is used by caching the last dev_pagemap while getting user pages. The gup_benchmark kernel self test reports this reduces time to get user pages to as low as 1/3 of the previous time.
Cc Dave Hansen <[email protected]>
Reviewed-by Dan Williams <[email protected]>
Signed-off-by Keith Busch <[email protected]>
---
Changes from previous version:
Explicitly set struct members rather than rely on gnu behavior
Added Reviews and Acks to change log
include/linux/huge_mm.h | 8 ++-- include/linux/mm.h | 12 +----- mm/gup.c | 110 ++++++++++++++++++++++++++++-------------------- mm/huge_memory.c | 16 +++---- mm/nommu.c | 6 +-- 5 files changed, 79 insertions(+), 73 deletions(-)
include/linux/huge_mm.h +4 -4
@@ -213,9 +213,9 @@ static inline int hpage_nr_pages(struct page *page) }struct page *follow_devmap_pmd (struct vm_area_struct *vma,unsigned long addr, -pmd_t *pmd,int flags); +pmd_t *pmd,int flags,struct dev_pagemap **pgmap);struct page *follow_devmap_pud (struct vm_area_struct *vma,unsigned long addr, -pud_t *pud,int flags); +pud_t *pud,int flags,struct dev_pagemap **pgmap);extern vm_fault_t do_huge_pmd_numa_page (struct vm_fault *vmf,pmd_t orig_pmd);
@@ -344,13 +344,13 @@ static inline void mm_put_huge_zero_page(struct mm_struct *mm) }static inline struct page *follow_devmap_pmd (struct vm_area_struct *vma, -unsigned long addr,pmd_t *pmd,int flags) +unsigned long addr,pmd_t *pmd,int flags,struct dev_pagemap **pgmap) {return NULL ; }static inline struct page *follow_devmap_pud (struct vm_area_struct *vma, -unsigned long addr,pud_t *pud,int flags) +unsigned long addr,pud_t *pud,int flags,struct dev_pagemap **pgmap) {return NULL ; }
include/linux/mm.h +2 -10
@@ -2540,16 +2540,8 @@ static inline vm_fault_t vmf_error(int err)return VM_FAULT_SIGBUS ; } -struct page *follow_page_mask (struct vm_area_struct *vma, -unsigned long address,unsigned int foll_flags, -unsigned int *page_mask); - -static inline struct page *follow_page (struct vm_area_struct *vma, -unsigned long address,unsigned int foll_flags) -{ -unsigned int unused_page_mask; -return follow_page_mask (vma, address, foll_flags, &unused_page_mask); -} +struct page *follow_page (struct vm_area_struct *vma,unsigned long address, +unsigned int foll_flags);#define FOLL_WRITE 0x01/* check pte is writable */ #define FOLL_TOUCH 0x02/* mark page accessed */
mm/gup.c +65 -45
267 lines not on this page · raw message
mm/huge_memory.c +6 -10
@@ -852,11 +852,10 @@ static void touch_pmd(struct vm_area_struct *vma, unsigned long addr, }struct page *follow_devmap_pmd (struct vm_area_struct *vma,unsigned long addr, -pmd_t *pmd,int flags) +pmd_t *pmd,int flags,struct dev_pagemap **pgmap) {unsigned long pfn =pmd_pfn (*pmd);struct mm_struct *mm = vma->vm_mm; -struct dev_pagemap *pgmap;struct page *page;assert_spin_locked (pmd_lockptr (mm, pmd));
@@ -886,12 +885,11 @@ struct page *follow_devmap_pmd(struct vm_area_struct *vma, unsigned long addr,return ERR_PTR (-EEXIST ); pfn += (addr & ~PMD_MASK ) >>PAGE_SHIFT ; - pgmap =get_dev_pagemap (pfn,NULL ); -if (!pgmap) + *pgmap =get_dev_pagemap (pfn, *pgmap); +if (!*pgmap)return ERR_PTR (-EFAULT ); page =pfn_to_page (pfn);get_page (page); -put_dev_pagemap (pgmap);return page; }
@@ -1000,11 +998,10 @@ static void touch_pud(struct vm_area_struct *vma, unsigned long addr, }struct page *follow_devmap_pud (struct vm_area_struct *vma,unsigned long addr, -pud_t *pud,int flags) +pud_t *pud,int flags,struct dev_pagemap **pgmap) {unsigned long pfn =pud_pfn (*pud);struct mm_struct *mm = vma->vm_mm; -struct dev_pagemap *pgmap;struct page *page;assert_spin_locked (pud_lockptr (mm, pud));
@@ -1028,12 +1025,11 @@ struct page *follow_devmap_pud(struct vm_area_struct *vma, unsigned long addr,return ERR_PTR (-EEXIST ); pfn += (addr & ~PUD_MASK ) >>PAGE_SHIFT ; - pgmap =get_dev_pagemap (pfn,NULL ); -if (!pgmap) + *pgmap =get_dev_pagemap (pfn, *pgmap); +if (!*pgmap)return ERR_PTR (-EFAULT ); page =pfn_to_page (pfn);get_page (page); -put_dev_pagemap (pgmap);return page; }
mm/nommu.c +2 -4
@@ -1709,11 +1709,9 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,return ret; } -struct page *follow_page_mask (struct vm_area_struct *vma, -unsigned long address,unsigned int flags, -unsigned int *page_mask) +struct page *follow_page (struct vm_area_struct *vma,unsigned long address, +unsigned int foll_flags) { - *page_mask =0 ;return NULL ; }
Signature · 1 line
2.14.4