public inbox for linux-scsi@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0 of 4] DIF/DIX fixes for 2.6.29
@ 2009-01-04  8:04 Martin K. Petersen
  2009-01-04  8:04 ` [PATCH 1 of 4] scsi: Fix error handling for DIF/DIX Martin K. Petersen
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Martin K. Petersen @ 2009-01-04  8:04 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi


Data integrity bug fixes for 2.6.29.

2 files changed, 19 insertions(+), 7 deletions(-)
drivers/scsi/scsi_lib.c |    9 ++++++++-
drivers/scsi/sd_dif.c   |   17 +++++++++++------



^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1 of 4] scsi: Fix error handling for DIF/DIX
  2009-01-04  8:04 [PATCH 0 of 4] DIF/DIX fixes for 2.6.29 Martin K. Petersen
@ 2009-01-04  8:04 ` Martin K. Petersen
  2009-01-04  8:04 ` [PATCH 2 of 4] sd: Show app tag on error Martin K. Petersen
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Martin K. Petersen @ 2009-01-04  8:04 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi

Alan's recent cleanup of the I/O completion code broke DIX error
handling.  Also, we are now using EILSEQ to indicate integrity errors to
the upper layers (as opposed to regular EIO failures).  This allows
filesystems to inspect buffers and decide whether to retry the I/O.
Update scsi_io_completion() accordingly.

Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

---
1 file changed, 8 insertions(+), 1 deletion(-)
drivers/scsi/scsi_lib.c |    9 ++++++++-



diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -963,6 +963,8 @@ void scsi_io_completion(struct scsi_cmnd
 		return;
 	this_count = blk_rq_bytes(req);
 
+	error = -EIO;
+
 	if (host_byte(result) == DID_RESET) {
 		/* Third party bus reset or reset for error recovery
 		 * reasons.  Just retry the command and see what
@@ -1004,13 +1006,18 @@ void scsi_io_completion(struct scsi_cmnd
 				/* This will issue a new 6-byte command. */
 				cmd->device->use_10_for_rw = 0;
 				action = ACTION_REPREP;
+			} else if (sshdr.asc == 0x10) /* DIX */ {
+				description = "Host Data Integrity Failure";
+				action = ACTION_FAIL;
+				error = -EILSEQ;
 			} else
 				action = ACTION_FAIL;
 			break;
 		case ABORTED_COMMAND:
 			if (sshdr.asc == 0x10) { /* DIF */
+				description = "Target Data Integrity Failure";
 				action = ACTION_FAIL;
-				description = "Data Integrity Failure";
+				error = -EILSEQ;
 			} else
 				action = ACTION_RETRY;
 			break;



^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 2 of 4] sd: Show app tag on error
  2009-01-04  8:04 [PATCH 0 of 4] DIF/DIX fixes for 2.6.29 Martin K. Petersen
  2009-01-04  8:04 ` [PATCH 1 of 4] scsi: Fix error handling for DIF/DIX Martin K. Petersen
