--- drivers/scsi/scsi_lib.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) Index: linux-2.6/drivers/scsi/scsi_lib.c =================================================================== --- linux-2.6.orig/drivers/scsi/scsi_lib.c +++ linux-2.6/drivers/scsi/scsi_lib.c @@ -708,6 +708,7 @@ void scsi_io_completion(struct scsi_cmnd int result = cmd->result; struct request_queue *q = cmd->device->request_queue; struct request *req = cmd->request; + int set_req_errors = 0; int error = 0; struct scsi_sense_hdr sshdr; int sense_valid = 0; @@ -718,18 +719,12 @@ void scsi_io_completion(struct scsi_cmnd if (result) { sense_valid = scsi_command_normalize_sense(cmd, &sshdr); - if (sense_valid) + if (sense_valid) { sense_deferred = scsi_sense_is_deferred(&sshdr); - } - - if (req->cmd_type == REQ_TYPE_BLOCK_PC) { /* SG_IO ioctl from block level */ - req->errors = result; - req->cmd_flags |= REQ_SCSI_ERROR; - - if (result) { - if (sense_valid && req->sense) { + if (req->sense) { /* - * SG_IO wants current and deferred errors + * Save the current and deferred errors + * for upper layers. */ int len = 8 + cmd->sense_buffer[7]; @@ -738,9 +733,13 @@ void scsi_io_completion(struct scsi_cmnd memcpy(req->sense, cmd->sense_buffer, len); req->sense_len = len; } - if (!sense_deferred) - error = -EIO; } + } + + if (req->cmd_type == REQ_TYPE_BLOCK_PC) { /* SG_IO ioctl from block level */ + set_req_errors = 1; + if (result && !sense_deferred) + error = -EIO; req->resid_len = scsi_get_resid(cmd); @@ -757,6 +756,15 @@ void scsi_io_completion(struct scsi_cmnd scsi_next_command(cmd); return; } + } else if (req->cmd_type == REQ_TYPE_FS) { + /* Only set req->errors for genuine error cases */ + if (scsi_decide_disposition(cmd) == SUCCESS) + set_req_errors = 1; + } + + if (result && set_req_errors) { + req->errors = result; + req->cmd_flags |= REQ_SCSI_ERROR; } /* no bidi support for !REQ_TYPE_BLOCK_PC yet */