[PATCH 1/1] mm/zswap: enable static key after runtime pool recovery

From: Longlong Xia

Date: Sat Sep 05 2026 - 08:52:46 EST


From: Longlong Xia <xialonglong@xxxxxxxxxx>

When CONFIG_ZSWAP_DEFAULT_ON is disabled, zswap_setup() can complete
without a pool after a failed initial pool creation. A later compressor
parameter update can create and publish a pool, but does not enable
zswap_ever_enabled.

If users then enable zswap, zswap_store() intercepts swapout while
zswap_load() still returns -ENOENT without consulting the xarray. The
swapin path therefore reads a stale backing swap slot because the store
skipped writing it.

Enable the static key after a successful compressor and pool update. Do
this outside zswap_pools_lock because static key updates may sleep.

Verified with fault injection on a stock kernel (compressor builtin,
CONFIG_ZSWAP_DEFAULT_ON=n):

1. Boot with zswap.enabled=1; pool creation fails, init completes
pool-less (static key off).
2. Echo an available compressor name to zswap.compressor; a pool is
recovered but the key stays off.
3. Enable zswap.
4. madvise(MADV_PAGEOUT) a pattern-verified 512 MiB region, then
fault it back in and verify.

Step 4 reads back 131072/131072 zeroed pages (zswpin=0, zswpout=131072)
without this patch; all pages intact (zswpin=131072) with it.

Fixes: 2d4d2b1cfb85 ("mm: zswap: add zswap_never_enabled()")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: Zcode:GLM-5.3
Signed-off-by: Longlong Xia <xialonglong@xxxxxxxxxx>
---
mm/zswap.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/mm/zswap.c b/mm/zswap.c
index 37f34e406c8e3..c48c4df63f188 100644
--- a/mm/zswap.c
+++ b/mm/zswap.c
@@ -586,6 +586,9 @@ static int zswap_compressor_param_set(const char *val, const struct kernel_param
else
ret = -EINVAL;

+ if (!ret)
+ static_branch_enable(&zswap_ever_enabled);
+
spin_lock_bh(&zswap_pools_lock);

if (!ret) {
--
2.43.0