Re: [PATCH v3 2/2] mm/swap: scan by cluster in find_next_to_unuse()
Kairui Song <[email protected]>
| Newsgroups | gmane.linux.kernel,gmane.linux.kernel.mm |
|---|---|
| Message-ID | <CAMgjq7DuLQ93ieakdh6P_rxjeDZS2nq0uaJWPJmw=28LujMOxg@mail.gmail.com> |
On Fri, Aug 7, 2026 at 3:47 AM Youngjun Park <[email protected]> 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 <[email protected]> > Reviewed-by: Barry Song <[email protected]> > --- > mm/swapfile.c | 43 ++++++++++++++++++++++++++++++------------- > 1 file changed, 30 insertions(+), 13 deletions(-) > Looks good. Acked-by: Kairui Song <[email protected]>