Skip to content

Commit 2d3a36a

Browse files
Michal Hockotorvalds
authored andcommitted
mm, mempolicy: fix up gup usage in lookup_node
ba84107 ("mm/mempolicy: Allow lookup_node() to handle fatal signal") has added a special casing for 0 return value because that was a possible gup return value when interrupted by fatal signal. This has been fixed by ae46d2a ("mm/gup: Let __get_user_pages_locked() return -EINTR for fatal signal") in the mean time so ba84107 can be reverted. This patch however doesn't go all the way to revert it because the check for 0 is wrong and confusing here. Firstly it is inherently unsafe to access the page when get_user_pages_locked returns 0 (aka no page returned). Fortunatelly this will not happen because get_user_pages_locked will not return 0 when nr_pages > 0 unless FOLL_NOWAIT is specified which is not the case here. Document this potential error code in gup code while we are at it. Signed-off-by: Michal Hocko <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Cc: Peter Xu <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Linus Torvalds <[email protected]>
1 parent 5b94ce2 commit 2d3a36a

File tree

2 files changed

+6
-4
lines changed

2 files changed

+6
-4
lines changed

mm/gup.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -989,6 +989,7 @@ static int check_vma_flags(struct vm_area_struct *vma, unsigned long gup_flags)
989989
* -- If nr_pages is >0, but no pages were pinned, returns -errno.
990990
* -- If nr_pages is >0, and some pages were pinned, returns the number of
991991
* pages pinned. Again, this may be less than nr_pages.
992+
* -- 0 return value is possible when the fault would need to be retried.
992993
*
993994
* The caller is responsible for releasing returned @pages, via put_page().
994995
*
@@ -1265,6 +1266,10 @@ int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm,
12651266
}
12661267
EXPORT_SYMBOL_GPL(fixup_user_fault);
12671268

1269+
/*
1270+
* Please note that this function, unlike __get_user_pages will not
1271+
* return 0 for nr_pages > 0 without FOLL_NOWAIT
1272+
*/
12681273
static __always_inline long __get_user_pages_locked(struct task_struct *tsk,
12691274
struct mm_struct *mm,
12701275
unsigned long start,

mm/mempolicy.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -927,10 +927,7 @@ static int lookup_node(struct mm_struct *mm, unsigned long addr)
927927

928928
int locked = 1;
929929
err = get_user_pages_locked(addr & PAGE_MASK, 1, 0, &p, &locked);
930-
if (err == 0) {
931-
/* E.g. GUP interrupted by fatal signal */
932-
err = -EFAULT;
933-
} else if (err > 0) {
930+
if (err > 0) {
934931
err = page_to_nid(p);
935932
put_page(p);
936933
}

0 commit comments

Comments
 (0)