[RFC PATCH 2/5] break sd_done sense processing out to own function

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

 



Break out the sense key handling in the sd_done() (response) path into
its own function. Note that the sense key only needs to be inspected
when a SCSI status of Check Condition is returned.


Signed-off-by: Douglas Gilbert <dgilbert@xxxxxxxxxxxx>
---

No speed up here, just a clean up. There could possibly be a speed
improvement (not observed in tests) from lessening the cache footprint
of the sd_done() function which is on the fast path.


 drivers/scsi/sd.c | 112 ++++++++++++++++++++++++----------------------
 1 file changed, 59 insertions(+), 53 deletions(-)

diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index b17b8c66881d..4b1402633c36 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1898,6 +1898,62 @@ static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd)
 	return min(good_bytes, transferred);
 }
 
+/* Helper for scsi_done() when there is a sense buffer */
+static int sd_done_sense(struct scsi_cmnd *SCpnt, unsigned int good_bytes,
+			 struct scsi_sense_hdr *sshdrp)
+{
+	struct request *req = SCpnt->request;
+	struct scsi_disk *sdkp = scsi_disk(SCpnt->request->rq_disk);
+
+	switch (sshdrp->sense_key) {
+	case HARDWARE_ERROR:
+	case MEDIUM_ERROR:
+		return sd_completed_bytes(SCpnt);
+	case RECOVERED_ERROR:
+		return scsi_bufflen(SCpnt);
+	case NO_SENSE:
+		/* This indicates a false check condition, so ignore it.  An
+		 * unknown amount of data was transferred so treat it as an
+		 * error.
+		 */
+		SCpnt->result = 0;
+		memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
+		break;
+	case ABORTED_COMMAND:
+		if (sshdrp->asc == 0x10)  /* DIF: Target detected corruption */
+			good_bytes = sd_completed_bytes(SCpnt);
+		break;
+	case ILLEGAL_REQUEST:
+		switch (sshdrp->asc) {
+		case 0x10:	/* DIX: Host detected corruption */
+			good_bytes = sd_completed_bytes(SCpnt);
+			break;
+		case 0x20:	/* INVALID COMMAND OPCODE */
+		case 0x24:	/* INVALID FIELD IN CDB */
+			switch (SCpnt->cmnd[0]) {
+			case UNMAP:
+				sd_config_discard(sdkp, SD_LBP_DISABLE);
+				break;
+			case WRITE_SAME_16:
+			case WRITE_SAME:
+				if (SCpnt->cmnd[1] & 8) { /* UNMAP */
+					sd_config_discard(sdkp, SD_LBP_DISABLE);
+				} else {
+					sdkp->device->no_write_same = 1;
+					sd_config_write_same(sdkp);
+					req->__data_len = blk_rq_bytes(req);
+					req->rq_flags |= RQF_QUIET;
+				}
+				break;
+			}
+		}
+		break;
+	default:
+		break;
+	}
+	return good_bytes;
+}
+
 /**
  *	sd_done - bottom half handler: called when the lower level
  *	driver has completed (successfully or otherwise) a scsi command.
@@ -1964,60 +2020,10 @@ static int sd_done(struct scsi_cmnd *SCpnt)
 	}
 	sdkp->medium_access_timed_out = 0;
 
-	if (driver_byte(result) != DRIVER_SENSE &&
-	    (!sense_valid || sense_deferred))
-		goto out;
+	if (unlikely(driver_byte(result) == DRIVER_SENSE ||
+		     (sense_valid && !sense_deferred)))
+		good_bytes = sd_done_sense(SCpnt, good_bytes, &sshdr);
 
-	switch (sshdr.sense_key) {
-	case HARDWARE_ERROR:
-	case MEDIUM_ERROR:
-		good_bytes = sd_completed_bytes(SCpnt);
-		break;
-	case RECOVERED_ERROR:
-		good_bytes = scsi_bufflen(SCpnt);
-		break;
-	case NO_SENSE:
-		/* This indicates a false check condition, so ignore it.  An
-		 * unknown amount of data was transferred so treat it as an
-		 * error.
-		 */
-		SCpnt->result = 0;
-		memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
-		break;
-	case ABORTED_COMMAND:
-		if (sshdr.asc == 0x10)  /* DIF: Target detected corruption */
-			good_bytes = sd_completed_bytes(SCpnt);
-		break;
-	case ILLEGAL_REQUEST:
-		switch (sshdr.asc) {
-		case 0x10:	/* DIX: Host detected corruption */
-			good_bytes = sd_completed_bytes(SCpnt);
-			break;
-		case 0x20:	/* INVALID COMMAND OPCODE */
-		case 0x24:	/* INVALID FIELD IN CDB */
-			switch (SCpnt->cmnd[0]) {
-			case UNMAP:
-				sd_config_discard(sdkp, SD_LBP_DISABLE);
-				break;
-			case WRITE_SAME_16:
-			case WRITE_SAME:
-				if (SCpnt->cmnd[1] & 8) { /* UNMAP */
-					sd_config_discard(sdkp, SD_LBP_DISABLE);
-				} else {
-					sdkp->device->no_write_same = 1;
-					sd_config_write_same(sdkp);
-					req->__data_len = blk_rq_bytes(req);
-					req->rq_flags |= RQF_QUIET;
-				}
-				break;
-			}
-		}
-		break;
-	default:
-		break;
-	}
-
- out:
 	if (sd_is_zoned(sdkp))
 		sd_zbc_complete(SCpnt, good_bytes, &sshdr);
 
-- 
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