Re: [PATCH] mm, swap: revalidate populated clusters before scanning
From: Kairui Song
Date: Tue Oct 20 2026 - 13:58:36 EST
On Tue, Oct 20, 2026 at 1:41 AM Nhat Pham <nphamcs@xxxxxxxxx> wrote:
>
> swap_cluster_populate() can publish a cluster's table with the cluster
> lock dropped. A cached allocator can use and empty it before the
> populating allocator reacquires the lock. The resumed scan can then
> dereference a NULL table.
>
> For example, CPU1 can retain a cached cluster offset on an SSD with
> per-page discard disabled:
>
> CPU0 CPU1
> ---- ----
> swap_cluster_populate()
> swap_cluster_alloc_table() fails
> spin_unlock(&ci->lock)
> local_unlock(&percpu_swap_cluster.lock)
> swap_cluster_alloc_table()
> rcu_assign_pointer(ci->table, table)
Nice catch!
I think the real problem is that it turns out calling
swap_cluster_alloc_table() without holding ci lock is bad idea... I
think this patch still leaves some other call site too?
We may instead add a "bool locked" to swap_cluster_alloc_table, and
let it lock the ci first before it does any assign (not the alloc) if
the allocation context is not locked. That is, keep the
sleep-allocated tables private until swap_cluster_populate()
reacquires local/global/ci, then install them under ci->lock,
something like pre-cdd77f84d966, always assign it atomically.
That should also cover the problem reported by Kemeng a few weeks
earlier too, and prevent further misuse. My Bad on that change :P