aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_target.c
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2014-02-19 20:51:25 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2014-02-20 16:01:17 -0500
commitddb95145a38eb37b236d4e00f43a75d067922dda (patch)
tree81a67c0febfeae8f71e8ca06e21dbb6f6aea9aa3 /drivers/scsi/qla2xxx/qla_target.c
parentd6a65fdc8903e632aa7bf86ee0f61a73969371f6 (diff)
qla2xxx: Fix qlt_lport_register base_vha callback race
This patch closes a race between qlt_lport_register() and tcm_qla2xxx callback logic by holding qla_tgt_mutex before making the callback. In order for this to work, the qlt_add_target() and qlt_remove_target() code has been changed to avoid the accessing qla_tgt_mutex + list_[add,del] for NPIV enabled ports. This bug introduced in v3.14-rc1 code with commit 49a47f2. 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>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_target.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_target.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 2eb97d7e8d12..ea3eaef3f81b 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -4181,6 +4181,9 @@ int qlt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha)
4181 tgt->datasegs_per_cmd = QLA_TGT_DATASEGS_PER_CMD_24XX; 4181 tgt->datasegs_per_cmd = QLA_TGT_DATASEGS_PER_CMD_24XX;
4182 tgt->datasegs_per_cont = QLA_TGT_DATASEGS_PER_CONT_24XX; 4182 tgt->datasegs_per_cont = QLA_TGT_DATASEGS_PER_CONT_24XX;
4183 4183
4184 if (base_vha->fc_vport)
4185 return 0;
4186
4184 mutex_lock(&qla_tgt_mutex); 4187 mutex_lock(&qla_tgt_mutex);
4185 list_add_tail(&tgt->tgt_list_entry, &qla_tgt_glist); 4188 list_add_tail(&tgt->tgt_list_entry, &qla_tgt_glist);
4186 mutex_unlock(&qla_tgt_mutex); 4189 mutex_unlock(&qla_tgt_mutex);
@@ -4194,6 +4197,10 @@ int qlt_remove_target(struct qla_hw_data *ha, struct scsi_qla_host *vha)
4194 if (!vha->vha_tgt.qla_tgt) 4197 if (!vha->vha_tgt.qla_tgt)
4195 return 0; 4198 return 0;
4196 4199
4200 if (vha->fc_vport) {
4201 qlt_release(vha->vha_tgt.qla_tgt);
4202 return 0;
4203 }
4197 mutex_lock(&qla_tgt_mutex); 4204 mutex_lock(&qla_tgt_mutex);
4198 list_del(&vha->vha_tgt.qla_tgt->tgt_list_entry); 4205 list_del(&vha->vha_tgt.qla_tgt->tgt_list_entry);
4199 mutex_unlock(&qla_tgt_mutex); 4206 mutex_unlock(&qla_tgt_mutex);
@@ -4265,6 +4272,12 @@ int qlt_lport_register(void *target_lport_ptr, u64 phys_wwpn,
4265 spin_unlock_irqrestore(&ha->hardware_lock, flags); 4272 spin_unlock_irqrestore(&ha->hardware_lock, flags);
4266 continue; 4273 continue;
4267 } 4274 }
4275 if (tgt->tgt_stop) {
4276 pr_debug("MODE_TARGET in shutdown on qla2xxx(%d)\n",
4277 host->host_no);
4278 spin_unlock_irqrestore(&ha->hardware_lock, flags);
4279 continue;
4280 }
4268 spin_unlock_irqrestore(&ha->hardware_lock, flags); 4281 spin_unlock_irqrestore(&ha->hardware_lock, flags);
4269 4282
4270 if (!scsi_host_get(host)) { 4283 if (!scsi_host_get(host)) {
@@ -4279,12 +4292,11 @@ int qlt_lport_register(void *target_lport_ptr, u64 phys_wwpn,
4279 scsi_host_put(host); 4292 scsi_host_put(host);
4280 continue; 4293 continue;
4281 } 4294 }
4282 mutex_unlock(&qla_tgt_mutex);
4283
4284 rc = (*callback)(vha, target_lport_ptr, npiv_wwpn, npiv_wwnn); 4295 rc = (*callback)(vha, target_lport_ptr, npiv_wwpn, npiv_wwnn);
4285 if (rc != 0) 4296 if (rc != 0)
4286 scsi_host_put(host); 4297 scsi_host_put(host);
4287 4298
4299 mutex_unlock(&qla_tgt_mutex);
4288 return rc; 4300 return rc;
4289 } 4301 }
4290 mutex_unlock(&qla_tgt_mutex); 4302 mutex_unlock(&qla_tgt_mutex);