[SCSI] fix recovered error handling
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>
This commit is contained in:
@@ -791,7 +791,22 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
|
|||||||
"%d bytes done.\n",
|
"%d bytes done.\n",
|
||||||
req->nr_sectors, good_bytes));
|
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
|
* are leftovers and there is some kind of error
|
||||||
* (result != 0), retry the rest.
|
* (result != 0), retry the rest.
|
||||||
*/
|
*/
|
||||||
|
@@ -1051,12 +1051,6 @@ static int sd_done(struct scsi_cmnd *SCpnt)
|
|||||||
good_bytes = sd_completed_bytes(SCpnt);
|
good_bytes = sd_completed_bytes(SCpnt);
|
||||||
break;
|
break;
|
||||||
case RECOVERED_ERROR:
|
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);
|
good_bytes = scsi_bufflen(SCpnt);
|
||||||
break;
|
break;
|
||||||
case NO_SENSE:
|
case NO_SENSE:
|
||||||
|
@@ -309,15 +309,6 @@ static int sr_done(struct scsi_cmnd *SCpnt)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case RECOVERED_ERROR:
|
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;
|
good_bytes = this_count;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user