diff options
author | Hannes Reinecke <hare@suse.de> | 2013-11-11 07:44:54 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-12-19 10:39:02 -0500 |
commit | e494f6a728394ab0df194342549ee20e6f0752df (patch) | |
tree | 2cbae9eea944540b2777e40f1787a90b78123334 /drivers/scsi/scsi.c | |
parent | 2451079bc2ae1334058be8babd44be03ecfa7041 (diff) |
[SCSI] improved eh timeout handler
When a command runs into a timeout we need to send an 'ABORT TASK'
TMF. This is typically done by the 'eh_abort_handler' LLDD callback.
Conceptually, however, this function is a normal SCSI command, so
there is no need to enter the error handler.
This patch implements a new scsi_abort_command() function which
invokes an asynchronous function scsi_eh_abort_handler() to
abort the commands via the usual 'eh_abort_handler'.
If abort succeeds the command is either retried or terminated,
depending on the number of allowed retries. However, 'eh_eflags'
records the abort, so if the retry would fail again the
command is pushed onto the error handler without trying to
abort it (again); it'll be cleared up from SCSI EH.
[hare: smatch detected stray switch fixed]
Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/scsi.c')
-rw-r--r-- | drivers/scsi/scsi.c | 3 |
1 files changed, 3 insertions, 0 deletions
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index fe0bcb18fb26..2b04a57e0f4f 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c | |||
@@ -297,6 +297,7 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, gfp_t gfp_mask) | |||
297 | 297 | ||
298 | cmd->device = dev; | 298 | cmd->device = dev; |
299 | INIT_LIST_HEAD(&cmd->list); | 299 | INIT_LIST_HEAD(&cmd->list); |
300 | INIT_DELAYED_WORK(&cmd->abort_work, scmd_eh_abort_handler); | ||
300 | spin_lock_irqsave(&dev->list_lock, flags); | 301 | spin_lock_irqsave(&dev->list_lock, flags); |
301 | list_add_tail(&cmd->list, &dev->cmd_list); | 302 | list_add_tail(&cmd->list, &dev->cmd_list); |
302 | spin_unlock_irqrestore(&dev->list_lock, flags); | 303 | spin_unlock_irqrestore(&dev->list_lock, flags); |
@@ -353,6 +354,8 @@ void scsi_put_command(struct scsi_cmnd *cmd) | |||
353 | list_del_init(&cmd->list); | 354 | list_del_init(&cmd->list); |
354 | spin_unlock_irqrestore(&cmd->device->list_lock, flags); | 355 | spin_unlock_irqrestore(&cmd->device->list_lock, flags); |
355 | 356 | ||
357 | cancel_delayed_work(&cmd->abort_work); | ||
358 | |||
356 | __scsi_put_command(cmd->device->host, cmd, &sdev->sdev_gendev); | 359 | __scsi_put_command(cmd->device->host, cmd, &sdev->sdev_gendev); |
357 | } | 360 | } |
358 | EXPORT_SYMBOL(scsi_put_command); | 361 | EXPORT_SYMBOL(scsi_put_command); |