[PATCH v5 0/3] mm/zswap: shrink zswap_entry via a pool id

From: Jianyue Wu

Date: Fri Sep 04 2026 - 10:18:58 EST


Every stored page has a struct zswap_entry, so its size is pure per-page
overhead. On 64-bit it is currently 56 bytes, of which 8 bytes are a
pointer to the owning zswap_pool.

Only a handful of pools are ever live: a new pool is created only when
the compressor is (re)set, and pools are reused across compressor
switches. That makes a per-entry pool pointer more expensive than it
needs to be, and the RCU list that currently tracks pools is more
machinery than this needs once each pool already has a stable id.

This series:

1. Releases retired pools with queue_rcu_work() instead of a worker
calling synchronize_rcu(), so the release worker no longer blocks
on an RCU grace period.
2. Replaces the zswap_pools list with an allocating xarray
(XA_FLAGS_ALLOC1 | XA_FLAGS_LOCK_BH) and a separate RCU-protected
current-pool pointer, giving each pool a stable small id. Ids
start at 1. The reserved id 0 is never allocated, so looking it
up resolves to NULL. The table grows as needed up to 255 live
pools (u8 pool_idx), not a fixed slot array.
3. Stores that u8 pool id in each zswap_entry instead of the pool
pointer. The u8 fits in padding after the bool referenced field,
so the entry shrinks from 56 to 48 bytes on 64-bit (~2MiB of
metadata saved per 1GiB of data held in zswap).

Runtime compressor switching is preserved. Pool ids are bounded to
1..255 because struct zswap_entry stores the id in a u8. The cap
counts every id still in the xarray, including a killed pool that still
has entries. Ids are reused when a pool is erased. Switching back to
a compressor that still has a pool in the xarray resurrects it rather
than allocating a new id. If all usable ids are full, creating a pool
for another compressor fails and the compressor switch is rejected.

On 64-bit, struct zswap_entry is 56 -> 48 bytes, which fits 73 -> 85
objects in a 4K slab.

Benchmark (x86_64, compressor=lzo, MADV_PAGEOUT store + fault-in load):

- e2e store+load median latency: no measurable regression vs baseline
at matched stored_delta

Each store, free, and decompress looks up the pool with xa_load()
instead of following a pointer. With only a handful of live pools the
xarray walk is short.

Testing
=======

- Boot with DEBUG_ATOMIC_SLEEP + lockdep/PROVE_RCU + KASAN:
zswap store/load, shrinker writeback, and compressor switch
(retire, then switch back to resurrect) pass

This series is based on akpm/mm-unstable as of 2026-09-04
(20cab322c95c).

To: Johannes Weiner <hannes@xxxxxxxxxxx>
To: Yosry Ahmed <yosry@xxxxxxxxxx>
To: Nhat Pham <nphamcs@xxxxxxxxx>
To: Chengming Zhou <chengming.zhou@xxxxxxxxx>
To: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
Cc: Chris Li <chrisl@xxxxxxxxxx>
Cc: linux-mm@xxxxxxxxx
Cc: linux-kernel@xxxxxxxxxxxxxxx
Signed-off-by: Jianyue Wu <wujianyue000@xxxxxxxxx>

Changes since RFC v4:
- Replace the RCU pool list with an allocating xarray
(XA_FLAGS_ALLOC1 | XA_FLAGS_LOCK_BH) and a separate RCU-protected
current-pool pointer.
- Resolve entry->pool_idx with xa_load() under rcu_read_lock().
- Write pool_idx before the entry is stored in the swap tree, so a
lookup cannot see a stale pool_idx left over from slab reuse.
- Retire pools with queue_rcu_work() on system_percpu_wq.
- Drop the RFC tag.

Link: https://lore.kernel.org/all/20260830114731.8322-1-wujianyue000@xxxxxxxxx/
Link: https://lore.kernel.org/all/20260815-shrink_zswap_entry_0815_v2-v3-3-0171bd86a667@xxxxxxxxx/
Link: https://lore.kernel.org/all/20260731-shrink_zswap_entry_v2-0-0-v2-0-e72083aa8734@xxxxxxxxx/
Link: https://lore.kernel.org/all/20260726-shrink_zswap_entry_v1-0-0-v1-1-30957e4d0cb6@xxxxxxxxx/

---
Jianyue Wu (3):
mm/zswap: release retired pools via queue_rcu_work() instead of
synchronize_rcu()
mm/zswap: replace the zswap_pools list with an allocating xarray
mm/zswap: reference the pool by id to shrink struct zswap_entry

mm/zswap.c | 144 ++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 97 insertions(+), 47 deletions(-)


base-commit: 20cab322c95cea0327215bb81a05df69336032dd
--
2.43.0