Skip to content

Commit 3c231bd

Browse files
author
Nicholas Bellinger
committed
qla2xxx: Check + fail when npiv_vports_inuse exists in shutdown
This patch adds an check to qlt_stop_phase1() to avoid shutdown when the base_vha contains a non-zero fc_host->npiv_vports_inuse count. This includes holding qla_tgt_mutex in qlt_stop_phase1() between the fc_host->npiv_vports_inuse check + setting of tgt->tgt_stop to avoid a possible race between qlt_lport_register() -> tcm_qla2xxx -> tcm_qla2xxx_lport_register_npiv_cb() calling fc_vport_create(). Cc: Sawan Chandak <sawan.chandak@qlogic.com> Cc: Quinn Tran <quinn.tran@qlogic.com> Cc: Saurav Kashyap <saurav.kashyap@qlogic.com> Cc: Giridhar Malavali <giridhar.malavali@qlogic.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
1 parent ddb9514 commit 3c231bd

File tree

2 files changed

+21
-4
lines changed

2 files changed

+21
-4
lines changed

drivers/scsi/qla2xxx/qla_target.c

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -790,17 +790,32 @@ static inline int test_tgt_sess_count(struct qla_tgt *tgt)
790790
}
791791

792792
/* Called by tcm_qla2xxx configfs code */
793-
void qlt_stop_phase1(struct qla_tgt *tgt)
793+
int qlt_stop_phase1(struct qla_tgt *tgt)
794794
{
795795
struct scsi_qla_host *vha = tgt->vha;
796796
struct qla_hw_data *ha = tgt->ha;
797797
unsigned long flags;
798798

799+
mutex_lock(&qla_tgt_mutex);
800+
if (!vha->fc_vport) {
801+
struct Scsi_Host *sh = vha->host;
802+
struct fc_host_attrs *fc_host = shost_to_fc_host(sh);
803+
bool npiv_vports;
804+
805+
spin_lock_irqsave(sh->host_lock, flags);
806+
npiv_vports = (fc_host->npiv_vports_inuse);
807+
spin_unlock_irqrestore(sh->host_lock, flags);
808+
809+
if (npiv_vports) {
810+
mutex_unlock(&qla_tgt_mutex);
811+
return -EPERM;
812+
}
813+
}
799814
if (tgt->tgt_stop || tgt->tgt_stopped) {
800815
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04e,
801816
"Already in tgt->tgt_stop or tgt_stopped state\n");
802-
dump_stack();
803-
return;
817+
mutex_unlock(&qla_tgt_mutex);
818+
return -EPERM;
804819
}
805820

806821
ql_dbg(ql_dbg_tgt, vha, 0xe003, "Stopping target for host %ld(%p)\n",
@@ -815,6 +830,7 @@ void qlt_stop_phase1(struct qla_tgt *tgt)
815830
qlt_clear_tgt_db(tgt, true);
816831
spin_unlock_irqrestore(&ha->hardware_lock, flags);
817832
mutex_unlock(&vha->vha_tgt.tgt_mutex);
833+
mutex_unlock(&qla_tgt_mutex);
818834

819835
flush_delayed_work(&tgt->sess_del_work);
820836

@@ -841,6 +857,7 @@ void qlt_stop_phase1(struct qla_tgt *tgt)
841857

842858
/* Wait for sessions to clear out (just in case) */
843859
wait_event(tgt->waitQ, test_tgt_sess_count(tgt));
860+
return 0;
844861
}
845862
EXPORT_SYMBOL(qlt_stop_phase1);
846863

drivers/scsi/qla2xxx/qla_target.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1001,7 +1001,7 @@ extern void qlt_modify_vp_config(struct scsi_qla_host *,
10011001
extern void qlt_probe_one_stage1(struct scsi_qla_host *, struct qla_hw_data *);
10021002
extern int qlt_mem_alloc(struct qla_hw_data *);
10031003
extern void qlt_mem_free(struct qla_hw_data *);
1004-
extern void qlt_stop_phase1(struct qla_tgt *);
1004+
extern int qlt_stop_phase1(struct qla_tgt *);
10051005
extern void qlt_stop_phase2(struct qla_tgt *);
10061006
extern irqreturn_t qla83xx_msix_atio_q(int, void *);
10071007
extern void qlt_83xx_iospace_config(struct qla_hw_data *);

0 commit comments

Comments
 (0)