From: Hyesoo Yu <hyesoo.yu@samsung.com>
Cc: janghyuck.kim@samsung.com, zhaoyang.huang@unisoc.com,
jaewon31.kim@gmail.com, david@redhat.com,
Hyesoo Yu <hyesoo.yu@samsung.com>,
Andrew Morton <akpm@linux-foundation.org>,
Jason Gunthorpe <jgg@ziepe.ca>,
John Hubbard <jhubbard@nvidia.com>, Peter Xu <peterx@redhat.com>,
linux-mm@kvack.org, linux-kernel@vger.kernel.org
Subject: [PATCH v2 2/2] mm: gup: avoid CMA page pinning by retrying migration if no migratable page
Date: Thu, 5 Jun 2025 12:32:07 +0900 [thread overview]
Message-ID: <20250605033210.3184521-3-hyesoo.yu@samsung.com> (raw)
In-Reply-To: <20250605033210.3184521-1-hyesoo.yu@samsung.com>
Commit 1aaf8c122918 ("mm: gup: fix infinite loop within __get_longterm_locked")
introduced an issue where CMA pages could be pinned by longterm GUP requests.
This occurs when unpinnable pages are detected but the movable_page_list is empty;
the commit would return success without retrying, allowing unpinnable
pages (such as CMA) to become pinned.
CMA pages may be temporarily off the LRU due to concurrent isolation,
for example when multiple longterm GUP requests are racing and therefore
not appear in movable_page_list. Before commit 1aaf8c, the kernel would
retry migration in such cases, which helped avoid accidental CMA pinning.
The original intent of the commit was to support longterm GUP on non-LRU
CMA pages in out-of-tree use cases such as pKVM. However, allowing this
can lead to broader CMA pinning issues.
To avoid this, the logic is restored to return -EAGAIN instead of success
when no folios could be collected but unpinnable pages were found.
This ensures that migration is retried until success, and avoids
inadvertently pinning unpinnable pages.
Fixes: 1aaf8c122918 ("mm: gup: fix infinite loop within __get_longterm_locked")
Signed-off-by: Hyesoo Yu <hyesoo.yu@samsung.com>
---
mm/gup.c | 28 ++++++++++++++++++++++------
1 file changed, 22 insertions(+), 6 deletions(-)
diff --git a/mm/gup.c b/mm/gup.c
index 68d91b000199..a25c8c894882 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -2300,15 +2300,13 @@ static void pofs_unpin(struct pages_or_folios *pofs)
unpin_user_pages(pofs->pages, pofs->nr_entries);
}
-/*
- * Returns the number of collected folios. Return value is always >= 0.
- */
-static void collect_longterm_unpinnable_folios(
+static bool collect_longterm_unpinnable_folios(
struct list_head *movable_folio_list,
struct pages_or_folios *pofs)
{
struct folio *prev_folio = NULL;
bool drain_allow = true;
+ bool any_unpinnable = false;
unsigned long i;
for (i = 0; i < pofs->nr_entries; i++) {
@@ -2321,6 +2319,8 @@ static void collect_longterm_unpinnable_folios(
if (folio_is_longterm_pinnable(folio))
continue;
+ any_unpinnable = true;
+
if (folio_is_device_coherent(folio))
continue;
@@ -2342,6 +2342,8 @@ static void collect_longterm_unpinnable_folios(
NR_ISOLATED_ANON + folio_is_file_lru(folio),
folio_nr_pages(folio));
}
+
+ return any_unpinnable;
}
/*
@@ -2407,11 +2409,25 @@ migrate_longterm_unpinnable_folios(struct list_head *movable_folio_list,
static long
check_and_migrate_movable_pages_or_folios(struct pages_or_folios *pofs)
{
+ bool any_unpinnable;
+
LIST_HEAD(movable_folio_list);
- collect_longterm_unpinnable_folios(&movable_folio_list, pofs);
- if (list_empty(&movable_folio_list))
+ any_unpinnable = collect_longterm_unpinnable_folios(&movable_folio_list, pofs);
+
+ if (list_empty(&movable_folio_list)) {
+ /*
+ * If we find any longterm unpinnable page that we failed to
+ * isolated for migration, it might be because someone else
+ * concurrently isolated it. Make the caller retry until it
+ * succeeds.
+ */
+ if (any_unpinnable) {
+ pofs_unpin(pofs);
+ return -EAGAIN;
+ }
return 0;
+ }
return migrate_longterm_unpinnable_folios(&movable_folio_list, pofs);
}
--
2.49.0
next prev parent reply other threads:[~2025-06-05 3:34 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <CGME20250605033401epcas2p46651837ba85629a50ed69db9665a52a2@epcas2p4.samsung.com>
2025-06-05 3:32 ` [PATCH v2 0/2] mm: gup: avoid CMA pinning and clean up stale logic Hyesoo Yu
[not found] ` <CGME20250605033430epcas2p37db099e1ff4f2225c2059e08bbaa97c9@epcas2p3.samsung.com>
2025-06-05 3:32 ` [PATCH v2 1/2] mm: gup: clean up stale logic in migrate_longterm_unpinnable_folio() Hyesoo Yu
[not found] ` <CGME20250605033432epcas2p4c024a9d05246b18c217f3562b3f53551@epcas2p4.samsung.com>
2025-06-05 3:32 ` Hyesoo Yu [this message]
2025-06-05 3:43 ` [PATCH v2 2/2] mm: gup: avoid CMA page pinning by retrying migration if no migratable page Andrew Morton
2025-06-05 5:11 ` Hyesoo Yu
2025-06-05 5:24 ` Andrew Morton
2025-06-05 6:59 ` Hyesoo Yu
2025-06-05 7:39 ` David Hildenbrand
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250605033210.3184521-3-hyesoo.yu@samsung.com \
--to=hyesoo.yu@samsung.com \
--cc=akpm@linux-foundation.org \
--cc=david@redhat.com \
--cc=jaewon31.kim@gmail.com \
--cc=janghyuck.kim@samsung.com \
--cc=jgg@ziepe.ca \
--cc=jhubbard@nvidia.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=peterx@redhat.com \
--cc=zhaoyang.huang@unisoc.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox