Commit 1e207eb1 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending

Pull scsi target fixes from Nicholas Bellinger:
 "These are the current target pending fixes headed for v3.7-rc4 code.
  This includes the following highlights:

   - Fix long-standing qla2xxx target bug where certain fc_port_t state
     transitions could cause the internal session b-tree list to become
     out-of-sync.  (Roland)
   - Fix task management double free of se_cmd descriptor in exception
     path for users of target_submit_tmr().  (nab)
   - Re-introduce simple NOP emulation of REZERO_UNIT, SEEK_6, and
     SEEK_10 SCSI-2 commands in order to support legacy initiators that
     still require them.  (Bernhard)

  Note these three patches are also CC'ed to stable.

  Also, there a couple of outstanding (external) regressions that are
  still being tracked down for tcm_fc(FCoE) and tcm_vhost fabrics for
  v3.7.0 code, so please expect another PULL as these issues identified
  -> resolved."

* git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending:
  target: reintroduce some obsolete SCSI-2 commands
  target: Fix double-free of se_cmd in target_complete_tmr_failure
  qla2xxx: Update target lookup session tables when a target session changes
  tcm_qla2xxx: Format VPD page 83h SCSI name string according to SPC
  qla2xxx: Add missing ->vport_slock while calling qlt_update_vp_map
