Commit 8de3ef25 authored by James Bottomley's avatar James Bottomley

[SCSI] libsas: misc fixes to the eh path

- Correct one use after free of the sas task
- update the reset required path to move straight to LUN reset
- make the bigger hammer actually reset something instead of just trying
  to clear all the tasks.
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent a29c0515
...@@ -498,10 +498,10 @@ int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd) ...@@ -498,10 +498,10 @@ int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd)
} }
/* Try to reset a device */ /* Try to reset a device */
static int try_to_reset_cmd_device(struct Scsi_Host *shost, static int try_to_reset_cmd_device(struct scsi_cmnd *cmd)
struct scsi_cmnd *cmd)
{ {
int res; int res;
struct Scsi_Host *shost = cmd->device->host;
if (!shost->hostt->eh_device_reset_handler) if (!shost->hostt->eh_device_reset_handler)
goto try_bus_reset; goto try_bus_reset;
...@@ -541,6 +541,12 @@ static int sas_eh_handle_sas_errors(struct Scsi_Host *shost, ...@@ -541,6 +541,12 @@ static int sas_eh_handle_sas_errors(struct Scsi_Host *shost,
need_reset = task->task_state_flags & SAS_TASK_NEED_DEV_RESET; need_reset = task->task_state_flags & SAS_TASK_NEED_DEV_RESET;
spin_unlock_irqrestore(&task->task_state_lock, flags); spin_unlock_irqrestore(&task->task_state_lock, flags);
if (need_reset) {
SAS_DPRINTK("%s: task 0x%p requests reset\n",
__FUNCTION__, task);
goto reset;
}
SAS_DPRINTK("trying to find task 0x%p\n", task); SAS_DPRINTK("trying to find task 0x%p\n", task);
res = sas_scsi_find_task(task); res = sas_scsi_find_task(task);
...@@ -551,18 +557,15 @@ static int sas_eh_handle_sas_errors(struct Scsi_Host *shost, ...@@ -551,18 +557,15 @@ static int sas_eh_handle_sas_errors(struct Scsi_Host *shost,
SAS_DPRINTK("%s: task 0x%p is done\n", __FUNCTION__, SAS_DPRINTK("%s: task 0x%p is done\n", __FUNCTION__,
task); task);
sas_eh_finish_cmd(cmd); sas_eh_finish_cmd(cmd);
if (need_reset)
try_to_reset_cmd_device(shost, cmd);
continue; continue;
case TASK_IS_ABORTED: case TASK_IS_ABORTED:
SAS_DPRINTK("%s: task 0x%p is aborted\n", SAS_DPRINTK("%s: task 0x%p is aborted\n",
__FUNCTION__, task); __FUNCTION__, task);
sas_eh_finish_cmd(cmd); sas_eh_finish_cmd(cmd);
if (need_reset)
try_to_reset_cmd_device(shost, cmd);
continue; continue;
case TASK_IS_AT_LU: case TASK_IS_AT_LU:
SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task); SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task);
reset:
tmf_resp = sas_recover_lu(task->dev, cmd); tmf_resp = sas_recover_lu(task->dev, cmd);
if (tmf_resp == TMF_RESP_FUNC_COMPLETE) { if (tmf_resp == TMF_RESP_FUNC_COMPLETE) {
SAS_DPRINTK("dev %016llx LU %x is " SAS_DPRINTK("dev %016llx LU %x is "
...@@ -570,8 +573,6 @@ static int sas_eh_handle_sas_errors(struct Scsi_Host *shost, ...@@ -570,8 +573,6 @@ static int sas_eh_handle_sas_errors(struct Scsi_Host *shost,
SAS_ADDR(task->dev), SAS_ADDR(task->dev),
cmd->device->lun); cmd->device->lun);
sas_eh_finish_cmd(cmd); sas_eh_finish_cmd(cmd);
if (need_reset)
try_to_reset_cmd_device(shost, cmd);
sas_scsi_clear_queue_lu(work_q, cmd); sas_scsi_clear_queue_lu(work_q, cmd);
goto Again; goto Again;
} }
...@@ -582,15 +583,15 @@ static int sas_eh_handle_sas_errors(struct Scsi_Host *shost, ...@@ -582,15 +583,15 @@ static int sas_eh_handle_sas_errors(struct Scsi_Host *shost,
task); task);
tmf_resp = sas_recover_I_T(task->dev); tmf_resp = sas_recover_I_T(task->dev);
if (tmf_resp == TMF_RESP_FUNC_COMPLETE) { if (tmf_resp == TMF_RESP_FUNC_COMPLETE) {
struct domain_device *dev = task->dev;
SAS_DPRINTK("I_T %016llx recovered\n", SAS_DPRINTK("I_T %016llx recovered\n",
SAS_ADDR(task->dev->sas_addr)); SAS_ADDR(task->dev->sas_addr));
sas_eh_finish_cmd(cmd); sas_eh_finish_cmd(cmd);
if (need_reset) sas_scsi_clear_queue_I_T(work_q, dev);
try_to_reset_cmd_device(shost, cmd);
sas_scsi_clear_queue_I_T(work_q, task->dev);
goto Again; goto Again;
} }
/* Hammer time :-) */ /* Hammer time :-) */
try_to_reset_cmd_device(cmd);
if (i->dft->lldd_clear_nexus_port) { if (i->dft->lldd_clear_nexus_port) {
struct asd_sas_port *port = task->dev->port; struct asd_sas_port *port = task->dev->port;
SAS_DPRINTK("clearing nexus for port:%d\n", SAS_DPRINTK("clearing nexus for port:%d\n",
...@@ -600,8 +601,6 @@ static int sas_eh_handle_sas_errors(struct Scsi_Host *shost, ...@@ -600,8 +601,6 @@ static int sas_eh_handle_sas_errors(struct Scsi_Host *shost,
SAS_DPRINTK("clear nexus port:%d " SAS_DPRINTK("clear nexus port:%d "
"succeeded\n", port->id); "succeeded\n", port->id);
sas_eh_finish_cmd(cmd); sas_eh_finish_cmd(cmd);
if (need_reset)
try_to_reset_cmd_device(shost, cmd);
sas_scsi_clear_queue_port(work_q, sas_scsi_clear_queue_port(work_q,
port); port);
goto Again; goto Again;
...@@ -614,8 +613,6 @@ static int sas_eh_handle_sas_errors(struct Scsi_Host *shost, ...@@ -614,8 +613,6 @@ static int sas_eh_handle_sas_errors(struct Scsi_Host *shost,
SAS_DPRINTK("clear nexus ha " SAS_DPRINTK("clear nexus ha "
"succeeded\n"); "succeeded\n");
sas_eh_finish_cmd(cmd); sas_eh_finish_cmd(cmd);
if (need_reset)
try_to_reset_cmd_device(shost, cmd);
goto clear_q; goto clear_q;
} }
} }
...@@ -629,8 +626,6 @@ static int sas_eh_handle_sas_errors(struct Scsi_Host *shost, ...@@ -629,8 +626,6 @@ static int sas_eh_handle_sas_errors(struct Scsi_Host *shost,
cmd->device->lun); cmd->device->lun);
sas_eh_finish_cmd(cmd); sas_eh_finish_cmd(cmd);
if (need_reset)
try_to_reset_cmd_device(shost, cmd);
goto clear_q; goto clear_q;
} }
} }
......
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