Commit ceae09be authored by Hannes Reinecke's avatar Hannes Reinecke Committed by Luis Henriques

tcm_loop: Fix wrong I_T nexus association

commit 506787a2 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: default avatarHannes Reinecke <hare@suse.de>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
[ luis: backported to 3.16: adjusted context ]
Signed-off-by: default avatarLuis Henriques <luis.henriques@canonical.com>
parent ea447345
...@@ -197,7 +197,7 @@ static void tcm_loop_submission_work(struct work_struct *work) ...@@ -197,7 +197,7 @@ static void tcm_loop_submission_work(struct work_struct *work)
set_host_byte(sc, DID_TRANSPORT_DISRUPTED); set_host_byte(sc, DID_TRANSPORT_DISRUPTED);
goto out_done; goto out_done;
} }
tl_nexus = tl_hba->tl_nexus; tl_nexus = tl_tpg->tl_nexus;
if (!tl_nexus) { if (!tl_nexus) {
scmd_printk(KERN_ERR, sc, "TCM_Loop I_T Nexus" scmd_printk(KERN_ERR, sc, "TCM_Loop I_T Nexus"
" does not exist\n"); " does not exist\n");
...@@ -277,16 +277,26 @@ static int tcm_loop_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc) ...@@ -277,16 +277,26 @@ static int tcm_loop_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc)
* to struct scsi_device * to struct scsi_device
*/ */
static int tcm_loop_issue_tmr(struct tcm_loop_tpg *tl_tpg, static int tcm_loop_issue_tmr(struct tcm_loop_tpg *tl_tpg,
struct tcm_loop_nexus *tl_nexus,
int lun, int task, enum tcm_tmreq_table tmr) int lun, int task, enum tcm_tmreq_table tmr)
{ {
struct se_cmd *se_cmd = NULL; struct se_cmd *se_cmd = NULL;
struct se_session *se_sess; struct se_session *se_sess;
struct se_portal_group *se_tpg; struct se_portal_group *se_tpg;
struct tcm_loop_nexus *tl_nexus;
struct tcm_loop_cmd *tl_cmd = NULL; struct tcm_loop_cmd *tl_cmd = NULL;
struct tcm_loop_tmr *tl_tmr = NULL; struct tcm_loop_tmr *tl_tmr = NULL;
int ret = TMR_FUNCTION_FAILED, rc; int ret = TMR_FUNCTION_FAILED, rc;
/*
* Locate the tl_nexus and se_sess pointers
*/
tl_nexus = tl_tpg->tl_nexus;
if (!tl_nexus) {
pr_err("Unable to perform device reset without"
" active I_T Nexus\n");
return ret;
}
tl_cmd = kmem_cache_zalloc(tcm_loop_cmd_cache, GFP_KERNEL); tl_cmd = kmem_cache_zalloc(tcm_loop_cmd_cache, GFP_KERNEL);
if (!tl_cmd) { if (!tl_cmd) {
pr_err("Unable to allocate memory for tl_cmd\n"); pr_err("Unable to allocate memory for tl_cmd\n");
...@@ -302,7 +312,7 @@ static int tcm_loop_issue_tmr(struct tcm_loop_tpg *tl_tpg, ...@@ -302,7 +312,7 @@ static int tcm_loop_issue_tmr(struct tcm_loop_tpg *tl_tpg,
se_cmd = &tl_cmd->tl_se_cmd; se_cmd = &tl_cmd->tl_se_cmd;
se_tpg = &tl_tpg->tl_se_tpg; se_tpg = &tl_tpg->tl_se_tpg;
se_sess = tl_nexus->se_sess; se_sess = tl_tpg->tl_nexus->se_sess;
/* /*
* Initialize struct se_cmd descriptor from target_core_mod infrastructure * Initialize struct se_cmd descriptor from target_core_mod infrastructure
*/ */
...@@ -347,7 +357,6 @@ static int tcm_loop_issue_tmr(struct tcm_loop_tpg *tl_tpg, ...@@ -347,7 +357,6 @@ static int tcm_loop_issue_tmr(struct tcm_loop_tpg *tl_tpg,
static int tcm_loop_abort_task(struct scsi_cmnd *sc) static int tcm_loop_abort_task(struct scsi_cmnd *sc)
{ {
struct tcm_loop_hba *tl_hba; struct tcm_loop_hba *tl_hba;
struct tcm_loop_nexus *tl_nexus;
struct tcm_loop_tpg *tl_tpg; struct tcm_loop_tpg *tl_tpg;
int ret = FAILED; int ret = FAILED;
...@@ -355,21 +364,8 @@ static int tcm_loop_abort_task(struct scsi_cmnd *sc) ...@@ -355,21 +364,8 @@ static int tcm_loop_abort_task(struct scsi_cmnd *sc)
* Locate the tcm_loop_hba_t pointer * Locate the tcm_loop_hba_t pointer
*/ */
tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host); tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
/*
* Locate the tl_nexus and se_sess pointers
*/
tl_nexus = tl_hba->tl_nexus;
if (!tl_nexus) {
pr_err("Unable to perform device reset without"
" active I_T Nexus\n");
return FAILED;
}
/*
* Locate the tl_tpg pointer from TargetID in sc->device->id
*/
tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id]; tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
ret = tcm_loop_issue_tmr(tl_tpg, tl_nexus, sc->device->lun, ret = tcm_loop_issue_tmr(tl_tpg, sc->device->lun,
sc->tag, TMR_ABORT_TASK); sc->tag, TMR_ABORT_TASK);
return (ret == TMR_FUNCTION_COMPLETE) ? SUCCESS : FAILED; return (ret == TMR_FUNCTION_COMPLETE) ? SUCCESS : FAILED;
} }
...@@ -381,7 +377,6 @@ static int tcm_loop_abort_task(struct scsi_cmnd *sc) ...@@ -381,7 +377,6 @@ static int tcm_loop_abort_task(struct scsi_cmnd *sc)
static int tcm_loop_device_reset(struct scsi_cmnd *sc) static int tcm_loop_device_reset(struct scsi_cmnd *sc)
{ {
struct tcm_loop_hba *tl_hba; struct tcm_loop_hba *tl_hba;
struct tcm_loop_nexus *tl_nexus;
struct tcm_loop_tpg *tl_tpg; struct tcm_loop_tpg *tl_tpg;
int ret = FAILED; int ret = FAILED;
...@@ -389,20 +384,9 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc) ...@@ -389,20 +384,9 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc)
* Locate the tcm_loop_hba_t pointer * Locate the tcm_loop_hba_t pointer
*/ */
tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host); tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
/*
* Locate the tl_nexus and se_sess pointers
*/
tl_nexus = tl_hba->tl_nexus;
if (!tl_nexus) {
pr_err("Unable to perform device reset without"
" active I_T Nexus\n");
return FAILED;
}
/*
* Locate the tl_tpg pointer from TargetID in sc->device->id
*/
tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id]; tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
ret = tcm_loop_issue_tmr(tl_tpg, tl_nexus, sc->device->lun,
ret = tcm_loop_issue_tmr(tl_tpg, sc->device->lun,
0, TMR_LUN_RESET); 0, TMR_LUN_RESET);
return (ret == TMR_FUNCTION_COMPLETE) ? SUCCESS : FAILED; return (ret == TMR_FUNCTION_COMPLETE) ? SUCCESS : FAILED;
} }
...@@ -1014,8 +998,8 @@ static int tcm_loop_make_nexus( ...@@ -1014,8 +998,8 @@ static int tcm_loop_make_nexus(
struct tcm_loop_nexus *tl_nexus; struct tcm_loop_nexus *tl_nexus;
int ret = -ENOMEM; int ret = -ENOMEM;
if (tl_tpg->tl_hba->tl_nexus) { if (tl_tpg->tl_nexus) {
pr_debug("tl_tpg->tl_hba->tl_nexus already exists\n"); pr_debug("tl_tpg->tl_nexus already exists\n");
return -EEXIST; return -EEXIST;
} }
se_tpg = &tl_tpg->tl_se_tpg; se_tpg = &tl_tpg->tl_se_tpg;
...@@ -1050,7 +1034,7 @@ static int tcm_loop_make_nexus( ...@@ -1050,7 +1034,7 @@ static int tcm_loop_make_nexus(
*/ */
__transport_register_session(se_tpg, tl_nexus->se_sess->se_node_acl, __transport_register_session(se_tpg, tl_nexus->se_sess->se_node_acl,
tl_nexus->se_sess, tl_nexus); 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" pr_debug("TCM_Loop_ConfigFS: Established 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(tl_hba),
name); name);
...@@ -1066,12 +1050,8 @@ static int tcm_loop_drop_nexus( ...@@ -1066,12 +1050,8 @@ static int tcm_loop_drop_nexus(
{ {
struct se_session *se_sess; struct se_session *se_sess;
struct tcm_loop_nexus *tl_nexus; struct tcm_loop_nexus *tl_nexus;
struct tcm_loop_hba *tl_hba = tpg->tl_hba;
if (!tl_hba) tl_nexus = tpg->tl_nexus;
return -ENODEV;
tl_nexus = tl_hba->tl_nexus;
if (!tl_nexus) if (!tl_nexus)
return -ENODEV; return -ENODEV;
...@@ -1087,13 +1067,13 @@ static int tcm_loop_drop_nexus( ...@@ -1087,13 +1067,13 @@ static int tcm_loop_drop_nexus(
} }
pr_debug("TCM_Loop_ConfigFS: Removing I_T Nexus to emulated" 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); tl_nexus->se_sess->se_node_acl->initiatorname);
/* /*
* Release the SCSI I_T Nexus to the emulated SAS Target Port * Release the SCSI I_T Nexus to the emulated SAS Target Port
*/ */
transport_deregister_session(tl_nexus->se_sess); transport_deregister_session(tl_nexus->se_sess);
tpg->tl_hba->tl_nexus = NULL; tpg->tl_nexus = NULL;
kfree(tl_nexus); kfree(tl_nexus);
return 0; return 0;
} }
...@@ -1109,7 +1089,7 @@ static ssize_t tcm_loop_tpg_show_nexus( ...@@ -1109,7 +1089,7 @@ static ssize_t tcm_loop_tpg_show_nexus(
struct tcm_loop_nexus *tl_nexus; struct tcm_loop_nexus *tl_nexus;
ssize_t ret; ssize_t ret;
tl_nexus = tl_tpg->tl_hba->tl_nexus; tl_nexus = tl_tpg->tl_nexus;
if (!tl_nexus) if (!tl_nexus)
return -ENODEV; return -ENODEV;
......
...@@ -27,11 +27,6 @@ struct tcm_loop_tmr { ...@@ -27,11 +27,6 @@ struct tcm_loop_tmr {
}; };
struct tcm_loop_nexus { 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 * Pointer to TCM session for I_T Nexus
*/ */
...@@ -51,6 +46,7 @@ struct tcm_loop_tpg { ...@@ -51,6 +46,7 @@ struct tcm_loop_tpg {
atomic_t tl_tpg_port_count; atomic_t tl_tpg_port_count;
struct se_portal_group tl_se_tpg; struct se_portal_group tl_se_tpg;
struct tcm_loop_hba *tl_hba; struct tcm_loop_hba *tl_hba;
struct tcm_loop_nexus *tl_nexus;
}; };
struct tcm_loop_hba { struct tcm_loop_hba {
...@@ -59,7 +55,6 @@ struct tcm_loop_hba { ...@@ -59,7 +55,6 @@ struct tcm_loop_hba {
struct se_hba_s *se_hba; struct se_hba_s *se_hba;
struct se_lun *tl_hba_lun; struct se_lun *tl_hba_lun;
struct se_port *tl_hba_lun_sep; struct se_port *tl_hba_lun_sep;
struct tcm_loop_nexus *tl_nexus;
struct device dev; struct device dev;
struct Scsi_Host *sh; struct Scsi_Host *sh;
struct tcm_loop_tpg tl_hba_tpgs[TL_TPGS_PER_HBA]; struct tcm_loop_tpg tl_hba_tpgs[TL_TPGS_PER_HBA];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment