A scsi command terminated with CHECK CONDITION is hijacked to execute
request sense with the original command information preserved and
restored respectively with scsi_eh_prep_cmnd() and
scsi_eh_restore_cmnd() in usb_stor_invoke_transport(). This means that
if the original command is retried, the command resid may not be 0,
indicating the residual at the time of the previous failed execution. If
the command is retried and fully succeed, the residual of 0 should thus
be set, always, to avoid reporting to the upper layer an incorrect
non-zero residual.

Cc: sta...@vger.kernel.org
Signed-off-by: Damien Le Moal <damien.lem...@wdc.com>
---
 drivers/usb/storage/transport.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 96cb0409dd89..c69fcbe467ef 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -1287,6 +1287,15 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, 
struct us_data *us)
                        scsi_set_resid(srb, max(scsi_get_resid(srb),
                                                               (int) residue));
                }
+       } else if (!residue) {
+               /*
+                * The command may have been retried after a CHECK CONDITION
+                * failure and autosense execution, which can result in resid
+                * to indicate the residual at the time of the failure instead
+                * of 0. Clear the resid here to indicate that the command
+                * fully completed.
+                */
+               scsi_set_resid(srb, 0);
        }
 
        /* based on the status code, we report good or bad */
-- 
2.21.0

Reply via email to