diff options
author | Lorenzo Stoakes <lstoakes@gmail.com> | 2016-10-12 20:20:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-18 17:13:37 -0400 |
commit | c164154f66f0c9b02673f07aa4f044f1d9c70274 (patch) | |
tree | fdfdc521c7cadcbbd8b4bb6bd85e8b17c13fcb13 | |
parent | d4944b0ecec0af882483fe44b66729316e575208 (diff) |
mm: replace get_user_pages_unlocked() write/force parameters with gup_flags
This removes the 'write' and 'force' use from get_user_pages_unlocked()
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>
Reviewed-by: Jan Kara <jack@suse.cz>
Acked-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | arch/mips/mm/gup.c | 2 | ||||
-rw-r--r-- | arch/s390/mm/gup.c | 3 | ||||
-rw-r--r-- | arch/sh/mm/gup.c | 3 | ||||
-rw-r--r-- | arch/sparc/mm/gup.c | 3 | ||||
-rw-r--r-- | arch/x86/mm/gup.c | 2 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-udma.c | 4 | ||||
-rw-r--r-- | drivers/media/pci/ivtv/ivtv-yuv.c | 5 | ||||
-rw-r--r-- | drivers/scsi/st.c | 5 | ||||
-rw-r--r-- | drivers/video/fbdev/pvr2fb.c | 4 | ||||
-rw-r--r-- | include/linux/mm.h | 2 | ||||
-rw-r--r-- | mm/gup.c | 14 | ||||
-rw-r--r-- | mm/nommu.c | 11 | ||||
-rw-r--r-- | mm/util.c | 3 | ||||
-rw-r--r-- | net/ceph/pagevec.c | 2 |
14 files changed, 27 insertions, 36 deletions
diff --git a/arch/mips/mm/gup.c b/arch/mips/mm/gup.c index 42d124fb6474..d8c3c159289a 100644 --- a/arch/mips/mm/gup.c +++ b/arch/mips/mm/gup.c | |||
@@ -287,7 +287,7 @@ slow_irqon: | |||
287 | pages += nr; | 287 | pages += nr; |
288 | 288 | ||
289 | ret = get_user_pages_unlocked(start, (end - start) >> PAGE_SHIFT, | 289 | ret = get_user_pages_unlocked(start, (end - start) >> PAGE_SHIFT, |
290 | write, 0, pages); | 290 | pages, write ? FOLL_WRITE : 0); |
291 | 291 | ||
292 | /* Have to be a bit careful with return values */ | 292 | /* Have to be a bit careful with return values */ |
293 | if (nr > 0) { | 293 | if (nr > 0) { |
diff --git a/arch/s390/mm/gup.c b/arch/s390/mm/gup.c index adb0c34bf431..18d4107e10ee 100644 --- a/arch/s390/mm/gup.c +++ b/arch/s390/mm/gup.c | |||
@@ -266,7 +266,8 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, | |||
266 | /* Try to get the remaining pages with get_user_pages */ | 266 | /* Try to get the remaining pages with get_user_pages */ |
267 | start += nr << PAGE_SHIFT; | 267 | start += nr << PAGE_SHIFT; |
268 | pages += nr; | 268 | pages += nr; |
269 | ret = get_user_pages_unlocked(start, nr_pages - nr, write, 0, pages); | 269 | ret = get_user_pages_unlocked(start, nr_pages - nr, pages, |
270 | write ? FOLL_WRITE : 0); | ||
270 | /* Have to be a bit careful with return values */ | 271 | /* Have to be a bit careful with return values */ |
271 | if (nr > 0) | 272 | if (nr > 0) |
272 | ret = (ret < 0) ? nr : ret + nr; | 273 | ret = (ret < 0) ? nr : ret + nr; |
diff --git a/arch/sh/mm/gup.c b/arch/sh/mm/gup.c index 40fa6c8adc43..063c298ba56c 100644 --- a/arch/sh/mm/gup.c +++ b/arch/sh/mm/gup.c | |||
@@ -258,7 +258,8 @@ slow_irqon: | |||
258 | pages += nr; | 258 | pages += nr; |
259 | 259 | ||
260 | ret = get_user_pages_unlocked(start, | 260 | ret = get_user_pages_unlocked(start, |
261 | (end - start) >> PAGE_SHIFT, write, 0, pages); | 261 | (end - start) >> PAGE_SHIFT, pages, |
262 | write ? FOLL_WRITE : 0); | ||
262 | 263 | ||
263 | /* Have to be a bit careful with return values */ | 264 | /* Have to be a bit careful with return values */ |
264 | if (nr > 0) { | 265 | if (nr > 0) { |
diff --git a/arch/sparc/mm/gup.c b/arch/sparc/mm/gup.c index 4e06750a5d29..cd0e32bbcb1d 100644 --- a/arch/sparc/mm/gup.c +++ b/arch/sparc/mm/gup.c | |||
@@ -238,7 +238,8 @@ slow: | |||
238 | pages += nr; | 238 | pages += nr; |
239 | 239 | ||
240 | ret = get_user_pages_unlocked(start, | 240 | ret = get_user_pages_unlocked(start, |
241 | (end - start) >> PAGE_SHIFT, write, 0, pages); | 241 | (end - start) >> PAGE_SHIFT, pages, |
242 | write ? FOLL_WRITE : 0); | ||
242 | 243 | ||
243 | /* Have to be a bit careful with return values */ | 244 | /* Have to be a bit careful with return values */ |
244 | if (nr > 0) { | 245 | if (nr > 0) { |
diff --git a/arch/x86/mm/gup.c b/arch/x86/mm/gup.c index b8b6a60b32cf..0d4fb3ebbbac 100644 --- a/arch/x86/mm/gup.c +++ b/arch/x86/mm/gup.c | |||
@@ -435,7 +435,7 @@ slow_irqon: | |||
435 | 435 | ||
436 | ret = get_user_pages_unlocked(start, | 436 | ret = get_user_pages_unlocked(start, |
437 | (end - start) >> PAGE_SHIFT, | 437 | (end - start) >> PAGE_SHIFT, |
438 | write, 0, pages); | 438 | pages, write ? FOLL_WRITE : 0); |
439 | 439 | ||
440 | /* Have to be a bit careful with return values */ | 440 | /* Have to be a bit careful with return values */ |
441 | if (nr > 0) { | 441 | if (nr > 0) { |
diff --git a/drivers/media/pci/ivtv/ivtv-udma.c b/drivers/media/pci/ivtv/ivtv-udma.c index 4769469fe842..2c9232ef7baa 100644 --- a/drivers/media/pci/ivtv/ivtv-udma.c +++ b/drivers/media/pci/ivtv/ivtv-udma.c | |||
@@ -124,8 +124,8 @@ int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr, | |||
124 | } | 124 | } |
125 | 125 | ||
126 | /* Get user pages for DMA Xfer */ | 126 | /* Get user pages for DMA Xfer */ |
127 | err = get_user_pages_unlocked(user_dma.uaddr, user_dma.page_count, 0, | 127 | err = get_user_pages_unlocked(user_dma.uaddr, user_dma.page_count, |
128 | 1, dma->map); | 128 | dma->map, FOLL_FORCE); |
129 | 129 | ||
130 | if (user_dma.page_count != err) { | 130 | if (user_dma.page_count != err) { |
131 | IVTV_DEBUG_WARN("failed to map user pages, returned %d instead of %d\n", | 131 | IVTV_DEBUG_WARN("failed to map user pages, returned %d instead of %d\n", |
diff --git a/drivers/media/pci/ivtv/ivtv-yuv.c b/drivers/media/pci/ivtv/ivtv-yuv.c index b094054cda6e..f7299d3d8244 100644 --- a/drivers/media/pci/ivtv/ivtv-yuv.c +++ b/drivers/media/pci/ivtv/ivtv-yuv.c | |||
@@ -76,11 +76,12 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma, | |||
76 | 76 | ||
77 | /* Get user pages for DMA Xfer */ | 77 | /* Get user pages for DMA Xfer */ |
78 | y_pages = get_user_pages_unlocked(y_dma.uaddr, | 78 | y_pages = get_user_pages_unlocked(y_dma.uaddr, |
79 | y_dma.page_count, 0, 1, &dma->map[0]); | 79 | y_dma.page_count, &dma->map[0], FOLL_FORCE); |
80 | uv_pages = 0; /* silence gcc. value is set and consumed only if: */ | 80 | uv_pages = 0; /* silence gcc. value is set and consumed only if: */ |
81 | if (y_pages == y_dma.page_count) { | 81 | if (y_pages == y_dma.page_count) { |
82 | uv_pages = get_user_pages_unlocked(uv_dma.uaddr, | 82 | uv_pages = get_user_pages_unlocked(uv_dma.uaddr, |
83 | uv_dma.page_count, 0, 1, &dma->map[y_pages]); | 83 | uv_dma.page_count, &dma->map[y_pages], |
84 | FOLL_FORCE); | ||
84 | } | 85 | } |
85 | 86 | ||
86 | if (y_pages != y_dma.page_count || uv_pages != uv_dma.page_count) { | 87 | if (y_pages != y_dma.page_count || uv_pages != uv_dma.page_count) { |
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 7af5226aa55b..618422ea3a41 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c | |||
@@ -4922,9 +4922,8 @@ static int sgl_map_user_pages(struct st_buffer *STbp, | |||
4922 | res = get_user_pages_unlocked( | 4922 | res = get_user_pages_unlocked( |
4923 | uaddr, | 4923 | uaddr, |
4924 | nr_pages, | 4924 | nr_pages, |
4925 | rw == READ, | 4925 | pages, |
4926 | 0, /* don't force */ | 4926 | rw == READ ? FOLL_WRITE : 0); /* don't force */ |
4927 | pages); | ||
4928 | 4927 | ||
4929 | /* Errors and no page mapped should return here */ | 4928 | /* Errors and no page mapped should return here */ |
4930 | if (res < nr_pages) | 4929 | if (res < nr_pages) |
diff --git a/drivers/video/fbdev/pvr2fb.c b/drivers/video/fbdev/pvr2fb.c index 3b1ca4411073..a2564ab91e62 100644 --- a/drivers/video/fbdev/pvr2fb.c +++ b/drivers/video/fbdev/pvr2fb.c | |||
@@ -686,8 +686,8 @@ static ssize_t pvr2fb_write(struct fb_info *info, const char *buf, | |||
686 | if (!pages) | 686 | if (!pages) |
687 | return -ENOMEM; | 687 | return -ENOMEM; |
688 | 688 | ||
689 | ret = get_user_pages_unlocked((unsigned long)buf, nr_pages, WRITE, | 689 | ret = get_user_pages_unlocked((unsigned long)buf, nr_pages, pages, |
690 | 0, pages); | 690 | FOLL_WRITE); |
691 | 691 | ||
692 | if (ret < nr_pages) { | 692 | if (ret < nr_pages) { |
693 | nr_pages = ret; | 693 | nr_pages = ret; |
diff --git a/include/linux/mm.h b/include/linux/mm.h index bcdea1f4e98c..abd53f2eb74e 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -1287,7 +1287,7 @@ long __get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm, | |||
1287 | unsigned long start, unsigned long nr_pages, | 1287 | unsigned long start, unsigned long nr_pages, |
1288 | struct page **pages, unsigned int gup_flags); | 1288 | struct page **pages, unsigned int gup_flags); |
1289 | long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages, | 1289 | long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages, |
1290 | int write, int force, struct page **pages); | 1290 | struct page **pages, unsigned int gup_flags); |
1291 | int get_user_pages_fast(unsigned long start, int nr_pages, int write, | 1291 | int get_user_pages_fast(unsigned long start, int nr_pages, int write, |
1292 | struct page **pages); | 1292 | struct page **pages); |
1293 | 1293 | ||
@@ -907,17 +907,10 @@ EXPORT_SYMBOL(__get_user_pages_unlocked); | |||
907 | * "force" parameter). | 907 | * "force" parameter). |
908 | */ | 908 | */ |
909 | long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages, | 909 | long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages, |
910 | int write, int force, struct page **pages) | 910 | struct page **pages, unsigned int gup_flags) |
911 | { | 911 | { |
912 | unsigned int flags = FOLL_TOUCH; | ||
913 | |||
914 | if (write) | ||
915 | flags |= FOLL_WRITE; | ||
916 | if (force) | ||
917 | flags |= FOLL_FORCE; | ||
918 | |||
919 | return __get_user_pages_unlocked(current, current->mm, start, nr_pages, | 912 | return __get_user_pages_unlocked(current, current->mm, start, nr_pages, |
920 | pages, flags); | 913 | pages, gup_flags | FOLL_TOUCH); |
921 | } | 914 | } |
922 | EXPORT_SYMBOL(get_user_pages_unlocked); | 915 | EXPORT_SYMBOL(get_user_pages_unlocked); |
923 | 916 | ||
@@ -1535,7 +1528,8 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, | |||
1535 | start += nr << PAGE_SHIFT; | 1528 | start += nr << PAGE_SHIFT; |
1536 | pages += nr; | 1529 | pages += nr; |
1537 | 1530 | ||
1538 | ret = get_user_pages_unlocked(start, nr_pages - nr, write, 0, pages); | 1531 | ret = get_user_pages_unlocked(start, nr_pages - nr, pages, |
1532 | write ? FOLL_WRITE : 0); | ||
1539 | 1533 | ||
1540 | /* Have to be a bit careful with return values */ | 1534 | /* Have to be a bit careful with return values */ |
1541 | if (nr > 0) { | 1535 | if (nr > 0) { |
diff --git a/mm/nommu.c b/mm/nommu.c index 925dcc1fa2f3..7e27add39f7e 100644 --- a/mm/nommu.c +++ b/mm/nommu.c | |||
@@ -197,17 +197,10 @@ long __get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm, | |||
197 | EXPORT_SYMBOL(__get_user_pages_unlocked); | 197 | EXPORT_SYMBOL(__get_user_pages_unlocked); |
198 | 198 | ||
199 | long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages, | 199 | long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages, |
200 | int write, int force, struct page **pages) | 200 | struct page **pages, unsigned int gup_flags) |
201 | { | 201 | { |
202 | unsigned int flags = 0; | ||
203 | |||
204 | if (write) | ||
205 | flags |= FOLL_WRITE; | ||
206 | if (force) | ||
207 | flags |= FOLL_FORCE; | ||
208 | |||
209 | return __get_user_pages_unlocked(current, current->mm, start, nr_pages, | 202 | return __get_user_pages_unlocked(current, current->mm, start, nr_pages, |
210 | pages, flags); | 203 | pages, gup_flags); |
211 | } | 204 | } |
212 | EXPORT_SYMBOL(get_user_pages_unlocked); | 205 | EXPORT_SYMBOL(get_user_pages_unlocked); |
213 | 206 | ||
@@ -283,7 +283,8 @@ EXPORT_SYMBOL_GPL(__get_user_pages_fast); | |||
283 | int __weak get_user_pages_fast(unsigned long start, | 283 | int __weak get_user_pages_fast(unsigned long start, |
284 | int nr_pages, int write, struct page **pages) | 284 | int nr_pages, int write, struct page **pages) |
285 | { | 285 | { |
286 | return get_user_pages_unlocked(start, nr_pages, write, 0, pages); | 286 | return get_user_pages_unlocked(start, nr_pages, pages, |
287 | write ? FOLL_WRITE : 0); | ||
287 | } | 288 | } |
288 | EXPORT_SYMBOL_GPL(get_user_pages_fast); | 289 | EXPORT_SYMBOL_GPL(get_user_pages_fast); |
289 | 290 | ||
diff --git a/net/ceph/pagevec.c b/net/ceph/pagevec.c index 00d2601407c5..1a7c9a79a53c 100644 --- a/net/ceph/pagevec.c +++ b/net/ceph/pagevec.c | |||
@@ -26,7 +26,7 @@ struct page **ceph_get_direct_page_vector(const void __user *data, | |||
26 | while (got < num_pages) { | 26 | while (got < num_pages) { |
27 | rc = get_user_pages_unlocked( | 27 | rc = get_user_pages_unlocked( |
28 | (unsigned long)data + ((unsigned long)got * PAGE_SIZE), | 28 | (unsigned long)data + ((unsigned long)got * PAGE_SIZE), |
29 | num_pages - got, write_page, 0, pages + got); | 29 | num_pages - got, pages + got, write_page ? FOLL_WRITE : 0); |
30 | if (rc < 0) | 30 | if (rc < 0) |
31 | break; | 31 | break; |
32 | BUG_ON(rc == 0); | 32 | BUG_ON(rc == 0); |