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 --- 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