Skip to content

Commit 400dd9d

Browse files
committed
mm: gup: fix infinite loop within __get_longterm_locked
JIRA: https://issues.redhat.com/browse/RHEL-89519 commit 1aaf8c1 Author: Zhaoyang Huang <zhaoyang.huang@unisoc.com> Date: Tue, 21 Jan 2025 10:01:59 +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. [zhaoyang.huang@unisoc.com: move definition of local] Link: https://lkml.kernel.org/r/20250122012604.3654667-1-zhaoyang.huang@unisoc.com Link: https://lkml.kernel.org/r/20250121020159.3636477-1-zhaoyang.huang@unisoc.com Fixes: 67e139b ("mm/gup.c: refactor check_and_migrate_movable_pages()") Signed-off-by: Zhaoyang Huang <zhaoyang.huang@unisoc.com> Reviewed-by: John Hubbard <jhubbard@nvidia.com> Reviewed-by: David Hildenbrand <david@redhat.com> Suggested-by: David Hildenbrand <david@redhat.com> Acked-by: David Hildenbrand <david@redhat.com> Cc: Aijun Sun <aijun.sun@unisoc.com> Cc: Alistair Popple <apopple@nvidia.com> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Waiman Long <longman@redhat.com>
1 parent 66665c8 commit 400dd9d

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
@@ -2069,13 +2069,13 @@ static void pofs_unpin(struct pages_or_folios *pofs)
20692069
/*
20702070
* Returns the number of collected folios. Return value is always >= 0.
20712071
*/
2072-
static unsigned long collect_longterm_unpinnable_folios(
2072+
static void collect_longterm_unpinnable_folios(
20732073
struct list_head *movable_folio_list,
20742074
struct pages_or_folios *pofs)
20752075
{
2076-
unsigned long i, collected = 0;
20772076
struct folio *prev_folio = NULL;
20782077
bool drain_allow = true;
2078+
unsigned long i;
20792079

20802080
for (i = 0; i < pofs->nr_entries; i++) {
20812081
struct folio *folio = pofs_get_folio(pofs, i);
@@ -2087,8 +2087,6 @@ static unsigned long collect_longterm_unpinnable_folios(
20872087
if (folio_is_longterm_pinnable(folio))
20882088
continue;
20892089

2090-
collected++;
2091-
20922090
if (folio_is_device_coherent(folio))
20932091
continue;
20942092

@@ -2110,8 +2108,6 @@ static unsigned long collect_longterm_unpinnable_folios(
21102108
NR_ISOLATED_ANON + folio_is_file_lru(folio),
21112109
folio_nr_pages(folio));
21122110
}
2113-
2114-
return collected;
21152111
}
21162112

21172113
/*
@@ -2188,11 +2184,9 @@ static long
21882184
check_and_migrate_movable_pages_or_folios(struct pages_or_folios *pofs)
21892185
{
21902186
LIST_HEAD(movable_folio_list);
2191-
unsigned long collected;
21922187

2193-
collected = collect_longterm_unpinnable_folios(&movable_folio_list,
2194-
pofs);
2195-
if (!collected)
2188+
collect_longterm_unpinnable_folios(&movable_folio_list, pofs);
2189+
if (list_empty(&movable_folio_list))
21962190
return 0;
21972191

21982192
return migrate_longterm_unpinnable_folios(&movable_folio_list, pofs);

0 commit comments

Comments
 (0)