Commit 52aeeca9 authored by Michael Reed's avatar Michael Reed Committed by James Bottomley

[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: default avatarMichael Reed <mdr@sgi.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent cec744fb
...@@ -449,6 +449,7 @@ EXPORT_SYMBOL_GPL(scsi_execute_async); ...@@ -449,6 +449,7 @@ EXPORT_SYMBOL_GPL(scsi_execute_async);
static void scsi_init_cmd_errh(struct scsi_cmnd *cmd) static void scsi_init_cmd_errh(struct scsi_cmnd *cmd)
{ {
cmd->serial_number = 0; cmd->serial_number = 0;
cmd->resid = 0;
memset(cmd->sense_buffer, 0, sizeof cmd->sense_buffer); memset(cmd->sense_buffer, 0, sizeof cmd->sense_buffer);
if (cmd->cmd_len == 0) if (cmd->cmd_len == 0)
cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]); cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment