Skip to content

Commit c986a5f

Browse files
Zhaoyang Huanggregkh
authored andcommitted
mm: gup: fix infinite loop within __get_longterm_locked
commit 1aaf8c122918aa8897605a9aa1e8ed6600d6f930 upstream. We can run into an infinite loop in __get_longterm_locked() when collect_longterm_unpinnable_folios() finds only folios that are isolated from the LRU or were never added to the LRU. This can happen when all folios to be pinned are never added to the LRU, for example when vm_ops->fault allocated pages using cma_alloc() and never added them to the LRU. Fix it by simply taking a look at the list in the single caller, to see if anything was added. [[email protected]: move definition of local] Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Fixes: 67e139b ("mm/gup.c: refactor check_and_migrate_movable_pages()") Signed-off-by: Zhaoyang Huang <[email protected]> Reviewed-by: John Hubbard <[email protected]> Reviewed-by: David Hildenbrand <[email protected]> Suggested-by: David Hildenbrand <[email protected]> Acked-by: David Hildenbrand <[email protected]> Cc: Aijun Sun <[email protected]> Cc: Alistair Popple <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Wentao Guan <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 5b2608b commit c986a5f

File tree

1 file changed

+4
-10
lines changed

1 file changed

+4
-10
lines changed

mm/gup.c

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1944,14 +1944,14 @@ struct page *get_dump_page(unsigned long addr)
19441944
/*
19451945
* Returns the number of collected pages. Return value is always >= 0.
19461946
*/
1947-
static unsigned long collect_longterm_unpinnable_pages(
1947+
static void collect_longterm_unpinnable_pages(
19481948
struct list_head *movable_page_list,
19491949
unsigned long nr_pages,
19501950
struct page **pages)
19511951
{
1952-
unsigned long i, collected = 0;
19531952
struct folio *prev_folio = NULL;
19541953
bool drain_allow = true;
1954+
unsigned long i;
19551955

19561956
for (i = 0; i < nr_pages; i++) {
19571957
struct folio *folio = page_folio(pages[i]);
@@ -1963,8 +1963,6 @@ static unsigned long collect_longterm_unpinnable_pages(
19631963
if (folio_is_longterm_pinnable(folio))
19641964
continue;
19651965

1966-
collected++;
1967-
19681966
if (folio_is_device_coherent(folio))
19691967
continue;
19701968

@@ -1986,8 +1984,6 @@ static unsigned long collect_longterm_unpinnable_pages(
19861984
NR_ISOLATED_ANON + folio_is_file_lru(folio),
19871985
folio_nr_pages(folio));
19881986
}
1989-
1990-
return collected;
19911987
}
19921988

19931989
/*
@@ -2080,12 +2076,10 @@ static int migrate_longterm_unpinnable_pages(
20802076
static long check_and_migrate_movable_pages(unsigned long nr_pages,
20812077
struct page **pages)
20822078
{
2083-
unsigned long collected;
20842079
LIST_HEAD(movable_page_list);
20852080

2086-
collected = collect_longterm_unpinnable_pages(&movable_page_list,
2087-
nr_pages, pages);
2088-
if (!collected)
2081+
collect_longterm_unpinnable_pages(&movable_page_list, nr_pages, pages);
2082+
if (list_empty(&movable_page_list))
20892083
return 0;
20902084

20912085
return migrate_longterm_unpinnable_pages(&movable_page_list, nr_pages,

0 commit comments

Comments
 (0)