forked from Minki/linux
[SCSI] libsas: prevent double completion of scmds from eh
We invoke task->task_done() to free the task in the eh case, but at this point we are prepared for scsi_eh_flush_done_q() to finish off the scmd. Introduce sas_end_task() to capture the final response status from the lldd and free the task. Also take the opportunity to kill this warning. drivers/scsi/libsas/sas_scsi_host.c: In function ‘sas_end_task’: drivers/scsi/libsas/sas_scsi_host.c:102:3: warning: case value ‘2’ not in enumerated type ‘enum exec_status’ [-Wswitch] Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
parent
3dff5721e4
commit
a3a142524a
@ -49,27 +49,12 @@
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/libata.h>
|
||||
|
||||
/* ---------- SCSI Host glue ---------- */
|
||||
|
||||
static void sas_scsi_task_done(struct sas_task *task)
|
||||
/* record final status and free the task */
|
||||
static void sas_end_task(struct scsi_cmnd *sc, struct sas_task *task)
|
||||
{
|
||||
struct task_status_struct *ts = &task->task_status;
|
||||
struct scsi_cmnd *sc = task->uldd_task;
|
||||
int hs = 0, stat = 0;
|
||||
|
||||
if (unlikely(task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
|
||||
/* Aborted tasks will be completed by the error handler */
|
||||
SAS_DPRINTK("task done but aborted\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (unlikely(!sc)) {
|
||||
SAS_DPRINTK("task_done called with non existing SCSI cmnd!\n");
|
||||
list_del_init(&task->list);
|
||||
sas_free_task(task);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ts->resp == SAS_TASK_UNDELIVERED) {
|
||||
/* transport error */
|
||||
hs = DID_NO_CONNECT;
|
||||
@ -124,10 +109,32 @@ static void sas_scsi_task_done(struct sas_task *task)
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSIGN_SAS_TASK(sc, NULL);
|
||||
|
||||
sc->result = (hs << 16) | stat;
|
||||
ASSIGN_SAS_TASK(sc, NULL);
|
||||
list_del_init(&task->list);
|
||||
sas_free_task(task);
|
||||
}
|
||||
|
||||
static void sas_scsi_task_done(struct sas_task *task)
|
||||
{
|
||||
struct scsi_cmnd *sc = task->uldd_task;
|
||||
|
||||
if (unlikely(task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
|
||||
/* Aborted tasks will be completed by the error handler */
|
||||
SAS_DPRINTK("task done but aborted\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (unlikely(!sc)) {
|
||||
SAS_DPRINTK("task_done called with non existing SCSI cmnd!\n");
|
||||
list_del_init(&task->list);
|
||||
sas_free_task(task);
|
||||
return;
|
||||
}
|
||||
|
||||
ASSIGN_SAS_TASK(sc, NULL);
|
||||
sas_end_task(sc, task);
|
||||
sc->scsi_done(sc);
|
||||
}
|
||||
|
||||
@ -236,18 +243,16 @@ static void sas_eh_finish_cmd(struct scsi_cmnd *cmd)
|
||||
struct sas_task *task = TO_SAS_TASK(cmd);
|
||||
struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(cmd->device->host);
|
||||
|
||||
/* remove the aborted task flag to allow the task to be
|
||||
* completed now. At this point, we only get called following
|
||||
* an actual abort of the task, so we should be guaranteed not
|
||||
* to be racing with any completions from the LLD (hence we
|
||||
* don't need the task state lock to clear the flag) */
|
||||
task->task_state_flags &= ~SAS_TASK_STATE_ABORTED;
|
||||
/* Now call task_done. However, task will be free'd after
|
||||
* this */
|
||||
task->task_done(task);
|
||||
/* At this point, we only get called following an actual abort
|
||||
* of the task, so we should be guaranteed not to be racing with
|
||||
* any completions from the LLD. Task is freed after this.
|
||||
*/
|
||||
sas_end_task(cmd, task);
|
||||
|
||||
/* now finish the command and move it on to the error
|
||||
* handler done list, this also takes it off the
|
||||
* error handler pending list */
|
||||
* error handler pending list.
|
||||
*/
|
||||
scsi_eh_finish_cmd(cmd, &sas_ha->eh_done_q);
|
||||
}
|
||||
|
||||
|
@ -452,7 +452,10 @@ enum service_response {
|
||||
};
|
||||
|
||||
enum exec_status {
|
||||
/* The SAM_STAT_.. codes fit in the lower 6 bits */
|
||||
/* The SAM_STAT_.. codes fit in the lower 6 bits, alias some of
|
||||
* them here to silence 'case value not in enumerated type' warnings
|
||||
*/
|
||||
__SAM_STAT_CHECK_CONDITION = SAM_STAT_CHECK_CONDITION,
|
||||
|
||||
SAS_DEV_NO_RESPONSE = 0x80,
|
||||
SAS_DATA_UNDERRUN,
|
||||
|
Loading…
Reference in New Issue
Block a user