From patchwork Mon Aug 6 04:51:13 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Douglas Gilbert X-Patchwork-Id: 10556479 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1F83B13BB for ; Mon, 6 Aug 2018 04:51:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0D67828FFB for ; Mon, 6 Aug 2018 04:51:29 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 01ACC29006; Mon, 6 Aug 2018 04:51:28 +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=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, 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 90A8428FFB for ; Mon, 6 Aug 2018 04:51:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726921AbeHFG6n (ORCPT ); Mon, 6 Aug 2018 02:58:43 -0400 Received: from smtp.infotech.no ([82.134.31.41]:35024 "EHLO smtp.infotech.no" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726449AbeHFG6n (ORCPT ); Mon, 6 Aug 2018 02:58:43 -0400 Received: from localhost (localhost [127.0.0.1]) by smtp.infotech.no (Postfix) with ESMTP id F3E2D204177; Mon, 6 Aug 2018 06:51:25 +0200 (CEST) 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 RTBobEhsuwZR; Mon, 6 Aug 2018 06:51:24 +0200 (CEST) Received: from xtwo70.bingwo.ca (host-45-58-245-67.dyn.295.ca [45.58.245.67]) by smtp.infotech.no (Postfix) with ESMTPA id 3EB06204248; Mon, 6 Aug 2018 06:51:22 +0200 (CEST) From: Douglas Gilbert To: linux-scsi@vger.kernel.org Cc: martin.petersen@oracle.com, hare@suse.de, bart.vanassche@wdc.com, jthumshirn@suse.de Subject: [RFC PATCH 3/5] streamline REQ_OP_READ-WRITE access Date: Mon, 6 Aug 2018 00:51:13 -0400 Message-Id: <20180806045115.7725-4-dgilbert@interlog.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180806045115.7725-1-dgilbert@interlog.com> References: <20180806045115.7725-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 Make the two block layer operations most frequently used (REQ_OP_READ and REQ_OP_WRITE) bypass the switch statements in the submission and response paths. Assume these two enums are 0 and 1 which allows a single comparison to select both of them. Check that assumption at driver start-up. Signed-off-by: Douglas Gilbert --- drivers/scsi/sd.c | 82 +++++++++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 27 deletions(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 4b1402633c36..9f047fd3c92d 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1227,6 +1227,14 @@ static int sd_init_command(struct scsi_cmnd *cmd) { struct request *rq = cmd->request; + /* + * Assumption that REQ_OP_READ and REQ_OP_WRITE are 0 and 1 is + * checked in init_sd(). The following "if" is done to dispatch + * REQ_OP_READ and REQ_OP_WRITE quickly. + */ + if (likely(req_op(rq) < 2)) + return sd_setup_read_write_cmnd(cmd); + switch (req_op(rq)) { case REQ_OP_DISCARD: switch (scsi_disk(rq->rq_disk)->provisioning_mode) { @@ -1247,9 +1255,6 @@ static int sd_init_command(struct scsi_cmnd *cmd) return sd_setup_write_same_cmnd(cmd); case REQ_OP_FLUSH: return sd_setup_flush_cmnd(cmd); - case REQ_OP_READ: - case REQ_OP_WRITE: - return sd_setup_read_write_cmnd(cmd); case REQ_OP_ZONE_REPORT: return sd_zbc_setup_report_cmnd(cmd); case REQ_OP_ZONE_RESET: @@ -1973,30 +1978,12 @@ static int sd_done(struct scsi_cmnd *SCpnt) int sense_valid = 0; int sense_deferred = 0; - switch (req_op(req)) { - case REQ_OP_DISCARD: - case REQ_OP_WRITE_ZEROES: - case REQ_OP_WRITE_SAME: - case REQ_OP_ZONE_RESET: - if (!result) { - good_bytes = blk_rq_bytes(req); - scsi_set_resid(SCpnt, 0); - } else { - good_bytes = 0; - scsi_set_resid(SCpnt, blk_rq_bytes(req)); - } - break; - case REQ_OP_ZONE_REPORT: - if (!result) { - good_bytes = scsi_bufflen(SCpnt) - - scsi_get_resid(SCpnt); - scsi_set_resid(SCpnt, 0); - } else { - good_bytes = 0; - scsi_set_resid(SCpnt, blk_rq_bytes(req)); - } - break; - default: + /* + * Assumption that REQ_OP_READ and REQ_OP_WRITE are 0 and 1 is + * checked in init_sd(). The following "if" is done to expedite + * REQ_OP_READ and REQ_OP_WRITE. + */ + if (likely(req_op(req) < 2)) { /* * In case of bogus fw or device, we could end up having * an unaligned partial completion. Check this here and force @@ -2011,6 +1998,36 @@ static int sd_done(struct scsi_cmnd *SCpnt) round_up(resid, sector_size)); scsi_set_resid(SCpnt, resid); } + } else { + switch (req_op(req)) { + case REQ_OP_DISCARD: + case REQ_OP_WRITE_ZEROES: + case REQ_OP_WRITE_SAME: + case REQ_OP_ZONE_RESET: + if (!result) { + good_bytes = blk_rq_bytes(req); + scsi_set_resid(SCpnt, 0); + } else { + good_bytes = 0; + scsi_set_resid(SCpnt, blk_rq_bytes(req)); + } + break; + case REQ_OP_ZONE_REPORT: + if (!result) { + good_bytes = scsi_bufflen(SCpnt) + - scsi_get_resid(SCpnt); + scsi_set_resid(SCpnt, 0); + } else { + good_bytes = 0; + scsi_set_resid(SCpnt, blk_rq_bytes(req)); + } + break; + default: + sd_printk(KERN_NOTICE, sdkp, "unexpected REQ_OP=%u\n", + (unsigned int)req_op(req)); + WARN_ON_ONCE(true); + break; + } } if (result) { @@ -3597,6 +3614,17 @@ static int __init init_sd(void) int majors = 0, i, err; SCSI_LOG_HLQUEUE(3, printk("init_sd: sd driver entry point\n")); + /* + * The sd_init_command() and sd_done() assume REQ_OP_READ and + * REQ_OP_WRITE are 0 and 1 and will fail if they are not. If they + * are not, would prefer a compile failure but the preprocessor can't + * use enum constants. Place check here because only need to check + * early and once. + */ + if (REQ_OP_READ + REQ_OP_WRITE > 1) + pr_err("%s: REQ_OP_READ=%d REQ_OP_WRITE=%d %s.\n", __func__, + REQ_OP_READ, REQ_OP_WRITE, + "expected 0 and 1. Logic ERROR"); for (i = 0; i < SD_MAJORS; i++) { if (register_blkdev(sd_major(i), "sd") != 0)