On Sat, Feb 22, 2025 at 3:12 PM Kemeng Shi <shikemeng@xxxxxxxxxxxxxxx> wrote: > > If allocation is racy with swapoff, we may call free_cluster for cluster > already in free list and trigger bug on as following: Maybe capitalize this "bug on" to BUG_ON to be consistent with the title. > Allocation Swapoff > cluster_alloc_swap_entry > ... > /* may get a free cluster with offset */ > offset = xxx; > if (offset) > ci = lock_cluster(si, offset); > > ... > del_from_avail_list(p, true); > si->flags &= ~SWP_WRITEOK; > > alloc_swap_scan_cluster(si, ci, ...) > ... > /* failed to alloc entry from free entry */ > if (!cluster_alloc_range(...)) > break; > ... > /* add back a free cluster */ > relocate_cluster(si, ci); > if (!ci->count) > free_cluster(si, ci); > VM_BUG_ON(ci->flags == CLUSTER_FLAG_FREE); > > Despite bug_on could be triggered, call free_cluster() for free cluster > only move cluster to tail of list and should be fine. > > Check cluster is not free before calling free_cluster() in > relocate_cluster() to avoid bug_on. Same here. > > Fixes: 3b644773eefda ("mm, swap: reduce contention on device lock") > Signed-off-by: Kemeng Shi <shikemeng@xxxxxxxxxxxxxxx> > --- > mm/swapfile.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/mm/swapfile.c b/mm/swapfile.c > index 425126c0a07d..fc45b9d56639 100644 > --- a/mm/swapfile.c > +++ b/mm/swapfile.c > @@ -653,7 +653,8 @@ static void relocate_cluster(struct swap_info_struct *si, > return; > > if (!ci->count) { > - free_cluster(si, ci); > + if (ci->flags != CLUSTER_FLAG_FREE) > + free_cluster(si, ci); > } else if (ci->count != SWAPFILE_CLUSTER) { > if (ci->flags != CLUSTER_FLAG_FRAG) > move_cluster(si, ci, &si->frag_clusters[ci->order], > -- > 2.30.0 Thanks, other than minor commit message issue: Reviewed-by: Kairui Song <kasong@xxxxxxxxxxx>