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>
This commit is contained in:
Родитель
d4944b0ece
Коммит
c164154f66
|
@ -287,7 +287,7 @@ slow_irqon:
|
|||
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 @@ slow_irqon:
|
|||
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 @@ slow:
|
|||
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 @@ slow_irqon:
|
|||
|
||||
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);
|
||||
|
||||
|
|
14
mm/gup.c
14
mm/gup.c
|
@ -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) {
|
||||
|
|
11
mm/nommu.c
11
mm/nommu.c
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче