[PATCH 2/2] mm: vmscan: stop scanning ineligible folios after max_nr_skipped

From: Wupeng Ma

Date: Tue Aug 11 2026 - 03:38:39 EST


When reclaiming for a lower zone, isolate_lru_folios() accounts folios
from higher zones as skipped and, once max_nr_skipped hits
SWAP_CLUSTER_MAX_SKIPPED, force-isolates the remaining ineligible folios
to keep the loop from spinning on the skipped ones. Those folios are
reclaimed even though they can never satisfy the current allocation, so
nr_reclaimed is inflated into a false progress that keeps resetting
no_progress_loops in should_reclaim_retry() and delays the OOM.

Stop scanning once max_nr_skipped is reached instead of force-isolating
the ineligible folios. The skipped folios are already accounted in
total_scan, so shrink_lruvec() can charge the overshoot against its scan
budget (see the previous commit) and will not rescan them.

Fixes: 1c7b17cf0594 ("mm/vmscan: fix hard LOCKUP in function isolate_lru_folios")
Signed-off-by: Wupeng Ma <mawupeng1@xxxxxxxxxx>
---
mm/vmscan.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/mm/vmscan.c b/mm/vmscan.c
index 147e74f9732d5..ac3237a58cb29 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1704,12 +1704,20 @@ static unsigned long isolate_lru_folios(unsigned long nr_to_scan,
nr_pages = folio_nr_pages(folio);
total_scan += nr_pages;

- /* Using max_nr_skipped to prevent hard LOCKUP*/
- if (max_nr_skipped < SWAP_CLUSTER_MAX_SKIPPED &&
- (folio_zonenum(folio) > sc->reclaim_idx)) {
+ /*
+ * Using max_nr_skipped to prevent hard LOCKUP.
+ * Once the cap is hit, stop rather than force-isolating:
+ * reclaiming ineligible folios only inflates nr_reclaimed
+ * into a false progress.
+ */
+ if (folio_zonenum(folio) > sc->reclaim_idx) {
nr_skipped[folio_zonenum(folio)] += nr_pages;
- move_to = &folios_skipped;
max_nr_skipped++;
+ if (max_nr_skipped >= SWAP_CLUSTER_MAX_SKIPPED) {
+ list_move(&folio->lru, &folios_skipped);
+ break;
+ }
+ move_to = &folios_skipped;
goto move;
}

--
2.43.0