Re: [PATCH v3 2/2] mm/swap: scan by cluster in find_next_to_unuse()

From: Kairui Song

Date: Fri Aug 07 2026 - 03:34:13 EST


On Fri, Aug 7, 2026 at 3:47 AM Youngjun Park <youngjun.park@xxxxxxx> wrote:
>
> find_next_to_unuse() walks every offset from 0 to si->max, and swapoff
> restarts that walk on each retry, so the cost scales with the size of
> the device rather than with the few slots the shmem and mmlist passes
> could not free. It has caused stalls before.
>
> The flat walk predates the swap table. Slot state now lives in a per
> cluster table, and wait_for_allocation() stops all allocation before
> try_to_unuse() runs, so a cluster that holds no slot in use stays that
> way. Skip such a cluster instead of reading all of its entries.
>
> Commit dc644a073769 ("mm: add three more cond_resched() in swapoff")
> answered those stalls with a cond_resched() every 256 offsets. A walk
> bounded by one cluster no longer needs that counter. The loop now runs
> at most SWAPFILE_CLUSTER times before it returns or reschedules, the
> same bound swap_reclaim_full_clusters() already scans between
> cond_resched() calls.
>
> The scan end is clamped to si->max, so the walk stops there rather than
> running into the masked tail of the last cluster.
>
> ci->count is read without ci->lock, so READ_ONCE() marks the read for
> KCSAN. Allocation is already stopped, so the count can only drop, and a
> slot stops being counted only after its folio has left the swap cache.
> An empty cluster therefore holds nothing for try_to_unuse() to act on.
>
> Signed-off-by: Youngjun Park <youngjun.park@xxxxxxx>
> Reviewed-by: Barry Song <baohua@xxxxxxxxxx>
> ---
> mm/swapfile.c | 43 ++++++++++++++++++++++++++++++-------------
> 1 file changed, 30 insertions(+), 13 deletions(-)
>

Looks good.

Acked-by: Kairui Song <kasong@xxxxxxxxxxx>