Re: BUG: CD driver sends command during host removal

Alan Stern
2004-09-29T16:55:23Z

On Wed, 29 Sep 2004, Luben Tuikov wrote:

> > Next usb-storage called scsi_remove_host(). Apparently this caused some
> > component of the CD driver to queue a command:

This sounds like a bug, by the way. Commands shouldn't be queued because
of a call to scsi_remove_host!

> > > Sep 26 11:20:54 localhost kernel: usb-storage: queuecommand called
> > > Sep 26 11:20:54 localhost kernel: usb-storage: *** thread awakened.
> > > Sep 26 11:20:54 localhost kernel: usb-storage: No command during
> > disconnect
> > > Sep 26 11:20:54 localhost kernel: usb-storage: *** thread sleeping.
> >
> > usb-storage accepted the command but then ignored it because the host was
> > in process of removal. Should the queuecommand routine have rejected the
> > command?
>
> Yes, if the service delivery subsystem (SDS) knows that the device is gone
> and the command wouldn't be delivered, it should *not* "ignore" the
> command, but return it with error.
>
> I.e. if the LLDD has active/most recent knowledge about the device
> whereto the command is destined, it should act on that and return
> an appropriate error. After all, this is what a properly implemented
> SDS would do.

According to Documentation/scsi/scsi_mid_low_api.txt, the only possible
error returns are SCSI_MLQUEUE_DEVICE_BUSY and SCSI_MLQUEUE_HOST_BUSY.
Neither is appropriate; should the second one be returned?

> > This would involve a race, because it's possible for
> > queuecommand to accept a command and then scsi_remove_host() to be called
> > before the command is carried out.
>
> If the command hasn't been carried out, then delivery would fail and SDS
> would return the appropriate error back to SCSI Core.

How? The SCSI core deallocates the scsi_cmnd before the SDS has a chance
to return anything.

> Where *was* the command? From the point of time when queuecommand() is
> called until scsi_done() is called, the command belongs to the LLDD.
> It should honor any TMF, regardless of the _state_ of the task.

If the command belongs to the LLDD, why does scsi_remove_host do the
following:

calls scsi_host_cancel,
which calls scsi_device_cancel_cb for each device,
which calls scsi_device_cancel,
which calls scsi_finish_command for each active command,
which passes the command back to the upper layer

Either there's a bug in the host removal sequence, or else the LLDD
doesn't own any requests once scsi_remove_host has been called.

Alan Stern