[PATCH 4/5][Bionic] scsi: hisi_sas: fix the risk of freeing slot twice

dann frazier dann.frazier at canonical.com
Fri Dec 22 21:50:39 UTC 2017

From: Xiaofei Tan <tanxiaofei at huawei.com>

BugLink: https://bugs.launchpad.net/bugs/1739807

The function hisi_sas_slot_task_free() is used to free the slot and do
tidy-up of LLDD resources. The LLDD generally should know the state of
a slot and decide when to free it, and it should only be done once.

For some scenarios, we really don't know the state, like when TMF
timeout. In this case, we check task->lldd_task before calling

However, we may miss some scenarios when we should also check
task->lldd_task, and it is not SMP safe to check task->lldd_task as we
don't protect it within spin lock.

This patch is to fix this risk of freeing slot twice, as follows:

  1. Check task->lldd_task in the hisi_sas_slot_task_free(), and give
     up freeing of this time if task->lldd_task is NULL.

  2. Set slot->buf to NULL after it is freed.

Signed-off-by: Xiaofei Tan <tanxiaofei at huawei.com>
Signed-off-by: John Garry <john.garry at huawei.com>
Signed-off-by: Martin K. Petersen <martin.petersen at oracle.com>
(cherry picked from commit 6ba0fbc35aa9f3bc8c12be3b4047055c9ce2ac92)
Signed-off-by: dann frazier <dann.frazier at canonical.com>
 drivers/scsi/hisi_sas/hisi_sas_main.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 3384e7a5d4b1..e2ed753e76dd 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -185,13 +185,16 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task,
 		struct domain_device *device = task->dev;
 		struct hisi_sas_device *sas_dev = device->lldd_dev;
+		if (!task->lldd_task)
+			return;
+		task->lldd_task = NULL;
 		if (!sas_protocol_ata(task->task_proto))
 			if (slot->n_elem)
 				dma_unmap_sg(dev, task->scatter, slot->n_elem,
-		task->lldd_task = NULL;
 		if (sas_dev)
@@ -199,8 +202,8 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task,
 	if (slot->buf)
 		dma_pool_free(hisi_hba->buffer_pool, slot->buf, slot->buf_dma);
+	slot->buf = NULL;
 	slot->task = NULL;
 	slot->port = NULL;
 	hisi_sas_slot_index_free(hisi_hba, slot->idx);

More information about the kernel-team mailing list