On Mon, Feb 12, 2024 at 5:29 AM Chengming Zhou <zhouchengming@xxxxxxxxxxxxx> wrote: > > On 2024/2/12 05:21, Nhat Pham wrote: > > On Sun, Feb 11, 2024 at 5:58 AM Chengming Zhou > > <zhouchengming@xxxxxxxxxxxxx> wrote: > >> > >> All zswap entries will take a reference of zswap_pool when > >> zswap_store(), and drop it when free. Change it to use the > >> percpu_ref is better for scalability performance. > >> > >> Testing kernel build in tmpfs with memory.max=2GB > >> (zswap shrinker and writeback enabled with one 50GB swapfile). > >> > >> mm-unstable zswap-global-lru > >> real 63.20 63.12 > >> user 1061.75 1062.95 > >> sys 268.74 264.44 > >> > >> Signed-off-by: Chengming Zhou <zhouchengming@xxxxxxxxxxxxx> > >> --- > >> mm/zswap.c | 30 +++++++++++++++++++++--------- > >> 1 file changed, 21 insertions(+), 9 deletions(-) > >> > >> diff --git a/mm/zswap.c b/mm/zswap.c > >> index 7668db8c10e3..afb31904fb08 100644 > >> --- a/mm/zswap.c > >> +++ b/mm/zswap.c > >> @@ -173,7 +173,7 @@ struct crypto_acomp_ctx { > >> struct zswap_pool { > >> struct zpool *zpools[ZSWAP_NR_ZPOOLS]; > >> struct crypto_acomp_ctx __percpu *acomp_ctx; > >> - struct kref kref; > >> + struct percpu_ref ref; > >> struct list_head list; > >> struct work_struct release_work; > >> struct hlist_node node; > >> @@ -303,6 +303,7 @@ static void zswap_update_total_size(void) > >> /********************************* > >> * pool functions > >> **********************************/ > >> +static void __zswap_pool_empty(struct percpu_ref *ref); > >> > >> static struct zswap_pool *zswap_pool_create(char *type, char *compressor) > >> { > >> @@ -356,13 +357,18 @@ static struct zswap_pool *zswap_pool_create(char *type, char *compressor) > >> /* being the current pool takes 1 ref; this func expects the > >> * caller to always add the new pool as the current pool > >> */ > >> - kref_init(&pool->kref); > >> + ret = percpu_ref_init(&pool->ref, __zswap_pool_empty, > >> + PERCPU_REF_ALLOW_REINIT, GFP_KERNEL); > >> + if (ret) > >> + goto ref_fail; > >> INIT_LIST_HEAD(&pool->list); > >> > >> zswap_pool_debug("created", pool); > >> > >> return pool; > >> > >> +ref_fail: > >> + cpuhp_state_remove_instance(CPUHP_MM_ZSWP_POOL_PREPARE, &pool->node); > >> error: > >> if (pool->acomp_ctx) > >> free_percpu(pool->acomp_ctx); > >> @@ -435,8 +441,8 @@ static void __zswap_pool_release(struct work_struct *work) > >> > >> synchronize_rcu(); > >> > >> - /* nobody should have been able to get a kref... */ > >> - WARN_ON(kref_get_unless_zero(&pool->kref)); > > > > Do we no longer care about this WARN? IIUC, this is to catch someone > > still holding a reference to the pool at release time, which sounds > > like a bug. I think we can simulate the similar behavior with: > > Ok, I thought it has already been put to 0 when we're here, so any tryget > will fail. But keeping this WARN_ON() is also fine to me, will keep it. Yup - it should fail, if the code is not buggy. But that's a pretty big if :) Jokes aside, we can remove it if folks think the benefit is not worth the cost/overhead. However, I'm a bit hesitant to remove checks in zswap, especially given how buggy it has been (some of which are refcnt bugs as well, IIRC).