FAILED: patch "[PATCH] mm: zswap: move allocations during CPU init outside the lock" failed to apply to 6.1-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 6.1-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.1.y
git checkout FETCH_HEAD
git cherry-pick -x 779b9955f64327c339a16f68055af98252fd3315
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2025012002-overstep-numbness-cf60@gregkh' --subject-prefix 'PATCH 6.1.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 779b9955f64327c339a16f68055af98252fd3315 Mon Sep 17 00:00:00 2001
From: Yosry Ahmed <[email protected]>
Date: Mon, 13 Jan 2025 21:44:58 +0000
Subject: [PATCH] mm: zswap: move allocations during CPU init outside the lock
In zswap_cpu_comp_prepare(), allocations are made and assigned to various members of acomp_ctx under acomp_ctx->mutex. However, allocations may recurse into zswap through reclaim, trying to acquire the same mutex and deadlocking.
Move the allocations before the mutex critical section. Only the initialization of acomp_ctx needs to be done with the mutex held.
mm/zswap.c +24 -18
@@ -820,15 +820,15 @@ static int zswap_cpu_comp_prepare(unsigned int cpu, struct hlist_node *node) { struct zswap_pool *pool = hlist_entry(node, struct zswap_pool, node);struct crypto_acomp_ctx *acomp_ctx =per_cpu_ptr (pool->acomp_ctx, cpu); -struct crypto_acomp *acomp; -struct acomp_req *req; +struct crypto_acomp *acomp =NULL ; +struct acomp_req *req =NULL ; +u8 *buffer =NULL ;int ret; -mutex_lock (&acomp_ctx->mutex); - acomp_ctx->buffer =kmalloc_node (PAGE_SIZE *2 ,GFP_KERNEL ,cpu_to_node (cpu)); -if (!acomp_ctx->buffer) { + buffer =kmalloc_node (PAGE_SIZE *2 ,GFP_KERNEL ,cpu_to_node (cpu)); +if (!buffer) { ret = -ENOMEM ; - goto buffer_fail; + goto fail; } acomp =crypto_alloc_acomp_node (pool->tfm_name,0 ,0 ,cpu_to_node (cpu));
@@ -836,21 +836,25 @@ static int zswap_cpu_comp_prepare(unsigned int cpu, struct hlist_node *node)pr_err ("could not alloc crypto acomp %s : %ld\n" , pool->tfm_name,PTR_ERR (acomp)); ret =PTR_ERR (acomp); - goto acomp_fail; + goto fail; } - acomp_ctx->acomp = acomp; - acomp_ctx->is_sleepable =acomp_is_async (acomp); - req =acomp_request_alloc (acomp_ctx->acomp); + req =acomp_request_alloc (acomp);if (!req) {pr_err ("could not alloc crypto acomp_request %s\n" , pool->tfm_name); ret = -ENOMEM ; - goto req_fail; + goto fail; } - acomp_ctx->req = req; +/* +* Only hold the mutex after completing allocations, otherwise we may +* recurse into zswap through reclaim and attempt to hold the mutex +* again resulting in a deadlock. +*/ +mutex_lock (&acomp_ctx->mutex);crypto_init_wait (&acomp_ctx->wait); +/* * if the backend of acomp is async zip, crypto_req_done() will wakeup * crypto_wait_req(); if the backend of acomp is scomp, the callback
@@ -859,15 +863,17 @@ static int zswap_cpu_comp_prepare(unsigned int cpu, struct hlist_node *node)acomp_request_set_callback (req,CRYPTO_TFM_REQ_MAY_BACKLOG , crypto_req_done, &acomp_ctx->wait); + acomp_ctx->buffer = buffer; + acomp_ctx->acomp = acomp; + acomp_ctx->is_sleepable =acomp_is_async (acomp); + acomp_ctx->req = req;mutex_unlock (&acomp_ctx->mutex);return 0 ; -req_fail: -crypto_free_acomp (acomp_ctx->acomp); -acomp_fail: -kfree (acomp_ctx->buffer); -buffer_fail: -mutex_unlock (&acomp_ctx->mutex); +fail: +if (acomp) +crypto_free_acomp (acomp); +kfree (buffer);return ret; }