[SCSI] Fix USB deadlock caused by SCSI error handling
authorHannes Reinecke <hare@suse.de>
Mon, 31 Mar 2014 14:37:34 +0000 (16:37 +0200)
committerJames Bottomley <JBottomley@Parallels.com>
Mon, 21 Apr 2014 21:28:26 +0000 (14:28 -0700)
USB requires that every command be aborted first before we escalate to reset.
In particular, USB will deadlock if we try to reset first before aborting the
command.

Unfortunately, the flag we use to tell if a command has already been aborted:
SCSI_EH_ABORT_SCHEDULED is not cleared properly leading to cases where we can
requeue a command with the flag set and proceed immediately to reset if it
fails (thus causing USB to deadlock).

Fix by clearing the SCSI_EH_ABORT_SCHEDULED flag if it has been set.  Which
means this will be the second time scsi_abort_command() has been called for
the same command.  IE the first abort went out, did its thing, but now the
same command has timed out again.

So this flag gets cleared, and scsi_abort_command() returns FAILED, and _no_
asynchronous abort is being scheduled.  scsi_times_out() will then proceed to
call scsi_eh_scmd_add().  But as we've cleared the SCSI_EH_ABORT_SCHEDULED
flag the SCSI_EH_CANCEL_CMD flag will continue to be set, and the command will
be aborted with the main SCSI EH routine.

Reported-by: Alan Stern <stern@rowland.harvard.edu>
Tested-by: Andreas Reis <andreas.reis@gmail.com>
Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/scsi_error.c

index 2953bfa92da7bf7b2d7268cc44563ab6a5d2c623..ad064d2d730bd331954d582282929fa959fdc0ca 100644 (file)
@@ -189,6 +189,7 @@ scsi_abort_command(struct scsi_cmnd *scmd)
                /*
                 * Retry after abort failed, escalate to next level.
                 */
+               scmd->eh_eflags &= ~SCSI_EH_ABORT_SCHEDULED;
                SCSI_LOG_ERROR_RECOVERY(3,
                        scmd_printk(KERN_INFO, scmd,
                                    "scmd %p previous abort failed\n", scmd));
This page took 0.042256 seconds and 5 git commands to generate.