Commit dee7121e authored by Bart Van Assche's avatar Bart Van Assche Committed by Martin K. Petersen
Browse files

scsi: core: Change the return type of .eh_timed_out()



Commit 6600593c ("block: rename BLK_EH_NOT_HANDLED to BLK_EH_DONE")
made it impossible for .eh_timed_out() implementations to call
scsi_done() without causing a crash.

Restore support for SCSI timeout handlers to call scsi_done() as follows:

 * Change all .eh_timed_out() handlers as follows:

   - Change the return type into enum scsi_timeout_action.
   - Change BLK_EH_RESET_TIMER into SCSI_EH_RESET_TIMER.
   - Change BLK_EH_DONE into SCSI_EH_NOT_HANDLED.

 * In scsi_timeout(), convert the SCSI_EH_* values into BLK_EH_* values.

Reviewed-by: default avatarLee Duncan <lduncan@suse.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Ming Lei <ming.lei@redhat.com>
Cc: John Garry <john.garry@huawei.com>
Cc: Mike Christie <michael.christie@oracle.com>
Cc: Hannes Reinecke <hare@suse.de>
Signed-off-by: default avatarBart Van Assche <bvanassche@acm.org>
Link: https://lore.kernel.org/r/20221018202958.1902564-3-bvanassche@acm.org


Reviewed-by: default avatarMike Christie <michael.christie@oracle.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 978b7922
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -92,14 +92,17 @@ The timeout handler is scsi_timeout(). When a timeout occurs, this function
 1. invokes optional hostt->eh_timed_out() callback.  Return value can
    be one of

    - BLK_EH_RESET_TIMER
    - SCSI_EH_RESET_TIMER
	This indicates that more time is required to finish the
	command.  Timer is restarted.

    - BLK_EH_DONE
    - SCSI_EH_NOT_HANDLED
        eh_timed_out() callback did not handle the command.
	Step #2 is taken.

    - SCSI_EH_DONE
        eh_timed_out() completed the command.

 2. scsi_abort_command() is invoked to schedule an asynchronous abort which may
    issue a retry scmd->allowed + 1 times.  Asynchronous aborts are not invoked
    for commands for which the SCSI_EH_ABORT_SCHEDULED flag is set (this
+4 −4
Original line number Diff line number Diff line
@@ -1952,12 +1952,12 @@ mptsas_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *SCpnt)
 *	@sc: scsi command that the midlayer is about to time out
 *
 **/
static enum blk_eh_timer_return mptsas_eh_timed_out(struct scsi_cmnd *sc)
static enum scsi_timeout_action mptsas_eh_timed_out(struct scsi_cmnd *sc)
{
	MPT_SCSI_HOST *hd;
	MPT_ADAPTER   *ioc;
	VirtDevice    *vdevice;
	enum blk_eh_timer_return rc = BLK_EH_DONE;
	enum scsi_timeout_action rc = SCSI_EH_NOT_HANDLED;

	hd = shost_priv(sc->device->host);
	if (hd == NULL) {
@@ -1980,7 +1980,7 @@ static enum blk_eh_timer_return mptsas_eh_timed_out(struct scsi_cmnd *sc)
		dtmprintk(ioc, printk(MYIOC_s_WARN_FMT ": %s: ioc is in reset,"
		    "SML need to reset the timer (sc=%p)\n",
		    ioc->name, __func__, sc));
		rc = BLK_EH_RESET_TIMER;
		rc = SCSI_EH_RESET_TIMER;
	}
	vdevice = sc->device->hostdata;
	if (vdevice && vdevice->vtarget && (vdevice->vtarget->inDMD
@@ -1988,7 +1988,7 @@ static enum blk_eh_timer_return mptsas_eh_timed_out(struct scsi_cmnd *sc)
		dtmprintk(ioc, printk(MYIOC_s_WARN_FMT ": %s: target removed "
		    "or in device removal delay (sc=%p)\n",
		    ioc->name, __func__, sc));
		rc = BLK_EH_RESET_TIMER;
		rc = SCSI_EH_RESET_TIMER;
		goto done;
	}

+13 −13
Original line number Diff line number Diff line
@@ -2071,9 +2071,9 @@ static int iscsi_has_ping_timed_out(struct iscsi_conn *conn)
		return 0;
}

enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
enum scsi_timeout_action iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
{
	enum blk_eh_timer_return rc = BLK_EH_DONE;
	enum scsi_timeout_action rc = SCSI_EH_NOT_HANDLED;
	struct iscsi_task *task = NULL, *running_task;
	struct iscsi_cls_session *cls_session;
	struct iscsi_session *session;
@@ -2093,7 +2093,7 @@ enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
		 * Raced with completion. Blk layer has taken ownership
		 * so let timeout code complete it now.
		 */
		rc = BLK_EH_DONE;
		rc = SCSI_EH_NOT_HANDLED;
		spin_unlock(&session->back_lock);
		goto done;
	}
@@ -2102,7 +2102,7 @@ enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
		 * Racing with the completion path right now, so give it more
		 * time so that path can complete it like normal.
		 */
		rc = BLK_EH_RESET_TIMER;
		rc = SCSI_EH_RESET_TIMER;
		task = NULL;
		spin_unlock(&session->back_lock);
		goto done;
@@ -2120,21 +2120,21 @@ enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
		if (unlikely(system_state != SYSTEM_RUNNING)) {
			sc->result = DID_NO_CONNECT << 16;
			ISCSI_DBG_EH(session, "sc on shutdown, handled\n");
			rc = BLK_EH_DONE;
			rc = SCSI_EH_NOT_HANDLED;
			goto done;
		}
		/*
		 * We are probably in the middle of iscsi recovery so let
		 * that complete and handle the error.
		 */
		rc = BLK_EH_RESET_TIMER;
		rc = SCSI_EH_RESET_TIMER;
		goto done;
	}

	conn = session->leadconn;
	if (!conn) {
		/* In the middle of shuting down */
		rc = BLK_EH_RESET_TIMER;
		rc = SCSI_EH_RESET_TIMER;
		goto done;
	}

