Skip to contentSkip to conversation

scsi: More detailed I/O errors

PATCH Superseded Hannes Reinecke 1 participant 4 messages Jun 6, 2013

Subsystems (3)

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

v2 cover scsi: More detailed I/O errors

As discussed at LSF the SCSI stack already knows about several error conditions, it's just not well documented. Also there are some more conditions upper layers might be interested in.

This patchset improves the documentation of the existing I/O error codes and adds two more error codes, ENOSPC for thin provisioning failure and ENODATA for medium error.

Changes since the initial version, suggested by Ren Mingxin:
- Add error description to blk_update_request()
- Document missing values

Hannes Reinecke (3):
scsi: Document enhanced error codes
scsi: Return ENOSPC on thin provisioning failure
scsi: Return ENODATA on medium error

 block/blk-core.c          |  6 ++++++
 drivers/scsi/scsi_error.c | 27 +++++++++++++++++++++++----
 drivers/scsi/scsi_lib.c   | 22 ++++++++++++++++++++++
 include/scsi/scsi.h       |  4 ++++
 4 files changed, 55 insertions(+), 4 deletions(-)
Signature · 1 line
1.7.12.4
#1 lore raw

PATCH v2 1/3 scsi: Document enhanced error codes

Document the various error codes returned on I/O failure.

---
 drivers/scsi/scsi_error.c |  8 ++++++--
 drivers/scsi/scsi_lib.c   | 12 ++++++++++++
 2 files changed, 18 insertions(+), 2 deletions(-)
drivers/scsi/scsi_error.c +6 -2
index f43de1e..5319eda 100644
@@ -229,8 +229,12 @@ static inline void scsi_eh_prt_fail_stats(struct Scsi_Host *shost,
  * scsi_check_sense - Examine scsi cmd sense
  * @scmd:	Cmd to have sense checked.
  *
- * Return value:
- *	SUCCESS or FAILED or NEEDS_RETRY or TARGET_ERROR
+ * Possible return values:
+ *	SUCCESS
+ *	FAILED
+ *	NEEDS_RETRY
+ *	TARGET_ERROR
+ *	ADD_TO_MLQUEUE
  *
  * Notes:
  *	When a deferred error is detected the current command has
drivers/scsi/scsi_lib.c +12 -0
index 86d5220..9bfee08 100644
@@ -700,6 +700,18 @@ void scsi_release_buffers(struct scsi_cmnd *cmd)
 }
 EXPORT_SYMBOL(scsi_release_buffers);
 
