[SCSI] libsas: Reset timer on taskless scsi_cmnds in sas_scsi_timed_out
Every so often, a scsi_cmnd will time out, and the libsas timeout handler will discover that the scsi_cmnd does not have a sas_task attached to it. This can happen in two cases: (1) the scsi_cmnd actually made it through libsas to the HBA and is now going through scsi_done, or (2) the scsi_cmnd has been held up (host lock, slab alloc, etc) and libsas has not yet attached a sas_task. In both cases, it is safe to ask SCSI for more time to process the command via EH_RESET_TIMER; we cannot blindly return EH_HANDLED because if (2) happens, we could end up calling scsi_done while another CPU is heading towards sas_queuecommand, which causes slab corruption when sas_task_done updates the freed scsi_cmnd. Signed-off-by: Darrick J. Wong <djwong@us.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
parent
acbf167d4a
commit
6d4dcd4dae
|
@ -524,9 +524,13 @@ enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd)
|
|||
unsigned long flags;
|
||||
|
||||
if (!task) {
|
||||
SAS_DPRINTK("command 0x%p, task 0x%p, gone: EH_HANDLED\n",
|
||||
cmd, task);
|
||||
return EH_HANDLED;
|
||||
cmd->timeout_per_command /= 2;
|
||||
SAS_DPRINTK("command 0x%p, task 0x%p, gone: %s\n",
|
||||
cmd, task, (cmd->timeout_per_command ?
|
||||
"EH_RESET_TIMER" : "EH_NOT_HANDLED"));
|
||||
if (!cmd->timeout_per_command)
|
||||
return EH_NOT_HANDLED;
|
||||
return EH_RESET_TIMER;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&task->task_state_lock, flags);
|
||||
|
|
Loading…
Reference in New Issue