Skip to content

Commit 318aaf3

Browse files
JasonYanHwmartinkpetersen
authored andcommitted
scsi: libsas: defer ata device eh commands to libata
When ata device doing EH, some commands still attached with tasks are not passed to libata when abort failed or recover failed, so libata did not handle these commands. After these commands done, sas task is freed, but ata qc is not freed. This will cause ata qc leak and trigger a warning like below: WARNING: CPU: 0 PID: 28512 at drivers/ata/libata-eh.c:4037 ata_eh_finish+0xb4/0xcc CPU: 0 PID: 28512 Comm: kworker/u32:2 Tainted: G W OE 4.14.0#1 ...... Call trace: [<ffff0000088b7bd0>] ata_eh_finish+0xb4/0xcc [<ffff0000088b8420>] ata_do_eh+0xc4/0xd8 [<ffff0000088b8478>] ata_std_error_handler+0x44/0x8c [<ffff0000088b8068>] ata_scsi_port_error_handler+0x480/0x694 [<ffff000008875fc4>] async_sas_ata_eh+0x4c/0x80 [<ffff0000080f6be8>] async_run_entry_fn+0x4c/0x170 [<ffff0000080ebd70>] process_one_work+0x144/0x390 [<ffff0000080ec100>] worker_thread+0x144/0x418 [<ffff0000080f2c98>] kthread+0x10c/0x138 [<ffff0000080855dc>] ret_from_fork+0x10/0x18 If ata qc leaked too many, ata tag allocation will fail and io blocked for ever. As suggested by Dan Williams, defer ata device commands to libata and merge sas_eh_finish_cmd() with sas_eh_defer_cmd(). libata will handle ata qcs correctly after this. Signed-off-by: Jason Yan <[email protected]> CC: Xiaofei Tan <[email protected]> CC: John Garry <[email protected]> CC: Dan Williams <[email protected]> Reviewed-by: Dan Williams <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 20bd1d0 commit 318aaf3

File tree

1 file changed

+13
-20
lines changed

1 file changed

+13
-20
lines changed

drivers/scsi/libsas/sas_scsi_host.c

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ int sas_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
223223
static void sas_eh_finish_cmd(struct scsi_cmnd *cmd)
224224
{
225225
struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(cmd->device->host);
226+
struct domain_device *dev = cmd_to_domain_dev(cmd);
226227
struct sas_task *task = TO_SAS_TASK(cmd);
227228

228229
/* At this point, we only get called following an actual abort
@@ -231,37 +232,29 @@ static void sas_eh_finish_cmd(struct scsi_cmnd *cmd)
231232
*/
232233
sas_end_task(cmd, task);
233234

235+
if (dev_is_sata(dev)) {
236+
/* defer commands to libata so that libata EH can
237+
* handle ata qcs correctly
238+
*/
239+
list_move_tail(&cmd->eh_entry, &sas_ha->eh_ata_q);
240+
return;
241+
}
242+
234243
/* now finish the command and move it on to the error
235244
* handler done list, this also takes it off the
236245
* error handler pending list.
237246
*/
238247
scsi_eh_finish_cmd(cmd, &sas_ha->eh_done_q);
239248
}
240249

241-
static void sas_eh_defer_cmd(struct scsi_cmnd *cmd)
242-
{
243-
struct domain_device *dev = cmd_to_domain_dev(cmd);
244-
struct sas_ha_struct *ha = dev->port->ha;
245-
struct sas_task *task = TO_SAS_TASK(cmd);
246-
247-
if (!dev_is_sata(dev)) {
248-
sas_eh_finish_cmd(cmd);
249-
return;
250-
}
251-
252-
/* report the timeout to libata */
253-
sas_end_task(cmd, task);
254-
list_move_tail(&cmd->eh_entry, &ha->eh_ata_q);
255-
}
256-
257250
static void sas_scsi_clear_queue_lu(struct list_head *error_q, struct scsi_cmnd *my_cmd)
258251
{
259252
struct scsi_cmnd *cmd, *n;
260253

261254
list_for_each_entry_safe(cmd, n, error_q, eh_entry) {
262255
if (cmd->device->sdev_target == my_cmd->device->sdev_target &&
263256
cmd->device->lun == my_cmd->device->lun)
264-
sas_eh_defer_cmd(cmd);
257+
sas_eh_finish_cmd(cmd);
265258
}
266259
}
267260

@@ -618,12 +611,12 @@ static void sas_eh_handle_sas_errors(struct Scsi_Host *shost, struct list_head *
618611
case TASK_IS_DONE:
619612
SAS_DPRINTK("%s: task 0x%p is done\n", __func__,
620613
task);
621-
sas_eh_defer_cmd(cmd);
614+
sas_eh_finish_cmd(cmd);
622615
continue;
623616
case TASK_IS_ABORTED:
624617
SAS_DPRINTK("%s: task 0x%p is aborted\n",
625618
__func__, task);
626-
sas_eh_defer_cmd(cmd);
619+
sas_eh_finish_cmd(cmd);
627620
continue;
628621
case TASK_IS_AT_LU:
629622
SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task);
@@ -634,7 +627,7 @@ static void sas_eh_handle_sas_errors(struct Scsi_Host *shost, struct list_head *
634627
"recovered\n",
635628
SAS_ADDR(task->dev),
636629
cmd->device->lun);
637-
sas_eh_defer_cmd(cmd);
630+
sas_eh_finish_cmd(cmd);
638631
sas_scsi_clear_queue_lu(work_q, cmd);
639632
goto Again;
640633
}

0 commit comments

Comments
 (0)