shrink_folio_list() contains a self-contained pageout() dispatch state machine. Extract it into pageout_one() to reduce the size of shrink_folio_list() and make the pageout step independently readable. No functional change. Signed-off-by: Zhang Peng --- mm/vmscan.c | 107 ++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 65 insertions(+), 42 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index b31f67801836..456d38eb172c 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1161,8 +1161,68 @@ static bool folio_free(struct folio *folio, struct folio_batch *free_folios, return true; } +static bool pageout_one(struct folio *folio, + struct folio_batch *free_folios, + struct scan_control *sc, struct reclaim_stat *stat, + struct swap_iocb **plug, struct list_head *folio_list, + unsigned int *nr_reclaimed) +{ + struct address_space *mapping = folio_mapping(folio); + unsigned int nr_pages = folio_nr_pages(folio); + + switch (pageout(folio, mapping, plug, folio_list)) { + case PAGE_ACTIVATE: + /* + * If shmem folio is split when writeback to swap, + * the tail pages will make their own pass through + * this function and be accounted then. + */ + if (nr_pages > 1 && !folio_test_large(folio)) { + sc->nr_scanned -= (nr_pages - 1); + nr_pages = 1; + } + folio_activate_locked(folio, stat, nr_pages); + folio_unlock(folio); + return false; + case PAGE_KEEP: + folio_unlock(folio); + return false; + case PAGE_SUCCESS: + if (nr_pages > 1 && !folio_test_large(folio)) { + sc->nr_scanned -= (nr_pages - 1); + nr_pages = 1; + } + stat->nr_pageout += nr_pages; + + if (folio_test_writeback(folio)) + return false; + if (folio_test_dirty(folio)) + return false; + + /* + * A synchronous write - probably a ramdisk. Go + * ahead and try to reclaim the folio. + */ + if (!folio_trylock(folio)) + return false; + if (folio_test_dirty(folio) || + folio_test_writeback(folio)) { + folio_unlock(folio); + return false; + } + mapping = folio_mapping(folio); + fallthrough; + case PAGE_CLEAN: + ; /* try to free the folio below */ + } + if (folio_free(folio, free_folios, sc, stat, nr_reclaimed)) + return true; + folio_unlock(folio); + return false; +} + /* - * shrink_folio_list() returns the number of reclaimed pages + * Reclaimed folios are counted in the return value. */ static unsigned int shrink_folio_list(struct list_head *folio_list, struct pglist_data *pgdat, struct scan_control *sc, @@ -1499,53 +1559,16 @@ static unsigned int shrink_folio_list(struct list_head *folio_list, goto keep_locked; if (!sc->may_writepage) goto keep_locked; - /* * Folio is dirty. Flush the TLB if a writable entry * potentially exists to avoid CPU writes after I/O * starts and then write it out here. */ try_to_unmap_flush_dirty(); - switch (pageout(folio, mapping, &plug, folio_list)) { - case PAGE_KEEP: - goto keep_locked; - case PAGE_ACTIVATE: - /* - * If shmem folio is split when writeback to swap, - * the tail pages will make their own pass through - * this function and be accounted then. - */ - if (nr_pages > 1 && !folio_test_large(folio)) { - sc->nr_scanned -= (nr_pages - 1); - nr_pages = 1; - } - goto activate_locked; - case PAGE_SUCCESS: - if (nr_pages > 1 && !folio_test_large(folio)) { - sc->nr_scanned -= (nr_pages - 1); - nr_pages = 1; - } - stat->nr_pageout += nr_pages; - - if (folio_test_writeback(folio)) - goto keep; - if (folio_test_dirty(folio)) - goto keep; - - /* - * A synchronous write - probably a ramdisk. Go - * ahead and try to reclaim the folio. - */ - if (!folio_trylock(folio)) - goto keep; - if (folio_test_dirty(folio) || - folio_test_writeback(folio)) - goto keep_locked; - mapping = folio_mapping(folio); - fallthrough; - case PAGE_CLEAN: - ; /* try to free the folio below */ - } + if (!pageout_one(folio, &free_folios, sc, stat, &plug, + folio_list, &nr_reclaimed)) + goto keep; + continue; } if (!folio_free(folio, &free_folios, sc, stat, &nr_reclaimed)) -- 2.43.7