Thread (3 messages) 3 messages, 3 authors, 2021-07-29

Re: [PATCH] scsi: pm80xx: Fix tmf task completion race condition

From: Jinpu Wang <jinpu.wang@ionos.com>
Date: 2021-07-27 05:20:01

On Wed, Jul 7, 2021 at 8:59 PM Igor Pylypiv [off-list ref] wrote:
The tmf timeout timer may trigger at the same time when the response
from a controller is being handled. When this happens the sas task may
get freed before the response processing is finished.

Fix this by calling complete() only when SAS_TASK_STATE_DONE is not set.

Similar race condition was fixed in commit b90cd6f2b905
("scsi: libsas: fix a race condition when smp task timeout")

Reviewed-by: Vishakha Channapattan <redacted>
Signed-off-by: Igor Pylypiv <redacted>
Looks good to me, thx, sorry for late reply, somehow I missed it.
Acked-by: Jack Wang <jinpu.wang@ionos.com>
quoted hunk ↗ jump to hunk
---
 drivers/scsi/pm8001/pm8001_sas.c | 32 +++++++++++++++-----------------
 1 file changed, 15 insertions(+), 17 deletions(-)
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 6f33d821e545..1d35587c28e0 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -682,8 +682,7 @@ int pm8001_dev_found(struct domain_device *dev)

 void pm8001_task_done(struct sas_task *task)
 {
-       if (!del_timer(&task->slow_task->timer))
-               return;
+       del_timer(&task->slow_task->timer);
        complete(&task->slow_task->completion);
 }
@@ -691,9 +690,14 @@ static void pm8001_tmf_timedout(struct timer_list *t)
 {
        struct sas_task_slow *slow = from_timer(slow, t, timer);
        struct sas_task *task = slow->task;
+       unsigned long flags;

-       task->task_state_flags |= SAS_TASK_STATE_ABORTED;
-       complete(&task->slow_task->completion);
+       spin_lock_irqsave(&task->task_state_lock, flags);
+       if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
+               task->task_state_flags |= SAS_TASK_STATE_ABORTED;
+               complete(&task->slow_task->completion);
+       }
+       spin_unlock_irqrestore(&task->task_state_lock, flags);
 }

 #define PM8001_TASK_TIMEOUT 20
@@ -746,13 +750,10 @@ static int pm8001_exec_internal_tmf_task(struct domain_device *dev,
                }
                res = -TMF_RESP_FUNC_FAILED;
                /* Even TMF timed out, return direct. */
-               if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
-                       if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
-                               pm8001_dbg(pm8001_ha, FAIL,
-                                          "TMF task[%x]timeout.\n",
-                                          tmf->tmf);
-                               goto ex_err;
-                       }
+               if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
+                       pm8001_dbg(pm8001_ha, FAIL, "TMF task[%x]timeout.\n",
+                                  tmf->tmf);
+                       goto ex_err;
                }

                if (task->task_status.resp == SAS_TASK_COMPLETE &&
@@ -832,12 +833,9 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha,
                wait_for_completion(&task->slow_task->completion);
                res = TMF_RESP_FUNC_FAILED;
                /* Even TMF timed out, return direct. */
-               if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
-                       if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
-                               pm8001_dbg(pm8001_ha, FAIL,
-                                          "TMF task timeout.\n");
-                               goto ex_err;
-                       }
+               if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
+                       pm8001_dbg(pm8001_ha, FAIL, "TMF task timeout.\n");
+                       goto ex_err;
                }

                if (task->task_status.resp == SAS_TASK_COMPLETE &&
--
2.32.0.93.g670b81a890-goog
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help