| From d9e3d13806b61b0136243e4436ab610d0fa3bc37 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 22 Jun 2022 11:35:01 +0900 |
| Subject: zram: do not lookup algorithm in backends table |
| |
| From: Sergey Senozhatsky <senozhatsky@chromium.org> |
| |
| [ Upstream commit dc89997264de565999a1cb55db3f295d3a8e457b ] |
| |
| Always use crypto_has_comp() so that crypto can lookup module, call |
| usermodhelper to load the modules, wait for usermodhelper to finish and so |
| on. Otherwise crypto will do all of these steps under CPU hot-plug lock |
| and this looks like too much stuff to handle under the CPU hot-plug lock. |
| Besides this can end up in a deadlock when usermodhelper triggers a code |
| path that attempts to lock the CPU hot-plug lock, that zram already holds. |
| |
| An example of such deadlock: |
| |
| - path A. zram grabs CPU hot-plug lock, execs /sbin/modprobe from crypto |
| and waits for modprobe to finish |
| |
| disksize_store |
| zcomp_create |
| __cpuhp_state_add_instance |
| __cpuhp_state_add_instance_cpuslocked |
| zcomp_cpu_up_prepare |
| crypto_alloc_base |
| crypto_alg_mod_lookup |
| call_usermodehelper_exec |
| wait_for_completion_killable |
| do_wait_for_common |
| schedule |
| |
| - path B. async work kthread that brings in scsi device. It wants to |
| register CPUHP states at some point, and it needs the CPU hot-plug |
| lock for that, which is owned by zram. |
| |
| async_run_entry_fn |
| scsi_probe_and_add_lun |
| scsi_mq_alloc_queue |
| blk_mq_init_queue |
| blk_mq_init_allocated_queue |
| blk_mq_realloc_hw_ctxs |
| __cpuhp_state_add_instance |
| __cpuhp_state_add_instance_cpuslocked |
| mutex_lock |
| schedule |
| |
| - path C. modprobe sleeps, waiting for all aync works to finish. |
| |
| load_module |
| do_init_module |
| async_synchronize_full |
| async_synchronize_cookie_domain |
| schedule |
| |
| [senozhatsky@chromium.org: add comment] |
| Link: https://lkml.kernel.org/r/20220624060606.1014474-1-senozhatsky@chromium.org |
| Link: https://lkml.kernel.org/r/20220622023501.517125-1-senozhatsky@chromium.org |
| Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org> |
| Cc: Minchan Kim <minchan@kernel.org> |
| Cc: Nitin Gupta <ngupta@vflare.org> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/block/zram/zcomp.c | 11 +++++------ |
| 1 file changed, 5 insertions(+), 6 deletions(-) |
| |
| diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c |
| index 33e3b76c4fa9..b08650417bf0 100644 |
| --- a/drivers/block/zram/zcomp.c |
| +++ b/drivers/block/zram/zcomp.c |
| @@ -61,12 +61,6 @@ static int zcomp_strm_init(struct zcomp_strm *zstrm, struct zcomp *comp) |
| |
| bool zcomp_available_algorithm(const char *comp) |
| { |
| - int i; |
| - |
| - i = sysfs_match_string(backends, comp); |
| - if (i >= 0) |
| - return true; |
| - |
| /* |
| * Crypto does not ignore a trailing new line symbol, |
| * so make sure you don't supply a string containing |
| @@ -215,6 +209,11 @@ struct zcomp *zcomp_create(const char *compress) |
| struct zcomp *comp; |
| int error; |
| |
| + /* |
| + * Crypto API will execute /sbin/modprobe if the compression module |
| + * is not loaded yet. We must do it here, otherwise we are about to |
| + * call /sbin/modprobe under CPU hot-plug lock. |
| + */ |
| if (!zcomp_available_algorithm(compress)) |
| return ERR_PTR(-EINVAL); |
| |
| -- |
| 2.35.1 |
| |