The patch titled Subject: mm/zswap: fix zswap_pools_lock usages after changing to percpu_ref has been added to the -mm mm-unstable branch. Its filename is mm-zswap-change-zswap_pool-kref-to-percpu_ref-fix.patch This patch will shortly appear at https://git.kernel.org/pub/scm/linux/kernel/git/akpm/25-new.git/tree/patches/mm-zswap-change-zswap_pool-kref-to-percpu_ref-fix.patch This patch will later appear in the mm-unstable branch at git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm Before you just go and hit "reply", please: a) Consider who else should be cc'ed b) Prefer to cc a suitable mailing list as well c) Ideally: find the original patch on the mailing list and do a reply-to-all to that, adding suitable additional cc's *** Remember to use Documentation/process/submit-checklist.rst when testing your code *** The -mm tree is included into linux-next via the mm-everything branch at git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm and is updated there every 2-3 working days ------------------------------------------------------ From: Chengming Zhou <chengming.zhou@xxxxxxxxx> Subject: mm/zswap: fix zswap_pools_lock usages after changing to percpu_ref Date: Wed, 28 Feb 2024 15:49:54 +0000 Now the release of zswap pool is controlled by percpu_ref, its release callback (__zswap_pool_empty()) will be called when percpu_ref hit 0. But this release callback may potentially be called from RCU callback context by percpu_ref_kill(), which maybe from the softirq context. So we need to use spin_lock/unlock_bh() to avoid potential deadlock. This problem is introduced by the commit f3da427e82c4 ("mm/zswap: change zswap_pool kref to percpu_ref"), which is in mm-unstable branch now. It can be reproduced by testing kernel build in tmpfs with zswap and CONFIG_LOCKDEP enabled, meanwhile changing the zswap compressor setting dynamically. Link: https://lkml.kernel.org/r/20240228154954.3028626-1-chengming.zhou@xxxxxxxxx Signed-off-by: Chengming Zhou <chengming.zhou@xxxxxxxxx> Cc: Chengming Zhou <zhouchengming@xxxxxxxxxxxxx> Cc: Johannes Weiner <hannes@xxxxxxxxxxx> Cc: Nhat Pham <nphamcs@xxxxxxxxx> Cc: Yosry Ahmed <yosryahmed@xxxxxxxxxx> Cc: Matthew Wilcox (Oracle) <willy@xxxxxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- mm/zswap.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) --- a/mm/zswap.c~mm-zswap-change-zswap_pool-kref-to-percpu_ref-fix +++ a/mm/zswap.c @@ -459,7 +459,7 @@ static void __zswap_pool_empty(struct pe pool = container_of(ref, typeof(*pool), ref); - spin_lock(&zswap_pools_lock); + spin_lock_bh(&zswap_pools_lock); WARN_ON(pool == zswap_pool_current()); @@ -468,7 +468,7 @@ static void __zswap_pool_empty(struct pe INIT_WORK(&pool->release_work, __zswap_pool_release); schedule_work(&pool->release_work); - spin_unlock(&zswap_pools_lock); + spin_unlock_bh(&zswap_pools_lock); } static int __must_check zswap_pool_get(struct zswap_pool *pool) @@ -598,7 +598,7 @@ static int __zswap_param_set(const char return -EINVAL; } - spin_lock(&zswap_pools_lock); + spin_lock_bh(&zswap_pools_lock); pool = zswap_pool_find_get(type, compressor); if (pool) { @@ -607,7 +607,7 @@ static int __zswap_param_set(const char list_del_rcu(&pool->list); } - spin_unlock(&zswap_pools_lock); + spin_unlock_bh(&zswap_pools_lock); if (!pool) pool = zswap_pool_create(type, compressor); @@ -628,7 +628,7 @@ static int __zswap_param_set(const char else ret = -EINVAL; - spin_lock(&zswap_pools_lock); + spin_lock_bh(&zswap_pools_lock); if (!ret) { put_pool = zswap_pool_current(); @@ -643,7 +643,7 @@ static int __zswap_param_set(const char put_pool = pool; } - spin_unlock(&zswap_pools_lock); + spin_unlock_bh(&zswap_pools_lock); if (!zswap_has_pool && !pool) { /* if initial pool creation failed, and this pool creation also _ Patches currently in -mm which might be from chengming.zhou@xxxxxxxxx are mm-zswap-change-zswap_pool-kref-to-percpu_ref-fix.patch