[PATCH v5 1/3] mm/zswap: release retired pools via queue_rcu_work() instead of synchronize_rcu()
From: Jianyue Wu
Date: Fri Sep 04 2026 - 10:19:26 EST
When a pool's last reference is dropped, __zswap_pool_empty() removes it
from the pool list and schedules __zswap_pool_release(), which calls
synchronize_rcu() to wait for readers before tearing the pool down.
synchronize_rcu() is a synchronous, potentially long wait. Replace it
with queue_rcu_work(): __zswap_pool_empty() hands the pool to
queue_rcu_work(), which waits for a grace period asynchronously and then
runs __zswap_pool_release() from a worker for the sleepable teardown
(__zswap_pool_empty() can run in atomic context and must not block).
The grace-period guarantee is unchanged; the retirement path just no
longer blocks on it.
Suggested-by: Yosry Ahmed <yosry@xxxxxxxxxx>
Signed-off-by: Jianyue Wu <wujianyue000@xxxxxxxxx>
Acked-by: Yosry Ahmed <yosry@xxxxxxxxxx>
---
mm/zswap.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/mm/zswap.c b/mm/zswap.c
index f3ae3c81e48e..e456e5080531 100644
--- a/mm/zswap.c
+++ b/mm/zswap.c
@@ -155,7 +155,7 @@ struct zswap_pool {
struct crypto_acomp_ctx __percpu *acomp_ctx;
struct percpu_ref ref;
struct list_head list;
- struct work_struct release_work;
+ struct rcu_work release_rwork;
struct hlist_node node;
char tfm_name[CRYPTO_MAX_ALG_NAME];
};
@@ -379,10 +379,8 @@ static void zswap_pool_destroy(struct zswap_pool *pool)
static void __zswap_pool_release(struct work_struct *work)
{
- struct zswap_pool *pool = container_of(work, typeof(*pool),
- release_work);
-
- synchronize_rcu();
+ struct zswap_pool *pool = container_of(to_rcu_work(work),
+ typeof(*pool), release_rwork);
/* nobody should have been able to get a ref... */
WARN_ON(!percpu_ref_is_zero(&pool->ref));
@@ -406,8 +404,8 @@ static void __zswap_pool_empty(struct percpu_ref *ref)
list_del_rcu(&pool->list);
- INIT_WORK(&pool->release_work, __zswap_pool_release);
- schedule_work(&pool->release_work);
+ INIT_RCU_WORK(&pool->release_rwork, __zswap_pool_release);
+ queue_rcu_work(system_percpu_wq, &pool->release_rwork);
spin_unlock_bh(&zswap_pools_lock);
}
--
2.43.0