aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@HansenPartnership.com>2008-04-02 19:11:52 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-04-07 13:19:10 -0400
commitfa8e36c39b00a219d2c37250e493c3421e0e67e9 (patch)
tree81fae0291d92b703fa281dba31011b9e9c467f9a /drivers/scsi
parentbfab1637b5d0c9683016917fa8e082ba6ce8d5a6 (diff)
[SCSI] fix barrier failure issue
Currently, if the barrier command fails, the error return isn't seen by the block layer and it proceeds on regardless. The problem is that SCSI always returns no error for REQ_TYPE_BLOCK_PC ... it expects the submitter to pick the errors out of req->errors, which the block barrier functions don't do. Since it appears that the way SG_IO and scsi_execute_request() work they discard the block error return and always use req->errors, the best fix for this is to have the SCSI layer return an error to block if one actually occurred (this also allows us to filter out spurious errors, like deferred sense). This patch is a bug fix that will need backporting to stable, but it's also quite a big change and in need of testing, so we'll incubate in the main kernel tree and backport at the -rc2 or so stage if no problems turn up. Acked-by: Jens Axboe <jens.axboe@oracle.com> Cc: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/scsi_lib.c10
1 files changed, 4 insertions, 6 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 1b199e15ce9b..67f412bb4974 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -839,7 +839,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
839 int this_count = scsi_bufflen(cmd); 839 int this_count = scsi_bufflen(cmd);
840 struct request_queue *q = cmd->device->request_queue; 840 struct request_queue *q = cmd->device->request_queue;
841 struct request *req = cmd->request; 841 struct request *req = cmd->request;
842 int clear_errors = 1; 842 int error = 0;
843 struct scsi_sense_hdr sshdr; 843 struct scsi_sense_hdr sshdr;
844 int sense_valid = 0; 844 int sense_valid = 0;
845 int sense_deferred = 0; 845 int sense_deferred = 0;
@@ -853,7 +853,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
853 if (blk_pc_request(req)) { /* SG_IO ioctl from block level */ 853 if (blk_pc_request(req)) { /* SG_IO ioctl from block level */
854 req->errors = result; 854 req->errors = result;
855 if (result) { 855 if (result) {
856 clear_errors = 0;
857 if (sense_valid && req->sense) { 856 if (sense_valid && req->sense) {
858 /* 857 /*
859 * SG_IO wants current and deferred errors 858 * SG_IO wants current and deferred errors
@@ -865,6 +864,8 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
865 memcpy(req->sense, cmd->sense_buffer, len); 864 memcpy(req->sense, cmd->sense_buffer, len);
866 req->sense_len = len; 865 req->sense_len = len;
867 } 866 }
867 if (!sense_deferred)
868 error = -EIO;
868 } 869 }
869 if (scsi_bidi_cmnd(cmd)) { 870 if (scsi_bidi_cmnd(cmd)) {
870 /* will also release_buffers */ 871 /* will also release_buffers */
@@ -885,14 +886,11 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
885 "%d bytes done.\n", 886 "%d bytes done.\n",
886 req->nr_sectors, good_bytes)); 887 req->nr_sectors, good_bytes));
887 888
888 if (clear_errors)
889 req->errors = 0;
890
891 /* A number of bytes were successfully read. If there 889 /* A number of bytes were successfully read. If there
892 * are leftovers and there is some kind of error 890 * are leftovers and there is some kind of error
893 * (result != 0), retry the rest. 891 * (result != 0), retry the rest.
894 */ 892 */
895 if (scsi_end_request(cmd, 0, good_bytes, result == 0) == NULL) 893 if (scsi_end_request(cmd, error, good_bytes, result == 0) == NULL)
896 return; 894 return;
897 895
898 /* good_bytes = 0, or (inclusive) there were leftovers and 896 /* good_bytes = 0, or (inclusive) there were leftovers and