From: Jianyue Wu <wujianyue000@gmail.com>
To: Johannes Weiner <hannes@cmpxchg.org>,
Yosry Ahmed <yosry@kernel.org>, Nhat Pham <nphamcs@gmail.com>,
Chengming Zhou <chengming.zhou@linux.dev>,
Andrew Morton <akpm@linux-foundation.org>
Cc: Chris Li <chrisl@kernel.org>,
linux-mm@kvack.org, linux-kernel@vger.kernel.org
Subject: [PATCH v5 0/3] mm/zswap: shrink zswap_entry via a pool id
Date: Fri, 4 Sep 2026 21:24:53 +0800 [thread overview]
Message-ID: <cover.1788528216.git.wujianyue000@gmail.com> (raw)
In-Reply-To: <20260830114731.8322-1-wujianyue000@gmail.com>
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@cmpxchg.org>
To: Yosry Ahmed <yosry@kernel.org>
To: Nhat Pham <nphamcs@gmail.com>
To: Chengming Zhou <chengming.zhou@linux.dev>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: Chris Li <chrisl@kernel.org>
Cc: linux-mm@kvack.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Jianyue Wu <wujianyue000@gmail.com>
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@gmail.com/
Link: https://lore.kernel.org/all/20260815-shrink_zswap_entry_0815_v2-v3-3-0171bd86a667@gmail.com/
Link: https://lore.kernel.org/all/20260731-shrink_zswap_entry_v2-0-0-v2-0-e72083aa8734@gmail.com/
Link: https://lore.kernel.org/all/20260726-shrink_zswap_entry_v1-0-0-v1-1-30957e4d0cb6@gmail.com/
---
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
next prev parent reply other threads:[~2026-09-04 13:25 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-30 11:47 [RFC PATCH v4 0/3] mm/zswap: shrink zswap_entry via a fixed pool index Jianyue Wu
2026-08-30 11:47 ` [RFC PATCH v4 1/3] mm/zswap: release retired pools via queue_rcu_work() instead of synchronize_rcu() Jianyue Wu
2026-08-31 15:20 ` Yosry Ahmed
2026-09-01 14:33 ` Jianyue Wu
2026-09-01 15:38 ` Johannes Weiner
2026-09-02 0:53 ` Jianyue Wu
2026-08-30 11:47 ` [RFC PATCH v4 2/3] mm/zswap: replace the zswap_pools list with a fixed pools array Jianyue Wu
2026-08-31 15:28 ` Yosry Ahmed
2026-09-01 16:13 ` Johannes Weiner
2026-09-02 0:50 ` Jianyue Wu
2026-09-03 12:59 ` Jianyue Wu
2026-08-30 11:47 ` [RFC PATCH v4 3/3] mm/zswap: reference the pool by index to shrink struct zswap_entry Jianyue Wu
2026-08-31 15:30 ` Yosry Ahmed
2026-09-04 13:24 ` Jianyue Wu [this message]
2026-09-04 13:24 ` [PATCH v5 1/3] mm/zswap: release retired pools via queue_rcu_work() instead of synchronize_rcu() Jianyue Wu
2026-09-04 13:24 ` [PATCH v5 2/3] mm/zswap: replace the zswap_pools list with an allocating xarray Jianyue Wu
2026-09-04 16:04 ` Yosry Ahmed
2026-09-05 13:15 ` Jianyue Wu
2026-09-04 13:24 ` [PATCH v5 3/3] mm/zswap: reference the pool by id to shrink struct zswap_entry Jianyue Wu
2026-09-04 15:38 ` Yosry Ahmed
2026-09-05 13:20 ` Jianyue Wu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=cover.1788528216.git.wujianyue000@gmail.com \
--to=wujianyue000@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=chengming.zhou@linux.dev \
--cc=chrisl@kernel.org \
--cc=hannes@cmpxchg.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=nphamcs@gmail.com \
--cc=yosry@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®