diff mbox series

[v2,6/7] qla2xxx: Wait for io return on terminate rport

Message ID 20230428075339.32551-7-njavali@marvell.com
State Superseded
Headers show
Series qla2xxx driver update | expand

Commit Message

Nilesh Javali April 28, 2023, 7:53 a.m. UTC
From: Quinn Tran <qutran@marvell.com>

System crash due to use after free.
Current code allows terminate_rport_io to exit before making
sure all IOs has returned. For FCP-2 device, IO's can hang
on in HW because driver has not tear down the session in FW at
first sign of cable pull. When dev_loss_tmo timer pops,
terminate_rport_io is called and upper layer is about to
free various resources. Terminate_rport_io trigger qla to do
the final cleanup, but the cleanup might not be fast enough where it
leave qla still holding on to the same resource.

Wait for IO's to return to upper layer before resources are freed.

Cc: stable@vger.kernel.org
Signed-off-by: Quinn Tran <qutran@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
---
 drivers/scsi/qla2xxx/qla_attr.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

Comments

Himanshu Madhani May 1, 2023, 3:10 p.m. UTC | #1
> On Apr 28, 2023, at 12:53 AM, Nilesh Javali <njavali@marvell.com> wrote:
> 
> From: Quinn Tran <qutran@marvell.com>
> 
> System crash due to use after free.
> Current code allows terminate_rport_io to exit before making
> sure all IOs has returned. For FCP-2 device, IO's can hang
> on in HW because driver has not tear down the session in FW at
> first sign of cable pull. When dev_loss_tmo timer pops,
> terminate_rport_io is called and upper layer is about to
> free various resources. Terminate_rport_io trigger qla to do
> the final cleanup, but the cleanup might not be fast enough where it
> leave qla still holding on to the same resource.
> 
> Wait for IO's to return to upper layer before resources are freed.
> 
> Cc: stable@vger.kernel.org
> Signed-off-by: Quinn Tran <qutran@marvell.com>
> Signed-off-by: Nilesh Javali <njavali@marvell.com>
> ---
> drivers/scsi/qla2xxx/qla_attr.c | 13 +++++++++++++
> 1 file changed, 13 insertions(+)
> 
> diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
> index 70cfc94c3d43..b00222459607 100644
> --- a/drivers/scsi/qla2xxx/qla_attr.c
> +++ b/drivers/scsi/qla2xxx/qla_attr.c
> @@ -2750,6 +2750,7 @@ static void
> qla2x00_terminate_rport_io(struct fc_rport *rport)
> {
> fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
> + scsi_qla_host_t *vha;
> 
> if (!fcport)
> return;
> @@ -2759,9 +2760,12 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)
> 
> if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags))
> return;
> + vha = fcport->vha;
> 
> if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) {
> qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16);
> + qla2x00_eh_wait_for_pending_commands(fcport->vha, fcport->d_id.b24,
> + 0, WAIT_TARGET);
> return;
> }
> /*
> @@ -2786,6 +2790,15 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)
> qla2x00_port_logout(fcport->vha, fcport);
> }
> }
> +
> + /* check for any straggling io left behind */
> + if (qla2x00_eh_wait_for_pending_commands(fcport->vha, fcport->d_id.b24, 0, WAIT_TARGET)) {
> + ql_log(ql_log_warn, vha, 0x300b,
> +       "IO not return.  Resetting. \n");
> + set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
> + qla2xxx_wake_dpc(vha);
> + qla2x00_wait_for_chip_reset(vha);
> + }
> }
> 
> static int
> -- 
> 2.23.1
> 
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
diff mbox series

Patch

diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 70cfc94c3d43..b00222459607 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -2750,6 +2750,7 @@  static void
 qla2x00_terminate_rport_io(struct fc_rport *rport)
 {
 	fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
+	scsi_qla_host_t *vha;
 
 	if (!fcport)
 		return;
@@ -2759,9 +2760,12 @@  qla2x00_terminate_rport_io(struct fc_rport *rport)
 
 	if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags))
 		return;
+	vha = fcport->vha;
 
 	if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) {
 		qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16);
+		qla2x00_eh_wait_for_pending_commands(fcport->vha, fcport->d_id.b24,
+			0, WAIT_TARGET);
 		return;
 	}
 	/*
@@ -2786,6 +2790,15 @@  qla2x00_terminate_rport_io(struct fc_rport *rport)
 			qla2x00_port_logout(fcport->vha, fcport);
 		}
 	}
+
+	/* check for any straggling io left behind */
+	if (qla2x00_eh_wait_for_pending_commands(fcport->vha, fcport->d_id.b24, 0, WAIT_TARGET)) {
+		ql_log(ql_log_warn, vha, 0x300b,
+		       "IO not return.  Resetting. \n");
+		set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+		qla2xxx_wake_dpc(vha);
+		qla2x00_wait_for_chip_reset(vha);
+	}
 }
 
 static int