Patch "scsi: Do not attempt to rescan suspended devices" has been added to the 6.5-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    scsi: Do not attempt to rescan suspended devices

to the 6.5-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     scsi-do-not-attempt-to-rescan-suspended-devices.patch
and it can be found in the queue-6.5 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 0c62f5a5665b1cb55824c1cf96f44be41b1ba176
Author: Damien Le Moal <dlemoal@xxxxxxxxxx>
Date:   Fri Sep 15 15:00:13 2023 +0900

    scsi: Do not attempt to rescan suspended devices
    
    [ Upstream commit ff48b37802e5c134e2dfc4d091f10b2eb5065a72 ]
    
    scsi_rescan_device() takes a scsi device lock before executing a device
    handler and device driver rescan methods. Waiting for the completion of
    any command issued to the device by these methods will thus be done with
    the device lock held. As a result, there is a risk of deadlocking within
    the power management code if scsi_rescan_device() is called to handle a
    device resume with the associated scsi device not yet resumed.
    
    Avoid such situation by checking that the target scsi device is in the
    running state, that is, fully capable of executing commands, before
    proceeding with the rescan and bailout returning -EWOULDBLOCK otherwise.
    With this error return, the caller can retry rescaning the device after
    a delay.
    
    The state check is done with the device lock held and is thus safe
    against incoming suspend power management operations.
    
    Fixes: 6aa0365a3c85 ("ata: libata-scsi: Avoid deadlock on rescan after device resume")
    Cc: stable@xxxxxxxxxxxxxxx
    Signed-off-by: Damien Le Moal <dlemoal@xxxxxxxxxx>
    Reviewed-by: Hannes Reinecke <hare@xxxxxxx>
    Reviewed-by: Niklas Cassel <niklas.cassel@xxxxxxx>
    Tested-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>
    Reviewed-by: Martin K. Petersen <martin.petersen@xxxxxxxxxx>
    Reviewed-by: Bart Van Assche <bvanassche@xxxxxxx>
    Stable-dep-of: 8b4d9469d0b0 ("ata: libata-scsi: Fix delayed scsi_rescan_device() execution")
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index eaa972bee6c00..902655d759476 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -1619,12 +1619,24 @@ int scsi_add_device(struct Scsi_Host *host, uint channel,
 }
 EXPORT_SYMBOL(scsi_add_device);
 
-void scsi_rescan_device(struct scsi_device *sdev)
+int scsi_rescan_device(struct scsi_device *sdev)
 {
 	struct device *dev = &sdev->sdev_gendev;
+	int ret = 0;
 
 	device_lock(dev);
 
+	/*
+	 * Bail out if the device is not running. Otherwise, the rescan may
+	 * block waiting for commands to be executed, with us holding the
+	 * device lock. This can result in a potential deadlock in the power
+	 * management core code when system resume is on-going.
+	 */
+	if (sdev->sdev_state != SDEV_RUNNING) {
+		ret = -EWOULDBLOCK;
+		goto unlock;
+	}
+
 	scsi_attach_vpd(sdev);
 	scsi_cdl_check(sdev);
 
@@ -1638,7 +1650,11 @@ void scsi_rescan_device(struct scsi_device *sdev)
 			drv->rescan(dev);
 		module_put(dev->driver->owner);
 	}
+
+unlock:
 	device_unlock(dev);
+
+	return ret;
 }
 EXPORT_SYMBOL(scsi_rescan_device);
 
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 49f768d0ff370..4c2dc8150c6d7 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -764,7 +764,7 @@ scsi_template_proc_dir(const struct scsi_host_template *sht);
 #define scsi_template_proc_dir(sht) NULL
 #endif
 extern void scsi_scan_host(struct Scsi_Host *);
-extern void scsi_rescan_device(struct scsi_device *);
+extern int scsi_rescan_device(struct scsi_device *sdev);
 extern void scsi_remove_host(struct Scsi_Host *);
 extern struct Scsi_Host *scsi_host_get(struct Scsi_Host *);
 extern int scsi_host_busy(struct Scsi_Host *shost);



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux