]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
scsi: mpi3mr: Fix potential deadlock in mpi3mr_fault_uevent_emit
authorChandrakanth Patil <chandrakanth.patil@broadcom.com>
Fri, 24 Jul 2026 17:52:31 +0000 (23:22 +0530)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 29 Jul 2026 02:05:42 +0000 (22:05 -0400)
mpi3mr_fault_uevent_emit() runs from the fault watchdog and reset paths
where host I/O may already be blocked. GFP_KERNEL allocations here, both
the local kzalloc_obj() and the ones inside kobject_uevent_env() itself,
can trigger reclaim that waits on that blocked I/O and deadlock.

Use memalloc_noio_save()/restore() to cover the whole call instead of
just the local allocation.

Fixes: ec54b348f274 ("scsi: mpi3mr: Record and report controller firmware faults")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260724164630.924288-1-chandrakanth.patil%40broadcom.com
Signed-off-by: Chandrakanth Patil <chandrakanth.patil@broadcom.com>
Link: https://patch.msgid.link/20260724175231.935192-1-chandrakanth.patil@broadcom.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/mpi3mr/mpi3mr_fw.c

index 31b19ed1528e50fb4ab842d8d6a2a61494249b78..681868716ebdbf69db32df0787dd4b4e9c2f9757 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "mpi3mr.h"
 #include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/sched/mm.h>
 
 static int
 mpi3mr_issue_reset(struct mpi3mr_ioc *mrioc, u16 reset_type, u16 reset_reason);
@@ -1287,11 +1288,14 @@ out_failed:
 static void mpi3mr_fault_uevent_emit(struct mpi3mr_ioc *mrioc)
 {
        struct kobj_uevent_env *env;
+       unsigned int noio_flag;
        int ret;
 
+       noio_flag = memalloc_noio_save();
+
        env = kzalloc_obj(*env);
        if (!env)
-               return;
+               goto out_restore;
 
        ret = add_uevent_var(env, "DRIVER=%s", mrioc->driver_name);
        if (ret)
@@ -1326,7 +1330,8 @@ static void mpi3mr_fault_uevent_emit(struct mpi3mr_ioc *mrioc)
 
 out_free:
        kfree(env);
-
+out_restore:
+       memalloc_noio_restore(noio_flag);
 }
 
 /**