Skip to content

Commit 57d910c

Browse files
Kemeng Shiakpm00
authored andcommitted
mm, swap: avoid BUG_ON in relocate_cluster()
If allocation is racy with swapoff, we may call free_cluster for cluster already in free list and trigger BUG_ON() as following: 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); To prevent the BUG_ON(), call free_cluster() for free cluster to move the cluster to tail of list. Check cluster is not free before calling free_cluster() in relocate_cluster() to avoid BUG_ON(). Link: https://lkml.kernel.org/r/20250222160850.505274-4-shikemeng@huaweicloud.com Fixes: 3b64477 ("mm, swap: reduce contention on device lock") Signed-off-by: Kemeng Shi <shikemeng@huaweicloud.com> Reviewed-by: Kairui Song <kasong@tencent.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
1 parent 7a2e7ae commit 57d910c

File tree

1 file changed

+2
-1
lines changed

1 file changed

+2
-1
lines changed

mm/swapfile.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,8 @@ static void relocate_cluster(struct swap_info_struct *si,
653653
return;
654654

655655
if (!ci->count) {
656-
free_cluster(si, ci);
656+
if (ci->flags != CLUSTER_FLAG_FREE)
657+
free_cluster(si, ci);
657658
} else if (ci->count != SWAPFILE_CLUSTER) {
658659
if (ci->flags != CLUSTER_FLAG_FRAG)
659660
move_cluster(si, ci, &si->frag_clusters[ci->order],

0 commit comments

Comments
 (0)