答复: [usb-storage] [PATCH v5 1/2] scsi: sd: mark disk dead on surprise host removal to avoid I/O hang
From: 胡连勤
Date: Tue Oct 13 2026 - 05:36:43 EST
Hi Oliver,
> > index a1b21ea14e54..98f861fb7e80 100644
> > --- a/drivers/scsi/sd.c
> > +++ b/drivers/scsi/sd.c
> > @@ -4272,6 +4272,10 @@ static void sd_remove(struct scsi_device *sdp)
> >
> > scsi_autopm_get_device(sdkp->device);
>
> Here you resume the device
>
> > + /* Device is gone; avoid sync_filesystem() hang in del_gendisk(). */
> > + if (sdkp->device->host->surprise_removal)
> > + blk_mark_disk_dead(sdkp->disk);
>
> Here you check whether it exists.
>
> That seems a bit inverted. What is the point of resuming a device
> that has gone away?
>
You're right. It makes no sense to resume a device that is already gone.
I'll move the surprise_removal check before scsi_autopm_get_device()
and skip the resume entirely for surprise removal:
if (test_bit(SHOST_SURPRISE_REMOVAL, &sdkp->device->host->flags))
blk_mark_disk_dead(sdkp->disk);
else
scsi_autopm_get_device(sdkp->device);
This way, for surprise removal we skip the resume and go straight to
marking the disk dead. For orderly removal, the resume proceeds as
before.
The complete changes:
drivers/scsi/sd.c | 6 +++++-
drivers/usb/storage/usb.c | 3 +++
include/scsi/scsi_host.h | 7 +++++++
3 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index a1b21ea14e54..db06fe67f4ce 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -4270,7 +4270,11 @@ static void sd_remove(struct scsi_device *sdp)
struct device *dev = &sdp->sdev_gendev;
struct scsi_disk *sdkp = dev_get_drvdata(dev);
- scsi_autopm_get_device(sdkp->device);
+ /* Surprise removal: skip resume and sync to avoid I/O hang. */
+ if (test_bit(SHOST_SURPRISE_REMOVAL, &sdkp->device->host->flags))
+ blk_mark_disk_dead(sdkp->disk);
+ else
+ scsi_autopm_get_device(sdkp->device);
device_del(&sdkp->disk_dev);
del_gendisk(sdkp->disk);
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 16243ec376cd..66aa9ae607de 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -757,6 +757,13 @@ struct Scsi_Host {
/* Delay for runtime autosuspend */
int rpm_autosuspend_delay;
+ /*
+ * Host flags for runtime state that may be set concurrently.
+ * Use atomic bitops (set_bit/test_bit) to access.
+ */
+ unsigned long flags;
+#define SHOST_SURPRISE_REMOVAL 0
+
/*
* We should ensure that this is aligned, both for better performance
* and also because some compilers (m68k) don't automatically force
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 064c7fc8e368..3a5a0cac2b78 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -930,6 +930,9 @@ static void quiesce_and_remove_host(struct us_data *us)
if (us->pusb_dev->state == USB_STATE_NOTATTACHED) {
set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
wake_up(&us->delay_wait);
+
+ /* Device is physically gone, cannot handle I/O */
+ set_bit(SHOST_SURPRISE_REMOVAL, &host->flags);
}
Regards,
Lianqin