[SCSI] fix recovered error handling
authorJames Bottomley <James.Bottomley@HansenPartnership.com>
Mon, 30 Mar 2009 16:55:51 +0000 (16:55 +0000)
committerJames Bottomley <James.Bottomley@HansenPartnership.com>
Fri, 3 Apr 2009 14:22:55 +0000 (09:22 -0500)
We have a problem with recovered error handling in that any command
which goes down as BLOCK_PC but which returns a sense code of RECOVERED
ERROR gets completed with -EIO.  For actual SG_IO commands, this doesn't
matter at all, since the error return code gets dropped in favour of
req->errors which contain the SCSI completion code.

However, if this command is part of the block system, then it will pay
attention to the returned error code.  In particularly if a SYNCHRONIZE
CACHE from a barrier command completes with RECOVERED ERROR, the
resulting -EIO on the barrier causes block to error the request and
return it to the filesystem.  Fix this by converting the -EIO for
recovered error to zero, plus remove the printing of this from sd and sr
so the message isn't double printed.

Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
drivers/scsi/scsi_lib.c
drivers/scsi/sd.c
drivers/scsi/sr.c

index 4b13e36..d1cb64a 100644 (file)
@@ -791,7 +791,22 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                                      "%d bytes done.\n",
                                      req->nr_sectors, good_bytes));
 
-       /* A number of bytes were successfully read.  If there
+       /*
+        * Recovered errors need reporting, but they're always treated
+        * as success, so fiddle the result code here.  For BLOCK_PC
+        * we already took a copy of the original into rq->errors which
+        * is what gets returned to the user
+        */
+       if (sense_valid && sshdr.sense_key == RECOVERED_ERROR) {
+               if (!(req->cmd_flags & REQ_QUIET))
+                       scsi_print_sense("", cmd);
+               result = 0;
+               /* BLOCK_PC may have set error */
+               error = 0;
+       }
+
+       /*
+        * A number of bytes were successfully read.  If there
         * are leftovers and there is some kind of error
         * (result != 0), retry the rest.
         */
index aeab5d9..3fcb64b 100644 (file)
@@ -1051,12 +1051,6 @@ static int sd_done(struct scsi_cmnd *SCpnt)
                good_bytes = sd_completed_bytes(SCpnt);
                break;
        case RECOVERED_ERROR:
-               /* Inform the user, but make sure that it's not treated
-                * as a hard error.
-                */
-               scsi_print_sense("sd", SCpnt);
-               SCpnt->result = 0;
-               memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
                good_bytes = scsi_bufflen(SCpnt);
                break;
        case NO_SENSE:
index e7fa3ca..0e1a0f2 100644 (file)
@@ -309,15 +309,6 @@ static int sr_done(struct scsi_cmnd *SCpnt)
                        break;
 
                case RECOVERED_ERROR:
-
-                       /*
-                        * An error occured, but it recovered.  Inform the
-                        * user, but make sure that it's not treated as a
-                        * hard error.
-                        */
-                       scsi_print_sense("sr", SCpnt);
-                       SCpnt->result = 0;
-                       SCpnt->sense_buffer[0] = 0x0;
                        good_bytes = this_count;
                        break;