scsi: core: Make SCSI Status CONDITION MET equivalent to GOOD
authorDouglas Gilbert <dgilbert@interlog.com>
Wed, 7 Mar 2018 03:19:49 +0000 (22:19 -0500)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 13 Mar 2018 01:55:24 +0000 (21:55 -0400)
The SCSI PRE-FETCH (10 or 16) command is present both on hard disks
and some SSDs. It is useful when the address of the next block(s) to
be read is known but it is not following the LBA of the current READ
(so read-ahead won't help). It returns two "good" SCSI Status values.
If the requested blocks have fitted (or will most likely fit (when
the IMMED bit is set)) into the disk's cache, it returns CONDITION
MET. If it didn't (or will not) fit then it returns GOOD status.

The goal of this patch is to stop the SCSI subsystem treating the
CONDITION MET SCSI status as an error. The current state makes the
PRE-FETCH command effectively unusable via pass-throughs.

Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
Reviewed-by: Bart Van Assche <bart.vanassche@wdc.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/scsi_lib.c
include/scsi/scsi.h

index 10430d500792eeab6f0e68efdadd05681f0d5602..393f9db8f41bf0eaa5f106af5722a122d923d112 100644 (file)
@@ -867,6 +867,17 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                /* for passthrough error may be set */
                error = BLK_STS_OK;
        }
+       /*
+        * Another corner case: the SCSI status byte is non-zero but 'good'.
+        * Example: PRE-FETCH command returns SAM_STAT_CONDITION_MET when
+        * it is able to fit nominated LBs in its cache (and SAM_STAT_GOOD
+        * if it can't fit). Treat SAM_STAT_CONDITION_MET and the related
+        * intermediate statuses (both obsolete in SAM-4) as good.
+        */
+       if (status_byte(result) && scsi_status_is_good(result)) {
+               result = 0;
+               error = BLK_STS_OK;
+       }
 
        /*
         * special case: failed zero length commands always need to
index cb85eddb47ea816347322c728c818f8e7fda0226..eb7853c1a23b8511fef8eb7b9ca1c85441f1cb38 100644 (file)
@@ -47,6 +47,8 @@ static inline int scsi_status_is_good(int status)
         */
        status &= 0xfe;
        return ((status == SAM_STAT_GOOD) ||
+               (status == SAM_STAT_CONDITION_MET) ||
+               /* Next two "intermediate" statuses are obsolete in SAM-4 */
                (status == SAM_STAT_INTERMEDIATE) ||
                (status == SAM_STAT_INTERMEDIATE_CONDITION_MET) ||
                /* FIXME: this is obsolete in SAM-3 */