You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
Pull SCSI target updates from Nicholas Bellinger: "Things have been quiet this round with mostly bugfixes, percpu conversions, and other minor iscsi-target conformance testing changes. The highlights include: - Add demo_mode_discovery attribute for iscsi-target (Thomas) - Convert tcm_fc(FCoE) to use percpu-ida pre-allocation - Add send completion interrupt coalescing for ib_isert - Convert target-core to use percpu-refcounting for se_lun - Fix mutex_trylock usage bug in iscsit_increment_maxcmdsn - tcm_loop updates (Hannes) - target-core ALUA cleanups + prep for v3.14 SCSI Referrals support (Hannes) v3.14 is currently shaping to be a busy development cycle in target land, with initial support for T10 Referrals and T10 DIF currently on the roadmap" * 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: (40 commits) iscsi-target: chap auth shouldn't match username with trailing garbage iscsi-target: fix extract_param to handle buffer length corner case iscsi-target: Expose default_erl as TPG attribute target_core_configfs: split up ALUA supported states target_core_alua: Make supported states configurable target_core_alua: Store supported ALUA states target_core_alua: Rename ALUA_ACCESS_STATE_OPTIMIZED target_core_alua: spellcheck target core: rename (ex,im)plict -> (ex,im)plicit percpu-refcount: Add percpu-refcount.o to obj-y iscsi-target: Do not reject non-immediate CmdSNs exceeding MaxCmdSN iscsi-target: Convert iscsi_session statistics to atomic_long_t target: Convert se_device statistics to atomic_long_t target: Fix delayed Task Aborted Status (TAS) handling bug iscsi-target: Reject unsupported multi PDU text command sequence ib_isert: Avoid duplicate iscsit_increment_maxcmdsn call iscsi-target: Fix mutex_trylock usage in iscsit_increment_maxcmdsn target: Core does not need blkdev.h target: Pass through I/O topology for block backstores iser-target: Avoid using FRMR for single dma entry requests ...
This commit is contained in:
@@ -805,14 +805,7 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
|
||||
int iscsi_task_attr;
|
||||
int sam_task_attr;
|
||||
|
||||
spin_lock_bh(&conn->sess->session_stats_lock);
|
||||
conn->sess->cmd_pdus++;
|
||||
if (conn->sess->se_sess->se_node_acl) {
|
||||
spin_lock(&conn->sess->se_sess->se_node_acl->stats_lock);
|
||||
conn->sess->se_sess->se_node_acl->num_cmds++;
|
||||
spin_unlock(&conn->sess->se_sess->se_node_acl->stats_lock);
|
||||
}
|
||||
spin_unlock_bh(&conn->sess->session_stats_lock);
|
||||
atomic_long_inc(&conn->sess->cmd_pdus);
|
||||
|
||||
hdr = (struct iscsi_scsi_req *) buf;
|
||||
payload_length = ntoh24(hdr->dlength);
|
||||
@@ -1254,20 +1247,12 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf,
|
||||
int rc;
|
||||
|
||||
if (!payload_length) {
|
||||
pr_err("DataOUT payload is ZERO, protocol error.\n");
|
||||
return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
|
||||
buf);
|
||||
pr_warn("DataOUT payload is ZERO, ignoring.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* iSCSI write */
|
||||
spin_lock_bh(&conn->sess->session_stats_lock);
|
||||
conn->sess->rx_data_octets += payload_length;
|
||||
if (conn->sess->se_sess->se_node_acl) {
|
||||
spin_lock(&conn->sess->se_sess->se_node_acl->stats_lock);
|
||||
conn->sess->se_sess->se_node_acl->write_bytes += payload_length;
|
||||
spin_unlock(&conn->sess->se_sess->se_node_acl->stats_lock);
|
||||
}
|
||||
spin_unlock_bh(&conn->sess->session_stats_lock);
|
||||
atomic_long_add(payload_length, &conn->sess->rx_data_octets);
|
||||
|
||||
if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
|
||||
pr_err("DataSegmentLength: %u is greater than"
|
||||
@@ -1486,7 +1471,7 @@ EXPORT_SYMBOL(iscsit_check_dataout_payload);
|
||||
|
||||
static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
|
||||
{
|
||||
struct iscsi_cmd *cmd;
|
||||
struct iscsi_cmd *cmd = NULL;
|
||||
struct iscsi_data *hdr = (struct iscsi_data *)buf;
|
||||
int rc;
|
||||
bool data_crc_failed = false;
|
||||
@@ -1954,6 +1939,13 @@ iscsit_setup_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
|
||||
(unsigned char *)hdr);
|
||||
}
|
||||
|
||||
if (!(hdr->flags & ISCSI_FLAG_CMD_FINAL) ||
|
||||
(hdr->flags & ISCSI_FLAG_TEXT_CONTINUE)) {
|
||||
pr_err("Multi sequence text commands currently not supported\n");
|
||||
return iscsit_reject_cmd(cmd, ISCSI_REASON_CMD_NOT_SUPPORTED,
|
||||
(unsigned char *)hdr);
|
||||
}
|
||||
|
||||
pr_debug("Got Text Request: ITT: 0x%08x, CmdSN: 0x%08x,"
|
||||
" ExpStatSN: 0x%08x, Length: %u\n", hdr->itt, hdr->cmdsn,
|
||||
hdr->exp_statsn, payload_length);
|
||||
@@ -2630,14 +2622,7 @@ static int iscsit_send_datain(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
|
||||
return -1;
|
||||
}
|
||||
|
||||
spin_lock_bh(&conn->sess->session_stats_lock);
|
||||
conn->sess->tx_data_octets += datain.length;
|
||||
if (conn->sess->se_sess->se_node_acl) {
|
||||
spin_lock(&conn->sess->se_sess->se_node_acl->stats_lock);
|
||||
conn->sess->se_sess->se_node_acl->read_bytes += datain.length;
|
||||
spin_unlock(&conn->sess->se_sess->se_node_acl->stats_lock);
|
||||
}
|
||||
spin_unlock_bh(&conn->sess->session_stats_lock);
|
||||
atomic_long_add(datain.length, &conn->sess->tx_data_octets);
|
||||
/*
|
||||
* Special case for successfully execution w/ both DATAIN
|
||||
* and Sense Data.
|
||||
@@ -3162,9 +3147,7 @@ void iscsit_build_rsp_pdu(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
|
||||
if (inc_stat_sn)
|
||||
cmd->stat_sn = conn->stat_sn++;
|
||||
|
||||
spin_lock_bh(&conn->sess->session_stats_lock);
|
||||
conn->sess->rsp_pdus++;
|
||||
spin_unlock_bh(&conn->sess->session_stats_lock);
|
||||
atomic_long_inc(&conn->sess->rsp_pdus);
|
||||
|
||||
memset(hdr, 0, ISCSI_HDR_LEN);
|
||||
hdr->opcode = ISCSI_OP_SCSI_CMD_RSP;
|
||||
@@ -3374,6 +3357,7 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
|
||||
struct iscsi_tiqn *tiqn;
|
||||
struct iscsi_tpg_np *tpg_np;
|
||||
int buffer_len, end_of_buf = 0, len = 0, payload_len = 0;
|
||||
int target_name_printed;
|
||||
unsigned char buf[ISCSI_IQN_LEN+12]; /* iqn + "TargetName=" + \0 */
|
||||
unsigned char *text_in = cmd->text_in_ptr, *text_ptr = NULL;
|
||||
|
||||
@@ -3411,19 +3395,23 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
|
||||
continue;
|
||||
}
|
||||
|
||||
len = sprintf(buf, "TargetName=%s", tiqn->tiqn);
|
||||
len += 1;
|
||||
|
||||
if ((len + payload_len) > buffer_len) {
|
||||
end_of_buf = 1;
|
||||
goto eob;
|
||||
}
|
||||
memcpy(payload + payload_len, buf, len);
|
||||
payload_len += len;
|
||||
target_name_printed = 0;
|
||||
|
||||
spin_lock(&tiqn->tiqn_tpg_lock);
|
||||
list_for_each_entry(tpg, &tiqn->tiqn_tpg_list, tpg_list) {
|
||||
|
||||
/* If demo_mode_discovery=0 and generate_node_acls=0
|
||||
* (demo mode dislabed) do not return
|
||||
* TargetName+TargetAddress unless a NodeACL exists.
|
||||
*/
|
||||
|
||||
if ((tpg->tpg_attrib.generate_node_acls == 0) &&
|
||||
(tpg->tpg_attrib.demo_mode_discovery == 0) &&
|
||||
(!core_tpg_get_initiator_node_acl(&tpg->tpg_se_tpg,
|
||||
cmd->conn->sess->sess_ops->InitiatorName))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
spin_lock(&tpg->tpg_state_lock);
|
||||
if ((tpg->tpg_state == TPG_STATE_FREE) ||
|
||||
(tpg->tpg_state == TPG_STATE_INACTIVE)) {
|
||||
@@ -3438,6 +3426,22 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
|
||||
struct iscsi_np *np = tpg_np->tpg_np;
|
||||
bool inaddr_any = iscsit_check_inaddr_any(np);
|
||||
|
||||
if (!target_name_printed) {
|
||||
len = sprintf(buf, "TargetName=%s",
|
||||
tiqn->tiqn);
|
||||
len += 1;
|
||||
|
||||
if ((len + payload_len) > buffer_len) {
|
||||
spin_unlock(&tpg->tpg_np_lock);
|
||||
spin_unlock(&tiqn->tiqn_tpg_lock);
|
||||
end_of_buf = 1;
|
||||
goto eob;
|
||||
}
|
||||
memcpy(payload + payload_len, buf, len);
|
||||
payload_len += len;
|
||||
target_name_printed = 1;
|
||||
}
|
||||
|
||||
len = sprintf(buf, "TargetAddress="
|
||||
"%s:%hu,%hu",
|
||||
(inaddr_any == false) ?
|
||||
@@ -4092,9 +4096,7 @@ restart:
|
||||
* hit default in the switch below.
|
||||
*/
|
||||
memset(buffer, 0xff, ISCSI_HDR_LEN);
|
||||
spin_lock_bh(&conn->sess->session_stats_lock);
|
||||
conn->sess->conn_digest_errors++;
|
||||
spin_unlock_bh(&conn->sess->session_stats_lock);
|
||||
atomic_long_inc(&conn->sess->conn_digest_errors);
|
||||
} else {
|
||||
pr_debug("Got HeaderDigest CRC32C"
|
||||
" 0x%08x\n", checksum);
|
||||
@@ -4381,7 +4383,7 @@ int iscsit_close_connection(
|
||||
|
||||
int iscsit_close_session(struct iscsi_session *sess)
|
||||
{
|
||||
struct iscsi_portal_group *tpg = ISCSI_TPG_S(sess);
|
||||
struct iscsi_portal_group *tpg = sess->tpg;
|
||||
struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
|
||||
|
||||
if (atomic_read(&sess->nconn)) {
|
||||
|
||||
@@ -111,7 +111,7 @@ static struct iscsi_chap *chap_server_open(
|
||||
/*
|
||||
* Set Identifier.
|
||||
*/
|
||||
chap->id = ISCSI_TPG_C(conn)->tpg_chap_id++;
|
||||
chap->id = conn->tpg->tpg_chap_id++;
|
||||
*aic_len += sprintf(aic_str + *aic_len, "CHAP_I=%d", chap->id);
|
||||
*aic_len += 1;
|
||||
pr_debug("[server] Sending CHAP_I=%d\n", chap->id);
|
||||
@@ -146,6 +146,7 @@ static int chap_server_compute_md5(
|
||||
unsigned char client_digest[MD5_SIGNATURE_SIZE];
|
||||
unsigned char server_digest[MD5_SIGNATURE_SIZE];
|
||||
unsigned char chap_n[MAX_CHAP_N_SIZE], chap_r[MAX_RESPONSE_LENGTH];
|
||||
size_t compare_len;
|
||||
struct iscsi_chap *chap = conn->auth_protocol;
|
||||
struct crypto_hash *tfm;
|
||||
struct hash_desc desc;
|
||||
@@ -184,7 +185,9 @@ static int chap_server_compute_md5(
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (memcmp(chap_n, auth->userid, strlen(auth->userid)) != 0) {
|
||||
/* Include the terminating NULL in the compare */
|
||||
compare_len = strlen(auth->userid) + 1;
|
||||
if (strncmp(chap_n, auth->userid, compare_len) != 0) {
|
||||
pr_err("CHAP_N values do not match!\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -372,7 +372,7 @@ static ssize_t iscsi_nacl_attrib_show_##name( \
|
||||
struct iscsi_node_acl *nacl = container_of(se_nacl, struct iscsi_node_acl, \
|
||||
se_node_acl); \
|
||||
\
|
||||
return sprintf(page, "%u\n", ISCSI_NODE_ATTRIB(nacl)->name); \
|
||||
return sprintf(page, "%u\n", nacl->node_attrib.name); \
|
||||
} \
|
||||
\
|
||||
static ssize_t iscsi_nacl_attrib_store_##name( \
|
||||
@@ -897,7 +897,7 @@ static struct se_node_acl *lio_target_make_nodeacl(
|
||||
if (!se_nacl_new)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
cmdsn_depth = ISCSI_TPG_ATTRIB(tpg)->default_cmdsn_depth;
|
||||
cmdsn_depth = tpg->tpg_attrib.default_cmdsn_depth;
|
||||
/*
|
||||
* se_nacl_new may be released by core_tpg_add_initiator_node_acl()
|
||||
* when converting a NdoeACL from demo mode -> explict
|
||||
@@ -920,9 +920,9 @@ static struct se_node_acl *lio_target_make_nodeacl(
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
stats_cg->default_groups[0] = &NODE_STAT_GRPS(acl)->iscsi_sess_stats_group;
|
||||
stats_cg->default_groups[0] = &acl->node_stat_grps.iscsi_sess_stats_group;
|
||||
stats_cg->default_groups[1] = NULL;
|
||||
config_group_init_type_name(&NODE_STAT_GRPS(acl)->iscsi_sess_stats_group,
|
||||
config_group_init_type_name(&acl->node_stat_grps.iscsi_sess_stats_group,
|
||||
"iscsi_sess_stats", &iscsi_stat_sess_cit);
|
||||
|
||||
return se_nacl;
|
||||
@@ -967,7 +967,7 @@ static ssize_t iscsi_tpg_attrib_show_##name( \
|
||||
if (iscsit_get_tpg(tpg) < 0) \
|
||||
return -EINVAL; \
|
||||
\
|
||||
rb = sprintf(page, "%u\n", ISCSI_TPG_ATTRIB(tpg)->name); \
|
||||
rb = sprintf(page, "%u\n", tpg->tpg_attrib.name); \
|
||||
iscsit_put_tpg(tpg); \
|
||||
return rb; \
|
||||
} \
|
||||
@@ -1041,6 +1041,16 @@ TPG_ATTR(demo_mode_write_protect, S_IRUGO | S_IWUSR);
|
||||
*/
|
||||
DEF_TPG_ATTRIB(prod_mode_write_protect);
|
||||
TPG_ATTR(prod_mode_write_protect, S_IRUGO | S_IWUSR);
|
||||
/*
|
||||
* Define iscsi_tpg_attrib_s_demo_mode_discovery,
|
||||
*/
|
||||
DEF_TPG_ATTRIB(demo_mode_discovery);
|
||||
TPG_ATTR(demo_mode_discovery, S_IRUGO | S_IWUSR);
|
||||
/*
|
||||
* Define iscsi_tpg_attrib_s_default_erl
|
||||
*/
|
||||
DEF_TPG_ATTRIB(default_erl);
|
||||
TPG_ATTR(default_erl, S_IRUGO | S_IWUSR);
|
||||
|
||||
static struct configfs_attribute *lio_target_tpg_attrib_attrs[] = {
|
||||
&iscsi_tpg_attrib_authentication.attr,
|
||||
@@ -1051,6 +1061,8 @@ static struct configfs_attribute *lio_target_tpg_attrib_attrs[] = {
|
||||
&iscsi_tpg_attrib_cache_dynamic_acls.attr,
|
||||
&iscsi_tpg_attrib_demo_mode_write_protect.attr,
|
||||
&iscsi_tpg_attrib_prod_mode_write_protect.attr,
|
||||
&iscsi_tpg_attrib_demo_mode_discovery.attr,
|
||||
&iscsi_tpg_attrib_default_erl.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -1514,21 +1526,21 @@ static struct se_wwn *lio_target_call_coreaddtiqn(
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
stats_cg->default_groups[0] = &WWN_STAT_GRPS(tiqn)->iscsi_instance_group;
|
||||
stats_cg->default_groups[1] = &WWN_STAT_GRPS(tiqn)->iscsi_sess_err_group;
|
||||
stats_cg->default_groups[2] = &WWN_STAT_GRPS(tiqn)->iscsi_tgt_attr_group;
|
||||
stats_cg->default_groups[3] = &WWN_STAT_GRPS(tiqn)->iscsi_login_stats_group;
|
||||
stats_cg->default_groups[4] = &WWN_STAT_GRPS(tiqn)->iscsi_logout_stats_group;
|
||||
stats_cg->default_groups[0] = &tiqn->tiqn_stat_grps.iscsi_instance_group;
|
||||
stats_cg->default_groups[1] = &tiqn->tiqn_stat_grps.iscsi_sess_err_group;
|
||||
stats_cg->default_groups[2] = &tiqn->tiqn_stat_grps.iscsi_tgt_attr_group;
|
||||
stats_cg->default_groups[3] = &tiqn->tiqn_stat_grps.iscsi_login_stats_group;
|
||||
stats_cg->default_groups[4] = &tiqn->tiqn_stat_grps.iscsi_logout_stats_group;
|
||||
stats_cg->default_groups[5] = NULL;
|
||||
config_group_init_type_name(&WWN_STAT_GRPS(tiqn)->iscsi_instance_group,
|
||||
config_group_init_type_name(&tiqn->tiqn_stat_grps.iscsi_instance_group,
|
||||
"iscsi_instance", &iscsi_stat_instance_cit);
|
||||
config_group_init_type_name(&WWN_STAT_GRPS(tiqn)->iscsi_sess_err_group,
|
||||
config_group_init_type_name(&tiqn->tiqn_stat_grps.iscsi_sess_err_group,
|
||||
"iscsi_sess_err", &iscsi_stat_sess_err_cit);
|
||||
config_group_init_type_name(&WWN_STAT_GRPS(tiqn)->iscsi_tgt_attr_group,
|
||||
config_group_init_type_name(&tiqn->tiqn_stat_grps.iscsi_tgt_attr_group,
|
||||
"iscsi_tgt_attr", &iscsi_stat_tgt_attr_cit);
|
||||
config_group_init_type_name(&WWN_STAT_GRPS(tiqn)->iscsi_login_stats_group,
|
||||
config_group_init_type_name(&tiqn->tiqn_stat_grps.iscsi_login_stats_group,
|
||||
"iscsi_login_stats", &iscsi_stat_login_cit);
|
||||
config_group_init_type_name(&WWN_STAT_GRPS(tiqn)->iscsi_logout_stats_group,
|
||||
config_group_init_type_name(&tiqn->tiqn_stat_grps.iscsi_logout_stats_group,
|
||||
"iscsi_logout_stats", &iscsi_stat_logout_cit);
|
||||
|
||||
pr_debug("LIO_Target_ConfigFS: REGISTER -> %s\n", tiqn->tiqn);
|
||||
@@ -1784,6 +1796,11 @@ static int lio_queue_status(struct se_cmd *se_cmd)
|
||||
struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
|
||||
|
||||
cmd->i_state = ISTATE_SEND_STATUS;
|
||||
|
||||
if (cmd->se_cmd.scsi_status || cmd->sense_reason) {
|
||||
iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state);
|
||||
return 0;
|
||||
}
|
||||
cmd->conn->conn_transport->iscsit_queue_status(cmd->conn, cmd);
|
||||
|
||||
return 0;
|
||||
@@ -1815,21 +1832,21 @@ static u32 lio_tpg_get_default_depth(struct se_portal_group *se_tpg)
|
||||
{
|
||||
struct iscsi_portal_group *tpg = se_tpg->se_tpg_fabric_ptr;
|
||||
|
||||
return ISCSI_TPG_ATTRIB(tpg)->default_cmdsn_depth;
|
||||
return tpg->tpg_attrib.default_cmdsn_depth;
|
||||
}
|
||||
|
||||
static int lio_tpg_check_demo_mode(struct se_portal_group *se_tpg)
|
||||
{
|
||||
struct iscsi_portal_group *tpg = se_tpg->se_tpg_fabric_ptr;
|
||||
|
||||
return ISCSI_TPG_ATTRIB(tpg)->generate_node_acls;
|
||||
return tpg->tpg_attrib.generate_node_acls;
|
||||
}
|
||||
|
||||
static int lio_tpg_check_demo_mode_cache(struct se_portal_group *se_tpg)
|
||||
{
|
||||
struct iscsi_portal_group *tpg = se_tpg->se_tpg_fabric_ptr;
|
||||
|
||||
return ISCSI_TPG_ATTRIB(tpg)->cache_dynamic_acls;
|
||||
return tpg->tpg_attrib.cache_dynamic_acls;
|
||||
}
|
||||
|
||||
static int lio_tpg_check_demo_mode_write_protect(
|
||||
@@ -1837,7 +1854,7 @@ static int lio_tpg_check_demo_mode_write_protect(
|
||||
{
|
||||
struct iscsi_portal_group *tpg = se_tpg->se_tpg_fabric_ptr;
|
||||
|
||||
return ISCSI_TPG_ATTRIB(tpg)->demo_mode_write_protect;
|
||||
return tpg->tpg_attrib.demo_mode_write_protect;
|
||||
}
|
||||
|
||||
static int lio_tpg_check_prod_mode_write_protect(
|
||||
@@ -1845,7 +1862,7 @@ static int lio_tpg_check_prod_mode_write_protect(
|
||||
{
|
||||
struct iscsi_portal_group *tpg = se_tpg->se_tpg_fabric_ptr;
|
||||
|
||||
return ISCSI_TPG_ATTRIB(tpg)->prod_mode_write_protect;
|
||||
return tpg->tpg_attrib.prod_mode_write_protect;
|
||||
}
|
||||
|
||||
static void lio_tpg_release_fabric_acl(
|
||||
@@ -1908,9 +1925,12 @@ static void lio_set_default_node_attributes(struct se_node_acl *se_acl)
|
||||
{
|
||||
struct iscsi_node_acl *acl = container_of(se_acl, struct iscsi_node_acl,
|
||||
se_node_acl);
|
||||
struct se_portal_group *se_tpg = se_acl->se_tpg;
|
||||
struct iscsi_portal_group *tpg = container_of(se_tpg,
|
||||
struct iscsi_portal_group, tpg_se_tpg);
|
||||
|
||||
ISCSI_NODE_ATTRIB(acl)->nacl = acl;
|
||||
iscsit_set_default_node_attribues(acl);
|
||||
acl->node_attrib.nacl = acl;
|
||||
iscsit_set_default_node_attribues(acl, tpg);
|
||||
}
|
||||
|
||||
static int lio_check_stop_free(struct se_cmd *se_cmd)
|
||||
@@ -1995,17 +2015,17 @@ int iscsi_target_register_configfs(void)
|
||||
* Setup default attribute lists for various fabric->tf_cit_tmpl
|
||||
* sturct config_item_type's
|
||||
*/
|
||||
TF_CIT_TMPL(fabric)->tfc_discovery_cit.ct_attrs = lio_target_discovery_auth_attrs;
|
||||
TF_CIT_TMPL(fabric)->tfc_wwn_cit.ct_attrs = lio_target_wwn_attrs;
|
||||
TF_CIT_TMPL(fabric)->tfc_tpg_base_cit.ct_attrs = lio_target_tpg_attrs;
|
||||
TF_CIT_TMPL(fabric)->tfc_tpg_attrib_cit.ct_attrs = lio_target_tpg_attrib_attrs;
|
||||
TF_CIT_TMPL(fabric)->tfc_tpg_auth_cit.ct_attrs = lio_target_tpg_auth_attrs;
|
||||
TF_CIT_TMPL(fabric)->tfc_tpg_param_cit.ct_attrs = lio_target_tpg_param_attrs;
|
||||
TF_CIT_TMPL(fabric)->tfc_tpg_np_base_cit.ct_attrs = lio_target_portal_attrs;
|
||||
TF_CIT_TMPL(fabric)->tfc_tpg_nacl_base_cit.ct_attrs = lio_target_initiator_attrs;
|
||||
TF_CIT_TMPL(fabric)->tfc_tpg_nacl_attrib_cit.ct_attrs = lio_target_nacl_attrib_attrs;
|
||||
TF_CIT_TMPL(fabric)->tfc_tpg_nacl_auth_cit.ct_attrs = lio_target_nacl_auth_attrs;
|
||||
TF_CIT_TMPL(fabric)->tfc_tpg_nacl_param_cit.ct_attrs = lio_target_nacl_param_attrs;
|
||||
fabric->tf_cit_tmpl.tfc_discovery_cit.ct_attrs = lio_target_discovery_auth_attrs;
|
||||
fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = lio_target_wwn_attrs;
|
||||
fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = lio_target_tpg_attrs;
|
||||
fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = lio_target_tpg_attrib_attrs;
|
||||
fabric->tf_cit_tmpl.tfc_tpg_auth_cit.ct_attrs = lio_target_tpg_auth_attrs;
|
||||
fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = lio_target_tpg_param_attrs;
|
||||
fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = lio_target_portal_attrs;
|
||||
fabric->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs = lio_target_initiator_attrs;
|
||||
fabric->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = lio_target_nacl_attrib_attrs;
|
||||
fabric->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = lio_target_nacl_auth_attrs;
|
||||
fabric->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = lio_target_nacl_param_attrs;
|
||||
|
||||
ret = target_fabric_configfs_register(fabric);
|
||||
if (ret < 0) {
|
||||
|
||||
@@ -37,9 +37,6 @@
|
||||
#define NA_RANDOM_DATAIN_PDU_OFFSETS 0
|
||||
#define NA_RANDOM_DATAIN_SEQ_OFFSETS 0
|
||||
#define NA_RANDOM_R2T_OFFSETS 0
|
||||
#define NA_DEFAULT_ERL 0
|
||||
#define NA_DEFAULT_ERL_MAX 2
|
||||
#define NA_DEFAULT_ERL_MIN 0
|
||||
|
||||
/* struct iscsi_tpg_attrib sanity values */
|
||||
#define TA_AUTHENTICATION 1
|
||||
@@ -58,6 +55,8 @@
|
||||
#define TA_DEMO_MODE_WRITE_PROTECT 1
|
||||
/* Disabled by default in production mode w/ explict ACLs */
|
||||
#define TA_PROD_MODE_WRITE_PROTECT 0
|
||||
#define TA_DEMO_MODE_DISCOVERY 1
|
||||
#define TA_DEFAULT_ERL 0
|
||||
#define TA_CACHE_CORE_NPS 0
|
||||
|
||||
|
||||
@@ -192,6 +191,7 @@ enum recover_cmdsn_ret_table {
|
||||
CMDSN_NORMAL_OPERATION = 0,
|
||||
CMDSN_LOWER_THAN_EXP = 1,
|
||||
CMDSN_HIGHER_THAN_EXP = 2,
|
||||
CMDSN_MAXCMDSN_OVERRUN = 3,
|
||||
};
|
||||
|
||||
/* Used for iscsi_handle_immediate_data() return values */
|
||||
@@ -650,14 +650,13 @@ struct iscsi_session {
|
||||
/* Used for session reference counting */
|
||||
int session_usage_count;
|
||||
int session_waiting_on_uc;
|
||||
u32 cmd_pdus;
|
||||
u32 rsp_pdus;
|
||||
u64 tx_data_octets;
|
||||
u64 rx_data_octets;
|
||||
u32 conn_digest_errors;
|
||||
u32 conn_timeout_errors;
|
||||
atomic_long_t cmd_pdus;
|
||||
atomic_long_t rsp_pdus;
|
||||
atomic_long_t tx_data_octets;
|
||||
atomic_long_t rx_data_octets;
|
||||
atomic_long_t conn_digest_errors;
|
||||
atomic_long_t conn_timeout_errors;
|
||||
u64 creation_time;
|
||||
spinlock_t session_stats_lock;
|
||||
/* Number of active connections */
|
||||
atomic_t nconn;
|
||||
atomic_t session_continuation;
|
||||
@@ -755,11 +754,6 @@ struct iscsi_node_acl {
|
||||
struct se_node_acl se_node_acl;
|
||||
};
|
||||
|
||||
#define NODE_STAT_GRPS(nacl) (&(nacl)->node_stat_grps)
|
||||
|
||||
#define ISCSI_NODE_ATTRIB(t) (&(t)->node_attrib)
|
||||
#define ISCSI_NODE_AUTH(t) (&(t)->node_auth)
|
||||
|
||||
struct iscsi_tpg_attrib {
|
||||
u32 authentication;
|
||||
u32 login_timeout;
|
||||
@@ -769,6 +763,8 @@ struct iscsi_tpg_attrib {
|
||||
u32 default_cmdsn_depth;
|
||||
u32 demo_mode_write_protect;
|
||||
u32 prod_mode_write_protect;
|
||||
u32 demo_mode_discovery;
|
||||
u32 default_erl;
|
||||
struct iscsi_portal_group *tpg;
|
||||
};
|
||||
|
||||
@@ -835,12 +831,6 @@ struct iscsi_portal_group {
|
||||
struct list_head tpg_list;
|
||||
} ____cacheline_aligned;
|
||||
|
||||
#define ISCSI_TPG_C(c) ((struct iscsi_portal_group *)(c)->tpg)
|
||||
#define ISCSI_TPG_LUN(c, l) ((iscsi_tpg_list_t *)(c)->tpg->tpg_lun_list_t[l])
|
||||
#define ISCSI_TPG_S(s) ((struct iscsi_portal_group *)(s)->tpg)
|
||||
#define ISCSI_TPG_ATTRIB(t) (&(t)->tpg_attrib)
|
||||
#define SE_TPG(tpg) (&(tpg)->tpg_se_tpg)
|
||||
|
||||
struct iscsi_wwn_stat_grps {
|
||||
struct config_group iscsi_stat_group;
|
||||
struct config_group iscsi_instance_group;
|
||||
@@ -871,8 +861,6 @@ struct iscsi_tiqn {
|
||||
struct iscsi_logout_stats logout_stats;
|
||||
} ____cacheline_aligned;
|
||||
|
||||
#define WWN_STAT_GRPS(tiqn) (&(tiqn)->tiqn_stat_grps)
|
||||
|
||||
struct iscsit_global {
|
||||
/* In core shutdown */
|
||||
u32 in_shutdown;
|
||||
|
||||
@@ -58,11 +58,7 @@ void iscsit_increment_maxcmdsn(struct iscsi_cmd *cmd, struct iscsi_session *sess
|
||||
|
||||
cmd->maxcmdsn_inc = 1;
|
||||
|
||||
if (!mutex_trylock(&sess->cmdsn_mutex)) {
|
||||
sess->max_cmd_sn += 1;
|
||||
pr_debug("Updated MaxCmdSN to 0x%08x\n", sess->max_cmd_sn);
|
||||
return;
|
||||
}
|
||||
mutex_lock(&sess->cmdsn_mutex);
|
||||
sess->max_cmd_sn += 1;
|
||||
pr_debug("Updated MaxCmdSN to 0x%08x\n", sess->max_cmd_sn);
|
||||
mutex_unlock(&sess->cmdsn_mutex);
|
||||
|
||||
@@ -757,7 +757,7 @@ int iscsit_check_post_dataout(
|
||||
static void iscsit_handle_time2retain_timeout(unsigned long data)
|
||||
{
|
||||
struct iscsi_session *sess = (struct iscsi_session *) data;
|
||||
struct iscsi_portal_group *tpg = ISCSI_TPG_S(sess);
|
||||
struct iscsi_portal_group *tpg = sess->tpg;
|
||||
struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
|
||||
|
||||
spin_lock_bh(&se_tpg->session_lock);
|
||||
@@ -785,7 +785,7 @@ static void iscsit_handle_time2retain_timeout(unsigned long data)
|
||||
tiqn->sess_err_stats.last_sess_failure_type =
|
||||
ISCSI_SESS_ERR_CXN_TIMEOUT;
|
||||
tiqn->sess_err_stats.cxn_timeout_errors++;
|
||||
sess->conn_timeout_errors++;
|
||||
atomic_long_inc(&sess->conn_timeout_errors);
|
||||
spin_unlock(&tiqn->sess_err_stats.lock);
|
||||
}
|
||||
}
|
||||
@@ -801,9 +801,9 @@ void iscsit_start_time2retain_handler(struct iscsi_session *sess)
|
||||
* Only start Time2Retain timer when the associated TPG is still in
|
||||
* an ACTIVE (eg: not disabled or shutdown) state.
|
||||
*/
|
||||
spin_lock(&ISCSI_TPG_S(sess)->tpg_state_lock);
|
||||
tpg_active = (ISCSI_TPG_S(sess)->tpg_state == TPG_STATE_ACTIVE);
|
||||
spin_unlock(&ISCSI_TPG_S(sess)->tpg_state_lock);
|
||||
spin_lock(&sess->tpg->tpg_state_lock);
|
||||
tpg_active = (sess->tpg->tpg_state == TPG_STATE_ACTIVE);
|
||||
spin_unlock(&sess->tpg->tpg_state_lock);
|
||||
|
||||
if (!tpg_active)
|
||||
return;
|
||||
@@ -829,7 +829,7 @@ void iscsit_start_time2retain_handler(struct iscsi_session *sess)
|
||||
*/
|
||||
int iscsit_stop_time2retain_timer(struct iscsi_session *sess)
|
||||
{
|
||||
struct iscsi_portal_group *tpg = ISCSI_TPG_S(sess);
|
||||
struct iscsi_portal_group *tpg = sess->tpg;
|
||||
struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
|
||||
|
||||
if (sess->time2retain_timer_flags & ISCSI_TF_EXPIRED)
|
||||
|
||||
@@ -305,7 +305,6 @@ static int iscsi_login_zero_tsih_s1(
|
||||
}
|
||||
|
||||
sess->creation_time = get_jiffies_64();
|
||||
spin_lock_init(&sess->session_stats_lock);
|
||||
/*
|
||||
* The FFP CmdSN window values will be allocated from the TPG's
|
||||
* Initiator Node's ACL once the login has been successfully completed.
|
||||
@@ -347,15 +346,15 @@ static int iscsi_login_zero_tsih_s2(
|
||||
* Assign a new TPG Session Handle. Note this is protected with
|
||||
* struct iscsi_portal_group->np_login_sem from iscsit_access_np().
|
||||
*/
|
||||
sess->tsih = ++ISCSI_TPG_S(sess)->ntsih;
|
||||
sess->tsih = ++sess->tpg->ntsih;
|
||||
if (!sess->tsih)
|
||||
sess->tsih = ++ISCSI_TPG_S(sess)->ntsih;
|
||||
sess->tsih = ++sess->tpg->ntsih;
|
||||
|
||||
/*
|
||||
* Create the default params from user defined values..
|
||||
*/
|
||||
if (iscsi_copy_param_list(&conn->param_list,
|
||||
ISCSI_TPG_C(conn)->param_list, 1) < 0) {
|
||||
conn->tpg->param_list, 1) < 0) {
|
||||
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
|
||||
ISCSI_LOGIN_STATUS_NO_RESOURCES);
|
||||
return -1;
|
||||
@@ -380,7 +379,7 @@ static int iscsi_login_zero_tsih_s2(
|
||||
* In our case, we have already located the struct iscsi_tiqn at this point.
|
||||
*/
|
||||
memset(buf, 0, 32);
|
||||
sprintf(buf, "TargetPortalGroupTag=%hu", ISCSI_TPG_S(sess)->tpgt);
|
||||
sprintf(buf, "TargetPortalGroupTag=%hu", sess->tpg->tpgt);
|
||||
if (iscsi_change_param_value(buf, conn->param_list, 0) < 0) {
|
||||
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
|
||||
ISCSI_LOGIN_STATUS_NO_RESOURCES);
|
||||
@@ -575,7 +574,7 @@ static int iscsi_login_non_zero_tsih_s2(
|
||||
iscsi_login_set_conn_values(sess, conn, pdu->cid);
|
||||
|
||||
if (iscsi_copy_param_list(&conn->param_list,
|
||||
ISCSI_TPG_C(conn)->param_list, 0) < 0) {
|
||||
conn->tpg->param_list, 0) < 0) {
|
||||
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
|
||||
ISCSI_LOGIN_STATUS_NO_RESOURCES);
|
||||
return -1;
|
||||
@@ -593,7 +592,7 @@ static int iscsi_login_non_zero_tsih_s2(
|
||||
* In our case, we have already located the struct iscsi_tiqn at this point.
|
||||
*/
|
||||
memset(buf, 0, 32);
|
||||
sprintf(buf, "TargetPortalGroupTag=%hu", ISCSI_TPG_S(sess)->tpgt);
|
||||
sprintf(buf, "TargetPortalGroupTag=%hu", sess->tpg->tpgt);
|
||||
if (iscsi_change_param_value(buf, conn->param_list, 0) < 0) {
|
||||
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
|
||||
ISCSI_LOGIN_STATUS_NO_RESOURCES);
|
||||
@@ -691,7 +690,7 @@ int iscsi_post_login_handler(
|
||||
int stop_timer = 0;
|
||||
struct iscsi_session *sess = conn->sess;
|
||||
struct se_session *se_sess = sess->se_sess;
|
||||
struct iscsi_portal_group *tpg = ISCSI_TPG_S(sess);
|
||||
struct iscsi_portal_group *tpg = sess->tpg;
|
||||
struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
|
||||
struct iscsi_thread_set *ts;
|
||||
|
||||
@@ -1154,7 +1153,7 @@ old_sess_out:
|
||||
spin_lock_bh(&conn->sess->conn_lock);
|
||||
if (conn->sess->session_state == TARG_SESS_STATE_FAILED) {
|
||||
struct se_portal_group *se_tpg =
|
||||
&ISCSI_TPG_C(conn)->tpg_se_tpg;
|
||||
&conn->tpg->tpg_se_tpg;
|
||||
|
||||
atomic_set(&conn->sess->session_continuation, 0);
|
||||
spin_unlock_bh(&conn->sess->conn_lock);
|
||||
|
||||
@@ -88,7 +88,7 @@ int extract_param(
|
||||
if (len < 0)
|
||||
return -1;
|
||||
|
||||
if (len > max_length) {
|
||||
if (len >= max_length) {
|
||||
pr_err("Length of input: %d exceeds max_length:"
|
||||
" %d\n", len, max_length);
|
||||
return -1;
|
||||
@@ -140,7 +140,7 @@ static u32 iscsi_handle_authentication(
|
||||
iscsi_nacl = container_of(se_nacl, struct iscsi_node_acl,
|
||||
se_node_acl);
|
||||
|
||||
auth = ISCSI_NODE_AUTH(iscsi_nacl);
|
||||
auth = &iscsi_nacl->node_auth;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
@@ -789,7 +789,7 @@ static int iscsi_target_handle_csg_zero(
|
||||
return -1;
|
||||
|
||||
if (!iscsi_check_negotiated_keys(conn->param_list)) {
|
||||
if (ISCSI_TPG_ATTRIB(ISCSI_TPG_C(conn))->authentication &&
|
||||
if (conn->tpg->tpg_attrib.authentication &&
|
||||
!strncmp(param->value, NONE, 4)) {
|
||||
pr_err("Initiator sent AuthMethod=None but"
|
||||
" Target is enforcing iSCSI Authentication,"
|
||||
@@ -799,7 +799,7 @@ static int iscsi_target_handle_csg_zero(
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ISCSI_TPG_ATTRIB(ISCSI_TPG_C(conn))->authentication &&
|
||||
if (conn->tpg->tpg_attrib.authentication &&
|
||||
!login->auth_complete)
|
||||
return 0;
|
||||
|
||||
@@ -862,7 +862,7 @@ static int iscsi_target_handle_csg_one(struct iscsi_conn *conn, struct iscsi_log
|
||||
}
|
||||
|
||||
if (!login->auth_complete &&
|
||||
ISCSI_TPG_ATTRIB(ISCSI_TPG_C(conn))->authentication) {
|
||||
conn->tpg->tpg_attrib.authentication) {
|
||||
pr_err("Initiator is requesting CSG: 1, has not been"
|
||||
" successfully authenticated, and the Target is"
|
||||
" enforcing iSCSI Authentication, login failed.\n");
|
||||
|
||||
@@ -33,7 +33,8 @@ static inline char *iscsit_na_get_initiatorname(
|
||||
}
|
||||
|
||||
void iscsit_set_default_node_attribues(
|
||||
struct iscsi_node_acl *acl)
|
||||
struct iscsi_node_acl *acl,
|
||||
struct iscsi_portal_group *tpg)
|
||||
{
|
||||
struct iscsi_node_attrib *a = &acl->node_attrib;
|
||||
|
||||
@@ -44,7 +45,7 @@ void iscsit_set_default_node_attribues(
|
||||
a->random_datain_pdu_offsets = NA_RANDOM_DATAIN_PDU_OFFSETS;
|
||||
a->random_datain_seq_offsets = NA_RANDOM_DATAIN_SEQ_OFFSETS;
|
||||
a->random_r2t_offsets = NA_RANDOM_R2T_OFFSETS;
|
||||
a->default_erl = NA_DEFAULT_ERL;
|
||||
a->default_erl = tpg->tpg_attrib.default_erl;
|
||||
}
|
||||
|
||||
int iscsit_na_dataout_timeout(
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#ifndef ISCSI_TARGET_NODEATTRIB_H
|
||||
#define ISCSI_TARGET_NODEATTRIB_H
|
||||
|
||||
extern void iscsit_set_default_node_attribues(struct iscsi_node_acl *);
|
||||
extern void iscsit_set_default_node_attribues(struct iscsi_node_acl *,
|
||||
struct iscsi_portal_group *);
|
||||
extern int iscsit_na_dataout_timeout(struct iscsi_node_acl *, u32);
|
||||
extern int iscsit_na_dataout_timeout_retries(struct iscsi_node_acl *, u32);
|
||||
extern int iscsit_na_nopin_timeout(struct iscsi_node_acl *, u32);
|
||||
|
||||
@@ -792,7 +792,8 @@ static ssize_t iscsi_stat_sess_show_attr_cmd_pdus(
|
||||
if (se_sess) {
|
||||
sess = se_sess->fabric_sess_ptr;
|
||||
if (sess)
|
||||
ret = snprintf(page, PAGE_SIZE, "%u\n", sess->cmd_pdus);
|
||||
ret = snprintf(page, PAGE_SIZE, "%lu\n",
|
||||
atomic_long_read(&sess->cmd_pdus));
|
||||
}
|
||||
spin_unlock_bh(&se_nacl->nacl_sess_lock);
|
||||
|
||||
@@ -815,7 +816,8 @@ static ssize_t iscsi_stat_sess_show_attr_rsp_pdus(
|
||||
if (se_sess) {
|
||||
sess = se_sess->fabric_sess_ptr;
|
||||
if (sess)
|
||||
ret = snprintf(page, PAGE_SIZE, "%u\n", sess->rsp_pdus);
|
||||
ret = snprintf(page, PAGE_SIZE, "%lu\n",
|
||||
atomic_long_read(&sess->rsp_pdus));
|
||||
}
|
||||
spin_unlock_bh(&se_nacl->nacl_sess_lock);
|
||||
|
||||
@@ -838,8 +840,8 @@ static ssize_t iscsi_stat_sess_show_attr_txdata_octs(
|
||||
if (se_sess) {
|
||||
sess = se_sess->fabric_sess_ptr;
|
||||
if (sess)
|
||||
ret = snprintf(page, PAGE_SIZE, "%llu\n",
|
||||
(unsigned long long)sess->tx_data_octets);
|
||||
ret = snprintf(page, PAGE_SIZE, "%lu\n",
|
||||
atomic_long_read(&sess->tx_data_octets));
|
||||
}
|
||||
spin_unlock_bh(&se_nacl->nacl_sess_lock);
|
||||
|
||||
@@ -862,8 +864,8 @@ static ssize_t iscsi_stat_sess_show_attr_rxdata_octs(
|
||||
if (se_sess) {
|
||||
sess = se_sess->fabric_sess_ptr;
|
||||
if (sess)
|
||||
ret = snprintf(page, PAGE_SIZE, "%llu\n",
|
||||
(unsigned long long)sess->rx_data_octets);
|
||||
ret = snprintf(page, PAGE_SIZE, "%lu\n",
|
||||
atomic_long_read(&sess->rx_data_octets));
|
||||
}
|
||||
spin_unlock_bh(&se_nacl->nacl_sess_lock);
|
||||
|
||||
@@ -886,8 +888,8 @@ static ssize_t iscsi_stat_sess_show_attr_conn_digest_errors(
|
||||
if (se_sess) {
|
||||
sess = se_sess->fabric_sess_ptr;
|
||||
if (sess)
|
||||
ret = snprintf(page, PAGE_SIZE, "%u\n",
|
||||
sess->conn_digest_errors);
|
||||
ret = snprintf(page, PAGE_SIZE, "%lu\n",
|
||||
atomic_long_read(&sess->conn_digest_errors));
|
||||
}
|
||||
spin_unlock_bh(&se_nacl->nacl_sess_lock);
|
||||
|
||||
@@ -910,8 +912,8 @@ static ssize_t iscsi_stat_sess_show_attr_conn_timeout_errors(
|
||||
if (se_sess) {
|
||||
sess = se_sess->fabric_sess_ptr;
|
||||
if (sess)
|
||||
ret = snprintf(page, PAGE_SIZE, "%u\n",
|
||||
sess->conn_timeout_errors);
|
||||
ret = snprintf(page, PAGE_SIZE, "%lu\n",
|
||||
atomic_long_read(&sess->conn_timeout_errors));
|
||||
}
|
||||
spin_unlock_bh(&se_nacl->nacl_sess_lock);
|
||||
|
||||
|
||||
@@ -223,6 +223,8 @@ static void iscsit_set_default_tpg_attribs(struct iscsi_portal_group *tpg)
|
||||
a->cache_dynamic_acls = TA_CACHE_DYNAMIC_ACLS;
|
||||
a->demo_mode_write_protect = TA_DEMO_MODE_WRITE_PROTECT;
|
||||
a->prod_mode_write_protect = TA_PROD_MODE_WRITE_PROTECT;
|
||||
a->demo_mode_discovery = TA_DEMO_MODE_DISCOVERY;
|
||||
a->default_erl = TA_DEFAULT_ERL;
|
||||
}
|
||||
|
||||
int iscsit_tpg_add_portal_group(struct iscsi_tiqn *tiqn, struct iscsi_portal_group *tpg)
|
||||
@@ -237,7 +239,7 @@ int iscsit_tpg_add_portal_group(struct iscsi_tiqn *tiqn, struct iscsi_portal_gro
|
||||
if (iscsi_create_default_params(&tpg->param_list) < 0)
|
||||
goto err_out;
|
||||
|
||||
ISCSI_TPG_ATTRIB(tpg)->tpg = tpg;
|
||||
tpg->tpg_attrib.tpg = tpg;
|
||||
|
||||
spin_lock(&tpg->tpg_state_lock);
|
||||
tpg->tpg_state = TPG_STATE_INACTIVE;
|
||||
@@ -330,7 +332,7 @@ int iscsit_tpg_enable_portal_group(struct iscsi_portal_group *tpg)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ISCSI_TPG_ATTRIB(tpg)->authentication) {
|
||||
if (tpg->tpg_attrib.authentication) {
|
||||
if (!strcmp(param->value, NONE)) {
|
||||
ret = iscsi_update_param_value(param, CHAP);
|
||||
if (ret)
|
||||
@@ -820,3 +822,39 @@ int iscsit_ta_prod_mode_write_protect(
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iscsit_ta_demo_mode_discovery(
|
||||
struct iscsi_portal_group *tpg,
|
||||
u32 flag)
|
||||
{
|
||||
struct iscsi_tpg_attrib *a = &tpg->tpg_attrib;
|
||||
|
||||
if ((flag != 0) && (flag != 1)) {
|
||||
pr_err("Illegal value %d\n", flag);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
a->demo_mode_discovery = flag;
|
||||
pr_debug("iSCSI_TPG[%hu] - Demo Mode Discovery bit:"
|
||||
" %s\n", tpg->tpgt, (a->demo_mode_discovery) ?
|
||||
"ON" : "OFF");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iscsit_ta_default_erl(
|
||||
struct iscsi_portal_group *tpg,
|
||||
u32 default_erl)
|
||||
{
|
||||
struct iscsi_tpg_attrib *a = &tpg->tpg_attrib;
|
||||
|
||||
if ((default_erl != 0) && (default_erl != 1) && (default_erl != 2)) {
|
||||
pr_err("Illegal value for default_erl: %u\n", default_erl);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
a->default_erl = default_erl;
|
||||
pr_debug("iSCSI_TPG[%hu] - DefaultERL: %u\n", tpg->tpgt, a->default_erl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -37,5 +37,7 @@ extern int iscsit_ta_default_cmdsn_depth(struct iscsi_portal_group *, u32);
|
||||
extern int iscsit_ta_cache_dynamic_acls(struct iscsi_portal_group *, u32);
|
||||
extern int iscsit_ta_demo_mode_write_protect(struct iscsi_portal_group *, u32);
|
||||
extern int iscsit_ta_prod_mode_write_protect(struct iscsi_portal_group *, u32);
|
||||
extern int iscsit_ta_demo_mode_discovery(struct iscsi_portal_group *, u32);
|
||||
extern int iscsit_ta_default_erl(struct iscsi_portal_group *, u32);
|
||||
|
||||
#endif /* ISCSI_TARGET_TPG_H */
|
||||
|
||||
@@ -242,9 +242,9 @@ static inline int iscsit_check_received_cmdsn(struct iscsi_session *sess, u32 cm
|
||||
*/
|
||||
if (iscsi_sna_gt(cmdsn, sess->max_cmd_sn)) {
|
||||
pr_err("Received CmdSN: 0x%08x is greater than"
|
||||
" MaxCmdSN: 0x%08x, protocol error.\n", cmdsn,
|
||||
" MaxCmdSN: 0x%08x, ignoring.\n", cmdsn,
|
||||
sess->max_cmd_sn);
|
||||
ret = CMDSN_ERROR_CANNOT_RECOVER;
|
||||
ret = CMDSN_MAXCMDSN_OVERRUN;
|
||||
|
||||
} else if (cmdsn == sess->exp_cmd_sn) {
|
||||
sess->exp_cmd_sn++;
|
||||
@@ -303,14 +303,16 @@ int iscsit_sequence_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
|
||||
ret = CMDSN_HIGHER_THAN_EXP;
|
||||
break;
|
||||
case CMDSN_LOWER_THAN_EXP:
|
||||
case CMDSN_MAXCMDSN_OVERRUN:
|
||||
default:
|
||||
cmd->i_state = ISTATE_REMOVE;
|
||||
iscsit_add_cmd_to_immediate_queue(cmd, conn, cmd->i_state);
|
||||
ret = cmdsn_ret;
|
||||
break;
|
||||
default:
|
||||
reason = ISCSI_REASON_PROTOCOL_ERROR;
|
||||
reject = true;
|
||||
ret = cmdsn_ret;
|
||||
/*
|
||||
* Existing callers for iscsit_sequence_cmd() will silently
|
||||
* ignore commands with CMDSN_LOWER_THAN_EXP, so force this
|
||||
* return for CMDSN_MAXCMDSN_OVERRUN as well..
|
||||
*/
|
||||
ret = CMDSN_LOWER_THAN_EXP;
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&conn->sess->cmdsn_mutex);
|
||||
@@ -980,7 +982,7 @@ static void iscsit_handle_nopin_response_timeout(unsigned long data)
|
||||
tiqn->sess_err_stats.last_sess_failure_type =
|
||||
ISCSI_SESS_ERR_CXN_TIMEOUT;
|
||||
tiqn->sess_err_stats.cxn_timeout_errors++;
|
||||
conn->sess->conn_timeout_errors++;
|
||||
atomic_long_inc(&conn->sess->conn_timeout_errors);
|
||||
spin_unlock_bh(&tiqn->sess_err_stats.lock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,6 +135,21 @@ static int tcm_loop_change_queue_depth(
|
||||
return sdev->queue_depth;
|
||||
}
|
||||
|
||||
static int tcm_loop_change_queue_type(struct scsi_device *sdev, int tag)
|
||||
{
|
||||
if (sdev->tagged_supported) {
|
||||
scsi_set_tag_type(sdev, tag);
|
||||
|
||||
if (tag)
|
||||
scsi_activate_tcq(sdev, sdev->queue_depth);
|
||||
else
|
||||
scsi_deactivate_tcq(sdev, sdev->queue_depth);
|
||||
} else
|
||||
tag = 0;
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
/*
|
||||
* Locate the SAM Task Attr from struct scsi_cmnd *
|
||||
*/
|
||||
@@ -178,7 +193,10 @@ static void tcm_loop_submission_work(struct work_struct *work)
|
||||
set_host_byte(sc, DID_NO_CONNECT);
|
||||
goto out_done;
|
||||
}
|
||||
|
||||
if (tl_tpg->tl_transport_status == TCM_TRANSPORT_OFFLINE) {
|
||||
set_host_byte(sc, DID_TRANSPORT_DISRUPTED);
|
||||
goto out_done;
|
||||
}
|
||||
tl_nexus = tl_hba->tl_nexus;
|
||||
if (!tl_nexus) {
|
||||
scmd_printk(KERN_ERR, sc, "TCM_Loop I_T Nexus"
|
||||
@@ -233,6 +251,7 @@ static int tcm_loop_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc)
|
||||
}
|
||||
|
||||
tl_cmd->sc = sc;
|
||||
tl_cmd->sc_cmd_tag = sc->tag;
|
||||
INIT_WORK(&tl_cmd->work, tcm_loop_submission_work);
|
||||
queue_work(tcm_loop_workqueue, &tl_cmd->work);
|
||||
return 0;
|
||||
@@ -242,17 +261,81 @@ static int tcm_loop_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc)
|
||||
* Called from SCSI EH process context to issue a LUN_RESET TMR
|
||||
* to struct scsi_device
|
||||
*/
|
||||
static int tcm_loop_device_reset(struct scsi_cmnd *sc)
|
||||
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)
|
||||
{
|
||||
struct se_cmd *se_cmd = NULL;
|
||||
struct se_portal_group *se_tpg;
|
||||
struct se_session *se_sess;
|
||||
struct se_portal_group *se_tpg;
|
||||
struct tcm_loop_cmd *tl_cmd = NULL;
|
||||
struct tcm_loop_tmr *tl_tmr = NULL;
|
||||
int ret = TMR_FUNCTION_FAILED, rc;
|
||||
|
||||
tl_cmd = kmem_cache_zalloc(tcm_loop_cmd_cache, GFP_KERNEL);
|
||||
if (!tl_cmd) {
|
||||
pr_err("Unable to allocate memory for tl_cmd\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
tl_tmr = kzalloc(sizeof(struct tcm_loop_tmr), GFP_KERNEL);
|
||||
if (!tl_tmr) {
|
||||
pr_err("Unable to allocate memory for tl_tmr\n");
|
||||
goto release;
|
||||
}
|
||||
init_waitqueue_head(&tl_tmr->tl_tmr_wait);
|
||||
|
||||
se_cmd = &tl_cmd->tl_se_cmd;
|
||||
se_tpg = &tl_tpg->tl_se_tpg;
|
||||
se_sess = tl_nexus->se_sess;
|
||||
/*
|
||||
* Initialize struct se_cmd descriptor from target_core_mod infrastructure
|
||||
*/
|
||||
transport_init_se_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess, 0,
|
||||
DMA_NONE, MSG_SIMPLE_TAG,
|
||||
&tl_cmd->tl_sense_buf[0]);
|
||||
|
||||
rc = core_tmr_alloc_req(se_cmd, tl_tmr, tmr, GFP_KERNEL);
|
||||
if (rc < 0)
|
||||
goto release;
|
||||
|
||||
if (tmr == TMR_ABORT_TASK)
|
||||
se_cmd->se_tmr_req->ref_task_tag = task;
|
||||
|
||||
/*
|
||||
* Locate the underlying TCM struct se_lun
|
||||
*/
|
||||
if (transport_lookup_tmr_lun(se_cmd, lun) < 0) {
|
||||
ret = TMR_LUN_DOES_NOT_EXIST;
|
||||
goto release;
|
||||
}
|
||||
/*
|
||||
* Queue the TMR to TCM Core and sleep waiting for
|
||||
* tcm_loop_queue_tm_rsp() to wake us up.
|
||||
*/
|
||||
transport_generic_handle_tmr(se_cmd);
|
||||
wait_event(tl_tmr->tl_tmr_wait, atomic_read(&tl_tmr->tmr_complete));
|
||||
/*
|
||||
* The TMR LUN_RESET has completed, check the response status and
|
||||
* then release allocations.
|
||||
*/
|
||||
ret = se_cmd->se_tmr_req->response;
|
||||
release:
|
||||
if (se_cmd)
|
||||
transport_generic_free_cmd(se_cmd, 1);
|
||||
else
|
||||
kmem_cache_free(tcm_loop_cmd_cache, tl_cmd);
|
||||
kfree(tl_tmr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tcm_loop_abort_task(struct scsi_cmnd *sc)
|
||||
{
|
||||
struct tcm_loop_hba *tl_hba;
|
||||
struct tcm_loop_nexus *tl_nexus;
|
||||
struct tcm_loop_tmr *tl_tmr = NULL;
|
||||
struct tcm_loop_tpg *tl_tpg;
|
||||
int ret = FAILED, rc;
|
||||
int ret = FAILED;
|
||||
|
||||
/*
|
||||
* Locate the tcm_loop_hba_t pointer
|
||||
*/
|
||||
@@ -266,61 +349,72 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc)
|
||||
" 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
|
||||
* Locate the tl_tpg pointer from TargetID in sc->device->id
|
||||
*/
|
||||
tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
|
||||
se_tpg = &tl_tpg->tl_se_tpg;
|
||||
ret = tcm_loop_issue_tmr(tl_tpg, tl_nexus, sc->device->lun,
|
||||
sc->tag, TMR_ABORT_TASK);
|
||||
return (ret == TMR_FUNCTION_COMPLETE) ? SUCCESS : FAILED;
|
||||
}
|
||||
|
||||
tl_cmd = kmem_cache_zalloc(tcm_loop_cmd_cache, GFP_KERNEL);
|
||||
if (!tl_cmd) {
|
||||
pr_err("Unable to allocate memory for tl_cmd\n");
|
||||
/*
|
||||
* Called from SCSI EH process context to issue a LUN_RESET TMR
|
||||
* to struct scsi_device
|
||||
*/
|
||||
static int tcm_loop_device_reset(struct scsi_cmnd *sc)
|
||||
{
|
||||
struct tcm_loop_hba *tl_hba;
|
||||
struct tcm_loop_nexus *tl_nexus;
|
||||
struct tcm_loop_tpg *tl_tpg;
|
||||
int ret = FAILED;
|
||||
|
||||
/*
|
||||
* Locate the tcm_loop_hba_t pointer
|
||||
*/
|
||||
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];
|
||||
ret = tcm_loop_issue_tmr(tl_tpg, tl_nexus, sc->device->lun,
|
||||
0, TMR_LUN_RESET);
|
||||
return (ret == TMR_FUNCTION_COMPLETE) ? SUCCESS : FAILED;
|
||||
}
|
||||
|
||||
tl_tmr = kzalloc(sizeof(struct tcm_loop_tmr), GFP_KERNEL);
|
||||
if (!tl_tmr) {
|
||||
pr_err("Unable to allocate memory for tl_tmr\n");
|
||||
goto release;
|
||||
static int tcm_loop_target_reset(struct scsi_cmnd *sc)
|
||||
{
|
||||
struct tcm_loop_hba *tl_hba;
|
||||
struct tcm_loop_tpg *tl_tpg;
|
||||
|
||||
/*
|
||||
* Locate the tcm_loop_hba_t pointer
|
||||
*/
|
||||
tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
|
||||
if (!tl_hba) {
|
||||
pr_err("Unable to perform device reset without"
|
||||
" active I_T Nexus\n");
|
||||
return FAILED;
|
||||
}
|
||||
init_waitqueue_head(&tl_tmr->tl_tmr_wait);
|
||||
|
||||
se_cmd = &tl_cmd->tl_se_cmd;
|
||||
/*
|
||||
* Initialize struct se_cmd descriptor from target_core_mod infrastructure
|
||||
* Locate the tl_tpg pointer from TargetID in sc->device->id
|
||||
*/
|
||||
transport_init_se_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess, 0,
|
||||
DMA_NONE, MSG_SIMPLE_TAG,
|
||||
&tl_cmd->tl_sense_buf[0]);
|
||||
|
||||
rc = core_tmr_alloc_req(se_cmd, tl_tmr, TMR_LUN_RESET, GFP_KERNEL);
|
||||
if (rc < 0)
|
||||
goto release;
|
||||
/*
|
||||
* Locate the underlying TCM struct se_lun from sc->device->lun
|
||||
*/
|
||||
if (transport_lookup_tmr_lun(se_cmd, sc->device->lun) < 0)
|
||||
goto release;
|
||||
/*
|
||||
* Queue the TMR to TCM Core and sleep waiting for tcm_loop_queue_tm_rsp()
|
||||
* to wake us up.
|
||||
*/
|
||||
transport_generic_handle_tmr(se_cmd);
|
||||
wait_event(tl_tmr->tl_tmr_wait, atomic_read(&tl_tmr->tmr_complete));
|
||||
/*
|
||||
* The TMR LUN_RESET has completed, check the response status and
|
||||
* then release allocations.
|
||||
*/
|
||||
ret = (se_cmd->se_tmr_req->response == TMR_FUNCTION_COMPLETE) ?
|
||||
SUCCESS : FAILED;
|
||||
release:
|
||||
if (se_cmd)
|
||||
transport_generic_free_cmd(se_cmd, 1);
|
||||
else
|
||||
kmem_cache_free(tcm_loop_cmd_cache, tl_cmd);
|
||||
kfree(tl_tmr);
|
||||
return ret;
|
||||
tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
|
||||
if (tl_tpg) {
|
||||
tl_tpg->tl_transport_status = TCM_TRANSPORT_ONLINE;
|
||||
return SUCCESS;
|
||||
}
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
static int tcm_loop_slave_alloc(struct scsi_device *sd)
|
||||
@@ -331,6 +425,15 @@ static int tcm_loop_slave_alloc(struct scsi_device *sd)
|
||||
|
||||
static int tcm_loop_slave_configure(struct scsi_device *sd)
|
||||
{
|
||||
if (sd->tagged_supported) {
|
||||
scsi_activate_tcq(sd, sd->queue_depth);
|
||||
scsi_adjust_queue_depth(sd, MSG_SIMPLE_TAG,
|
||||
sd->host->cmd_per_lun);
|
||||
} else {
|
||||
scsi_adjust_queue_depth(sd, 0,
|
||||
sd->host->cmd_per_lun);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -340,7 +443,10 @@ static struct scsi_host_template tcm_loop_driver_template = {
|
||||
.name = "TCM_Loopback",
|
||||
.queuecommand = tcm_loop_queuecommand,
|
||||
.change_queue_depth = tcm_loop_change_queue_depth,
|
||||
.change_queue_type = tcm_loop_change_queue_type,
|
||||
.eh_abort_handler = tcm_loop_abort_task,
|
||||
.eh_device_reset_handler = tcm_loop_device_reset,
|
||||
.eh_target_reset_handler = tcm_loop_target_reset,
|
||||
.can_queue = 1024,
|
||||
.this_id = -1,
|
||||
.sg_tablesize = 256,
|
||||
@@ -699,7 +805,10 @@ static void tcm_loop_set_default_node_attributes(struct se_node_acl *se_acl)
|
||||
|
||||
static u32 tcm_loop_get_task_tag(struct se_cmd *se_cmd)
|
||||
{
|
||||
return 1;
|
||||
struct tcm_loop_cmd *tl_cmd = container_of(se_cmd,
|
||||
struct tcm_loop_cmd, tl_se_cmd);
|
||||
|
||||
return tl_cmd->sc_cmd_tag;
|
||||
}
|
||||
|
||||
static int tcm_loop_get_cmd_state(struct se_cmd *se_cmd)
|
||||
@@ -932,7 +1041,10 @@ static int tcm_loop_drop_nexus(
|
||||
struct tcm_loop_nexus *tl_nexus;
|
||||
struct tcm_loop_hba *tl_hba = tpg->tl_hba;
|
||||
|
||||
tl_nexus = tpg->tl_hba->tl_nexus;
|
||||
if (!tl_hba)
|
||||
return -ENODEV;
|
||||
|
||||
tl_nexus = tl_hba->tl_nexus;
|
||||
if (!tl_nexus)
|
||||
return -ENODEV;
|
||||
|
||||
@@ -1061,8 +1173,56 @@ check_newline:
|
||||
|
||||
TF_TPG_BASE_ATTR(tcm_loop, nexus, S_IRUGO | S_IWUSR);
|
||||
|
||||
static ssize_t tcm_loop_tpg_show_transport_status(
|
||||
struct se_portal_group *se_tpg,
|
||||
char *page)
|
||||
{
|
||||
struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
|
||||
struct tcm_loop_tpg, tl_se_tpg);
|
||||
const char *status = NULL;
|
||||
ssize_t ret = -EINVAL;
|
||||
|
||||
switch (tl_tpg->tl_transport_status) {
|
||||
case TCM_TRANSPORT_ONLINE:
|
||||
status = "online";
|
||||
break;
|
||||
case TCM_TRANSPORT_OFFLINE:
|
||||
status = "offline";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (status)
|
||||
ret = snprintf(page, PAGE_SIZE, "%s\n", status);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t tcm_loop_tpg_store_transport_status(
|
||||
struct se_portal_group *se_tpg,
|
||||
const char *page,
|
||||
size_t count)
|
||||
{
|
||||
struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
|
||||
struct tcm_loop_tpg, tl_se_tpg);
|
||||
|
||||
if (!strncmp(page, "online", 6)) {
|
||||
tl_tpg->tl_transport_status = TCM_TRANSPORT_ONLINE;
|
||||
return count;
|
||||
}
|
||||
if (!strncmp(page, "offline", 7)) {
|
||||
tl_tpg->tl_transport_status = TCM_TRANSPORT_OFFLINE;
|
||||
return count;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
TF_TPG_BASE_ATTR(tcm_loop, transport_status, S_IRUGO | S_IWUSR);
|
||||
|
||||
static struct configfs_attribute *tcm_loop_tpg_attrs[] = {
|
||||
&tcm_loop_tpg_nexus.attr,
|
||||
&tcm_loop_tpg_transport_status.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -1334,11 +1494,11 @@ static int tcm_loop_register_configfs(void)
|
||||
/*
|
||||
* Setup default attribute lists for various fabric->tf_cit_tmpl
|
||||
*/
|
||||
TF_CIT_TMPL(fabric)->tfc_wwn_cit.ct_attrs = tcm_loop_wwn_attrs;
|
||||
TF_CIT_TMPL(fabric)->tfc_tpg_base_cit.ct_attrs = tcm_loop_tpg_attrs;
|
||||
TF_CIT_TMPL(fabric)->tfc_tpg_attrib_cit.ct_attrs = NULL;
|
||||
TF_CIT_TMPL(fabric)->tfc_tpg_param_cit.ct_attrs = NULL;
|
||||
TF_CIT_TMPL(fabric)->tfc_tpg_np_base_cit.ct_attrs = NULL;
|
||||
fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = tcm_loop_wwn_attrs;
|
||||
fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = tcm_loop_tpg_attrs;
|
||||
fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = NULL;
|
||||
fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;
|
||||
fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;
|
||||
/*
|
||||
* Once fabric->tf_ops has been setup, now register the fabric for
|
||||
* use within TCM
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
struct tcm_loop_cmd {
|
||||
/* State of Linux/SCSI CDB+Data descriptor */
|
||||
u32 sc_cmd_state;
|
||||
/* Tagged command queueing */
|
||||
u32 sc_cmd_tag;
|
||||
/* Pointer to the CDB+Data descriptor from Linux/SCSI subsystem */
|
||||
struct scsi_cmnd *sc;
|
||||
/* The TCM I/O descriptor that is accessed via container_of() */
|
||||
@@ -40,8 +42,12 @@ struct tcm_loop_nacl {
|
||||
struct se_node_acl se_node_acl;
|
||||
};
|
||||
|
||||
#define TCM_TRANSPORT_ONLINE 0
|
||||
#define TCM_TRANSPORT_OFFLINE 1
|
||||
|
||||
struct tcm_loop_tpg {
|
||||
unsigned short tl_tpgt;
|
||||
unsigned short tl_transport_status;
|
||||
atomic_t tl_tpg_port_count;
|
||||
struct se_portal_group tl_se_tpg;
|
||||
struct tcm_loop_hba *tl_hba;
|
||||
|
||||
@@ -2556,15 +2556,15 @@ static int sbp_register_configfs(void)
|
||||
/*
|
||||
* Setup default attribute lists for various fabric->tf_cit_tmpl
|
||||
*/
|
||||
TF_CIT_TMPL(fabric)->tfc_wwn_cit.ct_attrs = sbp_wwn_attrs;
|
||||
TF_CIT_TMPL(fabric)->tfc_tpg_base_cit.ct_attrs = sbp_tpg_base_attrs;
|
||||
TF_CIT_TMPL(fabric)->tfc_tpg_attrib_cit.ct_attrs = sbp_tpg_attrib_attrs;
|
||||
TF_CIT_TMPL(fabric)->tfc_tpg_param_cit.ct_attrs = NULL;
|
||||
TF_CIT_TMPL(fabric)->tfc_tpg_np_base_cit.ct_attrs = NULL;
|
||||
TF_CIT_TMPL(fabric)->tfc_tpg_nacl_base_cit.ct_attrs = NULL;
|
||||
TF_CIT_TMPL(fabric)->tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;
|
||||
TF_CIT_TMPL(fabric)->tfc_tpg_nacl_auth_cit.ct_attrs = NULL;
|
||||
TF_CIT_TMPL(fabric)->tfc_tpg_nacl_param_cit.ct_attrs = NULL;
|
||||
fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = sbp_wwn_attrs;
|
||||
fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = sbp_tpg_base_attrs;
|
||||
fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = sbp_tpg_attrib_attrs;
|
||||
fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;
|
||||
fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;
|
||||
fabric->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs = NULL;
|
||||
fabric->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;
|
||||
fabric->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = NULL;
|
||||
fabric->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = NULL;
|
||||
|
||||
ret = target_fabric_configfs_register(fabric);
|
||||
if (ret < 0) {
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
static sense_reason_t core_alua_check_transition(int state, int *primary);
|
||||
static int core_alua_set_tg_pt_secondary_state(
|
||||
struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem,
|
||||
struct se_port *port, int explict, int offline);
|
||||
struct se_port *port, int explicit, int offline);
|
||||
|
||||
static u16 alua_lu_gps_counter;
|
||||
static u32 alua_lu_gps_count;
|
||||
@@ -117,12 +117,7 @@ target_emulate_report_target_port_groups(struct se_cmd *cmd)
|
||||
/*
|
||||
* Set supported ASYMMETRIC ACCESS State bits
|
||||
*/
|
||||
buf[off] = 0x80; /* T_SUP */
|
||||
buf[off] |= 0x40; /* O_SUP */
|
||||
buf[off] |= 0x8; /* U_SUP */
|
||||
buf[off] |= 0x4; /* S_SUP */
|
||||
buf[off] |= 0x2; /* AN_SUP */
|
||||
buf[off++] |= 0x1; /* AO_SUP */
|
||||
buf[off++] |= tg_pt_gp->tg_pt_gp_alua_supported_states;
|
||||
/*
|
||||
* TARGET PORT GROUP
|
||||
*/
|
||||
@@ -175,7 +170,7 @@ target_emulate_report_target_port_groups(struct se_cmd *cmd)
|
||||
if (ext_hdr != 0) {
|
||||
buf[4] = 0x10;
|
||||
/*
|
||||
* Set the implict transition time (in seconds) for the application
|
||||
* Set the implicit transition time (in seconds) for the application
|
||||
* client to use as a base for it's transition timeout value.
|
||||
*
|
||||
* Use the current tg_pt_gp_mem -> tg_pt_gp membership from the LUN
|
||||
@@ -188,7 +183,7 @@ target_emulate_report_target_port_groups(struct se_cmd *cmd)
|
||||
spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
|
||||
tg_pt_gp = tg_pt_gp_mem->tg_pt_gp;
|
||||
if (tg_pt_gp)
|
||||
buf[5] = tg_pt_gp->tg_pt_gp_implict_trans_secs;
|
||||
buf[5] = tg_pt_gp->tg_pt_gp_implicit_trans_secs;
|
||||
spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
|
||||
}
|
||||
}
|
||||
@@ -199,7 +194,7 @@ target_emulate_report_target_port_groups(struct se_cmd *cmd)
|
||||
}
|
||||
|
||||
/*
|
||||
* SET_TARGET_PORT_GROUPS for explict ALUA operation.
|
||||
* SET_TARGET_PORT_GROUPS for explicit ALUA operation.
|
||||
*
|
||||
* See spc4r17 section 6.35
|
||||
*/
|
||||
@@ -232,7 +227,7 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
|
||||
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
||||
|
||||
/*
|
||||
* Determine if explict ALUA via SET_TARGET_PORT_GROUPS is allowed
|
||||
* Determine if explicit ALUA via SET_TARGET_PORT_GROUPS is allowed
|
||||
* for the local tg_pt_gp.
|
||||
*/
|
||||
l_tg_pt_gp_mem = l_port->sep_alua_tg_pt_gp_mem;
|
||||
@@ -251,9 +246,9 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
|
||||
}
|
||||
spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock);
|
||||
|
||||
if (!(l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICT_ALUA)) {
|
||||
if (!(l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICIT_ALUA)) {
|
||||
pr_debug("Unable to process SET_TARGET_PORT_GROUPS"
|
||||
" while TPGS_EXPLICT_ALUA is disabled\n");
|
||||
" while TPGS_EXPLICIT_ALUA is disabled\n");
|
||||
rc = TCM_UNSUPPORTED_SCSI_OPCODE;
|
||||
goto out;
|
||||
}
|
||||
@@ -330,7 +325,7 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
|
||||
spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
|
||||
} else {
|
||||
/*
|
||||
* Extact the RELATIVE TARGET PORT IDENTIFIER to identify
|
||||
* Extract the RELATIVE TARGET PORT IDENTIFIER to identify
|
||||
* the Target Port in question for the the incoming
|
||||
* SET_TARGET_PORT_GROUPS op.
|
||||
*/
|
||||
@@ -487,7 +482,7 @@ static inline int core_alua_state_transition(
|
||||
u8 *alua_ascq)
|
||||
{
|
||||
/*
|
||||
* Allowed CDBs for ALUA_ACCESS_STATE_TRANSITIO as defined by
|
||||
* Allowed CDBs for ALUA_ACCESS_STATE_TRANSITION as defined by
|
||||
* spc4r17 section 5.9.2.5
|
||||
*/
|
||||
switch (cdb[0]) {
|
||||
@@ -515,9 +510,9 @@ static inline int core_alua_state_transition(
|
||||
}
|
||||
|
||||
/*
|
||||
* return 1: Is used to signal LUN not accecsable, and check condition/not ready
|
||||
* return 1: Is used to signal LUN not accessible, and check condition/not ready
|
||||
* return 0: Used to signal success
|
||||
* reutrn -1: Used to signal failure, and invalid cdb field
|
||||
* return -1: Used to signal failure, and invalid cdb field
|
||||
*/
|
||||
sense_reason_t
|
||||
target_alua_state_check(struct se_cmd *cmd)
|
||||
@@ -566,12 +561,12 @@ target_alua_state_check(struct se_cmd *cmd)
|
||||
nonop_delay_msecs = tg_pt_gp->tg_pt_gp_nonop_delay_msecs;
|
||||
spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
|
||||
/*
|
||||
* Process ALUA_ACCESS_STATE_ACTIVE_OPTMIZED in a separate conditional
|
||||
* Process ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED in a separate conditional
|
||||
* statement so the compiler knows explicitly to check this case first.
|
||||
* For the Optimized ALUA access state case, we want to process the
|
||||
* incoming fabric cmd ASAP..
|
||||
*/
|
||||
if (out_alua_state == ALUA_ACCESS_STATE_ACTIVE_OPTMIZED)
|
||||
if (out_alua_state == ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED)
|
||||
return 0;
|
||||
|
||||
switch (out_alua_state) {
|
||||
@@ -620,13 +615,13 @@ out:
|
||||
}
|
||||
|
||||
/*
|
||||
* Check implict and explict ALUA state change request.
|
||||
* Check implicit and explicit ALUA state change request.
|
||||
*/
|
||||
static sense_reason_t
|
||||
core_alua_check_transition(int state, int *primary)
|
||||
{
|
||||
switch (state) {
|
||||
case ALUA_ACCESS_STATE_ACTIVE_OPTMIZED:
|
||||
case ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED:
|
||||
case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED:
|
||||
case ALUA_ACCESS_STATE_STANDBY:
|
||||
case ALUA_ACCESS_STATE_UNAVAILABLE:
|
||||
@@ -654,7 +649,7 @@ core_alua_check_transition(int state, int *primary)
|
||||
static char *core_alua_dump_state(int state)
|
||||
{
|
||||
switch (state) {
|
||||
case ALUA_ACCESS_STATE_ACTIVE_OPTMIZED:
|
||||
case ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED:
|
||||
return "Active/Optimized";
|
||||
case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED:
|
||||
return "Active/NonOptimized";
|
||||
@@ -676,10 +671,10 @@ char *core_alua_dump_status(int status)
|
||||
switch (status) {
|
||||
case ALUA_STATUS_NONE:
|
||||
return "None";
|
||||
case ALUA_STATUS_ALTERED_BY_EXPLICT_STPG:
|
||||
return "Altered by Explict STPG";
|
||||
case ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA:
|
||||
return "Altered by Implict ALUA";
|
||||
case ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG:
|
||||
return "Altered by Explicit STPG";
|
||||
case ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA:
|
||||
return "Altered by Implicit ALUA";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
@@ -770,7 +765,7 @@ static int core_alua_do_transition_tg_pt(
|
||||
struct se_node_acl *nacl,
|
||||
unsigned char *md_buf,
|
||||
int new_state,
|
||||
int explict)
|
||||
int explicit)
|
||||
{
|
||||
struct se_dev_entry *se_deve;
|
||||
struct se_lun_acl *lacl;
|
||||
@@ -784,9 +779,9 @@ static int core_alua_do_transition_tg_pt(
|
||||
old_state = atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state);
|
||||
atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state,
|
||||
ALUA_ACCESS_STATE_TRANSITION);
|
||||
tg_pt_gp->tg_pt_gp_alua_access_status = (explict) ?
|
||||
ALUA_STATUS_ALTERED_BY_EXPLICT_STPG :
|
||||
ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA;
|
||||
tg_pt_gp->tg_pt_gp_alua_access_status = (explicit) ?
|
||||
ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG :
|
||||
ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA;
|
||||
/*
|
||||
* Check for the optional ALUA primary state transition delay
|
||||
*/
|
||||
@@ -802,7 +797,7 @@ static int core_alua_do_transition_tg_pt(
|
||||
* change, a device server shall establish a unit attention
|
||||
* condition for the initiator port associated with every I_T
|
||||
* nexus with the additional sense code set to ASYMMETRIC
|
||||
* ACCESS STATE CHAGED.
|
||||
* ACCESS STATE CHANGED.
|
||||
*
|
||||
* After an explicit target port asymmetric access state
|
||||
* change, a device server shall establish a unit attention
|
||||
@@ -821,12 +816,12 @@ static int core_alua_do_transition_tg_pt(
|
||||
lacl = se_deve->se_lun_acl;
|
||||
/*
|
||||
* se_deve->se_lun_acl pointer may be NULL for a
|
||||
* entry created without explict Node+MappedLUN ACLs
|
||||
* entry created without explicit Node+MappedLUN ACLs
|
||||
*/
|
||||
if (!lacl)
|
||||
continue;
|
||||
|
||||
if (explict &&
|
||||
if (explicit &&
|
||||
(nacl != NULL) && (nacl == lacl->se_lun_nacl) &&
|
||||
(l_port != NULL) && (l_port == port))
|
||||
continue;
|
||||
@@ -866,8 +861,8 @@ static int core_alua_do_transition_tg_pt(
|
||||
atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state, new_state);
|
||||
|
||||
pr_debug("Successful %s ALUA transition TG PT Group: %s ID: %hu"
|
||||
" from primary access state %s to %s\n", (explict) ? "explict" :
|
||||
"implict", config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item),
|
||||
" from primary access state %s to %s\n", (explicit) ? "explicit" :
|
||||
"implicit", config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item),
|
||||
tg_pt_gp->tg_pt_gp_id, core_alua_dump_state(old_state),
|
||||
core_alua_dump_state(new_state));
|
||||
|
||||
@@ -880,7 +875,7 @@ int core_alua_do_port_transition(
|
||||
struct se_port *l_port,
|
||||
struct se_node_acl *l_nacl,
|
||||
int new_state,
|
||||
int explict)
|
||||
int explicit)
|
||||
{
|
||||
struct se_device *dev;
|
||||
struct se_port *port;
|
||||
@@ -917,7 +912,7 @@ int core_alua_do_port_transition(
|
||||
* success.
|
||||
*/
|
||||
core_alua_do_transition_tg_pt(l_tg_pt_gp, l_port, l_nacl,
|
||||
md_buf, new_state, explict);
|
||||
md_buf, new_state, explicit);
|
||||
atomic_dec(&lu_gp->lu_gp_ref_cnt);
|
||||
smp_mb__after_atomic_dec();
|
||||
kfree(md_buf);
|
||||
@@ -946,7 +941,7 @@ int core_alua_do_port_transition(
|
||||
continue;
|
||||
/*
|
||||
* If the target behavior port asymmetric access state
|
||||
* is changed for any target port group accessiable via
|
||||
* is changed for any target port group accessible via
|
||||
* a logical unit within a LU group, the target port
|
||||
* behavior group asymmetric access states for the same
|
||||
* target port group accessible via other logical units
|
||||
@@ -970,7 +965,7 @@ int core_alua_do_port_transition(
|
||||
* success.
|
||||
*/
|
||||
core_alua_do_transition_tg_pt(tg_pt_gp, port,
|
||||
nacl, md_buf, new_state, explict);
|
||||
nacl, md_buf, new_state, explicit);
|
||||
|
||||
spin_lock(&dev->t10_alua.tg_pt_gps_lock);
|
||||
atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt);
|
||||
@@ -987,7 +982,7 @@ int core_alua_do_port_transition(
|
||||
pr_debug("Successfully processed LU Group: %s all ALUA TG PT"
|
||||
" Group IDs: %hu %s transition to primary state: %s\n",
|
||||
config_item_name(&lu_gp->lu_gp_group.cg_item),
|
||||
l_tg_pt_gp->tg_pt_gp_id, (explict) ? "explict" : "implict",
|
||||
l_tg_pt_gp->tg_pt_gp_id, (explicit) ? "explicit" : "implicit",
|
||||
core_alua_dump_state(new_state));
|
||||
|
||||
atomic_dec(&lu_gp->lu_gp_ref_cnt);
|
||||
@@ -1034,7 +1029,7 @@ static int core_alua_update_tpg_secondary_metadata(
|
||||
static int core_alua_set_tg_pt_secondary_state(
|
||||
struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem,
|
||||
struct se_port *port,
|
||||
int explict,
|
||||
int explicit,
|
||||
int offline)
|
||||
{
|
||||
struct t10_alua_tg_pt_gp *tg_pt_gp;
|
||||
@@ -1061,13 +1056,13 @@ static int core_alua_set_tg_pt_secondary_state(
|
||||
atomic_set(&port->sep_tg_pt_secondary_offline, 0);
|
||||
|
||||
md_buf_len = tg_pt_gp->tg_pt_gp_md_buf_len;
|
||||
port->sep_tg_pt_secondary_stat = (explict) ?
|
||||
ALUA_STATUS_ALTERED_BY_EXPLICT_STPG :
|
||||
ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA;
|
||||
port->sep_tg_pt_secondary_stat = (explicit) ?
|
||||
ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG :
|
||||
ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA;
|
||||
|
||||
pr_debug("Successful %s ALUA transition TG PT Group: %s ID: %hu"
|
||||
" to secondary access state: %s\n", (explict) ? "explict" :
|
||||
"implict", config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item),
|
||||
" to secondary access state: %s\n", (explicit) ? "explicit" :
|
||||
"implicit", config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item),
|
||||
tg_pt_gp->tg_pt_gp_id, (offline) ? "OFFLINE" : "ONLINE");
|
||||
|
||||
spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
|
||||
@@ -1232,7 +1227,7 @@ void core_alua_free_lu_gp(struct t10_alua_lu_gp *lu_gp)
|
||||
* struct se_device is released via core_alua_free_lu_gp_mem().
|
||||
*
|
||||
* If the passed lu_gp does NOT match the default_lu_gp, assume
|
||||
* we want to re-assocate a given lu_gp_mem with default_lu_gp.
|
||||
* we want to re-associate a given lu_gp_mem with default_lu_gp.
|
||||
*/
|
||||
spin_lock(&lu_gp_mem->lu_gp_mem_lock);
|
||||
if (lu_gp != default_lu_gp)
|
||||
@@ -1354,18 +1349,25 @@ struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(struct se_device *dev,
|
||||
tg_pt_gp->tg_pt_gp_dev = dev;
|
||||
tg_pt_gp->tg_pt_gp_md_buf_len = ALUA_MD_BUF_LEN;
|
||||
atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state,
|
||||
ALUA_ACCESS_STATE_ACTIVE_OPTMIZED);
|
||||
ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED);
|
||||
/*
|
||||
* Enable both explict and implict ALUA support by default
|
||||
* Enable both explicit and implicit ALUA support by default
|
||||
*/
|
||||
tg_pt_gp->tg_pt_gp_alua_access_type =
|
||||
TPGS_EXPLICT_ALUA | TPGS_IMPLICT_ALUA;
|
||||
TPGS_EXPLICIT_ALUA | TPGS_IMPLICIT_ALUA;
|
||||
/*
|
||||
* Set the default Active/NonOptimized Delay in milliseconds
|
||||
*/
|
||||
tg_pt_gp->tg_pt_gp_nonop_delay_msecs = ALUA_DEFAULT_NONOP_DELAY_MSECS;
|
||||
tg_pt_gp->tg_pt_gp_trans_delay_msecs = ALUA_DEFAULT_TRANS_DELAY_MSECS;
|
||||
tg_pt_gp->tg_pt_gp_implict_trans_secs = ALUA_DEFAULT_IMPLICT_TRANS_SECS;
|
||||
tg_pt_gp->tg_pt_gp_implicit_trans_secs = ALUA_DEFAULT_IMPLICIT_TRANS_SECS;
|
||||
|
||||
/*
|
||||
* Enable all supported states
|
||||
*/
|
||||
tg_pt_gp->tg_pt_gp_alua_supported_states =
|
||||
ALUA_T_SUP | ALUA_O_SUP |
|
||||
ALUA_U_SUP | ALUA_S_SUP | ALUA_AN_SUP | ALUA_AO_SUP;
|
||||
|
||||
if (def_group) {
|
||||
spin_lock(&dev->t10_alua.tg_pt_gps_lock);
|
||||
@@ -1465,7 +1467,7 @@ void core_alua_free_tg_pt_gp(
|
||||
* been called from target_core_alua_drop_tg_pt_gp().
|
||||
*
|
||||
* Here we remove *tg_pt_gp from the global list so that
|
||||
* no assications *OR* explict ALUA via SET_TARGET_PORT_GROUPS
|
||||
* no associations *OR* explicit ALUA via SET_TARGET_PORT_GROUPS
|
||||
* can be made while we are releasing struct t10_alua_tg_pt_gp.
|
||||
*/
|
||||
spin_lock(&dev->t10_alua.tg_pt_gps_lock);
|
||||
@@ -1501,7 +1503,7 @@ void core_alua_free_tg_pt_gp(
|
||||
* core_alua_free_tg_pt_gp_mem().
|
||||
*
|
||||
* If the passed tg_pt_gp does NOT match the default_tg_pt_gp,
|
||||
* assume we want to re-assocate a given tg_pt_gp_mem with
|
||||
* assume we want to re-associate a given tg_pt_gp_mem with
|
||||
* default_tg_pt_gp.
|
||||
*/
|
||||
spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
|
||||
@@ -1740,13 +1742,13 @@ ssize_t core_alua_show_access_type(
|
||||
struct t10_alua_tg_pt_gp *tg_pt_gp,
|
||||
char *page)
|
||||
{
|
||||
if ((tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICT_ALUA) &&
|
||||
(tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_IMPLICT_ALUA))
|
||||
return sprintf(page, "Implict and Explict\n");
|
||||
else if (tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_IMPLICT_ALUA)
|
||||
return sprintf(page, "Implict\n");
|
||||
else if (tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICT_ALUA)
|
||||
return sprintf(page, "Explict\n");
|
||||
if ((tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICIT_ALUA) &&
|
||||
(tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_IMPLICIT_ALUA))
|
||||
return sprintf(page, "Implicit and Explicit\n");
|
||||
else if (tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_IMPLICIT_ALUA)
|
||||
return sprintf(page, "Implicit\n");
|
||||
else if (tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICIT_ALUA)
|
||||
return sprintf(page, "Explicit\n");
|
||||
else
|
||||
return sprintf(page, "None\n");
|
||||
}
|
||||
@@ -1771,11 +1773,11 @@ ssize_t core_alua_store_access_type(
|
||||
}
|
||||
if (tmp == 3)
|
||||
tg_pt_gp->tg_pt_gp_alua_access_type =
|
||||
TPGS_IMPLICT_ALUA | TPGS_EXPLICT_ALUA;
|
||||
TPGS_IMPLICIT_ALUA | TPGS_EXPLICIT_ALUA;
|
||||
else if (tmp == 2)
|
||||
tg_pt_gp->tg_pt_gp_alua_access_type = TPGS_EXPLICT_ALUA;
|
||||
tg_pt_gp->tg_pt_gp_alua_access_type = TPGS_EXPLICIT_ALUA;
|
||||
else if (tmp == 1)
|
||||
tg_pt_gp->tg_pt_gp_alua_access_type = TPGS_IMPLICT_ALUA;
|
||||
tg_pt_gp->tg_pt_gp_alua_access_type = TPGS_IMPLICIT_ALUA;
|
||||
else
|
||||
tg_pt_gp->tg_pt_gp_alua_access_type = 0;
|
||||
|
||||
@@ -1844,14 +1846,14 @@ ssize_t core_alua_store_trans_delay_msecs(
|
||||
return count;
|
||||
}
|
||||
|
||||
ssize_t core_alua_show_implict_trans_secs(
|
||||
ssize_t core_alua_show_implicit_trans_secs(
|
||||
struct t10_alua_tg_pt_gp *tg_pt_gp,
|
||||
char *page)
|
||||
{
|
||||
return sprintf(page, "%d\n", tg_pt_gp->tg_pt_gp_implict_trans_secs);
|
||||
return sprintf(page, "%d\n", tg_pt_gp->tg_pt_gp_implicit_trans_secs);
|
||||
}
|
||||
|
||||
ssize_t core_alua_store_implict_trans_secs(
|
||||
ssize_t core_alua_store_implicit_trans_secs(
|
||||
struct t10_alua_tg_pt_gp *tg_pt_gp,
|
||||
const char *page,
|
||||
size_t count)
|
||||
@@ -1861,16 +1863,16 @@ ssize_t core_alua_store_implict_trans_secs(
|
||||
|
||||
ret = kstrtoul(page, 0, &tmp);
|
||||
if (ret < 0) {
|
||||
pr_err("Unable to extract implict_trans_secs\n");
|
||||
pr_err("Unable to extract implicit_trans_secs\n");
|
||||
return ret;
|
||||
}
|
||||
if (tmp > ALUA_MAX_IMPLICT_TRANS_SECS) {
|
||||
pr_err("Passed implict_trans_secs: %lu, exceeds"
|
||||
" ALUA_MAX_IMPLICT_TRANS_SECS: %d\n", tmp,
|
||||
ALUA_MAX_IMPLICT_TRANS_SECS);
|
||||
if (tmp > ALUA_MAX_IMPLICIT_TRANS_SECS) {
|
||||
pr_err("Passed implicit_trans_secs: %lu, exceeds"
|
||||
" ALUA_MAX_IMPLICIT_TRANS_SECS: %d\n", tmp,
|
||||
ALUA_MAX_IMPLICIT_TRANS_SECS);
|
||||
return -EINVAL;
|
||||
}
|
||||
tg_pt_gp->tg_pt_gp_implict_trans_secs = (int)tmp;
|
||||
tg_pt_gp->tg_pt_gp_implicit_trans_secs = (int)tmp;
|
||||
|
||||
return count;
|
||||
}
|
||||
@@ -1970,8 +1972,8 @@ ssize_t core_alua_store_secondary_status(
|
||||
return ret;
|
||||
}
|
||||
if ((tmp != ALUA_STATUS_NONE) &&
|
||||
(tmp != ALUA_STATUS_ALTERED_BY_EXPLICT_STPG) &&
|
||||
(tmp != ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA)) {
|
||||
(tmp != ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG) &&
|
||||
(tmp != ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA)) {
|
||||
pr_err("Illegal value for alua_tg_pt_status: %lu\n",
|
||||
tmp);
|
||||
return -EINVAL;
|
||||
|
||||
@@ -7,29 +7,40 @@
|
||||
* from spc4r17 section 6.4.2 Table 135
|
||||
*/
|
||||
#define TPGS_NO_ALUA 0x00
|
||||
#define TPGS_IMPLICT_ALUA 0x10
|
||||
#define TPGS_EXPLICT_ALUA 0x20
|
||||
#define TPGS_IMPLICIT_ALUA 0x10
|
||||
#define TPGS_EXPLICIT_ALUA 0x20
|
||||
|
||||
/*
|
||||
* ASYMMETRIC ACCESS STATE field
|
||||
*
|
||||
* from spc4r17 section 6.27 Table 245
|
||||
*/
|
||||
#define ALUA_ACCESS_STATE_ACTIVE_OPTMIZED 0x0
|
||||
#define ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED 0x0
|
||||
#define ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED 0x1
|
||||
#define ALUA_ACCESS_STATE_STANDBY 0x2
|
||||
#define ALUA_ACCESS_STATE_UNAVAILABLE 0x3
|
||||
#define ALUA_ACCESS_STATE_OFFLINE 0xe
|
||||
#define ALUA_ACCESS_STATE_TRANSITION 0xf
|
||||
|
||||
/*
|
||||
* from spc4r36j section 6.37 Table 306
|
||||
*/
|
||||
#define ALUA_T_SUP 0x80
|
||||
#define ALUA_O_SUP 0x40
|
||||
#define ALUA_LBD_SUP 0x10
|
||||
#define ALUA_U_SUP 0x08
|
||||
#define ALUA_S_SUP 0x04
|
||||
#define ALUA_AN_SUP 0x02
|
||||
#define ALUA_AO_SUP 0x01
|
||||
|
||||
/*
|
||||
* REPORT_TARGET_PORT_GROUP STATUS CODE
|
||||
*
|
||||
* from spc4r17 section 6.27 Table 246
|
||||
*/
|
||||
#define ALUA_STATUS_NONE 0x00
|
||||
#define ALUA_STATUS_ALTERED_BY_EXPLICT_STPG 0x01
|
||||
#define ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA 0x02
|
||||
#define ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG 0x01
|
||||
#define ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA 0x02
|
||||
|
||||
/*
|
||||
* From spc4r17, Table D.1: ASC and ASCQ Assignement
|
||||
@@ -46,17 +57,17 @@
|
||||
#define ALUA_DEFAULT_NONOP_DELAY_MSECS 100
|
||||
#define ALUA_MAX_NONOP_DELAY_MSECS 10000 /* 10 seconds */
|
||||
/*
|
||||
* Used for implict and explict ALUA transitional delay, that is disabled
|
||||
* Used for implicit and explicit ALUA transitional delay, that is disabled
|
||||
* by default, and is intended to be used for debugging client side ALUA code.
|
||||
*/
|
||||
#define ALUA_DEFAULT_TRANS_DELAY_MSECS 0
|
||||
#define ALUA_MAX_TRANS_DELAY_MSECS 30000 /* 30 seconds */
|
||||
/*
|
||||
* Used for the recommended application client implict transition timeout
|
||||
* Used for the recommended application client implicit transition timeout
|
||||
* in seconds, returned by the REPORT_TARGET_PORT_GROUPS w/ extended header.
|
||||
*/
|
||||
#define ALUA_DEFAULT_IMPLICT_TRANS_SECS 0
|
||||
#define ALUA_MAX_IMPLICT_TRANS_SECS 255
|
||||
#define ALUA_DEFAULT_IMPLICIT_TRANS_SECS 0
|
||||
#define ALUA_MAX_IMPLICIT_TRANS_SECS 255
|
||||
/*
|
||||
* Used by core_alua_update_tpg_primary_metadata() and
|
||||
* core_alua_update_tpg_secondary_metadata()
|
||||
@@ -113,9 +124,9 @@ extern ssize_t core_alua_show_trans_delay_msecs(struct t10_alua_tg_pt_gp *,
|
||||
char *);
|
||||
extern ssize_t core_alua_store_trans_delay_msecs(struct t10_alua_tg_pt_gp *,
|
||||
const char *, size_t);
|
||||
extern ssize_t core_alua_show_implict_trans_secs(struct t10_alua_tg_pt_gp *,
|
||||
extern ssize_t core_alua_show_implicit_trans_secs(struct t10_alua_tg_pt_gp *,
|
||||
char *);
|
||||
extern ssize_t core_alua_store_implict_trans_secs(struct t10_alua_tg_pt_gp *,
|
||||
extern ssize_t core_alua_store_implicit_trans_secs(struct t10_alua_tg_pt_gp *,
|
||||
const char *, size_t);
|
||||
extern ssize_t core_alua_show_preferred_bit(struct t10_alua_tg_pt_gp *,
|
||||
char *);
|
||||
|
||||
@@ -177,16 +177,16 @@ static struct config_group *target_core_register_fabric(
|
||||
* struct target_fabric_configfs *tf will contain a usage reference.
|
||||
*/
|
||||
pr_debug("Target_Core_ConfigFS: REGISTER tfc_wwn_cit -> %p\n",
|
||||
&TF_CIT_TMPL(tf)->tfc_wwn_cit);
|
||||
&tf->tf_cit_tmpl.tfc_wwn_cit);
|
||||
|
||||
tf->tf_group.default_groups = tf->tf_default_groups;
|
||||
tf->tf_group.default_groups[0] = &tf->tf_disc_group;
|
||||
tf->tf_group.default_groups[1] = NULL;
|
||||
|
||||
config_group_init_type_name(&tf->tf_group, name,
|
||||
&TF_CIT_TMPL(tf)->tfc_wwn_cit);
|
||||
&tf->tf_cit_tmpl.tfc_wwn_cit);
|
||||
config_group_init_type_name(&tf->tf_disc_group, "discovery_auth",
|
||||
&TF_CIT_TMPL(tf)->tfc_discovery_cit);
|
||||
&tf->tf_cit_tmpl.tfc_discovery_cit);
|
||||
|
||||
pr_debug("Target_Core_ConfigFS: REGISTER -> Allocated Fabric:"
|
||||
" %s\n", tf->tf_group.cg_item.ci_name);
|
||||
@@ -2036,7 +2036,7 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_state(
|
||||
int new_state, ret;
|
||||
|
||||
if (!tg_pt_gp->tg_pt_gp_valid_id) {
|
||||
pr_err("Unable to do implict ALUA on non valid"
|
||||
pr_err("Unable to do implicit ALUA on non valid"
|
||||
" tg_pt_gp ID: %hu\n", tg_pt_gp->tg_pt_gp_valid_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -2049,9 +2049,9 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_state(
|
||||
}
|
||||
new_state = (int)tmp;
|
||||
|
||||
if (!(tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_IMPLICT_ALUA)) {
|
||||
pr_err("Unable to process implict configfs ALUA"
|
||||
" transition while TPGS_IMPLICT_ALUA is disabled\n");
|
||||
if (!(tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_IMPLICIT_ALUA)) {
|
||||
pr_err("Unable to process implicit configfs ALUA"
|
||||
" transition while TPGS_IMPLICIT_ALUA is disabled\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -2097,8 +2097,8 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_status(
|
||||
new_status = (int)tmp;
|
||||
|
||||
if ((new_status != ALUA_STATUS_NONE) &&
|
||||
(new_status != ALUA_STATUS_ALTERED_BY_EXPLICT_STPG) &&
|
||||
(new_status != ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA)) {
|
||||
(new_status != ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG) &&
|
||||
(new_status != ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA)) {
|
||||
pr_err("Illegal ALUA access status: 0x%02x\n",
|
||||
new_status);
|
||||
return -EINVAL;
|
||||
@@ -2130,6 +2130,90 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_type(
|
||||
|
||||
SE_DEV_ALUA_TG_PT_ATTR(alua_access_type, S_IRUGO | S_IWUSR);
|
||||
|
||||
/*
|
||||
* alua_supported_states
|
||||
*/
|
||||
|
||||
#define SE_DEV_ALUA_SUPPORT_STATE_SHOW(_name, _var, _bit) \
|
||||
static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_support_##_name( \
|
||||
struct t10_alua_tg_pt_gp *t, char *p) \
|
||||
{ \
|
||||
return sprintf(p, "%d\n", !!(t->_var & _bit)); \
|
||||
}
|
||||
|
||||
#define SE_DEV_ALUA_SUPPORT_STATE_STORE(_name, _var, _bit) \
|
||||
static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_support_##_name(\
|
||||
struct t10_alua_tg_pt_gp *t, const char *p, size_t c) \
|
||||
{ \
|
||||
unsigned long tmp; \
|
||||
int ret; \
|
||||
\
|
||||
if (!t->tg_pt_gp_valid_id) { \
|
||||
pr_err("Unable to do set ##_name ALUA state on non" \
|
||||
" valid tg_pt_gp ID: %hu\n", \
|
||||
t->tg_pt_gp_valid_id); \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
\
|
||||
ret = kstrtoul(p, 0, &tmp); \
|
||||
if (ret < 0) { \
|
||||
pr_err("Invalid value '%s', must be '0' or '1'\n", p); \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
if (tmp > 1) { \
|
||||
pr_err("Invalid value '%ld', must be '0' or '1'\n", tmp); \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
if (!tmp) \
|
||||
t->_var |= _bit; \
|
||||
else \
|
||||
t->_var &= ~_bit; \
|
||||
\
|
||||
return c; \
|
||||
}
|
||||
|
||||
SE_DEV_ALUA_SUPPORT_STATE_SHOW(transitioning,
|
||||
tg_pt_gp_alua_supported_states, ALUA_T_SUP);
|
||||
SE_DEV_ALUA_SUPPORT_STATE_STORE(transitioning,
|
||||
tg_pt_gp_alua_supported_states, ALUA_T_SUP);
|
||||
SE_DEV_ALUA_TG_PT_ATTR(alua_support_transitioning, S_IRUGO | S_IWUSR);
|
||||
|
||||
SE_DEV_ALUA_SUPPORT_STATE_SHOW(offline,
|
||||
tg_pt_gp_alua_supported_states, ALUA_O_SUP);
|
||||
SE_DEV_ALUA_SUPPORT_STATE_STORE(offline,
|
||||
tg_pt_gp_alua_supported_states, ALUA_O_SUP);
|
||||
SE_DEV_ALUA_TG_PT_ATTR(alua_support_offline, S_IRUGO | S_IWUSR);
|
||||
|
||||
SE_DEV_ALUA_SUPPORT_STATE_SHOW(lba_dependent,
|
||||
tg_pt_gp_alua_supported_states, ALUA_LBD_SUP);
|
||||
SE_DEV_ALUA_SUPPORT_STATE_STORE(lba_dependent,
|
||||
tg_pt_gp_alua_supported_states, ALUA_LBD_SUP);
|
||||
SE_DEV_ALUA_TG_PT_ATTR(alua_support_lba_dependent, S_IRUGO | S_IWUSR);
|
||||
|
||||
SE_DEV_ALUA_SUPPORT_STATE_SHOW(unavailable,
|
||||
tg_pt_gp_alua_supported_states, ALUA_U_SUP);
|
||||
SE_DEV_ALUA_SUPPORT_STATE_STORE(unavailable,
|
||||
tg_pt_gp_alua_supported_states, ALUA_U_SUP);
|
||||
SE_DEV_ALUA_TG_PT_ATTR(alua_support_unavailable, S_IRUGO | S_IWUSR);
|
||||
|
||||
SE_DEV_ALUA_SUPPORT_STATE_SHOW(standby,
|
||||
tg_pt_gp_alua_supported_states, ALUA_S_SUP);
|
||||
SE_DEV_ALUA_SUPPORT_STATE_STORE(standby,
|
||||
tg_pt_gp_alua_supported_states, ALUA_S_SUP);
|
||||
SE_DEV_ALUA_TG_PT_ATTR(alua_support_standby, S_IRUGO | S_IWUSR);
|
||||
|
||||
SE_DEV_ALUA_SUPPORT_STATE_SHOW(active_optimized,
|
||||
tg_pt_gp_alua_supported_states, ALUA_AO_SUP);
|
||||
SE_DEV_ALUA_SUPPORT_STATE_STORE(active_optimized,
|
||||
tg_pt_gp_alua_supported_states, ALUA_AO_SUP);
|
||||
SE_DEV_ALUA_TG_PT_ATTR(alua_support_active_optimized, S_IRUGO | S_IWUSR);
|
||||
|
||||
SE_DEV_ALUA_SUPPORT_STATE_SHOW(active_nonoptimized,
|
||||
tg_pt_gp_alua_supported_states, ALUA_AN_SUP);
|
||||
SE_DEV_ALUA_SUPPORT_STATE_STORE(active_nonoptimized,
|
||||
tg_pt_gp_alua_supported_states, ALUA_AN_SUP);
|
||||
SE_DEV_ALUA_TG_PT_ATTR(alua_support_active_nonoptimized, S_IRUGO | S_IWUSR);
|
||||
|
||||
/*
|
||||
* alua_write_metadata
|
||||
*/
|
||||
@@ -2210,24 +2294,24 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_trans_delay_msecs(
|
||||
SE_DEV_ALUA_TG_PT_ATTR(trans_delay_msecs, S_IRUGO | S_IWUSR);
|
||||
|
||||
/*
|
||||
* implict_trans_secs
|
||||
* implicit_trans_secs
|
||||
*/
|
||||
static ssize_t target_core_alua_tg_pt_gp_show_attr_implict_trans_secs(
|
||||
static ssize_t target_core_alua_tg_pt_gp_show_attr_implicit_trans_secs(
|
||||
struct t10_alua_tg_pt_gp *tg_pt_gp,
|
||||
char *page)
|
||||
{
|
||||
return core_alua_show_implict_trans_secs(tg_pt_gp, page);
|
||||
return core_alua_show_implicit_trans_secs(tg_pt_gp, page);
|
||||
}
|
||||
|
||||
static ssize_t target_core_alua_tg_pt_gp_store_attr_implict_trans_secs(
|
||||
static ssize_t target_core_alua_tg_pt_gp_store_attr_implicit_trans_secs(
|
||||
struct t10_alua_tg_pt_gp *tg_pt_gp,
|
||||
const char *page,
|
||||
size_t count)
|
||||
{
|
||||
return core_alua_store_implict_trans_secs(tg_pt_gp, page, count);
|
||||
return core_alua_store_implicit_trans_secs(tg_pt_gp, page, count);
|
||||
}
|
||||
|
||||
SE_DEV_ALUA_TG_PT_ATTR(implict_trans_secs, S_IRUGO | S_IWUSR);
|
||||
SE_DEV_ALUA_TG_PT_ATTR(implicit_trans_secs, S_IRUGO | S_IWUSR);
|
||||
|
||||
/*
|
||||
* preferred
|
||||
@@ -2350,10 +2434,17 @@ static struct configfs_attribute *target_core_alua_tg_pt_gp_attrs[] = {
|
||||
&target_core_alua_tg_pt_gp_alua_access_state.attr,
|
||||
&target_core_alua_tg_pt_gp_alua_access_status.attr,
|
||||
&target_core_alua_tg_pt_gp_alua_access_type.attr,
|
||||
&target_core_alua_tg_pt_gp_alua_support_transitioning.attr,
|
||||
&target_core_alua_tg_pt_gp_alua_support_offline.attr,
|
||||
&target_core_alua_tg_pt_gp_alua_support_lba_dependent.attr,
|
||||
&target_core_alua_tg_pt_gp_alua_support_unavailable.attr,
|
||||
&target_core_alua_tg_pt_gp_alua_support_standby.attr,
|
||||
&target_core_alua_tg_pt_gp_alua_support_active_nonoptimized.attr,
|
||||
&target_core_alua_tg_pt_gp_alua_support_active_optimized.attr,
|
||||
&target_core_alua_tg_pt_gp_alua_write_metadata.attr,
|
||||
&target_core_alua_tg_pt_gp_nonop_delay_msecs.attr,
|
||||
&target_core_alua_tg_pt_gp_trans_delay_msecs.attr,
|
||||
&target_core_alua_tg_pt_gp_implict_trans_secs.attr,
|
||||
&target_core_alua_tg_pt_gp_implicit_trans_secs.attr,
|
||||
&target_core_alua_tg_pt_gp_preferred.attr,
|
||||
&target_core_alua_tg_pt_gp_tg_pt_gp_id.attr,
|
||||
&target_core_alua_tg_pt_gp_members.attr,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user