summaryrefslogtreecommitdiff
path: root/mm/gup.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/gup.c')
-rw-r--r--mm/gup.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/mm/gup.c b/mm/gup.c
index 0692119b7904..bde05664fe9a 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -2273,6 +2273,7 @@ static unsigned long collect_longterm_unpinnable_folios(
for (folio = pofs_get_folio(pofs, i); folio;
folio = pofs_next_folio(folio, pofs, &i)) {
+ const int pin_refs = folio_has_pincount(folio) ? 1 : GUP_PIN_COUNTING_BIAS;
if (folio_is_longterm_pinnable(folio))
continue;
@@ -2287,15 +2288,20 @@ static unsigned long collect_longterm_unpinnable_folios(
continue;
}
+ /*
+ * We drain not only to make the folio_isolate_lru() succeed,
+ * but also to remove any other folio references from LRU
+ * caches.
+ */
if (drained == 0 && folio_may_be_lru_cached(folio) &&
folio_ref_count(folio) !=
- folio_expected_ref_count(folio) + 1) {
+ folio_expected_ref_count(folio) + pin_refs) {
lru_add_drain();
drained = 1;
}
if (drained == 1 && folio_may_be_lru_cached(folio) &&
folio_ref_count(folio) !=
- folio_expected_ref_count(folio) + 1) {
+ folio_expected_ref_count(folio) + pin_refs) {
lru_add_drain_all();
drained = 2;
}