Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mm: add locked parameter to get_user_pages_remote()

Patch series "mm: unexport __get_user_pages_unlocked()".

This patch series continues the cleanup of get_user_pages*() functions
taking advantage of the fact we can now pass gup_flags as we please.

It firstly adds an additional 'locked' parameter to
get_user_pages_remote() to allow for its callers to utilise
VM_FAULT_RETRY functionality. This is necessary as the invocation of
__get_user_pages_unlocked() in process_vm_rw_single_vec() makes use of
this and no other existing higher level function would allow it to do
so.

Secondly existing callers of __get_user_pages_unlocked() are replaced
with the appropriate higher-level replacement -
get_user_pages_unlocked() if the current task and memory descriptor are
referenced, or get_user_pages_remote() if other task/memory descriptors
are referenced (having acquiring mmap_sem.)

This patch (of 2):

Add a int *locked parameter to get_user_pages_remote() to allow
VM_FAULT_RETRY faulting behaviour similar to get_user_pages_[un]locked().

Taking into account the previous adjustments to get_user_pages*()
functions allowing for the passing of gup_flags, we are now in a
position where __get_user_pages_unlocked() need only be exported for his
ability to allow VM_FAULT_RETRY behaviour, this adjustment allows us to
subsequently unexport __get_user_pages_unlocked() as well as allowing
for future flexibility in the use of get_user_pages_remote().

[sfr@canb.auug.org.au: merge fix for get_user_pages_remote API change]
Link: http://lkml.kernel.org/r/20161122210511.024ec341@canb.auug.org.au
Link: http://lkml.kernel.org/r/20161027095141.2569-2-lstoakes@gmail.com
Signed-off-by: Lorenzo Stoakes <lstoakes@gmail.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Hugh Dickins <hughd@google.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Mel Gorman <mgorman@techsingularity.net>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Radim Krcmar <rkrcmar@redhat.com>
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Lorenzo Stoakes and committed by
Linus Torvalds
5b56d49f 370b262c

