aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_lib.c
diff options
context:
space:
mode:
authorMichael Reed <mdr@sgi.com>2007-09-17 18:11:39 -0400
committerJames Bottomley <jejb@mulgrave.localdomain>2007-10-12 14:49:04 -0400
commit52aeeca9001d1b4037a8e5d0c001ebb5fdc61b37 (patch)
tree6da81f575055bb26f960d80e9b2c6d1b03567cc8 /drivers/scsi/scsi_lib.c
parentcec744fb2b78e9dcd377a6740f2de05227c7faef (diff)
[SCSI] stale residual returned on write following BUSY retry
A BUSY status returned on a write request results in a stale residual being returned when the write ultimately successfully completes. This can be reproduced as follows: 1) issue immediate mode rewind to scsi tape drive 2) issue write request The tape drive returns busy. The low level driver detects underrun and sets the residual into the scsi command. The low level driver responds with (DID_OK << 16) | scsi_status. scsi_status is 8, hence status_byte(result) == 4, i.e., BUSY. scsi_softirq_done() calls scsi_decide_disposition() which returns ADD_TO_MLQUEUE. scsi_softirq_done() then calls scsi_queue_insert() which, on the way to resubmitting the request to the driver, calls scsi_init_cmd_errh(). The attached patch modifies scsi_init_cmd_errh() to clear the resid field. This prevents a "stale" residual from being returned when the scsi command finally completes without a BUSY status. Signed-off-by: Michael Reed <mdr@sgi.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
-rw-r--r--drivers/scsi/scsi_lib.c1
1 files changed, 1 insertions, 0 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 277f1b64e9ac..47d3cdd6ddf1 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -449,6 +449,7 @@ EXPORT_SYMBOL_GPL(scsi_execute_async);
449static void scsi_init_cmd_errh(struct scsi_cmnd *cmd) 449static void scsi_init_cmd_errh(struct scsi_cmnd *cmd)
450{ 450{
451 cmd->serial_number = 0; 451 cmd->serial_number = 0;
452 cmd->resid = 0;
452 memset(cmd->sense_buffer, 0, sizeof cmd->sense_buffer); 453 memset(cmd->sense_buffer, 0, sizeof cmd->sense_buffer);
453 if (cmd->cmd_len == 0) 454 if (cmd->cmd_len == 0)
454 cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]); 455 cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);