Skip to content

Commit 0e4b179

Browse files
JasonYanHwmartinkpetersen
authored andcommitted
scsi: libsas: Abort all in-flight requests when device is gone
When a disk is removed with in-flight I/O, the application needs to wait for 30 seconds (depending on the timeout configuration) to hear back from the kernel. Xingui tried to fix this issue by aborting the ATA link for SATA devices[1], however this approach left the SAS devices unresolved. Try to fix this issue by aborting all in-flight requests when the device is gone. This is implemented by iterating over the tagset. [1] https://lore.kernel.org/lkml/234e04db-7539-07e4-a6b8-c6b05f78193d@opensource.wdc.com/T/ Cc: Xingui Yang <yangxingui@huawei.com> Cc: John Garry <john.g.garry@oracle.com> Cc: Damien Le Moal <damien.lemoal@opensource.wdc.com> Cc: Hannes Reinecke <hare@suse.com> Signed-off-by: Jason Yan <yanaijie@huawei.com> Link: https://lore.kernel.org/r/20230330110930.175539-1-yanaijie@huawei.com Reviewed-by: John Garry <john.g.garry@oracle.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 543a827 commit 0e4b179

1 file changed

Lines changed: 29 additions & 0 deletions

File tree

drivers/scsi/libsas/sas_discover.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,33 @@ static void sas_destruct_ports(struct asd_sas_port *port)
360360
}
361361
}
362362

363+
static bool sas_abort_cmd(struct request *req, void *data)
364+
{
365+
struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req);
366+
struct domain_device *dev = data;
367+
368+
if (dev == cmd_to_domain_dev(cmd))
369+
blk_abort_request(req);
370+
return true;
371+
}
372+
373+
static void sas_abort_device_scsi_cmds(struct domain_device *dev)
374+
{
375+
struct sas_ha_struct *sas_ha = dev->port->ha;
376+
struct Scsi_Host *shost = sas_ha->core.shost;
377+
378+
if (dev_is_expander(dev->dev_type))
379+
return;
380+
381+
/*
382+
* For removed device with active IOs, the user space applications have
383+
* to spend very long time waiting for the timeout. This is not
384+
* necessary because a removed device will not return the IOs.
385+
* Abort the inflight IOs here so that EH can be quickly kicked in.
386+
*/
387+
blk_mq_tagset_busy_iter(&shost->tag_set, sas_abort_cmd, dev);
388+
}
389+
363390
void sas_unregister_dev(struct asd_sas_port *port, struct domain_device *dev)
364391
{
365392
if (!test_bit(SAS_DEV_DESTROY, &dev->state) &&
@@ -372,6 +399,8 @@ void sas_unregister_dev(struct asd_sas_port *port, struct domain_device *dev)
372399
}
373400

374401
if (!test_and_set_bit(SAS_DEV_DESTROY, &dev->state)) {
402+
if (test_bit(SAS_DEV_GONE, &dev->state))
403+
sas_abort_device_scsi_cmds(dev);
375404
sas_rphy_unlink(dev->rphy);
376405
list_move_tail(&dev->disco_list_node, &port->destroy_list);
377406
}

0 commit comments

Comments
 (0)