@ 2009-01-04  8:04 ` Martin K. Petersen
  2009-01-04  8:04 ` [PATCH 3 of 4] sd: Fix tagging on platforms with signed char Martin K. Petersen
  2009-01-04  8:04 ` [PATCH 4 of 4] sd: Correctly handle 6-byte commands with DIX Martin K. Petersen
  3 siblings, 0 replies; 7+ messages in thread
From: Martin K. Petersen @ 2009-01-04  8:04 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi

Add application tag to the output displayed on error.

Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

---
1 file changed, 3 insertions(+), 2 deletions(-)
drivers/scsi/sd_dif.c |    5 +++--



diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c
--- a/drivers/scsi/sd_dif.c
+++ b/drivers/scsi/sd_dif.c
@@ -475,8 +475,9 @@ int sd_dif_prepare(struct request *rq, s
 
 error:
 	kunmap_atomic(sdt, KM_USER0);
-	sd_printk(KERN_ERR, sdkp, "%s: virt %u, phys %u, ref %u\n",
-		  __func__, virt, phys, be32_to_cpu(sdt->ref_tag));
+	sd_printk(KERN_ERR, sdkp, "%s: virt %u, phys %u, ref %u, app %4x\n",
+		  __func__, virt, phys, be32_to_cpu(sdt->ref_tag),
+		  be16_to_cpu(sdt->app_tag));
 
 	return -EIO;
 }



^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 3 of 4] sd: Fix tagging on platforms with signed char
  2009-01-04  8:04 [PATCH 0 of 4] DIF/DIX fixes for 2.6.29 Martin K. Petersen
  2009-01-04  8:04 ` [PATCH 1 of 4] scsi: Fix error handling for DIF/DIX Martin K. Petersen
  2009-01-04  8:04 ` [PATCH 2 of 4] sd: Show app tag on error Martin K. Petersen
@ 2009-01-04  8:04 ` Martin K. Petersen
  2009-01-04  8:04 ` [PATCH 4 of 4] sd: Correctly handle 6-byte commands with DIX Martin K. Petersen
  3 siblings, 0 replies; 7+ messages in thread
From: Martin K. Petersen @ 2009-01-04  8:04 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi

Switch tag arrays to u8 to prevent problems on platforms with signed
char.

Reported-by: Tim LaBerge <tim.laberge@Quantum.Com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

---
1 file changed, 4 insertions(+), 4 deletions(-)
drivers/scsi/sd_dif.c |    8 ++++----



diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c
--- a/drivers/scsi/sd_dif.c
+++ b/drivers/scsi/sd_dif.c
@@ -142,7 +142,7 @@ static void sd_dif_type1_set_tag(void *p
 static void sd_dif_type1_set_tag(void *prot, void *tag_buf, unsigned int sectors)
 {
 	struct sd_dif_tuple *sdt = prot;
-	char *tag = tag_buf;
+	u8 *tag = tag_buf;
 	unsigned int i, j;
 
 	for (i = 0, j = 0 ; i < sectors ; i++, j += 2, sdt++) {
@@ -154,7 +154,7 @@ static void sd_dif_type1_get_tag(void *p
 static void sd_dif_type1_get_tag(void *prot, void *tag_buf, unsigned int sectors)
 {
 	struct sd_dif_tuple *sdt = prot;
-	char *tag = tag_buf;
+	u8 *tag = tag_buf;
 	unsigned int i, j;
 
 	for (i = 0, j = 0 ; i < sectors ; i++, j += 2, sdt++) {
@@ -256,7 +256,7 @@ static void sd_dif_type3_set_tag(void *p
 static void sd_dif_type3_set_tag(void *prot, void *tag_buf, unsigned int sectors)
 {
 	struct sd_dif_tuple *sdt = prot;
-	char *tag = tag_buf;
+	u8 *tag = tag_buf;
 	unsigned int i, j;
 
 	for (i = 0, j = 0 ; i < sectors ; i++, j += 6, sdt++) {
@@ -269,7 +269,7 @@ static void sd_dif_type3_get_tag(void *p
 static void sd_dif_type3_get_tag(void *prot, void *tag_buf, unsigned int sectors)
 {
 	struct sd_dif_tuple *sdt = prot;
-	char *tag = tag_buf;
+	u8 *tag = tag_buf;
 	unsigned int i, j;
 
 	for (i = 0, j = 0 ; i < sectors ; i++, j += 2, sdt++) {



^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 4 of 4] sd: Correctly handle 6-byte commands with DIX
  2009-01-04  8:04 [PATCH 0 of 4] DIF/DIX fixes for 2.6.29 Martin K. Petersen
                   ` (2 preceding siblings ...)
  2009-01-04  8:04 ` [PATCH 3 of 4] sd: Fix tagging on platforms with signed char Martin K. Petersen
@ 2009-01-04  8:04 ` Martin K. Petersen
  2009-01-04 13:28   ` Matthew Wilcox
  3 siblings, 1 reply; 7+ messages in thread
From: Martin K. Petersen @ 2009-01-04  8:04 UTC (permalink / raw)
  To: James.Bottomley, linux-scsi

DIF does not work with 6-byte commands so we previously ignored those
commands when preparing a request.  However, DIX does not need
RDPROTECT/WRPROTECT to be set and 6-byte commands are consequently
perfectly valid in host-only mode.

This patch fixes a problem where we would set the wrong DIX operation
when issuing commands to a legacy disk.

Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

---
1 file changed, 4 insertions(+)
drivers/scsi/sd_dif.c |    4 ++++



diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c
--- a/drivers/scsi/sd_dif.c
+++ b/drivers/scsi/sd_dif.c
@@ -374,7 +374,10 @@ void sd_dif_op(struct scsi_cmnd *scmd, u
 	else
 		csum_convert = 0;
 
+	BUG_ON(dif && (scmd->cmnd[0] == READ_6 || scmd->cmnd[0] == WRITE_6));
+
 	switch (scmd->cmnd[0]) {
+	case READ_6:
 	case READ_10:
 	case READ_12:
 	case READ_16:
@@ -390,6 +393,7 @@ void sd_dif_op(struct scsi_cmnd *scmd, u
 
 		break;
 
+	case WRITE_6:
 	case WRITE_10:
 	case WRITE_12:
 	case WRITE_16:



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 4 of 4] sd: Correctly handle 6-byte commands with DIX
  2009-01-04  8:04 ` [PATCH 4 of 4] sd: Correctly handle 6-byte commands with DIX Martin K. Petersen
