diff mbox

[3/5] scsi_io_completion: add _action helper function

Message ID 20180307032134.18978-4-dgilbert@interlog.com (mailing list archive)
State Superseded
Headers show

Commit Message

Douglas Gilbert March 7, 2018, 3:21 a.m. UTC
ChangeLog:
  - move the bottom half of the code in scsi_io_completion that is
    based on a local enum called 'action' to a helper function with
    that suffix
  - replicate the ACTION_REPREP case code since the former
    'goto requeue' would now need to jump into another function
    which is not permitted

Note: the diff below gives a rather misleading view of what this patch
does. Viewing it with difftool should make it clearer.

Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
---
 drivers/scsi/scsi_lib.c | 235 ++++++++++++++++++++++++++----------------------
 1 file changed, 128 insertions(+), 107 deletions(-)

Comments

Johannes Thumshirn March 16, 2018, 2:23 p.m. UTC | #1
Apart from the commit message,
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
diff mbox

Patch

diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index e19531b39394..8d2d12a69508 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -807,117 +807,23 @@  static blk_status_t scsi_io_completion_nz_result(struct scsi_cmnd *cmd,
 	return blk_stat;
 }
 
-/*
- * Function:    scsi_io_completion()
- *
- * Purpose:     Completion processing for block device I/O requests.
- *
- * Arguments:   cmd   - command that is finished.
- *
- * Lock status: Assumed that no lock is held upon entry.
- *
- * Returns:     Nothing
- *
- * Notes:       We will finish off the specified number of sectors.  If we
- *		are done, the command block will be released and the queue
- *		function will be goosed.  If we are not done then we have to
- *		figure out what to do next:
- *
- *		a) We can call scsi_requeue_command().  The request
- *		   will be unprepared and put back on the queue.  Then
- *		   a new command will be created for it.  This should
- *		   be used if we made forward progress, or if we want
- *		   to switch from READ(10) to READ(6) for example.
- *
- *		b) We can call __scsi_queue_insert().  The request will
- *		   be put back on the queue and retried using the same
- *		   command as before, possibly after a delay.
- *
- *		c) We can call scsi_end_request() with -EIO to fail
- *		   the remainder of the request.
- */
-void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
+/* Helper for scsi_io_completion() when special action required. */
+static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result)
 {
-	int result = cmd->result;
 	struct request_queue *q = cmd->device->request_queue;
 	struct request *req = cmd->request;
-	blk_status_t blk_stat = BLK_STS_OK;	/* u8: BLK_STS_OK is only 0 */
-	struct scsi_sense_hdr sshdr;
-	bool sense_valid = false;
-	bool sense_current = true;	/* false implies "deferred sense" */
 	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_and_current = false;
+	blk_status_t blk_stat;		/* enum, BLK_STS_OK is 0 */
 
-	if (result) {
-		sense_valid = scsi_command_normalize_sense(cmd, &sshdr);
-		if (sense_valid)
-			sense_current = !scsi_sense_is_deferred(&sshdr);
-		blk_stat = scsi_io_completion_nz_result(cmd, result);
-		if (blk_stat == BLK_STS_OK)
-			result = 0;
-		if (blk_stat == BLK_STS_NOTSUPP)  /* flagging no change */
-			blk_stat = BLK_STS_OK;
-
-	}
-
-	if (blk_rq_is_passthrough(req)) {
-		/*
-		 * __scsi_error_from_host_byte may have reset the host_byte
-		 */
-		scsi_req(req)->result = cmd->result;
-		scsi_req(req)->resid_len = scsi_get_resid(cmd);
-
-		if (scsi_bidi_cmnd(cmd)) {
-			/*
-			 * Bidi commands Must be complete as a whole,
-			 * both sides at once.
-			 */
-			scsi_req(req->next_rq)->resid_len = scsi_in(cmd)->resid;
-			if (scsi_end_request(req, BLK_STS_OK, blk_rq_bytes(req),
-					blk_rq_bytes(req->next_rq)))
-				BUG();
-			return;
-		}
-	}
-
-	/* no bidi support for !blk_rq_is_passthrough yet */
-	BUG_ON(blk_bidi_rq(req));
-
-	/*
-	 * Next deal with any sectors which we were able to correctly
-	 * handle.
-	 */
-	SCSI_LOG_HLCOMPLETE(1, scmd_printk(KERN_INFO, cmd,
-		"%u sectors total, %d bytes done.\n",
-		blk_rq_sectors(req), good_bytes));
-
-	/*
-	 * Next deal with any sectors which we were able to correctly
-	 * handle. Failed, zero length commands always need to drop down
-	 * to retry code. Fast path should return in this block.
-	 */
-	if (blk_rq_bytes(req) > 0 || blk_stat == BLK_STS_OK) {
-		if (!scsi_end_request(req, blk_stat, good_bytes, 0))
-			return; /* no bytes remaining */
-	}
-
-	/*
-	 * Kill remainder if no retrys.
-	 */
-	if (blk_stat && scsi_noretry_cmd(cmd)) {
-		if (scsi_end_request(req, blk_stat, blk_rq_bytes(req), 0))
-			BUG();
-		return;
-	}
-
-	/*
-	 * If there had been no error, but we have leftover bytes in the
-	 * requeues just queue the command up again.
-	 */
-	if (result == 0)
-		goto requeue;
+	/* sense not about current command is termed: deferred */
+	if (scsi_command_normalize_sense(cmd, &sshdr) &&
+	    !scsi_sense_is_deferred(&sshdr))
+		sense_valid_and_current = true;
 
 	blk_stat = __scsi_error_from_host_byte(cmd, result);
 
@@ -927,7 +833,7 @@  void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
 		 * happens.
 		 */
 		action = ACTION_RETRY;
-	} else if (sense_valid && sense_current) {
+	} else if (sense_valid_and_current) {
 		switch (sshdr.sense_key) {
 		case UNIT_ATTENTION:
 			if (cmd->device->removable) {
@@ -1041,13 +947,12 @@  void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
 			return;
 		/*FALLTHRU*/
 	case ACTION_REPREP:
-	requeue:
 		/* Unprep the request and put it back at the head of the queue.
 		 * A new command will be prepared and issued.
 		 */
-		if (q->mq_ops) {
+		if (q->mq_ops)
 			scsi_mq_requeue_cmd(cmd);
-		} else {
+		else {
 			scsi_release_buffers(cmd);
 			scsi_requeue_command(q, cmd);
 		}
@@ -1063,6 +968,122 @@  void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
 	}
 }
 
+/*
+ * Function:    scsi_io_completion()
+ *
+ * Purpose:     Completion processing for block device I/O requests.
+ *
+ * Arguments:   cmd   - command that is finished.
+ *
+ * Lock status: Assumed that no lock is held upon entry.
+ *
+ * Returns:     Nothing
+ *
+ * Notes:       We will finish off the specified number of sectors.  If we
+ *		are done, the command block will be released and the queue
+ *		function will be goosed.  If we are not done then we have to
+ *		figure out what to do next:
+ *
+ *		a) We can call scsi_requeue_command().  The request
+ *		   will be unprepared and put back on the queue.  Then
+ *		   a new command will be created for it.  This should
+ *		   be used if we made forward progress, or if we want
+ *		   to switch from READ(10) to READ(6) for example.
+ *
+ *		b) We can call __scsi_queue_insert().  The request will
+ *		   be put back on the queue and retried using the same
+ *		   command as before, possibly after a delay.
+ *
+ *		c) We can call scsi_end_request() with -EIO to fail
+ *		   the remainder of the request.
+ *
+ *		Most of the work is now done in the two helper functions
+ *		above: scsi_io_completion_nz_result() and
+ *		scsi_io_completion_action(). What is left here is mainly
+ *		the fast path (i.e. when cmd->result is zero).
+ */
+void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
+{
+	int result = cmd->result;
+	struct request_queue *q = cmd->device->request_queue;
+	struct request *req = cmd->request;
+	blk_status_t blk_stat = BLK_STS_OK;	/* u8: BLK_STS_OK is only 0 */
+
+	if (result) {
+		blk_stat = scsi_io_completion_nz_result(cmd, result);
+		if (blk_stat == BLK_STS_OK)
+			result = 0;
+		if (blk_stat == BLK_STS_NOTSUPP)  /* flagging no change */
+			blk_stat = BLK_STS_OK;
+	}
+
+	if (blk_rq_is_passthrough(req)) {
+		/*
+		 * __scsi_error_from_host_byte may have reset the host_byte
+		 */
+		scsi_req(req)->result = cmd->result;
+		scsi_req(req)->resid_len = scsi_get_resid(cmd);
+
+		if (scsi_bidi_cmnd(cmd)) {
+			/*
+			 * Bidi commands Must be complete as a whole,
+			 * both sides at once.
+			 */
+			scsi_req(req->next_rq)->resid_len = scsi_in(cmd)->resid;
+			if (scsi_end_request(req, BLK_STS_OK, blk_rq_bytes(req),
+					blk_rq_bytes(req->next_rq)))
+				BUG();
+			return;
+		}
+	}
+
+	/* no bidi support for !blk_rq_is_passthrough yet */
+	BUG_ON(blk_bidi_rq(req));
+
+	SCSI_LOG_HLCOMPLETE(1, scmd_printk(KERN_INFO, cmd,
+		"%u sectors total, %d bytes done.\n",
+		blk_rq_sectors(req), good_bytes));
+
+	/*
+	 * Next deal with any sectors which we were able to correctly
+	 * handle. Failed, zero length commands always need to drop down
+	 * to retry code. Fast path should return in this block.
+	 */
+	if (blk_rq_bytes(req) > 0 || blk_stat == BLK_STS_OK) {
+		if (!scsi_end_request(req, blk_stat, good_bytes, 0))
+			return; /* no bytes remaining */
+	}
+
+	/*
+	 * Kill remainder if no retrys.
+	 */
+	if (blk_stat && scsi_noretry_cmd(cmd)) {
+		if (scsi_end_request(req, blk_stat, blk_rq_bytes(req), 0))
+			BUG();
+		return;
+	}
+
+	/*
+	 * If there had been no error, but we have leftover bytes in the
+	 * requeues just queue the command up again.
+	 */
+	if (result == 0) {
+		/*
+		 * Unprep the request and put it back at the head of the
+		 * queue. A new command will be prepared and issued.
+		 * This block is the same as case ACTION_REPREP in
+		 * scsi_io_completion_action() above.
+		 */
+		if (q->mq_ops)
+			scsi_mq_requeue_cmd(cmd);
+		else {
+			scsi_release_buffers(cmd);
+			scsi_requeue_command(q, cmd);
+		}
+	} else
+		scsi_io_completion_action(cmd, result);
+}
+
 static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb)
 {
 	int count;