Skip to content

Commit 2935006

Browse files
committed
mm: gup: fix infinite loop within __get_longterm_locked
commit 1aaf8c1 Author: Zhaoyang Huang <[email protected]> Date: Tue Jan 21 10:01:59 2025 +0800 mm: gup: fix infinite loop within __get_longterm_locked 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]> JIRA: https://issues.redhat.com/browse/RHEL-77742 Signed-off-by: Nico Pache <[email protected]>
1 parent 5d62a2c commit 2935006

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
@@ -2323,13 +2323,13 @@ static void pofs_unpin(struct pages_or_folios *pofs)
23232323
/*
23242324
* Returns the number of collected folios. Return value is always >= 0.
23252325
*/
2326-
static unsigned long collect_longterm_unpinnable_folios(
2326+
static void collect_longterm_unpinnable_folios(
23272327
struct list_head *movable_folio_list,
23282328
struct pages_or_folios *pofs)
23292329
{
2330-
unsigned long i, collected = 0;
23312330
struct folio *prev_folio = NULL;
23322331
bool drain_allow = true;
2332+
unsigned long i;
23332333

23342334
for (i = 0; i < pofs->nr_entries; i++) {
23352335
struct folio *folio = pofs_get_folio(pofs, i);
@@ -2341,8 +2341,6 @@ static unsigned long collect_longterm_unpinnable_folios(
23412341
if (folio_is_longterm_pinnable(folio))
23422342
continue;
23432343

2344-
collected++;
2345-
23462344
if (folio_is_device_coherent(folio))
23472345
continue;
23482346

@@ -2364,8 +2362,6 @@ static unsigned long collect_longterm_unpinnable_folios(
23642362
NR_ISOLATED_ANON + folio_is_file_lru(folio),
23652363
folio_nr_pages(folio));
23662364
}
2367-
2368-
return collected;
23692365
}
23702366

23712367
/*
@@ -2442,11 +2438,9 @@ static long
24422438
check_and_migrate_movable_pages_or_folios(struct pages_or_folios *pofs)
24432439
{
24442440
LIST_HEAD(movable_folio_list);
2445-
unsigned long collected;
24462441

2447-
collected = collect_longterm_unpinnable_folios(&movable_folio_list,
2448-
pofs);
2449-
if (!collected)
2442+
collect_longterm_unpinnable_folios(&movable_folio_list, pofs);
2443+
if (list_empty(&movable_folio_list))
24502444
return 0;
24512445

24522446
return migrate_longterm_unpinnable_folios(&movable_folio_list, pofs);

0 commit comments

Comments
 (0)