parents ed48c06c 1a1ff38c
...@@ -149,6 +149,7 @@ qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha) ...@@ -149,6 +149,7 @@ qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha)
int int
qla24xx_disable_vp(scsi_qla_host_t *vha) qla24xx_disable_vp(scsi_qla_host_t *vha)
{ {
unsigned long flags;
int ret; int ret;
ret = qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL); ret = qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL);
...@@ -156,7 +157,9 @@ qla24xx_disable_vp(scsi_qla_host_t *vha) ...@@ -156,7 +157,9 @@ qla24xx_disable_vp(scsi_qla_host_t *vha)
atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
/* Remove port id from vp target map */ /* Remove port id from vp target map */
spin_lock_irqsave(&vha->hw->vport_slock, flags);
qlt_update_vp_map(vha, RESET_AL_PA); qlt_update_vp_map(vha, RESET_AL_PA);
spin_unlock_irqrestore(&vha->hw->vport_slock, flags);
qla2x00_mark_vp_devices_dead(vha); qla2x00_mark_vp_devices_dead(vha);
atomic_set(&vha->vp_state, VP_FAILED); atomic_set(&vha->vp_state, VP_FAILED);
......
...@@ -557,6 +557,7 @@ static bool qlt_check_fcport_exist(struct scsi_qla_host *vha, ...@@ -557,6 +557,7 @@ static bool qlt_check_fcport_exist(struct scsi_qla_host *vha,
int pmap_len; int pmap_len;
fc_port_t *fcport; fc_port_t *fcport;
int global_resets; int global_resets;
unsigned long flags;
retry: retry:
global_resets = atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count); global_resets = atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count);
...@@ -625,10 +626,10 @@ static bool qlt_check_fcport_exist(struct scsi_qla_host *vha, ...@@ -625,10 +626,10 @@ static bool qlt_check_fcport_exist(struct scsi_qla_host *vha,
sess->s_id.b.area, sess->loop_id, fcport->d_id.b.domain, sess->s_id.b.area, sess->loop_id, fcport->d_id.b.domain,
fcport->d_id.b.al_pa, fcport->d_id.b.area, fcport->loop_id); fcport->d_id.b.al_pa, fcport->d_id.b.area, fcport->loop_id);
sess->s_id = fcport->d_id; spin_lock_irqsave(&ha->hardware_lock, flags);
sess->loop_id = fcport->loop_id; ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
sess->conf_compl_supported = !!(fcport->flags & (fcport->flags & FCF_CONF_COMP_SUPPORTED));
FCF_CONF_COMP_SUPPORTED); spin_unlock_irqrestore(&ha->hardware_lock, flags);
res = true; res = true;
...@@ -740,10 +741,9 @@ static struct qla_tgt_sess *qlt_create_sess( ...@@ -740,10 +741,9 @@ static struct qla_tgt_sess *qlt_create_sess(
qlt_undelete_sess(sess); qlt_undelete_sess(sess);
kref_get(&sess->se_sess->sess_kref); kref_get(&sess->se_sess->sess_kref);
sess->s_id = fcport->d_id; ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
sess->loop_id = fcport->loop_id; (fcport->flags & FCF_CONF_COMP_SUPPORTED));
sess->conf_compl_supported = !!(fcport->flags &
FCF_CONF_COMP_SUPPORTED);
if (sess->local && !local) if (sess->local && !local)
sess->local = 0; sess->local = 0;
spin_unlock_irqrestore(&ha->hardware_lock, flags); spin_unlock_irqrestore(&ha->hardware_lock, flags);
...@@ -796,8 +796,7 @@ static struct qla_tgt_sess *qlt_create_sess( ...@@ -796,8 +796,7 @@ static struct qla_tgt_sess *qlt_create_sess(
*/ */
kref_get(&sess->se_sess->sess_kref); kref_get(&sess->se_sess->sess_kref);
sess->conf_compl_supported = !!(fcport->flags & sess->conf_compl_supported = (fcport->flags & FCF_CONF_COMP_SUPPORTED);
FCF_CONF_COMP_SUPPORTED);
BUILD_BUG_ON(sizeof(sess->port_name) != sizeof(fcport->port_name)); BUILD_BUG_ON(sizeof(sess->port_name) != sizeof(fcport->port_name));
memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name)); memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name));
...@@ -869,10 +868,8 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport) ...@@ -869,10 +868,8 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf007, ql_dbg(ql_dbg_tgt_mgt, vha, 0xf007,
"Reappeared sess %p\n", sess); "Reappeared sess %p\n", sess);
} }
sess->s_id = fcport->d_id; ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
sess->loop_id = fcport->loop_id; (fcport->flags & FCF_CONF_COMP_SUPPORTED));
sess->conf_compl_supported = !!(fcport->flags &
FCF_CONF_COMP_SUPPORTED);
} }
if (sess && sess->local) { if (sess && sess->local) {
......
...@@ -648,6 +648,7 @@ struct qla_tgt_func_tmpl { ...@@ -648,6 +648,7 @@ struct qla_tgt_func_tmpl {
int (*check_initiator_node_acl)(struct scsi_qla_host *, unsigned char *, int (*check_initiator_node_acl)(struct scsi_qla_host *, unsigned char *,
void *, uint8_t *, uint16_t); void *, uint8_t *, uint16_t);
void (*update_sess)(struct qla_tgt_sess *, port_id_t, uint16_t, bool);
struct qla_tgt_sess *(*find_sess_by_loop_id)(struct scsi_qla_host *, struct qla_tgt_sess *(*find_sess_by_loop_id)(struct scsi_qla_host *,
const uint16_t); const uint16_t);
struct qla_tgt_sess *(*find_sess_by_s_id)(struct scsi_qla_host *, struct qla_tgt_sess *(*find_sess_by_s_id)(struct scsi_qla_host *,
......
...@@ -237,7 +237,7 @@ static char *tcm_qla2xxx_get_fabric_wwn(struct se_portal_group *se_tpg) ...@@ -237,7 +237,7 @@ static char *tcm_qla2xxx_get_fabric_wwn(struct se_portal_group *se_tpg)
struct tcm_qla2xxx_tpg, se_tpg); struct tcm_qla2xxx_tpg, se_tpg);
struct tcm_qla2xxx_lport *lport = tpg->lport; struct tcm_qla2xxx_lport *lport = tpg->lport;
return &lport->lport_name[0]; return lport->lport_naa_name;
} }
static char *tcm_qla2xxx_npiv_get_fabric_wwn(struct se_portal_group *se_tpg) static char *tcm_qla2xxx_npiv_get_fabric_wwn(struct se_portal_group *se_tpg)
...@@ -1457,6 +1457,78 @@ static int tcm_qla2xxx_check_initiator_node_acl( ...@@ -1457,6 +1457,78 @@ static int tcm_qla2xxx_check_initiator_node_acl(
return 0; return 0;
} }
static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id,
uint16_t loop_id, bool conf_compl_supported)
{
struct qla_tgt *tgt = sess->tgt;
struct qla_hw_data *ha = tgt->ha;
struct tcm_qla2xxx_lport *lport = ha->tgt.target_lport_ptr;
struct se_node_acl *se_nacl = sess->se_sess->se_node_acl;
struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl,
struct tcm_qla2xxx_nacl, se_node_acl);
u32 key;
if (sess->loop_id != loop_id || sess->s_id.b24 != s_id.b24)
pr_info("Updating session %p from port %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x loop_id %d -> %d s_id %x:%x:%x -> %x:%x:%x\n",
sess,
sess->port_name[0], sess->port_name[1],
sess->port_name[2], sess->port_name[3],
sess->port_name[4], sess->port_name[5],
sess->port_name[6], sess->port_name[7],
sess->loop_id, loop_id,
sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa,
s_id.b.domain, s_id.b.area, s_id.b.al_pa);
if (sess->loop_id != loop_id) {
/*
* Because we can shuffle loop IDs around and we
* update different sessions non-atomically, we might
* have overwritten this session's old loop ID
* already, and we might end up overwriting some other
* session that will be updated later. So we have to
* be extra careful and we can't warn about those things...
*/
if (lport->lport_loopid_map[sess->loop_id].se_nacl == se_nacl)
lport->lport_loopid_map[sess->loop_id].se_nacl = NULL;
lport->lport_loopid_map[loop_id].se_nacl = se_nacl;
sess->loop_id = loop_id;
}
if (sess->s_id.b24 != s_id.b24) {
key = (((u32) sess->s_id.b.domain << 16) |
((u32) sess->s_id.b.area << 8) |
((u32) sess->s_id.b.al_pa));
if (btree_lookup32(&lport->lport_fcport_map, key))
WARN(btree_remove32(&lport->lport_fcport_map, key) != se_nacl,
"Found wrong se_nacl when updating s_id %x:%x:%x\n",
sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa);
else
WARN(1, "No lport_fcport_map entry for s_id %x:%x:%x\n",
sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa);
key = (((u32) s_id.b.domain << 16) |
((u32) s_id.b.area << 8) |
((u32) s_id.b.al_pa));
if (btree_lookup32(&lport->lport_fcport_map, key)) {
WARN(1, "Already have lport_fcport_map entry for s_id %x:%x:%x\n",
s_id.b.domain, s_id.b.area, s_id.b.al_pa);
btree_update32(&lport->lport_fcport_map, key, se_nacl);
} else {
btree_insert32(&lport->lport_fcport_map, key, se_nacl, GFP_ATOMIC);
}
sess->s_id = s_id;
nacl->nport_id = key;
}
sess->conf_compl_supported = conf_compl_supported;
}
/* /*
* Calls into tcm_qla2xxx used by qla2xxx LLD I/O path. * Calls into tcm_qla2xxx used by qla2xxx LLD I/O path.
*/ */
...@@ -1467,6 +1539,7 @@ static struct qla_tgt_func_tmpl tcm_qla2xxx_template = { ...@@ -1467,6 +1539,7 @@ static struct qla_tgt_func_tmpl tcm_qla2xxx_template = {
.free_cmd = tcm_qla2xxx_free_cmd, .free_cmd = tcm_qla2xxx_free_cmd,
.free_mcmd = tcm_qla2xxx_free_mcmd, .free_mcmd = tcm_qla2xxx_free_mcmd,
.free_session = tcm_qla2xxx_free_session, .free_session = tcm_qla2xxx_free_session,
.update_sess = tcm_qla2xxx_update_sess,
.check_initiator_node_acl = tcm_qla2xxx_check_initiator_node_acl, .check_initiator_node_acl = tcm_qla2xxx_check_initiator_node_acl,
.find_sess_by_s_id = tcm_qla2xxx_find_sess_by_s_id, .find_sess_by_s_id = tcm_qla2xxx_find_sess_by_s_id,
.find_sess_by_loop_id = tcm_qla2xxx_find_sess_by_loop_id, .find_sess_by_loop_id = tcm_qla2xxx_find_sess_by_loop_id,
...@@ -1534,6 +1607,7 @@ static struct se_wwn *tcm_qla2xxx_make_lport( ...@@ -1534,6 +1607,7 @@ static struct se_wwn *tcm_qla2xxx_make_lport(
lport->lport_wwpn = wwpn; lport->lport_wwpn = wwpn;
tcm_qla2xxx_format_wwn(&lport->lport_name[0], TCM_QLA2XXX_NAMELEN, tcm_qla2xxx_format_wwn(&lport->lport_name[0], TCM_QLA2XXX_NAMELEN,
wwpn); wwpn);
sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) wwpn);
ret = tcm_qla2xxx_init_lport(lport); ret = tcm_qla2xxx_init_lport(lport);
if (ret != 0) if (ret != 0)
...@@ -1601,6 +1675,7 @@ static struct se_wwn *tcm_qla2xxx_npiv_make_lport( ...@@ -1601,6 +1675,7 @@ static struct se_wwn *tcm_qla2xxx_npiv_make_lport(
lport->lport_npiv_wwnn = npiv_wwnn; lport->lport_npiv_wwnn = npiv_wwnn;
tcm_qla2xxx_npiv_format_wwn(&lport->lport_npiv_name[0], tcm_qla2xxx_npiv_format_wwn(&lport->lport_npiv_name[0],
TCM_QLA2XXX_NAMELEN, npiv_wwpn, npiv_wwnn); TCM_QLA2XXX_NAMELEN, npiv_wwpn, npiv_wwnn);
sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) npiv_wwpn);
/* FIXME: tcm_qla2xxx_npiv_make_lport */ /* FIXME: tcm_qla2xxx_npiv_make_lport */
ret = -ENOSYS; ret = -ENOSYS;
......
...@@ -61,6 +61,8 @@ struct tcm_qla2xxx_lport { ...@@ -61,6 +61,8 @@ struct tcm_qla2xxx_lport {
u64 lport_npiv_wwnn; u64 lport_npiv_wwnn;
/* ASCII formatted WWPN for FC Target Lport */ /* ASCII formatted WWPN for FC Target Lport */
char lport_name[TCM_QLA2XXX_NAMELEN]; char lport_name[TCM_QLA2XXX_NAMELEN];
/* ASCII formatted naa WWPN for VPD page 83 etc */
char lport_naa_name[TCM_QLA2XXX_NAMELEN];
/* ASCII formatted WWPN+WWNN for NPIV FC Target Lport */ /* ASCII formatted WWPN+WWNN for NPIV FC Target Lport */
char lport_npiv_name[TCM_QLA2XXX_NPIV_NAMELEN]; char lport_npiv_name[TCM_QLA2XXX_NPIV_NAMELEN];
/* map for fc_port pointers in 24-bit FC Port ID space */ /* map for fc_port pointers in 24-bit FC Port ID space */
......
...@@ -135,6 +135,12 @@ static int sbc_emulate_verify(struct se_cmd *cmd) ...@@ -135,6 +135,12 @@ static int sbc_emulate_verify(struct se_cmd *cmd)
return 0; return 0;
} }
static int sbc_emulate_noop(struct se_cmd *cmd)
{
target_complete_cmd(cmd, GOOD);
return 0;
}
static inline u32 sbc_get_size(struct se_cmd *cmd, u32 sectors) static inline u32 sbc_get_size(struct se_cmd *cmd, u32 sectors)
{ {
return cmd->se_dev->se_sub_dev->se_dev_attrib.block_size * sectors; return cmd->se_dev->se_sub_dev->se_dev_attrib.block_size * sectors;
...@@ -531,6 +537,18 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops) ...@@ -531,6 +537,18 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops)
size = 0; size = 0;
cmd->execute_cmd = sbc_emulate_verify; cmd->execute_cmd = sbc_emulate_verify;
break; break;
case REZERO_UNIT:
case SEEK_6:
case SEEK_10:
/*
* There are still clients out there which use these old SCSI-2
* commands. This mainly happens when running VMs with legacy
* guest systems, connected via SCSI command pass-through to
* iSCSI targets. Make them happy and return status GOOD.
*/
size = 0;
cmd->execute_cmd = sbc_emulate_noop;
break;
default: default:
ret = spc_parse_cdb(cmd, &size); ret = spc_parse_cdb(cmd, &size);
if (ret) if (ret)
......
...@@ -1616,7 +1616,6 @@ static void target_complete_tmr_failure(struct work_struct *work) ...@@ -1616,7 +1616,6 @@ static void target_complete_tmr_failure(struct work_struct *work)
se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST; se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST;
se_cmd->se_tfo->queue_tm_rsp(se_cmd); se_cmd->se_tfo->queue_tm_rsp(se_cmd);
transport_generic_free_cmd(se_cmd, 0);
} }
/** /**
......
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