Re: [PATCH v3 00/14] mm, swap: extendable swap devices (xswap)
From: Nhat Pham
Date: Thu Sep 17 2026 - 20:13:50 EST
On Wed, Sep 16, 2026 at 3:19 AM Baoquan He <hebaoquan@xxxxxxxxxx> wrote:
>
> xswap is a swap device with no backing storage. Swapped-out pages live
> in zswap. Its cluster_info[] array lives in a VM_SPARSE vmalloc area,
> and the area is grown and shrunk on demand as swap usage changes.
>
> The problem being solved is the static size of compressed swap. Both
> zram and zswap need the size fixed in advance, and neither gives memory
> back when the workload shrinks. The solution should be a device whose
> size can scale up/down as per usage. xswap does that by mapping the
> metadata lazily instead of reserving it for the whole range.
>
> Design
> ------
> - si->cluster_info[] stays a plain array. Access is still
> &si->cluster_info[offset / SWAPFILE_CLUSTER]: no per-access branch, no
> RCU discipline, no tear-down state machine, no NULL return.
> - Only an initial chunk is mapped at creation. The rest of the address
> space is reserved, not allocated, so an idle device costs nothing.
> - Growth is driven by allocation. When no free cluster is left and the
> address space has room, the next chunk is mapped and added to the free
> list. No userspace involvement.
> - Shrink is driven by frees. The free tail is scanned, and whole chunks
> are unmapped once the mapped range is at most half in use and several
> chunks can go. One chunk is left mapped as slack, so the next
> allocation does not map it straight back. A ceiling lowered below the
> mapped range skips the half-in-use rule and is enforced at once.
>
> Size
> ----
> A device starts at 1xRAM, rounded down to the cluster. That costs
> nothing, because the mapping is lazy. The underlying address space is
> 2xRAM. An optional per-device cap,
> /sys/kernel/mm/xswap/type<N>/limit, lets an admin lower the ceiling;
> the excess is unmapped right away. Grow and shrink both work without
> it. Creating a device requires zswap.
>
> Interface
> ---------
> /sys/kernel/mm/xswap/create write an optional priority
> /sys/kernel/mm/xswap/destroy write a swap type
> /sys/kernel/mm/xswap/type<N>/limit read/write, in pages
> The device shows up in /proc/swaps as xswap<N>.
>
> Note
> ----
> Writeback, rmap lookup, etc. are consumers of this base. I have a
> writeback prototype on top of this base and will post it as a reference.
Thanks for posting v3.
I spent a while building the other half of what I want out of this on
top of your series, to see how much work is needed if we are to expand
from xswap to cover the vswap use case.
It is actually way more work than I anticipated. And a lot of it is
because of the way you indiscriminately apply the full swap device
model to xswap, without careful consideration of actual use cases.
Johannes has already discussed one piece of that, the sizing knob [1],
so here I would like to expand on other design and interface choices.
First, in terms of priority, an xswap device has to be preferred over
disk swap. This is already zswap's model, as it is the *only* coherent
swap tiering scheme. Exposing priority selection to userspace just
invites misconfiguration - what if a user accidentally sets physical
swap to be preferred over zswap?
Next, regarding the ability to create multiple xswap devices:
With at most one virtual device, there is no selection problem to solve
at all: vswap's entire device-selection policy is reduced to two
branches: if vswap is possible, go for it; otherwise try physical swap
device. No need to think about policy to select which virtual device to
allocate. No need to track virtual vs physical devices to select the
right class for allocation, as you can just put the virtual device in a
pointer, and off the avail list (which is only used for physical
devices). These suddenly matter when you add multiple xswap devices.
And for what purpose? This has never been properly justified to me.
On the flip side, there are cases where your treatment of the xswap
device as "just an ordinary swap device" actually breaks *existing*
deployment, and makes several code paths more complicated.
For instance, at allocation time, cgroups that disable zswap might get
an xswap slot. At swap_writeout() time, it is *stuck* - we already do
the unmapping step, so we cannot reclaim the page. Ironically a
physical swapfile backend could have bailed you out here, but you have
not implemented it yet :)
The other way you can get around it is checking if the folio being
reclaimed belongs to a cgroup that allows for disk swap or zswap, and
bypass xswap/vswap if so. But that brings me to my next point: since
you just treat xswap/vswap as a normal swap device and share all the
allocation structures and logic, making such a selection becomes way
more complicated code-wise, and less efficient at runtime too (since
the per-cpu cache of clusters for allocation is shared for all swap
devices in your code).
As of this version, it not only does not work for the writeback use
case. It cannot even work in deployments where some workloads (cgroup)
select zswap, whereas others select disk swap. It can only work if you
intend to have a single class of device - either virtual/xswap or disk
swap - but not both.
There are more, but I think these already illustrate my points.
The root cause of all of these is that xswap reuses the swap device full
machinery and interface, even where it does not make sense, or where it
exposes a policy decision the kernel should be making (priority, size,
number of instances).
vswap's interface came from the other end: what has to be true for
zswap to be an independent AND co-existing tier, and what needs
userspace's input for that to work. The answer was close to nothing, which
is why close to nothing is exposed, and why there is so little to get wrong
inside it. It also simplifies the logic in many places.
Constraint liberates; liberty constrains.
So let me flip it on its head. What if we keep the interface I already
have, and use your data structure instead? I tried that too [2], and it
was significantly easier, because it is just a data structure change,
without having to accomodate for the full interface of swap device.
Happy to expand on the prototype if necessary.
Thanks,
Nhat
[1] https://lore.kernel.org/all/aqLi6cIjD2wJwk0B@xxxxxxxxxxx/
[2] https://lore.kernel.org/all/20260910232704.3364879-1-nphamcs@xxxxxxxxx/