答复: 答复: [PATCH v5 1/2] scsi: sd: mark disk dead on surprise host removal to avoid I/O hang

From: 胡连勤

Date: Tue Oct 13 2026 - 22:21:22 EST


Hi Bart,

> > 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);
> > }
> Why is a new member variable introduced in struct Scsi_Host instead of
> e.g. changing the state of all SCSI devices that are associated with the
> host to SDEV_OFFLINE?
>

Thanks for the suggestion, it's a good point. I did look into using
SDEV_OFFLINE, but ran into a few difficulties:

1. The hang is in the block layer, not the SCSI layer. The hang occurs
in del_gendisk() -> sync_filesystem() -> __bio_queue_enter().
SDEV_OFFLINE is a SCSI-layer concept and cannot prevent the block
layer from attempting the sync. We still need blk_mark_disk_dead()
to set GD_DEAD so that del_gendisk() skips sync_filesystem().

2. State override: Even if we set devices to SDEV_OFFLINE before
scsi_remove_host(), __scsi_remove_device() will transition them to
SDEV_CANCEL before sd_remove() is called. So sd_remove() cannot
distinguish surprise removal from orderly removal based on device
state alone.

Given these, I went with SHOST_SURPRISE_REMOVAL as a more targeted
approach. If you think SDEV_OFFLINE is viable, I'd be happy to explore
it further.

Regards,
Lianqin