mm/gup: Cache dev_pagemap while pinning pages
Subsystems (5)
PATCH v4 1/1 mm/gup: Cache dev_pagemap while pinning pages
Pinning 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 use pages. The gup_benchmark kernel self test reports this reduces time to get user pages to as low as 1/3 the previous time.
---
v3 -> v4:
Split the kernel patch out from the self tests patch series.
Moved function definitions out of header so the new struct 'follow_page_context' can be a private definition.
Maintain reference to dev_pagemap in follow_page_pte, the same optimization this patch adds to pud and pmd.
include/linux/huge_mm.h | 8 ++-- include/linux/mm.h | 12 +---- mm/gup.c | 113 +++++++++++++++++++++++++++++------------------- mm/huge_memory.c | 16 +++---- mm/nommu.c | 6 +-- 5 files changed, 82 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 +68 -45
270 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
kbuild test robot
build botI love your patch! Yet something to improve:
Hi Keith,
I love your patch! Yet something to improve:
[auto build test ERROR on linus/master]
[also build test ERROR on v4.19-rc7 next-20181011]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Keith-Busch/mm-gup-Cache-dev_pagemap-while-pinning-pages/20181011-205544
config: microblaze-nommu_defconfig (attached as .config)
compiler: microblaze-linux-gcc (GCC) 8.1.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=8.1.0 make.cross ARCH=microblaze
All errors (new ones prefixed by >>):
>> mm/nommu.c:1714:1: error: expected identifier or '(' before '{' token
{
^vim +1714 mm/nommu.c
^1da177e Linus Torvalds 2005-04-16 1711
9d889fcc Keith Busch 2018-10-10 1712 struct page *follow_page(struct vm_area_struct *vma, unsigned long address,
9d889fcc Keith Busch 2018-10-10 1713 unsigned int foll_flags);
^1da177e Linus Torvalds 2005-04-16 @1714 {
^1da177e Linus Torvalds 2005-04-16 1715 return NULL;
^1da177e Linus Torvalds 2005-04-16 1716 }^1da177e Linus Torvalds 2005-04-16 1717
:::::: The code at line 1714 was first introduced by commit :::::: 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 Linux-2.6.12-rc2
:::::: TO: Linus Torvalds <[email protected]> :::::: CC: Linus Torvalds <[email protected]>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation