When a command is terminated with CHECK CONDITION and request sense executed by hijacking the command descriptor, the original command resid is lost and replaced with the resid from the execution of request sense. If based on the obtained sense data the command is aborted and not retried, the resid that will be seen by drivers such as sd will be the resid of the request sense execution and not the value from the original command failure. Make sure this does not happen by adding resid as part of the command information saved using struct scsi_eh_save. Cc: stable@xxxxxxxxxxxxxxx Signed-off-by: Damien Le Moal <damien.lemoal@xxxxxxx> --- drivers/scsi/scsi_error.c | 2 ++ include/scsi/scsi_eh.h | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 1c470e31ae81..d4ac13979189 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -967,6 +967,7 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses, ses->data_direction = scmd->sc_data_direction; ses->sdb = scmd->sdb; ses->result = scmd->result; + ses->resid = scsi_get_resid(scmd); ses->underflow = scmd->underflow; ses->prot_op = scmd->prot_op; ses->eh_eflags = scmd->eh_eflags; @@ -1029,6 +1030,7 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses) scmd->sc_data_direction = ses->data_direction; scmd->sdb = ses->sdb; scmd->result = ses->result; + scsi_set_resid(scmd, ses->resid); scmd->underflow = ses->underflow; scmd->prot_op = ses->prot_op; scmd->eh_eflags = ses->eh_eflags; diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h index 3810b340551c..9caa9b262a32 100644 --- a/include/scsi/scsi_eh.h +++ b/include/scsi/scsi_eh.h @@ -32,6 +32,7 @@ extern int scsi_ioctl_reset(struct scsi_device *, int __user *); struct scsi_eh_save { /* saved state */ int result; + unsigned int resid; int eh_eflags; enum dma_data_direction data_direction; unsigned underflow; -- 2.21.0