[PATCH v2 11/26] mm/fbatch: remove migration's PAGE_WAS_MLOCKED lru_add_drain()
From: Hugh Dickins
Date: Wed Sep 09 2026 - 06:33:30 EST
A welcome side-effect of mm/mlock.c's mod_mlock_count() succeeding on
folios on the per-cpu lru_add fbatch, is that migrate_folio_move() no
longer has to lru_add_drain() before remove_migration_ptes() restores
a PAGE_WAS_MLOCKED mlock_count: so remove PAGE_WAS_MLOCKED altogether.
(Re the "We would like to do something similar for the old page, when
unsuccessful" comment above it: that may be easier now, but involve
some rearrangement: not researched, so just leave the comment as is.)
However: it was uncommon before, for isolate_migratepages_block() to
meet a folio on LRU, with suitable refcount, marked mlocked but not yet
unevictable: so that got missed when sysctl_compact_unevictable_allowed
should not allow it. But now it's a more common case, so check if the
folio will become unevictable, by using !folio_evictable() instead.
That is more expensive than testing mlocked and unevictable bits: but
it is consistent with the decision made once the fbatch gets drained,
and is_inaccessible further down depends on the right is_unevictable.
Optimize those checks better if they show a regression in practice.
Signed-off-by: Hugh Dickins <hughd@xxxxxxxxxx>
---
mm/compaction.c | 2 +-
mm/migrate.c | 8 +-------
2 files changed, 2 insertions(+), 8 deletions(-)
diff --git a/mm/compaction.c b/mm/compaction.c
index 9e045a90ba21..1290b9170cb2 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -1113,7 +1113,7 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,
if (!folio_test_lru(folio))
goto isolate_fail_put;
- is_unevictable = folio_test_unevictable(folio);
+ is_unevictable = !folio_evictable(folio);
/* Compaction might skip unevictable pages but CMA takes them */
if (!(mode & ISOLATE_UNEVICTABLE) && is_unevictable)
diff --git a/mm/migrate.c b/mm/migrate.c
index 1939d6ed19c9..364015cbef33 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -1147,8 +1147,7 @@ static int move_to_new_folio(struct folio *dst, struct folio *src,
*/
enum {
FOLIO_WAS_MAPPED = BIT(0),
- FOLIO_WAS_MLOCKED = BIT(1),
- FOLIO_OLD_STATES = FOLIO_WAS_MAPPED | FOLIO_WAS_MLOCKED,
+ FOLIO_OLD_STATES = FOLIO_WAS_MAPPED,
};
static void __migrate_folio_record(struct folio *dst,
@@ -1258,8 +1257,6 @@ static int migrate_folio_unmap(new_folio_t get_new_folio,
folio_lock(src);
}
locked = true;
- if (folio_test_mlocked(src))
- old_folio_state |= FOLIO_WAS_MLOCKED;
if (folio_test_writeback(src)) {
/*
@@ -1410,9 +1407,6 @@ static int migrate_folio_move(free_folio_t put_new_folio, unsigned long private,
* isolated from the unevictable LRU: but this case is the easiest.
*/
folio_add_lru(dst);
- if (old_folio_state & FOLIO_WAS_MLOCKED)
- lru_add_drain();
-
if (old_folio_state & FOLIO_WAS_MAPPED)
remove_migration_ptes(src, dst, 0);
--
2.51.0