scsi: core: Add limitless cmd retry support
Add infinite retry support to SCSI midlayer by combining common checks for retries into some helper functions, and then checking for the -1/SCSI_CMD_RETRIES_NO_LIMIT. Link: https://lore.kernel.org/r/1601566554-26752-2-git-send-email-michael.christie@oracle.com Reviewed-by: Bart Van Assche <bvanassche@acm.org> Signed-off-by: Mike Christie <michael.christie@oracle.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:

committed by
Martin K. Petersen

parent
7010645ba7
commit
2a242d59d6
@@ -669,6 +669,23 @@ static void scsi_io_completion_reprep(struct scsi_cmnd *cmd,
|
||||
scsi_mq_requeue_cmd(cmd);
|
||||
}
|
||||
|
||||
static bool scsi_cmd_runtime_exceeced(struct scsi_cmnd *cmd)
|
||||
{
|
||||
struct request *req = cmd->request;
|
||||
unsigned long wait_for;
|
||||
|
||||
if (cmd->allowed == SCSI_CMD_RETRIES_NO_LIMIT)
|
||||
return false;
|
||||
|
||||
wait_for = (cmd->allowed + 1) * req->timeout;
|
||||
if (time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) {
|
||||
scmd_printk(KERN_ERR, cmd, "timing out command, waited %lus\n",
|
||||
wait_for/HZ);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Helper for scsi_io_completion() when special action required. */
|
||||
static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result)
|
||||
{
|
||||
@@ -677,7 +694,6 @@ static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result)
|
||||
int level = 0;
|
||||
enum {ACTION_FAIL, ACTION_REPREP, ACTION_RETRY,
|
||||
ACTION_DELAYED_RETRY} action;
|
||||
unsigned long wait_for = (cmd->allowed + 1) * req->timeout;
|
||||
struct scsi_sense_hdr sshdr;
|
||||
bool sense_valid;
|
||||
bool sense_current = true; /* false implies "deferred sense" */
|
||||
@@ -782,8 +798,7 @@ static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result)
|
||||
} else
|
||||
action = ACTION_FAIL;
|
||||
|
||||
if (action != ACTION_FAIL &&
|
||||
time_before(cmd->jiffies_at_alloc + wait_for, jiffies))
|
||||
if (action != ACTION_FAIL && scsi_cmd_runtime_exceeced(cmd))
|
||||
action = ACTION_FAIL;
|
||||
|
||||
switch (action) {
|
||||
@@ -1456,7 +1471,6 @@ static bool scsi_mq_lld_busy(struct request_queue *q)
|
||||
static void scsi_softirq_done(struct request *rq)
|
||||
{
|
||||
struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
|
||||
unsigned long wait_for = (cmd->allowed + 1) * rq->timeout;
|
||||
int disposition;
|
||||
|
||||
INIT_LIST_HEAD(&cmd->eh_entry);
|
||||
@@ -1466,13 +1480,8 @@ static void scsi_softirq_done(struct request *rq)
|
||||
atomic_inc(&cmd->device->ioerr_cnt);
|
||||
|
||||
disposition = scsi_decide_disposition(cmd);
|
||||
if (disposition != SUCCESS &&
|
||||
time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) {
|
||||
scmd_printk(KERN_ERR, cmd,
|
||||
"timing out command, waited %lus\n",
|
||||
wait_for/HZ);
|
||||
if (disposition != SUCCESS && scsi_cmd_runtime_exceeced(cmd))
|
||||
disposition = SUCCESS;
|
||||
}
|
||||
|
||||
scsi_log_completion(cmd, disposition);
|
||||
|
||||
|
Reference in New Issue
Block a user