[RFC PATCH 3/5] streamline REQ_OP_READ-WRITE access

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 <dgilbert@xxxxxxxxxxxx>
---
 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)
-- 
2.17.1




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]

  Powered by Linux