diff options
author | Lorenzo Stoakes <lstoakes@gmail.com> | 2016-10-12 20:20:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-19 11:11:24 -0400 |
commit | 7f23b3504a0df63b724180262c5f3f117f21bcae (patch) | |
tree | 2cb724ea105ba582472261bda4450d32da1e67d4 | |
parent | 3b913179c3fa89dd0e304193fa0c746fc0481447 (diff) |
mm: replace get_vaddr_frames() write/force parameters with gup_flags
This removes the 'write' and 'force' from get_vaddr_frames() 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: Lorenzo Stoakes <lstoakes@gmail.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_g2d.c | 3 | ||||
-rw-r--r-- | drivers/media/platform/omap/omap_vout.c | 2 | ||||
-rw-r--r-- | drivers/media/v4l2-core/videobuf2-memops.c | 6 | ||||
-rw-r--r-- | include/linux/mm.h | 2 | ||||
-rw-r--r-- | mm/frame_vector.c | 13 |
5 files changed, 11 insertions, 15 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index aa92decf4233..fbd13fabdf2d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c | |||
@@ -488,7 +488,8 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev, | |||
488 | goto err_free; | 488 | goto err_free; |
489 | } | 489 | } |
490 | 490 | ||
491 | ret = get_vaddr_frames(start, npages, true, true, g2d_userptr->vec); | 491 | ret = get_vaddr_frames(start, npages, FOLL_FORCE | FOLL_WRITE, |
492 | g2d_userptr->vec); | ||
492 | if (ret != npages) { | 493 | if (ret != npages) { |
493 | DRM_ERROR("failed to get user pages from userptr.\n"); | 494 | DRM_ERROR("failed to get user pages from userptr.\n"); |
494 | if (ret < 0) | 495 | if (ret < 0) |
diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c index e668dde6d857..a31b95cb3b09 100644 --- a/drivers/media/platform/omap/omap_vout.c +++ b/drivers/media/platform/omap/omap_vout.c | |||
@@ -214,7 +214,7 @@ static int omap_vout_get_userptr(struct videobuf_buffer *vb, u32 virtp, | |||
214 | if (!vec) | 214 | if (!vec) |
215 | return -ENOMEM; | 215 | return -ENOMEM; |
216 | 216 | ||
217 | ret = get_vaddr_frames(virtp, 1, true, false, vec); | 217 | ret = get_vaddr_frames(virtp, 1, FOLL_WRITE, vec); |
218 | if (ret != 1) { | 218 | if (ret != 1) { |
219 | frame_vector_destroy(vec); | 219 | frame_vector_destroy(vec); |
220 | return -EINVAL; | 220 | return -EINVAL; |
diff --git a/drivers/media/v4l2-core/videobuf2-memops.c b/drivers/media/v4l2-core/videobuf2-memops.c index 3c3b517f1d1c..1cd322e939c7 100644 --- a/drivers/media/v4l2-core/videobuf2-memops.c +++ b/drivers/media/v4l2-core/videobuf2-memops.c | |||
@@ -42,6 +42,10 @@ struct frame_vector *vb2_create_framevec(unsigned long start, | |||
42 | unsigned long first, last; | 42 | unsigned long first, last; |
43 | unsigned long nr; | 43 | unsigned long nr; |
44 | struct frame_vector *vec; | 44 | struct frame_vector *vec; |
45 | unsigned int flags = FOLL_FORCE; | ||
46 | |||
47 | if (write) | ||
48 | flags |= FOLL_WRITE; | ||
45 | 49 | ||
46 | first = start >> PAGE_SHIFT; | 50 | first = start >> PAGE_SHIFT; |
47 | last = (start + length - 1) >> PAGE_SHIFT; | 51 | last = (start + length - 1) >> PAGE_SHIFT; |
@@ -49,7 +53,7 @@ struct frame_vector *vb2_create_framevec(unsigned long start, | |||
49 | vec = frame_vector_create(nr); | 53 | vec = frame_vector_create(nr); |
50 | if (!vec) | 54 | if (!vec) |
51 | return ERR_PTR(-ENOMEM); | 55 | return ERR_PTR(-ENOMEM); |
52 | ret = get_vaddr_frames(start & PAGE_MASK, nr, write, true, vec); | 56 | ret = get_vaddr_frames(start & PAGE_MASK, nr, flags, vec); |
53 | if (ret < 0) | 57 | if (ret < 0) |
54 | goto out_destroy; | 58 | goto out_destroy; |
55 | /* We accept only complete set of PFNs */ | 59 | /* We accept only complete set of PFNs */ |
diff --git a/include/linux/mm.h b/include/linux/mm.h index 9fe9b0438169..91cc923ce985 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -1305,7 +1305,7 @@ struct frame_vector { | |||
1305 | struct frame_vector *frame_vector_create(unsigned int nr_frames); | 1305 | struct frame_vector *frame_vector_create(unsigned int nr_frames); |
1306 | void frame_vector_destroy(struct frame_vector *vec); | 1306 | void frame_vector_destroy(struct frame_vector *vec); |
1307 | int get_vaddr_frames(unsigned long start, unsigned int nr_pfns, | 1307 | int get_vaddr_frames(unsigned long start, unsigned int nr_pfns, |
1308 | bool write, bool force, struct frame_vector *vec); | 1308 | unsigned int gup_flags, struct frame_vector *vec); |
1309 | void put_vaddr_frames(struct frame_vector *vec); | 1309 | void put_vaddr_frames(struct frame_vector *vec); |
1310 | int frame_vector_to_pages(struct frame_vector *vec); | 1310 | int frame_vector_to_pages(struct frame_vector *vec); |
1311 | void frame_vector_to_pfns(struct frame_vector *vec); | 1311 | void frame_vector_to_pfns(struct frame_vector *vec); |
diff --git a/mm/frame_vector.c b/mm/frame_vector.c index 81b67498bb9c..db77dcb38afd 100644 --- a/mm/frame_vector.c +++ b/mm/frame_vector.c | |||
@@ -11,10 +11,7 @@ | |||
11 | * get_vaddr_frames() - map virtual addresses to pfns | 11 | * get_vaddr_frames() - map virtual addresses to pfns |
12 | * @start: starting user address | 12 | * @start: starting user address |
13 | * @nr_frames: number of pages / pfns from start to map | 13 | * @nr_frames: number of pages / pfns from start to map |
14 | * @write: whether pages will be written to by the caller | 14 | * @gup_flags: flags modifying lookup behaviour |
15 | * @force: whether to force write access even if user mapping is | ||
16 | * readonly. See description of the same argument of | ||
17 | get_user_pages(). | ||
18 | * @vec: structure which receives pages / pfns of the addresses mapped. | 15 | * @vec: structure which receives pages / pfns of the addresses mapped. |
19 | * It should have space for at least nr_frames entries. | 16 | * It should have space for at least nr_frames entries. |
20 | * | 17 | * |
@@ -34,23 +31,17 @@ | |||
34 | * This function takes care of grabbing mmap_sem as necessary. | 31 | * This function takes care of grabbing mmap_sem as necessary. |
35 | */ | 32 | */ |
36 | int get_vaddr_frames(unsigned long start, unsigned int nr_frames, | 33 | int get_vaddr_frames(unsigned long start, unsigned int nr_frames, |
37 | bool write, bool force, struct frame_vector *vec) | 34 | unsigned int gup_flags, struct frame_vector *vec) |
38 | { | 35 | { |
39 | struct mm_struct *mm = current->mm; | 36 | struct mm_struct *mm = current->mm; |
40 | struct vm_area_struct *vma; | 37 | struct vm_area_struct *vma; |
41 | int ret = 0; | 38 | int ret = 0; |
42 | int err; | 39 | int err; |
43 | int locked; | 40 | int locked; |
44 | unsigned int gup_flags = 0; | ||
45 | 41 | ||
46 | if (nr_frames == 0) | 42 | if (nr_frames == 0) |
47 | return 0; | 43 | return 0; |
48 | 44 | ||
49 | if (write) | ||
50 | gup_flags |= FOLL_WRITE; | ||
51 | if (force) | ||
52 | gup_flags |= FOLL_FORCE; | ||
53 | |||
54 | if (WARN_ON_ONCE(nr_frames > vec->nr_allocated)) | 45 | if (WARN_ON_ONCE(nr_frames > vec->nr_allocated)) |
55 | nr_frames = vec->nr_allocated; | 46 | nr_frames = vec->nr_allocated; |
56 | 47 | ||