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 <dgilb...@interlog.com>
---
 drivers/scsi/scsi_lib.c | 235 ++++++++++++++++++++++++++----------------------
 1 file changed, 128 insertions(+), 107 deletions(-)

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;
-- 
2.14.1

Reply via email to