]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
scsi: qedf: Add synchronization between I/O completions and abort
authorJaved Hasan <jhasan@marvell.com>
Fri, 1 Sep 2023 06:06:46 +0000 (11:36 +0530)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 5 Sep 2023 09:57:49 +0000 (05:57 -0400)
Avoid race condition between I/O completion and abort processing by
protecting the cmd_type with the rport lock.

Signed-off-by: Javed Hasan <jhasan@marvell.com>
Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
Link: https://lore.kernel.org/r/20230901060646.27885-1-skashyap@marvell.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/qedf/qedf_io.c
drivers/scsi/qedf/qedf_main.c

index 4750ec5789a80db9f07060599d3705ddc6bcc062..10fe3383855c00558e0ffc26268023001376f796 100644 (file)
@@ -1904,6 +1904,7 @@ int qedf_initiate_abts(struct qedf_ioreq *io_req, bool return_scsi_cmd_on_abts)
                goto drop_rdata_kref;
        }
 
+       spin_lock_irqsave(&fcport->rport_lock, flags);
        if (!test_bit(QEDF_CMD_OUTSTANDING, &io_req->flags) ||
            test_bit(QEDF_CMD_IN_CLEANUP, &io_req->flags) ||
            test_bit(QEDF_CMD_IN_ABORT, &io_req->flags)) {
@@ -1911,17 +1912,20 @@ int qedf_initiate_abts(struct qedf_ioreq *io_req, bool return_scsi_cmd_on_abts)
                         "io_req xid=0x%x sc_cmd=%p already in cleanup or abort processing or already completed.\n",
                         io_req->xid, io_req->sc_cmd);
                rc = 1;
+               spin_unlock_irqrestore(&fcport->rport_lock, flags);
                goto drop_rdata_kref;
        }
 
+       /* Set the command type to abort */
+       io_req->cmd_type = QEDF_ABTS;
+       spin_unlock_irqrestore(&fcport->rport_lock, flags);
+
        kref_get(&io_req->refcount);
 
        xid = io_req->xid;
        qedf->control_requests++;
        qedf->packet_aborts++;
 
-       /* Set the command type to abort */
-       io_req->cmd_type = QEDF_ABTS;
        io_req->return_scsi_cmd_on_abts = return_scsi_cmd_on_abts;
 
        set_bit(QEDF_CMD_IN_ABORT, &io_req->flags);
@@ -2210,7 +2214,9 @@ process_els:
                  refcount, fcport, fcport->rdata->ids.port_id);
 
        /* Cleanup cmds re-use the same TID as the original I/O */
+       spin_lock_irqsave(&fcport->rport_lock, flags);
        io_req->cmd_type = QEDF_CLEANUP;
+       spin_unlock_irqrestore(&fcport->rport_lock, flags);
        io_req->return_scsi_cmd_on_abts = return_scsi_cmd_on_abts;
 
        init_completion(&io_req->cleanup_done);
index 7825765c936cd651b276af2507799664b5cedeb1..91f3f1d7098eb5b4b0680fb127ebc1978ec08f53 100644 (file)
@@ -2805,6 +2805,8 @@ void qedf_process_cqe(struct qedf_ctx *qedf, struct fcoe_cqe *cqe)
        struct qedf_ioreq *io_req;
        struct qedf_rport *fcport;
        u32 comp_type;
+       u8 io_comp_type;
+       unsigned long flags;
 
        comp_type = (cqe->cqe_data >> FCOE_CQE_CQE_TYPE_SHIFT) &
            FCOE_CQE_CQE_TYPE_MASK;
@@ -2838,11 +2840,14 @@ void qedf_process_cqe(struct qedf_ctx *qedf, struct fcoe_cqe *cqe)
                return;
        }
 
+       spin_lock_irqsave(&fcport->rport_lock, flags);
+       io_comp_type = io_req->cmd_type;
+       spin_unlock_irqrestore(&fcport->rport_lock, flags);
 
        switch (comp_type) {
        case FCOE_GOOD_COMPLETION_CQE_TYPE:
                atomic_inc(&fcport->free_sqes);
-               switch (io_req->cmd_type) {
+               switch (io_comp_type) {
                case QEDF_SCSI_CMD:
                        qedf_scsi_completion(qedf, cqe, io_req);
                        break;