From: Chengming Zhou <chengming.zhou@linux.dev>
To: Yosry Ahmed <yosryahmed@google.com>,
Andrew Morton <akpm@linux-foundation.org>
Cc: Johannes Weiner <hannes@cmpxchg.org>,
Nhat Pham <nphamcs@gmail.com>,
linux-mm@kvack.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] mm: zswap: move allocations during CPU init outside the lock
Date: Tue, 14 Jan 2025 10:20:33 +0800 [thread overview]
Message-ID: <b936cc00-926e-405a-9442-f4af33428c03@linux.dev> (raw)
In-Reply-To: <20250113214458.2123410-1-yosryahmed@google.com>
On 2025/1/14 05:44, Yosry Ahmed wrote:
> 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.
>
> Fixes: 12dcb0ef5406 ("mm: zswap: properly synchronize freeing resources during CPU hotunplug")
> Signed-off-by: Yosry Ahmed <yosryahmed@google.com>
Great catch!
Reviewed-by: Chengming Zhou <chengming.zhou@linux.dev>
Thanks.
> ---
> mm/zswap.c | 42 ++++++++++++++++++++++++------------------
> 1 file changed, 24 insertions(+), 18 deletions(-)
>
> diff --git a/mm/zswap.c b/mm/zswap.c
> index 30f5a27a68620..b84c20d889b1b 100644
> --- a/mm/zswap.c
> +++ b/mm/zswap.c
> @@ -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;
> }
>
prev parent reply other threads:[~2025-01-14 2:20 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-01-13 21:44 Yosry Ahmed
2025-01-14 2:20 ` Chengming Zhou [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=b936cc00-926e-405a-9442-f4af33428c03@linux.dev \
--to=chengming.zhou@linux.dev \
--cc=akpm@linux-foundation.org \
--cc=hannes@cmpxchg.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=nphamcs@gmail.com \
--cc=yosryahmed@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®