Commit 9beae1ea authored by Lorenzo Stoakes's avatar Lorenzo Stoakes Committed by Linus Torvalds
Browse files

mm: replace get_user_pages_remote() write/force parameters with gup_flags



This removes the 'write' and 'force' from get_user_pages_remote() and
replaces them with 'gup_flags' to make the use of FOLL_FORCE explicit in
callers as use of this flag can result in surprising behaviour (and
hence bugs) within the mm subsystem.

Signed-off-by: default avatarLorenzo Stoakes <lstoakes@gmail.com>
Acked-by: default avatarMichal Hocko <mhocko@suse.com>
Reviewed-by: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 768ae309
Loading
Loading
Loading
Loading
+5 −2
Original line number Original line Diff line number Diff line
@@ -748,19 +748,22 @@ static struct page **etnaviv_gem_userptr_do_get_pages(
	int ret = 0, pinned, npages = etnaviv_obj->base.size >> PAGE_SHIFT;
	int ret = 0, pinned, npages = etnaviv_obj->base.size >> PAGE_SHIFT;
	struct page **pvec;
	struct page **pvec;
	uintptr_t ptr;
	uintptr_t ptr;
	unsigned int flags = 0;


	pvec = drm_malloc_ab(npages, sizeof(struct page *));
	pvec = drm_malloc_ab(npages, sizeof(struct page *));
	if (!pvec)
	if (!pvec)
		return ERR_PTR(-ENOMEM);
		return ERR_PTR(-ENOMEM);


	if (!etnaviv_obj->userptr.ro)
		flags |= FOLL_WRITE;

	pinned = 0;
	pinned = 0;
	ptr = etnaviv_obj->userptr.ptr;
	ptr = etnaviv_obj->userptr.ptr;


	down_read(&mm->mmap_sem);
	down_read(&mm->mmap_sem);
	while (pinned < npages) {
	while (pinned < npages) {
		ret = get_user_pages_remote(task, mm, ptr, npages - pinned,
		ret = get_user_pages_remote(task, mm, ptr, npages - pinned,
					    !etnaviv_obj->userptr.ro, 0,
					    flags, pvec + pinned, NULL);
					    pvec + pinned, NULL);
		if (ret < 0)
		if (ret < 0)
			break;
			break;


+5 −1
Original line number Original line Diff line number Diff line
@@ -508,6 +508,10 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work)
	pvec = drm_malloc_gfp(npages, sizeof(struct page *), GFP_TEMPORARY);
	pvec = drm_malloc_gfp(npages, sizeof(struct page *), GFP_TEMPORARY);
	if (pvec != NULL) {
	if (pvec != NULL) {
		struct mm_struct *mm = obj->userptr.mm->mm;
		struct mm_struct *mm = obj->userptr.mm->mm;
		unsigned int flags = 0;

		if (!obj->userptr.read_only)
			flags |= FOLL_WRITE;


		ret = -EFAULT;
		ret = -EFAULT;
		if (atomic_inc_not_zero(&mm->mm_users)) {
		if (atomic_inc_not_zero(&mm->mm_users)) {
@@ -517,7 +521,7 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work)
					(work->task, mm,
					(work->task, mm,
					 obj->userptr.ptr + pinned * PAGE_SIZE,
					 obj->userptr.ptr + pinned * PAGE_SIZE,
					 npages - pinned,
					 npages - pinned,
					 !obj->userptr.read_only, 0,
					 flags,
					 pvec + pinned, NULL);
					 pvec + pinned, NULL);
				if (ret < 0)
				if (ret < 0)
					break;
					break;
+5 −2
Original line number Original line Diff line number Diff line
@@ -527,6 +527,7 @@ int ib_umem_odp_map_dma_pages(struct ib_umem *umem, u64 user_virt, u64 bcnt,
	u64 off;
	u64 off;
	int j, k, ret = 0, start_idx, npages = 0;
	int j, k, ret = 0, start_idx, npages = 0;
	u64 base_virt_addr;
	u64 base_virt_addr;
	unsigned int flags = 0;


	if (access_mask == 0)
	if (access_mask == 0)
		return -EINVAL;
		return -EINVAL;
@@ -556,6 +557,9 @@ int ib_umem_odp_map_dma_pages(struct ib_umem *umem, u64 user_virt, u64 bcnt,
		goto out_put_task;
		goto out_put_task;
	}
	}


	if (access_mask & ODP_WRITE_ALLOWED_BIT)
		flags |= FOLL_WRITE;

	start_idx = (user_virt - ib_umem_start(umem)) >> PAGE_SHIFT;
	start_idx = (user_virt - ib_umem_start(umem)) >> PAGE_SHIFT;
	k = start_idx;
	k = start_idx;


@@ -574,8 +578,7 @@ int ib_umem_odp_map_dma_pages(struct ib_umem *umem, u64 user_virt, u64 bcnt,
		 */
		 */
		npages = get_user_pages_remote(owning_process, owning_mm,
		npages = get_user_pages_remote(owning_process, owning_mm,
				user_virt, gup_num_pages,
				user_virt, gup_num_pages,
				access_mask & ODP_WRITE_ALLOWED_BIT,
				flags, local_page_list, NULL);
				0, local_page_list, NULL);
		up_read(&owning_mm->mmap_sem);
		up_read(&owning_mm->mmap_sem);


		if (npages < 0)
		if (npages < 0)
+7 −2
Original line number Original line Diff line number Diff line
@@ -191,6 +191,7 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
{
{
	struct page *page;
	struct page *page;
	int ret;
	int ret;
	unsigned int gup_flags = FOLL_FORCE;


#ifdef CONFIG_STACK_GROWSUP
#ifdef CONFIG_STACK_GROWSUP
	if (write) {
	if (write) {
@@ -199,12 +200,16 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
			return NULL;
			return NULL;
	}
	}
#endif
#endif

	if (write)
		gup_flags |= FOLL_WRITE;

	/*
	/*
	 * We are doing an exec().  'current' is the process
	 * We are doing an exec().  'current' is the process
	 * doing the exec and bprm->mm is the new process's mm.
	 * doing the exec and bprm->mm is the new process's mm.
	 */
	 */
	ret = get_user_pages_remote(current, bprm->mm, pos, 1, write,
	ret = get_user_pages_remote(current, bprm->mm, pos, 1, gup_flags,
			1, &page, NULL);
			&page, NULL);
	if (ret <= 0)
	if (ret <= 0)
		return NULL;
		return NULL;


+1 −1
Original line number Original line Diff line number Diff line
@@ -1276,7 +1276,7 @@ long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
		      struct vm_area_struct **vmas, int *nonblocking);
		      struct vm_area_struct **vmas, int *nonblocking);
long get_user_pages_remote(struct task_struct *tsk, struct mm_struct *mm,
long get_user_pages_remote(struct task_struct *tsk, struct mm_struct *mm,
			    unsigned long start, unsigned long nr_pages,
			    unsigned long start, unsigned long nr_pages,
			    int write, int force, struct page **pages,
			    unsigned int gup_flags, struct page **pages,
			    struct vm_area_struct **vmas);
			    struct vm_area_struct **vmas);
long get_user_pages(unsigned long start, unsigned long nr_pages,
long get_user_pages(unsigned long start, unsigned long nr_pages,
			    unsigned int gup_flags, struct page **pages,
			    unsigned int gup_flags, struct page **pages,
Loading