]>
Commit | Line | Data |
---|---|---|
82094b55 AF |
1 | From: James Bottomley <James.Bottomley@HansenPartnership.com> |
2 | Date: Mon Mar 30 16:55:51 2009 +0000 | |
3 | X-Git: a9bddd74630b2a1f2dedc537417c372b2d9edc76 | |
4 | Subject: scsi: fix recovered error handling | |
5 | References: bnc#487412 | |
6 | ||
7 | We have a problem with recovered error handling in that any command | |
8 | which goes down as BLOCK_PC but which returns a sense code of RECOVERED | |
9 | ERROR gets completed with -EIO. For actual SG_IO commands, this doesn't | |
10 | matter at all, since the error return code gets dropped in favour of | |
11 | req->errors which contain the SCSI completion code. | |
12 | ||
13 | However, if this command is part of the block system, then it will pay | |
14 | attention to the returned error code. In particularly if a SYNCHRONIZE | |
15 | CACHE from a barrier command completes with RECOVERED ERROR, the | |
16 | resulting -EIO on the barrier causes block to error the request and | |
17 | return it to the filesystem. Fix this by converting the -EIO for | |
18 | recovered error to zero, plus remove the printing of this from sd and | |
19 | sr so the message isn't double printed. | |
20 | ||
21 | Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com> | |
22 | Signed-off-by: Hannes Reinecke <hare@suse.de> | |
23 | ||
24 | diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c | |
25 | index 4b13e36..d1cb64a 100644 | |
26 | --- a/drivers/scsi/scsi_lib.c | |
27 | +++ b/drivers/scsi/scsi_lib.c | |
28 | @@ -791,7 +791,22 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) | |
29 | "%d bytes done.\n", | |
30 | req->nr_sectors, good_bytes)); | |
31 | ||
32 | - /* A number of bytes were successfully read. If there | |
33 | + /* | |
34 | + * Recovered errors need reporting, but they're always treated | |
35 | + * as success, so fiddle the result code here. For BLOCK_PC | |
36 | + * we already took a copy of the original into rq->errors which | |
37 | + * is what gets returned to the user | |
38 | + */ | |
39 | + if (sense_valid && sshdr.sense_key == RECOVERED_ERROR) { | |
40 | + if (!(req->cmd_flags & REQ_QUIET)) | |
41 | + scsi_print_sense("", cmd); | |
42 | + result = 0; | |
43 | + /* BLOCK_PC may have set error */ | |
44 | + error = 0; | |
45 | + } | |
46 | + | |
47 | + /* | |
48 | + * A number of bytes were successfully read. If there | |
49 | * are leftovers and there is some kind of error | |
50 | * (result != 0), retry the rest. | |
51 | */ | |
52 | diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c | |
53 | index aeab5d9..3fcb64b 100644 | |
54 | --- a/drivers/scsi/sd.c | |
55 | +++ b/drivers/scsi/sd.c | |
56 | @@ -1051,12 +1051,6 @@ static int sd_done(struct scsi_cmnd *SCpnt) | |
57 | good_bytes = sd_completed_bytes(SCpnt); | |
58 | break; | |
59 | case RECOVERED_ERROR: | |
60 | - /* Inform the user, but make sure that it's not treated | |
61 | - * as a hard error. | |
62 | - */ | |
63 | - scsi_print_sense("sd", SCpnt); | |
64 | - SCpnt->result = 0; | |
65 | - memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); | |
66 | good_bytes = scsi_bufflen(SCpnt); | |
67 | break; | |
68 | case NO_SENSE: | |
69 | diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c | |
70 | index e7fa3ca..0e1a0f2 100644 | |
71 | --- a/drivers/scsi/sr.c | |
72 | +++ b/drivers/scsi/sr.c | |
73 | @@ -309,15 +309,6 @@ static int sr_done(struct scsi_cmnd *SCpnt) | |
74 | break; | |
75 | ||
76 | case RECOVERED_ERROR: | |
77 | - | |
78 | - /* | |
79 | - * An error occured, but it recovered. Inform the | |
80 | - * user, but make sure that it's not treated as a | |
81 | - * hard error. | |
82 | - */ | |
83 | - scsi_print_sense("sr", SCpnt); | |
84 | - SCpnt->result = 0; | |
85 | - SCpnt->sense_buffer[0] = 0x0; | |
86 | good_bytes = this_count; | |
87 | break; | |
88 |