+/**
+ * __scsi_error_from_host_byte - translate SCSI error code into errno
+ * @cmd:	SCSI command (unused)
+ * @result:	scsi error code
+ *
+ * Translate SCSI error code into standard UNIX errno.
+ * Return values:
+ * -ENOLINK	temporary transport failure
+ * -EREMOTEIO	permanent target failure, do not retry
+ * -EBADE	permanent nexus failure, retry on other path
+ * -EIO		unclassified I/O error
+ */
 static int __scsi_error_from_host_byte(struct scsi_cmnd *cmd, int result)
 {
 	int error = 0;
Signature · 1 line
1.7.12.4
#2 lore raw

PATCH v2 2/3 scsi: Return ENOSPC on thin provisioning failure

In reply to Hannes Reinecke

When the thin provisioning hard threshold is reached we should return ENOSPC to inform upper layers about this fact.

---
 block/blk-core.c          |  3 +++
 drivers/scsi/scsi_error.c | 12 +++++++++++-
 drivers/scsi/scsi_lib.c   |  5 +++++
 include/scsi/scsi.h       |  2 ++
 4 files changed, 21 insertions(+), 1 deletion(-)
block/blk-core.c +3 -0
index 33c33bc..dab068b 100644
@@ -2315,6 +2315,9 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
 		case -EBADE:
 			error_type = "critical nexus";
 			break;
+		case -ENOSPC:
+			error_type = "space allocation";
+			break;
 		case -EIO:
 		default:
 			error_type = "I/O";
drivers/scsi/scsi_error.c +11 -1
index 5319eda..eff9b55 100644
@@ -235,6 +235,7 @@ static inline void scsi_eh_prt_fail_stats(struct Scsi_Host *shost,
  *	NEEDS_RETRY
  *	TARGET_ERROR
  *	ADD_TO_MLQUEUE
+ *	ALLOC_ERROR
  *
  * Notes:
  *	When a deferred error is detected the current command has
@@ -360,11 +361,15 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
 		return SUCCESS;
 
 		/* these are not supported */
+	case DATA_PROTECT:
+		if (sshdr.asc == 0x27 && sshdr.ascq == 0x07) {
+			/* Thin provisioning hard threshold reached */
+			return ALLOC_ERROR;
+		}
 	case COPY_ABORTED:
 	case VOLUME_OVERFLOW:
 	case MISCOMPARE:
 	case BLANK_CHECK:
-	case DATA_PROTECT:
 		return TARGET_ERROR;
 
 	case MEDIUM_ERROR:
@@ -850,6 +855,7 @@ retry:
 		case NEEDS_RETRY:
 		case FAILED:
 		case TARGET_ERROR:
+		case ALLOC_ERROR:
 			break;
 		case ADD_TO_MLQUEUE:
 			rtn = NEEDS_RETRY;
@@ -1589,6 +1595,10 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
 			 */
 			set_host_byte(scmd, DID_TARGET_FAILURE);
 			rtn = SUCCESS;
+		} else if (rtn == ALLOC_ERROR) {
+			/* target hit out-of-space condition */
+			set_host_byte(scmd, DID_ALLOC_FAILURE);
+			rtn = SUCCESS;
 		}
 		/* if rtn == FAILED, we have no sense information;
 		 * returning FAILED will wake the error handler thread
drivers/scsi/scsi_lib.c +5 -0
index 9bfee08..8de6697 100644
@@ -710,6 +710,7 @@ EXPORT_SYMBOL(scsi_release_buffers);
  * -ENOLINK	temporary transport failure
  * -EREMOTEIO	permanent target failure, do not retry
  * -EBADE	permanent nexus failure, retry on other path
+ * -ENOSPC	No write space available
  * -EIO		unclassified I/O error
  */
 static int __scsi_error_from_host_byte(struct scsi_cmnd *cmd, int result)
@@ -728,6 +729,10 @@ static int __scsi_error_from_host_byte(struct scsi_cmnd *cmd, int result)
 		set_host_byte(cmd, DID_OK);
 		error = -EBADE;
 		break;
+	case DID_ALLOC_FAILURE:
+		set_host_byte(cmd, DID_OK);
+		error = -ENOSPC;
+		break;
 	default:
 		error = -EIO;
 		break;
include/scsi/scsi.h +2 -0
index 66216c1..5ead86b 100644
@@ -452,6 +452,7 @@ static inline int scsi_is_wlun(unsigned int lun)
 				 * other paths */
 #define DID_NEXUS_FAILURE 0x11  /* Permanent nexus failure, retry on other
 				 * paths might yield different results */
+#define DID_ALLOC_FAILURE 0x12  /* Space allocation on the device failed */
 #define DRIVER_OK       0x00	/* Driver status                           */
 
 /*
@@ -482,6 +483,7 @@ static inline int scsi_is_wlun(unsigned int lun)
 #define SCSI_RETURN_NOT_HANDLED   0x2008
 #define FAST_IO_FAIL	0x2009
 #define TARGET_ERROR    0x200A
+#define ALLOC_ERROR     0x200B
 
 /*
  * Midlevel queue return values.
Signature · 1 line
1.7.12.4
#3 lore raw

PATCH v2 3/3 scsi: Return ENODATA on medium error

In reply to Hannes Reinecke

When a medium error is detected the SCSI stack should return ENODATA to the upper layers.

---
 block/blk-core.c          | 3 +++
 drivers/scsi/scsi_error.c | 7 ++++++-
 drivers/scsi/scsi_lib.c   | 5 +++++
 include/scsi/scsi.h       | 2 ++
 4 files changed, 16 insertions(+), 1 deletion(-)
block/blk-core.c +3 -0
index dab068b..c5548a4 100644
@@ -2318,6 +2318,9 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
 		case -ENOSPC:
 			error_type = "space allocation";
 			break;
+		case -ENODATA:
+			error_type = "medium";
+			break;
 		case -EIO:
 		default:
 			error_type = "I/O";
drivers/scsi/scsi_error.c +6 -1
index eff9b55..0a9e3f3 100644
@@ -236,6 +236,7 @@ static inline void scsi_eh_prt_fail_stats(struct Scsi_Host *shost,
  *	TARGET_ERROR
  *	ADD_TO_MLQUEUE
  *	ALLOC_ERROR
+ *	MEDIA_FAILURE
  *
  * Notes:
  *	When a deferred error is detected the current command has
@@ -376,7 +377,7 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
 		if (sshdr.asc == 0x11 || /* UNRECOVERED READ ERR */
 		    sshdr.asc == 0x13 || /* AMNF DATA FIELD */
 		    sshdr.asc == 0x14) { /* RECORD NOT FOUND */
-			return TARGET_ERROR;
+			return MEDIA_FAILURE;
 		}
 		return NEEDS_RETRY;
 
