From patchwork Wed Mar 7 03:21:32 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Douglas Gilbert X-Patchwork-Id: 10263333 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id C2D9260247 for ; Wed, 7 Mar 2018 03:21:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B97682947E for ; Wed, 7 Mar 2018 03:21:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B7BD629482; Wed, 7 Mar 2018 03:21:47 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0A71B2947F for ; Wed, 7 Mar 2018 03:21:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933106AbeCGDVq (ORCPT ); Tue, 6 Mar 2018 22:21:46 -0500 Received: from smtp.infotech.no ([82.134.31.41]:56311 "EHLO smtp.infotech.no" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933020AbeCGDVp (ORCPT ); Tue, 6 Mar 2018 22:21:45 -0500 Received: from localhost (localhost [127.0.0.1]) by smtp.infotech.no (Postfix) with ESMTP id 507FB20423D; Wed, 7 Mar 2018 04:21:43 +0100 (CET) X-Virus-Scanned: by amavisd-new-2.6.6 (20110518) (Debian) at infotech.no Received: from smtp.infotech.no ([127.0.0.1]) by localhost (smtp.infotech.no [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 3vAGOJLZ4n2o; Wed, 7 Mar 2018 04:21:41 +0100 (CET) Received: from xtwo70.bingwo.ca (host-184-164-15-239.dyn.295.ca [184.164.15.239]) by smtp.infotech.no (Postfix) with ESMTPA id F0AD02041D7; Wed, 7 Mar 2018 04:21:39 +0100 (CET) From: Douglas Gilbert To: linux-scsi@vger.kernel.org Cc: martin.petersen@oracle.com, jejb@linux.vnet.ibm.com, hare@suse.de, bart.vanassche@wdc.com, jthumshirn@suse.de Subject: [PATCH 3/5] scsi_io_completion: add _action helper function Date: Tue, 6 Mar 2018 22:21:32 -0500 Message-Id: <20180307032134.18978-4-dgilbert@interlog.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20180307032134.18978-1-dgilbert@interlog.com> References: <20180307032134.18978-1-dgilbert@interlog.com> Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 Reviewed-by: Johannes Thumshirn --- 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;