+18 -14
+1 -1
drivers/gpu/drm/etnaviv/etnaviv_gem.c
··· 759 759 down_read(&mm->mmap_sem); 760 760 while (pinned < npages) { 761 761 ret = get_user_pages_remote(task, mm, ptr, npages - pinned, 762 - flags, pvec + pinned, NULL); 762 + flags, pvec + pinned, NULL, NULL); 763 763 if (ret < 0) 764 764 break; 765 765
+1 -1
drivers/gpu/drm/i915/i915_gem_userptr.c
··· 515 515 obj->userptr.ptr + pinned * PAGE_SIZE, 516 516 npages - pinned, 517 517 flags, 518 - pvec + pinned, NULL); 518 + pvec + pinned, NULL, NULL); 519 519 if (ret < 0) 520 520 break; 521 521
+1 -1
drivers/infiniband/core/umem_odp.c
··· 578 578 */ 579 579 npages = get_user_pages_remote(owning_process, owning_mm, 580 580 user_virt, gup_num_pages, 581 - flags, local_page_list, NULL); 581 + flags, local_page_list, NULL, NULL); 582 582 up_read(&owning_mm->mmap_sem); 583 583 584 584 if (npages < 0)
+1 -1
drivers/vfio/vfio_iommu_type1.c
··· 362 362 363 363 down_read(&mm->mmap_sem); 364 364 ret = get_user_pages_remote(NULL, mm, vaddr, 1, flags, page, 365 - NULL); 365 + NULL, NULL); 366 366 up_read(&mm->mmap_sem); 367 367 } 368 368
+1 -1
fs/exec.c
··· 209 209 * doing the exec and bprm->mm is the new process's mm. 210 210 */ 211 211 ret = get_user_pages_remote(current, bprm->mm, pos, 1, gup_flags, 212 - &page, NULL); 212 + &page, NULL, NULL); 213 213 if (ret <= 0) 214 214 return NULL; 215 215
+1 -1
include/linux/mm.h
··· 1274 1274 long get_user_pages_remote(struct task_struct *tsk, struct mm_struct *mm, 1275 1275 unsigned long start, unsigned long nr_pages, 1276 1276 unsigned int gup_flags, struct page **pages, 1277 - struct vm_area_struct **vmas); 1277 + struct vm_area_struct **vmas, int *locked); 1278 1278 long get_user_pages(unsigned long start, unsigned long nr_pages, 1279 1279 unsigned int gup_flags, struct page **pages, 1280 1280 struct vm_area_struct **vmas);
+2 -2
kernel/events/uprobes.c
··· 301 301 retry: 302 302 /* Read the page with vaddr into memory */ 303 303 ret = get_user_pages_remote(NULL, mm, vaddr, 1, FOLL_FORCE, &old_page, 304 - &vma); 304 + &vma, NULL); 305 305 if (ret <= 0) 306 306 return ret; 307 307 ··· 1712 1712 * essentially a kernel access to the memory. 1713 1713 */ 1714 1714 result = get_user_pages_remote(NULL, mm, vaddr, 1, FOLL_FORCE, &page, 1715 - NULL); 1715 + NULL, NULL); 1716 1716 if (result < 0) 1717 1717 return result; 1718 1718
+8 -4
mm/gup.c
··· 917 917 * only intends to ensure the pages are faulted in. 918 918 * @vmas: array of pointers to vmas corresponding to each page. 919 919 * Or NULL if the caller does not require them. 920 + * @locked: pointer to lock flag indicating whether lock is held and 921 + * subsequently whether VM_FAULT_RETRY functionality can be 922 + * utilised. Lock must initially be held. 920 923 * 921 924 * Returns number of pages pinned. This may be fewer than the number 922 925 * requested. If nr_pages is 0 or negative, returns 0. If no pages ··· 963 960 long get_user_pages_remote(struct task_struct *tsk, struct mm_struct *mm, 964 961 unsigned long start, unsigned long nr_pages, 965 962 unsigned int gup_flags, struct page **pages, 966 - struct vm_area_struct **vmas) 963 + struct vm_area_struct **vmas, int *locked) 967 964 { 968 965 return __get_user_pages_locked(tsk, mm, start, nr_pages, pages, vmas, 969 - NULL, false, 966 + locked, true, 970 967 gup_flags | FOLL_TOUCH | FOLL_REMOTE); 971 968 } 972 969 EXPORT_SYMBOL(get_user_pages_remote); ··· 974 971 /* 975 972 * This is the same as get_user_pages_remote(), just with a 976 973 * less-flexible calling convention where we assume that the task 977 - * and mm being operated on are the current task's. We also 978 - * obviously don't pass FOLL_REMOTE in here. 974 + * and mm being operated on are the current task's and don't allow 975 + * passing of a locked parameter. We also obviously don't pass 976 + * FOLL_REMOTE in here. 979 977 */ 980 978 long get_user_pages(unsigned long start, unsigned long nr_pages, 981 979 unsigned int gup_flags, struct page **pages,
+1 -1
mm/memory.c
··· 3919 3919 struct page *page = NULL; 3920 3920 3921 3921 ret = get_user_pages_remote(tsk, mm, addr, 1, 3922 - gup_flags, &page, &vma); 3922 + gup_flags, &page, &vma, NULL); 3923 3923 if (ret <= 0) { 3924 3924 #ifndef CONFIG_HAVE_IOREMAP_PROT 3925 3925 break;
+1 -1
security/tomoyo/domain.c
··· 881 881 * the execve(). 882 882 */ 883 883 if (get_user_pages_remote(current, bprm->mm, pos, 1, 884 - FOLL_FORCE, &page, NULL) <= 0) 884 + FOLL_FORCE, &page, NULL, NULL) <= 0) 885 885 return false; 886 886 #else 887 887 page = bprm->page[pos / PAGE_SIZE];