@@ -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;
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(-)