scsi: core: Add error codes for internal SCSI midlayer use
authorMike Christie <michael.christie@oracle.com>
Fri, 12 Aug 2022 01:00:25 +0000 (20:00 -0500)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 7 Sep 2022 02:05:59 +0000 (22:05 -0400)
If a driver returns:

 - DID_TARGET_FAILURE

 - DID_NEXUS_FAILURE

 - DID_ALLOC_FAILURE

 - DID_MEDIUM_ERROR

we hit a couple bugs:

1. The SCSI error handler runs because scsi_decide_disposition() has no
case statements for them and we return FAILED.

2. For SG IO the userspace app gets a success status instead of failed,
because scsi_result_to_blk_status() clears those errors.

This patch adds a new internal error code byte for use by the SCSI
midlayer.  This will be used instead of the above error codes, so we don't
have to play that clearing the host code game in
scsi_result_to_blk_status() and drivers cannot accidentally use them.

A subsequent commit will then remove the internal users of the above codes
and convert us to use the new ones.

Link: https://lore.kernel.org/r/20220812010027.8251-9-michael.christie@oracle.com
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Mike Christie <michael.christie@oracle.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/scsi_error.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_priv.h

index 448748e3fba5e156243d6f0e54276739ac734c82..d09b9ba1518c35cbc963fc99176a51a412e44e6b 100644 (file)
@@ -514,6 +514,11 @@ static void scsi_report_sense(struct scsi_device *sdev,
        }
 }
 
+static inline void set_scsi_ml_byte(struct scsi_cmnd *cmd, u8 status)
+{
+       cmd->result = (cmd->result & 0xffff00ff) | (status << 8);
+}
+
 /**
  * scsi_check_sense - Examine scsi cmd sense
  * @scmd:      Cmd to have sense checked.
index 4dbd29ab1dcc37792688849a468e5b8e5dc72ede..92b8c050697eb6fc76e33549b7cf1a02800976ad 100644 (file)
@@ -576,6 +576,11 @@ static bool scsi_end_request(struct request *req, blk_status_t error,
        return false;
 }
 
+static inline u8 get_scsi_ml_byte(int result)
+{
+       return (result >> 8) & 0xff;
+}
+
 /**
  * scsi_result_to_blk_status - translate a SCSI result code into blk_status_t
  * @cmd:       SCSI command
@@ -586,6 +591,23 @@ static bool scsi_end_request(struct request *req, blk_status_t error,
  */
 static blk_status_t scsi_result_to_blk_status(struct scsi_cmnd *cmd, int result)
 {
+       /*
+        * Check the scsi-ml byte first in case we converted a host or status
+        * byte.
+        */
+       switch (get_scsi_ml_byte(result)) {
+       case SCSIML_STAT_OK:
+               break;
+       case SCSIML_STAT_RESV_CONFLICT:
+               return BLK_STS_NEXUS;
+       case SCSIML_STAT_NOSPC:
+               return BLK_STS_NOSPC;
+       case SCSIML_STAT_MED_ERROR:
+               return BLK_STS_MEDIUM;
+       case SCSIML_STAT_TGT_FAILURE:
+               return BLK_STS_TARGET;
+       }
+
        switch (host_byte(result)) {
        case DID_OK:
                if (scsi_status_is_good(result))
index 429663bd78ecf74fc3c160d85e2ba8144d21fb01..2b9e0559ddcbb4774896c3d8f769c689bae94023 100644 (file)
@@ -18,6 +18,17 @@ struct scsi_nl_hdr;
 
 #define SCSI_CMD_RETRIES_NO_LIMIT -1
 
+/*
+ * Error codes used by scsi-ml internally. These must not be used by drivers.
+ */
+enum scsi_ml_status {
+       SCSIML_STAT_OK                  = 0x00,
+       SCSIML_STAT_RESV_CONFLICT       = 0x01, /* Reservation conflict */
+       SCSIML_STAT_NOSPC               = 0x02, /* Space allocation on the dev failed */
+       SCSIML_STAT_MED_ERROR           = 0x03, /* Medium error */
+       SCSIML_STAT_TGT_FAILURE         = 0x04, /* Permanent target failure */
+};
+
 /*
  * Scsi Error Handler Flags
  */