@ 2009-01-04 13:28   ` Matthew Wilcox
  2009-01-05  2:35     ` Martin K. Petersen
  0 siblings, 1 reply; 7+ messages in thread
From: Matthew Wilcox @ 2009-01-04 13:28 UTC (permalink / raw)
  To: Martin K. Petersen; +Cc: James.Bottomley, linux-scsi

On Sun, Jan 04, 2009 at 03:04:34AM -0500, Martin K. Petersen wrote:
> @@ -374,7 +374,10 @@ void sd_dif_op(struct scsi_cmnd *scmd, u
>  	else
>  		csum_convert = 0;
>  
> +	BUG_ON(dif && (scmd->cmnd[0] == READ_6 || scmd->cmnd[0] == WRITE_6));

This BUG_ON gave me a 'Huh?' moment.  I immediately wondered if it was
user-triggerable.  The answer is "no, this is kosher".  sd_dif_op() is
only called from sd.c where it has chosen which READ_*/WRITE_* opcode to
set up, and it would indeed be an internal bug for this combination of
conditions to exist.

Reviewed-by: Matthew Wilcox <willy@linux.intel.com>

> +
>  	switch (scmd->cmnd[0]) {
> +	case READ_6:
>  	case READ_10:
>  	case READ_12:
>  	case READ_16:
> @@ -390,6 +393,7 @@ void sd_dif_op(struct scsi_cmnd *scmd, u
>  
>  		break;
>  
> +	case WRITE_6:
>  	case WRITE_10:
>  	case WRITE_12:
>  	case WRITE_16:
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Matthew Wilcox				Intel Open Source Technology Centre
"Bill, look, we understand that you're interested in selling us this
operating system, but compare it to ours.  We can't possibly take such
a retrograde step."

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 4 of 4] sd: Correctly handle 6-byte commands with DIX
  2009-01-04 13:28   ` Matthew Wilcox
@ 2009-01-05  2:35     ` Martin K. Petersen
  0 siblings, 0 replies; 7+ messages in thread
From: Martin K. Petersen @ 2009-01-05  2:35 UTC (permalink / raw)
  To: Matthew Wilcox; +Cc: Martin K. Petersen, James.Bottomley, linux-scsi

>>>>> "Matthew" == Matthew Wilcox <matthew@wil.cx> writes:

>> + BUG_ON(dif && (scmd->cmnd[0] == READ_6 || scmd->cmnd[0] ==
>>  	WRITE_6));

Matthew> This BUG_ON gave me a 'Huh?' moment.  I immediately wondered if
Matthew> it was user-triggerable.  The answer is "no, this is kosher".
Matthew> sd_dif_op() is only called from sd.c where it has chosen which
Matthew> READ_*/WRITE_* opcode to set up, and it would indeed be an
Matthew> internal bug for this combination of conditions to exist.

Yep, I recently had to track down a bug where we had accidentally (for
completely different reasons) switched to 6-byte commands.  The code in
the completion path that triggered this condition is now gone, thanks to
Alan.  But I left the BUG_ON in place because it was no fun track this
down.

-- 
Martin K. Petersen	Oracle Linux Engineering

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2009-01-05  2:35 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-01-04  8:04 [PATCH 0 of 4] DIF/DIX fixes for 2.6.29 Martin K. Petersen
2009-01-04  8:04 ` [PATCH 1 of 4] scsi: Fix error handling for DIF/DIX Martin K. Petersen
2009-01-04  8:04 ` [PATCH 2 of 4] sd: Show app tag on error Martin K. Petersen
2009-01-04  8:04 ` [PATCH 3 of 4] sd: Fix tagging on platforms with signed char Martin K. Petersen
2009-01-04  8:04 ` [PATCH 4 of 4] sd: Correctly handle 6-byte commands with DIX Martin K. Petersen
2009-01-04 13:28   ` Matthew Wilcox
2009-01-05  2:35     ` Martin K. Petersen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox