Skip to content

Commit 6dfe434

Browse files
Quinn Tranmartinkpetersen
authored andcommitted
scsi: qla2xxx: Fix deletion race condition
System crash when using debug kernel due to link list corruption. The cause of the link list corruption is due to session deletion was allowed to queue up twice. Here's the internal trace that show the same port was allowed to double queue for deletion on different cpu. 20808683956 015 qla2xxx [0000:13:00.1]-e801:4: Scheduling sess ffff93ebf9306800 for deletion 50:06:0e:80:12:48:ff:50 fc4_type 1 20808683957 027 qla2xxx [0000:13:00.1]-e801:4: Scheduling sess ffff93ebf9306800 for deletion 50:06:0e:80:12:48:ff:50 fc4_type 1 Move the clearing/setting of deleted flag lock. Cc: stable@vger.kernel.org Fixes: 726b854 ("qla2xxx: Add framework for async fabric discovery") Signed-off-by: Quinn Tran <qutran@marvell.com> Signed-off-by: Nilesh Javali <njavali@marvell.com> Link: https://lore.kernel.org/r/20230714070104.40052-2-njavali@marvell.com Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 06c2afb commit 6dfe434

File tree

2 files changed

+21
-9
lines changed

2 files changed

+21
-9
lines changed

drivers/scsi/qla2xxx/qla_init.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,7 @@ static
508508
void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea)
509509
{
510510
struct fc_port *fcport = ea->fcport;
511+
unsigned long flags;
511512

512513
ql_dbg(ql_dbg_disc, vha, 0x20d2,
513514
"%s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d lid %d\n",
@@ -522,9 +523,15 @@ void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea)
522523
ql_dbg(ql_dbg_disc, vha, 0x2066,
523524
"%s %8phC: adisc fail: post delete\n",
524525
__func__, ea->fcport->port_name);
526+
527+
spin_lock_irqsave(&vha->work_lock, flags);
525528
/* deleted = 0 & logout_on_delete = force fw cleanup */
526-
fcport->deleted = 0;
529+
if (fcport->deleted == QLA_SESS_DELETED)
530+
fcport->deleted = 0;
531+
527532
fcport->logout_on_delete = 1;
533+
spin_unlock_irqrestore(&vha->work_lock, flags);
534+
528535
qlt_schedule_sess_for_deletion(ea->fcport);
529536
return;
530537
}
@@ -1446,7 +1453,6 @@ void __qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
14461453

14471454
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
14481455
ea->fcport->login_gen++;
1449-
ea->fcport->deleted = 0;
14501456
ea->fcport->logout_on_delete = 1;
14511457

14521458
if (!ea->fcport->login_succ && !IS_SW_RESV_ADDR(ea->fcport->d_id)) {
@@ -6090,6 +6096,8 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport)
60906096
void
60916097
qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
60926098
{
6099+
unsigned long flags;
6100+
60936101
if (IS_SW_RESV_ADDR(fcport->d_id))
60946102
return;
60956103

@@ -6099,7 +6107,11 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
60996107
qla2x00_set_fcport_disc_state(fcport, DSC_UPD_FCPORT);
61006108
fcport->login_retry = vha->hw->login_retry_count;
61016109
fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
6110+
6111+
spin_lock_irqsave(&vha->work_lock, flags);
61026112
fcport->deleted = 0;
6113+
spin_unlock_irqrestore(&vha->work_lock, flags);
6114+
61036115
if (vha->hw->current_topology == ISP_CFG_NL)
61046116
fcport->logout_on_delete = 0;
61056117
else

drivers/scsi/qla2xxx/qla_target.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,10 +1068,6 @@ void qlt_free_session_done(struct work_struct *work)
10681068
(struct imm_ntfy_from_isp *)sess->iocb, SRB_NACK_LOGO);
10691069
}
10701070

1071-
spin_lock_irqsave(&vha->work_lock, flags);
1072-
sess->flags &= ~FCF_ASYNC_SENT;
1073-
spin_unlock_irqrestore(&vha->work_lock, flags);
1074-
10751071
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
10761072
if (sess->se_sess) {
10771073
sess->se_sess = NULL;
@@ -1081,7 +1077,6 @@ void qlt_free_session_done(struct work_struct *work)
10811077

10821078
qla2x00_set_fcport_disc_state(sess, DSC_DELETED);
10831079
sess->fw_login_state = DSC_LS_PORT_UNAVAIL;
1084-
sess->deleted = QLA_SESS_DELETED;
10851080

10861081
if (sess->login_succ && !IS_SW_RESV_ADDR(sess->d_id)) {
10871082
vha->fcport_count--;
@@ -1133,10 +1128,15 @@ void qlt_free_session_done(struct work_struct *work)
11331128

11341129
sess->explicit_logout = 0;
11351130
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
1136-
sess->free_pending = 0;
11371131

11381132
qla2x00_dfs_remove_rport(vha, sess);
11391133

1134+
spin_lock_irqsave(&vha->work_lock, flags);
1135+
sess->flags &= ~FCF_ASYNC_SENT;
1136+
sess->deleted = QLA_SESS_DELETED;
1137+
sess->free_pending = 0;
1138+
spin_unlock_irqrestore(&vha->work_lock, flags);
1139+
11401140
ql_dbg(ql_dbg_disc, vha, 0xf001,
11411141
"Unregistration of sess %p %8phC finished fcp_cnt %d\n",
11421142
sess, sess->port_name, vha->fcport_count);
@@ -1185,12 +1185,12 @@ void qlt_unreg_sess(struct fc_port *sess)
11851185
* management from being sent.
11861186
*/
11871187
sess->flags |= FCF_ASYNC_SENT;
1188+
sess->deleted = QLA_SESS_DELETION_IN_PROGRESS;
11881189
spin_unlock_irqrestore(&sess->vha->work_lock, flags);
11891190

11901191
if (sess->se_sess)
11911192
vha->hw->tgt.tgt_ops->clear_nacl_from_fcport_map(sess);
11921193

1193-
sess->deleted = QLA_SESS_DELETION_IN_PROGRESS;
11941194
qla2x00_set_fcport_disc_state(sess, DSC_DELETE_PEND);
11951195
sess->last_rscn_gen = sess->rscn_gen;
11961196
sess->last_login_gen = sess->login_gen;

0 commit comments

Comments
 (0)