tcm_loop: Fix wrong I_T nexus association

commit 506787a2c7daed45f0a213674ca706cbc83a9089 upstream.

tcm_loop has the I_T nexus associated with the HBA. This causes
commands to become misdirected if the HBA has more than one
target portal group; any command is then being sent to the
first target portal group instead of the correct one.

The nexus needs to be associated with the target portal group
instead.

Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Hannes Reinecke 2015-01-30 22:17:23 +00:00 committed by Greg Kroah-Hartman
parent 3ce3a8612d
commit 9ed763fc27
2 changed files with 15 additions and 21 deletions

View File

@ -179,7 +179,7 @@ static void tcm_loop_submission_work(struct work_struct *work)
goto out_done;
}
tl_nexus = tl_hba->tl_nexus;
tl_nexus = tl_tpg->tl_nexus;
if (!tl_nexus) {
scmd_printk(KERN_ERR, sc, "TCM_Loop I_T Nexus"
" does not exist\n");
@ -257,21 +257,21 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc)
* Locate the tcm_loop_hba_t pointer
*/
tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
/*
* Locate the tl_tpg and se_tpg pointers from TargetID in sc->device->id
*/
tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
se_tpg = &tl_tpg->tl_se_tpg;
/*
* Locate the tl_nexus and se_sess pointers
*/
tl_nexus = tl_hba->tl_nexus;
tl_nexus = tl_tpg->tl_nexus;
if (!tl_nexus) {
pr_err("Unable to perform device reset without"
" active I_T Nexus\n");
return FAILED;
}
se_sess = tl_nexus->se_sess;
/*
* Locate the tl_tpg and se_tpg pointers from TargetID in sc->device->id
*/
tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
se_tpg = &tl_tpg->tl_se_tpg;
tl_cmd = kmem_cache_zalloc(tcm_loop_cmd_cache, GFP_KERNEL);
if (!tl_cmd) {
@ -879,8 +879,8 @@ static int tcm_loop_make_nexus(
struct tcm_loop_nexus *tl_nexus;
int ret = -ENOMEM;
if (tl_tpg->tl_hba->tl_nexus) {
pr_debug("tl_tpg->tl_hba->tl_nexus already exists\n");
if (tl_tpg->tl_nexus) {
pr_debug("tl_tpg->tl_nexus already exists\n");
return -EEXIST;
}
se_tpg = &tl_tpg->tl_se_tpg;
@ -915,7 +915,7 @@ static int tcm_loop_make_nexus(
*/
__transport_register_session(se_tpg, tl_nexus->se_sess->se_node_acl,
tl_nexus->se_sess, tl_nexus);
tl_tpg->tl_hba->tl_nexus = tl_nexus;
tl_tpg->tl_nexus = tl_nexus;
pr_debug("TCM_Loop_ConfigFS: Established I_T Nexus to emulated"
" %s Initiator Port: %s\n", tcm_loop_dump_proto_id(tl_hba),
name);
@ -931,9 +931,8 @@ static int tcm_loop_drop_nexus(
{
struct se_session *se_sess;
struct tcm_loop_nexus *tl_nexus;
struct tcm_loop_hba *tl_hba = tpg->tl_hba;
tl_nexus = tpg->tl_hba->tl_nexus;
tl_nexus = tpg->tl_nexus;
if (!tl_nexus)
return -ENODEV;
@ -949,13 +948,13 @@ static int tcm_loop_drop_nexus(
}
pr_debug("TCM_Loop_ConfigFS: Removing I_T Nexus to emulated"
" %s Initiator Port: %s\n", tcm_loop_dump_proto_id(tl_hba),
" %s Initiator Port: %s\n", tcm_loop_dump_proto_id(tpg->tl_hba),
tl_nexus->se_sess->se_node_acl->initiatorname);
/*
* Release the SCSI I_T Nexus to the emulated SAS Target Port
*/
transport_deregister_session(tl_nexus->se_sess);
tpg->tl_hba->tl_nexus = NULL;
tpg->tl_nexus = NULL;
kfree(tl_nexus);
return 0;
}
@ -971,7 +970,7 @@ static ssize_t tcm_loop_tpg_show_nexus(
struct tcm_loop_nexus *tl_nexus;
ssize_t ret;
tl_nexus = tl_tpg->tl_hba->tl_nexus;
tl_nexus = tl_tpg->tl_nexus;
if (!tl_nexus)
return -ENODEV;

View File

@ -25,11 +25,6 @@ struct tcm_loop_tmr {
};
struct tcm_loop_nexus {
int it_nexus_active;
/*
* Pointer to Linux/SCSI HBA from linux/include/scsi_host.h
*/
struct scsi_host *sh;
/*
* Pointer to TCM session for I_T Nexus
*/
@ -45,6 +40,7 @@ struct tcm_loop_tpg {
atomic_t tl_tpg_port_count;
struct se_portal_group tl_se_tpg;
struct tcm_loop_hba *tl_hba;
struct tcm_loop_nexus *tl_nexus;
};
struct tcm_loop_hba {
@ -53,7 +49,6 @@ struct tcm_loop_hba {
struct se_hba_s *se_hba;
struct se_lun *tl_hba_lun;
struct se_port *tl_hba_lun_sep;
struct tcm_loop_nexus *tl_nexus;
struct device dev;
struct Scsi_Host *sh;
struct tcm_loop_tpg tl_hba_tpgs[TL_TPGS_PER_HBA];