Permalink
Browse files

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>
  • Loading branch information...
lorenzo-stoakes authored and torvalds committed Oct 13, 2016
1 parent d4944b0 commit c164154f66f0c9b02673f07aa4f044f1d9c70274
@@ -287,7 +287,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
pages += nr;

ret = get_user_pages_unlocked(start, (end - start) >> PAGE_SHIFT,
write, 0, pages);
pages, write ? FOLL_WRITE : 0);

/* Have to be a bit careful with return values */
if (nr > 0) {
@@ -266,7 +266,8 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
/* Try to get the remaining pages with get_user_pages */
start += nr << PAGE_SHIFT;
pages += nr;
ret = get_user_pages_unlocked(start, nr_pages - nr, write, 0, pages);
ret = get_user_pages_unlocked(start, nr_pages - nr, pages,
write ? FOLL_WRITE : 0);
/* Have to be a bit careful with return values */
if (nr > 0)
ret = (ret < 0) ? nr : ret + nr;
@@ -258,7 +258,8 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
pages += nr;

ret = get_user_pages_unlocked(start,
(end - start) >> PAGE_SHIFT, write, 0, pages);
(end - start) >> PAGE_SHIFT, pages,
write ? FOLL_WRITE : 0);

/* Have to be a bit careful with return values */
if (nr > 0) {
@@ -238,7 +238,8 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
pages += nr;

ret = get_user_pages_unlocked(start,
(end - start) >> PAGE_SHIFT, write, 0, pages);
(end - start) >> PAGE_SHIFT, pages,
write ? FOLL_WRITE : 0);

/* Have to be a bit careful with return values */
if (nr > 0) {
@@ -435,7 +435,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,

ret = get_user_pages_unlocked(start,
(end - start) >> PAGE_SHIFT,
write, 0, pages);
pages, write ? FOLL_WRITE : 0);

/* Have to be a bit careful with return values */
if (nr > 0) {
@@ -124,8 +124,8 @@ int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr,
}

/* Get user pages for DMA Xfer */
err = get_user_pages_unlocked(user_dma.uaddr, user_dma.page_count, 0,
1, dma->map);
err = get_user_pages_unlocked(user_dma.uaddr, user_dma.page_count,
dma->map, FOLL_FORCE);

if (user_dma.page_count != err) {
IVTV_DEBUG_WARN("failed to map user pages, returned %d instead of %d\n",
@@ -76,11 +76,12 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma,

/* Get user pages for DMA Xfer */
y_pages = get_user_pages_unlocked(y_dma.uaddr,
y_dma.page_count, 0, 1, &dma->map[0]);
y_dma.page_count, &dma->map[0], FOLL_FORCE);
uv_pages = 0; /* silence gcc. value is set and consumed only if: */
if (y_pages == y_dma.page_count) {
uv_pages = get_user_pages_unlocked(uv_dma.uaddr,
uv_dma.page_count, 0, 1, &dma->map[y_pages]);
uv_dma.page_count, &dma->map[y_pages],
FOLL_FORCE);
}

if (y_pages != y_dma.page_count || uv_pages != uv_dma.page_count) {
@@ -4922,9 +4922,8 @@ static int sgl_map_user_pages(struct st_buffer *STbp,
res = get_user_pages_unlocked(
uaddr,
nr_pages,
rw == READ,
0, /* don't force */
pages);
pages,
rw == READ ? FOLL_WRITE : 0); /* don't force */

/* Errors and no page mapped should return here */
if (res < nr_pages)
@@ -686,8 +686,8 @@ static ssize_t pvr2fb_write(struct fb_info *info, const char *buf,
if (!pages)
return -ENOMEM;

ret = get_user_pages_unlocked((unsigned long)buf, nr_pages, WRITE,
0, pages);
ret = get_user_pages_unlocked((unsigned long)buf, nr_pages, pages,
FOLL_WRITE);

if (ret < nr_pages) {
nr_pages = ret;
@@ -1287,7 +1287,7 @@ long __get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm,
unsigned long start, unsigned long nr_pages,
struct page **pages, unsigned int gup_flags);
long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages,
int write, int force, struct page **pages);
struct page **pages, unsigned int gup_flags);
int get_user_pages_fast(unsigned long start, int nr_pages, int write,
struct page **pages);

@@ -907,17 +907,10 @@ EXPORT_SYMBOL(__get_user_pages_unlocked);
* "force" parameter).
*/
long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages,
int write, int force, struct page **pages)
struct page **pages, unsigned int gup_flags)
{
unsigned int flags = FOLL_TOUCH;

if (write)
flags |= FOLL_WRITE;
if (force)
flags |= FOLL_FORCE;

return __get_user_pages_unlocked(current, current->mm, start, nr_pages,
pages, flags);
pages, gup_flags | FOLL_TOUCH);
}
EXPORT_SYMBOL(get_user_pages_unlocked);

@@ -1535,7 +1528,8 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
start += nr << PAGE_SHIFT;
pages += nr;

ret = get_user_pages_unlocked(start, nr_pages - nr, write, 0, pages);
ret = get_user_pages_unlocked(start, nr_pages - nr, pages,
write ? FOLL_WRITE : 0);

/* Have to be a bit careful with return values */
if (nr > 0) {
@@ -197,17 +197,10 @@ long __get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm,
EXPORT_SYMBOL(__get_user_pages_unlocked);

long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages,
int write, int force, struct page **pages)
struct page **pages, unsigned int gup_flags)
{
unsigned int flags = 0;

if (write)
flags |= FOLL_WRITE;
if (force)
flags |= FOLL_FORCE;

return __get_user_pages_unlocked(current, current->mm, start, nr_pages,
pages, flags);
pages, gup_flags);
}
EXPORT_SYMBOL(get_user_pages_unlocked);

@@ -283,7 +283,8 @@ EXPORT_SYMBOL_GPL(__get_user_pages_fast);
int __weak get_user_pages_fast(unsigned long start,
int nr_pages, int write, struct page **pages)
{
return get_user_pages_unlocked(start, nr_pages, write, 0, pages);
return get_user_pages_unlocked(start, nr_pages, pages,
write ? FOLL_WRITE : 0);
}
EXPORT_SYMBOL_GPL(get_user_pages_fast);

@@ -26,7 +26,7 @@ struct page **ceph_get_direct_page_vector(const void __user *data,
while (got < num_pages) {
rc = get_user_pages_unlocked(
(unsigned long)data + ((unsigned long)got * PAGE_SIZE),
num_pages - got, write_page, 0, pages + got);
num_pages - got, pages + got, write_page ? FOLL_WRITE : 0);
if (rc < 0)
break;
BUG_ON(rc == 0);

0 comments on commit c164154

Please sign in to comment.