mm-gup-remove-vmas-parameter-from-get_user_pages_remote.patch removed from -mm tree
The quilt patch titled
Subject: mm/gup: remove vmas parameter from get_user_pages_remote()
has been removed from the -mm tree. Its filename was
mm-gup-remove-vmas-parameter-from-get_user_pages_remote.patch
This patch was dropped because it was merged into the mm-stable branch of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
------------------------------------------------------
From: Lorenzo Stoakes <[email protected]>
Subject: mm/gup: remove vmas parameter from get_user_pages_remote()
Date: Wed, 17 May 2023 20:25:39 +0100
The only instances of get_user_pages_remote() invocations which used the vmas parameter were for a single page which can instead simply look up the VMA directly. In particular:-
- __update_ref_ctr() looked up the VMA but did nothing with it so we simply remove it.
- __access_remote_vm() was already using vma_lookup() when the original lookup failed so by doing the lookup directly this also de-duplicates the code.
We are able to perform these VMA operations as we already hold the mmap_lock in order to be able to call get_user_pages_remote().
As part of this work we add get_user_page_vma_remote() which abstracts the VMA lookup, error handling and decrementing the page reference count should the VMA lookup fail.
This forms part of a broader set of patches intended to eliminate the vmas parameter altogether.
---
arch/arm64/kernel/mte.c | 17 +++++++++-------- arch/s390/kvm/interrupt.c | 2 +- fs/exec.c | 2 +- include/linux/mm.h | 34 +++++++++++++++++++++++++++++++--- kernel/events/uprobes.c | 13 +++++-------- mm/gup.c | 12 ++++-------- mm/memory.c | 20 ++++++++++---------- mm/rmap.c | 2 +- security/tomoyo/domain.c | 2 +- virt/kvm/async_pf.c | 3 +-- 10 files changed, 64 insertions(+), 43 deletions(-)
arch/arm64/kernel/mte.c renamed from arch/arm64/kernel/mte.c~mm-gup-remove-vmas-parameter-from-get_user_pages_remote +9 -8
@@ -416,10 +416,9 @@ long get_mte_ctrl(struct task_struct *tastatic int __access_remote_tags (struct mm_struct *mm,unsigned long addr,struct iovec *kiov,unsigned int gup_flags) { -struct vm_area_struct *vma;void __user *buf = kiov->iov_base;size_t len = kiov->iov_len; -int ret; +int err =0 ;int write = gup_flags &FOLL_WRITE ;if (!access_ok (buf, len))
@@ -429,14 +428,16 @@ static int __access_remote_tags(struct mreturn -EIO ;while (len) { +struct vm_area_struct *vma;unsigned long tags, offset;void *maddr; -struct page *page =NULL ; +struct page *page =get_user_page_vma_remote (mm, addr, + gup_flags, &vma); - ret =get_user_pages_remote (mm, addr,1 , gup_flags, &page, - &vma,NULL ); -if (ret <=0 ) +if (IS_ERR_OR_NULL (page)) { + err = page ==NULL ? -EIO :PTR_ERR (page);break ; + }/* * Only copy tags if the page has been mapped as PROT_MTE
@@ -446,7 +447,7 @@ static int __access_remote_tags(struct m* was never mapped with PROT_MTE. */ if (!(vma->vm_flags &VM_MTE )) { - ret = -EOPNOTSUPP ; + err = -EOPNOTSUPP ;put_page (page);break ; }
@@ -479,7 +480,7 @@ static int __access_remote_tags(struct m kiov->iov_len = buf - kiov->iov_base;if (!kiov->iov_len) {/* check for error accessing the tracee's address space */ -if (ret <=0 ) +if (err)return -EIO ;else return -EFAULT ;
arch/s390/kvm/interrupt.c renamed from arch/s390/kvm/interrupt.c~mm-gup-remove-vmas-parameter-from-get_user_pages_remote +1 -1
@@ -2777,7 +2777,7 @@ static struct page *get_map_page(structmmap_read_lock (kvm->mm);get_user_pages_remote (kvm->mm, uaddr,1 ,FOLL_WRITE , - &page,NULL ,NULL ); + &page,NULL );mmap_read_unlock (kvm->mm);return page; }
fs/exec.c renamed from fs/exec.c~mm-gup-remove-vmas-parameter-from-get_user_pages_remote +1 -1
@@ -220,7 +220,7 @@ static struct page *get_arg_page(struct*/ mmap_read_lock (bprm->mm); ret =get_user_pages_remote (bprm->mm, pos,1 , gup_flags, - &page,NULL ,NULL ); + &page,NULL );mmap_read_unlock (bprm->mm);if (ret <=0 )return NULL ;
include/linux/mm.h renamed from include/linux/mm.h~mm-gup-remove-vmas-parameter-from-get_user_pages_remote +31 -3
@@ -2353,6 +2353,9 @@ static inline void unmap_shared_mapping_unmap_mapping_range (mapping, holebegin, holelen,0 ); } +static inline struct vm_area_struct *vma_lookup (struct mm_struct *mm, +unsigned long addr); +extern int access_process_vm (struct task_struct *tsk,unsigned long addr,void *buf,int len,unsigned int gup_flags); extern int access_remote_vm(struct mm_struct *mm, unsigned long addr,
@@ -2361,13 +2364,38 @@ extern int __access_remote_vm(struct mm_ void *buf, int len, unsigned int gup_flags);long get_user_pages_remote (struct mm_struct *mm, -unsigned long start,unsigned long nr_pages, -unsigned int gup_flags,struct page **pages, -struct vm_area_struct **vmas,int *locked); +unsigned long start,unsigned long nr_pages, +unsigned int gup_flags,struct page **pages, +int *locked);long pin_user_pages_remote (struct mm_struct *mm,unsigned long start,unsigned long nr_pages,unsigned int gup_flags,struct page **pages,int *locked); + +static inline struct page *get_user_page_vma_remote (struct mm_struct *mm, +unsigned long addr, +int gup_flags, +struct vm_area_struct **vmap) +{ +struct page *page; +struct vm_area_struct *vma; +int got =get_user_pages_remote (mm, addr,1 , gup_flags, &page,NULL ); + +if (got <0 ) +return ERR_PTR (got); +if (got ==0 ) +return NULL ; + + vma =vma_lookup (mm, addr); +if (WARN_ON_ONCE (!vma)) { +put_page (page); +return ERR_PTR (-EINVAL ); + } + + *vmap = vma; +return page; +} +long get_user_pages (unsigned long start,unsigned long nr_pages,unsigned int gup_flags,struct page **pages); long pin_user_pages(unsigned long start, unsigned long nr_pages,
kernel/events/uprobes.c renamed from kernel/events/uprobes.c~mm-gup-remove-vmas-parameter-from-get_user_pages_remote +5 -8
@@ -365,7 +365,6 @@ __update_ref_ctr(struct mm_struct *mm, u {void *kaddr;struct page *page; -struct vm_area_struct *vma;int ret;short *ptr;
@@ -373,7 +372,7 @@ __update_ref_ctr(struct mm_struct *mm, ureturn -EINVAL ; ret =get_user_pages_remote (mm, vaddr,1 , -FOLL_WRITE , &page, &vma,NULL ); +FOLL_WRITE , &page,NULL );if (unlikely (ret <=0 )) {/* * We are asking for 1 page. If get_user_pages_remote() fails,
@@ -474,10 +473,9 @@ retry:if (is_register) gup_flags |=FOLL_SPLIT_PMD ;/* Read the page with vaddr into memory */ - ret =get_user_pages_remote (mm, vaddr,1 , gup_flags, - &old_page, &vma,NULL ); -if (ret <=0 ) -return ret; + old_page =get_user_page_vma_remote (mm, vaddr, gup_flags, &vma); +if (IS_ERR_OR_NULL (old_page)) +return old_page ?PTR_ERR (old_page) :0 ; ret =verify_opcode (old_page, vaddr, &opcode);if (ret <=0 )
@@ -2027,8 +2025,7 @@ static int is_trap_at_addr(struct mm_str* but we treat this as a 'remote' access since it is * essentially a kernel access to the memory. */ - result =get_user_pages_remote (mm, vaddr,1 ,FOLL_FORCE , &page, -NULL ,NULL ); + result =get_user_pages_remote (mm, vaddr,1 ,FOLL_FORCE , &page,NULL );if (result <0 )return result;
mm/gup.c renamed from mm/gup.c~mm-gup-remove-vmas-parameter-from-get_user_pages_remote +4 -8
@@ -2165,8 +2165,6 @@ static bool is_valid_gup_args(struct pag* @pages: array that receives pointers to the pages pinned. * Should be at least nr_pages long. Or NULL, if caller * only intends to ensure the pages are faulted in. -* @vmas: array of pointers to vmas corresponding to each page. -* Or NULL if the caller does not require them. * @locked: pointer to lock flag indicating whether lock is held and * subsequently whether VM_FAULT_RETRY functionality can be * utilised. Lock must initially be held.
@@ -2181,8 +2179,6 @@ static bool is_valid_gup_args(struct pag* * The caller is responsible for releasing returned @pages, via put_page(). * -* @vmas are valid only as long as mmap_lock is held. -* * Must be called with mmap_lock held for read or write. * * get_user_pages_remote walks a process's page tables and takes a reference
@@ -2219,15 +2215,15 @@ static bool is_valid_gup_args(struct paglong get_user_pages_remote (struct mm_struct *mm,unsigned long start,unsigned long nr_pages,unsigned int gup_flags,struct page **pages, -struct vm_area_struct **vmas,int *locked) +int *locked) {int local_locked =1 ; -if (!is_valid_gup_args (pages, vmas, locked, &gup_flags, +if (!is_valid_gup_args (pages,NULL , locked, &gup_flags,FOLL_TOUCH |FOLL_REMOTE ))return -EINVAL ; -return __get_user_pages_locked (mm, start, nr_pages, pages, vmas, +return __get_user_pages_locked (mm, start, nr_pages, pages,NULL , locked ? locked : &local_locked, gup_flags); }
@@ -2237,7 +2233,7 @@ EXPORT_SYMBOL(get_user_pages_remote);long get_user_pages_remote (struct mm_struct *mm,unsigned long start,unsigned long nr_pages,unsigned int gup_flags,struct page **pages, -struct vm_area_struct **vmas,int *locked) +int *locked) {return 0 ; }
mm/memory.c renamed from mm/memory.c~mm-gup-remove-vmas-parameter-from-get_user_pages_remote +10 -10
@@ -5587,7 +5587,6 @@ EXPORT_SYMBOL_GPL(generic_access_phys);int __access_remote_vm (struct mm_struct *mm,unsigned long addr,void *buf,int len,unsigned int gup_flags) { -struct vm_area_struct *vma;void *old_buf = buf;int write = gup_flags &FOLL_WRITE ;
@@ -5596,29 +5595,30 @@ int __access_remote_vm(struct mm_struct/* ignore errors, just check how much was successfully transferred */ while (len) { -int bytes, ret, offset; +int bytes, offset;void *maddr; -struct page *page =NULL ; +struct vm_area_struct *vma =NULL ; +struct page *page =get_user_page_vma_remote (mm, addr, + gup_flags, &vma); - ret =get_user_pages_remote (mm, addr,1 , - gup_flags, &page, &vma,NULL ); -if (ret <=0 ) { +if (IS_ERR_OR_NULL (page)) {#ifndef CONFIG_HAVE_IOREMAP_PROT break ;#else +int res =0 ; +/* * Check if this is a VM_IO | VM_PFNMAP VMA, which * we can access using slightly different code. */ - vma =vma_lookup (mm, addr);if (!vma)break ;if (vma->vm_ops && vma->vm_ops->access) - ret = vma->vm_ops->access (vma, addr, buf, + res = vma->vm_ops->access (vma, addr, buf, len, write); -if (ret <=0 ) +if (res <=0 )break ; - bytes = ret; + bytes = res;#endif }else { bytes = len;
mm/rmap.c renamed from mm/rmap.c~mm-gup-remove-vmas-parameter-from-get_user_pages_remote +1 -1
@@ -2328,7 +2328,7 @@ int make_device_exclusive_range(struct m npages =get_user_pages_remote (mm, start, npages,FOLL_GET |FOLL_WRITE |FOLL_SPLIT_PMD , - pages,NULL ,NULL ); + pages,NULL );if (npages <0 )return npages;
security/tomoyo/domain.c renamed from security/tomoyo/domain.c~mm-gup-remove-vmas-parameter-from-get_user_pages_remote +1 -1
@@ -916,7 +916,7 @@ bool tomoyo_dump_page(struct linux_binpr*/ mmap_read_lock (bprm->mm); ret =get_user_pages_remote (bprm->mm, pos,1 , -FOLL_FORCE , &page,NULL ,NULL ); +FOLL_FORCE , &page,NULL );mmap_read_unlock (bprm->mm);if (ret <=0 )return false;
virt/kvm/async_pf.c renamed from virt/kvm/async_pf.c~mm-gup-remove-vmas-parameter-from-get_user_pages_remote +1 -2
@@ -61,8 +61,7 @@ static void async_pf_execute(struct work* access remotely. */ mmap_read_lock (mm); -get_user_pages_remote (mm, addr,1 ,FOLL_WRITE ,NULL ,NULL , - &locked); +get_user_pages_remote (mm, addr,1 ,FOLL_WRITE ,NULL , &locked);if (locked)mmap_read_unlock (mm);
_
Patches currently in -mm which might be from [email protected] are
mm-vmalloc-do-not-output-a-spurious-warning-when-huge-vmalloc-fails.patch