Re: [RFC PATCH 00/10] mm/swap: ghost swapfile with backend switching via Redirect entries

From: Nhat Pham

Date: Tue Jul 07 2026 - 17:23:56 EST


On Tue, Jul 7, 2026 at 1:26 AM Baoquan He <baoquan.he@xxxxxxxxx> wrote:
>
> This series introduces a virtual "ghost" swapfile that can be backed
> by multiple physical swap devices, switching between them at runtime
> using a new "Redirect" swap table entry type.
>
> Motivation
> ----------
> Physical swap devices have fixed, large sizes but a machine may only
> need a fraction at any given time. Ghost swap decouples the logical
> swap capacity from physical swap allocation: it presents a large
> virtual swap device to userspace while lazily mapping slots to
> physical devices only when data must leave zswap (writeback). This
> enables overcommit of swap capacity without wasting physical disk
> space, and allows the ghost device to grow dynamically at runtime.
>
> Ghost swapfile characteristics
> --------------------------------
> Ghost swap decouples logical swap capacity from physical swap allocation.
> Key properties:
>
> - No backing store required. A ghost swap device can operate purely
> as a zswap container — compressed pages stay in the zswap pool without
> ever touching a physical swap device. No physical swap device needs
> to be attached.
>
> - Optional physical backing. One or more physical swap devices can be
> swapon'd alongside the ghost device, acting as writeback targets when
> the zswap pool needs to evict cold pages. The Redirect entry in the
> ghost swap table links each evicted slot to its physical destination.
>
> - Dynamic size growth. The ghost device can be extended at runtime via

We don't want to put additional operational burden on users. Besides,
expecting userspace to react to swap space being filled, especially
under memory pressure (at which point userspace processes might be
stalling already), is tricky.

This is especially bad when redirection entry still eats up space in
the upper level (ghost zswap) swapfile. You will run out of zswap
space really fast under concurrent zswap store and zswap writeback.

> sysfs, up to a current maximum of 1TB. This is implemented through
> lazy vmalloc: a sparse 64MB virtual address space is reserved at
> swapon time to cover the full 1TB range, but physical pages for

This range seems a bit small, especially from something essentially fixed.

> cluster_info[] structures are allocated only on demand as the device
> grows. The cluster_info pointer never changes, so all existing
> accessors (__swap_offset_to_cluster, cluster_index) work unchanged.
>
> - sysfs control. Each ghost device exposes attributes under
> /sys/kernel/mm/ghost_swap/ghost_<N>/:
> path (RO) — backing device name
> max (RW) — current max pages; writing a larger value triggers
> swap_ghost_extend_max()
>
> Design overview
> ---------------
> A swap table slot can now hold a Redirect entry:
>
> Redirect: |----- physical swp_entry_t -----|101|
>
> This stores a plain swp_entry_t pointing to a slot on a real (physical)
> swap device. The low 3-bit mark (0b101) distinguishes it from Pointer
> (0b100), PFN (0b10), Shadow (0b1), and NULL (0) entries.
>
> The lifecycle is:
>
> 1. swapon a ghost device — reserves sparse vmalloc area (64MB virtual)
> and physically backs only the initial range. The device starts with
> no physical backing store: pages swapped out go to zswap, and zswap
> pool evictions go to any concurrently attached physical device.

If you think this data structure is superior to the xarray for dynamic
swap address, it's a fairly simple change on top of what I had in the
virtual swap RFC, no?

It can be grafted on top of what I had in a subsequent patch, or
squashed into my first patch. If you have concerns with me
implementing your idea here, I'd take your code if it proves to be
superior.

>
> 2. zswap writeback from ghost: when the zswap pool needs to evict,
> zswap_writeback_ghost() allocates a physical slot from any real
> swap device, writes the data there, and plants a Redirect entry
> in the ghost's swap table pointing to the physical slot.

What if user swapoff the physical swapfile, whose slot is backing a
redirection entry of a ghost swapfile, rather than a PTE. Has this
been handled yet?

Similarly, say the physical swapfile is full, and you attempt to
reclaim a physical swap slot that is swap-cache-only (swap count = 0).
Say this physical swap slot was allocated from a previous zswap
writeback attempt, i.e it has a redirection entry in the ghost zswap
swapfile associated with it. Did we handle it somehow?

My apologies if I missed it somehow.

>
> 3. Swap-in from ghost: swap_read_folio() detects the ghost device
> (SWP_GHOST), resolves the Redirect to the physical swp_entry_t,
> and forwards the read I/O to the physical device.
>
> 4. When the swap cache folio is removed, the Redirect entry is restored
> from an xarray (redirect_xa) that persists the mapping, so
> subsequent reads still find the physical backing.
>
> 5. When the physical slot is freed, the ghost slot is also freed,
> cascading through swap_range_free().

I don't get how *any* of this is simpler from what I had. If anything,
it's more complicated. With a vswap device, you just allocate a
physical swap slot (which you also did), change the backend, submit
the IO (which you also did), and that's it. No need to juggle this
redirect_xa entry. What does this redirect_xa buy us?

Not to mention now it entagles generic swap logic into
backend-specific code, unnecessarily. And we have more state in the
state machine to consider: With a generic vswap device, vswap -> disk
swap directly is the same state as vswap -> written back zswap entry.
With this zswap ghost swapfile design, you have to treat the latter
separately, as there is a redirection entry involved, which means
concurrent swap operations interact with it.

So it's more complicated, and achieve less - this is specific to
zswap, whereas what I provide is something generic to swap
infrastructure, which can be extended for future backends. I would
understand if it resulted in less overhead (which was the argument for
my pre-swap-table vswap design), but this seems like it's just virtual
swap, with similar space overhead (technically a bit worse since you
added redirect_xa xarray to physical swap cluster too), and with more
complications?

>
> Note:
> ------
> Ghost swapfile is a proof of concept. Compared with the other patchset:
> [RFC PATCH v2 0/7] mm, swap: Virtual Swap Space (Swap Table Edition),
> it explores a different approach to implementing virtual swap on top of
> the existing swap table infrastructure, with a simpler implementation.

You neglected to mention that this "simpler" implementation lacks a
lot of design choices. Just on top of my head:

1. Certain optimizations for cases when vswap points to disk swap.

2. No reverse mapping, or at least some mechanisms to handle the case
where you have to go from physical swap slots to the upper layer.

3. Charging behavior difference, and deduplication of metadata when we
have multiple swap levels. (In fact, you seem to be double charging a
writtenback entry here towards the swap counter, not just duplicating
the metadata space)

4. Infrastructure to make sure allocation from this swap device and
allocation from the backing swap device does not invalidate each
other's per-cpu allocation cache. You seem to just go for the slow
path with alloc_phys_swap_slot() for zswap writeback?

It's fine to disagree with any or all of these design choices of mine
- I'm receptive to discussion. But it's misleading to say you have a
simpler design here, IMHO. My design choices resulted from multiple
thoughtful iterations (a lot of them could be found in my
pre-swap-table version of vswap) and real production pains.