@@ -1599,6 +1600,10 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
 			/* target hit out-of-space condition */
 			set_host_byte(scmd, DID_ALLOC_FAILURE);
 			rtn = SUCCESS;
+		} else if (rtn == MEDIA_FAILURE) {
+			/* medium error */
+			set_host_byte(scmd, DID_MEDIUM_ERROR);
+			rtn = SUCCESS;
 		}
 		/* if rtn == FAILED, we have no sense information;
 		 * returning FAILED will wake the error handler thread
drivers/scsi/scsi_lib.c +5 -0
index 8de6697..27ec5b4 100644
@@ -711,6 +711,7 @@ EXPORT_SYMBOL(scsi_release_buffers);
  * -EREMOTEIO	permanent target failure, do not retry
  * -EBADE	permanent nexus failure, retry on other path
  * -ENOSPC	No write space available
+ * -ENODATA	Medium error
  * -EIO		unclassified I/O error
  */
 static int __scsi_error_from_host_byte(struct scsi_cmnd *cmd, int result)
@@ -733,6 +734,10 @@ static int __scsi_error_from_host_byte(struct scsi_cmnd *cmd, int result)
 		set_host_byte(cmd, DID_OK);
 		error = -ENOSPC;
 		break;
+	case DID_MEDIUM_ERROR:
+		set_host_byte(cmd, DID_OK);
+		error = -ENODATA;
+		break;
 	default:
 		error = -EIO;
 		break;
include/scsi/scsi.h +2 -0
index 5ead86b..c397684 100644
@@ -453,6 +453,7 @@ static inline int scsi_is_wlun(unsigned int lun)
 #define DID_NEXUS_FAILURE 0x11  /* Permanent nexus failure, retry on other
 				 * paths might yield different results */
 #define DID_ALLOC_FAILURE 0x12  /* Space allocation on the device failed */
+#define DID_MEDIUM_ERROR  0x13  /* Medium error */
 #define DRIVER_OK       0x00	/* Driver status                           */
 
 /*
@@ -484,6 +485,7 @@ static inline int scsi_is_wlun(unsigned int lun)
 #define FAST_IO_FAIL	0x2009
 #define TARGET_ERROR    0x200A
 #define ALLOC_ERROR     0x200B
+#define MEDIA_FAILURE   0x200C
 
 /*
  * Midlevel queue return values.
Signature · 1 line
1.7.12.4