[PATCH 5/7] time needs to be adjusted when eh was running

Bernd Schubert
2008-11-26T18:29:31Z

If the error handler was active and we use the normal command timeout,
the command will probably fail, even though the error handler may have
succeeded to recover the device.

Signed-off-by: Bernd Schubert <bs@q-leap.de>

drivers/scsi/scsi_error.c | 3 +++
drivers/scsi/scsi_lib.c | 13 ++++++++++++-
include/scsi/scsi_host.h | 2 ++
3 files changed, 17 insertions(+), 1 deletion(-)

Index: linux-2.6/drivers/scsi/scsi_lib.c
===================================================================
--- linux-2.6.orig/drivers/scsi/scsi_lib.c
+++ linux-2.6/drivers/scsi/scsi_lib.c
@@ -1537,7 +1537,9 @@ static void scsi_softirq_done(struct req
{
struct scsi_cmnd *cmd = rq->special;
unsigned long wait_for = (cmd->allowed + 1) * rq->timeout;
+ unsigned long cmd_start;
int disposition;
+ struct Scsi_Host *shost = cmd->device->host;

INIT_LIST_HEAD(&cmd->eh_entry);

@@ -1550,9 +1552,18 @@ static void scsi_softirq_done(struct req
if (cmd->result)
atomic_inc(&cmd->device->ioerr_cnt);

+ /*
+ * If the error handler was active, the command will need more time,
+ * of course.
+ */
+ if (shost->last_recovery > cmd->jiffies_at_alloc)
+ cmd_start = shost->last_recovery;
+ else
+ cmd_start = cmd->jiffies_at_alloc;
+
disposition = scsi_decide_disposition(cmd);
if (disposition != SUCCESS &&
- time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) {
+ time_before(cmd_start + wait_for, jiffies)) {
sdev_printk(KERN_ERR, cmd->device,
"timing out command, waited %lus\n",
wait_for/HZ);
Index: linux-2.6/include/scsi/scsi_host.h
===================================================================
--- linux-2.6.orig/include/scsi/scsi_host.h
+++ linux-2.6/include/scsi/scsi_host.h
@@ -521,6 +521,8 @@ struct Scsi_Host {
struct task_struct * ehandler; /* Error recovery thread. */
struct completion * eh_action; /* Wait for specific actions on the
host. */
+ unsigned long last_recovery; /* last time eh completed */
+
wait_queue_head_t host_wait;
struct scsi_host_template *hostt;
struct scsi_transport_template *transportt;
Index: linux-2.6/drivers/scsi/scsi_error.c
===================================================================
--- linux-2.6.orig/drivers/scsi/scsi_error.c
+++ linux-2.6/drivers/scsi/scsi_error.c
@@ -1559,6 +1559,9 @@ static void scsi_restart_operations(stru
BUG_ON(scsi_host_set_state(shost, SHOST_DEL));
spin_unlock_irqrestore(shost->host_lock, flags);

+ /* before starting the queues save the time of recovery */
+ shost->last_recovery = jiffies;
+
wake_up(&shost->host_wait);

/*