@@ -2151,7 +2151,7 @@ enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
			     "Last data xfer at %lu. Last timeout was at "
			     "%lu\n.", task->last_xfer, task->last_timeout);
		task->have_checked_conn = false;
		rc = BLK_EH_RESET_TIMER;
		rc = SCSI_EH_RESET_TIMER;
		goto done;
	}

@@ -2162,7 +2162,7 @@ enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
	 * and can let the iscsi eh handle it
	 */
	if (iscsi_has_ping_timed_out(conn)) {
		rc = BLK_EH_RESET_TIMER;
		rc = SCSI_EH_RESET_TIMER;
		goto done;
	}

@@ -2200,7 +2200,7 @@ enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
				     task->last_xfer, running_task->last_xfer,
				     task->last_timeout);
			spin_unlock(&session->back_lock);
			rc = BLK_EH_RESET_TIMER;
			rc = SCSI_EH_RESET_TIMER;
			goto done;
		}
	}
@@ -2216,14 +2216,14 @@ enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
	 */
	if (READ_ONCE(conn->ping_task)) {
		task->have_checked_conn = true;
		rc = BLK_EH_RESET_TIMER;
		rc = SCSI_EH_RESET_TIMER;
		goto done;
	}

	/* Make sure there is a transport check done */
	iscsi_send_nopout(conn, NULL);
	task->have_checked_conn = true;
	rc = BLK_EH_RESET_TIMER;
	rc = SCSI_EH_RESET_TIMER;

done:
	spin_unlock_bh(&session->frwd_lock);
@@ -2232,7 +2232,7 @@ enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
		task->last_timeout = jiffies;
		iscsi_put_task(task);
	}
	ISCSI_DBG_EH(session, "return %s\n", rc == BLK_EH_RESET_TIMER ?
	ISCSI_DBG_EH(session, "return %s\n", rc == SCSI_EH_RESET_TIMER ?
		     "timer reset" : "shutdown or nh");
	return rc;
}
+3 −4
Original line number Diff line number Diff line
@@ -2927,15 +2927,14 @@ static int megasas_generic_reset(struct scsi_cmnd *scmd)
 * Sets the FW busy flag and reduces the host->can_queue if the
 * cmd has not been completed within the timeout period.
 */
static enum
blk_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd)
static enum scsi_timeout_action megasas_reset_timer(struct scsi_cmnd *scmd)
{
	struct megasas_instance *instance;
	unsigned long flags;

	if (time_after(jiffies, scmd->jiffies_at_alloc +
				(scmd_timeout * 2) * HZ)) {
		return BLK_EH_DONE;
		return SCSI_EH_NOT_HANDLED;
	}

	instance = (struct megasas_instance *)scmd->device->host->hostdata;
@@ -2949,7 +2948,7 @@ blk_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd)

		spin_unlock_irqrestore(instance->host->host_lock, flags);
	}
	return BLK_EH_RESET_TIMER;
	return SCSI_EH_RESET_TIMER;
}

/**
+2 −2
Original line number Diff line number Diff line
@@ -2109,7 +2109,7 @@ static int mvumi_queue_command(struct Scsi_Host *shost,
	return 0;
}

static enum blk_eh_timer_return mvumi_timed_out(struct scsi_cmnd *scmd)
static enum scsi_timeout_action mvumi_timed_out(struct scsi_cmnd *scmd)
{
	struct mvumi_cmd *cmd = mvumi_priv(scmd)->cmd_priv;
	struct Scsi_Host *host = scmd->device->host;
@@ -2137,7 +2137,7 @@ static enum blk_eh_timer_return mvumi_timed_out(struct scsi_cmnd *scmd)
	mvumi_return_cmd(mhba, cmd);
	spin_unlock_irqrestore(mhba->shost->host_lock, flags);

	return BLK_EH_DONE;
	return SCSI_EH_NOT_HANDLED;
}

static int
Loading