1
0
Fork 0

Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending

Pull SCSI target updates from Nicholas Bellinger:
 "It's been a busy development cycle for target-core in a number of
  different areas.

  The fabric API usage for se_node_acl allocation is now within
  target-core code, dropping the external API callers for all fabric
  drivers tree-wide.

  There is a new conversion to RCU hlists for se_node_acl and
  se_portal_group LUN mappings, that turns fast-past LUN lookup into a
  completely lockless code-path.  It also removes the original
  hard-coded limitation of 256 LUNs per fabric endpoint.

  The configfs attributes for backends can now be shared between core
  and driver code, allowing existing drivers to use common code while
  still allowing flexibility for new backend provided attributes.

  The highlights include:

   - Merge sbc_verify_dif_* into common code (sagi)
   - Remove iscsi-target support for obsolete IFMarker/OFMarker
     (Christophe Vu-Brugier)
   - Add bidi support in target/user backend (ilias + vangelis + agover)
   - Move se_node_acl allocation into target-core code (hch)
   - Add crc_t10dif_update common helper (akinobu + mkp)
   - Handle target-core odd SGL mapping for data transfer memory
     (akinobu)
   - Move transport ID handling into target-core (hch)
   - Move task tag into struct se_cmd + support 64-bit tags (bart)
   - Convert se_node_acl->device_list[] to RCU hlist (nab + hch +
     paulmck)
   - Convert se_portal_group->tpg_lun_list[] to RCU hlist (nab + hch +
     paulmck)
   - Simplify target backend driver registration (hch)
   - Consolidate + simplify target backend attribute implementations
     (hch + nab)
   - Subsume se_port + t10_alua_tg_pt_gp_member into se_lun (hch)
   - Drop lun_sep_lock for se_lun->lun_se_dev RCU usage (hch + nab)
   - Drop unnecessary core_tpg_register TFO parameter (nab)
   - Use 64-bit LUNs tree-wide (hannes)
   - Drop left-over TARGET_MAX_LUNS_PER_TRANSPORT limit (hannes)"

* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: (76 commits)
  target: Bump core version to v5.0
  target: remove target_core_configfs.h
  target: remove unused TARGET_CORE_CONFIG_ROOT define
  target: consolidate version defines
  target: implement WRITE_SAME with UNMAP bit using ->execute_unmap
  target: simplify UNMAP handling
  target: replace se_cmd->execute_rw with a protocol_data field
  target/user: Fix inconsistent kmap_atomic/kunmap_atomic
  target: Send UA when changing LUN inventory
  target: Send UA upon LUN RESET tmr completion
  target: Send UA on ALUA target port group change
  target: Convert se_lun->lun_deve_lock to normal spinlock
  target: use 'se_dev_entry' when allocating UAs
  target: Remove 'ua_nacl' pointer from se_ua structure
  target_core_alua: Correct UA handling when switching states
  xen-scsiback: Fix compile warning for 64-bit LUN
  target: Remove TARGET_MAX_LUNS_PER_TRANSPORT
  target: use 64-bit LUNs
  target: Drop duplicate + unused se_dev_check_wce
  target: Drop unnecessary core_tpg_register TFO parameter
  ...
hifive-unleashed-5.1
Linus Torvalds 2015-07-04 14:13:43 -07:00
commit 5c755fe142
68 changed files with 3152 additions and 6301 deletions

View File

@ -50,15 +50,6 @@ def tcm_mod_build_FC_include(fabric_mod_dir_var, fabric_mod_name):
buf = "#define " + fabric_mod_name.upper() + "_VERSION \"v0.1\"\n" buf = "#define " + fabric_mod_name.upper() + "_VERSION \"v0.1\"\n"
buf += "#define " + fabric_mod_name.upper() + "_NAMELEN 32\n" buf += "#define " + fabric_mod_name.upper() + "_NAMELEN 32\n"
buf += "\n" buf += "\n"
buf += "struct " + fabric_mod_name + "_nacl {\n"
buf += " /* Binary World Wide unique Port Name for FC Initiator Nport */\n"
buf += " u64 nport_wwpn;\n"
buf += " /* ASCII formatted WWPN for FC Initiator Nport */\n"
buf += " char nport_name[" + fabric_mod_name.upper() + "_NAMELEN];\n"
buf += " /* Returned by " + fabric_mod_name + "_make_nodeacl() */\n"
buf += " struct se_node_acl se_node_acl;\n"
buf += "};\n"
buf += "\n"
buf += "struct " + fabric_mod_name + "_tpg {\n" buf += "struct " + fabric_mod_name + "_tpg {\n"
buf += " /* FC lport target portal group tag for TCM */\n" buf += " /* FC lport target portal group tag for TCM */\n"
buf += " u16 lport_tpgt;\n" buf += " u16 lport_tpgt;\n"
@ -69,8 +60,6 @@ def tcm_mod_build_FC_include(fabric_mod_dir_var, fabric_mod_name):
buf += "};\n" buf += "};\n"
buf += "\n" buf += "\n"
buf += "struct " + fabric_mod_name + "_lport {\n" buf += "struct " + fabric_mod_name + "_lport {\n"
buf += " /* SCSI protocol the lport is providing */\n"
buf += " u8 lport_proto_id;\n"
buf += " /* Binary World Wide unique Port Name for FC Target Lport */\n" buf += " /* Binary World Wide unique Port Name for FC Target Lport */\n"
buf += " u64 lport_wwpn;\n" buf += " u64 lport_wwpn;\n"
buf += " /* ASCII formatted WWPN for FC Target Lport */\n" buf += " /* ASCII formatted WWPN for FC Target Lport */\n"
@ -105,14 +94,6 @@ def tcm_mod_build_SAS_include(fabric_mod_dir_var, fabric_mod_name):
buf = "#define " + fabric_mod_name.upper() + "_VERSION \"v0.1\"\n" buf = "#define " + fabric_mod_name.upper() + "_VERSION \"v0.1\"\n"
buf += "#define " + fabric_mod_name.upper() + "_NAMELEN 32\n" buf += "#define " + fabric_mod_name.upper() + "_NAMELEN 32\n"
buf += "\n" buf += "\n"
buf += "struct " + fabric_mod_name + "_nacl {\n"
buf += " /* Binary World Wide unique Port Name for SAS Initiator port */\n"
buf += " u64 iport_wwpn;\n"
buf += " /* ASCII formatted WWPN for Sas Initiator port */\n"
buf += " char iport_name[" + fabric_mod_name.upper() + "_NAMELEN];\n"
buf += " /* Returned by " + fabric_mod_name + "_make_nodeacl() */\n"
buf += " struct se_node_acl se_node_acl;\n"
buf += "};\n\n"
buf += "struct " + fabric_mod_name + "_tpg {\n" buf += "struct " + fabric_mod_name + "_tpg {\n"
buf += " /* SAS port target portal group tag for TCM */\n" buf += " /* SAS port target portal group tag for TCM */\n"
buf += " u16 tport_tpgt;\n" buf += " u16 tport_tpgt;\n"
@ -122,8 +103,6 @@ def tcm_mod_build_SAS_include(fabric_mod_dir_var, fabric_mod_name):
buf += " struct se_portal_group se_tpg;\n" buf += " struct se_portal_group se_tpg;\n"
buf += "};\n\n" buf += "};\n\n"
buf += "struct " + fabric_mod_name + "_tport {\n" buf += "struct " + fabric_mod_name + "_tport {\n"
buf += " /* SCSI protocol the tport is providing */\n"
buf += " u8 tport_proto_id;\n"
buf += " /* Binary World Wide unique Port Name for SAS Target port */\n" buf += " /* Binary World Wide unique Port Name for SAS Target port */\n"
buf += " u64 tport_wwpn;\n" buf += " u64 tport_wwpn;\n"
buf += " /* ASCII formatted WWPN for SAS Target port */\n" buf += " /* ASCII formatted WWPN for SAS Target port */\n"
@ -158,12 +137,6 @@ def tcm_mod_build_iSCSI_include(fabric_mod_dir_var, fabric_mod_name):
buf = "#define " + fabric_mod_name.upper() + "_VERSION \"v0.1\"\n" buf = "#define " + fabric_mod_name.upper() + "_VERSION \"v0.1\"\n"
buf += "#define " + fabric_mod_name.upper() + "_NAMELEN 32\n" buf += "#define " + fabric_mod_name.upper() + "_NAMELEN 32\n"
buf += "\n" buf += "\n"
buf += "struct " + fabric_mod_name + "_nacl {\n"
buf += " /* ASCII formatted InitiatorName */\n"
buf += " char iport_name[" + fabric_mod_name.upper() + "_NAMELEN];\n"
buf += " /* Returned by " + fabric_mod_name + "_make_nodeacl() */\n"
buf += " struct se_node_acl se_node_acl;\n"
buf += "};\n\n"
buf += "struct " + fabric_mod_name + "_tpg {\n" buf += "struct " + fabric_mod_name + "_tpg {\n"
buf += " /* iSCSI target portal group tag for TCM */\n" buf += " /* iSCSI target portal group tag for TCM */\n"
buf += " u16 tport_tpgt;\n" buf += " u16 tport_tpgt;\n"
@ -173,8 +146,6 @@ def tcm_mod_build_iSCSI_include(fabric_mod_dir_var, fabric_mod_name):
buf += " struct se_portal_group se_tpg;\n" buf += " struct se_portal_group se_tpg;\n"
buf += "};\n\n" buf += "};\n\n"
buf += "struct " + fabric_mod_name + "_tport {\n" buf += "struct " + fabric_mod_name + "_tport {\n"
buf += " /* SCSI protocol the tport is providing */\n"
buf += " u8 tport_proto_id;\n"
buf += " /* ASCII formatted TargetName for IQN */\n" buf += " /* ASCII formatted TargetName for IQN */\n"
buf += " char tport_name[" + fabric_mod_name.upper() + "_NAMELEN];\n" buf += " char tport_name[" + fabric_mod_name.upper() + "_NAMELEN];\n"
buf += " /* Returned by " + fabric_mod_name + "_make_tport() */\n" buf += " /* Returned by " + fabric_mod_name + "_make_tport() */\n"
@ -232,61 +203,12 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
buf += "#include <target/target_core_base.h>\n" buf += "#include <target/target_core_base.h>\n"
buf += "#include <target/target_core_fabric.h>\n" buf += "#include <target/target_core_fabric.h>\n"
buf += "#include <target/target_core_fabric_configfs.h>\n" buf += "#include <target/target_core_fabric_configfs.h>\n"
buf += "#include <target/target_core_configfs.h>\n"
buf += "#include <target/configfs_macros.h>\n\n" buf += "#include <target/configfs_macros.h>\n\n"
buf += "#include \"" + fabric_mod_name + "_base.h\"\n" buf += "#include \"" + fabric_mod_name + "_base.h\"\n"
buf += "#include \"" + fabric_mod_name + "_fabric.h\"\n\n" buf += "#include \"" + fabric_mod_name + "_fabric.h\"\n\n"
buf += "static const struct target_core_fabric_ops " + fabric_mod_name + "_ops;\n\n" buf += "static const struct target_core_fabric_ops " + fabric_mod_name + "_ops;\n\n"
buf += "static struct se_node_acl *" + fabric_mod_name + "_make_nodeacl(\n"
buf += " struct se_portal_group *se_tpg,\n"
buf += " struct config_group *group,\n"
buf += " const char *name)\n"
buf += "{\n"
buf += " struct se_node_acl *se_nacl, *se_nacl_new;\n"
buf += " struct " + fabric_mod_name + "_nacl *nacl;\n"
if proto_ident == "FC" or proto_ident == "SAS":
buf += " u64 wwpn = 0;\n"
buf += " u32 nexus_depth;\n\n"
buf += " /* " + fabric_mod_name + "_parse_wwn(name, &wwpn, 1) < 0)\n"
buf += " return ERR_PTR(-EINVAL); */\n"
buf += " se_nacl_new = " + fabric_mod_name + "_alloc_fabric_acl(se_tpg);\n"
buf += " if (!se_nacl_new)\n"
buf += " return ERR_PTR(-ENOMEM);\n"
buf += "//#warning FIXME: Hardcoded nexus depth in " + fabric_mod_name + "_make_nodeacl()\n"
buf += " nexus_depth = 1;\n"
buf += " /*\n"
buf += " * se_nacl_new may be released by core_tpg_add_initiator_node_acl()\n"
buf += " * when converting a NodeACL from demo mode -> explict\n"
buf += " */\n"
buf += " se_nacl = core_tpg_add_initiator_node_acl(se_tpg, se_nacl_new,\n"
buf += " name, nexus_depth);\n"
buf += " if (IS_ERR(se_nacl)) {\n"
buf += " " + fabric_mod_name + "_release_fabric_acl(se_tpg, se_nacl_new);\n"
buf += " return se_nacl;\n"
buf += " }\n"
buf += " /*\n"
buf += " * Locate our struct " + fabric_mod_name + "_nacl and set the FC Nport WWPN\n"
buf += " */\n"
buf += " nacl = container_of(se_nacl, struct " + fabric_mod_name + "_nacl, se_node_acl);\n"
if proto_ident == "FC" or proto_ident == "SAS":
buf += " nacl->" + fabric_mod_init_port + "_wwpn = wwpn;\n"
buf += " /* " + fabric_mod_name + "_format_wwn(&nacl->" + fabric_mod_init_port + "_name[0], " + fabric_mod_name.upper() + "_NAMELEN, wwpn); */\n\n"
buf += " return se_nacl;\n"
buf += "}\n\n"
buf += "static void " + fabric_mod_name + "_drop_nodeacl(struct se_node_acl *se_acl)\n"
buf += "{\n"
buf += " struct " + fabric_mod_name + "_nacl *nacl = container_of(se_acl,\n"
buf += " struct " + fabric_mod_name + "_nacl, se_node_acl);\n"
buf += " core_tpg_del_initiator_node_acl(se_acl->se_tpg, se_acl, 1);\n"
buf += " kfree(nacl);\n"
buf += "}\n\n"
buf += "static struct se_portal_group *" + fabric_mod_name + "_make_tpg(\n" buf += "static struct se_portal_group *" + fabric_mod_name + "_make_tpg(\n"
buf += " struct se_wwn *wwn,\n" buf += " struct se_wwn *wwn,\n"
buf += " struct config_group *group,\n" buf += " struct config_group *group,\n"
@ -309,8 +231,7 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
buf += " tpg->" + fabric_mod_port + " = " + fabric_mod_port + ";\n" buf += " tpg->" + fabric_mod_port + " = " + fabric_mod_port + ";\n"
buf += " tpg->" + fabric_mod_port + "_tpgt = tpgt;\n\n" buf += " tpg->" + fabric_mod_port + "_tpgt = tpgt;\n\n"
buf += " ret = core_tpg_register(&" + fabric_mod_name + "_ops, wwn,\n" buf += " ret = core_tpg_register(&" + fabric_mod_name + "_ops, wwn,\n"
buf += " &tpg->se_tpg, tpg,\n" buf += " &tpg->se_tpg, SCSI_PROTOCOL_SAS);\n"
buf += " TRANSPORT_TPG_TYPE_NORMAL);\n"
buf += " if (ret < 0) {\n" buf += " if (ret < 0) {\n"
buf += " kfree(tpg);\n" buf += " kfree(tpg);\n"
buf += " return NULL;\n" buf += " return NULL;\n"
@ -372,21 +293,13 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
buf += "static const struct target_core_fabric_ops " + fabric_mod_name + "_ops = {\n" buf += "static const struct target_core_fabric_ops " + fabric_mod_name + "_ops = {\n"
buf += " .module = THIS_MODULE,\n" buf += " .module = THIS_MODULE,\n"
buf += " .name = " + fabric_mod_name + ",\n" buf += " .name = " + fabric_mod_name + ",\n"
buf += " .get_fabric_proto_ident = " + fabric_mod_name + "_get_fabric_proto_ident,\n"
buf += " .get_fabric_name = " + fabric_mod_name + "_get_fabric_name,\n" buf += " .get_fabric_name = " + fabric_mod_name + "_get_fabric_name,\n"
buf += " .get_fabric_proto_ident = " + fabric_mod_name + "_get_fabric_proto_ident,\n"
buf += " .tpg_get_wwn = " + fabric_mod_name + "_get_fabric_wwn,\n" buf += " .tpg_get_wwn = " + fabric_mod_name + "_get_fabric_wwn,\n"
buf += " .tpg_get_tag = " + fabric_mod_name + "_get_tag,\n" buf += " .tpg_get_tag = " + fabric_mod_name + "_get_tag,\n"
buf += " .tpg_get_default_depth = " + fabric_mod_name + "_get_default_depth,\n"
buf += " .tpg_get_pr_transport_id = " + fabric_mod_name + "_get_pr_transport_id,\n"
buf += " .tpg_get_pr_transport_id_len = " + fabric_mod_name + "_get_pr_transport_id_len,\n"
buf += " .tpg_parse_pr_out_transport_id = " + fabric_mod_name + "_parse_pr_out_transport_id,\n"
buf += " .tpg_check_demo_mode = " + fabric_mod_name + "_check_false,\n" buf += " .tpg_check_demo_mode = " + fabric_mod_name + "_check_false,\n"
buf += " .tpg_check_demo_mode_cache = " + fabric_mod_name + "_check_true,\n" buf += " .tpg_check_demo_mode_cache = " + fabric_mod_name + "_check_true,\n"
buf += " .tpg_check_demo_mode_write_protect = " + fabric_mod_name + "_check_true,\n" buf += " .tpg_check_demo_mode_write_protect = " + fabric_mod_name + "_check_true,\n"
buf += " .tpg_check_prod_mode_write_protect = " + fabric_mod_name + "_check_false,\n" buf += " .tpg_check_prod_mode_write_protect = " + fabric_mod_name + "_check_false,\n"
buf += " .tpg_alloc_fabric_acl = " + fabric_mod_name + "_alloc_fabric_acl,\n"
buf += " .tpg_release_fabric_acl = " + fabric_mod_name + "_release_fabric_acl,\n"
buf += " .tpg_get_inst_index = " + fabric_mod_name + "_tpg_get_inst_index,\n" buf += " .tpg_get_inst_index = " + fabric_mod_name + "_tpg_get_inst_index,\n"
buf += " .release_cmd = " + fabric_mod_name + "_release_cmd,\n" buf += " .release_cmd = " + fabric_mod_name + "_release_cmd,\n"
buf += " .shutdown_session = " + fabric_mod_name + "_shutdown_session,\n" buf += " .shutdown_session = " + fabric_mod_name + "_shutdown_session,\n"
@ -396,7 +309,6 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
buf += " .write_pending = " + fabric_mod_name + "_write_pending,\n" buf += " .write_pending = " + fabric_mod_name + "_write_pending,\n"
buf += " .write_pending_status = " + fabric_mod_name + "_write_pending_status,\n" buf += " .write_pending_status = " + fabric_mod_name + "_write_pending_status,\n"
buf += " .set_default_node_attributes = " + fabric_mod_name + "_set_default_node_attrs,\n" buf += " .set_default_node_attributes = " + fabric_mod_name + "_set_default_node_attrs,\n"
buf += " .get_task_tag = " + fabric_mod_name + "_get_task_tag,\n"
buf += " .get_cmd_state = " + fabric_mod_name + "_get_cmd_state,\n" buf += " .get_cmd_state = " + fabric_mod_name + "_get_cmd_state,\n"
buf += " .queue_data_in = " + fabric_mod_name + "_queue_data_in,\n" buf += " .queue_data_in = " + fabric_mod_name + "_queue_data_in,\n"
buf += " .queue_status = " + fabric_mod_name + "_queue_status,\n" buf += " .queue_status = " + fabric_mod_name + "_queue_status,\n"
@ -409,12 +321,6 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
buf += " .fabric_drop_wwn = " + fabric_mod_name + "_drop_" + fabric_mod_port + ",\n" buf += " .fabric_drop_wwn = " + fabric_mod_name + "_drop_" + fabric_mod_port + ",\n"
buf += " .fabric_make_tpg = " + fabric_mod_name + "_make_tpg,\n" buf += " .fabric_make_tpg = " + fabric_mod_name + "_make_tpg,\n"
buf += " .fabric_drop_tpg = " + fabric_mod_name + "_drop_tpg,\n" buf += " .fabric_drop_tpg = " + fabric_mod_name + "_drop_tpg,\n"
buf += " .fabric_post_link = NULL,\n"
buf += " .fabric_pre_unlink = NULL,\n"
buf += " .fabric_make_np = NULL,\n"
buf += " .fabric_drop_np = NULL,\n"
buf += " .fabric_make_nodeacl = " + fabric_mod_name + "_make_nodeacl,\n"
buf += " .fabric_drop_nodeacl = " + fabric_mod_name + "_drop_nodeacl,\n"
buf += "\n" buf += "\n"
buf += " .tfc_wwn_attrs = " + fabric_mod_name + "_wwn_attrs;\n" buf += " .tfc_wwn_attrs = " + fabric_mod_name + "_wwn_attrs;\n"
buf += "};\n\n" buf += "};\n\n"
@ -507,7 +413,6 @@ def tcm_mod_dump_fabric_ops(proto_ident, fabric_mod_dir_var, fabric_mod_name):
buf += "#include <scsi/scsi_proto.h>\n" buf += "#include <scsi/scsi_proto.h>\n"
buf += "#include <target/target_core_base.h>\n" buf += "#include <target/target_core_base.h>\n"
buf += "#include <target/target_core_fabric.h>\n" buf += "#include <target/target_core_fabric.h>\n"
buf += "#include <target/target_core_configfs.h>\n\n"
buf += "#include \"" + fabric_mod_name + "_base.h\"\n" buf += "#include \"" + fabric_mod_name + "_base.h\"\n"
buf += "#include \"" + fabric_mod_name + "_fabric.h\"\n\n" buf += "#include \"" + fabric_mod_name + "_fabric.h\"\n\n"
@ -539,35 +444,6 @@ def tcm_mod_dump_fabric_ops(proto_ident, fabric_mod_dir_var, fabric_mod_name):
bufi += "char *" + fabric_mod_name + "_get_fabric_name(void);\n" bufi += "char *" + fabric_mod_name + "_get_fabric_name(void);\n"
continue continue
if re.search('get_fabric_proto_ident', fo):
buf += "u8 " + fabric_mod_name + "_get_fabric_proto_ident(struct se_portal_group *se_tpg)\n"
buf += "{\n"
buf += " struct " + fabric_mod_name + "_tpg *tpg = container_of(se_tpg,\n"
buf += " struct " + fabric_mod_name + "_tpg, se_tpg);\n"
buf += " struct " + fabric_mod_name + "_" + fabric_mod_port + " *" + fabric_mod_port + " = tpg->" + fabric_mod_port + ";\n"
buf += " u8 proto_id;\n\n"
buf += " switch (" + fabric_mod_port + "->" + fabric_mod_port + "_proto_id) {\n"
if proto_ident == "FC":
buf += " case SCSI_PROTOCOL_FCP:\n"
buf += " default:\n"
buf += " proto_id = fc_get_fabric_proto_ident(se_tpg);\n"
buf += " break;\n"
elif proto_ident == "SAS":
buf += " case SCSI_PROTOCOL_SAS:\n"
buf += " default:\n"
buf += " proto_id = sas_get_fabric_proto_ident(se_tpg);\n"
buf += " break;\n"
elif proto_ident == "iSCSI":
buf += " case SCSI_PROTOCOL_ISCSI:\n"
buf += " default:\n"
buf += " proto_id = iscsi_get_fabric_proto_ident(se_tpg);\n"
buf += " break;\n"
buf += " }\n\n"
buf += " return proto_id;\n"
buf += "}\n\n"
bufi += "u8 " + fabric_mod_name + "_get_fabric_proto_ident(struct se_portal_group *);\n"
if re.search('get_wwn', fo): if re.search('get_wwn', fo):
buf += "char *" + fabric_mod_name + "_get_fabric_wwn(struct se_portal_group *se_tpg)\n" buf += "char *" + fabric_mod_name + "_get_fabric_wwn(struct se_portal_group *se_tpg)\n"
buf += "{\n" buf += "{\n"
@ -587,150 +463,6 @@ def tcm_mod_dump_fabric_ops(proto_ident, fabric_mod_dir_var, fabric_mod_name):
buf += "}\n\n" buf += "}\n\n"
bufi += "u16 " + fabric_mod_name + "_get_tag(struct se_portal_group *);\n" bufi += "u16 " + fabric_mod_name + "_get_tag(struct se_portal_group *);\n"
if re.search('get_default_depth', fo):
buf += "u32 " + fabric_mod_name + "_get_default_depth(struct se_portal_group *se_tpg)\n"
buf += "{\n"
buf += " return 1;\n"
buf += "}\n\n"
bufi += "u32 " + fabric_mod_name + "_get_default_depth(struct se_portal_group *);\n"
if re.search('get_pr_transport_id\)\(', fo):
buf += "u32 " + fabric_mod_name + "_get_pr_transport_id(\n"
buf += " struct se_portal_group *se_tpg,\n"
buf += " struct se_node_acl *se_nacl,\n"
buf += " struct t10_pr_registration *pr_reg,\n"
buf += " int *format_code,\n"
buf += " unsigned char *buf)\n"
buf += "{\n"
buf += " struct " + fabric_mod_name + "_tpg *tpg = container_of(se_tpg,\n"
buf += " struct " + fabric_mod_name + "_tpg, se_tpg);\n"
buf += " struct " + fabric_mod_name + "_" + fabric_mod_port + " *" + fabric_mod_port + " = tpg->" + fabric_mod_port + ";\n"
buf += " int ret = 0;\n\n"
buf += " switch (" + fabric_mod_port + "->" + fabric_mod_port + "_proto_id) {\n"
if proto_ident == "FC":
buf += " case SCSI_PROTOCOL_FCP:\n"
buf += " default:\n"
buf += " ret = fc_get_pr_transport_id(se_tpg, se_nacl, pr_reg,\n"
buf += " format_code, buf);\n"
buf += " break;\n"
elif proto_ident == "SAS":
buf += " case SCSI_PROTOCOL_SAS:\n"
buf += " default:\n"
buf += " ret = sas_get_pr_transport_id(se_tpg, se_nacl, pr_reg,\n"
buf += " format_code, buf);\n"
buf += " break;\n"
elif proto_ident == "iSCSI":
buf += " case SCSI_PROTOCOL_ISCSI:\n"
buf += " default:\n"
buf += " ret = iscsi_get_pr_transport_id(se_tpg, se_nacl, pr_reg,\n"
buf += " format_code, buf);\n"
buf += " break;\n"
buf += " }\n\n"
buf += " return ret;\n"
buf += "}\n\n"
bufi += "u32 " + fabric_mod_name + "_get_pr_transport_id(struct se_portal_group *,\n"
bufi += " struct se_node_acl *, struct t10_pr_registration *,\n"
bufi += " int *, unsigned char *);\n"
if re.search('get_pr_transport_id_len\)\(', fo):
buf += "u32 " + fabric_mod_name + "_get_pr_transport_id_len(\n"
buf += " struct se_portal_group *se_tpg,\n"
buf += " struct se_node_acl *se_nacl,\n"
buf += " struct t10_pr_registration *pr_reg,\n"
buf += " int *format_code)\n"
buf += "{\n"
buf += " struct " + fabric_mod_name + "_tpg *tpg = container_of(se_tpg,\n"
buf += " struct " + fabric_mod_name + "_tpg, se_tpg);\n"
buf += " struct " + fabric_mod_name + "_" + fabric_mod_port + " *" + fabric_mod_port + " = tpg->" + fabric_mod_port + ";\n"
buf += " int ret = 0;\n\n"
buf += " switch (" + fabric_mod_port + "->" + fabric_mod_port + "_proto_id) {\n"
if proto_ident == "FC":
buf += " case SCSI_PROTOCOL_FCP:\n"
buf += " default:\n"
buf += " ret = fc_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,\n"
buf += " format_code);\n"
buf += " break;\n"
elif proto_ident == "SAS":
buf += " case SCSI_PROTOCOL_SAS:\n"
buf += " default:\n"
buf += " ret = sas_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,\n"
buf += " format_code);\n"
buf += " break;\n"
elif proto_ident == "iSCSI":
buf += " case SCSI_PROTOCOL_ISCSI:\n"
buf += " default:\n"
buf += " ret = iscsi_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,\n"
buf += " format_code);\n"
buf += " break;\n"
buf += " }\n\n"
buf += " return ret;\n"
buf += "}\n\n"
bufi += "u32 " + fabric_mod_name + "_get_pr_transport_id_len(struct se_portal_group *,\n"
bufi += " struct se_node_acl *, struct t10_pr_registration *,\n"
bufi += " int *);\n"
if re.search('parse_pr_out_transport_id\)\(', fo):
buf += "char *" + fabric_mod_name + "_parse_pr_out_transport_id(\n"
buf += " struct se_portal_group *se_tpg,\n"
buf += " const char *buf,\n"
buf += " u32 *out_tid_len,\n"
buf += " char **port_nexus_ptr)\n"
buf += "{\n"
buf += " struct " + fabric_mod_name + "_tpg *tpg = container_of(se_tpg,\n"
buf += " struct " + fabric_mod_name + "_tpg, se_tpg);\n"
buf += " struct " + fabric_mod_name + "_" + fabric_mod_port + " *" + fabric_mod_port + " = tpg->" + fabric_mod_port + ";\n"
buf += " char *tid = NULL;\n\n"
buf += " switch (" + fabric_mod_port + "->" + fabric_mod_port + "_proto_id) {\n"
if proto_ident == "FC":
buf += " case SCSI_PROTOCOL_FCP:\n"
buf += " default:\n"
buf += " tid = fc_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,\n"
buf += " port_nexus_ptr);\n"
elif proto_ident == "SAS":
buf += " case SCSI_PROTOCOL_SAS:\n"
buf += " default:\n"
buf += " tid = sas_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,\n"
buf += " port_nexus_ptr);\n"
elif proto_ident == "iSCSI":
buf += " case SCSI_PROTOCOL_ISCSI:\n"
buf += " default:\n"
buf += " tid = iscsi_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,\n"
buf += " port_nexus_ptr);\n"
buf += " }\n\n"
buf += " return tid;\n"
buf += "}\n\n"
bufi += "char *" + fabric_mod_name + "_parse_pr_out_transport_id(struct se_portal_group *,\n"
bufi += " const char *, u32 *, char **);\n"
if re.search('alloc_fabric_acl\)\(', fo):
buf += "struct se_node_acl *" + fabric_mod_name + "_alloc_fabric_acl(struct se_portal_group *se_tpg)\n"
buf += "{\n"
buf += " struct " + fabric_mod_name + "_nacl *nacl;\n\n"
buf += " nacl = kzalloc(sizeof(struct " + fabric_mod_name + "_nacl), GFP_KERNEL);\n"
buf += " if (!nacl) {\n"
buf += " printk(KERN_ERR \"Unable to allocate struct " + fabric_mod_name + "_nacl\\n\");\n"
buf += " return NULL;\n"
buf += " }\n\n"
buf += " return &nacl->se_node_acl;\n"
buf += "}\n\n"
bufi += "struct se_node_acl *" + fabric_mod_name + "_alloc_fabric_acl(struct se_portal_group *);\n"
if re.search('release_fabric_acl\)\(', fo):
buf += "void " + fabric_mod_name + "_release_fabric_acl(\n"
buf += " struct se_portal_group *se_tpg,\n"
buf += " struct se_node_acl *se_nacl)\n"
buf += "{\n"
buf += " struct " + fabric_mod_name + "_nacl *nacl = container_of(se_nacl,\n"
buf += " struct " + fabric_mod_name + "_nacl, se_node_acl);\n"
buf += " kfree(nacl);\n"
buf += "}\n\n"
bufi += "void " + fabric_mod_name + "_release_fabric_acl(struct se_portal_group *,\n"
bufi += " struct se_node_acl *);\n"
if re.search('tpg_get_inst_index\)\(', fo): if re.search('tpg_get_inst_index\)\(', fo):
buf += "u32 " + fabric_mod_name + "_tpg_get_inst_index(struct se_portal_group *se_tpg)\n" buf += "u32 " + fabric_mod_name + "_tpg_get_inst_index(struct se_portal_group *se_tpg)\n"
buf += "{\n" buf += "{\n"
@ -787,13 +519,6 @@ def tcm_mod_dump_fabric_ops(proto_ident, fabric_mod_dir_var, fabric_mod_name):
buf += "}\n\n" buf += "}\n\n"
bufi += "void " + fabric_mod_name + "_set_default_node_attrs(struct se_node_acl *);\n" bufi += "void " + fabric_mod_name + "_set_default_node_attrs(struct se_node_acl *);\n"
if re.search('get_task_tag\)\(', fo):
buf += "u32 " + fabric_mod_name + "_get_task_tag(struct se_cmd *se_cmd)\n"
buf += "{\n"
buf += " return 0;\n"
buf += "}\n\n"
bufi += "u32 " + fabric_mod_name + "_get_task_tag(struct se_cmd *);\n"
if re.search('get_cmd_state\)\(', fo): if re.search('get_cmd_state\)\(', fo):
buf += "int " + fabric_mod_name + "_get_cmd_state(struct se_cmd *se_cmd)\n" buf += "int " + fabric_mod_name + "_get_cmd_state(struct se_cmd *se_cmd)\n"
buf += "{\n" buf += "{\n"

View File

@ -13,8 +13,8 @@ fabric skeleton, by simply using:
This script will create a new drivers/target/$TCM_NEW_MOD/, and will do the following This script will create a new drivers/target/$TCM_NEW_MOD/, and will do the following
*) Generate new API callers for drivers/target/target_core_fabric_configs.c logic *) Generate new API callers for drivers/target/target_core_fabric_configs.c logic
->make_nodeacl(), ->drop_nodeacl(), ->make_tpg(), ->drop_tpg() ->make_tpg(), ->drop_tpg(), ->make_wwn(), ->drop_wwn(). These are created
->make_wwn(), ->drop_wwn(). These are created into $TCM_NEW_MOD/$TCM_NEW_MOD_configfs.c into $TCM_NEW_MOD/$TCM_NEW_MOD_configfs.c
*) Generate basic infrastructure for loading/unloading LKMs and TCM/ConfigFS fabric module *) Generate basic infrastructure for loading/unloading LKMs and TCM/ConfigFS fabric module
using a skeleton struct target_core_fabric_ops API template. using a skeleton struct target_core_fabric_ops API template.
*) Based on user defined T10 Proto_Ident for the new fabric module being built, *) Based on user defined T10 Proto_Ident for the new fabric module being built,

View File

@ -152,7 +152,7 @@ overall shared memory region, not the entry. The data in/out buffers
are accessible via tht req.iov[] array. iov_cnt contains the number of are accessible via tht req.iov[] array. iov_cnt contains the number of
entries in iov[] needed to describe either the Data-In or Data-Out entries in iov[] needed to describe either the Data-In or Data-Out
buffers. For bidirectional commands, iov_cnt specifies how many iovec buffers. For bidirectional commands, iov_cnt specifies how many iovec
entries cover the Data-Out area, and iov_bidi_count specifies how many entries cover the Data-Out area, and iov_bidi_cnt specifies how many
iovec entries immediately after that in iov[] cover the Data-In iovec entries immediately after that in iov[] cover the Data-In
area. Just like other fields, iov.iov_base is an offset from the start area. Just like other fields, iov.iov_base is an offset from the start
of the region. of the region.

View File

@ -1356,7 +1356,7 @@ sequence_cmd:
if (!rc && dump_payload == false && unsol_data) if (!rc && dump_payload == false && unsol_data)
iscsit_set_unsoliticed_dataout(cmd); iscsit_set_unsoliticed_dataout(cmd);
else if (dump_payload && imm_data) else if (dump_payload && imm_data)
target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); target_put_sess_cmd(&cmd->se_cmd);
return 0; return 0;
} }
@ -1781,7 +1781,7 @@ isert_put_cmd(struct isert_cmd *isert_cmd, bool comp_err)
cmd->se_cmd.t_state == TRANSPORT_WRITE_PENDING) { cmd->se_cmd.t_state == TRANSPORT_WRITE_PENDING) {
struct se_cmd *se_cmd = &cmd->se_cmd; struct se_cmd *se_cmd = &cmd->se_cmd;
target_put_sess_cmd(se_cmd->se_sess, se_cmd); target_put_sess_cmd(se_cmd);
} }
} }
@ -1954,7 +1954,7 @@ isert_completion_rdma_read(struct iser_tx_desc *tx_desc,
spin_unlock_bh(&cmd->istate_lock); spin_unlock_bh(&cmd->istate_lock);
if (ret) { if (ret) {
target_put_sess_cmd(se_cmd->se_sess, se_cmd); target_put_sess_cmd(se_cmd);
transport_send_check_condition_and_sense(se_cmd, transport_send_check_condition_and_sense(se_cmd,
se_cmd->pi_err, 0); se_cmd->pi_err, 0);
} else { } else {

View File

@ -47,7 +47,6 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_fabric_configfs.h> #include <target/target_core_fabric_configfs.h>
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
#include "ib_srpt.h" #include "ib_srpt.h"
/* Name of this kernel module. */ /* Name of this kernel module. */
@ -94,7 +93,6 @@ MODULE_PARM_DESC(srpt_service_guid,
" instead of using the node_guid of the first HCA."); " instead of using the node_guid of the first HCA.");
static struct ib_client srpt_client; static struct ib_client srpt_client;
static const struct target_core_fabric_ops srpt_template;
static void srpt_release_channel(struct srpt_rdma_ch *ch); static void srpt_release_channel(struct srpt_rdma_ch *ch);
static int srpt_queue_status(struct se_cmd *cmd); static int srpt_queue_status(struct se_cmd *cmd);
@ -1336,12 +1334,12 @@ static int srpt_abort_cmd(struct srpt_send_ioctx *ioctx)
BUG_ON(ch->sess == NULL); BUG_ON(ch->sess == NULL);
target_put_sess_cmd(ch->sess, &ioctx->cmd); target_put_sess_cmd(&ioctx->cmd);
goto out; goto out;
} }
pr_debug("Aborting cmd with state %d and tag %lld\n", state, pr_debug("Aborting cmd with state %d and tag %lld\n", state,
ioctx->tag); ioctx->cmd.tag);
switch (state) { switch (state) {
case SRPT_STATE_NEW: case SRPT_STATE_NEW:
@ -1367,11 +1365,11 @@ static int srpt_abort_cmd(struct srpt_send_ioctx *ioctx)
* not been received in time. * not been received in time.
*/ */
srpt_unmap_sg_to_ib_sge(ioctx->ch, ioctx); srpt_unmap_sg_to_ib_sge(ioctx->ch, ioctx);
target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd); target_put_sess_cmd(&ioctx->cmd);
break; break;
case SRPT_STATE_MGMT_RSP_SENT: case SRPT_STATE_MGMT_RSP_SENT:
srpt_set_cmd_state(ioctx, SRPT_STATE_DONE); srpt_set_cmd_state(ioctx, SRPT_STATE_DONE);
target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd); target_put_sess_cmd(&ioctx->cmd);
break; break;
default: default:
WARN(1, "Unexpected command state (%d)", state); WARN(1, "Unexpected command state (%d)", state);
@ -1389,7 +1387,6 @@ static void srpt_handle_send_err_comp(struct srpt_rdma_ch *ch, u64 wr_id)
{ {
struct srpt_send_ioctx *ioctx; struct srpt_send_ioctx *ioctx;
enum srpt_command_state state; enum srpt_command_state state;
struct se_cmd *cmd;
u32 index; u32 index;
atomic_inc(&ch->sq_wr_avail); atomic_inc(&ch->sq_wr_avail);
@ -1397,7 +1394,6 @@ static void srpt_handle_send_err_comp(struct srpt_rdma_ch *ch, u64 wr_id)
index = idx_from_wr_id(wr_id); index = idx_from_wr_id(wr_id);
ioctx = ch->ioctx_ring[index]; ioctx = ch->ioctx_ring[index];
state = srpt_get_cmd_state(ioctx); state = srpt_get_cmd_state(ioctx);
cmd = &ioctx->cmd;
WARN_ON(state != SRPT_STATE_CMD_RSP_SENT WARN_ON(state != SRPT_STATE_CMD_RSP_SENT
&& state != SRPT_STATE_MGMT_RSP_SENT && state != SRPT_STATE_MGMT_RSP_SENT
@ -1474,10 +1470,8 @@ static void srpt_handle_rdma_err_comp(struct srpt_rdma_ch *ch,
struct srpt_send_ioctx *ioctx, struct srpt_send_ioctx *ioctx,
enum srpt_opcode opcode) enum srpt_opcode opcode)
{ {
struct se_cmd *cmd;
enum srpt_command_state state; enum srpt_command_state state;
cmd = &ioctx->cmd;
state = srpt_get_cmd_state(ioctx); state = srpt_get_cmd_state(ioctx);
switch (opcode) { switch (opcode) {
case SRPT_RDMA_READ_LAST: case SRPT_RDMA_READ_LAST:
@ -1681,7 +1675,7 @@ static int srpt_check_stop_free(struct se_cmd *cmd)
struct srpt_send_ioctx *ioctx = container_of(cmd, struct srpt_send_ioctx *ioctx = container_of(cmd,
struct srpt_send_ioctx, cmd); struct srpt_send_ioctx, cmd);
return target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd); return target_put_sess_cmd(&ioctx->cmd);
} }
/** /**
@ -1703,7 +1697,7 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch,
srp_cmd = recv_ioctx->ioctx.buf; srp_cmd = recv_ioctx->ioctx.buf;
cmd = &send_ioctx->cmd; cmd = &send_ioctx->cmd;
send_ioctx->tag = srp_cmd->tag; cmd->tag = srp_cmd->tag;
switch (srp_cmd->task_attr) { switch (srp_cmd->task_attr) {
case SRP_CMD_SIMPLE_Q: case SRP_CMD_SIMPLE_Q:
@ -1774,7 +1768,7 @@ static int srpt_rx_mgmt_fn_tag(struct srpt_send_ioctx *ioctx, u64 tag)
for (i = 0; i < ch->rq_size; ++i) { for (i = 0; i < ch->rq_size; ++i) {
target = ch->ioctx_ring[i]; target = ch->ioctx_ring[i];
if (target->cmd.se_lun == ioctx->cmd.se_lun && if (target->cmd.se_lun == ioctx->cmd.se_lun &&
target->tag == tag && target->cmd.tag == tag &&
srpt_get_cmd_state(target) != SRPT_STATE_DONE) { srpt_get_cmd_state(target) != SRPT_STATE_DONE) {
ret = 0; ret = 0;
/* now let the target core abort &target->cmd; */ /* now let the target core abort &target->cmd; */
@ -1833,7 +1827,7 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,
srp_tsk->task_tag, srp_tsk->tag, ch->cm_id, ch->sess); srp_tsk->task_tag, srp_tsk->tag, ch->cm_id, ch->sess);
srpt_set_cmd_state(send_ioctx, SRPT_STATE_MGMT); srpt_set_cmd_state(send_ioctx, SRPT_STATE_MGMT);
send_ioctx->tag = srp_tsk->tag; send_ioctx->cmd.tag = srp_tsk->tag;
tcm_tmr = srp_tmr_to_tcm(srp_tsk->tsk_mgmt_func); tcm_tmr = srp_tmr_to_tcm(srp_tsk->tsk_mgmt_func);
if (tcm_tmr < 0) { if (tcm_tmr < 0) {
send_ioctx->cmd.se_tmr_req->response = send_ioctx->cmd.se_tmr_req->response =
@ -2180,12 +2174,9 @@ static void srpt_destroy_ch_ib(struct srpt_rdma_ch *ch)
*/ */
static void __srpt_close_ch(struct srpt_rdma_ch *ch) static void __srpt_close_ch(struct srpt_rdma_ch *ch)
{ {
struct srpt_device *sdev;
enum rdma_ch_state prev_state; enum rdma_ch_state prev_state;
unsigned long flags; unsigned long flags;
sdev = ch->sport->sdev;
spin_lock_irqsave(&ch->spinlock, flags); spin_lock_irqsave(&ch->spinlock, flags);
prev_state = ch->state; prev_state = ch->state;
switch (prev_state) { switch (prev_state) {
@ -2983,7 +2974,7 @@ static int srpt_write_pending(struct se_cmd *se_cmd)
case CH_DRAINING: case CH_DRAINING:
case CH_RELEASING: case CH_RELEASING:
pr_debug("cmd with tag %lld: channel disconnecting\n", pr_debug("cmd with tag %lld: channel disconnecting\n",
ioctx->tag); ioctx->cmd.tag);
srpt_set_cmd_state(ioctx, SRPT_STATE_DATA_IN); srpt_set_cmd_state(ioctx, SRPT_STATE_DATA_IN);
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
@ -3058,27 +3049,27 @@ static void srpt_queue_response(struct se_cmd *cmd)
ret = srpt_xfer_data(ch, ioctx); ret = srpt_xfer_data(ch, ioctx);
if (ret) { if (ret) {
pr_err("xfer_data failed for tag %llu\n", pr_err("xfer_data failed for tag %llu\n",
ioctx->tag); ioctx->cmd.tag);
return; return;
} }
} }
if (state != SRPT_STATE_MGMT) if (state != SRPT_STATE_MGMT)
resp_len = srpt_build_cmd_rsp(ch, ioctx, ioctx->tag, resp_len = srpt_build_cmd_rsp(ch, ioctx, ioctx->cmd.tag,
cmd->scsi_status); cmd->scsi_status);
else { else {
srp_tm_status srp_tm_status
= tcm_to_srp_tsk_mgmt_status(cmd->se_tmr_req->response); = tcm_to_srp_tsk_mgmt_status(cmd->se_tmr_req->response);
resp_len = srpt_build_tskmgmt_rsp(ch, ioctx, srp_tm_status, resp_len = srpt_build_tskmgmt_rsp(ch, ioctx, srp_tm_status,
ioctx->tag); ioctx->cmd.tag);
} }
ret = srpt_post_send(ch, ioctx, resp_len); ret = srpt_post_send(ch, ioctx, resp_len);
if (ret) { if (ret) {
pr_err("sending cmd response failed for tag %llu\n", pr_err("sending cmd response failed for tag %llu\n",
ioctx->tag); ioctx->cmd.tag);
srpt_unmap_sg_to_ib_sge(ch, ioctx); srpt_unmap_sg_to_ib_sge(ch, ioctx);
srpt_set_cmd_state(ioctx, SRPT_STATE_DONE); srpt_set_cmd_state(ioctx, SRPT_STATE_DONE);
target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd); target_put_sess_cmd(&ioctx->cmd);
} }
} }
@ -3398,11 +3389,6 @@ static char *srpt_get_fabric_name(void)
return "srpt"; return "srpt";
} }
static u8 srpt_get_fabric_proto_ident(struct se_portal_group *se_tpg)
{
return SCSI_TRANSPORTID_PROTOCOLID_SRP;
}
static char *srpt_get_fabric_wwn(struct se_portal_group *tpg) static char *srpt_get_fabric_wwn(struct se_portal_group *tpg)
{ {
struct srpt_port *sport = container_of(tpg, struct srpt_port, port_tpg_1); struct srpt_port *sport = container_of(tpg, struct srpt_port, port_tpg_1);
@ -3415,69 +3401,6 @@ static u16 srpt_get_tag(struct se_portal_group *tpg)
return 1; return 1;
} }
static u32 srpt_get_default_depth(struct se_portal_group *se_tpg)
{
return 1;
}
static u32 srpt_get_pr_transport_id(struct se_portal_group *se_tpg,
struct se_node_acl *se_nacl,
struct t10_pr_registration *pr_reg,
int *format_code, unsigned char *buf)
{
struct srpt_node_acl *nacl;
struct spc_rdma_transport_id *tr_id;
nacl = container_of(se_nacl, struct srpt_node_acl, nacl);
tr_id = (void *)buf;
tr_id->protocol_identifier = SCSI_TRANSPORTID_PROTOCOLID_SRP;
memcpy(tr_id->i_port_id, nacl->i_port_id, sizeof(tr_id->i_port_id));
return sizeof(*tr_id);
}
static u32 srpt_get_pr_transport_id_len(struct se_portal_group *se_tpg,
struct se_node_acl *se_nacl,
struct t10_pr_registration *pr_reg,
int *format_code)
{
*format_code = 0;
return sizeof(struct spc_rdma_transport_id);
}
static char *srpt_parse_pr_out_transport_id(struct se_portal_group *se_tpg,
const char *buf, u32 *out_tid_len,
char **port_nexus_ptr)
{
struct spc_rdma_transport_id *tr_id;
*port_nexus_ptr = NULL;
*out_tid_len = sizeof(struct spc_rdma_transport_id);
tr_id = (void *)buf;
return (char *)tr_id->i_port_id;
}
static struct se_node_acl *srpt_alloc_fabric_acl(struct se_portal_group *se_tpg)
{
struct srpt_node_acl *nacl;
nacl = kzalloc(sizeof(struct srpt_node_acl), GFP_KERNEL);
if (!nacl) {
pr_err("Unable to allocate struct srpt_node_acl\n");
return NULL;
}
return &nacl->nacl;
}
static void srpt_release_fabric_acl(struct se_portal_group *se_tpg,
struct se_node_acl *se_nacl)
{
struct srpt_node_acl *nacl;
nacl = container_of(se_nacl, struct srpt_node_acl, nacl);
kfree(nacl);
}
static u32 srpt_tpg_get_inst_index(struct se_portal_group *se_tpg) static u32 srpt_tpg_get_inst_index(struct se_portal_group *se_tpg)
{ {
return 1; return 1;
@ -3551,14 +3474,6 @@ static void srpt_set_default_node_attrs(struct se_node_acl *nacl)
{ {
} }
static u32 srpt_get_task_tag(struct se_cmd *se_cmd)
{
struct srpt_send_ioctx *ioctx;
ioctx = container_of(se_cmd, struct srpt_send_ioctx, cmd);
return ioctx->tag;
}
/* Note: only used from inside debug printk's by the TCM core. */ /* Note: only used from inside debug printk's by the TCM core. */
static int srpt_get_tcm_cmd_state(struct se_cmd *se_cmd) static int srpt_get_tcm_cmd_state(struct se_cmd *se_cmd)
{ {
@ -3601,40 +3516,19 @@ out:
* configfs callback function invoked for * configfs callback function invoked for
* mkdir /sys/kernel/config/target/$driver/$port/$tpg/acls/$i_port_id * mkdir /sys/kernel/config/target/$driver/$port/$tpg/acls/$i_port_id
*/ */
static struct se_node_acl *srpt_make_nodeacl(struct se_portal_group *tpg, static int srpt_init_nodeacl(struct se_node_acl *se_nacl, const char *name)
struct config_group *group,
const char *name)
{ {
struct srpt_port *sport = container_of(tpg, struct srpt_port, port_tpg_1); struct srpt_port *sport =
struct se_node_acl *se_nacl, *se_nacl_new; container_of(se_nacl->se_tpg, struct srpt_port, port_tpg_1);
struct srpt_node_acl *nacl; struct srpt_node_acl *nacl =
int ret = 0; container_of(se_nacl, struct srpt_node_acl, nacl);
u32 nexus_depth = 1;
u8 i_port_id[16]; u8 i_port_id[16];
if (srpt_parse_i_port_id(i_port_id, name) < 0) { if (srpt_parse_i_port_id(i_port_id, name) < 0) {
pr_err("invalid initiator port ID %s\n", name); pr_err("invalid initiator port ID %s\n", name);
ret = -EINVAL; return -EINVAL;
goto err;
} }
se_nacl_new = srpt_alloc_fabric_acl(tpg);
if (!se_nacl_new) {
ret = -ENOMEM;
goto err;
}
/*
* nacl_new may be released by core_tpg_add_initiator_node_acl()
* when converting a node ACL from demo mode to explict
*/
se_nacl = core_tpg_add_initiator_node_acl(tpg, se_nacl_new, name,
nexus_depth);
if (IS_ERR(se_nacl)) {
ret = PTR_ERR(se_nacl);
goto err;
}
/* Locate our struct srpt_node_acl and set sdev and i_port_id. */
nacl = container_of(se_nacl, struct srpt_node_acl, nacl);
memcpy(&nacl->i_port_id[0], &i_port_id[0], 16); memcpy(&nacl->i_port_id[0], &i_port_id[0], 16);
nacl->sport = sport; nacl->sport = sport;
@ -3642,29 +3536,22 @@ static struct se_node_acl *srpt_make_nodeacl(struct se_portal_group *tpg,
list_add_tail(&nacl->list, &sport->port_acl_list); list_add_tail(&nacl->list, &sport->port_acl_list);
spin_unlock_irq(&sport->port_acl_lock); spin_unlock_irq(&sport->port_acl_lock);
return se_nacl; return 0;
err:
return ERR_PTR(ret);
} }
/* /*
* configfs callback function invoked for * configfs callback function invoked for
* rmdir /sys/kernel/config/target/$driver/$port/$tpg/acls/$i_port_id * rmdir /sys/kernel/config/target/$driver/$port/$tpg/acls/$i_port_id
*/ */
static void srpt_drop_nodeacl(struct se_node_acl *se_nacl) static void srpt_cleanup_nodeacl(struct se_node_acl *se_nacl)
{ {
struct srpt_node_acl *nacl; struct srpt_node_acl *nacl =
struct srpt_device *sdev; container_of(se_nacl, struct srpt_node_acl, nacl);
struct srpt_port *sport; struct srpt_port *sport = nacl->sport;
nacl = container_of(se_nacl, struct srpt_node_acl, nacl);
sport = nacl->sport;
sdev = sport->sdev;
spin_lock_irq(&sport->port_acl_lock); spin_lock_irq(&sport->port_acl_lock);
list_del(&nacl->list); list_del(&nacl->list);
spin_unlock_irq(&sport->port_acl_lock); spin_unlock_irq(&sport->port_acl_lock);
core_tpg_del_initiator_node_acl(&sport->port_tpg_1, se_nacl, 1);
srpt_release_fabric_acl(NULL, se_nacl);
} }
static ssize_t srpt_tpg_attrib_show_srp_max_rdma_size( static ssize_t srpt_tpg_attrib_show_srp_max_rdma_size(
@ -3849,8 +3736,7 @@ static struct se_portal_group *srpt_make_tpg(struct se_wwn *wwn,
int res; int res;
/* Initialize sport->port_wwn and sport->port_tpg_1 */ /* Initialize sport->port_wwn and sport->port_tpg_1 */
res = core_tpg_register(&srpt_template, &sport->port_wwn, res = core_tpg_register(&sport->port_wwn, &sport->port_tpg_1, SCSI_PROTOCOL_SRP);
&sport->port_tpg_1, sport, TRANSPORT_TPG_TYPE_NORMAL);
if (res) if (res)
return ERR_PTR(res); return ERR_PTR(res);
@ -3920,20 +3806,14 @@ static struct configfs_attribute *srpt_wwn_attrs[] = {
static const struct target_core_fabric_ops srpt_template = { static const struct target_core_fabric_ops srpt_template = {
.module = THIS_MODULE, .module = THIS_MODULE,
.name = "srpt", .name = "srpt",
.node_acl_size = sizeof(struct srpt_node_acl),
.get_fabric_name = srpt_get_fabric_name, .get_fabric_name = srpt_get_fabric_name,
.get_fabric_proto_ident = srpt_get_fabric_proto_ident,
.tpg_get_wwn = srpt_get_fabric_wwn, .tpg_get_wwn = srpt_get_fabric_wwn,
.tpg_get_tag = srpt_get_tag, .tpg_get_tag = srpt_get_tag,
.tpg_get_default_depth = srpt_get_default_depth,
.tpg_get_pr_transport_id = srpt_get_pr_transport_id,
.tpg_get_pr_transport_id_len = srpt_get_pr_transport_id_len,
.tpg_parse_pr_out_transport_id = srpt_parse_pr_out_transport_id,
.tpg_check_demo_mode = srpt_check_false, .tpg_check_demo_mode = srpt_check_false,
.tpg_check_demo_mode_cache = srpt_check_true, .tpg_check_demo_mode_cache = srpt_check_true,
.tpg_check_demo_mode_write_protect = srpt_check_true, .tpg_check_demo_mode_write_protect = srpt_check_true,
.tpg_check_prod_mode_write_protect = srpt_check_false, .tpg_check_prod_mode_write_protect = srpt_check_false,
.tpg_alloc_fabric_acl = srpt_alloc_fabric_acl,
.tpg_release_fabric_acl = srpt_release_fabric_acl,
.tpg_get_inst_index = srpt_tpg_get_inst_index, .tpg_get_inst_index = srpt_tpg_get_inst_index,
.release_cmd = srpt_release_cmd, .release_cmd = srpt_release_cmd,
.check_stop_free = srpt_check_stop_free, .check_stop_free = srpt_check_stop_free,
@ -3944,7 +3824,6 @@ static const struct target_core_fabric_ops srpt_template = {
.write_pending = srpt_write_pending, .write_pending = srpt_write_pending,
.write_pending_status = srpt_write_pending_status, .write_pending_status = srpt_write_pending_status,
.set_default_node_attributes = srpt_set_default_node_attrs, .set_default_node_attributes = srpt_set_default_node_attrs,
.get_task_tag = srpt_get_task_tag,
.get_cmd_state = srpt_get_tcm_cmd_state, .get_cmd_state = srpt_get_tcm_cmd_state,
.queue_data_in = srpt_queue_data_in, .queue_data_in = srpt_queue_data_in,
.queue_status = srpt_queue_status, .queue_status = srpt_queue_status,
@ -3958,12 +3837,8 @@ static const struct target_core_fabric_ops srpt_template = {
.fabric_drop_wwn = srpt_drop_tport, .fabric_drop_wwn = srpt_drop_tport,
.fabric_make_tpg = srpt_make_tpg, .fabric_make_tpg = srpt_make_tpg,
.fabric_drop_tpg = srpt_drop_tpg, .fabric_drop_tpg = srpt_drop_tpg,
.fabric_post_link = NULL, .fabric_init_nodeacl = srpt_init_nodeacl,
.fabric_pre_unlink = NULL, .fabric_cleanup_nodeacl = srpt_cleanup_nodeacl,
.fabric_make_np = NULL,
.fabric_drop_np = NULL,
.fabric_make_nodeacl = srpt_make_nodeacl,
.fabric_drop_nodeacl = srpt_drop_nodeacl,
.tfc_wwn_attrs = srpt_wwn_attrs, .tfc_wwn_attrs = srpt_wwn_attrs,
.tfc_tpg_base_attrs = srpt_tpg_attrs, .tfc_tpg_base_attrs = srpt_tpg_attrs,

View File

@ -238,7 +238,6 @@ struct srpt_send_ioctx {
bool rdma_aborted; bool rdma_aborted;
struct se_cmd cmd; struct se_cmd cmd;
struct completion tx_done; struct completion tx_done;
u64 tag;
int sg_cnt; int sg_cnt;
int mapped_sg_count; int mapped_sg_count;
u16 n_rdma_ius; u16 n_rdma_ius;
@ -410,34 +409,16 @@ struct srpt_device {
/** /**
* struct srpt_node_acl - Per-initiator ACL data (managed via configfs). * struct srpt_node_acl - Per-initiator ACL data (managed via configfs).
* @nacl: Target core node ACL information.
* @i_port_id: 128-bit SRP initiator port ID. * @i_port_id: 128-bit SRP initiator port ID.
* @sport: port information. * @sport: port information.
* @nacl: Target core node ACL information.
* @list: Element of the per-HCA ACL list. * @list: Element of the per-HCA ACL list.
*/ */
struct srpt_node_acl { struct srpt_node_acl {
struct se_node_acl nacl;
u8 i_port_id[16]; u8 i_port_id[16];
struct srpt_port *sport; struct srpt_port *sport;
struct se_node_acl nacl;
struct list_head list; struct list_head list;
}; };
/*
* SRP-releated SCSI persistent reservation definitions.
*
* See also SPC4r28, section 7.6.1 (Protocol specific parameters introduction).
* See also SPC4r28, section 7.6.4.5 (TransportID for initiator ports using
* SCSI over an RDMA interface).
*/
enum {
SCSI_TRANSPORTID_PROTOCOLID_SRP = 4,
};
struct spc_rdma_transport_id {
uint8_t protocol_identifier;
uint8_t reserved[7];
uint8_t i_port_id[16];
};
#endif /* IB_SRPT_H */ #endif /* IB_SRPT_H */

View File

@ -1191,7 +1191,7 @@ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha,
list_for_each_entry(se_cmd, &se_sess->sess_cmd_list, se_cmd_list) { list_for_each_entry(se_cmd, &se_sess->sess_cmd_list, se_cmd_list) {
struct qla_tgt_cmd *cmd = struct qla_tgt_cmd *cmd =
container_of(se_cmd, struct qla_tgt_cmd, se_cmd); container_of(se_cmd, struct qla_tgt_cmd, se_cmd);
if (cmd->tag == abts->exchange_addr_to_abort) { if (se_cmd->tag == abts->exchange_addr_to_abort) {
lun = cmd->unpacked_lun; lun = cmd->unpacked_lun;
found_lun = true; found_lun = true;
break; break;
@ -1728,9 +1728,8 @@ static int qlt_pre_xmit_response(struct qla_tgt_cmd *cmd,
if (unlikely(cmd->aborted)) { if (unlikely(cmd->aborted)) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf014, ql_dbg(ql_dbg_tgt_mgt, vha, 0xf014,
"qla_target(%d): terminating exchange " "qla_target(%d): terminating exchange for aborted cmd=%p (se_cmd=%p, tag=%lld)",
"for aborted cmd=%p (se_cmd=%p, tag=%d)", vha->vp_idx, cmd, vha->vp_idx, cmd, se_cmd, se_cmd->tag);
se_cmd, cmd->tag);
cmd->state = QLA_TGT_STATE_ABORTED; cmd->state = QLA_TGT_STATE_ABORTED;
cmd->cmd_flags |= BIT_6; cmd->cmd_flags |= BIT_6;
@ -1765,18 +1764,17 @@ static int qlt_pre_xmit_response(struct qla_tgt_cmd *cmd,
if (se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) { if (se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) {
prm->residual = se_cmd->residual_count; prm->residual = se_cmd->residual_count;
ql_dbg(ql_dbg_io + ql_dbg_verbose, vha, 0x305c, ql_dbg(ql_dbg_io + ql_dbg_verbose, vha, 0x305c,
"Residual underflow: %d (tag %d, " "Residual underflow: %d (tag %lld, op %x, bufflen %d, rq_result %x)\n",
"op %x, bufflen %d, rq_result %x)\n", prm->residual, prm->residual, se_cmd->tag,
cmd->tag, se_cmd->t_task_cdb ? se_cmd->t_task_cdb[0] : 0, se_cmd->t_task_cdb ? se_cmd->t_task_cdb[0] : 0,
cmd->bufflen, prm->rq_result); cmd->bufflen, prm->rq_result);
prm->rq_result |= SS_RESIDUAL_UNDER; prm->rq_result |= SS_RESIDUAL_UNDER;
} else if (se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) { } else if (se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) {
prm->residual = se_cmd->residual_count; prm->residual = se_cmd->residual_count;
ql_dbg(ql_dbg_io, vha, 0x305d, ql_dbg(ql_dbg_io, vha, 0x305d,
"Residual overflow: %d (tag %d, " "Residual overflow: %d (tag %lld, op %x, bufflen %d, rq_result %x)\n",
"op %x, bufflen %d, rq_result %x)\n", prm->residual, prm->residual, se_cmd->tag, se_cmd->t_task_cdb ?
cmd->tag, se_cmd->t_task_cdb ? se_cmd->t_task_cdb[0] : 0, se_cmd->t_task_cdb[0] : 0, cmd->bufflen, prm->rq_result);
cmd->bufflen, prm->rq_result);
prm->rq_result |= SS_RESIDUAL_OVER; prm->rq_result |= SS_RESIDUAL_OVER;
} }
@ -1849,7 +1847,7 @@ static void qlt_check_srr_debug(struct qla_tgt_cmd *cmd, int *xmit_type)
== 50) { == 50) {
*xmit_type &= ~QLA_TGT_XMIT_STATUS; *xmit_type &= ~QLA_TGT_XMIT_STATUS;
ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf015, ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf015,
"Dropping cmd %p (tag %d) status", cmd, cmd->tag); "Dropping cmd %p (tag %d) status", cmd, se_cmd->tag);
} }
#endif #endif
/* /*
@ -1873,7 +1871,7 @@ static void qlt_check_srr_debug(struct qla_tgt_cmd *cmd, int *xmit_type)
ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf016, ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf016,
"Cutting cmd %p (tag %d) buffer" "Cutting cmd %p (tag %d) buffer"
" tail to len %d, sg_cnt %d (cmd->bufflen %d," " tail to len %d, sg_cnt %d (cmd->bufflen %d,"
" cmd->sg_cnt %d)", cmd, cmd->tag, tot_len, leave, " cmd->sg_cnt %d)", cmd, se_cmd->tag, tot_len, leave,
cmd->bufflen, cmd->sg_cnt); cmd->bufflen, cmd->sg_cnt);
cmd->bufflen = tot_len; cmd->bufflen = tot_len;
@ -1885,13 +1883,13 @@ static void qlt_check_srr_debug(struct qla_tgt_cmd *cmd, int *xmit_type)
ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf017, ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf017,
"Cutting cmd %p (tag %d) buffer head " "Cutting cmd %p (tag %d) buffer head "
"to offset %d (cmd->bufflen %d)", cmd, cmd->tag, offset, "to offset %d (cmd->bufflen %d)", cmd, se_cmd->tag, offset,
cmd->bufflen); cmd->bufflen);
if (offset == 0) if (offset == 0)
*xmit_type &= ~QLA_TGT_XMIT_DATA; *xmit_type &= ~QLA_TGT_XMIT_DATA;
else if (qlt_set_data_offset(cmd, offset)) { else if (qlt_set_data_offset(cmd, offset)) {
ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf018, ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf018,
"qlt_set_data_offset() failed (tag %d)", cmd->tag); "qlt_set_data_offset() failed (tag %d)", se_cmd->tag);
} }
} }
} }
@ -3194,7 +3192,7 @@ skip_term:
return; return;
} else if (cmd->state == QLA_TGT_STATE_ABORTED) { } else if (cmd->state == QLA_TGT_STATE_ABORTED) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01e, ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01e,
"Aborted command %p (tag %d) finished\n", cmd, cmd->tag); "Aborted command %p (tag %lld) finished\n", cmd, se_cmd->tag);
} else { } else {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05c, ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05c,
"qla_target(%d): A command in state (%d) should " "qla_target(%d): A command in state (%d) should "
@ -3266,7 +3264,7 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd)
goto out_term; goto out_term;
cdb = &atio->u.isp24.fcp_cmnd.cdb[0]; cdb = &atio->u.isp24.fcp_cmnd.cdb[0];
cmd->tag = atio->u.isp24.exchange_addr; cmd->se_cmd.tag = atio->u.isp24.exchange_addr;
cmd->unpacked_lun = scsilun_to_int( cmd->unpacked_lun = scsilun_to_int(
(struct scsi_lun *)&atio->u.isp24.fcp_cmnd.lun); (struct scsi_lun *)&atio->u.isp24.fcp_cmnd.lun);
@ -3893,9 +3891,8 @@ static void qlt_handle_srr(struct scsi_qla_host *vha,
resp = 1; resp = 1;
} else { } else {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf064, ql_dbg(ql_dbg_tgt_mgt, vha, 0xf064,
"qla_target(%d): SRR for in data for cmd " "qla_target(%d): SRR for in data for cmd without them (tag %lld, SCSI status %d), reject",
"without them (tag %d, SCSI status %d), " vha->vp_idx, se_cmd->tag,
"reject", vha->vp_idx, cmd->tag,
cmd->se_cmd.scsi_status); cmd->se_cmd.scsi_status);
goto out_reject; goto out_reject;
} }
@ -3929,10 +3926,8 @@ static void qlt_handle_srr(struct scsi_qla_host *vha,
} }
} else { } else {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf066, ql_dbg(ql_dbg_tgt_mgt, vha, 0xf066,
"qla_target(%d): SRR for out data for cmd " "qla_target(%d): SRR for out data for cmd without them (tag %lld, SCSI status %d), reject",
"without them (tag %d, SCSI status %d), " vha->vp_idx, se_cmd->tag, cmd->se_cmd.scsi_status);
"reject", vha->vp_idx, cmd->tag,
cmd->se_cmd.scsi_status);
goto out_reject; goto out_reject;
} }
break; break;
@ -4053,10 +4048,9 @@ restart:
cmd->sg = se_cmd->t_data_sg; cmd->sg = se_cmd->t_data_sg;
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf02c, ql_dbg(ql_dbg_tgt_mgt, vha, 0xf02c,
"SRR cmd %p (se_cmd %p, tag %d, op %x), " "SRR cmd %p (se_cmd %p, tag %lld, op %x), sg_cnt=%d, offset=%d",
"sg_cnt=%d, offset=%d", cmd, &cmd->se_cmd, cmd->tag, cmd, &cmd->se_cmd, se_cmd->tag, se_cmd->t_task_cdb ?
se_cmd->t_task_cdb ? se_cmd->t_task_cdb[0] : 0, se_cmd->t_task_cdb[0] : 0, cmd->sg_cnt, cmd->offset);
cmd->sg_cnt, cmd->offset);
qlt_handle_srr(vha, sctio, imm); qlt_handle_srr(vha, sctio, imm);

View File

@ -924,7 +924,6 @@ struct qla_tgt_cmd {
int sg_cnt; /* SG segments count */ int sg_cnt; /* SG segments count */
int bufflen; /* cmd buffer length */ int bufflen; /* cmd buffer length */
int offset; int offset;
uint32_t tag;
uint32_t unpacked_lun; uint32_t unpacked_lun;
enum dma_data_direction dma_data_direction; enum dma_data_direction dma_data_direction;
uint32_t reset_count; uint32_t reset_count;

View File

@ -44,7 +44,6 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/target_core_fabric_configfs.h> #include <target/target_core_fabric_configfs.h>
#include <target/target_core_configfs.h>
#include <target/configfs_macros.h> #include <target/configfs_macros.h>
#include "qla_def.h" #include "qla_def.h"
@ -54,9 +53,6 @@
static struct workqueue_struct *tcm_qla2xxx_free_wq; static struct workqueue_struct *tcm_qla2xxx_free_wq;
static struct workqueue_struct *tcm_qla2xxx_cmd_wq; static struct workqueue_struct *tcm_qla2xxx_cmd_wq;
static const struct target_core_fabric_ops tcm_qla2xxx_ops;
static const struct target_core_fabric_ops tcm_qla2xxx_npiv_ops;
/* /*
* Parse WWN. * Parse WWN.
* If strict, we require lower-case hex and colon separators to be sure * If strict, we require lower-case hex and colon separators to be sure
@ -191,23 +187,6 @@ static char *tcm_qla2xxx_npiv_get_fabric_name(void)
return "qla2xxx_npiv"; return "qla2xxx_npiv";
} }
static u8 tcm_qla2xxx_get_fabric_proto_ident(struct se_portal_group *se_tpg)
{
struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
struct tcm_qla2xxx_tpg, se_tpg);
struct tcm_qla2xxx_lport *lport = tpg->lport;
u8 proto_id;
switch (lport->lport_proto_id) {
case SCSI_PROTOCOL_FCP:
default:
proto_id = fc_get_fabric_proto_ident(se_tpg);
break;
}
return proto_id;
}
static char *tcm_qla2xxx_get_fabric_wwn(struct se_portal_group *se_tpg) static char *tcm_qla2xxx_get_fabric_wwn(struct se_portal_group *se_tpg)
{ {
struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
@ -224,78 +203,6 @@ static u16 tcm_qla2xxx_get_tag(struct se_portal_group *se_tpg)
return tpg->lport_tpgt; return tpg->lport_tpgt;
} }
static u32 tcm_qla2xxx_get_default_depth(struct se_portal_group *se_tpg)
{
return 1;
}
static u32 tcm_qla2xxx_get_pr_transport_id(
struct se_portal_group *se_tpg,
struct se_node_acl *se_nacl,
struct t10_pr_registration *pr_reg,
int *format_code,
unsigned char *buf)
{
struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
struct tcm_qla2xxx_tpg, se_tpg);
struct tcm_qla2xxx_lport *lport = tpg->lport;
int ret = 0;
switch (lport->lport_proto_id) {
case SCSI_PROTOCOL_FCP:
default:
ret = fc_get_pr_transport_id(se_tpg, se_nacl, pr_reg,
format_code, buf);
break;
}
return ret;
}
static u32 tcm_qla2xxx_get_pr_transport_id_len(
struct se_portal_group *se_tpg,
struct se_node_acl *se_nacl,
struct t10_pr_registration *pr_reg,
int *format_code)
{
struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
struct tcm_qla2xxx_tpg, se_tpg);
struct tcm_qla2xxx_lport *lport = tpg->lport;
int ret = 0;
switch (lport->lport_proto_id) {
case SCSI_PROTOCOL_FCP:
default:
ret = fc_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,
format_code);
break;
}
return ret;
}
static char *tcm_qla2xxx_parse_pr_out_transport_id(
struct se_portal_group *se_tpg,
const char *buf,
u32 *out_tid_len,
char **port_nexus_ptr)
{
struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
struct tcm_qla2xxx_tpg, se_tpg);
struct tcm_qla2xxx_lport *lport = tpg->lport;
char *tid = NULL;
switch (lport->lport_proto_id) {
case SCSI_PROTOCOL_FCP:
default:
tid = fc_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,
port_nexus_ptr);
break;
}
return tid;
}
static int tcm_qla2xxx_check_demo_mode(struct se_portal_group *se_tpg) static int tcm_qla2xxx_check_demo_mode(struct se_portal_group *se_tpg)
{ {
struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
@ -344,29 +251,6 @@ static int tcm_qla2xxx_check_prot_fabric_only(struct se_portal_group *se_tpg)
return tpg->tpg_attrib.fabric_prot_type; return tpg->tpg_attrib.fabric_prot_type;
} }
static struct se_node_acl *tcm_qla2xxx_alloc_fabric_acl(
struct se_portal_group *se_tpg)
{
struct tcm_qla2xxx_nacl *nacl;
nacl = kzalloc(sizeof(struct tcm_qla2xxx_nacl), GFP_KERNEL);
if (!nacl) {
pr_err("Unable to allocate struct tcm_qla2xxx_nacl\n");
return NULL;
}
return &nacl->se_node_acl;
}
static void tcm_qla2xxx_release_fabric_acl(
struct se_portal_group *se_tpg,
struct se_node_acl *se_nacl)
{
struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl,
struct tcm_qla2xxx_nacl, se_node_acl);
kfree(nacl);
}
static u32 tcm_qla2xxx_tpg_get_inst_index(struct se_portal_group *se_tpg) static u32 tcm_qla2xxx_tpg_get_inst_index(struct se_portal_group *se_tpg)
{ {
struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
@ -430,7 +314,7 @@ static int tcm_qla2xxx_check_stop_free(struct se_cmd *se_cmd)
cmd->cmd_flags |= BIT_14; cmd->cmd_flags |= BIT_14;
} }
return target_put_sess_cmd(se_cmd->se_sess, se_cmd); return target_put_sess_cmd(se_cmd);
} }
/* tcm_qla2xxx_release_cmd - Callback from TCM Core to release underlying /* tcm_qla2xxx_release_cmd - Callback from TCM Core to release underlying
@ -534,19 +418,6 @@ static void tcm_qla2xxx_set_default_node_attrs(struct se_node_acl *nacl)
return; return;
} }
static u32 tcm_qla2xxx_get_task_tag(struct se_cmd *se_cmd)
{
struct qla_tgt_cmd *cmd;
/* check for task mgmt cmd */
if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)
return 0xffffffff;
cmd = container_of(se_cmd, struct qla_tgt_cmd, se_cmd);
return cmd->tag;
}
static int tcm_qla2xxx_get_cmd_state(struct se_cmd *se_cmd) static int tcm_qla2xxx_get_cmd_state(struct se_cmd *se_cmd)
{ {
return 0; return 0;
@ -827,17 +698,6 @@ static void tcm_qla2xxx_release_session(struct kref *kref)
qlt_unreg_sess(se_sess->fabric_sess_ptr); qlt_unreg_sess(se_sess->fabric_sess_ptr);
} }
static void tcm_qla2xxx_put_session(struct se_session *se_sess)
{
struct qla_tgt_sess *sess = se_sess->fabric_sess_ptr;
struct qla_hw_data *ha = sess->vha->hw;
unsigned long flags;
spin_lock_irqsave(&ha->hardware_lock, flags);
kref_put(&se_sess->sess_kref, tcm_qla2xxx_release_session);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
static void tcm_qla2xxx_put_sess(struct qla_tgt_sess *sess) static void tcm_qla2xxx_put_sess(struct qla_tgt_sess *sess)
{ {
if (!sess) if (!sess)
@ -853,53 +713,20 @@ static void tcm_qla2xxx_shutdown_sess(struct qla_tgt_sess *sess)
target_sess_cmd_list_set_waiting(sess->se_sess); target_sess_cmd_list_set_waiting(sess->se_sess);
} }
static struct se_node_acl *tcm_qla2xxx_make_nodeacl( static int tcm_qla2xxx_init_nodeacl(struct se_node_acl *se_nacl,
struct se_portal_group *se_tpg, const char *name)
struct config_group *group,
const char *name)
{ {
struct se_node_acl *se_nacl, *se_nacl_new; struct tcm_qla2xxx_nacl *nacl =
struct tcm_qla2xxx_nacl *nacl; container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl);
u64 wwnn; u64 wwnn;
u32 qla2xxx_nexus_depth;
if (tcm_qla2xxx_parse_wwn(name, &wwnn, 1) < 0) if (tcm_qla2xxx_parse_wwn(name, &wwnn, 1) < 0)
return ERR_PTR(-EINVAL); return -EINVAL;
se_nacl_new = tcm_qla2xxx_alloc_fabric_acl(se_tpg);
if (!se_nacl_new)
return ERR_PTR(-ENOMEM);
/* #warning FIXME: Hardcoded qla2xxx_nexus depth in tcm_qla2xxx_make_nodeacl */
qla2xxx_nexus_depth = 1;
/*
* se_nacl_new may be released by core_tpg_add_initiator_node_acl()
* when converting a NodeACL from demo mode -> explict
*/
se_nacl = core_tpg_add_initiator_node_acl(se_tpg, se_nacl_new,
name, qla2xxx_nexus_depth);
if (IS_ERR(se_nacl)) {
tcm_qla2xxx_release_fabric_acl(se_tpg, se_nacl_new);
return se_nacl;
}
/*
* Locate our struct tcm_qla2xxx_nacl and set the FC Nport WWPN
*/
nacl = container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl);
nacl->nport_wwnn = wwnn; nacl->nport_wwnn = wwnn;
tcm_qla2xxx_format_wwn(&nacl->nport_name[0], TCM_QLA2XXX_NAMELEN, wwnn); tcm_qla2xxx_format_wwn(&nacl->nport_name[0], TCM_QLA2XXX_NAMELEN, wwnn);
return se_nacl; return 0;
}
static void tcm_qla2xxx_drop_nodeacl(struct se_node_acl *se_acl)
{
struct se_portal_group *se_tpg = se_acl->se_tpg;
struct tcm_qla2xxx_nacl *nacl = container_of(se_acl,
struct tcm_qla2xxx_nacl, se_node_acl);
core_tpg_del_initiator_node_acl(se_tpg, se_acl, 1);
kfree(nacl);
} }
/* Start items for tcm_qla2xxx_tpg_attrib_cit */ /* Start items for tcm_qla2xxx_tpg_attrib_cit */
@ -1175,8 +1002,7 @@ static struct se_portal_group *tcm_qla2xxx_make_tpg(
tpg->tpg_attrib.cache_dynamic_acls = 1; tpg->tpg_attrib.cache_dynamic_acls = 1;
tpg->tpg_attrib.demo_mode_login_only = 1; tpg->tpg_attrib.demo_mode_login_only = 1;
ret = core_tpg_register(&tcm_qla2xxx_ops, wwn, ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_FCP);
&tpg->se_tpg, tpg, TRANSPORT_TPG_TYPE_NORMAL);
if (ret < 0) { if (ret < 0) {
kfree(tpg); kfree(tpg);
return NULL; return NULL;
@ -1295,8 +1121,7 @@ static struct se_portal_group *tcm_qla2xxx_npiv_make_tpg(
tpg->tpg_attrib.cache_dynamic_acls = 1; tpg->tpg_attrib.cache_dynamic_acls = 1;
tpg->tpg_attrib.demo_mode_login_only = 1; tpg->tpg_attrib.demo_mode_login_only = 1;
ret = core_tpg_register(&tcm_qla2xxx_npiv_ops, wwn, ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_FCP);
&tpg->se_tpg, tpg, TRANSPORT_TPG_TYPE_NORMAL);
if (ret < 0) { if (ret < 0) {
kfree(tpg); kfree(tpg);
return NULL; return NULL;
@ -1988,14 +1813,10 @@ static struct configfs_attribute *tcm_qla2xxx_wwn_attrs[] = {
static const struct target_core_fabric_ops tcm_qla2xxx_ops = { static const struct target_core_fabric_ops tcm_qla2xxx_ops = {
.module = THIS_MODULE, .module = THIS_MODULE,
.name = "qla2xxx", .name = "qla2xxx",
.node_acl_size = sizeof(struct tcm_qla2xxx_nacl),
.get_fabric_name = tcm_qla2xxx_get_fabric_name, .get_fabric_name = tcm_qla2xxx_get_fabric_name,
.get_fabric_proto_ident = tcm_qla2xxx_get_fabric_proto_ident,
.tpg_get_wwn = tcm_qla2xxx_get_fabric_wwn, .tpg_get_wwn = tcm_qla2xxx_get_fabric_wwn,
.tpg_get_tag = tcm_qla2xxx_get_tag, .tpg_get_tag = tcm_qla2xxx_get_tag,
.tpg_get_default_depth = tcm_qla2xxx_get_default_depth,
.tpg_get_pr_transport_id = tcm_qla2xxx_get_pr_transport_id,
.tpg_get_pr_transport_id_len = tcm_qla2xxx_get_pr_transport_id_len,
.tpg_parse_pr_out_transport_id = tcm_qla2xxx_parse_pr_out_transport_id,
.tpg_check_demo_mode = tcm_qla2xxx_check_demo_mode, .tpg_check_demo_mode = tcm_qla2xxx_check_demo_mode,
.tpg_check_demo_mode_cache = tcm_qla2xxx_check_demo_mode_cache, .tpg_check_demo_mode_cache = tcm_qla2xxx_check_demo_mode_cache,
.tpg_check_demo_mode_write_protect = .tpg_check_demo_mode_write_protect =
@ -2004,12 +1825,9 @@ static const struct target_core_fabric_ops tcm_qla2xxx_ops = {
tcm_qla2xxx_check_prod_write_protect, tcm_qla2xxx_check_prod_write_protect,
.tpg_check_prot_fabric_only = tcm_qla2xxx_check_prot_fabric_only, .tpg_check_prot_fabric_only = tcm_qla2xxx_check_prot_fabric_only,
.tpg_check_demo_mode_login_only = tcm_qla2xxx_check_demo_mode_login_only, .tpg_check_demo_mode_login_only = tcm_qla2xxx_check_demo_mode_login_only,
.tpg_alloc_fabric_acl = tcm_qla2xxx_alloc_fabric_acl,
.tpg_release_fabric_acl = tcm_qla2xxx_release_fabric_acl,
.tpg_get_inst_index = tcm_qla2xxx_tpg_get_inst_index, .tpg_get_inst_index = tcm_qla2xxx_tpg_get_inst_index,
.check_stop_free = tcm_qla2xxx_check_stop_free, .check_stop_free = tcm_qla2xxx_check_stop_free,
.release_cmd = tcm_qla2xxx_release_cmd, .release_cmd = tcm_qla2xxx_release_cmd,
.put_session = tcm_qla2xxx_put_session,
.shutdown_session = tcm_qla2xxx_shutdown_session, .shutdown_session = tcm_qla2xxx_shutdown_session,
.close_session = tcm_qla2xxx_close_session, .close_session = tcm_qla2xxx_close_session,
.sess_get_index = tcm_qla2xxx_sess_get_index, .sess_get_index = tcm_qla2xxx_sess_get_index,
@ -2017,7 +1835,6 @@ static const struct target_core_fabric_ops tcm_qla2xxx_ops = {
.write_pending = tcm_qla2xxx_write_pending, .write_pending = tcm_qla2xxx_write_pending,
.write_pending_status = tcm_qla2xxx_write_pending_status, .write_pending_status = tcm_qla2xxx_write_pending_status,
.set_default_node_attributes = tcm_qla2xxx_set_default_node_attrs, .set_default_node_attributes = tcm_qla2xxx_set_default_node_attrs,
.get_task_tag = tcm_qla2xxx_get_task_tag,
.get_cmd_state = tcm_qla2xxx_get_cmd_state, .get_cmd_state = tcm_qla2xxx_get_cmd_state,
.queue_data_in = tcm_qla2xxx_queue_data_in, .queue_data_in = tcm_qla2xxx_queue_data_in,
.queue_status = tcm_qla2xxx_queue_status, .queue_status = tcm_qla2xxx_queue_status,
@ -2031,12 +1848,7 @@ static const struct target_core_fabric_ops tcm_qla2xxx_ops = {
.fabric_drop_wwn = tcm_qla2xxx_drop_lport, .fabric_drop_wwn = tcm_qla2xxx_drop_lport,
.fabric_make_tpg = tcm_qla2xxx_make_tpg, .fabric_make_tpg = tcm_qla2xxx_make_tpg,
.fabric_drop_tpg = tcm_qla2xxx_drop_tpg, .fabric_drop_tpg = tcm_qla2xxx_drop_tpg,
.fabric_post_link = NULL, .fabric_init_nodeacl = tcm_qla2xxx_init_nodeacl,
.fabric_pre_unlink = NULL,
.fabric_make_np = NULL,
.fabric_drop_np = NULL,
.fabric_make_nodeacl = tcm_qla2xxx_make_nodeacl,
.fabric_drop_nodeacl = tcm_qla2xxx_drop_nodeacl,
.tfc_wwn_attrs = tcm_qla2xxx_wwn_attrs, .tfc_wwn_attrs = tcm_qla2xxx_wwn_attrs,
.tfc_tpg_base_attrs = tcm_qla2xxx_tpg_attrs, .tfc_tpg_base_attrs = tcm_qla2xxx_tpg_attrs,
@ -2046,26 +1858,19 @@ static const struct target_core_fabric_ops tcm_qla2xxx_ops = {
static const struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = { static const struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = {
.module = THIS_MODULE, .module = THIS_MODULE,
.name = "qla2xxx_npiv", .name = "qla2xxx_npiv",
.node_acl_size = sizeof(struct tcm_qla2xxx_nacl),
.get_fabric_name = tcm_qla2xxx_npiv_get_fabric_name, .get_fabric_name = tcm_qla2xxx_npiv_get_fabric_name,
.get_fabric_proto_ident = tcm_qla2xxx_get_fabric_proto_ident,
.tpg_get_wwn = tcm_qla2xxx_get_fabric_wwn, .tpg_get_wwn = tcm_qla2xxx_get_fabric_wwn,
.tpg_get_tag = tcm_qla2xxx_get_tag, .tpg_get_tag = tcm_qla2xxx_get_tag,
.tpg_get_default_depth = tcm_qla2xxx_get_default_depth,
.tpg_get_pr_transport_id = tcm_qla2xxx_get_pr_transport_id,
.tpg_get_pr_transport_id_len = tcm_qla2xxx_get_pr_transport_id_len,
.tpg_parse_pr_out_transport_id = tcm_qla2xxx_parse_pr_out_transport_id,
.tpg_check_demo_mode = tcm_qla2xxx_check_demo_mode, .tpg_check_demo_mode = tcm_qla2xxx_check_demo_mode,
.tpg_check_demo_mode_cache = tcm_qla2xxx_check_demo_mode_cache, .tpg_check_demo_mode_cache = tcm_qla2xxx_check_demo_mode_cache,
.tpg_check_demo_mode_write_protect = tcm_qla2xxx_check_demo_mode, .tpg_check_demo_mode_write_protect = tcm_qla2xxx_check_demo_mode,
.tpg_check_prod_mode_write_protect = .tpg_check_prod_mode_write_protect =
tcm_qla2xxx_check_prod_write_protect, tcm_qla2xxx_check_prod_write_protect,
.tpg_check_demo_mode_login_only = tcm_qla2xxx_check_demo_mode_login_only, .tpg_check_demo_mode_login_only = tcm_qla2xxx_check_demo_mode_login_only,
.tpg_alloc_fabric_acl = tcm_qla2xxx_alloc_fabric_acl,
.tpg_release_fabric_acl = tcm_qla2xxx_release_fabric_acl,
.tpg_get_inst_index = tcm_qla2xxx_tpg_get_inst_index, .tpg_get_inst_index = tcm_qla2xxx_tpg_get_inst_index,
.check_stop_free = tcm_qla2xxx_check_stop_free, .check_stop_free = tcm_qla2xxx_check_stop_free,
.release_cmd = tcm_qla2xxx_release_cmd, .release_cmd = tcm_qla2xxx_release_cmd,
.put_session = tcm_qla2xxx_put_session,
.shutdown_session = tcm_qla2xxx_shutdown_session, .shutdown_session = tcm_qla2xxx_shutdown_session,
.close_session = tcm_qla2xxx_close_session, .close_session = tcm_qla2xxx_close_session,
.sess_get_index = tcm_qla2xxx_sess_get_index, .sess_get_index = tcm_qla2xxx_sess_get_index,
@ -2073,7 +1878,6 @@ static const struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = {
.write_pending = tcm_qla2xxx_write_pending, .write_pending = tcm_qla2xxx_write_pending,
.write_pending_status = tcm_qla2xxx_write_pending_status, .write_pending_status = tcm_qla2xxx_write_pending_status,
.set_default_node_attributes = tcm_qla2xxx_set_default_node_attrs, .set_default_node_attributes = tcm_qla2xxx_set_default_node_attrs,
.get_task_tag = tcm_qla2xxx_get_task_tag,
.get_cmd_state = tcm_qla2xxx_get_cmd_state, .get_cmd_state = tcm_qla2xxx_get_cmd_state,
.queue_data_in = tcm_qla2xxx_queue_data_in, .queue_data_in = tcm_qla2xxx_queue_data_in,
.queue_status = tcm_qla2xxx_queue_status, .queue_status = tcm_qla2xxx_queue_status,
@ -2087,12 +1891,7 @@ static const struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = {
.fabric_drop_wwn = tcm_qla2xxx_npiv_drop_lport, .fabric_drop_wwn = tcm_qla2xxx_npiv_drop_lport,
.fabric_make_tpg = tcm_qla2xxx_npiv_make_tpg, .fabric_make_tpg = tcm_qla2xxx_npiv_make_tpg,
.fabric_drop_tpg = tcm_qla2xxx_drop_tpg, .fabric_drop_tpg = tcm_qla2xxx_drop_tpg,
.fabric_post_link = NULL, .fabric_init_nodeacl = tcm_qla2xxx_init_nodeacl,
.fabric_pre_unlink = NULL,
.fabric_make_np = NULL,
.fabric_drop_np = NULL,
.fabric_make_nodeacl = tcm_qla2xxx_make_nodeacl,
.fabric_drop_nodeacl = tcm_qla2xxx_drop_nodeacl,
.tfc_wwn_attrs = tcm_qla2xxx_wwn_attrs, .tfc_wwn_attrs = tcm_qla2xxx_wwn_attrs,
.tfc_tpg_base_attrs = tcm_qla2xxx_npiv_tpg_attrs, .tfc_tpg_base_attrs = tcm_qla2xxx_npiv_tpg_attrs,

View File

@ -13,6 +13,8 @@
#include "qla_target.h" #include "qla_target.h"
struct tcm_qla2xxx_nacl { struct tcm_qla2xxx_nacl {
struct se_node_acl se_node_acl;
/* From libfc struct fc_rport->port_id */ /* From libfc struct fc_rport->port_id */
u32 nport_id; u32 nport_id;
/* Binary World Wide unique Node Name for remote FC Initiator Nport */ /* Binary World Wide unique Node Name for remote FC Initiator Nport */
@ -23,8 +25,6 @@ struct tcm_qla2xxx_nacl {
struct qla_tgt_sess *qla_tgt_sess; struct qla_tgt_sess *qla_tgt_sess;
/* Pointer to TCM FC nexus */ /* Pointer to TCM FC nexus */
struct se_session *nport_nexus; struct se_session *nport_nexus;
/* Returned by tcm_qla2xxx_make_nodeacl() */
struct se_node_acl se_node_acl;
}; };
struct tcm_qla2xxx_tpg_attrib { struct tcm_qla2xxx_tpg_attrib {
@ -57,8 +57,6 @@ struct tcm_qla2xxx_fc_loopid {
}; };
struct tcm_qla2xxx_lport { struct tcm_qla2xxx_lport {
/* SCSI protocol the lport is providing */
u8 lport_proto_id;
/* Binary World Wide unique Port Name for FC Target Lport */ /* Binary World Wide unique Port Name for FC Target Lport */
u64 lport_wwpn; u64 lport_wwpn;
/* Binary World Wide unique Port Name for FC NPIV Target Lport */ /* Binary World Wide unique Port Name for FC NPIV Target Lport */

View File

@ -29,7 +29,6 @@
#include <scsi/scsi_tcq.h> #include <scsi/scsi_tcq.h>
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
#include <target/iscsi/iscsi_target_core.h> #include <target/iscsi/iscsi_target_core.h>
#include "iscsi_target_parameters.h" #include "iscsi_target_parameters.h"
@ -716,7 +715,7 @@ static int iscsit_add_reject_from_cmd(
*/ */
if (cmd->se_cmd.se_tfo != NULL) { if (cmd->se_cmd.se_tfo != NULL) {
pr_debug("iscsi reject: calling target_put_sess_cmd >>>>>>\n"); pr_debug("iscsi reject: calling target_put_sess_cmd >>>>>>\n");
target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); target_put_sess_cmd(&cmd->se_cmd);
} }
return -1; return -1;
} }
@ -1002,13 +1001,15 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
hdr->cmdsn, be32_to_cpu(hdr->data_length), payload_length, hdr->cmdsn, be32_to_cpu(hdr->data_length), payload_length,
conn->cid); conn->cid);
target_get_sess_cmd(conn->sess->se_sess, &cmd->se_cmd, true); target_get_sess_cmd(&cmd->se_cmd, true);
cmd->sense_reason = transport_lookup_cmd_lun(&cmd->se_cmd, cmd->sense_reason = transport_lookup_cmd_lun(&cmd->se_cmd,
scsilun_to_int(&hdr->lun)); scsilun_to_int(&hdr->lun));
if (cmd->sense_reason) if (cmd->sense_reason)
goto attach_cmd; goto attach_cmd;
/* only used for printks or comparing with ->ref_task_tag */
cmd->se_cmd.tag = (__force u32)cmd->init_task_tag;
cmd->sense_reason = target_setup_cmd_from_cdb(&cmd->se_cmd, hdr->cdb); cmd->sense_reason = target_setup_cmd_from_cdb(&cmd->se_cmd, hdr->cdb);
if (cmd->sense_reason) { if (cmd->sense_reason) {
if (cmd->sense_reason == TCM_OUT_OF_RESOURCES) { if (cmd->sense_reason == TCM_OUT_OF_RESOURCES) {
@ -1068,7 +1069,7 @@ int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
return -1; return -1;
else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) { else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); target_put_sess_cmd(&cmd->se_cmd);
return 0; return 0;
} }
} }
@ -1084,7 +1085,7 @@ int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
if (!cmd->sense_reason) if (!cmd->sense_reason)
return 0; return 0;
target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); target_put_sess_cmd(&cmd->se_cmd);
return 0; return 0;
} }
@ -1115,7 +1116,6 @@ static int
iscsit_get_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr, iscsit_get_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr,
bool dump_payload) bool dump_payload)
{ {
struct iscsi_conn *conn = cmd->conn;
int cmdsn_ret = 0, immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION; int cmdsn_ret = 0, immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION;
/* /*
* Special case for Unsupported SAM WRITE Opcodes and ImmediateData=Yes. * Special case for Unsupported SAM WRITE Opcodes and ImmediateData=Yes.
@ -1142,7 +1142,7 @@ after_immediate_data:
rc = iscsit_dump_data_payload(cmd->conn, rc = iscsit_dump_data_payload(cmd->conn,
cmd->first_burst_len, 1); cmd->first_burst_len, 1);
target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); target_put_sess_cmd(&cmd->se_cmd);
return rc; return rc;
} else if (cmd->unsolicited_data) } else if (cmd->unsolicited_data)
iscsit_set_unsoliticed_dataout(cmd); iscsit_set_unsoliticed_dataout(cmd);
@ -1811,7 +1811,7 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
conn->sess->se_sess, 0, DMA_NONE, conn->sess->se_sess, 0, DMA_NONE,
TCM_SIMPLE_TAG, cmd->sense_buffer + 2); TCM_SIMPLE_TAG, cmd->sense_buffer + 2);
target_get_sess_cmd(conn->sess->se_sess, &cmd->se_cmd, true); target_get_sess_cmd(&cmd->se_cmd, true);
sess_ref = true; sess_ref = true;
switch (function) { switch (function) {
@ -1953,7 +1953,7 @@ attach:
*/ */
if (sess_ref) { if (sess_ref) {
pr_debug("Handle TMR, using sess_ref=true check\n"); pr_debug("Handle TMR, using sess_ref=true check\n");
target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); target_put_sess_cmd(&cmd->se_cmd);
} }
iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state); iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
@ -2737,11 +2737,7 @@ static int iscsit_send_datain(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
cmd->iov_data_count = iov_count; cmd->iov_data_count = iov_count;
cmd->tx_size = tx_size; cmd->tx_size = tx_size;
/* sendpage is preferred but can't insert markers */ ret = iscsit_fe_sendpage_sg(cmd, conn);
if (!conn->conn_ops->IFMarker)
ret = iscsit_fe_sendpage_sg(cmd, conn);
else
ret = iscsit_send_tx_data(cmd, conn, 0);
iscsit_unmap_iovec(cmd); iscsit_unmap_iovec(cmd);
@ -4073,17 +4069,9 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf)
" opcode while ERL=0, closing iSCSI connection.\n"); " opcode while ERL=0, closing iSCSI connection.\n");
return -1; return -1;
} }
if (!conn->conn_ops->OFMarker) { pr_err("Unable to recover from unknown opcode while OFMarker=No,"
pr_err("Unable to recover from unknown" " closing iSCSI connection.\n");
" opcode while OFMarker=No, closing iSCSI" ret = -1;
" connection.\n");
return -1;
}
if (iscsit_recover_from_unknown_opcode(conn) < 0) {
pr_err("Unable to recover from unknown"
" opcode, closing iSCSI connection.\n");
return -1;
}
break; break;
} }

View File

@ -24,7 +24,6 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/target_core_fabric_configfs.h> #include <target/target_core_fabric_configfs.h>
#include <target/target_core_configfs.h>
#include <target/configfs_macros.h> #include <target/configfs_macros.h>
#include <target/iscsi/iscsi_transport.h> #include <target/iscsi/iscsi_transport.h>
@ -860,57 +859,19 @@ static struct configfs_attribute *lio_target_initiator_attrs[] = {
NULL, NULL,
}; };
static struct se_node_acl *lio_tpg_alloc_fabric_acl( static int lio_target_init_nodeacl(struct se_node_acl *se_nacl,
struct se_portal_group *se_tpg) const char *name)
{ {
struct iscsi_node_acl *acl; struct iscsi_node_acl *acl =
container_of(se_nacl, struct iscsi_node_acl, se_node_acl);
acl = kzalloc(sizeof(struct iscsi_node_acl), GFP_KERNEL); struct config_group *stats_cg = &se_nacl->acl_fabric_stat_group;
if (!acl) {
pr_err("Unable to allocate memory for struct iscsi_node_acl\n");
return NULL;
}
return &acl->se_node_acl;
}
static struct se_node_acl *lio_target_make_nodeacl(
struct se_portal_group *se_tpg,
struct config_group *group,
const char *name)
{
struct config_group *stats_cg;
struct iscsi_node_acl *acl;
struct se_node_acl *se_nacl_new, *se_nacl;
struct iscsi_portal_group *tpg = container_of(se_tpg,
struct iscsi_portal_group, tpg_se_tpg);
u32 cmdsn_depth;
se_nacl_new = lio_tpg_alloc_fabric_acl(se_tpg);
if (!se_nacl_new)
return ERR_PTR(-ENOMEM);
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
*/
se_nacl = core_tpg_add_initiator_node_acl(se_tpg, se_nacl_new,
name, cmdsn_depth);
if (IS_ERR(se_nacl))
return se_nacl;
acl = container_of(se_nacl, struct iscsi_node_acl, se_node_acl);
stats_cg = &se_nacl->acl_fabric_stat_group;
stats_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, stats_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2,
GFP_KERNEL); GFP_KERNEL);
if (!stats_cg->default_groups) { if (!stats_cg->default_groups) {
pr_err("Unable to allocate memory for" pr_err("Unable to allocate memory for"
" stats_cg->default_groups\n"); " stats_cg->default_groups\n");
core_tpg_del_initiator_node_acl(se_tpg, se_nacl, 1); return -ENOMEM;
kfree(acl);
return ERR_PTR(-ENOMEM);
} }
stats_cg->default_groups[0] = &acl->node_stat_grps.iscsi_sess_stats_group; stats_cg->default_groups[0] = &acl->node_stat_grps.iscsi_sess_stats_group;
@ -918,13 +879,11 @@ static struct se_node_acl *lio_target_make_nodeacl(
config_group_init_type_name(&acl->node_stat_grps.iscsi_sess_stats_group, config_group_init_type_name(&acl->node_stat_grps.iscsi_sess_stats_group,
"iscsi_sess_stats", &iscsi_stat_sess_cit); "iscsi_sess_stats", &iscsi_stat_sess_cit);
return se_nacl; return 0;
} }
static void lio_target_drop_nodeacl( static void lio_target_cleanup_nodeacl( struct se_node_acl *se_nacl)
struct se_node_acl *se_nacl)
{ {
struct se_portal_group *se_tpg = se_nacl->se_tpg;
struct iscsi_node_acl *acl = container_of(se_nacl, struct iscsi_node_acl *acl = container_of(se_nacl,
struct iscsi_node_acl, se_node_acl); struct iscsi_node_acl, se_node_acl);
struct config_item *df_item; struct config_item *df_item;
@ -938,9 +897,6 @@ static void lio_target_drop_nodeacl(
config_item_put(df_item); config_item_put(df_item);
} }
kfree(stats_cg->default_groups); kfree(stats_cg->default_groups);
core_tpg_del_initiator_node_acl(se_tpg, se_nacl, 1);
kfree(acl);
} }
/* End items for lio_target_acl_cit */ /* End items for lio_target_acl_cit */
@ -1463,8 +1419,7 @@ static struct se_portal_group *lio_target_tiqn_addtpg(
if (!tpg) if (!tpg)
return NULL; return NULL;
ret = core_tpg_register(&iscsi_ops, wwn, &tpg->tpg_se_tpg, ret = core_tpg_register(wwn, &tpg->tpg_se_tpg, SCSI_PROTOCOL_ISCSI);
tpg, TRANSPORT_TPG_TYPE_NORMAL);
if (ret < 0) if (ret < 0)
return NULL; return NULL;
@ -1735,14 +1690,6 @@ static char *iscsi_get_fabric_name(void)
return "iSCSI"; return "iSCSI";
} }
static u32 iscsi_get_task_tag(struct se_cmd *se_cmd)
{
struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
/* only used for printks or comparism with ->ref_task_tag */
return (__force u32)cmd->init_task_tag;
}
static int iscsi_get_cmd_state(struct se_cmd *se_cmd) static int iscsi_get_cmd_state(struct se_cmd *se_cmd)
{ {
struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd); struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
@ -1832,78 +1779,58 @@ static void lio_aborted_task(struct se_cmd *se_cmd)
cmd->conn->conn_transport->iscsit_aborted_task(cmd->conn, cmd); cmd->conn->conn_transport->iscsit_aborted_task(cmd->conn, cmd);
} }
static inline struct iscsi_portal_group *iscsi_tpg(struct se_portal_group *se_tpg)
{
return container_of(se_tpg, struct iscsi_portal_group, tpg_se_tpg);
}
static char *lio_tpg_get_endpoint_wwn(struct se_portal_group *se_tpg) static char *lio_tpg_get_endpoint_wwn(struct se_portal_group *se_tpg)
{ {
struct iscsi_portal_group *tpg = se_tpg->se_tpg_fabric_ptr; return iscsi_tpg(se_tpg)->tpg_tiqn->tiqn;
return &tpg->tpg_tiqn->tiqn[0];
} }
static u16 lio_tpg_get_tag(struct se_portal_group *se_tpg) static u16 lio_tpg_get_tag(struct se_portal_group *se_tpg)
{ {
struct iscsi_portal_group *tpg = se_tpg->se_tpg_fabric_ptr; return iscsi_tpg(se_tpg)->tpgt;
return tpg->tpgt;
} }
static u32 lio_tpg_get_default_depth(struct se_portal_group *se_tpg) 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(se_tpg)->tpg_attrib.default_cmdsn_depth;
return tpg->tpg_attrib.default_cmdsn_depth;
} }
static int lio_tpg_check_demo_mode(struct se_portal_group *se_tpg) 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(se_tpg)->tpg_attrib.generate_node_acls;
return tpg->tpg_attrib.generate_node_acls;
} }
static int lio_tpg_check_demo_mode_cache(struct se_portal_group *se_tpg) 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(se_tpg)->tpg_attrib.cache_dynamic_acls;
return tpg->tpg_attrib.cache_dynamic_acls;
} }
static int lio_tpg_check_demo_mode_write_protect( static int lio_tpg_check_demo_mode_write_protect(
struct se_portal_group *se_tpg) struct se_portal_group *se_tpg)
{ {
struct iscsi_portal_group *tpg = se_tpg->se_tpg_fabric_ptr; return iscsi_tpg(se_tpg)->tpg_attrib.demo_mode_write_protect;
return tpg->tpg_attrib.demo_mode_write_protect;
} }
static int lio_tpg_check_prod_mode_write_protect( static int lio_tpg_check_prod_mode_write_protect(
struct se_portal_group *se_tpg) struct se_portal_group *se_tpg)
{ {
struct iscsi_portal_group *tpg = se_tpg->se_tpg_fabric_ptr; return iscsi_tpg(se_tpg)->tpg_attrib.prod_mode_write_protect;
return tpg->tpg_attrib.prod_mode_write_protect;
} }
static int lio_tpg_check_prot_fabric_only( static int lio_tpg_check_prot_fabric_only(
struct se_portal_group *se_tpg) struct se_portal_group *se_tpg)
{ {
struct iscsi_portal_group *tpg = se_tpg->se_tpg_fabric_ptr;
/* /*
* Only report fabric_prot_type if t10_pi has also been enabled * Only report fabric_prot_type if t10_pi has also been enabled
* for incoming ib_isert sessions. * for incoming ib_isert sessions.
*/ */
if (!tpg->tpg_attrib.t10_pi) if (!iscsi_tpg(se_tpg)->tpg_attrib.t10_pi)
return 0; return 0;
return iscsi_tpg(se_tpg)->tpg_attrib.fabric_prot_type;
return tpg->tpg_attrib.fabric_prot_type;
}
static void lio_tpg_release_fabric_acl(
struct se_portal_group *se_tpg,
struct se_node_acl *se_acl)
{
struct iscsi_node_acl *acl = container_of(se_acl,
struct iscsi_node_acl, se_node_acl);
kfree(acl);
} }
/* /*
@ -1948,9 +1875,7 @@ static void lio_tpg_close_session(struct se_session *se_sess)
static u32 lio_tpg_get_inst_index(struct se_portal_group *se_tpg) static u32 lio_tpg_get_inst_index(struct se_portal_group *se_tpg)
{ {
struct iscsi_portal_group *tpg = se_tpg->se_tpg_fabric_ptr; return iscsi_tpg(se_tpg)->tpg_tiqn->tiqn_index;
return tpg->tpg_tiqn->tiqn_index;
} }
static void lio_set_default_node_attributes(struct se_node_acl *se_acl) static void lio_set_default_node_attributes(struct se_node_acl *se_acl)
@ -1967,7 +1892,7 @@ static void lio_set_default_node_attributes(struct se_node_acl *se_acl)
static int lio_check_stop_free(struct se_cmd *se_cmd) static int lio_check_stop_free(struct se_cmd *se_cmd)
{ {
return target_put_sess_cmd(se_cmd->se_sess, se_cmd); return target_put_sess_cmd(se_cmd);
} }
static void lio_release_cmd(struct se_cmd *se_cmd) static void lio_release_cmd(struct se_cmd *se_cmd)
@ -1981,14 +1906,11 @@ static void lio_release_cmd(struct se_cmd *se_cmd)
const struct target_core_fabric_ops iscsi_ops = { const struct target_core_fabric_ops iscsi_ops = {
.module = THIS_MODULE, .module = THIS_MODULE,
.name = "iscsi", .name = "iscsi",
.node_acl_size = sizeof(struct iscsi_node_acl),
.get_fabric_name = iscsi_get_fabric_name, .get_fabric_name = iscsi_get_fabric_name,
.get_fabric_proto_ident = iscsi_get_fabric_proto_ident,
.tpg_get_wwn = lio_tpg_get_endpoint_wwn, .tpg_get_wwn = lio_tpg_get_endpoint_wwn,
.tpg_get_tag = lio_tpg_get_tag, .tpg_get_tag = lio_tpg_get_tag,
.tpg_get_default_depth = lio_tpg_get_default_depth, .tpg_get_default_depth = lio_tpg_get_default_depth,
.tpg_get_pr_transport_id = iscsi_get_pr_transport_id,
.tpg_get_pr_transport_id_len = iscsi_get_pr_transport_id_len,
.tpg_parse_pr_out_transport_id = iscsi_parse_pr_out_transport_id,
.tpg_check_demo_mode = lio_tpg_check_demo_mode, .tpg_check_demo_mode = lio_tpg_check_demo_mode,
.tpg_check_demo_mode_cache = lio_tpg_check_demo_mode_cache, .tpg_check_demo_mode_cache = lio_tpg_check_demo_mode_cache,
.tpg_check_demo_mode_write_protect = .tpg_check_demo_mode_write_protect =
@ -1996,8 +1918,6 @@ const struct target_core_fabric_ops iscsi_ops = {
.tpg_check_prod_mode_write_protect = .tpg_check_prod_mode_write_protect =
lio_tpg_check_prod_mode_write_protect, lio_tpg_check_prod_mode_write_protect,
.tpg_check_prot_fabric_only = &lio_tpg_check_prot_fabric_only, .tpg_check_prot_fabric_only = &lio_tpg_check_prot_fabric_only,
.tpg_alloc_fabric_acl = lio_tpg_alloc_fabric_acl,
.tpg_release_fabric_acl = lio_tpg_release_fabric_acl,
.tpg_get_inst_index = lio_tpg_get_inst_index, .tpg_get_inst_index = lio_tpg_get_inst_index,
.check_stop_free = lio_check_stop_free, .check_stop_free = lio_check_stop_free,
.release_cmd = lio_release_cmd, .release_cmd = lio_release_cmd,
@ -2008,7 +1928,6 @@ const struct target_core_fabric_ops iscsi_ops = {
.write_pending = lio_write_pending, .write_pending = lio_write_pending,
.write_pending_status = lio_write_pending_status, .write_pending_status = lio_write_pending_status,
.set_default_node_attributes = lio_set_default_node_attributes, .set_default_node_attributes = lio_set_default_node_attributes,
.get_task_tag = iscsi_get_task_tag,
.get_cmd_state = iscsi_get_cmd_state, .get_cmd_state = iscsi_get_cmd_state,
.queue_data_in = lio_queue_data_in, .queue_data_in = lio_queue_data_in,
.queue_status = lio_queue_status, .queue_status = lio_queue_status,
@ -2020,8 +1939,8 @@ const struct target_core_fabric_ops iscsi_ops = {
.fabric_drop_tpg = lio_target_tiqn_deltpg, .fabric_drop_tpg = lio_target_tiqn_deltpg,
.fabric_make_np = lio_target_call_addnptotpg, .fabric_make_np = lio_target_call_addnptotpg,
.fabric_drop_np = lio_target_call_delnpfromtpg, .fabric_drop_np = lio_target_call_delnpfromtpg,
.fabric_make_nodeacl = lio_target_make_nodeacl, .fabric_init_nodeacl = lio_target_init_nodeacl,
.fabric_drop_nodeacl = lio_target_drop_nodeacl, .fabric_cleanup_nodeacl = lio_target_cleanup_nodeacl,
.tfc_discovery_attrs = lio_target_discovery_auth_attrs, .tfc_discovery_attrs = lio_target_discovery_auth_attrs,
.tfc_wwn_attrs = lio_target_wwn_attrs, .tfc_wwn_attrs = lio_target_wwn_attrs,

View File

@ -956,56 +956,3 @@ void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn)
iscsit_handle_connection_cleanup(conn); iscsit_handle_connection_cleanup(conn);
} }
/*
* This is the simple function that makes the magic of
* sync and steering happen in the follow paradoxical order:
*
* 0) Receive conn->of_marker (bytes left until next OFMarker)
* bytes into an offload buffer. When we pass the exact number
* of bytes in conn->of_marker, iscsit_dump_data_payload() and hence
* rx_data() will automatically receive the identical u32 marker
* values and store it in conn->of_marker_offset;
* 1) Now conn->of_marker_offset will contain the offset to the start
* of the next iSCSI PDU. Dump these remaining bytes into another
* offload buffer.
* 2) We are done!
* Next byte in the TCP stream will contain the next iSCSI PDU!
* Cool Huh?!
*/
int iscsit_recover_from_unknown_opcode(struct iscsi_conn *conn)
{
/*
* Make sure the remaining bytes to next maker is a sane value.
*/
if (conn->of_marker > (conn->conn_ops->OFMarkInt * 4)) {
pr_err("Remaining bytes to OFMarker: %u exceeds"
" OFMarkInt bytes: %u.\n", conn->of_marker,
conn->conn_ops->OFMarkInt * 4);
return -1;
}
pr_debug("Advancing %u bytes in TCP stream to get to the"
" next OFMarker.\n", conn->of_marker);
if (iscsit_dump_data_payload(conn, conn->of_marker, 0) < 0)
return -1;
/*
* Make sure the offset marker we retrived is a valid value.
*/
if (conn->of_marker_offset > (ISCSI_HDR_LEN + (ISCSI_CRC_LEN * 2) +
conn->conn_ops->MaxRecvDataSegmentLength)) {
pr_err("OfMarker offset value: %u exceeds limit.\n",
conn->of_marker_offset);
return -1;
}
pr_debug("Discarding %u bytes of TCP stream to get to the"
" next iSCSI Opcode.\n", conn->of_marker_offset);
if (iscsit_dump_data_payload(conn, conn->of_marker_offset, 0) < 0)
return -1;
return 0;
}

View File

@ -10,6 +10,5 @@ extern void iscsit_connection_reinstatement_rcfr(struct iscsi_conn *);
extern void iscsit_cause_connection_reinstatement(struct iscsi_conn *, int); extern void iscsit_cause_connection_reinstatement(struct iscsi_conn *, int);
extern void iscsit_fall_back_to_erl0(struct iscsi_session *); extern void iscsit_fall_back_to_erl0(struct iscsi_session *);
extern void iscsit_take_action_for_connection_exit(struct iscsi_conn *); extern void iscsit_take_action_for_connection_exit(struct iscsi_conn *);
extern int iscsit_recover_from_unknown_opcode(struct iscsi_conn *);
#endif /*** ISCSI_TARGET_ERL0_H ***/ #endif /*** ISCSI_TARGET_ERL0_H ***/

View File

@ -410,8 +410,6 @@ static int iscsi_login_zero_tsih_s2(
if (iscsi_change_param_sprintf(conn, "ErrorRecoveryLevel=%d", na->default_erl)) if (iscsi_change_param_sprintf(conn, "ErrorRecoveryLevel=%d", na->default_erl))
return -1; return -1;
if (iscsi_login_disable_FIM_keys(conn->param_list, conn) < 0)
return -1;
/* /*
* Set RDMAExtensions=Yes by default for iSER enabled network portals * Set RDMAExtensions=Yes by default for iSER enabled network portals
*/ */
@ -477,59 +475,6 @@ check_prot:
return 0; return 0;
} }
/*
* Remove PSTATE_NEGOTIATE for the four FIM related keys.
* The Initiator node will be able to enable FIM by proposing them itself.
*/
int iscsi_login_disable_FIM_keys(
struct iscsi_param_list *param_list,
struct iscsi_conn *conn)
{
struct iscsi_param *param;
param = iscsi_find_param_from_key("OFMarker", param_list);
if (!param) {
pr_err("iscsi_find_param_from_key() for"
" OFMarker failed\n");
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
ISCSI_LOGIN_STATUS_NO_RESOURCES);
return -1;
}
param->state &= ~PSTATE_NEGOTIATE;
param = iscsi_find_param_from_key("OFMarkInt", param_list);
if (!param) {
pr_err("iscsi_find_param_from_key() for"
" IFMarker failed\n");
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
ISCSI_LOGIN_STATUS_NO_RESOURCES);
return -1;
}
param->state &= ~PSTATE_NEGOTIATE;
param = iscsi_find_param_from_key("IFMarker", param_list);
if (!param) {
pr_err("iscsi_find_param_from_key() for"
" IFMarker failed\n");
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
ISCSI_LOGIN_STATUS_NO_RESOURCES);
return -1;
}
param->state &= ~PSTATE_NEGOTIATE;
param = iscsi_find_param_from_key("IFMarkInt", param_list);
if (!param) {
pr_err("iscsi_find_param_from_key() for"
" IFMarker failed\n");
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
ISCSI_LOGIN_STATUS_NO_RESOURCES);
return -1;
}
param->state &= ~PSTATE_NEGOTIATE;
return 0;
}
static int iscsi_login_non_zero_tsih_s1( static int iscsi_login_non_zero_tsih_s1(
struct iscsi_conn *conn, struct iscsi_conn *conn,
unsigned char *buf) unsigned char *buf)
@ -616,7 +561,7 @@ static int iscsi_login_non_zero_tsih_s2(
if (iscsi_change_param_sprintf(conn, "TargetPortalGroupTag=%hu", sess->tpg->tpgt)) if (iscsi_change_param_sprintf(conn, "TargetPortalGroupTag=%hu", sess->tpg->tpgt))
return -1; return -1;
return iscsi_login_disable_FIM_keys(conn->param_list, conn); return 0;
} }
int iscsi_login_post_auth_non_zero_tsih( int iscsi_login_post_auth_non_zero_tsih(
@ -765,7 +710,6 @@ int iscsi_post_login_handler(
conn->conn_state = TARG_CONN_STATE_LOGGED_IN; conn->conn_state = TARG_CONN_STATE_LOGGED_IN;
iscsi_set_connection_parameters(conn->conn_ops, conn->param_list); iscsi_set_connection_parameters(conn->conn_ops, conn->param_list);
iscsit_set_sync_and_steering_values(conn);
/* /*
* SCSI Initiator -> SCSI Target Port Mapping * SCSI Initiator -> SCSI Target Port Mapping
*/ */

View File

@ -16,6 +16,5 @@ extern int iscsi_post_login_handler(struct iscsi_np *, struct iscsi_conn *, u8);
extern void iscsi_target_login_sess_out(struct iscsi_conn *, struct iscsi_np *, extern void iscsi_target_login_sess_out(struct iscsi_conn *, struct iscsi_np *,
bool, bool); bool, bool);
extern int iscsi_target_login_thread(void *); extern int iscsi_target_login_thread(void *);
extern int iscsi_login_disable_FIM_keys(struct iscsi_param_list *, struct iscsi_conn *);
#endif /*** ISCSI_TARGET_LOGIN_H ***/ #endif /*** ISCSI_TARGET_LOGIN_H ***/

View File

@ -34,13 +34,6 @@ int iscsi_login_rx_data(
iov.iov_len = length; iov.iov_len = length;
iov.iov_base = buf; iov.iov_base = buf;
/*
* Initial Marker-less Interval.
* Add the values regardless of IFMarker/OFMarker, considering
* it may not be negoitated yet.
*/
conn->of_marker += length;
rx_got = rx_data(conn, &iov, 1, length); rx_got = rx_data(conn, &iov, 1, length);
if (rx_got != length) { if (rx_got != length) {
pr_err("rx_data returned %d, expecting %d.\n", pr_err("rx_data returned %d, expecting %d.\n",
@ -72,13 +65,6 @@ int iscsi_login_tx_data(
iov_cnt++; iov_cnt++;
} }
/*
* Initial Marker-less Interval.
* Add the values regardless of IFMarker/OFMarker, considering
* it may not be negoitated yet.
*/
conn->if_marker += length;
tx_sent = tx_data(conn, &iov[0], iov_cnt, length); tx_sent = tx_data(conn, &iov[0], iov_cnt, length);
if (tx_sent != length) { if (tx_sent != length) {
pr_err("tx_data returned %d, expecting %d.\n", pr_err("tx_data returned %d, expecting %d.\n",
@ -97,12 +83,6 @@ void iscsi_dump_conn_ops(struct iscsi_conn_ops *conn_ops)
"CRC32C" : "None"); "CRC32C" : "None");
pr_debug("MaxRecvDataSegmentLength: %u\n", pr_debug("MaxRecvDataSegmentLength: %u\n",
conn_ops->MaxRecvDataSegmentLength); conn_ops->MaxRecvDataSegmentLength);
pr_debug("OFMarker: %s\n", (conn_ops->OFMarker) ? "Yes" : "No");
pr_debug("IFMarker: %s\n", (conn_ops->IFMarker) ? "Yes" : "No");
if (conn_ops->OFMarker)
pr_debug("OFMarkInt: %u\n", conn_ops->OFMarkInt);
if (conn_ops->IFMarker)
pr_debug("IFMarkInt: %u\n", conn_ops->IFMarkInt);
} }
void iscsi_dump_sess_ops(struct iscsi_sess_ops *sess_ops) void iscsi_dump_sess_ops(struct iscsi_sess_ops *sess_ops)
@ -194,10 +174,6 @@ static struct iscsi_param *iscsi_set_default_param(struct iscsi_param_list *para
case TYPERANGE_DIGEST: case TYPERANGE_DIGEST:
param->type = TYPE_VALUE_LIST | TYPE_STRING; param->type = TYPE_VALUE_LIST | TYPE_STRING;
break; break;
case TYPERANGE_MARKINT:
param->type = TYPE_NUMBER_RANGE;
param->type_range |= TYPERANGE_1_TO_65535;
break;
case TYPERANGE_ISCSINAME: case TYPERANGE_ISCSINAME:
case TYPERANGE_SESSIONTYPE: case TYPERANGE_SESSIONTYPE:
case TYPERANGE_TARGETADDRESS: case TYPERANGE_TARGETADDRESS:
@ -422,13 +398,13 @@ int iscsi_create_default_params(struct iscsi_param_list **param_list_ptr)
param = iscsi_set_default_param(pl, IFMARKINT, INITIAL_IFMARKINT, param = iscsi_set_default_param(pl, IFMARKINT, INITIAL_IFMARKINT,
PHASE_OPERATIONAL, SCOPE_CONNECTION_ONLY, SENDER_BOTH, PHASE_OPERATIONAL, SCOPE_CONNECTION_ONLY, SENDER_BOTH,
TYPERANGE_MARKINT, USE_INITIAL_ONLY); TYPERANGE_UTF8, USE_INITIAL_ONLY);
if (!param) if (!param)
goto out; goto out;
param = iscsi_set_default_param(pl, OFMARKINT, INITIAL_OFMARKINT, param = iscsi_set_default_param(pl, OFMARKINT, INITIAL_OFMARKINT,
PHASE_OPERATIONAL, SCOPE_CONNECTION_ONLY, SENDER_BOTH, PHASE_OPERATIONAL, SCOPE_CONNECTION_ONLY, SENDER_BOTH,
TYPERANGE_MARKINT, USE_INITIAL_ONLY); TYPERANGE_UTF8, USE_INITIAL_ONLY);
if (!param) if (!param)
goto out; goto out;
/* /*
@ -524,9 +500,9 @@ int iscsi_set_keys_to_negotiate(
} else if (!strcmp(param->name, OFMARKER)) { } else if (!strcmp(param->name, OFMARKER)) {
SET_PSTATE_NEGOTIATE(param); SET_PSTATE_NEGOTIATE(param);
} else if (!strcmp(param->name, IFMARKINT)) { } else if (!strcmp(param->name, IFMARKINT)) {
SET_PSTATE_NEGOTIATE(param); SET_PSTATE_REJECT(param);
} else if (!strcmp(param->name, OFMARKINT)) { } else if (!strcmp(param->name, OFMARKINT)) {
SET_PSTATE_NEGOTIATE(param); SET_PSTATE_REJECT(param);
} else if (!strcmp(param->name, RDMAEXTENSIONS)) { } else if (!strcmp(param->name, RDMAEXTENSIONS)) {
if (iser) if (iser)
SET_PSTATE_NEGOTIATE(param); SET_PSTATE_NEGOTIATE(param);
@ -906,91 +882,6 @@ static int iscsi_check_numerical_value(struct iscsi_param *param, char *value_pt
return 0; return 0;
} }
static int iscsi_check_numerical_range_value(struct iscsi_param *param, char *value)
{
char *left_val_ptr = NULL, *right_val_ptr = NULL;
char *tilde_ptr = NULL;
u32 left_val, right_val, local_left_val;
if (strcmp(param->name, IFMARKINT) &&
strcmp(param->name, OFMARKINT)) {
pr_err("Only parameters \"%s\" or \"%s\" may contain a"
" numerical range value.\n", IFMARKINT, OFMARKINT);
return -1;
}
if (IS_PSTATE_PROPOSER(param))
return 0;
tilde_ptr = strchr(value, '~');
if (!tilde_ptr) {
pr_err("Unable to locate numerical range indicator"
" \"~\" for \"%s\".\n", param->name);
return -1;
}
*tilde_ptr = '\0';
left_val_ptr = value;
right_val_ptr = value + strlen(left_val_ptr) + 1;
if (iscsi_check_numerical_value(param, left_val_ptr) < 0)
return -1;
if (iscsi_check_numerical_value(param, right_val_ptr) < 0)
return -1;
left_val = simple_strtoul(left_val_ptr, NULL, 0);
right_val = simple_strtoul(right_val_ptr, NULL, 0);
*tilde_ptr = '~';
if (right_val < left_val) {
pr_err("Numerical range for parameter \"%s\" contains"
" a right value which is less than the left.\n",
param->name);
return -1;
}
/*
* For now, enforce reasonable defaults for [I,O]FMarkInt.
*/
tilde_ptr = strchr(param->value, '~');
if (!tilde_ptr) {
pr_err("Unable to locate numerical range indicator"
" \"~\" for \"%s\".\n", param->name);
return -1;
}
*tilde_ptr = '\0';
left_val_ptr = param->value;
right_val_ptr = param->value + strlen(left_val_ptr) + 1;
local_left_val = simple_strtoul(left_val_ptr, NULL, 0);
*tilde_ptr = '~';
if (param->set_param) {
if ((left_val < local_left_val) ||
(right_val < local_left_val)) {
pr_err("Passed value range \"%u~%u\" is below"
" minimum left value \"%u\" for key \"%s\","
" rejecting.\n", left_val, right_val,
local_left_val, param->name);
return -1;
}
} else {
if ((left_val < local_left_val) &&
(right_val < local_left_val)) {
pr_err("Received value range \"%u~%u\" is"
" below minimum left value \"%u\" for key"
" \"%s\", rejecting.\n", left_val, right_val,
local_left_val, param->name);
SET_PSTATE_REJECT(param);
if (iscsi_update_param_value(param, REJECT) < 0)
return -1;
}
}
return 0;
}
static int iscsi_check_string_or_list_value(struct iscsi_param *param, char *value) static int iscsi_check_string_or_list_value(struct iscsi_param *param, char *value)
{ {
if (IS_PSTATE_PROPOSER(param)) if (IS_PSTATE_PROPOSER(param))
@ -1027,33 +918,6 @@ static int iscsi_check_string_or_list_value(struct iscsi_param *param, char *val
return 0; return 0;
} }
/*
* This function is used to pick a value range number, currently just
* returns the lesser of both right values.
*/
static char *iscsi_get_value_from_number_range(
struct iscsi_param *param,
char *value)
{
char *end_ptr, *tilde_ptr1 = NULL, *tilde_ptr2 = NULL;
u32 acceptor_right_value, proposer_right_value;
tilde_ptr1 = strchr(value, '~');
if (!tilde_ptr1)
return NULL;
*tilde_ptr1++ = '\0';
proposer_right_value = simple_strtoul(tilde_ptr1, &end_ptr, 0);
tilde_ptr2 = strchr(param->value, '~');
if (!tilde_ptr2)
return NULL;
*tilde_ptr2++ = '\0';
acceptor_right_value = simple_strtoul(tilde_ptr2, &end_ptr, 0);
return (acceptor_right_value >= proposer_right_value) ?
tilde_ptr1 : tilde_ptr2;
}
static char *iscsi_check_valuelist_for_support( static char *iscsi_check_valuelist_for_support(
struct iscsi_param *param, struct iscsi_param *param,
char *value) char *value)
@ -1103,7 +967,7 @@ static int iscsi_check_acceptor_state(struct iscsi_param *param, char *value,
struct iscsi_conn *conn) struct iscsi_conn *conn)
{ {
u8 acceptor_boolean_value = 0, proposer_boolean_value = 0; u8 acceptor_boolean_value = 0, proposer_boolean_value = 0;
char *negoitated_value = NULL; char *negotiated_value = NULL;
if (IS_PSTATE_ACCEPTOR(param)) { if (IS_PSTATE_ACCEPTOR(param)) {
pr_err("Received key \"%s\" twice, protocol error.\n", pr_err("Received key \"%s\" twice, protocol error.\n",
@ -1203,24 +1067,16 @@ static int iscsi_check_acceptor_state(struct iscsi_param *param, char *value,
pr_debug("Updated %s to target MXDSL value: %s\n", pr_debug("Updated %s to target MXDSL value: %s\n",
param->name, param->value); param->name, param->value);
} }
} else if (IS_TYPE_NUMBER_RANGE(param)) {
negoitated_value = iscsi_get_value_from_number_range(
param, value);
if (!negoitated_value)
return -1;
if (iscsi_update_param_value(param, negoitated_value) < 0)
return -1;
} else if (IS_TYPE_VALUE_LIST(param)) { } else if (IS_TYPE_VALUE_LIST(param)) {
negoitated_value = iscsi_check_valuelist_for_support( negotiated_value = iscsi_check_valuelist_for_support(
param, value); param, value);
if (!negoitated_value) { if (!negotiated_value) {
pr_err("Proposer's value list \"%s\" contains" pr_err("Proposer's value list \"%s\" contains"
" no valid values from Acceptor's value list" " no valid values from Acceptor's value list"
" \"%s\".\n", value, param->value); " \"%s\".\n", value, param->value);
return -1; return -1;
} }
if (iscsi_update_param_value(param, negoitated_value) < 0) if (iscsi_update_param_value(param, negotiated_value) < 0)
return -1; return -1;
} else if (IS_PHASE_DECLARATIVE(param)) { } else if (IS_PHASE_DECLARATIVE(param)) {
if (iscsi_update_param_value(param, value) < 0) if (iscsi_update_param_value(param, value) < 0)
@ -1239,47 +1095,7 @@ static int iscsi_check_proposer_state(struct iscsi_param *param, char *value)
return -1; return -1;
} }
if (IS_TYPE_NUMBER_RANGE(param)) { if (IS_TYPE_VALUE_LIST(param)) {
u32 left_val = 0, right_val = 0, recieved_value = 0;
char *left_val_ptr = NULL, *right_val_ptr = NULL;
char *tilde_ptr = NULL;
if (!strcmp(value, IRRELEVANT) || !strcmp(value, REJECT)) {
if (iscsi_update_param_value(param, value) < 0)
return -1;
return 0;
}
tilde_ptr = strchr(value, '~');
if (tilde_ptr) {
pr_err("Illegal \"~\" in response for \"%s\".\n",
param->name);
return -1;
}
tilde_ptr = strchr(param->value, '~');
if (!tilde_ptr) {
pr_err("Unable to locate numerical range"
" indicator \"~\" for \"%s\".\n", param->name);
return -1;
}
*tilde_ptr = '\0';
left_val_ptr = param->value;
right_val_ptr = param->value + strlen(left_val_ptr) + 1;
left_val = simple_strtoul(left_val_ptr, NULL, 0);
right_val = simple_strtoul(right_val_ptr, NULL, 0);
recieved_value = simple_strtoul(value, NULL, 0);
*tilde_ptr = '~';
if ((recieved_value < left_val) ||
(recieved_value > right_val)) {
pr_err("Illegal response \"%s=%u\", value must"
" be between %u and %u.\n", param->name,
recieved_value, left_val, right_val);
return -1;
}
} else if (IS_TYPE_VALUE_LIST(param)) {
char *comma_ptr = NULL, *tmp_ptr = NULL; char *comma_ptr = NULL, *tmp_ptr = NULL;
comma_ptr = strchr(value, ','); comma_ptr = strchr(value, ',');
@ -1361,9 +1177,6 @@ static int iscsi_check_value(struct iscsi_param *param, char *value)
} else if (IS_TYPE_NUMBER(param)) { } else if (IS_TYPE_NUMBER(param)) {
if (iscsi_check_numerical_value(param, value) < 0) if (iscsi_check_numerical_value(param, value) < 0)
return -1; return -1;
} else if (IS_TYPE_NUMBER_RANGE(param)) {
if (iscsi_check_numerical_range_value(param, value) < 0)
return -1;
} else if (IS_TYPE_STRING(param) || IS_TYPE_VALUE_LIST(param)) { } else if (IS_TYPE_STRING(param) || IS_TYPE_VALUE_LIST(param)) {
if (iscsi_check_string_or_list_value(param, value) < 0) if (iscsi_check_string_or_list_value(param, value) < 0)
return -1; return -1;
@ -1483,8 +1296,6 @@ static int iscsi_enforce_integrity_rules(
char *tmpptr; char *tmpptr;
u8 DataSequenceInOrder = 0; u8 DataSequenceInOrder = 0;
u8 ErrorRecoveryLevel = 0, SessionType = 0; u8 ErrorRecoveryLevel = 0, SessionType = 0;
u8 IFMarker = 0, OFMarker = 0;
u8 IFMarkInt_Reject = 1, OFMarkInt_Reject = 1;
u32 FirstBurstLength = 0, MaxBurstLength = 0; u32 FirstBurstLength = 0, MaxBurstLength = 0;
struct iscsi_param *param = NULL; struct iscsi_param *param = NULL;
@ -1503,28 +1314,12 @@ static int iscsi_enforce_integrity_rules(
if (!strcmp(param->name, MAXBURSTLENGTH)) if (!strcmp(param->name, MAXBURSTLENGTH))
MaxBurstLength = simple_strtoul(param->value, MaxBurstLength = simple_strtoul(param->value,
&tmpptr, 0); &tmpptr, 0);
if (!strcmp(param->name, IFMARKER))
if (!strcmp(param->value, YES))
IFMarker = 1;
if (!strcmp(param->name, OFMARKER))
if (!strcmp(param->value, YES))
OFMarker = 1;
if (!strcmp(param->name, IFMARKINT))
if (!strcmp(param->value, REJECT))
IFMarkInt_Reject = 1;
if (!strcmp(param->name, OFMARKINT))
if (!strcmp(param->value, REJECT))
OFMarkInt_Reject = 1;
} }
list_for_each_entry(param, &param_list->param_list, p_list) { list_for_each_entry(param, &param_list->param_list, p_list) {
if (!(param->phase & phase)) if (!(param->phase & phase))
continue; continue;
if (!SessionType && (!IS_PSTATE_ACCEPTOR(param) && if (!SessionType && !IS_PSTATE_ACCEPTOR(param))
(strcmp(param->name, IFMARKER) &&
strcmp(param->name, OFMARKER) &&
strcmp(param->name, IFMARKINT) &&
strcmp(param->name, OFMARKINT))))
continue; continue;
if (!strcmp(param->name, MAXOUTSTANDINGR2T) && if (!strcmp(param->name, MAXOUTSTANDINGR2T) &&
DataSequenceInOrder && (ErrorRecoveryLevel > 0)) { DataSequenceInOrder && (ErrorRecoveryLevel > 0)) {
@ -1556,38 +1351,6 @@ static int iscsi_enforce_integrity_rules(
param->name, param->value); param->name, param->value);
} }
} }
if (!strcmp(param->name, IFMARKER) && IFMarkInt_Reject) {
if (iscsi_update_param_value(param, NO) < 0)
return -1;
IFMarker = 0;
pr_debug("Reset \"%s\" to \"%s\".\n",
param->name, param->value);
}
if (!strcmp(param->name, OFMARKER) && OFMarkInt_Reject) {
if (iscsi_update_param_value(param, NO) < 0)
return -1;
OFMarker = 0;
pr_debug("Reset \"%s\" to \"%s\".\n",
param->name, param->value);
}
if (!strcmp(param->name, IFMARKINT) && !IFMarker) {
if (!strcmp(param->value, REJECT))
continue;
param->state &= ~PSTATE_NEGOTIATE;
if (iscsi_update_param_value(param, IRRELEVANT) < 0)
return -1;
pr_debug("Reset \"%s\" to \"%s\".\n",
param->name, param->value);
}
if (!strcmp(param->name, OFMARKINT) && !OFMarker) {
if (!strcmp(param->value, REJECT))
continue;
param->state &= ~PSTATE_NEGOTIATE;
if (iscsi_update_param_value(param, IRRELEVANT) < 0)
return -1;
pr_debug("Reset \"%s\" to \"%s\".\n",
param->name, param->value);
}
} }
return 0; return 0;
@ -1824,24 +1587,6 @@ void iscsi_set_connection_parameters(
*/ */
pr_debug("MaxRecvDataSegmentLength: %u\n", pr_debug("MaxRecvDataSegmentLength: %u\n",
ops->MaxRecvDataSegmentLength); ops->MaxRecvDataSegmentLength);
} else if (!strcmp(param->name, OFMARKER)) {
ops->OFMarker = !strcmp(param->value, YES);
pr_debug("OFMarker: %s\n",
param->value);
} else if (!strcmp(param->name, IFMARKER)) {
ops->IFMarker = !strcmp(param->value, YES);
pr_debug("IFMarker: %s\n",
param->value);
} else if (!strcmp(param->name, OFMARKINT)) {
ops->OFMarkInt =
simple_strtoul(param->value, &tmpptr, 0);
pr_debug("OFMarkInt: %s\n",
param->value);
} else if (!strcmp(param->name, IFMARKINT)) {
ops->IFMarkInt =
simple_strtoul(param->value, &tmpptr, 0);
pr_debug("IFMarkInt: %s\n",
param->value);
} else if (!strcmp(param->name, INITIATORRECVDATASEGMENTLENGTH)) { } else if (!strcmp(param->name, INITIATORRECVDATASEGMENTLENGTH)) {
ops->InitiatorRecvDataSegmentLength = ops->InitiatorRecvDataSegmentLength =
simple_strtoul(param->value, &tmpptr, 0); simple_strtoul(param->value, &tmpptr, 0);

View File

@ -138,8 +138,8 @@ extern void iscsi_set_session_parameters(struct iscsi_sess_ops *,
#define INITIAL_SESSIONTYPE NORMAL #define INITIAL_SESSIONTYPE NORMAL
#define INITIAL_IFMARKER NO #define INITIAL_IFMARKER NO
#define INITIAL_OFMARKER NO #define INITIAL_OFMARKER NO
#define INITIAL_IFMARKINT "2048~65535" #define INITIAL_IFMARKINT REJECT
#define INITIAL_OFMARKINT "2048~65535" #define INITIAL_OFMARKINT REJECT
/* /*
* Initial values for iSER parameters following RFC-5046 Section 6 * Initial values for iSER parameters following RFC-5046 Section 6
@ -239,10 +239,9 @@ extern void iscsi_set_session_parameters(struct iscsi_sess_ops *,
#define TYPERANGE_AUTH 0x0200 #define TYPERANGE_AUTH 0x0200
#define TYPERANGE_DIGEST 0x0400 #define TYPERANGE_DIGEST 0x0400
#define TYPERANGE_ISCSINAME 0x0800 #define TYPERANGE_ISCSINAME 0x0800
#define TYPERANGE_MARKINT 0x1000 #define TYPERANGE_SESSIONTYPE 0x1000
#define TYPERANGE_SESSIONTYPE 0x2000 #define TYPERANGE_TARGETADDRESS 0x2000
#define TYPERANGE_TARGETADDRESS 0x4000 #define TYPERANGE_UTF8 0x4000
#define TYPERANGE_UTF8 0x8000
#define IS_TYPERANGE_0_TO_2(p) ((p)->type_range & TYPERANGE_0_TO_2) #define IS_TYPERANGE_0_TO_2(p) ((p)->type_range & TYPERANGE_0_TO_2)
#define IS_TYPERANGE_0_TO_3600(p) ((p)->type_range & TYPERANGE_0_TO_3600) #define IS_TYPERANGE_0_TO_3600(p) ((p)->type_range & TYPERANGE_0_TO_3600)

View File

@ -120,7 +120,7 @@ u8 iscsit_tmr_task_reassign(
struct iscsi_tmr_req *tmr_req = cmd->tmr_req; struct iscsi_tmr_req *tmr_req = cmd->tmr_req;
struct se_tmr_req *se_tmr = cmd->se_cmd.se_tmr_req; struct se_tmr_req *se_tmr = cmd->se_cmd.se_tmr_req;
struct iscsi_tm *hdr = (struct iscsi_tm *) buf; struct iscsi_tm *hdr = (struct iscsi_tm *) buf;
int ret, ref_lun; u64 ret, ref_lun;
pr_debug("Got TASK_REASSIGN TMR ITT: 0x%08x," pr_debug("Got TASK_REASSIGN TMR ITT: 0x%08x,"
" RefTaskTag: 0x%08x, ExpDataSN: 0x%08x, CID: %hu\n", " RefTaskTag: 0x%08x, ExpDataSN: 0x%08x, CID: %hu\n",
@ -164,7 +164,7 @@ u8 iscsit_tmr_task_reassign(
ref_lun = scsilun_to_int(&hdr->lun); ref_lun = scsilun_to_int(&hdr->lun);
if (ref_lun != ref_cmd->se_cmd.orig_fe_lun) { if (ref_lun != ref_cmd->se_cmd.orig_fe_lun) {
pr_err("Unable to perform connection recovery for" pr_err("Unable to perform connection recovery for"
" differing ref_lun: %d ref_cmd orig_fe_lun: %u\n", " differing ref_lun: %llu ref_cmd orig_fe_lun: %llu\n",
ref_lun, ref_cmd->se_cmd.orig_fe_lun); ref_lun, ref_cmd->se_cmd.orig_fe_lun);
return ISCSI_TMF_RSP_REJECTED; return ISCSI_TMF_RSP_REJECTED;
} }

View File

@ -18,7 +18,6 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
#include <target/iscsi/iscsi_target_core.h> #include <target/iscsi/iscsi_target_core.h>
#include "iscsi_target_erl0.h" #include "iscsi_target_erl0.h"
@ -67,9 +66,12 @@ int iscsit_load_discovery_tpg(void)
pr_err("Unable to allocate struct iscsi_portal_group\n"); pr_err("Unable to allocate struct iscsi_portal_group\n");
return -1; return -1;
} }
/*
ret = core_tpg_register(&iscsi_ops, NULL, &tpg->tpg_se_tpg, * Save iscsi_ops pointer for special case discovery TPG that
tpg, TRANSPORT_TPG_TYPE_DISCOVERY); * doesn't exist as se_wwn->wwn_group within configfs.
*/
tpg->tpg_se_tpg.se_tpg_tfo = &iscsi_ops;
ret = core_tpg_register(NULL, &tpg->tpg_se_tpg, -1);
if (ret < 0) { if (ret < 0) {
kfree(tpg); kfree(tpg);
return -1; return -1;
@ -280,8 +282,6 @@ int iscsit_tpg_del_portal_group(
return -EPERM; return -EPERM;
} }
core_tpg_clear_object_luns(&tpg->tpg_se_tpg);
if (tpg->param_list) { if (tpg->param_list) {
iscsi_release_param_list(tpg->param_list); iscsi_release_param_list(tpg->param_list);
tpg->param_list = NULL; tpg->param_list = NULL;

View File

@ -22,7 +22,6 @@
#include <scsi/iscsi_proto.h> #include <scsi/iscsi_proto.h>
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
#include <target/iscsi/iscsi_transport.h> #include <target/iscsi/iscsi_transport.h>
#include <target/iscsi/iscsi_target_core.h> #include <target/iscsi/iscsi_target_core.h>
@ -746,7 +745,7 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd, bool shutdown)
rc = transport_generic_free_cmd(&cmd->se_cmd, shutdown); rc = transport_generic_free_cmd(&cmd->se_cmd, shutdown);
if (!rc && shutdown && se_cmd && se_cmd->se_sess) { if (!rc && shutdown && se_cmd && se_cmd->se_sess) {
__iscsit_free_cmd(cmd, true, shutdown); __iscsit_free_cmd(cmd, true, shutdown);
target_put_sess_cmd(se_cmd->se_sess, se_cmd); target_put_sess_cmd(se_cmd);
} }
break; break;
case ISCSI_OP_REJECT: case ISCSI_OP_REJECT:
@ -762,7 +761,7 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd, bool shutdown)
rc = transport_generic_free_cmd(&cmd->se_cmd, shutdown); rc = transport_generic_free_cmd(&cmd->se_cmd, shutdown);
if (!rc && shutdown && se_cmd->se_sess) { if (!rc && shutdown && se_cmd->se_sess) {
__iscsit_free_cmd(cmd, true, shutdown); __iscsit_free_cmd(cmd, true, shutdown);
target_put_sess_cmd(se_cmd->se_sess, se_cmd); target_put_sess_cmd(se_cmd);
} }
break; break;
} }
@ -809,54 +808,6 @@ void iscsit_inc_session_usage_count(struct iscsi_session *sess)
spin_unlock_bh(&sess->session_usage_lock); spin_unlock_bh(&sess->session_usage_lock);
} }
/*
* Setup conn->if_marker and conn->of_marker values based upon
* the initial marker-less interval. (see iSCSI v19 A.2)
*/
int iscsit_set_sync_and_steering_values(struct iscsi_conn *conn)
{
int login_ifmarker_count = 0, login_ofmarker_count = 0, next_marker = 0;
/*
* IFMarkInt and OFMarkInt are negotiated as 32-bit words.
*/
u32 IFMarkInt = (conn->conn_ops->IFMarkInt * 4);
u32 OFMarkInt = (conn->conn_ops->OFMarkInt * 4);
if (conn->conn_ops->OFMarker) {
/*
* Account for the first Login Command received not
* via iscsi_recv_msg().
*/
conn->of_marker += ISCSI_HDR_LEN;
if (conn->of_marker <= OFMarkInt) {
conn->of_marker = (OFMarkInt - conn->of_marker);
} else {
login_ofmarker_count = (conn->of_marker / OFMarkInt);
next_marker = (OFMarkInt * (login_ofmarker_count + 1)) +
(login_ofmarker_count * MARKER_SIZE);
conn->of_marker = (next_marker - conn->of_marker);
}
conn->of_marker_offset = 0;
pr_debug("Setting OFMarker value to %u based on Initial"
" Markerless Interval.\n", conn->of_marker);
}
if (conn->conn_ops->IFMarker) {
if (conn->if_marker <= IFMarkInt) {
conn->if_marker = (IFMarkInt - conn->if_marker);
} else {
login_ifmarker_count = (conn->if_marker / IFMarkInt);
next_marker = (IFMarkInt * (login_ifmarker_count + 1)) +
(login_ifmarker_count * MARKER_SIZE);
conn->if_marker = (next_marker - conn->if_marker);
}
pr_debug("Setting IFMarker value to %u based on Initial"
" Markerless Interval.\n", conn->if_marker);
}
return 0;
}
struct iscsi_conn *iscsit_get_conn_from_cid(struct iscsi_session *sess, u16 cid) struct iscsi_conn *iscsit_get_conn_from_cid(struct iscsi_session *sess, u16 cid)
{ {
struct iscsi_conn *conn; struct iscsi_conn *conn;

View File

@ -34,7 +34,6 @@ extern void iscsit_free_cmd(struct iscsi_cmd *, bool);
extern int iscsit_check_session_usage_count(struct iscsi_session *); extern int iscsit_check_session_usage_count(struct iscsi_session *);
extern void iscsit_dec_session_usage_count(struct iscsi_session *); extern void iscsit_dec_session_usage_count(struct iscsi_session *);
extern void iscsit_inc_session_usage_count(struct iscsi_session *); extern void iscsit_inc_session_usage_count(struct iscsi_session *);
extern int iscsit_set_sync_and_steering_values(struct iscsi_conn *);
extern struct iscsi_conn *iscsit_get_conn_from_cid(struct iscsi_session *, u16); extern struct iscsi_conn *iscsit_get_conn_from_cid(struct iscsi_session *, u16);
extern struct iscsi_conn *iscsit_get_conn_from_cid_rcfr(struct iscsi_session *, u16); extern struct iscsi_conn *iscsit_get_conn_from_cid_rcfr(struct iscsi_session *, u16);
extern void iscsit_check_conn_usage_count(struct iscsi_conn *); extern void iscsit_check_conn_usage_count(struct iscsi_conn *);

View File

@ -35,14 +35,11 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/target_core_fabric_configfs.h> #include <target/target_core_fabric_configfs.h>
#include <target/target_core_configfs.h>
#include "tcm_loop.h" #include "tcm_loop.h"
#define to_tcm_loop_hba(hba) container_of(hba, struct tcm_loop_hba, dev) #define to_tcm_loop_hba(hba) container_of(hba, struct tcm_loop_hba, dev)
static const struct target_core_fabric_ops loop_ops;
static struct workqueue_struct *tcm_loop_workqueue; static struct workqueue_struct *tcm_loop_workqueue;
static struct kmem_cache *tcm_loop_cmd_cache; static struct kmem_cache *tcm_loop_cmd_cache;
@ -165,6 +162,7 @@ static void tcm_loop_submission_work(struct work_struct *work)
transfer_length = scsi_bufflen(sc); transfer_length = scsi_bufflen(sc);
} }
se_cmd->tag = tl_cmd->sc_cmd_tag;
rc = target_submit_cmd_map_sgls(se_cmd, tl_nexus->se_sess, sc->cmnd, rc = target_submit_cmd_map_sgls(se_cmd, tl_nexus->se_sess, sc->cmnd,
&tl_cmd->tl_sense_buf[0], tl_cmd->sc->device->lun, &tl_cmd->tl_sense_buf[0], tl_cmd->sc->device->lun,
transfer_length, TCM_SIMPLE_TAG, transfer_length, TCM_SIMPLE_TAG,
@ -217,7 +215,7 @@ static int tcm_loop_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc)
* to struct scsi_device * to struct scsi_device
*/ */
static int tcm_loop_issue_tmr(struct tcm_loop_tpg *tl_tpg, static int tcm_loop_issue_tmr(struct tcm_loop_tpg *tl_tpg,
int lun, int task, enum tcm_tmreq_table tmr) u64 lun, int task, enum tcm_tmreq_table tmr)
{ {
struct se_cmd *se_cmd = NULL; struct se_cmd *se_cmd = NULL;
struct se_session *se_sess; struct se_session *se_sess;
@ -409,7 +407,7 @@ static int tcm_loop_driver_probe(struct device *dev)
sh->max_id = 2; sh->max_id = 2;
sh->max_lun = 0; sh->max_lun = 0;
sh->max_channel = 0; sh->max_channel = 0;
sh->max_cmd_len = TL_SCSI_MAX_CMD_LEN; sh->max_cmd_len = SCSI_MAX_VARLEN_CDB_SIZE;
host_prot = SHOST_DIF_TYPE1_PROTECTION | SHOST_DIF_TYPE2_PROTECTION | host_prot = SHOST_DIF_TYPE1_PROTECTION | SHOST_DIF_TYPE2_PROTECTION |
SHOST_DIF_TYPE3_PROTECTION | SHOST_DIX_TYPE1_PROTECTION | SHOST_DIF_TYPE3_PROTECTION | SHOST_DIX_TYPE1_PROTECTION |
@ -520,147 +518,26 @@ static char *tcm_loop_get_fabric_name(void)
return "loopback"; return "loopback";
} }
static u8 tcm_loop_get_fabric_proto_ident(struct se_portal_group *se_tpg) static inline struct tcm_loop_tpg *tl_tpg(struct se_portal_group *se_tpg)
{ {
struct tcm_loop_tpg *tl_tpg = se_tpg->se_tpg_fabric_ptr; return container_of(se_tpg, struct tcm_loop_tpg, tl_se_tpg);
struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
/*
* tl_proto_id is set at tcm_loop_configfs.c:tcm_loop_make_scsi_hba()
* time based on the protocol dependent prefix of the passed configfs group.
*
* Based upon tl_proto_id, TCM_Loop emulates the requested fabric
* ProtocolID using target_core_fabric_lib.c symbols.
*/
switch (tl_hba->tl_proto_id) {
case SCSI_PROTOCOL_SAS:
return sas_get_fabric_proto_ident(se_tpg);
case SCSI_PROTOCOL_FCP:
return fc_get_fabric_proto_ident(se_tpg);
case SCSI_PROTOCOL_ISCSI:
return iscsi_get_fabric_proto_ident(se_tpg);
default:
pr_err("Unknown tl_proto_id: 0x%02x, using"
" SAS emulation\n", tl_hba->tl_proto_id);
break;
}
return sas_get_fabric_proto_ident(se_tpg);
} }
static char *tcm_loop_get_endpoint_wwn(struct se_portal_group *se_tpg) static char *tcm_loop_get_endpoint_wwn(struct se_portal_group *se_tpg)
{ {
struct tcm_loop_tpg *tl_tpg = se_tpg->se_tpg_fabric_ptr;
/* /*
* Return the passed NAA identifier for the SAS Target Port * Return the passed NAA identifier for the SAS Target Port
*/ */
return &tl_tpg->tl_hba->tl_wwn_address[0]; return &tl_tpg(se_tpg)->tl_hba->tl_wwn_address[0];
} }
static u16 tcm_loop_get_tag(struct se_portal_group *se_tpg) static u16 tcm_loop_get_tag(struct se_portal_group *se_tpg)
{ {
struct tcm_loop_tpg *tl_tpg = se_tpg->se_tpg_fabric_ptr;
/* /*
* This Tag is used when forming SCSI Name identifier in EVPD=1 0x83 * This Tag is used when forming SCSI Name identifier in EVPD=1 0x83
* to represent the SCSI Target Port. * to represent the SCSI Target Port.
*/ */
return tl_tpg->tl_tpgt; return tl_tpg(se_tpg)->tl_tpgt;
}
static u32 tcm_loop_get_default_depth(struct se_portal_group *se_tpg)
{
return 1;
}
static u32 tcm_loop_get_pr_transport_id(
struct se_portal_group *se_tpg,
struct se_node_acl *se_nacl,
struct t10_pr_registration *pr_reg,
int *format_code,
unsigned char *buf)
{
struct tcm_loop_tpg *tl_tpg = se_tpg->se_tpg_fabric_ptr;
struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
switch (tl_hba->tl_proto_id) {
case SCSI_PROTOCOL_SAS:
return sas_get_pr_transport_id(se_tpg, se_nacl, pr_reg,
format_code, buf);
case SCSI_PROTOCOL_FCP:
return fc_get_pr_transport_id(se_tpg, se_nacl, pr_reg,
format_code, buf);
case SCSI_PROTOCOL_ISCSI:
return iscsi_get_pr_transport_id(se_tpg, se_nacl, pr_reg,
format_code, buf);
default:
pr_err("Unknown tl_proto_id: 0x%02x, using"
" SAS emulation\n", tl_hba->tl_proto_id);
break;
}
return sas_get_pr_transport_id(se_tpg, se_nacl, pr_reg,
format_code, buf);
}
static u32 tcm_loop_get_pr_transport_id_len(
struct se_portal_group *se_tpg,
struct se_node_acl *se_nacl,
struct t10_pr_registration *pr_reg,
int *format_code)
{
struct tcm_loop_tpg *tl_tpg = se_tpg->se_tpg_fabric_ptr;
struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
switch (tl_hba->tl_proto_id) {
case SCSI_PROTOCOL_SAS:
return sas_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,
format_code);
case SCSI_PROTOCOL_FCP:
return fc_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,
format_code);
case SCSI_PROTOCOL_ISCSI:
return iscsi_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,
format_code);
default:
pr_err("Unknown tl_proto_id: 0x%02x, using"
" SAS emulation\n", tl_hba->tl_proto_id);
break;
}
return sas_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,
format_code);
}
/*
* Used for handling SCSI fabric dependent TransportIDs in SPC-3 and above
* Persistent Reservation SPEC_I_PT=1 and PROUT REGISTER_AND_MOVE operations.
*/
static char *tcm_loop_parse_pr_out_transport_id(
struct se_portal_group *se_tpg,
const char *buf,
u32 *out_tid_len,
char **port_nexus_ptr)
{
struct tcm_loop_tpg *tl_tpg = se_tpg->se_tpg_fabric_ptr;
struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
switch (tl_hba->tl_proto_id) {
case SCSI_PROTOCOL_SAS:
return sas_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,
port_nexus_ptr);
case SCSI_PROTOCOL_FCP:
return fc_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,
port_nexus_ptr);
case SCSI_PROTOCOL_ISCSI:
return iscsi_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,
port_nexus_ptr);
default:
pr_err("Unknown tl_proto_id: 0x%02x, using"
" SAS emulation\n", tl_hba->tl_proto_id);
break;
}
return sas_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,
port_nexus_ptr);
} }
/* /*
@ -703,30 +580,6 @@ static int tcm_loop_check_prot_fabric_only(struct se_portal_group *se_tpg)
return tl_tpg->tl_fabric_prot_type; return tl_tpg->tl_fabric_prot_type;
} }
static struct se_node_acl *tcm_loop_tpg_alloc_fabric_acl(
struct se_portal_group *se_tpg)
{
struct tcm_loop_nacl *tl_nacl;
tl_nacl = kzalloc(sizeof(struct tcm_loop_nacl), GFP_KERNEL);
if (!tl_nacl) {
pr_err("Unable to allocate struct tcm_loop_nacl\n");
return NULL;
}
return &tl_nacl->se_node_acl;
}
static void tcm_loop_tpg_release_fabric_acl(
struct se_portal_group *se_tpg,
struct se_node_acl *se_nacl)
{
struct tcm_loop_nacl *tl_nacl = container_of(se_nacl,
struct tcm_loop_nacl, se_node_acl);
kfree(tl_nacl);
}
static u32 tcm_loop_get_inst_index(struct se_portal_group *se_tpg) static u32 tcm_loop_get_inst_index(struct se_portal_group *se_tpg)
{ {
return 1; return 1;
@ -742,14 +595,6 @@ static void tcm_loop_set_default_node_attributes(struct se_node_acl *se_acl)
return; return;
} }
static u32 tcm_loop_get_task_tag(struct se_cmd *se_cmd)
{
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) static int tcm_loop_get_cmd_state(struct se_cmd *se_cmd)
{ {
struct tcm_loop_cmd *tl_cmd = container_of(se_cmd, struct tcm_loop_cmd *tl_cmd = container_of(se_cmd,
@ -902,7 +747,7 @@ static void tcm_loop_port_unlink(
se_lun->unpacked_lun); se_lun->unpacked_lun);
if (!sd) { if (!sd) {
pr_err("Unable to locate struct scsi_device for %d:%d:" pr_err("Unable to locate struct scsi_device for %d:%d:"
"%d\n", 0, tl_tpg->tl_tpgt, se_lun->unpacked_lun); "%llu\n", 0, tl_tpg->tl_tpgt, se_lun->unpacked_lun);
return; return;
} }
/* /*
@ -1234,8 +1079,7 @@ static struct se_portal_group *tcm_loop_make_naa_tpg(
/* /*
* Register the tl_tpg as a emulated SAS TCM Target Endpoint * Register the tl_tpg as a emulated SAS TCM Target Endpoint
*/ */
ret = core_tpg_register(&loop_ops, wwn, &tl_tpg->tl_se_tpg, tl_tpg, ret = core_tpg_register(wwn, &tl_tpg->tl_se_tpg, tl_hba->tl_proto_id);
TRANSPORT_TPG_TYPE_NORMAL);
if (ret < 0) if (ret < 0)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
@ -1386,13 +1230,8 @@ static const struct target_core_fabric_ops loop_ops = {
.module = THIS_MODULE, .module = THIS_MODULE,
.name = "loopback", .name = "loopback",
.get_fabric_name = tcm_loop_get_fabric_name, .get_fabric_name = tcm_loop_get_fabric_name,
.get_fabric_proto_ident = tcm_loop_get_fabric_proto_ident,
.tpg_get_wwn = tcm_loop_get_endpoint_wwn, .tpg_get_wwn = tcm_loop_get_endpoint_wwn,
.tpg_get_tag = tcm_loop_get_tag, .tpg_get_tag = tcm_loop_get_tag,
.tpg_get_default_depth = tcm_loop_get_default_depth,
.tpg_get_pr_transport_id = tcm_loop_get_pr_transport_id,
.tpg_get_pr_transport_id_len = tcm_loop_get_pr_transport_id_len,
.tpg_parse_pr_out_transport_id = tcm_loop_parse_pr_out_transport_id,
.tpg_check_demo_mode = tcm_loop_check_demo_mode, .tpg_check_demo_mode = tcm_loop_check_demo_mode,
.tpg_check_demo_mode_cache = tcm_loop_check_demo_mode_cache, .tpg_check_demo_mode_cache = tcm_loop_check_demo_mode_cache,
.tpg_check_demo_mode_write_protect = .tpg_check_demo_mode_write_protect =
@ -1400,8 +1239,6 @@ static const struct target_core_fabric_ops loop_ops = {
.tpg_check_prod_mode_write_protect = .tpg_check_prod_mode_write_protect =
tcm_loop_check_prod_mode_write_protect, tcm_loop_check_prod_mode_write_protect,
.tpg_check_prot_fabric_only = tcm_loop_check_prot_fabric_only, .tpg_check_prot_fabric_only = tcm_loop_check_prot_fabric_only,
.tpg_alloc_fabric_acl = tcm_loop_tpg_alloc_fabric_acl,
.tpg_release_fabric_acl = tcm_loop_tpg_release_fabric_acl,
.tpg_get_inst_index = tcm_loop_get_inst_index, .tpg_get_inst_index = tcm_loop_get_inst_index,
.check_stop_free = tcm_loop_check_stop_free, .check_stop_free = tcm_loop_check_stop_free,
.release_cmd = tcm_loop_release_cmd, .release_cmd = tcm_loop_release_cmd,
@ -1411,7 +1248,6 @@ static const struct target_core_fabric_ops loop_ops = {
.write_pending = tcm_loop_write_pending, .write_pending = tcm_loop_write_pending,
.write_pending_status = tcm_loop_write_pending_status, .write_pending_status = tcm_loop_write_pending_status,
.set_default_node_attributes = tcm_loop_set_default_node_attributes, .set_default_node_attributes = tcm_loop_set_default_node_attributes,
.get_task_tag = tcm_loop_get_task_tag,
.get_cmd_state = tcm_loop_get_cmd_state, .get_cmd_state = tcm_loop_get_cmd_state,
.queue_data_in = tcm_loop_queue_data_in, .queue_data_in = tcm_loop_queue_data_in,
.queue_status = tcm_loop_queue_status, .queue_status = tcm_loop_queue_status,

View File

@ -2,11 +2,6 @@
#define TL_WWN_ADDR_LEN 256 #define TL_WWN_ADDR_LEN 256
#define TL_TPGS_PER_HBA 32 #define TL_TPGS_PER_HBA 32
/*
* Used in tcm_loop_driver_probe() for struct Scsi_Host->max_cmd_len
*/
#define TL_SCSI_MAX_CMD_LEN 32
struct tcm_loop_cmd { struct tcm_loop_cmd {
/* State of Linux/SCSI CDB+Data descriptor */ /* State of Linux/SCSI CDB+Data descriptor */
u32 sc_cmd_state; u32 sc_cmd_state;
@ -33,10 +28,6 @@ struct tcm_loop_nexus {
struct se_session *se_sess; struct se_session *se_sess;
}; };
struct tcm_loop_nacl {
struct se_node_acl se_node_acl;
};
#define TCM_TRANSPORT_ONLINE 0 #define TCM_TRANSPORT_ONLINE 0
#define TCM_TRANSPORT_OFFLINE 1 #define TCM_TRANSPORT_OFFLINE 1

View File

@ -36,7 +36,6 @@
#include <target/target_core_backend.h> #include <target/target_core_backend.h>
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/target_core_fabric_configfs.h> #include <target/target_core_fabric_configfs.h>
#include <target/target_core_configfs.h>
#include <target/configfs_macros.h> #include <target/configfs_macros.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
@ -109,13 +108,13 @@ static struct sbp_session *sbp_session_find_by_guid(
} }
static struct sbp_login_descriptor *sbp_login_find_by_lun( static struct sbp_login_descriptor *sbp_login_find_by_lun(
struct sbp_session *session, struct se_lun *lun) struct sbp_session *session, u32 unpacked_lun)
{ {
struct sbp_login_descriptor *login, *found = NULL; struct sbp_login_descriptor *login, *found = NULL;
spin_lock_bh(&session->lock); spin_lock_bh(&session->lock);
list_for_each_entry(login, &session->login_list, link) { list_for_each_entry(login, &session->login_list, link) {
if (login->lun == lun) if (login->login_lun == unpacked_lun)
found = login; found = login;
} }
spin_unlock_bh(&session->lock); spin_unlock_bh(&session->lock);
@ -125,7 +124,7 @@ static struct sbp_login_descriptor *sbp_login_find_by_lun(
static int sbp_login_count_all_by_lun( static int sbp_login_count_all_by_lun(
struct sbp_tpg *tpg, struct sbp_tpg *tpg,
struct se_lun *lun, u32 unpacked_lun,
int exclusive) int exclusive)
{ {
struct se_session *se_sess; struct se_session *se_sess;
@ -139,7 +138,7 @@ static int sbp_login_count_all_by_lun(
spin_lock_bh(&sess->lock); spin_lock_bh(&sess->lock);
list_for_each_entry(login, &sess->login_list, link) { list_for_each_entry(login, &sess->login_list, link) {
if (login->lun != lun) if (login->login_lun != unpacked_lun)
continue; continue;
if (!exclusive || login->exclusive) if (!exclusive || login->exclusive)
@ -175,23 +174,23 @@ static struct sbp_login_descriptor *sbp_login_find_by_id(
return found; return found;
} }
static struct se_lun *sbp_get_lun_from_tpg(struct sbp_tpg *tpg, int lun) static u32 sbp_get_lun_from_tpg(struct sbp_tpg *tpg, u32 login_lun, int *err)
{ {
struct se_portal_group *se_tpg = &tpg->se_tpg; struct se_portal_group *se_tpg = &tpg->se_tpg;
struct se_lun *se_lun; struct se_lun *se_lun;
if (lun >= TRANSPORT_MAX_LUNS_PER_TPG) rcu_read_lock();
return ERR_PTR(-EINVAL); hlist_for_each_entry_rcu(se_lun, &se_tpg->tpg_lun_hlist, link) {
if (se_lun->unpacked_lun == login_lun) {
rcu_read_unlock();
*err = 0;
return login_lun;
}
}
rcu_read_unlock();
spin_lock(&se_tpg->tpg_lun_lock); *err = -ENODEV;
se_lun = se_tpg->tpg_lun_list[lun]; return login_lun;
if (se_lun->lun_status != TRANSPORT_LUN_STATUS_ACTIVE)
se_lun = ERR_PTR(-ENODEV);
spin_unlock(&se_tpg->tpg_lun_lock);
return se_lun;
} }
static struct sbp_session *sbp_session_create( static struct sbp_session *sbp_session_create(
@ -295,17 +294,16 @@ static void sbp_management_request_login(
{ {
struct sbp_tport *tport = agent->tport; struct sbp_tport *tport = agent->tport;
struct sbp_tpg *tpg = tport->tpg; struct sbp_tpg *tpg = tport->tpg;
struct se_lun *se_lun;
int ret;
u64 guid;
struct sbp_session *sess; struct sbp_session *sess;
struct sbp_login_descriptor *login; struct sbp_login_descriptor *login;
struct sbp_login_response_block *response; struct sbp_login_response_block *response;
int login_response_len; u64 guid;
u32 unpacked_lun;
int login_response_len, ret;
se_lun = sbp_get_lun_from_tpg(tpg, unpacked_lun = sbp_get_lun_from_tpg(tpg,
LOGIN_ORB_LUN(be32_to_cpu(req->orb.misc))); LOGIN_ORB_LUN(be32_to_cpu(req->orb.misc)), &ret);
if (IS_ERR(se_lun)) { if (ret) {
pr_notice("login to unknown LUN: %d\n", pr_notice("login to unknown LUN: %d\n",
LOGIN_ORB_LUN(be32_to_cpu(req->orb.misc))); LOGIN_ORB_LUN(be32_to_cpu(req->orb.misc)));
@ -326,11 +324,11 @@ static void sbp_management_request_login(
} }
pr_notice("mgt_agent LOGIN to LUN %d from %016llx\n", pr_notice("mgt_agent LOGIN to LUN %d from %016llx\n",
se_lun->unpacked_lun, guid); unpacked_lun, guid);
sess = sbp_session_find_by_guid(tpg, guid); sess = sbp_session_find_by_guid(tpg, guid);
if (sess) { if (sess) {
login = sbp_login_find_by_lun(sess, se_lun); login = sbp_login_find_by_lun(sess, unpacked_lun);
if (login) { if (login) {
pr_notice("initiator already logged-in\n"); pr_notice("initiator already logged-in\n");
@ -358,7 +356,7 @@ static void sbp_management_request_login(
* reject with access_denied if any logins present * reject with access_denied if any logins present
*/ */
if (LOGIN_ORB_EXCLUSIVE(be32_to_cpu(req->orb.misc)) && if (LOGIN_ORB_EXCLUSIVE(be32_to_cpu(req->orb.misc)) &&
sbp_login_count_all_by_lun(tpg, se_lun, 0)) { sbp_login_count_all_by_lun(tpg, unpacked_lun, 0)) {
pr_warn("refusing exclusive login with other active logins\n"); pr_warn("refusing exclusive login with other active logins\n");
req->status.status = cpu_to_be32( req->status.status = cpu_to_be32(
@ -371,7 +369,7 @@ static void sbp_management_request_login(
* check exclusive bit in any existing login descriptor * check exclusive bit in any existing login descriptor
* reject with access_denied if any exclusive logins present * reject with access_denied if any exclusive logins present
*/ */
if (sbp_login_count_all_by_lun(tpg, se_lun, 1)) { if (sbp_login_count_all_by_lun(tpg, unpacked_lun, 1)) {
pr_warn("refusing login while another exclusive login present\n"); pr_warn("refusing login while another exclusive login present\n");
req->status.status = cpu_to_be32( req->status.status = cpu_to_be32(
@ -384,7 +382,7 @@ static void sbp_management_request_login(
* check we haven't exceeded the number of allowed logins * check we haven't exceeded the number of allowed logins
* reject with resources_unavailable if we have * reject with resources_unavailable if we have
*/ */
if (sbp_login_count_all_by_lun(tpg, se_lun, 0) >= if (sbp_login_count_all_by_lun(tpg, unpacked_lun, 0) >=
tport->max_logins_per_lun) { tport->max_logins_per_lun) {
pr_warn("max number of logins reached\n"); pr_warn("max number of logins reached\n");
@ -440,7 +438,7 @@ static void sbp_management_request_login(
} }
login->sess = sess; login->sess = sess;
login->lun = se_lun; login->login_lun = unpacked_lun;
login->status_fifo_addr = sbp2_pointer_to_addr(&req->orb.status_fifo); login->status_fifo_addr = sbp2_pointer_to_addr(&req->orb.status_fifo);
login->exclusive = LOGIN_ORB_EXCLUSIVE(be32_to_cpu(req->orb.misc)); login->exclusive = LOGIN_ORB_EXCLUSIVE(be32_to_cpu(req->orb.misc));
login->login_id = atomic_inc_return(&login_id); login->login_id = atomic_inc_return(&login_id);
@ -602,7 +600,7 @@ static void sbp_management_request_logout(
} }
pr_info("mgt_agent LOGOUT from LUN %d session %d\n", pr_info("mgt_agent LOGOUT from LUN %d session %d\n",
login->lun->unpacked_lun, login->login_id); login->login_lun, login->login_id);
if (req->node_addr != login->sess->node_id) { if (req->node_addr != login->sess->node_id) {
pr_warn("logout from different node ID\n"); pr_warn("logout from different node ID\n");
@ -1228,12 +1226,14 @@ static void sbp_handle_command(struct sbp_target_request *req)
goto err; goto err;
} }
unpacked_lun = req->login->lun->unpacked_lun; unpacked_lun = req->login->login_lun;
sbp_calc_data_length_direction(req, &data_length, &data_dir); sbp_calc_data_length_direction(req, &data_length, &data_dir);
pr_debug("sbp_handle_command ORB:0x%llx unpacked_lun:%d data_len:%d data_dir:%d\n", pr_debug("sbp_handle_command ORB:0x%llx unpacked_lun:%d data_len:%d data_dir:%d\n",
req->orb_pointer, unpacked_lun, data_length, data_dir); req->orb_pointer, unpacked_lun, data_length, data_dir);
/* only used for printk until we do TMRs */
req->se_cmd.tag = req->orb_pointer;
if (target_submit_cmd(&req->se_cmd, sess->se_sess, req->cmd_buf, if (target_submit_cmd(&req->se_cmd, sess->se_sess, req->cmd_buf,
req->sense_buf, unpacked_lun, data_length, req->sense_buf, unpacked_lun, data_length,
TCM_SIMPLE_TAG, data_dir, 0)) TCM_SIMPLE_TAG, data_dir, 0))
@ -1707,33 +1707,6 @@ static u16 sbp_get_tag(struct se_portal_group *se_tpg)
return tpg->tport_tpgt; return tpg->tport_tpgt;
} }
static u32 sbp_get_default_depth(struct se_portal_group *se_tpg)
{
return 1;
}
static struct se_node_acl *sbp_alloc_fabric_acl(struct se_portal_group *se_tpg)
{
struct sbp_nacl *nacl;
nacl = kzalloc(sizeof(struct sbp_nacl), GFP_KERNEL);
if (!nacl) {
pr_err("Unable to allocate struct sbp_nacl\n");
return NULL;
}
return &nacl->se_node_acl;
}
static void sbp_release_fabric_acl(
struct se_portal_group *se_tpg,
struct se_node_acl *se_nacl)
{
struct sbp_nacl *nacl =
container_of(se_nacl, struct sbp_nacl, se_node_acl);
kfree(nacl);
}
static u32 sbp_tpg_get_inst_index(struct se_portal_group *se_tpg) static u32 sbp_tpg_get_inst_index(struct se_portal_group *se_tpg)
{ {
return 1; return 1;
@ -1795,15 +1768,6 @@ static void sbp_set_default_node_attrs(struct se_node_acl *nacl)
return; return;
} }
static u32 sbp_get_task_tag(struct se_cmd *se_cmd)
{
struct sbp_target_request *req = container_of(se_cmd,
struct sbp_target_request, se_cmd);
/* only used for printk until we do TMRs */
return (u32)req->orb_pointer;
}
static int sbp_get_cmd_state(struct se_cmd *se_cmd) static int sbp_get_cmd_state(struct se_cmd *se_cmd)
{ {
return 0; return 0;
@ -1859,106 +1823,23 @@ static int sbp_check_stop_free(struct se_cmd *se_cmd)
return 1; return 1;
} }
/*
* Handlers for Serial Bus Protocol 2/3 (SBP-2 / SBP-3)
*/
static u8 sbp_get_fabric_proto_ident(struct se_portal_group *se_tpg)
{
/*
* Return a IEEE 1394 SCSI Protocol identifier for loopback operations
* This is defined in section 7.5.1 Table 362 in spc4r17
*/
return SCSI_PROTOCOL_SBP;
}
static u32 sbp_get_pr_transport_id(
struct se_portal_group *se_tpg,
struct se_node_acl *se_nacl,
struct t10_pr_registration *pr_reg,
int *format_code,
unsigned char *buf)
{
int ret;
/*
* Set PROTOCOL IDENTIFIER to 3h for SBP
*/
buf[0] = SCSI_PROTOCOL_SBP;
/*
* From spc4r17, 7.5.4.4 TransportID for initiator ports using SCSI
* over IEEE 1394
*/
ret = hex2bin(&buf[8], se_nacl->initiatorname, 8);
if (ret < 0)
pr_debug("sbp transport_id: invalid hex string\n");
/*
* The IEEE 1394 Transport ID is a hardcoded 24-byte length
*/
return 24;
}
static u32 sbp_get_pr_transport_id_len(
struct se_portal_group *se_tpg,
struct se_node_acl *se_nacl,
struct t10_pr_registration *pr_reg,
int *format_code)
{
*format_code = 0;
/*
* From spc4r17, 7.5.4.4 TransportID for initiator ports using SCSI
* over IEEE 1394
*
* The SBP Transport ID is a hardcoded 24-byte length
*/
return 24;
}
/*
* Used for handling SCSI fabric dependent TransportIDs in SPC-3 and above
* Persistent Reservation SPEC_I_PT=1 and PROUT REGISTER_AND_MOVE operations.
*/
static char *sbp_parse_pr_out_transport_id(
struct se_portal_group *se_tpg,
const char *buf,
u32 *out_tid_len,
char **port_nexus_ptr)
{
/*
* Assume the FORMAT CODE 00b from spc4r17, 7.5.4.4 TransportID
* for initiator ports using SCSI over SBP Serial SCSI Protocol
*
* The TransportID for a IEEE 1394 Initiator Port is of fixed size of
* 24 bytes, and IEEE 1394 does not contain a I_T nexus identifier,
* so we return the **port_nexus_ptr set to NULL.
*/
*port_nexus_ptr = NULL;
*out_tid_len = 24;
return (char *)&buf[8];
}
static int sbp_count_se_tpg_luns(struct se_portal_group *tpg) static int sbp_count_se_tpg_luns(struct se_portal_group *tpg)
{ {
int i, count = 0; struct se_lun *lun;
int count = 0;
spin_lock(&tpg->tpg_lun_lock);
for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
struct se_lun *se_lun = tpg->tpg_lun_list[i];
if (se_lun->lun_status == TRANSPORT_LUN_STATUS_FREE)
continue;
rcu_read_lock();
hlist_for_each_entry_rcu(lun, &tpg->tpg_lun_hlist, link)
count++; count++;
} rcu_read_unlock();
spin_unlock(&tpg->tpg_lun_lock);
return count; return count;
} }
static int sbp_update_unit_directory(struct sbp_tport *tport) static int sbp_update_unit_directory(struct sbp_tport *tport)
{ {
int num_luns, num_entries, idx = 0, mgt_agt_addr, ret, i; struct se_lun *lun;
int num_luns, num_entries, idx = 0, mgt_agt_addr, ret;
u32 *data; u32 *data;
if (tport->unit_directory.data) { if (tport->unit_directory.data) {
@ -2020,28 +1901,23 @@ static int sbp_update_unit_directory(struct sbp_tport *tport)
/* unit unique ID (leaf is just after LUNs) */ /* unit unique ID (leaf is just after LUNs) */
data[idx++] = 0x8d000000 | (num_luns + 1); data[idx++] = 0x8d000000 | (num_luns + 1);
spin_lock(&tport->tpg->se_tpg.tpg_lun_lock); rcu_read_lock();
for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { hlist_for_each_entry_rcu(lun, &tport->tpg->se_tpg.tpg_lun_hlist, link) {
struct se_lun *se_lun = tport->tpg->se_tpg.tpg_lun_list[i];
struct se_device *dev; struct se_device *dev;
int type; int type;
/*
if (se_lun->lun_status == TRANSPORT_LUN_STATUS_FREE) * rcu_dereference_raw protected by se_lun->lun_group symlink
continue; * reference to se_device->dev_group.
*/
spin_unlock(&tport->tpg->se_tpg.tpg_lun_lock); dev = rcu_dereference_raw(lun->lun_se_dev);
dev = se_lun->lun_se_dev;
type = dev->transport->get_device_type(dev); type = dev->transport->get_device_type(dev);
/* logical_unit_number */ /* logical_unit_number */
data[idx++] = 0x14000000 | data[idx++] = 0x14000000 |
((type << 16) & 0x1f0000) | ((type << 16) & 0x1f0000) |
(se_lun->unpacked_lun & 0xffff); (lun->unpacked_lun & 0xffff);
spin_lock(&tport->tpg->se_tpg.tpg_lun_lock);
} }
spin_unlock(&tport->tpg->se_tpg.tpg_lun_lock); rcu_read_unlock();
/* unit unique ID leaf */ /* unit unique ID leaf */
data[idx++] = 2 << 16; data[idx++] = 2 << 16;
@ -2100,48 +1976,13 @@ static ssize_t sbp_format_wwn(char *buf, size_t len, u64 wwn)
return snprintf(buf, len, "%016llx", wwn); return snprintf(buf, len, "%016llx", wwn);
} }
static struct se_node_acl *sbp_make_nodeacl( static int sbp_init_nodeacl(struct se_node_acl *se_nacl, const char *name)
struct se_portal_group *se_tpg,
struct config_group *group,
const char *name)
{ {
struct se_node_acl *se_nacl, *se_nacl_new;
struct sbp_nacl *nacl;
u64 guid = 0; u64 guid = 0;
u32 nexus_depth = 1;
if (sbp_parse_wwn(name, &guid) < 0) if (sbp_parse_wwn(name, &guid) < 0)
return ERR_PTR(-EINVAL); return -EINVAL;
return 0;
se_nacl_new = sbp_alloc_fabric_acl(se_tpg);
if (!se_nacl_new)
return ERR_PTR(-ENOMEM);
/*
* se_nacl_new may be released by core_tpg_add_initiator_node_acl()
* when converting a NodeACL from demo mode -> explict
*/
se_nacl = core_tpg_add_initiator_node_acl(se_tpg, se_nacl_new,
name, nexus_depth);
if (IS_ERR(se_nacl)) {
sbp_release_fabric_acl(se_tpg, se_nacl_new);
return se_nacl;
}
nacl = container_of(se_nacl, struct sbp_nacl, se_node_acl);
nacl->guid = guid;
sbp_format_wwn(nacl->iport_name, SBP_NAMELEN, guid);
return se_nacl;
}
static void sbp_drop_nodeacl(struct se_node_acl *se_acl)
{
struct sbp_nacl *nacl =
container_of(se_acl, struct sbp_nacl, se_node_acl);
core_tpg_del_initiator_node_acl(se_acl->se_tpg, se_acl, 1);
kfree(nacl);
} }
static int sbp_post_link_lun( static int sbp_post_link_lun(
@ -2214,8 +2055,7 @@ static struct se_portal_group *sbp_make_tpg(
goto out_free_tpg; goto out_free_tpg;
} }
ret = core_tpg_register(&sbp_ops, wwn, &tpg->se_tpg, tpg, ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_SBP);
TRANSPORT_TPG_TYPE_NORMAL);
if (ret < 0) if (ret < 0)
goto out_unreg_mgt_agt; goto out_unreg_mgt_agt;
@ -2505,19 +2345,12 @@ static const struct target_core_fabric_ops sbp_ops = {
.module = THIS_MODULE, .module = THIS_MODULE,
.name = "sbp", .name = "sbp",
.get_fabric_name = sbp_get_fabric_name, .get_fabric_name = sbp_get_fabric_name,
.get_fabric_proto_ident = sbp_get_fabric_proto_ident,
.tpg_get_wwn = sbp_get_fabric_wwn, .tpg_get_wwn = sbp_get_fabric_wwn,
.tpg_get_tag = sbp_get_tag, .tpg_get_tag = sbp_get_tag,
.tpg_get_default_depth = sbp_get_default_depth,
.tpg_get_pr_transport_id = sbp_get_pr_transport_id,
.tpg_get_pr_transport_id_len = sbp_get_pr_transport_id_len,
.tpg_parse_pr_out_transport_id = sbp_parse_pr_out_transport_id,
.tpg_check_demo_mode = sbp_check_true, .tpg_check_demo_mode = sbp_check_true,
.tpg_check_demo_mode_cache = sbp_check_true, .tpg_check_demo_mode_cache = sbp_check_true,
.tpg_check_demo_mode_write_protect = sbp_check_false, .tpg_check_demo_mode_write_protect = sbp_check_false,
.tpg_check_prod_mode_write_protect = sbp_check_false, .tpg_check_prod_mode_write_protect = sbp_check_false,
.tpg_alloc_fabric_acl = sbp_alloc_fabric_acl,
.tpg_release_fabric_acl = sbp_release_fabric_acl,
.tpg_get_inst_index = sbp_tpg_get_inst_index, .tpg_get_inst_index = sbp_tpg_get_inst_index,
.release_cmd = sbp_release_cmd, .release_cmd = sbp_release_cmd,
.shutdown_session = sbp_shutdown_session, .shutdown_session = sbp_shutdown_session,
@ -2526,7 +2359,6 @@ static const struct target_core_fabric_ops sbp_ops = {
.write_pending = sbp_write_pending, .write_pending = sbp_write_pending,
.write_pending_status = sbp_write_pending_status, .write_pending_status = sbp_write_pending_status,
.set_default_node_attributes = sbp_set_default_node_attrs, .set_default_node_attributes = sbp_set_default_node_attrs,
.get_task_tag = sbp_get_task_tag,
.get_cmd_state = sbp_get_cmd_state, .get_cmd_state = sbp_get_cmd_state,
.queue_data_in = sbp_queue_data_in, .queue_data_in = sbp_queue_data_in,
.queue_status = sbp_queue_status, .queue_status = sbp_queue_status,
@ -2542,8 +2374,7 @@ static const struct target_core_fabric_ops sbp_ops = {
.fabric_pre_unlink = sbp_pre_unlink_lun, .fabric_pre_unlink = sbp_pre_unlink_lun,
.fabric_make_np = NULL, .fabric_make_np = NULL,
.fabric_drop_np = NULL, .fabric_drop_np = NULL,
.fabric_make_nodeacl = sbp_make_nodeacl, .fabric_init_nodeacl = sbp_init_nodeacl,
.fabric_drop_nodeacl = sbp_drop_nodeacl,
.tfc_wwn_attrs = sbp_wwn_attrs, .tfc_wwn_attrs = sbp_wwn_attrs,
.tfc_tpg_base_attrs = sbp_tpg_base_attrs, .tfc_tpg_base_attrs = sbp_tpg_base_attrs,

View File

@ -125,7 +125,7 @@ struct sbp_login_descriptor {
struct sbp_session *sess; struct sbp_session *sess;
struct list_head link; struct list_head link;
struct se_lun *lun; u32 login_lun;
u64 status_fifo_addr; u64 status_fifo_addr;
int exclusive; int exclusive;
@ -151,15 +151,6 @@ struct sbp_session {
u64 reconnect_expires; u64 reconnect_expires;
}; };
struct sbp_nacl {
/* Initiator EUI-64 */
u64 guid;
/* ASCII formatted GUID for SBP Initiator port */
char iport_name[SBP_NAMELEN];
/* Returned by sbp_make_nodeacl() */
struct se_node_acl se_node_acl;
};
struct sbp_tpg { struct sbp_tpg {
/* Target portal group tag for TCM */ /* Target portal group tag for TCM */
u16 tport_tpgt; u16 tport_tpgt;

View File

@ -34,7 +34,6 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_backend.h> #include <target/target_core_backend.h>
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
#include "target_core_internal.h" #include "target_core_internal.h"
#include "target_core_alua.h" #include "target_core_alua.h"
@ -43,11 +42,13 @@
static sense_reason_t core_alua_check_transition(int state, int valid, static sense_reason_t core_alua_check_transition(int state, int valid,
int *primary); int *primary);
static int core_alua_set_tg_pt_secondary_state( static int core_alua_set_tg_pt_secondary_state(
struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, struct se_lun *lun, int explicit, int offline);
struct se_port *port, int explicit, int offline);
static char *core_alua_dump_state(int state); static char *core_alua_dump_state(int state);
static void __target_attach_tg_pt_gp(struct se_lun *lun,
struct t10_alua_tg_pt_gp *tg_pt_gp);
static u16 alua_lu_gps_counter; static u16 alua_lu_gps_counter;
static u32 alua_lu_gps_count; static u32 alua_lu_gps_count;
@ -145,9 +146,8 @@ sense_reason_t
target_emulate_report_target_port_groups(struct se_cmd *cmd) target_emulate_report_target_port_groups(struct se_cmd *cmd)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct se_port *port;
struct t10_alua_tg_pt_gp *tg_pt_gp; struct t10_alua_tg_pt_gp *tg_pt_gp;
struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; struct se_lun *lun;
unsigned char *buf; unsigned char *buf;
u32 rd_len = 0, off; u32 rd_len = 0, off;
int ext_hdr = (cmd->t_task_cdb[1] & 0x20); int ext_hdr = (cmd->t_task_cdb[1] & 0x20);
@ -222,9 +222,8 @@ target_emulate_report_target_port_groups(struct se_cmd *cmd)
rd_len += 8; rd_len += 8;
spin_lock(&tg_pt_gp->tg_pt_gp_lock); spin_lock(&tg_pt_gp->tg_pt_gp_lock);
list_for_each_entry(tg_pt_gp_mem, &tg_pt_gp->tg_pt_gp_mem_list, list_for_each_entry(lun, &tg_pt_gp->tg_pt_gp_lun_list,
tg_pt_gp_mem_list) { lun_tg_pt_gp_link) {
port = tg_pt_gp_mem->tg_pt;
/* /*
* Start Target Port descriptor format * Start Target Port descriptor format
* *
@ -234,8 +233,8 @@ target_emulate_report_target_port_groups(struct se_cmd *cmd)
/* /*
* Set RELATIVE TARGET PORT IDENTIFIER * Set RELATIVE TARGET PORT IDENTIFIER
*/ */
buf[off++] = ((port->sep_rtpi >> 8) & 0xff); buf[off++] = ((lun->lun_rtpi >> 8) & 0xff);
buf[off++] = (port->sep_rtpi & 0xff); buf[off++] = (lun->lun_rtpi & 0xff);
rd_len += 4; rd_len += 4;
} }
spin_unlock(&tg_pt_gp->tg_pt_gp_lock); spin_unlock(&tg_pt_gp->tg_pt_gp_lock);
@ -259,15 +258,11 @@ target_emulate_report_target_port_groups(struct se_cmd *cmd)
* this CDB was received upon to determine this value individually * this CDB was received upon to determine this value individually
* for ALUA target port group. * for ALUA target port group.
*/ */
port = cmd->se_lun->lun_sep; spin_lock(&cmd->se_lun->lun_tg_pt_gp_lock);
tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; tg_pt_gp = cmd->se_lun->lun_tg_pt_gp;
if (tg_pt_gp_mem) { if (tg_pt_gp)
spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); buf[5] = tg_pt_gp->tg_pt_gp_implicit_trans_secs;
tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; spin_unlock(&cmd->se_lun->lun_tg_pt_gp_lock);
if (tg_pt_gp)
buf[5] = tg_pt_gp->tg_pt_gp_implicit_trans_secs;
spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
}
} }
transport_kunmap_data_sg(cmd); transport_kunmap_data_sg(cmd);
@ -284,10 +279,9 @@ sense_reason_t
target_emulate_set_target_port_groups(struct se_cmd *cmd) target_emulate_set_target_port_groups(struct se_cmd *cmd)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct se_port *port, *l_port = cmd->se_lun->lun_sep; struct se_lun *l_lun = cmd->se_lun;
struct se_node_acl *nacl = cmd->se_sess->se_node_acl; struct se_node_acl *nacl = cmd->se_sess->se_node_acl;
struct t10_alua_tg_pt_gp *tg_pt_gp = NULL, *l_tg_pt_gp; struct t10_alua_tg_pt_gp *tg_pt_gp = NULL, *l_tg_pt_gp;
struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *l_tg_pt_gp_mem;
unsigned char *buf; unsigned char *buf;
unsigned char *ptr; unsigned char *ptr;
sense_reason_t rc = TCM_NO_SENSE; sense_reason_t rc = TCM_NO_SENSE;
@ -295,9 +289,6 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
int alua_access_state, primary = 0, valid_states; int alua_access_state, primary = 0, valid_states;
u16 tg_pt_id, rtpi; u16 tg_pt_id, rtpi;
if (!l_port)
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
if (cmd->data_length < 4) { if (cmd->data_length < 4) {
pr_warn("SET TARGET PORT GROUPS parameter list length %u too" pr_warn("SET TARGET PORT GROUPS parameter list length %u too"
" small\n", cmd->data_length); " small\n", cmd->data_length);
@ -312,29 +303,24 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
* Determine if explicit 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. * for the local tg_pt_gp.
*/ */
l_tg_pt_gp_mem = l_port->sep_alua_tg_pt_gp_mem; spin_lock(&l_lun->lun_tg_pt_gp_lock);
if (!l_tg_pt_gp_mem) { l_tg_pt_gp = l_lun->lun_tg_pt_gp;
pr_err("Unable to access l_port->sep_alua_tg_pt_gp_mem\n");
rc = TCM_UNSUPPORTED_SCSI_OPCODE;
goto out;
}
spin_lock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock);
l_tg_pt_gp = l_tg_pt_gp_mem->tg_pt_gp;
if (!l_tg_pt_gp) { if (!l_tg_pt_gp) {
spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); spin_unlock(&l_lun->lun_tg_pt_gp_lock);
pr_err("Unable to access *l_tg_pt_gp_mem->tg_pt_gp\n"); pr_err("Unable to access l_lun->tg_pt_gp\n");
rc = TCM_UNSUPPORTED_SCSI_OPCODE; rc = TCM_UNSUPPORTED_SCSI_OPCODE;
goto out; goto out;
} }
spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock);
if (!(l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICIT_ALUA)) { if (!(l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICIT_ALUA)) {
spin_unlock(&l_lun->lun_tg_pt_gp_lock);
pr_debug("Unable to process SET_TARGET_PORT_GROUPS" pr_debug("Unable to process SET_TARGET_PORT_GROUPS"
" while TPGS_EXPLICIT_ALUA is disabled\n"); " while TPGS_EXPLICIT_ALUA is disabled\n");
rc = TCM_UNSUPPORTED_SCSI_OPCODE; rc = TCM_UNSUPPORTED_SCSI_OPCODE;
goto out; goto out;
} }
valid_states = l_tg_pt_gp->tg_pt_gp_alua_supported_states; valid_states = l_tg_pt_gp->tg_pt_gp_alua_supported_states;
spin_unlock(&l_lun->lun_tg_pt_gp_lock);
ptr = &buf[4]; /* Skip over RESERVED area in header */ ptr = &buf[4]; /* Skip over RESERVED area in header */
@ -396,7 +382,7 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
spin_unlock(&dev->t10_alua.tg_pt_gps_lock); spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
if (!core_alua_do_port_transition(tg_pt_gp, if (!core_alua_do_port_transition(tg_pt_gp,
dev, l_port, nacl, dev, l_lun, nacl,
alua_access_state, 1)) alua_access_state, 1))
found = true; found = true;
@ -406,6 +392,8 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
} }
spin_unlock(&dev->t10_alua.tg_pt_gps_lock); spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
} else { } else {
struct se_lun *lun;
/* /*
* Extract the RELATIVE TARGET PORT IDENTIFIER to identify * Extract the RELATIVE TARGET PORT IDENTIFIER to identify
* the Target Port in question for the the incoming * the Target Port in question for the the incoming
@ -417,17 +405,16 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
* for the struct se_device storage object. * for the struct se_device storage object.
*/ */
spin_lock(&dev->se_port_lock); spin_lock(&dev->se_port_lock);
list_for_each_entry(port, &dev->dev_sep_list, list_for_each_entry(lun, &dev->dev_sep_list,
sep_list) { lun_dev_link) {
if (port->sep_rtpi != rtpi) if (lun->lun_rtpi != rtpi)
continue; continue;
tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; // XXX: racy unlock
spin_unlock(&dev->se_port_lock); spin_unlock(&dev->se_port_lock);
if (!core_alua_set_tg_pt_secondary_state( if (!core_alua_set_tg_pt_secondary_state(
tg_pt_gp_mem, port, 1, 1)) lun, 1, 1))
found = true; found = true;
spin_lock(&dev->se_port_lock); spin_lock(&dev->se_port_lock);
@ -696,9 +683,7 @@ target_alua_state_check(struct se_cmd *cmd)
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
unsigned char *cdb = cmd->t_task_cdb; unsigned char *cdb = cmd->t_task_cdb;
struct se_lun *lun = cmd->se_lun; struct se_lun *lun = cmd->se_lun;
struct se_port *port = lun->lun_sep;
struct t10_alua_tg_pt_gp *tg_pt_gp; struct t10_alua_tg_pt_gp *tg_pt_gp;
struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
int out_alua_state, nonop_delay_msecs; int out_alua_state, nonop_delay_msecs;
if (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE) if (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)
@ -706,33 +691,27 @@ target_alua_state_check(struct se_cmd *cmd)
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH) if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
return 0; return 0;
if (!port)
return 0;
/* /*
* First, check for a struct se_port specific secondary ALUA target port * First, check for a struct se_port specific secondary ALUA target port
* access state: OFFLINE * access state: OFFLINE
*/ */
if (atomic_read(&port->sep_tg_pt_secondary_offline)) { if (atomic_read(&lun->lun_tg_pt_secondary_offline)) {
pr_debug("ALUA: Got secondary offline status for local" pr_debug("ALUA: Got secondary offline status for local"
" target port\n"); " target port\n");
set_ascq(cmd, ASCQ_04H_ALUA_OFFLINE); set_ascq(cmd, ASCQ_04H_ALUA_OFFLINE);
return TCM_CHECK_CONDITION_NOT_READY; return TCM_CHECK_CONDITION_NOT_READY;
} }
/*
* Second, obtain the struct t10_alua_tg_pt_gp_member pointer to the if (!lun->lun_tg_pt_gp)
* ALUA target port group, to obtain current ALUA access state.
* Otherwise look for the underlying struct se_device association with
* a ALUA logical unit group.
*/
tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
if (!tg_pt_gp_mem)
return 0; return 0;
spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); spin_lock(&lun->lun_tg_pt_gp_lock);
tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; tg_pt_gp = lun->lun_tg_pt_gp;
out_alua_state = atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state); out_alua_state = atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state);
nonop_delay_msecs = tg_pt_gp->tg_pt_gp_nonop_delay_msecs; nonop_delay_msecs = tg_pt_gp->tg_pt_gp_nonop_delay_msecs;
spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
// XXX: keeps using tg_pt_gp witout reference after unlock
spin_unlock(&lun->lun_tg_pt_gp_lock);
/* /*
* Process ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED 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. * statement so the compiler knows explicitly to check this case first.
@ -764,7 +743,7 @@ target_alua_state_check(struct se_cmd *cmd)
break; break;
/* /*
* OFFLINE is a secondary ALUA target port group access state, that is * OFFLINE is a secondary ALUA target port group access state, that is
* handled above with struct se_port->sep_tg_pt_secondary_offline=1 * handled above with struct se_lun->lun_tg_pt_secondary_offline=1
*/ */
case ALUA_ACCESS_STATE_OFFLINE: case ALUA_ACCESS_STATE_OFFLINE:
default: default:
@ -906,10 +885,6 @@ int core_alua_check_nonop_delay(
} }
EXPORT_SYMBOL(core_alua_check_nonop_delay); EXPORT_SYMBOL(core_alua_check_nonop_delay);
/*
* Called with tg_pt_gp->tg_pt_gp_md_mutex or tg_pt_gp_mem->sep_tg_pt_md_mutex
*
*/
static int core_alua_write_tpg_metadata( static int core_alua_write_tpg_metadata(
const char *path, const char *path,
unsigned char *md_buf, unsigned char *md_buf,
@ -965,22 +940,15 @@ static int core_alua_update_tpg_primary_metadata(
return rc; return rc;
} }
static void core_alua_do_transition_tg_pt_work(struct work_struct *work) static void core_alua_queue_state_change_ua(struct t10_alua_tg_pt_gp *tg_pt_gp)
{ {
struct t10_alua_tg_pt_gp *tg_pt_gp = container_of(work,
struct t10_alua_tg_pt_gp, tg_pt_gp_transition_work.work);
struct se_device *dev = tg_pt_gp->tg_pt_gp_dev;
struct se_dev_entry *se_deve; struct se_dev_entry *se_deve;
struct se_lun *lun;
struct se_lun_acl *lacl; struct se_lun_acl *lacl;
struct se_port *port;
struct t10_alua_tg_pt_gp_member *mem;
bool explicit = (tg_pt_gp->tg_pt_gp_alua_access_status ==
ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG);
spin_lock(&tg_pt_gp->tg_pt_gp_lock); spin_lock(&tg_pt_gp->tg_pt_gp_lock);
list_for_each_entry(mem, &tg_pt_gp->tg_pt_gp_mem_list, list_for_each_entry(lun, &tg_pt_gp->tg_pt_gp_lun_list,
tg_pt_gp_mem_list) { lun_tg_pt_gp_link) {
port = mem->tg_pt;
/* /*
* After an implicit target port asymmetric access state * After an implicit target port asymmetric access state
* change, a device server shall establish a unit attention * change, a device server shall establish a unit attention
@ -995,38 +963,58 @@ static void core_alua_do_transition_tg_pt_work(struct work_struct *work)
* every I_T nexus other than the I_T nexus on which the SET * every I_T nexus other than the I_T nexus on which the SET
* TARGET PORT GROUPS command * TARGET PORT GROUPS command
*/ */
atomic_inc_mb(&mem->tg_pt_gp_mem_ref_cnt); if (!percpu_ref_tryget_live(&lun->lun_ref))
continue;
spin_unlock(&tg_pt_gp->tg_pt_gp_lock); spin_unlock(&tg_pt_gp->tg_pt_gp_lock);
spin_lock_bh(&port->sep_alua_lock); spin_lock(&lun->lun_deve_lock);
list_for_each_entry(se_deve, &port->sep_alua_list, list_for_each_entry(se_deve, &lun->lun_deve_list, lun_link) {
alua_port_list) { lacl = rcu_dereference_check(se_deve->se_lun_acl,
lacl = se_deve->se_lun_acl; lockdep_is_held(&lun->lun_deve_lock));
/*
* spc4r37 p.242:
* After an explicit target port asymmetric access
* state change, a device server shall establish a
* unit attention condition with the additional sense
* code set to ASYMMETRIC ACCESS STATE CHANGED for
* the initiator port associated with every I_T nexus
* other than the I_T nexus on which the SET TARGET
* PORT GROUPS command was received.
*/
if ((tg_pt_gp->tg_pt_gp_alua_access_status ==
ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG) &&
(tg_pt_gp->tg_pt_gp_alua_lun != NULL) &&
(tg_pt_gp->tg_pt_gp_alua_lun == lun))
continue;
/* /*
* se_deve->se_lun_acl pointer may be NULL for a * se_deve->se_lun_acl pointer may be NULL for a
* entry created without explicit Node+MappedLUN ACLs * entry created without explicit Node+MappedLUN ACLs
*/ */
if (!lacl) if (lacl && (tg_pt_gp->tg_pt_gp_alua_nacl != NULL) &&
(tg_pt_gp->tg_pt_gp_alua_nacl == lacl->se_lun_nacl))
continue; continue;
if ((tg_pt_gp->tg_pt_gp_alua_access_status == core_scsi3_ua_allocate(se_deve, 0x2A,
ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG) &&
(tg_pt_gp->tg_pt_gp_alua_nacl != NULL) &&
(tg_pt_gp->tg_pt_gp_alua_nacl == lacl->se_lun_nacl) &&
(tg_pt_gp->tg_pt_gp_alua_port != NULL) &&
(tg_pt_gp->tg_pt_gp_alua_port == port))
continue;
core_scsi3_ua_allocate(lacl->se_lun_nacl,
se_deve->mapped_lun, 0x2A,
ASCQ_2AH_ASYMMETRIC_ACCESS_STATE_CHANGED); ASCQ_2AH_ASYMMETRIC_ACCESS_STATE_CHANGED);
} }
spin_unlock_bh(&port->sep_alua_lock); spin_unlock(&lun->lun_deve_lock);
spin_lock(&tg_pt_gp->tg_pt_gp_lock); spin_lock(&tg_pt_gp->tg_pt_gp_lock);
atomic_dec_mb(&mem->tg_pt_gp_mem_ref_cnt); percpu_ref_put(&lun->lun_ref);
} }
spin_unlock(&tg_pt_gp->tg_pt_gp_lock); spin_unlock(&tg_pt_gp->tg_pt_gp_lock);
}
static void core_alua_do_transition_tg_pt_work(struct work_struct *work)
{
struct t10_alua_tg_pt_gp *tg_pt_gp = container_of(work,
struct t10_alua_tg_pt_gp, tg_pt_gp_transition_work.work);
struct se_device *dev = tg_pt_gp->tg_pt_gp_dev;
bool explicit = (tg_pt_gp->tg_pt_gp_alua_access_status ==
ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG);
/* /*
* Update the ALUA metadata buf that has been allocated in * Update the ALUA metadata buf that has been allocated in
* core_alua_do_port_transition(), this metadata will be written * core_alua_do_port_transition(), this metadata will be written
@ -1056,6 +1044,9 @@ static void core_alua_do_transition_tg_pt_work(struct work_struct *work)
tg_pt_gp->tg_pt_gp_id, tg_pt_gp->tg_pt_gp_id,
core_alua_dump_state(tg_pt_gp->tg_pt_gp_alua_previous_state), core_alua_dump_state(tg_pt_gp->tg_pt_gp_alua_previous_state),
core_alua_dump_state(tg_pt_gp->tg_pt_gp_alua_pending_state)); core_alua_dump_state(tg_pt_gp->tg_pt_gp_alua_pending_state));
core_alua_queue_state_change_ua(tg_pt_gp);
spin_lock(&dev->t10_alua.tg_pt_gps_lock); spin_lock(&dev->t10_alua.tg_pt_gps_lock);
atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt); atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt);
spin_unlock(&dev->t10_alua.tg_pt_gps_lock); spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
@ -1108,6 +1099,8 @@ static int core_alua_do_transition_tg_pt(
ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG : ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG :
ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA; ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA;
core_alua_queue_state_change_ua(tg_pt_gp);
/* /*
* Check for the optional ALUA primary state transition delay * Check for the optional ALUA primary state transition delay
*/ */
@ -1142,7 +1135,7 @@ static int core_alua_do_transition_tg_pt(
int core_alua_do_port_transition( int core_alua_do_port_transition(
struct t10_alua_tg_pt_gp *l_tg_pt_gp, struct t10_alua_tg_pt_gp *l_tg_pt_gp,
struct se_device *l_dev, struct se_device *l_dev,
struct se_port *l_port, struct se_lun *l_lun,
struct se_node_acl *l_nacl, struct se_node_acl *l_nacl,
int new_state, int new_state,
int explicit) int explicit)
@ -1172,7 +1165,7 @@ int core_alua_do_port_transition(
* core_alua_do_transition_tg_pt() will always return * core_alua_do_transition_tg_pt() will always return
* success. * success.
*/ */
l_tg_pt_gp->tg_pt_gp_alua_port = l_port; l_tg_pt_gp->tg_pt_gp_alua_lun = l_lun;
l_tg_pt_gp->tg_pt_gp_alua_nacl = l_nacl; l_tg_pt_gp->tg_pt_gp_alua_nacl = l_nacl;
rc = core_alua_do_transition_tg_pt(l_tg_pt_gp, rc = core_alua_do_transition_tg_pt(l_tg_pt_gp,
new_state, explicit); new_state, explicit);
@ -1211,10 +1204,10 @@ int core_alua_do_port_transition(
continue; continue;
if (l_tg_pt_gp == tg_pt_gp) { if (l_tg_pt_gp == tg_pt_gp) {
tg_pt_gp->tg_pt_gp_alua_port = l_port; tg_pt_gp->tg_pt_gp_alua_lun = l_lun;
tg_pt_gp->tg_pt_gp_alua_nacl = l_nacl; tg_pt_gp->tg_pt_gp_alua_nacl = l_nacl;
} else { } else {
tg_pt_gp->tg_pt_gp_alua_port = NULL; tg_pt_gp->tg_pt_gp_alua_lun = NULL;
tg_pt_gp->tg_pt_gp_alua_nacl = NULL; tg_pt_gp->tg_pt_gp_alua_nacl = NULL;
} }
atomic_inc_mb(&tg_pt_gp->tg_pt_gp_ref_cnt); atomic_inc_mb(&tg_pt_gp->tg_pt_gp_ref_cnt);
@ -1251,22 +1244,20 @@ int core_alua_do_port_transition(
return rc; return rc;
} }
/* static int core_alua_update_tpg_secondary_metadata(struct se_lun *lun)
* Called with tg_pt_gp_mem->sep_tg_pt_md_mutex held
*/
static int core_alua_update_tpg_secondary_metadata(
struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem,
struct se_port *port)
{ {
struct se_portal_group *se_tpg = lun->lun_tpg;
unsigned char *md_buf; unsigned char *md_buf;
struct se_portal_group *se_tpg = port->sep_tpg;
char path[ALUA_METADATA_PATH_LEN], wwn[ALUA_SECONDARY_METADATA_WWN_LEN]; char path[ALUA_METADATA_PATH_LEN], wwn[ALUA_SECONDARY_METADATA_WWN_LEN];
int len, rc; int len, rc;
mutex_lock(&lun->lun_tg_pt_md_mutex);
md_buf = kzalloc(ALUA_MD_BUF_LEN, GFP_KERNEL); md_buf = kzalloc(ALUA_MD_BUF_LEN, GFP_KERNEL);
if (!md_buf) { if (!md_buf) {
pr_err("Unable to allocate buf for ALUA metadata\n"); pr_err("Unable to allocate buf for ALUA metadata\n");
return -ENOMEM; rc = -ENOMEM;
goto out_unlock;
} }
memset(path, 0, ALUA_METADATA_PATH_LEN); memset(path, 0, ALUA_METADATA_PATH_LEN);
@ -1281,32 +1272,33 @@ static int core_alua_update_tpg_secondary_metadata(
len = snprintf(md_buf, ALUA_MD_BUF_LEN, "alua_tg_pt_offline=%d\n" len = snprintf(md_buf, ALUA_MD_BUF_LEN, "alua_tg_pt_offline=%d\n"
"alua_tg_pt_status=0x%02x\n", "alua_tg_pt_status=0x%02x\n",
atomic_read(&port->sep_tg_pt_secondary_offline), atomic_read(&lun->lun_tg_pt_secondary_offline),
port->sep_tg_pt_secondary_stat); lun->lun_tg_pt_secondary_stat);
snprintf(path, ALUA_METADATA_PATH_LEN, "/var/target/alua/%s/%s/lun_%u", snprintf(path, ALUA_METADATA_PATH_LEN, "/var/target/alua/%s/%s/lun_%llu",
se_tpg->se_tpg_tfo->get_fabric_name(), wwn, se_tpg->se_tpg_tfo->get_fabric_name(), wwn,
port->sep_lun->unpacked_lun); lun->unpacked_lun);
rc = core_alua_write_tpg_metadata(path, md_buf, len); rc = core_alua_write_tpg_metadata(path, md_buf, len);
kfree(md_buf); kfree(md_buf);
out_unlock:
mutex_unlock(&lun->lun_tg_pt_md_mutex);
return rc; return rc;
} }
static int core_alua_set_tg_pt_secondary_state( static int core_alua_set_tg_pt_secondary_state(
struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, struct se_lun *lun,
struct se_port *port,
int explicit, int explicit,
int offline) int offline)
{ {
struct t10_alua_tg_pt_gp *tg_pt_gp; struct t10_alua_tg_pt_gp *tg_pt_gp;
int trans_delay_msecs; int trans_delay_msecs;
spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); spin_lock(&lun->lun_tg_pt_gp_lock);
tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; tg_pt_gp = lun->lun_tg_pt_gp;
if (!tg_pt_gp) { if (!tg_pt_gp) {
spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); spin_unlock(&lun->lun_tg_pt_gp_lock);
pr_err("Unable to complete secondary state" pr_err("Unable to complete secondary state"
" transition\n"); " transition\n");
return -EINVAL; return -EINVAL;
@ -1314,14 +1306,14 @@ static int core_alua_set_tg_pt_secondary_state(
trans_delay_msecs = tg_pt_gp->tg_pt_gp_trans_delay_msecs; trans_delay_msecs = tg_pt_gp->tg_pt_gp_trans_delay_msecs;
/* /*
* Set the secondary ALUA target port access state to OFFLINE * Set the secondary ALUA target port access state to OFFLINE
* or release the previously secondary state for struct se_port * or release the previously secondary state for struct se_lun
*/ */
if (offline) if (offline)
atomic_set(&port->sep_tg_pt_secondary_offline, 1); atomic_set(&lun->lun_tg_pt_secondary_offline, 1);
else else
atomic_set(&port->sep_tg_pt_secondary_offline, 0); atomic_set(&lun->lun_tg_pt_secondary_offline, 0);
port->sep_tg_pt_secondary_stat = (explicit) ? lun->lun_tg_pt_secondary_stat = (explicit) ?
ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG : ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG :
ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA; ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA;
@ -1330,7 +1322,7 @@ static int core_alua_set_tg_pt_secondary_state(
"implicit", config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item), "implicit", config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item),
tg_pt_gp->tg_pt_gp_id, (offline) ? "OFFLINE" : "ONLINE"); tg_pt_gp->tg_pt_gp_id, (offline) ? "OFFLINE" : "ONLINE");
spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); spin_unlock(&lun->lun_tg_pt_gp_lock);
/* /*
* Do the optional transition delay after we set the secondary * Do the optional transition delay after we set the secondary
* ALUA access state. * ALUA access state.
@ -1341,11 +1333,8 @@ static int core_alua_set_tg_pt_secondary_state(
* See if we need to update the ALUA fabric port metadata for * See if we need to update the ALUA fabric port metadata for
* secondary state and status * secondary state and status
*/ */
if (port->sep_tg_pt_secondary_write_md) { if (lun->lun_tg_pt_secondary_write_md)
mutex_lock(&port->sep_tg_pt_md_mutex); core_alua_update_tpg_secondary_metadata(lun);
core_alua_update_tpg_secondary_metadata(tg_pt_gp_mem, port);
mutex_unlock(&port->sep_tg_pt_md_mutex);
}
return 0; return 0;
} }
@ -1699,7 +1688,7 @@ struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(struct se_device *dev,
return NULL; return NULL;
} }
INIT_LIST_HEAD(&tg_pt_gp->tg_pt_gp_list); INIT_LIST_HEAD(&tg_pt_gp->tg_pt_gp_list);
INIT_LIST_HEAD(&tg_pt_gp->tg_pt_gp_mem_list); INIT_LIST_HEAD(&tg_pt_gp->tg_pt_gp_lun_list);
mutex_init(&tg_pt_gp->tg_pt_gp_md_mutex); mutex_init(&tg_pt_gp->tg_pt_gp_md_mutex);
spin_lock_init(&tg_pt_gp->tg_pt_gp_lock); spin_lock_init(&tg_pt_gp->tg_pt_gp_lock);
atomic_set(&tg_pt_gp->tg_pt_gp_ref_cnt, 0); atomic_set(&tg_pt_gp->tg_pt_gp_ref_cnt, 0);
@ -1793,32 +1782,11 @@ again:
return 0; return 0;
} }
struct t10_alua_tg_pt_gp_member *core_alua_allocate_tg_pt_gp_mem(
struct se_port *port)
{
struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
tg_pt_gp_mem = kmem_cache_zalloc(t10_alua_tg_pt_gp_mem_cache,
GFP_KERNEL);
if (!tg_pt_gp_mem) {
pr_err("Unable to allocate struct t10_alua_tg_pt_gp_member\n");
return ERR_PTR(-ENOMEM);
}
INIT_LIST_HEAD(&tg_pt_gp_mem->tg_pt_gp_mem_list);
spin_lock_init(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
atomic_set(&tg_pt_gp_mem->tg_pt_gp_mem_ref_cnt, 0);
tg_pt_gp_mem->tg_pt = port;
port->sep_alua_tg_pt_gp_mem = tg_pt_gp_mem;
return tg_pt_gp_mem;
}
void core_alua_free_tg_pt_gp( void core_alua_free_tg_pt_gp(
struct t10_alua_tg_pt_gp *tg_pt_gp) struct t10_alua_tg_pt_gp *tg_pt_gp)
{ {
struct se_device *dev = tg_pt_gp->tg_pt_gp_dev; struct se_device *dev = tg_pt_gp->tg_pt_gp_dev;
struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *tg_pt_gp_mem_tmp; struct se_lun *lun, *next;
/* /*
* Once we have reached this point, config_item_put() has already * Once we have reached this point, config_item_put() has already
@ -1849,30 +1817,24 @@ void core_alua_free_tg_pt_gp(
* struct se_port. * struct se_port.
*/ */
spin_lock(&tg_pt_gp->tg_pt_gp_lock); spin_lock(&tg_pt_gp->tg_pt_gp_lock);
list_for_each_entry_safe(tg_pt_gp_mem, tg_pt_gp_mem_tmp, list_for_each_entry_safe(lun, next,
&tg_pt_gp->tg_pt_gp_mem_list, tg_pt_gp_mem_list) { &tg_pt_gp->tg_pt_gp_lun_list, lun_tg_pt_gp_link) {
if (tg_pt_gp_mem->tg_pt_gp_assoc) { list_del_init(&lun->lun_tg_pt_gp_link);
list_del(&tg_pt_gp_mem->tg_pt_gp_mem_list); tg_pt_gp->tg_pt_gp_members--;
tg_pt_gp->tg_pt_gp_members--;
tg_pt_gp_mem->tg_pt_gp_assoc = 0;
}
spin_unlock(&tg_pt_gp->tg_pt_gp_lock); spin_unlock(&tg_pt_gp->tg_pt_gp_lock);
/* /*
* tg_pt_gp_mem is associated with a single
* se_port->sep_alua_tg_pt_gp_mem, and is released via
* core_alua_free_tg_pt_gp_mem().
*
* If the passed tg_pt_gp does NOT match the default_tg_pt_gp, * If the passed tg_pt_gp does NOT match the default_tg_pt_gp,
* assume we want to re-associate a given tg_pt_gp_mem with * assume we want to re-associate a given tg_pt_gp_mem with
* default_tg_pt_gp. * default_tg_pt_gp.
*/ */
spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); spin_lock(&lun->lun_tg_pt_gp_lock);
if (tg_pt_gp != dev->t10_alua.default_tg_pt_gp) { if (tg_pt_gp != dev->t10_alua.default_tg_pt_gp) {
__core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem, __target_attach_tg_pt_gp(lun,
dev->t10_alua.default_tg_pt_gp); dev->t10_alua.default_tg_pt_gp);
} else } else
tg_pt_gp_mem->tg_pt_gp = NULL; lun->lun_tg_pt_gp = NULL;
spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); spin_unlock(&lun->lun_tg_pt_gp_lock);
spin_lock(&tg_pt_gp->tg_pt_gp_lock); spin_lock(&tg_pt_gp->tg_pt_gp_lock);
} }
@ -1881,35 +1843,6 @@ void core_alua_free_tg_pt_gp(
kmem_cache_free(t10_alua_tg_pt_gp_cache, tg_pt_gp); kmem_cache_free(t10_alua_tg_pt_gp_cache, tg_pt_gp);
} }
void core_alua_free_tg_pt_gp_mem(struct se_port *port)
{
struct t10_alua_tg_pt_gp *tg_pt_gp;
struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
if (!tg_pt_gp_mem)
return;
while (atomic_read(&tg_pt_gp_mem->tg_pt_gp_mem_ref_cnt))
cpu_relax();
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) {
spin_lock(&tg_pt_gp->tg_pt_gp_lock);
if (tg_pt_gp_mem->tg_pt_gp_assoc) {
list_del(&tg_pt_gp_mem->tg_pt_gp_mem_list);
tg_pt_gp->tg_pt_gp_members--;
tg_pt_gp_mem->tg_pt_gp_assoc = 0;
}
spin_unlock(&tg_pt_gp->tg_pt_gp_lock);
tg_pt_gp_mem->tg_pt_gp = NULL;
}
spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
kmem_cache_free(t10_alua_tg_pt_gp_mem_cache, tg_pt_gp_mem);
}
static struct t10_alua_tg_pt_gp *core_alua_get_tg_pt_gp_by_name( static struct t10_alua_tg_pt_gp *core_alua_get_tg_pt_gp_by_name(
struct se_device *dev, const char *name) struct se_device *dev, const char *name)
{ {
@ -1943,50 +1876,65 @@ static void core_alua_put_tg_pt_gp_from_name(
spin_unlock(&dev->t10_alua.tg_pt_gps_lock); spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
} }
/* static void __target_attach_tg_pt_gp(struct se_lun *lun,
* Called with struct t10_alua_tg_pt_gp_member->tg_pt_gp_mem_lock held struct t10_alua_tg_pt_gp *tg_pt_gp)
*/
void __core_alua_attach_tg_pt_gp_mem(
struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem,
struct t10_alua_tg_pt_gp *tg_pt_gp)
{ {
struct se_dev_entry *se_deve;
assert_spin_locked(&lun->lun_tg_pt_gp_lock);
spin_lock(&tg_pt_gp->tg_pt_gp_lock); spin_lock(&tg_pt_gp->tg_pt_gp_lock);
tg_pt_gp_mem->tg_pt_gp = tg_pt_gp; lun->lun_tg_pt_gp = tg_pt_gp;
tg_pt_gp_mem->tg_pt_gp_assoc = 1; list_add_tail(&lun->lun_tg_pt_gp_link, &tg_pt_gp->tg_pt_gp_lun_list);
list_add_tail(&tg_pt_gp_mem->tg_pt_gp_mem_list,
&tg_pt_gp->tg_pt_gp_mem_list);
tg_pt_gp->tg_pt_gp_members++; tg_pt_gp->tg_pt_gp_members++;
spin_lock(&lun->lun_deve_lock);
list_for_each_entry(se_deve, &lun->lun_deve_list, lun_link)
core_scsi3_ua_allocate(se_deve, 0x3f,
ASCQ_3FH_INQUIRY_DATA_HAS_CHANGED);
spin_unlock(&lun->lun_deve_lock);
spin_unlock(&tg_pt_gp->tg_pt_gp_lock); spin_unlock(&tg_pt_gp->tg_pt_gp_lock);
} }
/* void target_attach_tg_pt_gp(struct se_lun *lun,
* Called with struct t10_alua_tg_pt_gp_member->tg_pt_gp_mem_lock held struct t10_alua_tg_pt_gp *tg_pt_gp)
*/
static void __core_alua_drop_tg_pt_gp_mem(
struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem,
struct t10_alua_tg_pt_gp *tg_pt_gp)
{ {
spin_lock(&lun->lun_tg_pt_gp_lock);
__target_attach_tg_pt_gp(lun, tg_pt_gp);
spin_unlock(&lun->lun_tg_pt_gp_lock);
}
static void __target_detach_tg_pt_gp(struct se_lun *lun,
struct t10_alua_tg_pt_gp *tg_pt_gp)
{
assert_spin_locked(&lun->lun_tg_pt_gp_lock);
spin_lock(&tg_pt_gp->tg_pt_gp_lock); spin_lock(&tg_pt_gp->tg_pt_gp_lock);
list_del(&tg_pt_gp_mem->tg_pt_gp_mem_list); list_del_init(&lun->lun_tg_pt_gp_link);
tg_pt_gp_mem->tg_pt_gp = NULL;
tg_pt_gp_mem->tg_pt_gp_assoc = 0;
tg_pt_gp->tg_pt_gp_members--; tg_pt_gp->tg_pt_gp_members--;
spin_unlock(&tg_pt_gp->tg_pt_gp_lock); spin_unlock(&tg_pt_gp->tg_pt_gp_lock);
lun->lun_tg_pt_gp = NULL;
} }
ssize_t core_alua_show_tg_pt_gp_info(struct se_port *port, char *page) void target_detach_tg_pt_gp(struct se_lun *lun)
{
struct t10_alua_tg_pt_gp *tg_pt_gp;
spin_lock(&lun->lun_tg_pt_gp_lock);
tg_pt_gp = lun->lun_tg_pt_gp;
if (tg_pt_gp)
__target_detach_tg_pt_gp(lun, tg_pt_gp);
spin_unlock(&lun->lun_tg_pt_gp_lock);
}
ssize_t core_alua_show_tg_pt_gp_info(struct se_lun *lun, char *page)
{ {
struct config_item *tg_pt_ci; struct config_item *tg_pt_ci;
struct t10_alua_tg_pt_gp *tg_pt_gp; struct t10_alua_tg_pt_gp *tg_pt_gp;
struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
ssize_t len = 0; ssize_t len = 0;
tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; spin_lock(&lun->lun_tg_pt_gp_lock);
if (!tg_pt_gp_mem) tg_pt_gp = lun->lun_tg_pt_gp;
return len;
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) { if (tg_pt_gp) {
tg_pt_ci = &tg_pt_gp->tg_pt_gp_group.cg_item; tg_pt_ci = &tg_pt_gp->tg_pt_gp_group.cg_item;
len += sprintf(page, "TG Port Alias: %s\nTG Port Group ID:" len += sprintf(page, "TG Port Alias: %s\nTG Port Group ID:"
@ -1998,34 +1946,33 @@ ssize_t core_alua_show_tg_pt_gp_info(struct se_port *port, char *page)
&tg_pt_gp->tg_pt_gp_alua_access_state)), &tg_pt_gp->tg_pt_gp_alua_access_state)),
core_alua_dump_status( core_alua_dump_status(
tg_pt_gp->tg_pt_gp_alua_access_status), tg_pt_gp->tg_pt_gp_alua_access_status),
(atomic_read(&port->sep_tg_pt_secondary_offline)) ? atomic_read(&lun->lun_tg_pt_secondary_offline) ?
"Offline" : "None", "Offline" : "None",
core_alua_dump_status(port->sep_tg_pt_secondary_stat)); core_alua_dump_status(lun->lun_tg_pt_secondary_stat));
} }
spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); spin_unlock(&lun->lun_tg_pt_gp_lock);
return len; return len;
} }
ssize_t core_alua_store_tg_pt_gp_info( ssize_t core_alua_store_tg_pt_gp_info(
struct se_port *port, struct se_lun *lun,
const char *page, const char *page,
size_t count) size_t count)
{ {
struct se_portal_group *tpg; struct se_portal_group *tpg = lun->lun_tpg;
struct se_lun *lun; /*
struct se_device *dev = port->sep_lun->lun_se_dev; * rcu_dereference_raw protected by se_lun->lun_group symlink
* reference to se_device->dev_group.
*/
struct se_device *dev = rcu_dereference_raw(lun->lun_se_dev);
struct t10_alua_tg_pt_gp *tg_pt_gp = NULL, *tg_pt_gp_new = NULL; struct t10_alua_tg_pt_gp *tg_pt_gp = NULL, *tg_pt_gp_new = NULL;
struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
unsigned char buf[TG_PT_GROUP_NAME_BUF]; unsigned char buf[TG_PT_GROUP_NAME_BUF];
int move = 0; int move = 0;
tpg = port->sep_tpg; if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH ||
lun = port->sep_lun; (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE))
return -ENODEV;
tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
if (!tg_pt_gp_mem)
return 0;
if (count > TG_PT_GROUP_NAME_BUF) { if (count > TG_PT_GROUP_NAME_BUF) {
pr_err("ALUA Target Port Group alias too large!\n"); pr_err("ALUA Target Port Group alias too large!\n");
@ -2049,8 +1996,8 @@ ssize_t core_alua_store_tg_pt_gp_info(
return -ENODEV; return -ENODEV;
} }
spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); spin_lock(&lun->lun_tg_pt_gp_lock);
tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; tg_pt_gp = lun->lun_tg_pt_gp;
if (tg_pt_gp) { if (tg_pt_gp) {
/* /*
* Clearing an existing tg_pt_gp association, and replacing * Clearing an existing tg_pt_gp association, and replacing
@ -2068,24 +2015,19 @@ ssize_t core_alua_store_tg_pt_gp_info(
&tg_pt_gp->tg_pt_gp_group.cg_item), &tg_pt_gp->tg_pt_gp_group.cg_item),
tg_pt_gp->tg_pt_gp_id); tg_pt_gp->tg_pt_gp_id);
__core_alua_drop_tg_pt_gp_mem(tg_pt_gp_mem, tg_pt_gp); __target_detach_tg_pt_gp(lun, tg_pt_gp);
__core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem, __target_attach_tg_pt_gp(lun,
dev->t10_alua.default_tg_pt_gp); dev->t10_alua.default_tg_pt_gp);
spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); spin_unlock(&lun->lun_tg_pt_gp_lock);
return count; return count;
} }
/* __target_detach_tg_pt_gp(lun, tg_pt_gp);
* Removing existing association of tg_pt_gp_mem with tg_pt_gp
*/
__core_alua_drop_tg_pt_gp_mem(tg_pt_gp_mem, tg_pt_gp);
move = 1; move = 1;
} }
/*
* Associate tg_pt_gp_mem with tg_pt_gp_new. __target_attach_tg_pt_gp(lun, tg_pt_gp_new);
*/ spin_unlock(&lun->lun_tg_pt_gp_lock);
__core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem, tg_pt_gp_new);
spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
pr_debug("Target_Core_ConfigFS: %s %s/tpgt_%hu/%s to ALUA" pr_debug("Target_Core_ConfigFS: %s %s/tpgt_%hu/%s to ALUA"
" Target Port Group: alua/%s, ID: %hu\n", (move) ? " Target Port Group: alua/%s, ID: %hu\n", (move) ?
"Moving" : "Adding", tpg->se_tpg_tfo->tpg_get_wwn(tpg), "Moving" : "Adding", tpg->se_tpg_tfo->tpg_get_wwn(tpg),
@ -2268,11 +2210,8 @@ ssize_t core_alua_store_preferred_bit(
ssize_t core_alua_show_offline_bit(struct se_lun *lun, char *page) ssize_t core_alua_show_offline_bit(struct se_lun *lun, char *page)
{ {
if (!lun->lun_sep)
return -ENODEV;
return sprintf(page, "%d\n", return sprintf(page, "%d\n",
atomic_read(&lun->lun_sep->sep_tg_pt_secondary_offline)); atomic_read(&lun->lun_tg_pt_secondary_offline));
} }
ssize_t core_alua_store_offline_bit( ssize_t core_alua_store_offline_bit(
@ -2280,11 +2219,16 @@ ssize_t core_alua_store_offline_bit(
const char *page, const char *page,
size_t count) size_t count)
{ {
struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; /*
* rcu_dereference_raw protected by se_lun->lun_group symlink
* reference to se_device->dev_group.
*/
struct se_device *dev = rcu_dereference_raw(lun->lun_se_dev);
unsigned long tmp; unsigned long tmp;
int ret; int ret;
if (!lun->lun_sep) if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH ||
(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE))
return -ENODEV; return -ENODEV;
ret = kstrtoul(page, 0, &tmp); ret = kstrtoul(page, 0, &tmp);
@ -2297,14 +2241,8 @@ ssize_t core_alua_store_offline_bit(
tmp); tmp);
return -EINVAL; return -EINVAL;
} }
tg_pt_gp_mem = lun->lun_sep->sep_alua_tg_pt_gp_mem;
if (!tg_pt_gp_mem) {
pr_err("Unable to locate *tg_pt_gp_mem\n");
return -EINVAL;
}
ret = core_alua_set_tg_pt_secondary_state(tg_pt_gp_mem, ret = core_alua_set_tg_pt_secondary_state(lun, 0, (int)tmp);
lun->lun_sep, 0, (int)tmp);
if (ret < 0) if (ret < 0)
return -EINVAL; return -EINVAL;
@ -2315,7 +2253,7 @@ ssize_t core_alua_show_secondary_status(
struct se_lun *lun, struct se_lun *lun,
char *page) char *page)
{ {
return sprintf(page, "%d\n", lun->lun_sep->sep_tg_pt_secondary_stat); return sprintf(page, "%d\n", lun->lun_tg_pt_secondary_stat);
} }
ssize_t core_alua_store_secondary_status( ssize_t core_alua_store_secondary_status(
@ -2338,7 +2276,7 @@ ssize_t core_alua_store_secondary_status(
tmp); tmp);
return -EINVAL; return -EINVAL;
} }
lun->lun_sep->sep_tg_pt_secondary_stat = (int)tmp; lun->lun_tg_pt_secondary_stat = (int)tmp;
return count; return count;
} }
@ -2347,8 +2285,7 @@ ssize_t core_alua_show_secondary_write_metadata(
struct se_lun *lun, struct se_lun *lun,
char *page) char *page)
{ {
return sprintf(page, "%d\n", return sprintf(page, "%d\n", lun->lun_tg_pt_secondary_write_md);
lun->lun_sep->sep_tg_pt_secondary_write_md);
} }
ssize_t core_alua_store_secondary_write_metadata( ssize_t core_alua_store_secondary_write_metadata(
@ -2369,7 +2306,7 @@ ssize_t core_alua_store_secondary_write_metadata(
" %lu\n", tmp); " %lu\n", tmp);
return -EINVAL; return -EINVAL;
} }
lun->lun_sep->sep_tg_pt_secondary_write_md = (int)tmp; lun->lun_tg_pt_secondary_write_md = (int)tmp;
return count; return count;
} }

View File

@ -85,7 +85,6 @@
extern struct kmem_cache *t10_alua_lu_gp_cache; extern struct kmem_cache *t10_alua_lu_gp_cache;
extern struct kmem_cache *t10_alua_lu_gp_mem_cache; extern struct kmem_cache *t10_alua_lu_gp_mem_cache;
extern struct kmem_cache *t10_alua_tg_pt_gp_cache; extern struct kmem_cache *t10_alua_tg_pt_gp_cache;
extern struct kmem_cache *t10_alua_tg_pt_gp_mem_cache;
extern struct kmem_cache *t10_alua_lba_map_cache; extern struct kmem_cache *t10_alua_lba_map_cache;
extern struct kmem_cache *t10_alua_lba_map_mem_cache; extern struct kmem_cache *t10_alua_lba_map_mem_cache;
@ -94,7 +93,7 @@ extern sense_reason_t target_emulate_set_target_port_groups(struct se_cmd *);
extern sense_reason_t target_emulate_report_referrals(struct se_cmd *); extern sense_reason_t target_emulate_report_referrals(struct se_cmd *);
extern int core_alua_check_nonop_delay(struct se_cmd *); extern int core_alua_check_nonop_delay(struct se_cmd *);
extern int core_alua_do_port_transition(struct t10_alua_tg_pt_gp *, extern int core_alua_do_port_transition(struct t10_alua_tg_pt_gp *,
struct se_device *, struct se_port *, struct se_device *, struct se_lun *,
struct se_node_acl *, int, int); struct se_node_acl *, int, int);
extern char *core_alua_dump_status(int); extern char *core_alua_dump_status(int);
extern struct t10_alua_lba_map *core_alua_allocate_lba_map( extern struct t10_alua_lba_map *core_alua_allocate_lba_map(
@ -117,14 +116,11 @@ extern void core_alua_drop_lu_gp_dev(struct se_device *);
extern struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp( extern struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(
struct se_device *, const char *, int); struct se_device *, const char *, int);
extern int core_alua_set_tg_pt_gp_id(struct t10_alua_tg_pt_gp *, u16); extern int core_alua_set_tg_pt_gp_id(struct t10_alua_tg_pt_gp *, u16);
extern struct t10_alua_tg_pt_gp_member *core_alua_allocate_tg_pt_gp_mem(
struct se_port *);
extern void core_alua_free_tg_pt_gp(struct t10_alua_tg_pt_gp *); extern void core_alua_free_tg_pt_gp(struct t10_alua_tg_pt_gp *);
extern void core_alua_free_tg_pt_gp_mem(struct se_port *); extern void target_detach_tg_pt_gp(struct se_lun *);
extern void __core_alua_attach_tg_pt_gp_mem(struct t10_alua_tg_pt_gp_member *, extern void target_attach_tg_pt_gp(struct se_lun *, struct t10_alua_tg_pt_gp *);
struct t10_alua_tg_pt_gp *); extern ssize_t core_alua_show_tg_pt_gp_info(struct se_lun *, char *);
extern ssize_t core_alua_show_tg_pt_gp_info(struct se_port *, char *); extern ssize_t core_alua_store_tg_pt_gp_info(struct se_lun *, const char *,
extern ssize_t core_alua_store_tg_pt_gp_info(struct se_port *, const char *,
size_t); size_t);
extern ssize_t core_alua_show_access_type(struct t10_alua_tg_pt_gp *, char *); extern ssize_t core_alua_show_access_type(struct t10_alua_tg_pt_gp *, char *);
extern ssize_t core_alua_store_access_type(struct t10_alua_tg_pt_gp *, extern ssize_t core_alua_store_access_type(struct t10_alua_tg_pt_gp *,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -36,7 +36,6 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/target_core_fabric_configfs.h> #include <target/target_core_fabric_configfs.h>
#include <target/target_core_configfs.h>
#include <target/configfs_macros.h> #include <target/configfs_macros.h>
#include "target_core_internal.h" #include "target_core_internal.h"
@ -46,27 +45,25 @@
#define TF_CIT_SETUP(_name, _item_ops, _group_ops, _attrs) \ #define TF_CIT_SETUP(_name, _item_ops, _group_ops, _attrs) \
static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf) \ static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf) \
{ \ { \
struct target_fabric_configfs_template *tfc = &tf->tf_cit_tmpl; \ struct config_item_type *cit = &tf->tf_##_name##_cit; \
struct config_item_type *cit = &tfc->tfc_##_name##_cit; \
\ \
cit->ct_item_ops = _item_ops; \ cit->ct_item_ops = _item_ops; \
cit->ct_group_ops = _group_ops; \ cit->ct_group_ops = _group_ops; \
cit->ct_attrs = _attrs; \ cit->ct_attrs = _attrs; \
cit->ct_owner = tf->tf_module; \ cit->ct_owner = tf->tf_ops->module; \
pr_debug("Setup generic %s\n", __stringify(_name)); \ pr_debug("Setup generic %s\n", __stringify(_name)); \
} }
#define TF_CIT_SETUP_DRV(_name, _item_ops, _group_ops) \ #define TF_CIT_SETUP_DRV(_name, _item_ops, _group_ops) \
static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf) \ static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf) \
{ \ { \
struct target_fabric_configfs_template *tfc = &tf->tf_cit_tmpl; \ struct config_item_type *cit = &tf->tf_##_name##_cit; \
struct config_item_type *cit = &tfc->tfc_##_name##_cit; \ struct configfs_attribute **attrs = tf->tf_ops->tfc_##_name##_attrs; \
struct configfs_attribute **attrs = tf->tf_ops.tfc_##_name##_attrs; \
\ \
cit->ct_item_ops = _item_ops; \ cit->ct_item_ops = _item_ops; \
cit->ct_group_ops = _group_ops; \ cit->ct_group_ops = _group_ops; \
cit->ct_attrs = attrs; \ cit->ct_attrs = attrs; \
cit->ct_owner = tf->tf_module; \ cit->ct_owner = tf->tf_ops->module; \
pr_debug("Setup generic %s\n", __stringify(_name)); \ pr_debug("Setup generic %s\n", __stringify(_name)); \
} }
@ -83,7 +80,7 @@ static int target_fabric_mappedlun_link(
struct se_lun_acl, se_lun_group); struct se_lun_acl, se_lun_group);
struct se_portal_group *se_tpg; struct se_portal_group *se_tpg;
struct config_item *nacl_ci, *tpg_ci, *tpg_ci_s, *wwn_ci, *wwn_ci_s; struct config_item *nacl_ci, *tpg_ci, *tpg_ci_s, *wwn_ci, *wwn_ci_s;
int ret = 0, lun_access; int lun_access;
if (lun->lun_link_magic != SE_LUN_LINK_MAGIC) { if (lun->lun_link_magic != SE_LUN_LINK_MAGIC) {
pr_err("Bad lun->lun_link_magic, not a valid lun_ci pointer:" pr_err("Bad lun->lun_link_magic, not a valid lun_ci pointer:"
@ -93,12 +90,11 @@ static int target_fabric_mappedlun_link(
/* /*
* Ensure that the source port exists * Ensure that the source port exists
*/ */
if (!lun->lun_sep || !lun->lun_sep->sep_tpg) { if (!lun->lun_se_dev) {
pr_err("Source se_lun->lun_sep or lun->lun_sep->sep" pr_err("Source se_lun->lun_se_dev does not exist\n");
"_tpg does not exist\n");
return -EINVAL; return -EINVAL;
} }
se_tpg = lun->lun_sep->sep_tpg; se_tpg = lun->lun_tpg;
nacl_ci = &lun_acl_ci->ci_parent->ci_group->cg_item; nacl_ci = &lun_acl_ci->ci_parent->ci_group->cg_item;
tpg_ci = &nacl_ci->ci_group->cg_item; tpg_ci = &nacl_ci->ci_group->cg_item;
@ -125,49 +121,35 @@ static int target_fabric_mappedlun_link(
* which be will write protected (READ-ONLY) when * which be will write protected (READ-ONLY) when
* tpg_1/attrib/demo_mode_write_protect=1 * tpg_1/attrib/demo_mode_write_protect=1
*/ */
spin_lock_irq(&lacl->se_lun_nacl->device_list_lock); rcu_read_lock();
deve = lacl->se_lun_nacl->device_list[lacl->mapped_lun]; deve = target_nacl_find_deve(lacl->se_lun_nacl, lacl->mapped_lun);
if (deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS) if (deve)
lun_access = deve->lun_flags; lun_access = deve->lun_flags;
else else
lun_access = lun_access =
(se_tpg->se_tpg_tfo->tpg_check_prod_mode_write_protect( (se_tpg->se_tpg_tfo->tpg_check_prod_mode_write_protect(
se_tpg)) ? TRANSPORT_LUNFLAGS_READ_ONLY : se_tpg)) ? TRANSPORT_LUNFLAGS_READ_ONLY :
TRANSPORT_LUNFLAGS_READ_WRITE; TRANSPORT_LUNFLAGS_READ_WRITE;
spin_unlock_irq(&lacl->se_lun_nacl->device_list_lock); rcu_read_unlock();
/* /*
* Determine the actual mapped LUN value user wants.. * Determine the actual mapped LUN value user wants..
* *
* This value is what the SCSI Initiator actually sees the * This value is what the SCSI Initiator actually sees the
* iscsi/$IQN/$TPGT/lun/lun_* as on their SCSI Initiator Ports. * $FABRIC/$WWPN/$TPGT/lun/lun_* as on their SCSI Initiator Ports.
*/ */
ret = core_dev_add_initiator_node_lun_acl(se_tpg, lacl, return core_dev_add_initiator_node_lun_acl(se_tpg, lacl, lun, lun_access);
lun->unpacked_lun, lun_access);
return (ret < 0) ? -EINVAL : 0;
} }
static int target_fabric_mappedlun_unlink( static int target_fabric_mappedlun_unlink(
struct config_item *lun_acl_ci, struct config_item *lun_acl_ci,
struct config_item *lun_ci) struct config_item *lun_ci)
{ {
struct se_lun *lun;
struct se_lun_acl *lacl = container_of(to_config_group(lun_acl_ci), struct se_lun_acl *lacl = container_of(to_config_group(lun_acl_ci),
struct se_lun_acl, se_lun_group); struct se_lun_acl, se_lun_group);
struct se_node_acl *nacl = lacl->se_lun_nacl; struct se_lun *lun = container_of(to_config_group(lun_ci),
struct se_dev_entry *deve = nacl->device_list[lacl->mapped_lun]; struct se_lun, lun_group);
struct se_portal_group *se_tpg;
/*
* Determine if the underlying MappedLUN has already been released..
*/
if (!deve->se_lun)
return 0;
lun = container_of(to_config_group(lun_ci), struct se_lun, lun_group); return core_dev_del_initiator_node_lun_acl(lun, lacl);
se_tpg = lun->lun_sep->sep_tpg;
core_dev_del_initiator_node_lun_acl(se_tpg, lun, lacl);
return 0;
} }
CONFIGFS_EATTR_STRUCT(target_fabric_mappedlun, se_lun_acl); CONFIGFS_EATTR_STRUCT(target_fabric_mappedlun, se_lun_acl);
@ -183,14 +165,15 @@ static ssize_t target_fabric_mappedlun_show_write_protect(
{ {
struct se_node_acl *se_nacl = lacl->se_lun_nacl; struct se_node_acl *se_nacl = lacl->se_lun_nacl;
struct se_dev_entry *deve; struct se_dev_entry *deve;
ssize_t len; ssize_t len = 0;
spin_lock_irq(&se_nacl->device_list_lock); rcu_read_lock();
deve = se_nacl->device_list[lacl->mapped_lun]; deve = target_nacl_find_deve(se_nacl, lacl->mapped_lun);
len = sprintf(page, "%d\n", if (deve) {
(deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) ? len = sprintf(page, "%d\n",
1 : 0); (deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) ? 1 : 0);
spin_unlock_irq(&se_nacl->device_list_lock); }
rcu_read_unlock();
return len; return len;
} }
@ -218,7 +201,7 @@ static ssize_t target_fabric_mappedlun_store_write_protect(
lacl->se_lun_nacl); lacl->se_lun_nacl);
pr_debug("%s_ConfigFS: Changed Initiator ACL: %s" pr_debug("%s_ConfigFS: Changed Initiator ACL: %s"
" Mapped LUN: %u Write Protect bit to %s\n", " Mapped LUN: %llu Write Protect bit to %s\n",
se_tpg->se_tpg_tfo->get_fabric_name(), se_tpg->se_tpg_tfo->get_fabric_name(),
lacl->initiatorname, lacl->mapped_lun, (op) ? "ON" : "OFF"); lacl->initiatorname, lacl->mapped_lun, (op) ? "ON" : "OFF");
@ -338,7 +321,7 @@ static struct config_group *target_fabric_make_mappedlun(
struct config_item *acl_ci; struct config_item *acl_ci;
struct config_group *lacl_cg = NULL, *ml_stat_grp = NULL; struct config_group *lacl_cg = NULL, *ml_stat_grp = NULL;
char *buf; char *buf;
unsigned long mapped_lun; unsigned long long mapped_lun;
int ret = 0; int ret = 0;
acl_ci = &group->cg_item; acl_ci = &group->cg_item;
@ -366,21 +349,9 @@ static struct config_group *target_fabric_make_mappedlun(
* Determine the Mapped LUN value. This is what the SCSI Initiator * Determine the Mapped LUN value. This is what the SCSI Initiator
* Port will actually see. * Port will actually see.
*/ */
ret = kstrtoul(buf + 4, 0, &mapped_lun); ret = kstrtoull(buf + 4, 0, &mapped_lun);
if (ret) if (ret)
goto out; goto out;
if (mapped_lun > UINT_MAX) {
ret = -EINVAL;
goto out;
}
if (mapped_lun > (TRANSPORT_MAX_LUNS_PER_TPG-1)) {
pr_err("Mapped LUN: %lu exceeds TRANSPORT_MAX_LUNS_PER_TPG"
"-1: %u for Target Portal Group: %u\n", mapped_lun,
TRANSPORT_MAX_LUNS_PER_TPG-1,
se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg));
ret = -EINVAL;
goto out;
}
lacl = core_dev_init_initiator_node_lun_acl(se_tpg, se_nacl, lacl = core_dev_init_initiator_node_lun_acl(se_tpg, se_nacl,
mapped_lun, &ret); mapped_lun, &ret);
@ -399,9 +370,9 @@ static struct config_group *target_fabric_make_mappedlun(
} }
config_group_init_type_name(&lacl->se_lun_group, name, config_group_init_type_name(&lacl->se_lun_group, name,
&tf->tf_cit_tmpl.tfc_tpg_mappedlun_cit); &tf->tf_tpg_mappedlun_cit);
config_group_init_type_name(&lacl->ml_stat_grps.stat_group, config_group_init_type_name(&lacl->ml_stat_grps.stat_group,
"statistics", &tf->tf_cit_tmpl.tfc_tpg_mappedlun_stat_cit); "statistics", &tf->tf_tpg_mappedlun_stat_cit);
lacl_cg->default_groups[0] = &lacl->ml_stat_grps.stat_group; lacl_cg->default_groups[0] = &lacl->ml_stat_grps.stat_group;
lacl_cg->default_groups[1] = NULL; lacl_cg->default_groups[1] = NULL;
@ -458,10 +429,11 @@ static void target_fabric_nacl_base_release(struct config_item *item)
{ {
struct se_node_acl *se_nacl = container_of(to_config_group(item), struct se_node_acl *se_nacl = container_of(to_config_group(item),
struct se_node_acl, acl_group); struct se_node_acl, acl_group);
struct se_portal_group *se_tpg = se_nacl->se_tpg; struct target_fabric_configfs *tf = se_nacl->se_tpg->se_tpg_wwn->wwn_tf;
struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
tf->tf_ops.fabric_drop_nodeacl(se_nacl); if (tf->tf_ops->fabric_cleanup_nodeacl)
tf->tf_ops->fabric_cleanup_nodeacl(se_nacl);
core_tpg_del_initiator_node_acl(se_nacl);
} }
static struct configfs_item_operations target_fabric_nacl_base_item_ops = { static struct configfs_item_operations target_fabric_nacl_base_item_ops = {
@ -501,15 +473,18 @@ static struct config_group *target_fabric_make_nodeacl(
struct se_node_acl *se_nacl; struct se_node_acl *se_nacl;
struct config_group *nacl_cg; struct config_group *nacl_cg;
if (!tf->tf_ops.fabric_make_nodeacl) { se_nacl = core_tpg_add_initiator_node_acl(se_tpg, name);
pr_err("tf->tf_ops.fabric_make_nodeacl is NULL\n");
return ERR_PTR(-ENOSYS);
}
se_nacl = tf->tf_ops.fabric_make_nodeacl(se_tpg, group, name);
if (IS_ERR(se_nacl)) if (IS_ERR(se_nacl))
return ERR_CAST(se_nacl); return ERR_CAST(se_nacl);
if (tf->tf_ops->fabric_init_nodeacl) {
int ret = tf->tf_ops->fabric_init_nodeacl(se_nacl, name);
if (ret) {
core_tpg_del_initiator_node_acl(se_nacl);
return ERR_PTR(ret);
}
}
nacl_cg = &se_nacl->acl_group; nacl_cg = &se_nacl->acl_group;
nacl_cg->default_groups = se_nacl->acl_default_groups; nacl_cg->default_groups = se_nacl->acl_default_groups;
nacl_cg->default_groups[0] = &se_nacl->acl_attrib_group; nacl_cg->default_groups[0] = &se_nacl->acl_attrib_group;
@ -519,16 +494,15 @@ static struct config_group *target_fabric_make_nodeacl(
nacl_cg->default_groups[4] = NULL; nacl_cg->default_groups[4] = NULL;
config_group_init_type_name(&se_nacl->acl_group, name, config_group_init_type_name(&se_nacl->acl_group, name,
&tf->tf_cit_tmpl.tfc_tpg_nacl_base_cit); &tf->tf_tpg_nacl_base_cit);
config_group_init_type_name(&se_nacl->acl_attrib_group, "attrib", config_group_init_type_name(&se_nacl->acl_attrib_group, "attrib",
&tf->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit); &tf->tf_tpg_nacl_attrib_cit);
config_group_init_type_name(&se_nacl->acl_auth_group, "auth", config_group_init_type_name(&se_nacl->acl_auth_group, "auth",
&tf->tf_cit_tmpl.tfc_tpg_nacl_auth_cit); &tf->tf_tpg_nacl_auth_cit);
config_group_init_type_name(&se_nacl->acl_param_group, "param", config_group_init_type_name(&se_nacl->acl_param_group, "param",
&tf->tf_cit_tmpl.tfc_tpg_nacl_param_cit); &tf->tf_tpg_nacl_param_cit);
config_group_init_type_name(&se_nacl->acl_fabric_stat_group, config_group_init_type_name(&se_nacl->acl_fabric_stat_group,
"fabric_statistics", "fabric_statistics", &tf->tf_tpg_nacl_stat_cit);
&tf->tf_cit_tmpl.tfc_tpg_nacl_stat_cit);
return &se_nacl->acl_group; return &se_nacl->acl_group;
} }
@ -575,7 +549,7 @@ static void target_fabric_np_base_release(struct config_item *item)
struct se_portal_group *se_tpg = se_tpg_np->tpg_np_parent; struct se_portal_group *se_tpg = se_tpg_np->tpg_np_parent;
struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
tf->tf_ops.fabric_drop_np(se_tpg_np); tf->tf_ops->fabric_drop_np(se_tpg_np);
} }
static struct configfs_item_operations target_fabric_np_base_item_ops = { static struct configfs_item_operations target_fabric_np_base_item_ops = {
@ -599,18 +573,18 @@ static struct config_group *target_fabric_make_np(
struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
struct se_tpg_np *se_tpg_np; struct se_tpg_np *se_tpg_np;
if (!tf->tf_ops.fabric_make_np) { if (!tf->tf_ops->fabric_make_np) {
pr_err("tf->tf_ops.fabric_make_np is NULL\n"); pr_err("tf->tf_ops.fabric_make_np is NULL\n");
return ERR_PTR(-ENOSYS); return ERR_PTR(-ENOSYS);
} }
se_tpg_np = tf->tf_ops.fabric_make_np(se_tpg, group, name); se_tpg_np = tf->tf_ops->fabric_make_np(se_tpg, group, name);
if (!se_tpg_np || IS_ERR(se_tpg_np)) if (!se_tpg_np || IS_ERR(se_tpg_np))
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
se_tpg_np->tpg_np_parent = se_tpg; se_tpg_np->tpg_np_parent = se_tpg;
config_group_init_type_name(&se_tpg_np->tpg_np_group, name, config_group_init_type_name(&se_tpg_np->tpg_np_group, name,
&tf->tf_cit_tmpl.tfc_tpg_np_base_cit); &tf->tf_tpg_np_base_cit);
return &se_tpg_np->tpg_np_group; return &se_tpg_np->tpg_np_group;
} }
@ -654,10 +628,10 @@ static ssize_t target_fabric_port_show_attr_alua_tg_pt_gp(
struct se_lun *lun, struct se_lun *lun,
char *page) char *page)
{ {
if (!lun || !lun->lun_sep) if (!lun || !lun->lun_se_dev)
return -ENODEV; return -ENODEV;
return core_alua_show_tg_pt_gp_info(lun->lun_sep, page); return core_alua_show_tg_pt_gp_info(lun, page);
} }
static ssize_t target_fabric_port_store_attr_alua_tg_pt_gp( static ssize_t target_fabric_port_store_attr_alua_tg_pt_gp(
@ -665,10 +639,10 @@ static ssize_t target_fabric_port_store_attr_alua_tg_pt_gp(
const char *page, const char *page,
size_t count) size_t count)
{ {
if (!lun || !lun->lun_sep) if (!lun || !lun->lun_se_dev)
return -ENODEV; return -ENODEV;
return core_alua_store_tg_pt_gp_info(lun->lun_sep, page, count); return core_alua_store_tg_pt_gp_info(lun, page, count);
} }
TCM_PORT_ATTR(alua_tg_pt_gp, S_IRUGO | S_IWUSR); TCM_PORT_ATTR(alua_tg_pt_gp, S_IRUGO | S_IWUSR);
@ -680,7 +654,7 @@ static ssize_t target_fabric_port_show_attr_alua_tg_pt_offline(
struct se_lun *lun, struct se_lun *lun,
char *page) char *page)
{ {
if (!lun || !lun->lun_sep) if (!lun || !lun->lun_se_dev)
return -ENODEV; return -ENODEV;
return core_alua_show_offline_bit(lun, page); return core_alua_show_offline_bit(lun, page);
@ -691,7 +665,7 @@ static ssize_t target_fabric_port_store_attr_alua_tg_pt_offline(
const char *page, const char *page,
size_t count) size_t count)
{ {
if (!lun || !lun->lun_sep) if (!lun || !lun->lun_se_dev)
return -ENODEV; return -ENODEV;
return core_alua_store_offline_bit(lun, page, count); return core_alua_store_offline_bit(lun, page, count);
@ -706,7 +680,7 @@ static ssize_t target_fabric_port_show_attr_alua_tg_pt_status(
struct se_lun *lun, struct se_lun *lun,
char *page) char *page)
{ {
if (!lun || !lun->lun_sep) if (!lun || !lun->lun_se_dev)
return -ENODEV; return -ENODEV;
return core_alua_show_secondary_status(lun, page); return core_alua_show_secondary_status(lun, page);
@ -717,7 +691,7 @@ static ssize_t target_fabric_port_store_attr_alua_tg_pt_status(
const char *page, const char *page,
size_t count) size_t count)
{ {
if (!lun || !lun->lun_sep) if (!lun || !lun->lun_se_dev)
return -ENODEV; return -ENODEV;
return core_alua_store_secondary_status(lun, page, count); return core_alua_store_secondary_status(lun, page, count);
@ -732,7 +706,7 @@ static ssize_t target_fabric_port_show_attr_alua_tg_pt_write_md(
struct se_lun *lun, struct se_lun *lun,
char *page) char *page)
{ {
if (!lun || !lun->lun_sep) if (!lun || !lun->lun_se_dev)
return -ENODEV; return -ENODEV;
return core_alua_show_secondary_write_metadata(lun, page); return core_alua_show_secondary_write_metadata(lun, page);
@ -743,7 +717,7 @@ static ssize_t target_fabric_port_store_attr_alua_tg_pt_write_md(
const char *page, const char *page,
size_t count) size_t count)
{ {
if (!lun || !lun->lun_sep) if (!lun || !lun->lun_se_dev)
return -ENODEV; return -ENODEV;
return core_alua_store_secondary_write_metadata(lun, page, count); return core_alua_store_secondary_write_metadata(lun, page, count);
@ -769,7 +743,6 @@ static int target_fabric_port_link(
struct config_item *tpg_ci; struct config_item *tpg_ci;
struct se_lun *lun = container_of(to_config_group(lun_ci), struct se_lun *lun = container_of(to_config_group(lun_ci),
struct se_lun, lun_group); struct se_lun, lun_group);
struct se_lun *lun_p;
struct se_portal_group *se_tpg; struct se_portal_group *se_tpg;
struct se_device *dev = struct se_device *dev =
container_of(to_config_group(se_dev_ci), struct se_device, dev_group); container_of(to_config_group(se_dev_ci), struct se_device, dev_group);
@ -797,20 +770,19 @@ static int target_fabric_port_link(
return -EEXIST; return -EEXIST;
} }
lun_p = core_dev_add_lun(se_tpg, dev, lun->unpacked_lun); ret = core_dev_add_lun(se_tpg, dev, lun);
if (IS_ERR(lun_p)) { if (ret) {
pr_err("core_dev_add_lun() failed\n"); pr_err("core_dev_add_lun() failed: %d\n", ret);
ret = PTR_ERR(lun_p);
goto out; goto out;
} }
if (tf->tf_ops.fabric_post_link) { if (tf->tf_ops->fabric_post_link) {
/* /*
* Call the optional fabric_post_link() to allow a * Call the optional fabric_post_link() to allow a
* fabric module to setup any additional state once * fabric module to setup any additional state once
* core_dev_add_lun() has been called.. * core_dev_add_lun() has been called..
*/ */
tf->tf_ops.fabric_post_link(se_tpg, lun); tf->tf_ops->fabric_post_link(se_tpg, lun);
} }
return 0; return 0;
@ -824,25 +796,34 @@ static int target_fabric_port_unlink(
{ {
struct se_lun *lun = container_of(to_config_group(lun_ci), struct se_lun *lun = container_of(to_config_group(lun_ci),
struct se_lun, lun_group); struct se_lun, lun_group);
struct se_portal_group *se_tpg = lun->lun_sep->sep_tpg; struct se_portal_group *se_tpg = lun->lun_tpg;
struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
if (tf->tf_ops.fabric_pre_unlink) { if (tf->tf_ops->fabric_pre_unlink) {
/* /*
* Call the optional fabric_pre_unlink() to allow a * Call the optional fabric_pre_unlink() to allow a
* fabric module to release any additional stat before * fabric module to release any additional stat before
* core_dev_del_lun() is called. * core_dev_del_lun() is called.
*/ */
tf->tf_ops.fabric_pre_unlink(se_tpg, lun); tf->tf_ops->fabric_pre_unlink(se_tpg, lun);
} }
core_dev_del_lun(se_tpg, lun); core_dev_del_lun(se_tpg, lun);
return 0; return 0;
} }
static void target_fabric_port_release(struct config_item *item)
{
struct se_lun *lun = container_of(to_config_group(item),
struct se_lun, lun_group);
kfree_rcu(lun, rcu_head);
}
static struct configfs_item_operations target_fabric_port_item_ops = { static struct configfs_item_operations target_fabric_port_item_ops = {
.show_attribute = target_fabric_port_attr_show, .show_attribute = target_fabric_port_attr_show,
.store_attribute = target_fabric_port_attr_store, .store_attribute = target_fabric_port_attr_store,
.release = target_fabric_port_release,
.allow_link = target_fabric_port_link, .allow_link = target_fabric_port_link,
.drop_link = target_fabric_port_unlink, .drop_link = target_fabric_port_unlink,
}; };
@ -887,7 +868,7 @@ static struct config_group *target_fabric_make_lun(
struct se_portal_group, tpg_lun_group); struct se_portal_group, tpg_lun_group);
struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf; struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
struct config_group *lun_cg = NULL, *port_stat_grp = NULL; struct config_group *lun_cg = NULL, *port_stat_grp = NULL;
unsigned long unpacked_lun; unsigned long long unpacked_lun;
int errno; int errno;
if (strstr(name, "lun_") != name) { if (strstr(name, "lun_") != name) {
@ -895,28 +876,27 @@ static struct config_group *target_fabric_make_lun(
" \"lun_$LUN_NUMBER\"\n"); " \"lun_$LUN_NUMBER\"\n");
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
errno = kstrtoul(name + 4, 0, &unpacked_lun); errno = kstrtoull(name + 4, 0, &unpacked_lun);
if (errno) if (errno)
return ERR_PTR(errno); return ERR_PTR(errno);
if (unpacked_lun > UINT_MAX)
return ERR_PTR(-EINVAL);
lun = core_get_lun_from_tpg(se_tpg, unpacked_lun); lun = core_tpg_alloc_lun(se_tpg, unpacked_lun);
if (!lun) if (IS_ERR(lun))
return ERR_PTR(-EINVAL); return ERR_CAST(lun);
lun_cg = &lun->lun_group; lun_cg = &lun->lun_group;
lun_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, lun_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2,
GFP_KERNEL); GFP_KERNEL);
if (!lun_cg->default_groups) { if (!lun_cg->default_groups) {
pr_err("Unable to allocate lun_cg->default_groups\n"); pr_err("Unable to allocate lun_cg->default_groups\n");
kfree(lun);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
config_group_init_type_name(&lun->lun_group, name, config_group_init_type_name(&lun->lun_group, name,
&tf->tf_cit_tmpl.tfc_tpg_port_cit); &tf->tf_tpg_port_cit);
config_group_init_type_name(&lun->port_stat_grps.stat_group, config_group_init_type_name(&lun->port_stat_grps.stat_group,
"statistics", &tf->tf_cit_tmpl.tfc_tpg_port_stat_cit); "statistics", &tf->tf_tpg_port_stat_cit);
lun_cg->default_groups[0] = &lun->port_stat_grps.stat_group; lun_cg->default_groups[0] = &lun->port_stat_grps.stat_group;
lun_cg->default_groups[1] = NULL; lun_cg->default_groups[1] = NULL;
@ -926,6 +906,7 @@ static struct config_group *target_fabric_make_lun(
if (!port_stat_grp->default_groups) { if (!port_stat_grp->default_groups) {
pr_err("Unable to allocate port_stat_grp->default_groups\n"); pr_err("Unable to allocate port_stat_grp->default_groups\n");
kfree(lun_cg->default_groups); kfree(lun_cg->default_groups);
kfree(lun);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
target_stat_setup_port_default_groups(lun); target_stat_setup_port_default_groups(lun);
@ -1023,7 +1004,7 @@ static void target_fabric_tpg_release(struct config_item *item)
struct se_wwn *wwn = se_tpg->se_tpg_wwn; struct se_wwn *wwn = se_tpg->se_tpg_wwn;
struct target_fabric_configfs *tf = wwn->wwn_tf; struct target_fabric_configfs *tf = wwn->wwn_tf;
tf->tf_ops.fabric_drop_tpg(se_tpg); tf->tf_ops->fabric_drop_tpg(se_tpg);
} }
static struct configfs_item_operations target_fabric_tpg_base_item_ops = { static struct configfs_item_operations target_fabric_tpg_base_item_ops = {
@ -1046,12 +1027,12 @@ static struct config_group *target_fabric_make_tpg(
struct target_fabric_configfs *tf = wwn->wwn_tf; struct target_fabric_configfs *tf = wwn->wwn_tf;
struct se_portal_group *se_tpg; struct se_portal_group *se_tpg;
if (!tf->tf_ops.fabric_make_tpg) { if (!tf->tf_ops->fabric_make_tpg) {
pr_err("tf->tf_ops.fabric_make_tpg is NULL\n"); pr_err("tf->tf_ops->fabric_make_tpg is NULL\n");
return ERR_PTR(-ENOSYS); return ERR_PTR(-ENOSYS);
} }
se_tpg = tf->tf_ops.fabric_make_tpg(wwn, group, name); se_tpg = tf->tf_ops->fabric_make_tpg(wwn, group, name);
if (!se_tpg || IS_ERR(se_tpg)) if (!se_tpg || IS_ERR(se_tpg))
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
/* /*
@ -1067,19 +1048,19 @@ static struct config_group *target_fabric_make_tpg(
se_tpg->tpg_group.default_groups[6] = NULL; se_tpg->tpg_group.default_groups[6] = NULL;
config_group_init_type_name(&se_tpg->tpg_group, name, config_group_init_type_name(&se_tpg->tpg_group, name,
&tf->tf_cit_tmpl.tfc_tpg_base_cit); &tf->tf_tpg_base_cit);
config_group_init_type_name(&se_tpg->tpg_lun_group, "lun", config_group_init_type_name(&se_tpg->tpg_lun_group, "lun",
&tf->tf_cit_tmpl.tfc_tpg_lun_cit); &tf->tf_tpg_lun_cit);
config_group_init_type_name(&se_tpg->tpg_np_group, "np", config_group_init_type_name(&se_tpg->tpg_np_group, "np",
&tf->tf_cit_tmpl.tfc_tpg_np_cit); &tf->tf_tpg_np_cit);
config_group_init_type_name(&se_tpg->tpg_acl_group, "acls", config_group_init_type_name(&se_tpg->tpg_acl_group, "acls",
&tf->tf_cit_tmpl.tfc_tpg_nacl_cit); &tf->tf_tpg_nacl_cit);
config_group_init_type_name(&se_tpg->tpg_attrib_group, "attrib", config_group_init_type_name(&se_tpg->tpg_attrib_group, "attrib",
&tf->tf_cit_tmpl.tfc_tpg_attrib_cit); &tf->tf_tpg_attrib_cit);
config_group_init_type_name(&se_tpg->tpg_auth_group, "auth", config_group_init_type_name(&se_tpg->tpg_auth_group, "auth",
&tf->tf_cit_tmpl.tfc_tpg_auth_cit); &tf->tf_tpg_auth_cit);
config_group_init_type_name(&se_tpg->tpg_param_group, "param", config_group_init_type_name(&se_tpg->tpg_param_group, "param",
&tf->tf_cit_tmpl.tfc_tpg_param_cit); &tf->tf_tpg_param_cit);
return &se_tpg->tpg_group; return &se_tpg->tpg_group;
} }
@ -1112,7 +1093,7 @@ static void target_fabric_release_wwn(struct config_item *item)
struct se_wwn, wwn_group); struct se_wwn, wwn_group);
struct target_fabric_configfs *tf = wwn->wwn_tf; struct target_fabric_configfs *tf = wwn->wwn_tf;
tf->tf_ops.fabric_drop_wwn(wwn); tf->tf_ops->fabric_drop_wwn(wwn);
} }
static struct configfs_item_operations target_fabric_tpg_item_ops = { static struct configfs_item_operations target_fabric_tpg_item_ops = {
@ -1148,12 +1129,12 @@ static struct config_group *target_fabric_make_wwn(
struct target_fabric_configfs, tf_group); struct target_fabric_configfs, tf_group);
struct se_wwn *wwn; struct se_wwn *wwn;
if (!tf->tf_ops.fabric_make_wwn) { if (!tf->tf_ops->fabric_make_wwn) {
pr_err("tf->tf_ops.fabric_make_wwn is NULL\n"); pr_err("tf->tf_ops.fabric_make_wwn is NULL\n");
return ERR_PTR(-ENOSYS); return ERR_PTR(-ENOSYS);
} }
wwn = tf->tf_ops.fabric_make_wwn(tf, group, name); wwn = tf->tf_ops->fabric_make_wwn(tf, group, name);
if (!wwn || IS_ERR(wwn)) if (!wwn || IS_ERR(wwn))
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
@ -1165,10 +1146,9 @@ static struct config_group *target_fabric_make_wwn(
wwn->wwn_group.default_groups[0] = &wwn->fabric_stat_group; wwn->wwn_group.default_groups[0] = &wwn->fabric_stat_group;
wwn->wwn_group.default_groups[1] = NULL; wwn->wwn_group.default_groups[1] = NULL;
config_group_init_type_name(&wwn->wwn_group, name, config_group_init_type_name(&wwn->wwn_group, name, &tf->tf_tpg_cit);
&tf->tf_cit_tmpl.tfc_tpg_cit);
config_group_init_type_name(&wwn->fabric_stat_group, "fabric_statistics", config_group_init_type_name(&wwn->fabric_stat_group, "fabric_statistics",
&tf->tf_cit_tmpl.tfc_wwn_fabric_stats_cit); &tf->tf_wwn_fabric_stats_cit);
return &wwn->wwn_group; return &wwn->wwn_group;
} }

View File

@ -24,6 +24,11 @@
* *
******************************************************************************/ ******************************************************************************/
/*
* See SPC4, section 7.5 "Protocol specific parameters" for details
* on the formats implemented in this file.
*/
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/ctype.h> #include <linux/ctype.h>
@ -34,124 +39,30 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
#include "target_core_internal.h" #include "target_core_internal.h"
#include "target_core_pr.h" #include "target_core_pr.h"
/*
* Handlers for Serial Attached SCSI (SAS)
*/
u8 sas_get_fabric_proto_ident(struct se_portal_group *se_tpg)
{
/*
* Return a SAS Serial SCSI Protocol identifier for loopback operations
* This is defined in section 7.5.1 Table 362 in spc4r17
*/
return 0x6;
}
EXPORT_SYMBOL(sas_get_fabric_proto_ident);
u32 sas_get_pr_transport_id( static int sas_get_pr_transport_id(
struct se_portal_group *se_tpg, struct se_node_acl *nacl,
struct se_node_acl *se_nacl,
struct t10_pr_registration *pr_reg,
int *format_code, int *format_code,
unsigned char *buf) unsigned char *buf)
{ {
unsigned char *ptr;
int ret; int ret;
/* /* Skip over 'naa. prefix */
* Set PROTOCOL IDENTIFIER to 6h for SAS ret = hex2bin(&buf[4], &nacl->initiatorname[4], 8);
*/ if (ret) {
buf[0] = 0x06; pr_debug("%s: invalid hex string\n", __func__);
/* return ret;
* From spc4r17, 7.5.4.7 TransportID for initiator ports using SCSI }
* over SAS Serial SCSI Protocol
*/
ptr = &se_nacl->initiatorname[4]; /* Skip over 'naa. prefix */
ret = hex2bin(&buf[4], ptr, 8);
if (ret < 0)
pr_debug("sas transport_id: invalid hex string\n");
/*
* The SAS Transport ID is a hardcoded 24-byte length
*/
return 24; return 24;
} }
EXPORT_SYMBOL(sas_get_pr_transport_id);
u32 sas_get_pr_transport_id_len( static int fc_get_pr_transport_id(
struct se_portal_group *se_tpg,
struct se_node_acl *se_nacl, struct se_node_acl *se_nacl,
struct t10_pr_registration *pr_reg,
int *format_code)
{
*format_code = 0;
/*
* From spc4r17, 7.5.4.7 TransportID for initiator ports using SCSI
* over SAS Serial SCSI Protocol
*
* The SAS Transport ID is a hardcoded 24-byte length
*/
return 24;
}
EXPORT_SYMBOL(sas_get_pr_transport_id_len);
/*
* Used for handling SCSI fabric dependent TransportIDs in SPC-3 and above
* Persistent Reservation SPEC_I_PT=1 and PROUT REGISTER_AND_MOVE operations.
*/
char *sas_parse_pr_out_transport_id(
struct se_portal_group *se_tpg,
const char *buf,
u32 *out_tid_len,
char **port_nexus_ptr)
{
/*
* Assume the FORMAT CODE 00b from spc4r17, 7.5.4.7 TransportID
* for initiator ports using SCSI over SAS Serial SCSI Protocol
*
* The TransportID for a SAS Initiator Port is of fixed size of
* 24 bytes, and SAS does not contain a I_T nexus identifier,
* so we return the **port_nexus_ptr set to NULL.
*/
*port_nexus_ptr = NULL;
*out_tid_len = 24;
return (char *)&buf[4];
}
EXPORT_SYMBOL(sas_parse_pr_out_transport_id);
/*
* Handlers for Fibre Channel Protocol (FCP)
*/
u8 fc_get_fabric_proto_ident(struct se_portal_group *se_tpg)
{
return 0x0; /* 0 = fcp-2 per SPC4 section 7.5.1 */
}
EXPORT_SYMBOL(fc_get_fabric_proto_ident);
u32 fc_get_pr_transport_id_len(
struct se_portal_group *se_tpg,
struct se_node_acl *se_nacl,
struct t10_pr_registration *pr_reg,
int *format_code)
{
*format_code = 0;
/*
* The FC Transport ID is a hardcoded 24-byte length
*/
return 24;
}
EXPORT_SYMBOL(fc_get_pr_transport_id_len);
u32 fc_get_pr_transport_id(
struct se_portal_group *se_tpg,
struct se_node_acl *se_nacl,
struct t10_pr_registration *pr_reg,
int *format_code, int *format_code,
unsigned char *buf) unsigned char *buf)
{ {
@ -160,24 +71,20 @@ u32 fc_get_pr_transport_id(
u32 off = 8; u32 off = 8;
/* /*
* PROTOCOL IDENTIFIER is 0h for FCP-2
*
* From spc4r17, 7.5.4.2 TransportID for initiator ports using
* SCSI over Fibre Channel
*
* We convert the ASCII formatted N Port name into a binary * We convert the ASCII formatted N Port name into a binary
* encoded TransportID. * encoded TransportID.
*/ */
ptr = &se_nacl->initiatorname[0]; ptr = &se_nacl->initiatorname[0];
for (i = 0; i < 24; ) { for (i = 0; i < 24; ) {
if (!strncmp(&ptr[i], ":", 1)) { if (!strncmp(&ptr[i], ":", 1)) {
i++; i++;
continue; continue;
} }
ret = hex2bin(&buf[off++], &ptr[i], 1); ret = hex2bin(&buf[off++], &ptr[i], 1);
if (ret < 0) if (ret < 0) {
pr_debug("fc transport_id: invalid hex string\n"); pr_debug("%s: invalid hex string\n", __func__);
return ret;
}
i += 2; i += 2;
} }
/* /*
@ -185,42 +92,52 @@ u32 fc_get_pr_transport_id(
*/ */
return 24; return 24;
} }
EXPORT_SYMBOL(fc_get_pr_transport_id);
char *fc_parse_pr_out_transport_id( static int sbp_get_pr_transport_id(
struct se_portal_group *se_tpg, struct se_node_acl *nacl,
const char *buf, int *format_code,
u32 *out_tid_len, unsigned char *buf)
char **port_nexus_ptr)
{ {
/* int ret;
* The TransportID for a FC N Port is of fixed size of
* 24 bytes, and FC does not contain a I_T nexus identifier,
* so we return the **port_nexus_ptr set to NULL.
*/
*port_nexus_ptr = NULL;
*out_tid_len = 24;
return (char *)&buf[8]; ret = hex2bin(&buf[8], nacl->initiatorname, 8);
if (ret) {
pr_debug("%s: invalid hex string\n", __func__);
return ret;
}
return 24;
} }
EXPORT_SYMBOL(fc_parse_pr_out_transport_id);
/* static int srp_get_pr_transport_id(
* Handlers for Internet Small Computer Systems Interface (iSCSI) struct se_node_acl *nacl,
*/ int *format_code,
unsigned char *buf)
u8 iscsi_get_fabric_proto_ident(struct se_portal_group *se_tpg)
{ {
/* const char *p;
* This value is defined for "Internet SCSI (iSCSI)" unsigned len, count, leading_zero_bytes;
* in spc4r17 section 7.5.1 Table 362 int rc;
*/
return 0x5;
}
EXPORT_SYMBOL(iscsi_get_fabric_proto_ident);
u32 iscsi_get_pr_transport_id( p = nacl->initiatorname;
struct se_portal_group *se_tpg, if (strncasecmp(p, "0x", 2) == 0)
p += 2;
len = strlen(p);
if (len % 2)
return -EINVAL;
count = min(len / 2, 16U);
leading_zero_bytes = 16 - count;
memset(buf + 8, 0, leading_zero_bytes);
rc = hex2bin(buf + 8 + leading_zero_bytes, p, count);
if (rc < 0) {
pr_debug("hex2bin failed for %s: %d\n", __func__, rc);
return rc;
}
return 24;
}
static int iscsi_get_pr_transport_id(
struct se_node_acl *se_nacl, struct se_node_acl *se_nacl,
struct t10_pr_registration *pr_reg, struct t10_pr_registration *pr_reg,
int *format_code, int *format_code,
@ -230,10 +147,6 @@ u32 iscsi_get_pr_transport_id(
u16 len = 0; u16 len = 0;
spin_lock_irq(&se_nacl->nacl_sess_lock); spin_lock_irq(&se_nacl->nacl_sess_lock);
/*
* Set PROTOCOL IDENTIFIER to 5h for iSCSI
*/
buf[0] = 0x05;
/* /*
* From spc4r17 Section 7.5.4.6: TransportID for initiator * From spc4r17 Section 7.5.4.6: TransportID for initiator
* ports using SCSI over iSCSI. * ports using SCSI over iSCSI.
@ -313,10 +226,8 @@ u32 iscsi_get_pr_transport_id(
return len; return len;
} }
EXPORT_SYMBOL(iscsi_get_pr_transport_id);
u32 iscsi_get_pr_transport_id_len( static int iscsi_get_pr_transport_id_len(
struct se_portal_group *se_tpg,
struct se_node_acl *se_nacl, struct se_node_acl *se_nacl,
struct t10_pr_registration *pr_reg, struct t10_pr_registration *pr_reg,
int *format_code) int *format_code)
@ -359,9 +270,8 @@ u32 iscsi_get_pr_transport_id_len(
return len; return len;
} }
EXPORT_SYMBOL(iscsi_get_pr_transport_id_len);
char *iscsi_parse_pr_out_transport_id( static char *iscsi_parse_pr_out_transport_id(
struct se_portal_group *se_tpg, struct se_portal_group *se_tpg,
const char *buf, const char *buf,
u32 *out_tid_len, u32 *out_tid_len,
@ -448,4 +358,79 @@ char *iscsi_parse_pr_out_transport_id(
return (char *)&buf[4]; return (char *)&buf[4];
} }
EXPORT_SYMBOL(iscsi_parse_pr_out_transport_id);
int target_get_pr_transport_id_len(struct se_node_acl *nacl,
struct t10_pr_registration *pr_reg, int *format_code)
{
switch (nacl->se_tpg->proto_id) {
case SCSI_PROTOCOL_FCP:
case SCSI_PROTOCOL_SBP:
case SCSI_PROTOCOL_SRP:
case SCSI_PROTOCOL_SAS:
break;
case SCSI_PROTOCOL_ISCSI:
return iscsi_get_pr_transport_id_len(nacl, pr_reg, format_code);
default:
pr_err("Unknown proto_id: 0x%02x\n", nacl->se_tpg->proto_id);
return -EINVAL;
}
/*
* Most transports use a fixed length 24 byte identifier.
*/
*format_code = 0;
return 24;
}
int target_get_pr_transport_id(struct se_node_acl *nacl,
struct t10_pr_registration *pr_reg, int *format_code,
unsigned char *buf)
{
switch (nacl->se_tpg->proto_id) {
case SCSI_PROTOCOL_SAS:
return sas_get_pr_transport_id(nacl, format_code, buf);
case SCSI_PROTOCOL_SBP:
return sbp_get_pr_transport_id(nacl, format_code, buf);
case SCSI_PROTOCOL_SRP:
return srp_get_pr_transport_id(nacl, format_code, buf);
case SCSI_PROTOCOL_FCP:
return fc_get_pr_transport_id(nacl, format_code, buf);
case SCSI_PROTOCOL_ISCSI:
return iscsi_get_pr_transport_id(nacl, pr_reg, format_code,
buf);
default:
pr_err("Unknown proto_id: 0x%02x\n", nacl->se_tpg->proto_id);
return -EINVAL;
}
}
const char *target_parse_pr_out_transport_id(struct se_portal_group *tpg,
const char *buf, u32 *out_tid_len, char **port_nexus_ptr)
{
u32 offset;
switch (tpg->proto_id) {
case SCSI_PROTOCOL_SAS:
/*
* Assume the FORMAT CODE 00b from spc4r17, 7.5.4.7 TransportID
* for initiator ports using SCSI over SAS Serial SCSI Protocol.
*/
offset = 4;
break;
case SCSI_PROTOCOL_SBP:
case SCSI_PROTOCOL_SRP:
case SCSI_PROTOCOL_FCP:
offset = 8;
break;
case SCSI_PROTOCOL_ISCSI:
return iscsi_parse_pr_out_transport_id(tpg, buf, out_tid_len,
port_nexus_ptr);
default:
pr_err("Unknown proto_id: 0x%02x\n", tpg->proto_id);
return NULL;
}
*port_nexus_ptr = NULL;
*out_tid_len = 24;
return buf + offset;
}

View File

@ -37,7 +37,6 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_backend.h> #include <target/target_core_backend.h>
#include <target/target_core_backend_configfs.h>
#include "target_core_file.h" #include "target_core_file.h"
@ -46,10 +45,6 @@ static inline struct fd_dev *FD_DEV(struct se_device *dev)
return container_of(dev, struct fd_dev, dev); return container_of(dev, struct fd_dev, dev);
} }
/* fd_attach_hba(): (Part of se_subsystem_api_t template)
*
*
*/
static int fd_attach_hba(struct se_hba *hba, u32 host_id) static int fd_attach_hba(struct se_hba *hba, u32 host_id)
{ {
struct fd_host *fd_host; struct fd_host *fd_host;
@ -66,7 +61,7 @@ static int fd_attach_hba(struct se_hba *hba, u32 host_id)
pr_debug("CORE_HBA[%d] - TCM FILEIO HBA Driver %s on Generic" pr_debug("CORE_HBA[%d] - TCM FILEIO HBA Driver %s on Generic"
" Target Core Stack %s\n", hba->hba_id, FD_VERSION, " Target Core Stack %s\n", hba->hba_id, FD_VERSION,
TARGET_CORE_MOD_VERSION); TARGET_CORE_VERSION);
pr_debug("CORE_HBA[%d] - Attached FILEIO HBA: %u to Generic\n", pr_debug("CORE_HBA[%d] - Attached FILEIO HBA: %u to Generic\n",
hba->hba_id, fd_host->fd_host_id); hba->hba_id, fd_host->fd_host_id);
@ -246,6 +241,14 @@ fail:
return ret; return ret;
} }
static void fd_dev_call_rcu(struct rcu_head *p)
{
struct se_device *dev = container_of(p, struct se_device, rcu_head);
struct fd_dev *fd_dev = FD_DEV(dev);
kfree(fd_dev);
}
static void fd_free_device(struct se_device *dev) static void fd_free_device(struct se_device *dev)
{ {
struct fd_dev *fd_dev = FD_DEV(dev); struct fd_dev *fd_dev = FD_DEV(dev);
@ -254,79 +257,18 @@ static void fd_free_device(struct se_device *dev)
filp_close(fd_dev->fd_file, NULL); filp_close(fd_dev->fd_file, NULL);
fd_dev->fd_file = NULL; fd_dev->fd_file = NULL;
} }
call_rcu(&dev->rcu_head, fd_dev_call_rcu);
kfree(fd_dev);
} }
static int fd_do_prot_rw(struct se_cmd *cmd, struct fd_prot *fd_prot, static int fd_do_rw(struct se_cmd *cmd, struct file *fd,
int is_write) u32 block_size, struct scatterlist *sgl,
u32 sgl_nents, u32 data_length, int is_write)
{ {
struct se_device *se_dev = cmd->se_dev;
struct fd_dev *dev = FD_DEV(se_dev);
struct file *prot_fd = dev->fd_prot_file;
loff_t pos = (cmd->t_task_lba * se_dev->prot_length);
unsigned char *buf;
u32 prot_size;
int rc, ret = 1;
prot_size = (cmd->data_length / se_dev->dev_attrib.block_size) *
se_dev->prot_length;
if (!is_write) {
fd_prot->prot_buf = kzalloc(prot_size, GFP_KERNEL);
if (!fd_prot->prot_buf) {
pr_err("Unable to allocate fd_prot->prot_buf\n");
return -ENOMEM;
}
buf = fd_prot->prot_buf;
fd_prot->prot_sg_nents = 1;
fd_prot->prot_sg = kzalloc(sizeof(struct scatterlist),
GFP_KERNEL);
if (!fd_prot->prot_sg) {
pr_err("Unable to allocate fd_prot->prot_sg\n");
kfree(fd_prot->prot_buf);
return -ENOMEM;
}
sg_init_table(fd_prot->prot_sg, fd_prot->prot_sg_nents);
sg_set_buf(fd_prot->prot_sg, buf, prot_size);
}
if (is_write) {
rc = kernel_write(prot_fd, fd_prot->prot_buf, prot_size, pos);
if (rc < 0 || prot_size != rc) {
pr_err("kernel_write() for fd_do_prot_rw failed:"
" %d\n", rc);
ret = -EINVAL;
}
} else {
rc = kernel_read(prot_fd, pos, fd_prot->prot_buf, prot_size);
if (rc < 0) {
pr_err("kernel_read() for fd_do_prot_rw failed:"
" %d\n", rc);
ret = -EINVAL;
}
}
if (is_write || ret < 0) {
kfree(fd_prot->prot_sg);
kfree(fd_prot->prot_buf);
}
return ret;
}
static int fd_do_rw(struct se_cmd *cmd, struct scatterlist *sgl,
u32 sgl_nents, int is_write)
{
struct se_device *se_dev = cmd->se_dev;
struct fd_dev *dev = FD_DEV(se_dev);
struct file *fd = dev->fd_file;
struct scatterlist *sg; struct scatterlist *sg;
struct iov_iter iter; struct iov_iter iter;
struct bio_vec *bvec; struct bio_vec *bvec;
ssize_t len = 0; ssize_t len = 0;
loff_t pos = (cmd->t_task_lba * se_dev->dev_attrib.block_size); loff_t pos = (cmd->t_task_lba * block_size);
int ret = 0, i; int ret = 0, i;
bvec = kcalloc(sgl_nents, sizeof(struct bio_vec), GFP_KERNEL); bvec = kcalloc(sgl_nents, sizeof(struct bio_vec), GFP_KERNEL);
@ -352,7 +294,7 @@ static int fd_do_rw(struct se_cmd *cmd, struct scatterlist *sgl,
kfree(bvec); kfree(bvec);
if (is_write) { if (is_write) {
if (ret < 0 || ret != cmd->data_length) { if (ret < 0 || ret != data_length) {
pr_err("%s() write returned %d\n", __func__, ret); pr_err("%s() write returned %d\n", __func__, ret);
return (ret < 0 ? ret : -EINVAL); return (ret < 0 ? ret : -EINVAL);
} }
@ -363,10 +305,10 @@ static int fd_do_rw(struct se_cmd *cmd, struct scatterlist *sgl,
* block_device. * block_device.
*/ */
if (S_ISBLK(file_inode(fd)->i_mode)) { if (S_ISBLK(file_inode(fd)->i_mode)) {
if (ret < 0 || ret != cmd->data_length) { if (ret < 0 || ret != data_length) {
pr_err("%s() returned %d, expecting %u for " pr_err("%s() returned %d, expecting %u for "
"S_ISBLK\n", __func__, ret, "S_ISBLK\n", __func__, ret,
cmd->data_length); data_length);
return (ret < 0 ? ret : -EINVAL); return (ret < 0 ? ret : -EINVAL);
} }
} else { } else {
@ -533,9 +475,9 @@ fd_do_prot_unmap(struct se_cmd *cmd, sector_t lba, sector_t nolb)
} }
static sense_reason_t static sense_reason_t
fd_do_unmap(struct se_cmd *cmd, void *priv, sector_t lba, sector_t nolb) fd_execute_unmap(struct se_cmd *cmd, sector_t lba, sector_t nolb)
{ {
struct file *file = priv; struct file *file = FD_DEV(cmd->se_dev)->fd_file;
struct inode *inode = file->f_mapping->host; struct inode *inode = file->f_mapping->host;
int ret; int ret;
@ -576,43 +518,14 @@ fd_do_unmap(struct se_cmd *cmd, void *priv, sector_t lba, sector_t nolb)
return 0; return 0;
} }
static sense_reason_t
fd_execute_write_same_unmap(struct se_cmd *cmd)
{
struct se_device *se_dev = cmd->se_dev;
struct fd_dev *fd_dev = FD_DEV(se_dev);
struct file *file = fd_dev->fd_file;
sector_t lba = cmd->t_task_lba;
sector_t nolb = sbc_get_write_same_sectors(cmd);
sense_reason_t ret;
if (!nolb) {
target_complete_cmd(cmd, SAM_STAT_GOOD);
return 0;
}
ret = fd_do_unmap(cmd, file, lba, nolb);
if (ret)
return ret;
target_complete_cmd(cmd, GOOD);
return 0;
}
static sense_reason_t
fd_execute_unmap(struct se_cmd *cmd)
{
struct file *file = FD_DEV(cmd->se_dev)->fd_file;
return sbc_execute_unmap(cmd, fd_do_unmap, file);
}
static sense_reason_t static sense_reason_t
fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
enum dma_data_direction data_direction) enum dma_data_direction data_direction)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct fd_prot fd_prot; struct fd_dev *fd_dev = FD_DEV(dev);
struct file *file = fd_dev->fd_file;
struct file *pfile = fd_dev->fd_prot_file;
sense_reason_t rc; sense_reason_t rc;
int ret = 0; int ret = 0;
/* /*
@ -630,58 +543,45 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
* physical memory addresses to struct iovec virtual memory. * physical memory addresses to struct iovec virtual memory.
*/ */
if (data_direction == DMA_FROM_DEVICE) { if (data_direction == DMA_FROM_DEVICE) {
memset(&fd_prot, 0, sizeof(struct fd_prot));
if (cmd->prot_type && dev->dev_attrib.pi_prot_type) { if (cmd->prot_type && dev->dev_attrib.pi_prot_type) {
ret = fd_do_prot_rw(cmd, &fd_prot, false); ret = fd_do_rw(cmd, pfile, dev->prot_length,
cmd->t_prot_sg, cmd->t_prot_nents,
cmd->prot_length, 0);
if (ret < 0) if (ret < 0)
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
} }
ret = fd_do_rw(cmd, sgl, sgl_nents, 0); ret = fd_do_rw(cmd, file, dev->dev_attrib.block_size,
sgl, sgl_nents, cmd->data_length, 0);
if (ret > 0 && cmd->prot_type && dev->dev_attrib.pi_prot_type) { if (ret > 0 && cmd->prot_type && dev->dev_attrib.pi_prot_type) {
u32 sectors = cmd->data_length / dev->dev_attrib.block_size; u32 sectors = cmd->data_length >>
ilog2(dev->dev_attrib.block_size);
rc = sbc_dif_verify_read(cmd, cmd->t_task_lba, sectors, rc = sbc_dif_verify(cmd, cmd->t_task_lba, sectors,
0, fd_prot.prot_sg, 0); 0, cmd->t_prot_sg, 0);
if (rc) { if (rc)
kfree(fd_prot.prot_sg);
kfree(fd_prot.prot_buf);
return rc; return rc;
}
kfree(fd_prot.prot_sg);
kfree(fd_prot.prot_buf);
} }
} else { } else {
memset(&fd_prot, 0, sizeof(struct fd_prot));
if (cmd->prot_type && dev->dev_attrib.pi_prot_type) { if (cmd->prot_type && dev->dev_attrib.pi_prot_type) {
u32 sectors = cmd->data_length / dev->dev_attrib.block_size; u32 sectors = cmd->data_length >>
ilog2(dev->dev_attrib.block_size);
ret = fd_do_prot_rw(cmd, &fd_prot, false); rc = sbc_dif_verify(cmd, cmd->t_task_lba, sectors,
if (ret < 0) 0, cmd->t_prot_sg, 0);
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; if (rc)
rc = sbc_dif_verify_write(cmd, cmd->t_task_lba, sectors,
0, fd_prot.prot_sg, 0);
if (rc) {
kfree(fd_prot.prot_sg);
kfree(fd_prot.prot_buf);
return rc; return rc;
}
} }
ret = fd_do_rw(cmd, sgl, sgl_nents, 1); ret = fd_do_rw(cmd, file, dev->dev_attrib.block_size,
sgl, sgl_nents, cmd->data_length, 1);
/* /*
* Perform implicit vfs_fsync_range() for fd_do_writev() ops * Perform implicit vfs_fsync_range() for fd_do_writev() ops
* for SCSI WRITEs with Forced Unit Access (FUA) set. * for SCSI WRITEs with Forced Unit Access (FUA) set.
* Allow this to happen independent of WCE=0 setting. * Allow this to happen independent of WCE=0 setting.
*/ */
if (ret > 0 && if (ret > 0 && (cmd->se_cmd_flags & SCF_FUA)) {
dev->dev_attrib.emulate_fua_write > 0 &&
(cmd->se_cmd_flags & SCF_FUA)) {
struct fd_dev *fd_dev = FD_DEV(dev);
loff_t start = cmd->t_task_lba * loff_t start = cmd->t_task_lba *
dev->dev_attrib.block_size; dev->dev_attrib.block_size;
loff_t end; loff_t end;
@ -695,17 +595,16 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
} }
if (ret > 0 && cmd->prot_type && dev->dev_attrib.pi_prot_type) { if (ret > 0 && cmd->prot_type && dev->dev_attrib.pi_prot_type) {
ret = fd_do_prot_rw(cmd, &fd_prot, true); ret = fd_do_rw(cmd, pfile, dev->prot_length,
cmd->t_prot_sg, cmd->t_prot_nents,
cmd->prot_length, 1);
if (ret < 0) if (ret < 0)
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
} }
} }
if (ret < 0) { if (ret < 0)
kfree(fd_prot.prot_sg);
kfree(fd_prot.prot_buf);
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
}
if (ret) if (ret)
target_complete_cmd(cmd, SAM_STAT_GOOD); target_complete_cmd(cmd, SAM_STAT_GOOD);
@ -908,7 +807,6 @@ static struct sbc_ops fd_sbc_ops = {
.execute_rw = fd_execute_rw, .execute_rw = fd_execute_rw,
.execute_sync_cache = fd_execute_sync_cache, .execute_sync_cache = fd_execute_sync_cache,
.execute_write_same = fd_execute_write_same, .execute_write_same = fd_execute_write_same,
.execute_write_same_unmap = fd_execute_write_same_unmap,
.execute_unmap = fd_execute_unmap, .execute_unmap = fd_execute_unmap,
}; };
@ -918,42 +816,7 @@ fd_parse_cdb(struct se_cmd *cmd)
return sbc_parse_cdb(cmd, &fd_sbc_ops); return sbc_parse_cdb(cmd, &fd_sbc_ops);
} }
DEF_TB_DEFAULT_ATTRIBS(fileio); static const struct target_backend_ops fileio_ops = {
static struct configfs_attribute *fileio_backend_dev_attrs[] = {
&fileio_dev_attrib_emulate_model_alias.attr,
&fileio_dev_attrib_emulate_dpo.attr,
&fileio_dev_attrib_emulate_fua_write.attr,
&fileio_dev_attrib_emulate_fua_read.attr,
&fileio_dev_attrib_emulate_write_cache.attr,
&fileio_dev_attrib_emulate_ua_intlck_ctrl.attr,
&fileio_dev_attrib_emulate_tas.attr,
&fileio_dev_attrib_emulate_tpu.attr,
&fileio_dev_attrib_emulate_tpws.attr,
&fileio_dev_attrib_emulate_caw.attr,
&fileio_dev_attrib_emulate_3pc.attr,
&fileio_dev_attrib_pi_prot_type.attr,
&fileio_dev_attrib_hw_pi_prot_type.attr,
&fileio_dev_attrib_pi_prot_format.attr,
&fileio_dev_attrib_enforce_pr_isids.attr,
&fileio_dev_attrib_is_nonrot.attr,
&fileio_dev_attrib_emulate_rest_reord.attr,
&fileio_dev_attrib_force_pr_aptpl.attr,
&fileio_dev_attrib_hw_block_size.attr,
&fileio_dev_attrib_block_size.attr,
&fileio_dev_attrib_hw_max_sectors.attr,
&fileio_dev_attrib_optimal_sectors.attr,
&fileio_dev_attrib_hw_queue_depth.attr,
&fileio_dev_attrib_queue_depth.attr,
&fileio_dev_attrib_max_unmap_lba_count.attr,
&fileio_dev_attrib_max_unmap_block_desc_count.attr,
&fileio_dev_attrib_unmap_granularity.attr,
&fileio_dev_attrib_unmap_granularity_alignment.attr,
&fileio_dev_attrib_max_write_same_len.attr,
NULL,
};
static struct se_subsystem_api fileio_template = {
.name = "fileio", .name = "fileio",
.inquiry_prod = "FILEIO", .inquiry_prod = "FILEIO",
.inquiry_rev = FD_VERSION, .inquiry_rev = FD_VERSION,
@ -971,21 +834,17 @@ static struct se_subsystem_api fileio_template = {
.init_prot = fd_init_prot, .init_prot = fd_init_prot,
.format_prot = fd_format_prot, .format_prot = fd_format_prot,
.free_prot = fd_free_prot, .free_prot = fd_free_prot,
.tb_dev_attrib_attrs = sbc_attrib_attrs,
}; };
static int __init fileio_module_init(void) static int __init fileio_module_init(void)
{ {
struct target_backend_cits *tbc = &fileio_template.tb_cits; return transport_backend_register(&fileio_ops);
target_core_setup_sub_cits(&fileio_template);
tbc->tb_dev_attrib_cit.ct_attrs = fileio_backend_dev_attrs;
return transport_subsystem_register(&fileio_template);
} }
static void __exit fileio_module_exit(void) static void __exit fileio_module_exit(void)
{ {
transport_subsystem_release(&fileio_template); target_backend_unregister(&fileio_ops);
} }
MODULE_DESCRIPTION("TCM FILEIO subsystem plugin"); MODULE_DESCRIPTION("TCM FILEIO subsystem plugin");

View File

@ -21,12 +21,6 @@
#define FDBD_HAS_BUFFERED_IO_WCE 0x04 #define FDBD_HAS_BUFFERED_IO_WCE 0x04
#define FDBD_FORMAT_UNIT_SIZE 2048 #define FDBD_FORMAT_UNIT_SIZE 2048
struct fd_prot {
unsigned char *prot_buf;
struct scatterlist *prot_sg;
u32 prot_sg_nents;
};
struct fd_dev { struct fd_dev {
struct se_device dev; struct se_device dev;

View File

@ -36,67 +36,78 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_backend.h> #include <target/target_core_backend.h>
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
#include "target_core_internal.h" #include "target_core_internal.h"
static LIST_HEAD(subsystem_list); static LIST_HEAD(backend_list);
static DEFINE_MUTEX(subsystem_mutex); static DEFINE_MUTEX(backend_mutex);
static u32 hba_id_counter; static u32 hba_id_counter;
static DEFINE_SPINLOCK(hba_lock); static DEFINE_SPINLOCK(hba_lock);
static LIST_HEAD(hba_list); static LIST_HEAD(hba_list);
int transport_subsystem_register(struct se_subsystem_api *sub_api)
int transport_backend_register(const struct target_backend_ops *ops)
{ {
struct se_subsystem_api *s; struct target_backend *tb, *old;
INIT_LIST_HEAD(&sub_api->sub_api_list); tb = kzalloc(sizeof(*tb), GFP_KERNEL);
if (!tb)
return -ENOMEM;
tb->ops = ops;
mutex_lock(&subsystem_mutex); mutex_lock(&backend_mutex);
list_for_each_entry(s, &subsystem_list, sub_api_list) { list_for_each_entry(old, &backend_list, list) {
if (!strcmp(s->name, sub_api->name)) { if (!strcmp(old->ops->name, ops->name)) {
pr_err("%p is already registered with" pr_err("backend %s already registered.\n", ops->name);
" duplicate name %s, unable to process" mutex_unlock(&backend_mutex);
" request\n", s, s->name); kfree(tb);
mutex_unlock(&subsystem_mutex);
return -EEXIST; return -EEXIST;
} }
} }
list_add_tail(&sub_api->sub_api_list, &subsystem_list); target_setup_backend_cits(tb);
mutex_unlock(&subsystem_mutex); list_add_tail(&tb->list, &backend_list);
mutex_unlock(&backend_mutex);
pr_debug("TCM: Registered subsystem plugin: %s struct module:" pr_debug("TCM: Registered subsystem plugin: %s struct module: %p\n",
" %p\n", sub_api->name, sub_api->owner); ops->name, ops->owner);
return 0; return 0;
} }
EXPORT_SYMBOL(transport_subsystem_register); EXPORT_SYMBOL(transport_backend_register);
void transport_subsystem_release(struct se_subsystem_api *sub_api) void target_backend_unregister(const struct target_backend_ops *ops)
{ {
mutex_lock(&subsystem_mutex); struct target_backend *tb;
list_del(&sub_api->sub_api_list);
mutex_unlock(&subsystem_mutex); mutex_lock(&backend_mutex);
list_for_each_entry(tb, &backend_list, list) {
if (tb->ops == ops) {
list_del(&tb->list);
kfree(tb);
break;
}
}
mutex_unlock(&backend_mutex);
} }
EXPORT_SYMBOL(transport_subsystem_release); EXPORT_SYMBOL(target_backend_unregister);
static struct se_subsystem_api *core_get_backend(const char *sub_name) static struct target_backend *core_get_backend(const char *name)
{ {
struct se_subsystem_api *s; struct target_backend *tb;
mutex_lock(&subsystem_mutex); mutex_lock(&backend_mutex);
list_for_each_entry(s, &subsystem_list, sub_api_list) { list_for_each_entry(tb, &backend_list, list) {
if (!strcmp(s->name, sub_name)) if (!strcmp(tb->ops->name, name))
goto found; goto found;
} }
mutex_unlock(&subsystem_mutex); mutex_unlock(&backend_mutex);
return NULL; return NULL;
found: found:
if (s->owner && !try_module_get(s->owner)) if (tb->ops->owner && !try_module_get(tb->ops->owner))
s = NULL; tb = NULL;
mutex_unlock(&subsystem_mutex); mutex_unlock(&backend_mutex);
return s; return tb;
} }
struct se_hba * struct se_hba *
@ -117,13 +128,13 @@ core_alloc_hba(const char *plugin_name, u32 plugin_dep_id, u32 hba_flags)
hba->hba_index = scsi_get_new_index(SCSI_INST_INDEX); hba->hba_index = scsi_get_new_index(SCSI_INST_INDEX);
hba->hba_flags |= hba_flags; hba->hba_flags |= hba_flags;
hba->transport = core_get_backend(plugin_name); hba->backend = core_get_backend(plugin_name);
if (!hba->transport) { if (!hba->backend) {
ret = -EINVAL; ret = -EINVAL;
goto out_free_hba; goto out_free_hba;
} }
ret = hba->transport->attach_hba(hba, plugin_dep_id); ret = hba->backend->ops->attach_hba(hba, plugin_dep_id);
if (ret < 0) if (ret < 0)
goto out_module_put; goto out_module_put;
@ -138,8 +149,8 @@ core_alloc_hba(const char *plugin_name, u32 plugin_dep_id, u32 hba_flags)
return hba; return hba;
out_module_put: out_module_put:
module_put(hba->transport->owner); module_put(hba->backend->ops->owner);
hba->transport = NULL; hba->backend = NULL;
out_free_hba: out_free_hba:
kfree(hba); kfree(hba);
return ERR_PTR(ret); return ERR_PTR(ret);
@ -150,7 +161,7 @@ core_delete_hba(struct se_hba *hba)
{ {
WARN_ON(hba->dev_count); WARN_ON(hba->dev_count);
hba->transport->detach_hba(hba); hba->backend->ops->detach_hba(hba);
spin_lock(&hba_lock); spin_lock(&hba_lock);
list_del(&hba->hba_node); list_del(&hba->hba_node);
@ -159,9 +170,9 @@ core_delete_hba(struct se_hba *hba)
pr_debug("CORE_HBA[%d] - Detached HBA from Generic Target" pr_debug("CORE_HBA[%d] - Detached HBA from Generic Target"
" Core\n", hba->hba_id); " Core\n", hba->hba_id);
module_put(hba->transport->owner); module_put(hba->backend->ops->owner);
hba->transport = NULL; hba->backend = NULL;
kfree(hba); kfree(hba);
return 0; return 0;
} }

View File

@ -40,7 +40,6 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_backend.h> #include <target/target_core_backend.h>
#include <target/target_core_backend_configfs.h>
#include "target_core_iblock.h" #include "target_core_iblock.h"
@ -53,17 +52,11 @@ static inline struct iblock_dev *IBLOCK_DEV(struct se_device *dev)
} }
static struct se_subsystem_api iblock_template;
/* iblock_attach_hba(): (Part of se_subsystem_api_t template)
*
*
*/
static int iblock_attach_hba(struct se_hba *hba, u32 host_id) static int iblock_attach_hba(struct se_hba *hba, u32 host_id)
{ {
pr_debug("CORE_HBA[%d] - TCM iBlock HBA Driver %s on" pr_debug("CORE_HBA[%d] - TCM iBlock HBA Driver %s on"
" Generic Target Core Stack %s\n", hba->hba_id, " Generic Target Core Stack %s\n", hba->hba_id,
IBLOCK_VERSION, TARGET_CORE_MOD_VERSION); IBLOCK_VERSION, TARGET_CORE_VERSION);
return 0; return 0;
} }
@ -197,6 +190,14 @@ out:
return ret; return ret;
} }
static void iblock_dev_call_rcu(struct rcu_head *p)
{
struct se_device *dev = container_of(p, struct se_device, rcu_head);
struct iblock_dev *ib_dev = IBLOCK_DEV(dev);
kfree(ib_dev);
}
static void iblock_free_device(struct se_device *dev) static void iblock_free_device(struct se_device *dev)
{ {
struct iblock_dev *ib_dev = IBLOCK_DEV(dev); struct iblock_dev *ib_dev = IBLOCK_DEV(dev);
@ -206,7 +207,7 @@ static void iblock_free_device(struct se_device *dev)
if (ib_dev->ibd_bio_set != NULL) if (ib_dev->ibd_bio_set != NULL)
bioset_free(ib_dev->ibd_bio_set); bioset_free(ib_dev->ibd_bio_set);
kfree(ib_dev); call_rcu(&dev->rcu_head, iblock_dev_call_rcu);
} }
static unsigned long long iblock_emulate_read_cap_with_block_size( static unsigned long long iblock_emulate_read_cap_with_block_size(
@ -414,10 +415,9 @@ iblock_execute_sync_cache(struct se_cmd *cmd)
} }
static sense_reason_t static sense_reason_t
iblock_do_unmap(struct se_cmd *cmd, void *priv, iblock_execute_unmap(struct se_cmd *cmd, sector_t lba, sector_t nolb)
sector_t lba, sector_t nolb)
{ {
struct block_device *bdev = priv; struct block_device *bdev = IBLOCK_DEV(cmd->se_dev)->ibd_bd;
int ret; int ret;
ret = blkdev_issue_discard(bdev, lba, nolb, GFP_KERNEL, 0); ret = blkdev_issue_discard(bdev, lba, nolb, GFP_KERNEL, 0);
@ -429,30 +429,6 @@ iblock_do_unmap(struct se_cmd *cmd, void *priv,
return 0; return 0;
} }
static sense_reason_t
iblock_execute_unmap(struct se_cmd *cmd)
{
struct block_device *bdev = IBLOCK_DEV(cmd->se_dev)->ibd_bd;
return sbc_execute_unmap(cmd, iblock_do_unmap, bdev);
}
static sense_reason_t
iblock_execute_write_same_unmap(struct se_cmd *cmd)
{
struct block_device *bdev = IBLOCK_DEV(cmd->se_dev)->ibd_bd;
sector_t lba = cmd->t_task_lba;
sector_t nolb = sbc_get_write_same_sectors(cmd);
sense_reason_t ret;
ret = iblock_do_unmap(cmd, bdev, lba, nolb);
if (ret)
return ret;
target_complete_cmd(cmd, GOOD);
return 0;
}
static sense_reason_t static sense_reason_t
iblock_execute_write_same(struct se_cmd *cmd) iblock_execute_write_same(struct se_cmd *cmd)
{ {
@ -844,7 +820,6 @@ static struct sbc_ops iblock_sbc_ops = {
.execute_rw = iblock_execute_rw, .execute_rw = iblock_execute_rw,
.execute_sync_cache = iblock_execute_sync_cache, .execute_sync_cache = iblock_execute_sync_cache,
.execute_write_same = iblock_execute_write_same, .execute_write_same = iblock_execute_write_same,
.execute_write_same_unmap = iblock_execute_write_same_unmap,
.execute_unmap = iblock_execute_unmap, .execute_unmap = iblock_execute_unmap,
}; };
@ -863,42 +838,7 @@ static bool iblock_get_write_cache(struct se_device *dev)
return q->flush_flags & REQ_FLUSH; return q->flush_flags & REQ_FLUSH;
} }
DEF_TB_DEFAULT_ATTRIBS(iblock); static const struct target_backend_ops iblock_ops = {
static struct configfs_attribute *iblock_backend_dev_attrs[] = {
&iblock_dev_attrib_emulate_model_alias.attr,
&iblock_dev_attrib_emulate_dpo.attr,
&iblock_dev_attrib_emulate_fua_write.attr,
&iblock_dev_attrib_emulate_fua_read.attr,
&iblock_dev_attrib_emulate_write_cache.attr,
&iblock_dev_attrib_emulate_ua_intlck_ctrl.attr,
&iblock_dev_attrib_emulate_tas.attr,
&iblock_dev_attrib_emulate_tpu.attr,
&iblock_dev_attrib_emulate_tpws.attr,
&iblock_dev_attrib_emulate_caw.attr,
&iblock_dev_attrib_emulate_3pc.attr,
&iblock_dev_attrib_pi_prot_type.attr,
&iblock_dev_attrib_hw_pi_prot_type.attr,
&iblock_dev_attrib_pi_prot_format.attr,
&iblock_dev_attrib_enforce_pr_isids.attr,
&iblock_dev_attrib_is_nonrot.attr,
&iblock_dev_attrib_emulate_rest_reord.attr,
&iblock_dev_attrib_force_pr_aptpl.attr,
&iblock_dev_attrib_hw_block_size.attr,
&iblock_dev_attrib_block_size.attr,
&iblock_dev_attrib_hw_max_sectors.attr,
&iblock_dev_attrib_optimal_sectors.attr,
&iblock_dev_attrib_hw_queue_depth.attr,
&iblock_dev_attrib_queue_depth.attr,
&iblock_dev_attrib_max_unmap_lba_count.attr,
&iblock_dev_attrib_max_unmap_block_desc_count.attr,
&iblock_dev_attrib_unmap_granularity.attr,
&iblock_dev_attrib_unmap_granularity_alignment.attr,
&iblock_dev_attrib_max_write_same_len.attr,
NULL,
};
static struct se_subsystem_api iblock_template = {
.name = "iblock", .name = "iblock",
.inquiry_prod = "IBLOCK", .inquiry_prod = "IBLOCK",
.inquiry_rev = IBLOCK_VERSION, .inquiry_rev = IBLOCK_VERSION,
@ -918,21 +858,17 @@ static struct se_subsystem_api iblock_template = {
.get_io_min = iblock_get_io_min, .get_io_min = iblock_get_io_min,
.get_io_opt = iblock_get_io_opt, .get_io_opt = iblock_get_io_opt,
.get_write_cache = iblock_get_write_cache, .get_write_cache = iblock_get_write_cache,
.tb_dev_attrib_attrs = sbc_attrib_attrs,
}; };
static int __init iblock_module_init(void) static int __init iblock_module_init(void)
{ {
struct target_backend_cits *tbc = &iblock_template.tb_cits; return transport_backend_register(&iblock_ops);
target_core_setup_sub_cits(&iblock_template);
tbc->tb_dev_attrib_cit.ct_attrs = iblock_backend_dev_attrs;
return transport_subsystem_register(&iblock_template);
} }
static void __exit iblock_module_exit(void) static void __exit iblock_module_exit(void)
{ {
transport_subsystem_release(&iblock_template); target_backend_unregister(&iblock_ops);
} }
MODULE_DESCRIPTION("TCM IBLOCK subsystem plugin"); MODULE_DESCRIPTION("TCM IBLOCK subsystem plugin");

View File

@ -1,6 +1,53 @@
#ifndef TARGET_CORE_INTERNAL_H #ifndef TARGET_CORE_INTERNAL_H
#define TARGET_CORE_INTERNAL_H #define TARGET_CORE_INTERNAL_H
#define TARGET_CORE_NAME_MAX_LEN 64
#define TARGET_FABRIC_NAME_SIZE 32
struct target_backend {
struct list_head list;
const struct target_backend_ops *ops;
struct config_item_type tb_dev_cit;
struct config_item_type tb_dev_attrib_cit;
struct config_item_type tb_dev_pr_cit;
struct config_item_type tb_dev_wwn_cit;
struct config_item_type tb_dev_alua_tg_pt_gps_cit;
struct config_item_type tb_dev_stat_cit;
};
struct target_fabric_configfs {
atomic_t tf_access_cnt;
struct list_head tf_list;
struct config_group tf_group;
struct config_group tf_disc_group;
struct config_group *tf_default_groups[2];
const struct target_core_fabric_ops *tf_ops;
struct config_item_type tf_discovery_cit;
struct config_item_type tf_wwn_cit;
struct config_item_type tf_wwn_fabric_stats_cit;
struct config_item_type tf_tpg_cit;
struct config_item_type tf_tpg_base_cit;
struct config_item_type tf_tpg_lun_cit;
struct config_item_type tf_tpg_port_cit;
struct config_item_type tf_tpg_port_stat_cit;
struct config_item_type tf_tpg_np_cit;
struct config_item_type tf_tpg_np_base_cit;
struct config_item_type tf_tpg_attrib_cit;
struct config_item_type tf_tpg_auth_cit;
struct config_item_type tf_tpg_param_cit;
struct config_item_type tf_tpg_nacl_cit;
struct config_item_type tf_tpg_nacl_base_cit;
struct config_item_type tf_tpg_nacl_attrib_cit;
struct config_item_type tf_tpg_nacl_auth_cit;
struct config_item_type tf_tpg_nacl_param_cit;
struct config_item_type tf_tpg_nacl_stat_cit;
struct config_item_type tf_tpg_mappedlun_cit;
struct config_item_type tf_tpg_mappedlun_stat_cit;
};
/* target_core_alua.c */ /* target_core_alua.c */
extern struct t10_alua_lu_gp *default_lu_gp; extern struct t10_alua_lu_gp *default_lu_gp;
@ -8,28 +55,27 @@ extern struct t10_alua_lu_gp *default_lu_gp;
extern struct mutex g_device_mutex; extern struct mutex g_device_mutex;
extern struct list_head g_device_list; extern struct list_head g_device_list;
int core_alloc_rtpi(struct se_lun *lun, struct se_device *dev);
struct se_dev_entry *core_get_se_deve_from_rtpi(struct se_node_acl *, u16); struct se_dev_entry *core_get_se_deve_from_rtpi(struct se_node_acl *, u16);
int core_free_device_list_for_node(struct se_node_acl *, void target_pr_kref_release(struct kref *);
void core_free_device_list_for_node(struct se_node_acl *,
struct se_portal_group *); struct se_portal_group *);
void core_update_device_list_access(u32, u32, struct se_node_acl *); void core_update_device_list_access(u64, u32, struct se_node_acl *);
struct se_dev_entry *target_nacl_find_deve(struct se_node_acl *, u64);
int core_enable_device_list_for_node(struct se_lun *, struct se_lun_acl *, int core_enable_device_list_for_node(struct se_lun *, struct se_lun_acl *,
u32, u32, struct se_node_acl *, struct se_portal_group *); u64, u32, struct se_node_acl *, struct se_portal_group *);
int core_disable_device_list_for_node(struct se_lun *, struct se_lun_acl *, void core_disable_device_list_for_node(struct se_lun *, struct se_dev_entry *,
u32, u32, struct se_node_acl *, struct se_portal_group *); struct se_node_acl *, struct se_portal_group *);
void core_clear_lun_from_tpg(struct se_lun *, struct se_portal_group *); void core_clear_lun_from_tpg(struct se_lun *, struct se_portal_group *);
int core_dev_export(struct se_device *, struct se_portal_group *, int core_dev_add_lun(struct se_portal_group *, struct se_device *,
struct se_lun *); struct se_lun *lun);
void core_dev_unexport(struct se_device *, struct se_portal_group *,
struct se_lun *);
struct se_lun *core_dev_add_lun(struct se_portal_group *, struct se_device *, u32);
void core_dev_del_lun(struct se_portal_group *, struct se_lun *); void core_dev_del_lun(struct se_portal_group *, struct se_lun *);
struct se_lun *core_get_lun_from_tpg(struct se_portal_group *, u32);
struct se_lun_acl *core_dev_init_initiator_node_lun_acl(struct se_portal_group *, struct se_lun_acl *core_dev_init_initiator_node_lun_acl(struct se_portal_group *,
struct se_node_acl *, u32, int *); struct se_node_acl *, u64, int *);
int core_dev_add_initiator_node_lun_acl(struct se_portal_group *, int core_dev_add_initiator_node_lun_acl(struct se_portal_group *,
struct se_lun_acl *, u32, u32); struct se_lun_acl *, struct se_lun *lun, u32);
int core_dev_del_initiator_node_lun_acl(struct se_portal_group *, int core_dev_del_initiator_node_lun_acl(struct se_lun *,
struct se_lun *, struct se_lun_acl *); struct se_lun_acl *);
void core_dev_free_initiator_node_lun_acl(struct se_portal_group *, void core_dev_free_initiator_node_lun_acl(struct se_portal_group *,
struct se_lun_acl *lacl); struct se_lun_acl *lacl);
int core_dev_setup_virtual_lun0(void); int core_dev_setup_virtual_lun0(void);
@ -38,6 +84,18 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name);
int target_configure_device(struct se_device *dev); int target_configure_device(struct se_device *dev);
void target_free_device(struct se_device *); void target_free_device(struct se_device *);
/* target_core_configfs.c */
void target_setup_backend_cits(struct target_backend *);
/* target_core_fabric_lib.c */
int target_get_pr_transport_id_len(struct se_node_acl *nacl,
struct t10_pr_registration *pr_reg, int *format_code);
int target_get_pr_transport_id(struct se_node_acl *nacl,
struct t10_pr_registration *pr_reg, int *format_code,
unsigned char *buf);
const char *target_parse_pr_out_transport_id(struct se_portal_group *tpg,
const char *buf, u32 *out_tid_len, char **port_nexus_ptr);
/* target_core_hba.c */ /* target_core_hba.c */
struct se_hba *core_alloc_hba(const char *, u32, u32); struct se_hba *core_alloc_hba(const char *, u32, u32);
int core_delete_hba(struct se_hba *); int core_delete_hba(struct se_hba *);
@ -53,12 +111,16 @@ extern struct se_device *g_lun0_dev;
struct se_node_acl *__core_tpg_get_initiator_node_acl(struct se_portal_group *tpg, struct se_node_acl *__core_tpg_get_initiator_node_acl(struct se_portal_group *tpg,
const char *); const char *);
void core_tpg_add_node_to_devs(struct se_node_acl *, struct se_portal_group *); void core_tpg_add_node_to_devs(struct se_node_acl *, struct se_portal_group *,
struct se_lun *);
void core_tpg_wait_for_nacl_pr_ref(struct se_node_acl *); void core_tpg_wait_for_nacl_pr_ref(struct se_node_acl *);
struct se_lun *core_tpg_alloc_lun(struct se_portal_group *, u32); struct se_lun *core_tpg_alloc_lun(struct se_portal_group *, u64);
int core_tpg_add_lun(struct se_portal_group *, struct se_lun *, int core_tpg_add_lun(struct se_portal_group *, struct se_lun *,
u32, struct se_device *); u32, struct se_device *);
void core_tpg_remove_lun(struct se_portal_group *, struct se_lun *); void core_tpg_remove_lun(struct se_portal_group *, struct se_lun *);
struct se_node_acl *core_tpg_add_initiator_node_acl(struct se_portal_group *tpg,
const char *initiatorname);
void core_tpg_del_initiator_node_acl(struct se_node_acl *acl);
/* target_core_transport.c */ /* target_core_transport.c */
extern struct kmem_cache *se_tmr_req_cache; extern struct kmem_cache *se_tmr_req_cache;
@ -77,14 +139,19 @@ int transport_dump_vpd_assoc(struct t10_vpd *, unsigned char *, int);
int transport_dump_vpd_ident_type(struct t10_vpd *, unsigned char *, int); int transport_dump_vpd_ident_type(struct t10_vpd *, unsigned char *, int);
int transport_dump_vpd_ident(struct t10_vpd *, unsigned char *, int); int transport_dump_vpd_ident(struct t10_vpd *, unsigned char *, int);
bool target_stop_cmd(struct se_cmd *cmd, unsigned long *flags); bool target_stop_cmd(struct se_cmd *cmd, unsigned long *flags);
int transport_clear_lun_ref(struct se_lun *); void transport_clear_lun_ref(struct se_lun *);
void transport_send_task_abort(struct se_cmd *); void transport_send_task_abort(struct se_cmd *);
sense_reason_t target_cmd_size_check(struct se_cmd *cmd, unsigned int size); sense_reason_t target_cmd_size_check(struct se_cmd *cmd, unsigned int size);
void target_qf_do_work(struct work_struct *work); void target_qf_do_work(struct work_struct *work);
bool target_check_wce(struct se_device *dev);
bool target_check_fua(struct se_device *dev);
/* target_core_stat.c */ /* target_core_stat.c */
void target_stat_setup_dev_default_groups(struct se_device *); void target_stat_setup_dev_default_groups(struct se_device *);
void target_stat_setup_port_default_groups(struct se_lun *); void target_stat_setup_port_default_groups(struct se_lun *);
void target_stat_setup_mappedlun_default_groups(struct se_lun_acl *); void target_stat_setup_mappedlun_default_groups(struct se_lun_acl *);
/* target_core_xcopy.c */
extern struct se_portal_group xcopy_pt_tpg;
#endif /* TARGET_CORE_INTERNAL_H */ #endif /* TARGET_CORE_INTERNAL_H */

View File

@ -35,7 +35,6 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_backend.h> #include <target/target_core_backend.h>
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
#include "target_core_internal.h" #include "target_core_internal.h"
#include "target_core_pr.h" #include "target_core_pr.h"
@ -45,7 +44,6 @@
* Used for Specify Initiator Ports Capable Bit (SPEC_I_PT) * Used for Specify Initiator Ports Capable Bit (SPEC_I_PT)
*/ */
struct pr_transport_id_holder { struct pr_transport_id_holder {
int dest_local_nexus;
struct t10_pr_registration *dest_pr_reg; struct t10_pr_registration *dest_pr_reg;
struct se_portal_group *dest_tpg; struct se_portal_group *dest_tpg;
struct se_node_acl *dest_node_acl; struct se_node_acl *dest_node_acl;
@ -231,9 +229,10 @@ target_scsi2_reservation_release(struct se_cmd *cmd)
dev->dev_reservation_flags &= ~DRF_SPC2_RESERVATIONS_WITH_ISID; dev->dev_reservation_flags &= ~DRF_SPC2_RESERVATIONS_WITH_ISID;
} }
tpg = sess->se_tpg; tpg = sess->se_tpg;
pr_debug("SCSI-2 Released reservation for %s LUN: %u ->" pr_debug("SCSI-2 Released reservation for %s LUN: %llu ->"
" MAPPED LUN: %u for %s\n", tpg->se_tpg_tfo->get_fabric_name(), " MAPPED LUN: %llu for %s\n",
cmd->se_lun->unpacked_lun, cmd->se_deve->mapped_lun, tpg->se_tpg_tfo->get_fabric_name(),
cmd->se_lun->unpacked_lun, cmd->orig_fe_lun,
sess->se_node_acl->initiatorname); sess->se_node_acl->initiatorname);
out_unlock: out_unlock:
@ -277,12 +276,12 @@ target_scsi2_reservation_reserve(struct se_cmd *cmd)
(dev->dev_reserved_node_acl != sess->se_node_acl)) { (dev->dev_reserved_node_acl != sess->se_node_acl)) {
pr_err("SCSI-2 RESERVATION CONFLIFT for %s fabric\n", pr_err("SCSI-2 RESERVATION CONFLIFT for %s fabric\n",
tpg->se_tpg_tfo->get_fabric_name()); tpg->se_tpg_tfo->get_fabric_name());
pr_err("Original reserver LUN: %u %s\n", pr_err("Original reserver LUN: %llu %s\n",
cmd->se_lun->unpacked_lun, cmd->se_lun->unpacked_lun,
dev->dev_reserved_node_acl->initiatorname); dev->dev_reserved_node_acl->initiatorname);
pr_err("Current attempt - LUN: %u -> MAPPED LUN: %u" pr_err("Current attempt - LUN: %llu -> MAPPED LUN: %llu"
" from %s \n", cmd->se_lun->unpacked_lun, " from %s \n", cmd->se_lun->unpacked_lun,
cmd->se_deve->mapped_lun, cmd->orig_fe_lun,
sess->se_node_acl->initiatorname); sess->se_node_acl->initiatorname);
ret = TCM_RESERVATION_CONFLICT; ret = TCM_RESERVATION_CONFLICT;
goto out_unlock; goto out_unlock;
@ -294,9 +293,9 @@ target_scsi2_reservation_reserve(struct se_cmd *cmd)
dev->dev_res_bin_isid = sess->sess_bin_isid; dev->dev_res_bin_isid = sess->sess_bin_isid;
dev->dev_reservation_flags |= DRF_SPC2_RESERVATIONS_WITH_ISID; dev->dev_reservation_flags |= DRF_SPC2_RESERVATIONS_WITH_ISID;
} }
pr_debug("SCSI-2 Reserved %s LUN: %u -> MAPPED LUN: %u" pr_debug("SCSI-2 Reserved %s LUN: %llu -> MAPPED LUN: %llu"
" for %s\n", tpg->se_tpg_tfo->get_fabric_name(), " for %s\n", tpg->se_tpg_tfo->get_fabric_name(),
cmd->se_lun->unpacked_lun, cmd->se_deve->mapped_lun, cmd->se_lun->unpacked_lun, cmd->orig_fe_lun,
sess->se_node_acl->initiatorname); sess->se_node_acl->initiatorname);
out_unlock: out_unlock:
@ -314,28 +313,31 @@ out:
* This function is called by those initiator ports who are *NOT* * This function is called by those initiator ports who are *NOT*
* the active PR reservation holder when a reservation is present. * the active PR reservation holder when a reservation is present.
*/ */
static int core_scsi3_pr_seq_non_holder( static int core_scsi3_pr_seq_non_holder(struct se_cmd *cmd, u32 pr_reg_type,
struct se_cmd *cmd, bool isid_mismatch)
u32 pr_reg_type)
{ {
unsigned char *cdb = cmd->t_task_cdb; unsigned char *cdb = cmd->t_task_cdb;
struct se_dev_entry *se_deve;
struct se_session *se_sess = cmd->se_sess; struct se_session *se_sess = cmd->se_sess;
int other_cdb = 0, ignore_reg; struct se_node_acl *nacl = se_sess->se_node_acl;
int other_cdb = 0;
int registered_nexus = 0, ret = 1; /* Conflict by default */ int registered_nexus = 0, ret = 1; /* Conflict by default */
int all_reg = 0, reg_only = 0; /* ALL_REG, REG_ONLY */ int all_reg = 0, reg_only = 0; /* ALL_REG, REG_ONLY */
int we = 0; /* Write Exclusive */ int we = 0; /* Write Exclusive */
int legacy = 0; /* Act like a legacy device and return int legacy = 0; /* Act like a legacy device and return
* RESERVATION CONFLICT on some CDBs */ * RESERVATION CONFLICT on some CDBs */
se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun]; if (isid_mismatch) {
/* registered_nexus = 0;
* Determine if the registration should be ignored due to } else {
* non-matching ISIDs in target_scsi3_pr_reservation_check(). struct se_dev_entry *se_deve;
*/
ignore_reg = (pr_reg_type & 0x80000000); rcu_read_lock();
if (ignore_reg) se_deve = target_nacl_find_deve(nacl, cmd->orig_fe_lun);
pr_reg_type &= ~0x80000000; if (se_deve)
registered_nexus = test_bit(DEF_PR_REG_ACTIVE,
&se_deve->deve_flags);
rcu_read_unlock();
}
switch (pr_reg_type) { switch (pr_reg_type) {
case PR_TYPE_WRITE_EXCLUSIVE: case PR_TYPE_WRITE_EXCLUSIVE:
@ -345,8 +347,6 @@ static int core_scsi3_pr_seq_non_holder(
* Some commands are only allowed for the persistent reservation * Some commands are only allowed for the persistent reservation
* holder. * holder.
*/ */
if ((se_deve->def_pr_registered) && !(ignore_reg))
registered_nexus = 1;
break; break;
case PR_TYPE_WRITE_EXCLUSIVE_REGONLY: case PR_TYPE_WRITE_EXCLUSIVE_REGONLY:
we = 1; we = 1;
@ -355,8 +355,6 @@ static int core_scsi3_pr_seq_non_holder(
* Some commands are only allowed for registered I_T Nexuses. * Some commands are only allowed for registered I_T Nexuses.
*/ */
reg_only = 1; reg_only = 1;
if ((se_deve->def_pr_registered) && !(ignore_reg))
registered_nexus = 1;
break; break;
case PR_TYPE_WRITE_EXCLUSIVE_ALLREG: case PR_TYPE_WRITE_EXCLUSIVE_ALLREG:
we = 1; we = 1;
@ -365,8 +363,6 @@ static int core_scsi3_pr_seq_non_holder(
* Each registered I_T Nexus is a reservation holder. * Each registered I_T Nexus is a reservation holder.
*/ */
all_reg = 1; all_reg = 1;
if ((se_deve->def_pr_registered) && !(ignore_reg))
registered_nexus = 1;
break; break;
default: default:
return -EINVAL; return -EINVAL;
@ -572,6 +568,7 @@ target_scsi3_pr_reservation_check(struct se_cmd *cmd)
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct se_session *sess = cmd->se_sess; struct se_session *sess = cmd->se_sess;
u32 pr_reg_type; u32 pr_reg_type;
bool isid_mismatch = false;
if (!dev->dev_pr_res_holder) if (!dev->dev_pr_res_holder)
return 0; return 0;
@ -584,7 +581,7 @@ target_scsi3_pr_reservation_check(struct se_cmd *cmd)
if (dev->dev_pr_res_holder->isid_present_at_reg) { if (dev->dev_pr_res_holder->isid_present_at_reg) {
if (dev->dev_pr_res_holder->pr_reg_bin_isid != if (dev->dev_pr_res_holder->pr_reg_bin_isid !=
sess->sess_bin_isid) { sess->sess_bin_isid) {
pr_reg_type |= 0x80000000; isid_mismatch = true;
goto check_nonholder; goto check_nonholder;
} }
} }
@ -592,7 +589,7 @@ target_scsi3_pr_reservation_check(struct se_cmd *cmd)
return 0; return 0;
check_nonholder: check_nonholder:
if (core_scsi3_pr_seq_non_holder(cmd, pr_reg_type)) if (core_scsi3_pr_seq_non_holder(cmd, pr_reg_type, isid_mismatch))
return TCM_RESERVATION_CONFLICT; return TCM_RESERVATION_CONFLICT;
return 0; return 0;
} }
@ -620,7 +617,9 @@ static u32 core_scsi3_pr_generation(struct se_device *dev)
static struct t10_pr_registration *__core_scsi3_do_alloc_registration( static struct t10_pr_registration *__core_scsi3_do_alloc_registration(
struct se_device *dev, struct se_device *dev,
struct se_node_acl *nacl, struct se_node_acl *nacl,
struct se_lun *lun,
struct se_dev_entry *deve, struct se_dev_entry *deve,
u64 mapped_lun,
unsigned char *isid, unsigned char *isid,
u64 sa_res_key, u64 sa_res_key,
int all_tg_pt, int all_tg_pt,
@ -642,12 +641,12 @@ static struct t10_pr_registration *__core_scsi3_do_alloc_registration(
atomic_set(&pr_reg->pr_res_holders, 0); atomic_set(&pr_reg->pr_res_holders, 0);
pr_reg->pr_reg_nacl = nacl; pr_reg->pr_reg_nacl = nacl;
pr_reg->pr_reg_deve = deve; pr_reg->pr_reg_deve = deve;
pr_reg->pr_res_mapped_lun = deve->mapped_lun; pr_reg->pr_res_mapped_lun = mapped_lun;
pr_reg->pr_aptpl_target_lun = deve->se_lun->unpacked_lun; pr_reg->pr_aptpl_target_lun = lun->unpacked_lun;
pr_reg->tg_pt_sep_rtpi = lun->lun_rtpi;
pr_reg->pr_res_key = sa_res_key; pr_reg->pr_res_key = sa_res_key;
pr_reg->pr_reg_all_tg_pt = all_tg_pt; pr_reg->pr_reg_all_tg_pt = all_tg_pt;
pr_reg->pr_reg_aptpl = aptpl; pr_reg->pr_reg_aptpl = aptpl;
pr_reg->pr_reg_tg_pt_lun = deve->se_lun;
/* /*
* If an ISID value for this SCSI Initiator Port exists, * If an ISID value for this SCSI Initiator Port exists,
* save it to the registration now. * save it to the registration now.
@ -671,7 +670,9 @@ static void core_scsi3_lunacl_undepend_item(struct se_dev_entry *);
static struct t10_pr_registration *__core_scsi3_alloc_registration( static struct t10_pr_registration *__core_scsi3_alloc_registration(
struct se_device *dev, struct se_device *dev,
struct se_node_acl *nacl, struct se_node_acl *nacl,
struct se_lun *lun,
struct se_dev_entry *deve, struct se_dev_entry *deve,
u64 mapped_lun,
unsigned char *isid, unsigned char *isid,
u64 sa_res_key, u64 sa_res_key,
int all_tg_pt, int all_tg_pt,
@ -679,7 +680,8 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
{ {
struct se_dev_entry *deve_tmp; struct se_dev_entry *deve_tmp;
struct se_node_acl *nacl_tmp; struct se_node_acl *nacl_tmp;
struct se_port *port, *port_tmp; struct se_lun_acl *lacl_tmp;
struct se_lun *lun_tmp, *next, *dest_lun;
const struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo; const struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo;
struct t10_pr_registration *pr_reg, *pr_reg_atp, *pr_reg_tmp, *pr_reg_tmp_safe; struct t10_pr_registration *pr_reg, *pr_reg_atp, *pr_reg_tmp, *pr_reg_tmp_safe;
int ret; int ret;
@ -687,8 +689,9 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
* Create a registration for the I_T Nexus upon which the * Create a registration for the I_T Nexus upon which the
* PROUT REGISTER was received. * PROUT REGISTER was received.
*/ */
pr_reg = __core_scsi3_do_alloc_registration(dev, nacl, deve, isid, pr_reg = __core_scsi3_do_alloc_registration(dev, nacl, lun, deve, mapped_lun,
sa_res_key, all_tg_pt, aptpl); isid, sa_res_key, all_tg_pt,
aptpl);
if (!pr_reg) if (!pr_reg)
return NULL; return NULL;
/* /*
@ -701,13 +704,13 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
* for ALL_TG_PT=1 * for ALL_TG_PT=1
*/ */
spin_lock(&dev->se_port_lock); spin_lock(&dev->se_port_lock);
list_for_each_entry_safe(port, port_tmp, &dev->dev_sep_list, sep_list) { list_for_each_entry_safe(lun_tmp, next, &dev->dev_sep_list, lun_dev_link) {
atomic_inc_mb(&port->sep_tg_pt_ref_cnt); if (!percpu_ref_tryget_live(&lun_tmp->lun_ref))
continue;
spin_unlock(&dev->se_port_lock); spin_unlock(&dev->se_port_lock);
spin_lock_bh(&port->sep_alua_lock); spin_lock(&lun_tmp->lun_deve_lock);
list_for_each_entry(deve_tmp, &port->sep_alua_list, list_for_each_entry(deve_tmp, &lun_tmp->lun_deve_list, lun_link) {
alua_port_list) {
/* /*
* This pointer will be NULL for demo mode MappedLUNs * This pointer will be NULL for demo mode MappedLUNs
* that have not been make explicit via a ConfigFS * that have not been make explicit via a ConfigFS
@ -716,7 +719,9 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
if (!deve_tmp->se_lun_acl) if (!deve_tmp->se_lun_acl)
continue; continue;
nacl_tmp = deve_tmp->se_lun_acl->se_lun_nacl; lacl_tmp = rcu_dereference_check(deve_tmp->se_lun_acl,
lockdep_is_held(&lun_tmp->lun_deve_lock));
nacl_tmp = lacl_tmp->se_lun_nacl;
/* /*
* Skip the matching struct se_node_acl that is allocated * Skip the matching struct se_node_acl that is allocated
* above.. * above..
@ -736,8 +741,8 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
if (strcmp(nacl->initiatorname, nacl_tmp->initiatorname)) if (strcmp(nacl->initiatorname, nacl_tmp->initiatorname))
continue; continue;
atomic_inc_mb(&deve_tmp->pr_ref_count); kref_get(&deve_tmp->pr_kref);
spin_unlock_bh(&port->sep_alua_lock); spin_unlock(&lun_tmp->lun_deve_lock);
/* /*
* Grab a configfs group dependency that is released * Grab a configfs group dependency that is released
* for the exception path at label out: below, or upon * for the exception path at label out: below, or upon
@ -748,8 +753,8 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
if (ret < 0) { if (ret < 0) {
pr_err("core_scsi3_lunacl_depend" pr_err("core_scsi3_lunacl_depend"
"_item() failed\n"); "_item() failed\n");
atomic_dec_mb(&port->sep_tg_pt_ref_cnt); percpu_ref_put(&lun_tmp->lun_ref);
atomic_dec_mb(&deve_tmp->pr_ref_count); kref_put(&deve_tmp->pr_kref, target_pr_kref_release);
goto out; goto out;
} }
/* /*
@ -759,24 +764,27 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
* the original *pr_reg is processed in * the original *pr_reg is processed in
* __core_scsi3_add_registration() * __core_scsi3_add_registration()
*/ */
dest_lun = rcu_dereference_check(deve_tmp->se_lun,
atomic_read(&deve_tmp->pr_kref.refcount) != 0);
pr_reg_atp = __core_scsi3_do_alloc_registration(dev, pr_reg_atp = __core_scsi3_do_alloc_registration(dev,
nacl_tmp, deve_tmp, NULL, nacl_tmp, dest_lun, deve_tmp,
deve_tmp->mapped_lun, NULL,
sa_res_key, all_tg_pt, aptpl); sa_res_key, all_tg_pt, aptpl);
if (!pr_reg_atp) { if (!pr_reg_atp) {
atomic_dec_mb(&port->sep_tg_pt_ref_cnt); percpu_ref_put(&lun_tmp->lun_ref);
atomic_dec_mb(&deve_tmp->pr_ref_count);
core_scsi3_lunacl_undepend_item(deve_tmp); core_scsi3_lunacl_undepend_item(deve_tmp);
goto out; goto out;
} }
list_add_tail(&pr_reg_atp->pr_reg_atp_mem_list, list_add_tail(&pr_reg_atp->pr_reg_atp_mem_list,
&pr_reg->pr_reg_atp_list); &pr_reg->pr_reg_atp_list);
spin_lock_bh(&port->sep_alua_lock); spin_lock(&lun_tmp->lun_deve_lock);
} }
spin_unlock_bh(&port->sep_alua_lock); spin_unlock(&lun_tmp->lun_deve_lock);
spin_lock(&dev->se_port_lock); spin_lock(&dev->se_port_lock);
atomic_dec_mb(&port->sep_tg_pt_ref_cnt); percpu_ref_put(&lun_tmp->lun_ref);
} }
spin_unlock(&dev->se_port_lock); spin_unlock(&dev->se_port_lock);
@ -797,10 +805,10 @@ int core_scsi3_alloc_aptpl_registration(
u64 sa_res_key, u64 sa_res_key,
unsigned char *i_port, unsigned char *i_port,
unsigned char *isid, unsigned char *isid,
u32 mapped_lun, u64 mapped_lun,
unsigned char *t_port, unsigned char *t_port,
u16 tpgt, u16 tpgt,
u32 target_lun, u64 target_lun,
int res_holder, int res_holder,
int all_tg_pt, int all_tg_pt,
u8 type) u8 type)
@ -831,7 +839,6 @@ int core_scsi3_alloc_aptpl_registration(
pr_reg->pr_res_key = sa_res_key; pr_reg->pr_res_key = sa_res_key;
pr_reg->pr_reg_all_tg_pt = all_tg_pt; pr_reg->pr_reg_all_tg_pt = all_tg_pt;
pr_reg->pr_reg_aptpl = 1; pr_reg->pr_reg_aptpl = 1;
pr_reg->pr_reg_tg_pt_lun = NULL;
pr_reg->pr_res_scope = 0; /* Always LUN_SCOPE */ pr_reg->pr_res_scope = 0; /* Always LUN_SCOPE */
pr_reg->pr_res_type = type; pr_reg->pr_res_type = type;
/* /*
@ -895,9 +902,9 @@ static int __core_scsi3_check_aptpl_registration(
struct se_device *dev, struct se_device *dev,
struct se_portal_group *tpg, struct se_portal_group *tpg,
struct se_lun *lun, struct se_lun *lun,
u32 target_lun, u64 target_lun,
struct se_node_acl *nacl, struct se_node_acl *nacl,
struct se_dev_entry *deve) u64 mapped_lun)
{ {
struct t10_pr_registration *pr_reg, *pr_reg_tmp; struct t10_pr_registration *pr_reg, *pr_reg_tmp;
struct t10_reservation *pr_tmpl = &dev->t10_pr; struct t10_reservation *pr_tmpl = &dev->t10_pr;
@ -925,14 +932,13 @@ static int __core_scsi3_check_aptpl_registration(
pr_reg_aptpl_list) { pr_reg_aptpl_list) {
if (!strcmp(pr_reg->pr_iport, i_port) && if (!strcmp(pr_reg->pr_iport, i_port) &&
(pr_reg->pr_res_mapped_lun == deve->mapped_lun) && (pr_reg->pr_res_mapped_lun == mapped_lun) &&
!(strcmp(pr_reg->pr_tport, t_port)) && !(strcmp(pr_reg->pr_tport, t_port)) &&
(pr_reg->pr_reg_tpgt == tpgt) && (pr_reg->pr_reg_tpgt == tpgt) &&
(pr_reg->pr_aptpl_target_lun == target_lun)) { (pr_reg->pr_aptpl_target_lun == target_lun)) {
pr_reg->pr_reg_nacl = nacl; pr_reg->pr_reg_nacl = nacl;
pr_reg->pr_reg_deve = deve; pr_reg->tg_pt_sep_rtpi = lun->lun_rtpi;
pr_reg->pr_reg_tg_pt_lun = lun;
list_del(&pr_reg->pr_reg_aptpl_list); list_del(&pr_reg->pr_reg_aptpl_list);
spin_unlock(&pr_tmpl->aptpl_reg_lock); spin_unlock(&pr_tmpl->aptpl_reg_lock);
@ -967,15 +973,14 @@ int core_scsi3_check_aptpl_registration(
struct se_portal_group *tpg, struct se_portal_group *tpg,
struct se_lun *lun, struct se_lun *lun,
struct se_node_acl *nacl, struct se_node_acl *nacl,
u32 mapped_lun) u64 mapped_lun)
{ {
struct se_dev_entry *deve = nacl->device_list[mapped_lun];
if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
return 0; return 0;
return __core_scsi3_check_aptpl_registration(dev, tpg, lun, return __core_scsi3_check_aptpl_registration(dev, tpg, lun,
lun->unpacked_lun, nacl, deve); lun->unpacked_lun, nacl,
mapped_lun);
} }
static void __core_scsi3_dump_registration( static void __core_scsi3_dump_registration(
@ -1009,10 +1014,6 @@ static void __core_scsi3_dump_registration(
pr_reg->pr_reg_aptpl); pr_reg->pr_reg_aptpl);
} }
/*
* this function can be called with struct se_device->dev_reservation_lock
* when register_move = 1
*/
static void __core_scsi3_add_registration( static void __core_scsi3_add_registration(
struct se_device *dev, struct se_device *dev,
struct se_node_acl *nacl, struct se_node_acl *nacl,
@ -1023,6 +1024,7 @@ static void __core_scsi3_add_registration(
const struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo; const struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo;
struct t10_pr_registration *pr_reg_tmp, *pr_reg_tmp_safe; struct t10_pr_registration *pr_reg_tmp, *pr_reg_tmp_safe;
struct t10_reservation *pr_tmpl = &dev->t10_pr; struct t10_reservation *pr_tmpl = &dev->t10_pr;
struct se_dev_entry *deve;
/* /*
* Increment PRgeneration counter for struct se_device upon a successful * Increment PRgeneration counter for struct se_device upon a successful
@ -1039,10 +1041,16 @@ static void __core_scsi3_add_registration(
spin_lock(&pr_tmpl->registration_lock); spin_lock(&pr_tmpl->registration_lock);
list_add_tail(&pr_reg->pr_reg_list, &pr_tmpl->registration_list); list_add_tail(&pr_reg->pr_reg_list, &pr_tmpl->registration_list);
pr_reg->pr_reg_deve->def_pr_registered = 1;
__core_scsi3_dump_registration(tfo, dev, nacl, pr_reg, register_type); __core_scsi3_dump_registration(tfo, dev, nacl, pr_reg, register_type);
spin_unlock(&pr_tmpl->registration_lock); spin_unlock(&pr_tmpl->registration_lock);
rcu_read_lock();
deve = pr_reg->pr_reg_deve;
if (deve)
set_bit(DEF_PR_REG_ACTIVE, &deve->deve_flags);
rcu_read_unlock();
/* /*
* Skip extra processing for ALL_TG_PT=0 or REGISTER_AND_MOVE. * Skip extra processing for ALL_TG_PT=0 or REGISTER_AND_MOVE.
*/ */
@ -1054,6 +1062,8 @@ static void __core_scsi3_add_registration(
*/ */
list_for_each_entry_safe(pr_reg_tmp, pr_reg_tmp_safe, list_for_each_entry_safe(pr_reg_tmp, pr_reg_tmp_safe,
&pr_reg->pr_reg_atp_list, pr_reg_atp_mem_list) { &pr_reg->pr_reg_atp_list, pr_reg_atp_mem_list) {
struct se_node_acl *nacl_tmp = pr_reg_tmp->pr_reg_nacl;
list_del(&pr_reg_tmp->pr_reg_atp_mem_list); list_del(&pr_reg_tmp->pr_reg_atp_mem_list);
pr_reg_tmp->pr_res_generation = core_scsi3_pr_generation(dev); pr_reg_tmp->pr_res_generation = core_scsi3_pr_generation(dev);
@ -1061,12 +1071,17 @@ static void __core_scsi3_add_registration(
spin_lock(&pr_tmpl->registration_lock); spin_lock(&pr_tmpl->registration_lock);
list_add_tail(&pr_reg_tmp->pr_reg_list, list_add_tail(&pr_reg_tmp->pr_reg_list,
&pr_tmpl->registration_list); &pr_tmpl->registration_list);
pr_reg_tmp->pr_reg_deve->def_pr_registered = 1;
__core_scsi3_dump_registration(tfo, dev, __core_scsi3_dump_registration(tfo, dev, nacl_tmp, pr_reg_tmp,
pr_reg_tmp->pr_reg_nacl, pr_reg_tmp, register_type);
register_type);
spin_unlock(&pr_tmpl->registration_lock); spin_unlock(&pr_tmpl->registration_lock);
rcu_read_lock();
deve = pr_reg_tmp->pr_reg_deve;
if (deve)
set_bit(DEF_PR_REG_ACTIVE, &deve->deve_flags);
rcu_read_unlock();
/* /*
* Drop configfs group dependency reference from * Drop configfs group dependency reference from
* __core_scsi3_alloc_registration() * __core_scsi3_alloc_registration()
@ -1078,7 +1093,9 @@ static void __core_scsi3_add_registration(
static int core_scsi3_alloc_registration( static int core_scsi3_alloc_registration(
struct se_device *dev, struct se_device *dev,
struct se_node_acl *nacl, struct se_node_acl *nacl,
struct se_lun *lun,
struct se_dev_entry *deve, struct se_dev_entry *deve,
u64 mapped_lun,
unsigned char *isid, unsigned char *isid,
u64 sa_res_key, u64 sa_res_key,
int all_tg_pt, int all_tg_pt,
@ -1088,8 +1105,9 @@ static int core_scsi3_alloc_registration(
{ {
struct t10_pr_registration *pr_reg; struct t10_pr_registration *pr_reg;
pr_reg = __core_scsi3_alloc_registration(dev, nacl, deve, isid, pr_reg = __core_scsi3_alloc_registration(dev, nacl, lun, deve, mapped_lun,
sa_res_key, all_tg_pt, aptpl); isid, sa_res_key, all_tg_pt,
aptpl);
if (!pr_reg) if (!pr_reg)
return -EPERM; return -EPERM;
@ -1242,13 +1260,13 @@ static void __core_scsi3_free_registration(
const struct target_core_fabric_ops *tfo = const struct target_core_fabric_ops *tfo =
pr_reg->pr_reg_nacl->se_tpg->se_tpg_tfo; pr_reg->pr_reg_nacl->se_tpg->se_tpg_tfo;
struct t10_reservation *pr_tmpl = &dev->t10_pr; struct t10_reservation *pr_tmpl = &dev->t10_pr;
struct se_node_acl *nacl = pr_reg->pr_reg_nacl;
struct se_dev_entry *deve;
char i_buf[PR_REG_ISID_ID_LEN]; char i_buf[PR_REG_ISID_ID_LEN];
memset(i_buf, 0, PR_REG_ISID_ID_LEN); memset(i_buf, 0, PR_REG_ISID_ID_LEN);
core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN); core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN);
pr_reg->pr_reg_deve->def_pr_registered = 0;
pr_reg->pr_reg_deve->pr_res_key = 0;
if (!list_empty(&pr_reg->pr_reg_list)) if (!list_empty(&pr_reg->pr_reg_list))
list_del(&pr_reg->pr_reg_list); list_del(&pr_reg->pr_reg_list);
/* /*
@ -1257,6 +1275,8 @@ static void __core_scsi3_free_registration(
*/ */
if (dec_holders) if (dec_holders)
core_scsi3_put_pr_reg(pr_reg); core_scsi3_put_pr_reg(pr_reg);
spin_unlock(&pr_tmpl->registration_lock);
/* /*
* Wait until all reference from any other I_T nexuses for this * Wait until all reference from any other I_T nexuses for this
* *pr_reg have been released. Because list_del() is called above, * *pr_reg have been released. Because list_del() is called above,
@ -1264,13 +1284,18 @@ static void __core_scsi3_free_registration(
* count back to zero, and we release *pr_reg. * count back to zero, and we release *pr_reg.
*/ */
while (atomic_read(&pr_reg->pr_res_holders) != 0) { while (atomic_read(&pr_reg->pr_res_holders) != 0) {
spin_unlock(&pr_tmpl->registration_lock);
pr_debug("SPC-3 PR [%s] waiting for pr_res_holders\n", pr_debug("SPC-3 PR [%s] waiting for pr_res_holders\n",
tfo->get_fabric_name()); tfo->get_fabric_name());
cpu_relax(); cpu_relax();
spin_lock(&pr_tmpl->registration_lock);
} }
rcu_read_lock();
deve = target_nacl_find_deve(nacl, pr_reg->pr_res_mapped_lun);
if (deve)
clear_bit(DEF_PR_REG_ACTIVE, &deve->deve_flags);
rcu_read_unlock();
spin_lock(&pr_tmpl->registration_lock);
pr_debug("SPC-3 PR [%s] Service Action: UNREGISTER Initiator" pr_debug("SPC-3 PR [%s] Service Action: UNREGISTER Initiator"
" Node: %s%s\n", tfo->get_fabric_name(), " Node: %s%s\n", tfo->get_fabric_name(),
pr_reg->pr_reg_nacl->initiatorname, pr_reg->pr_reg_nacl->initiatorname,
@ -1392,12 +1417,14 @@ static void core_scsi3_nodeacl_undepend_item(struct se_node_acl *nacl)
static int core_scsi3_lunacl_depend_item(struct se_dev_entry *se_deve) static int core_scsi3_lunacl_depend_item(struct se_dev_entry *se_deve)
{ {
struct se_lun_acl *lun_acl = se_deve->se_lun_acl; struct se_lun_acl *lun_acl;
struct se_node_acl *nacl; struct se_node_acl *nacl;
struct se_portal_group *tpg; struct se_portal_group *tpg;
/* /*
* For nacl->dynamic_node_acl=1 * For nacl->dynamic_node_acl=1
*/ */
lun_acl = rcu_dereference_check(se_deve->se_lun_acl,
atomic_read(&se_deve->pr_kref.refcount) != 0);
if (!lun_acl) if (!lun_acl)
return 0; return 0;
@ -1409,21 +1436,23 @@ static int core_scsi3_lunacl_depend_item(struct se_dev_entry *se_deve)
static void core_scsi3_lunacl_undepend_item(struct se_dev_entry *se_deve) static void core_scsi3_lunacl_undepend_item(struct se_dev_entry *se_deve)
{ {
struct se_lun_acl *lun_acl = se_deve->se_lun_acl; struct se_lun_acl *lun_acl;
struct se_node_acl *nacl; struct se_node_acl *nacl;
struct se_portal_group *tpg; struct se_portal_group *tpg;
/* /*
* For nacl->dynamic_node_acl=1 * For nacl->dynamic_node_acl=1
*/ */
lun_acl = rcu_dereference_check(se_deve->se_lun_acl,
atomic_read(&se_deve->pr_kref.refcount) != 0);
if (!lun_acl) { if (!lun_acl) {
atomic_dec_mb(&se_deve->pr_ref_count); kref_put(&se_deve->pr_kref, target_pr_kref_release);
return; return;
} }
nacl = lun_acl->se_lun_nacl; nacl = lun_acl->se_lun_nacl;
tpg = nacl->se_tpg; tpg = nacl->se_tpg;
target_undepend_item(&lun_acl->se_lun_group.cg_item); target_undepend_item(&lun_acl->se_lun_group.cg_item);
atomic_dec_mb(&se_deve->pr_ref_count); kref_put(&se_deve->pr_kref, target_pr_kref_release);
} }
static sense_reason_t static sense_reason_t
@ -1436,30 +1465,25 @@ core_scsi3_decode_spec_i_port(
int aptpl) int aptpl)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct se_port *tmp_port;
struct se_portal_group *dest_tpg = NULL, *tmp_tpg; struct se_portal_group *dest_tpg = NULL, *tmp_tpg;
struct se_session *se_sess = cmd->se_sess; struct se_session *se_sess = cmd->se_sess;
struct se_node_acl *dest_node_acl = NULL; struct se_node_acl *dest_node_acl = NULL;
struct se_dev_entry *dest_se_deve = NULL, *local_se_deve; struct se_dev_entry *dest_se_deve = NULL;
struct t10_pr_registration *dest_pr_reg, *local_pr_reg, *pr_reg_e; struct t10_pr_registration *dest_pr_reg, *local_pr_reg, *pr_reg_e;
struct t10_pr_registration *pr_reg_tmp, *pr_reg_tmp_safe; struct t10_pr_registration *pr_reg_tmp, *pr_reg_tmp_safe;
LIST_HEAD(tid_dest_list); LIST_HEAD(tid_dest_list);
struct pr_transport_id_holder *tidh_new, *tidh, *tidh_tmp; struct pr_transport_id_holder *tidh_new, *tidh, *tidh_tmp;
const struct target_core_fabric_ops *tmp_tf_ops; unsigned char *buf, *ptr, proto_ident;
unsigned char *buf; const unsigned char *i_str;
unsigned char *ptr, *i_str = NULL, proto_ident, tmp_proto_ident;
char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN]; char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN];
sense_reason_t ret; sense_reason_t ret;
u32 tpdl, tid_len = 0; u32 tpdl, tid_len = 0;
int dest_local_nexus;
u32 dest_rtpi = 0; u32 dest_rtpi = 0;
local_se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun];
/* /*
* Allocate a struct pr_transport_id_holder and setup the * Allocate a struct pr_transport_id_holder and setup the
* local_node_acl and local_se_deve pointers and add to * local_node_acl pointer and add to struct list_head tid_dest_list
* struct list_head tid_dest_list for add registration * for add registration processing in the loop of tid_dest_list below.
* processing in the loop of tid_dest_list below.
*/ */
tidh_new = kzalloc(sizeof(struct pr_transport_id_holder), GFP_KERNEL); tidh_new = kzalloc(sizeof(struct pr_transport_id_holder), GFP_KERNEL);
if (!tidh_new) { if (!tidh_new) {
@ -1469,10 +1493,10 @@ core_scsi3_decode_spec_i_port(
INIT_LIST_HEAD(&tidh_new->dest_list); INIT_LIST_HEAD(&tidh_new->dest_list);
tidh_new->dest_tpg = tpg; tidh_new->dest_tpg = tpg;
tidh_new->dest_node_acl = se_sess->se_node_acl; tidh_new->dest_node_acl = se_sess->se_node_acl;
tidh_new->dest_se_deve = local_se_deve;
local_pr_reg = __core_scsi3_alloc_registration(cmd->se_dev, local_pr_reg = __core_scsi3_alloc_registration(cmd->se_dev,
se_sess->se_node_acl, local_se_deve, l_isid, se_sess->se_node_acl, cmd->se_lun,
NULL, cmd->orig_fe_lun, l_isid,
sa_res_key, all_tg_pt, aptpl); sa_res_key, all_tg_pt, aptpl);
if (!local_pr_reg) { if (!local_pr_reg) {
kfree(tidh_new); kfree(tidh_new);
@ -1481,10 +1505,10 @@ core_scsi3_decode_spec_i_port(
tidh_new->dest_pr_reg = local_pr_reg; tidh_new->dest_pr_reg = local_pr_reg;
/* /*
* The local I_T nexus does not hold any configfs dependances, * The local I_T nexus does not hold any configfs dependances,
* so we set tid_h->dest_local_nexus=1 to prevent the * so we set tidh_new->dest_se_deve to NULL to prevent the
* configfs_undepend_item() calls in the tid_dest_list loops below. * configfs_undepend_item() calls in the tid_dest_list loops below.
*/ */
tidh_new->dest_local_nexus = 1; tidh_new->dest_se_deve = NULL;
list_add_tail(&tidh_new->dest_list, &tid_dest_list); list_add_tail(&tidh_new->dest_list, &tid_dest_list);
if (cmd->data_length < 28) { if (cmd->data_length < 28) {
@ -1525,32 +1549,25 @@ core_scsi3_decode_spec_i_port(
ptr = &buf[28]; ptr = &buf[28];
while (tpdl > 0) { while (tpdl > 0) {
struct se_lun *dest_lun, *tmp_lun;
proto_ident = (ptr[0] & 0x0f); proto_ident = (ptr[0] & 0x0f);
dest_tpg = NULL; dest_tpg = NULL;
spin_lock(&dev->se_port_lock); spin_lock(&dev->se_port_lock);
list_for_each_entry(tmp_port, &dev->dev_sep_list, sep_list) { list_for_each_entry(tmp_lun, &dev->dev_sep_list, lun_dev_link) {
tmp_tpg = tmp_port->sep_tpg; tmp_tpg = tmp_lun->lun_tpg;
if (!tmp_tpg)
continue;
tmp_tf_ops = tmp_tpg->se_tpg_tfo;
if (!tmp_tf_ops)
continue;
if (!tmp_tf_ops->get_fabric_proto_ident ||
!tmp_tf_ops->tpg_parse_pr_out_transport_id)
continue;
/* /*
* Look for the matching proto_ident provided by * Look for the matching proto_ident provided by
* the received TransportID * the received TransportID
*/ */
tmp_proto_ident = tmp_tf_ops->get_fabric_proto_ident(tmp_tpg); if (tmp_tpg->proto_id != proto_ident)
if (tmp_proto_ident != proto_ident)
continue; continue;
dest_rtpi = tmp_port->sep_rtpi; dest_rtpi = tmp_lun->lun_rtpi;
i_str = tmp_tf_ops->tpg_parse_pr_out_transport_id( i_str = target_parse_pr_out_transport_id(tmp_tpg,
tmp_tpg, (const char *)ptr, &tid_len, (const char *)ptr, &tid_len, &iport_ptr);
&iport_ptr);
if (!i_str) if (!i_str)
continue; continue;
@ -1569,12 +1586,12 @@ core_scsi3_decode_spec_i_port(
* from the decoded fabric module specific TransportID * from the decoded fabric module specific TransportID
* at *i_str. * at *i_str.
*/ */
spin_lock_irq(&tmp_tpg->acl_node_lock); mutex_lock(&tmp_tpg->acl_node_mutex);
dest_node_acl = __core_tpg_get_initiator_node_acl( dest_node_acl = __core_tpg_get_initiator_node_acl(
tmp_tpg, i_str); tmp_tpg, i_str);
if (dest_node_acl) if (dest_node_acl)
atomic_inc_mb(&dest_node_acl->acl_pr_ref_count); atomic_inc_mb(&dest_node_acl->acl_pr_ref_count);
spin_unlock_irq(&tmp_tpg->acl_node_lock); mutex_unlock(&tmp_tpg->acl_node_mutex);
if (!dest_node_acl) { if (!dest_node_acl) {
core_scsi3_tpg_undepend_item(tmp_tpg); core_scsi3_tpg_undepend_item(tmp_tpg);
@ -1644,7 +1661,7 @@ core_scsi3_decode_spec_i_port(
if (core_scsi3_lunacl_depend_item(dest_se_deve)) { if (core_scsi3_lunacl_depend_item(dest_se_deve)) {
pr_err("core_scsi3_lunacl_depend_item()" pr_err("core_scsi3_lunacl_depend_item()"
" failed\n"); " failed\n");
atomic_dec_mb(&dest_se_deve->pr_ref_count); kref_put(&dest_se_deve->pr_kref, target_pr_kref_release);
core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_nodeacl_undepend_item(dest_node_acl);
core_scsi3_tpg_undepend_item(dest_tpg); core_scsi3_tpg_undepend_item(dest_tpg);
ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
@ -1652,7 +1669,7 @@ core_scsi3_decode_spec_i_port(
} }
pr_debug("SPC-3 PR SPEC_I_PT: Located %s Node: %s" pr_debug("SPC-3 PR SPEC_I_PT: Located %s Node: %s"
" dest_se_deve mapped_lun: %u\n", " dest_se_deve mapped_lun: %llu\n",
dest_tpg->se_tpg_tfo->get_fabric_name(), dest_tpg->se_tpg_tfo->get_fabric_name(),
dest_node_acl->initiatorname, dest_se_deve->mapped_lun); dest_node_acl->initiatorname, dest_se_deve->mapped_lun);
@ -1708,9 +1725,13 @@ core_scsi3_decode_spec_i_port(
* and then call __core_scsi3_add_registration() in the * and then call __core_scsi3_add_registration() in the
* 2nd loop which will never fail. * 2nd loop which will never fail.
*/ */
dest_lun = rcu_dereference_check(dest_se_deve->se_lun,
atomic_read(&dest_se_deve->pr_kref.refcount) != 0);
dest_pr_reg = __core_scsi3_alloc_registration(cmd->se_dev, dest_pr_reg = __core_scsi3_alloc_registration(cmd->se_dev,
dest_node_acl, dest_se_deve, iport_ptr, dest_node_acl, dest_lun, dest_se_deve,
sa_res_key, all_tg_pt, aptpl); dest_se_deve->mapped_lun, iport_ptr,
sa_res_key, all_tg_pt, aptpl);
if (!dest_pr_reg) { if (!dest_pr_reg) {
core_scsi3_lunacl_undepend_item(dest_se_deve); core_scsi3_lunacl_undepend_item(dest_se_deve);
core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_nodeacl_undepend_item(dest_node_acl);
@ -1748,7 +1769,6 @@ core_scsi3_decode_spec_i_port(
dest_node_acl = tidh->dest_node_acl; dest_node_acl = tidh->dest_node_acl;
dest_se_deve = tidh->dest_se_deve; dest_se_deve = tidh->dest_se_deve;
dest_pr_reg = tidh->dest_pr_reg; dest_pr_reg = tidh->dest_pr_reg;
dest_local_nexus = tidh->dest_local_nexus;
list_del(&tidh->dest_list); list_del(&tidh->dest_list);
kfree(tidh); kfree(tidh);
@ -1761,10 +1781,11 @@ core_scsi3_decode_spec_i_port(
pr_debug("SPC-3 PR [%s] SPEC_I_PT: Successfully" pr_debug("SPC-3 PR [%s] SPEC_I_PT: Successfully"
" registered Transport ID for Node: %s%s Mapped LUN:" " registered Transport ID for Node: %s%s Mapped LUN:"
" %u\n", dest_tpg->se_tpg_tfo->get_fabric_name(), " %llu\n", dest_tpg->se_tpg_tfo->get_fabric_name(),
dest_node_acl->initiatorname, i_buf, dest_se_deve->mapped_lun); dest_node_acl->initiatorname, i_buf, (dest_se_deve) ?
dest_se_deve->mapped_lun : 0);
if (dest_local_nexus) if (!dest_se_deve)
continue; continue;
core_scsi3_lunacl_undepend_item(dest_se_deve); core_scsi3_lunacl_undepend_item(dest_se_deve);
@ -1785,7 +1806,6 @@ out:
dest_node_acl = tidh->dest_node_acl; dest_node_acl = tidh->dest_node_acl;
dest_se_deve = tidh->dest_se_deve; dest_se_deve = tidh->dest_se_deve;
dest_pr_reg = tidh->dest_pr_reg; dest_pr_reg = tidh->dest_pr_reg;
dest_local_nexus = tidh->dest_local_nexus;
list_del(&tidh->dest_list); list_del(&tidh->dest_list);
kfree(tidh); kfree(tidh);
@ -1803,7 +1823,7 @@ out:
kmem_cache_free(t10_pr_reg_cache, dest_pr_reg); kmem_cache_free(t10_pr_reg_cache, dest_pr_reg);
if (dest_local_nexus) if (!dest_se_deve)
continue; continue;
core_scsi3_lunacl_undepend_item(dest_se_deve); core_scsi3_lunacl_undepend_item(dest_se_deve);
@ -1818,7 +1838,6 @@ static int core_scsi3_update_aptpl_buf(
unsigned char *buf, unsigned char *buf,
u32 pr_aptpl_buf_len) u32 pr_aptpl_buf_len)
{ {
struct se_lun *lun;
struct se_portal_group *tpg; struct se_portal_group *tpg;
struct t10_pr_registration *pr_reg; struct t10_pr_registration *pr_reg;
unsigned char tmp[512], isid_buf[32]; unsigned char tmp[512], isid_buf[32];
@ -1837,7 +1856,6 @@ static int core_scsi3_update_aptpl_buf(
tmp[0] = '\0'; tmp[0] = '\0';
isid_buf[0] = '\0'; isid_buf[0] = '\0';
tpg = pr_reg->pr_reg_nacl->se_tpg; tpg = pr_reg->pr_reg_nacl->se_tpg;
lun = pr_reg->pr_reg_tg_pt_lun;
/* /*
* Write out any ISID value to APTPL metadata that was included * Write out any ISID value to APTPL metadata that was included
* in the original registration. * in the original registration.
@ -1856,7 +1874,7 @@ static int core_scsi3_update_aptpl_buf(
"sa_res_key=%llu\n" "sa_res_key=%llu\n"
"res_holder=1\nres_type=%02x\n" "res_holder=1\nres_type=%02x\n"
"res_scope=%02x\nres_all_tg_pt=%d\n" "res_scope=%02x\nres_all_tg_pt=%d\n"
"mapped_lun=%u\n", reg_count, "mapped_lun=%llu\n", reg_count,
tpg->se_tpg_tfo->get_fabric_name(), tpg->se_tpg_tfo->get_fabric_name(),
pr_reg->pr_reg_nacl->initiatorname, isid_buf, pr_reg->pr_reg_nacl->initiatorname, isid_buf,
pr_reg->pr_res_key, pr_reg->pr_res_type, pr_reg->pr_res_key, pr_reg->pr_res_type,
@ -1866,7 +1884,7 @@ static int core_scsi3_update_aptpl_buf(
snprintf(tmp, 512, "PR_REG_START: %d\n" snprintf(tmp, 512, "PR_REG_START: %d\n"
"initiator_fabric=%s\ninitiator_node=%s\n%s" "initiator_fabric=%s\ninitiator_node=%s\n%s"
"sa_res_key=%llu\nres_holder=0\n" "sa_res_key=%llu\nres_holder=0\n"
"res_all_tg_pt=%d\nmapped_lun=%u\n", "res_all_tg_pt=%d\nmapped_lun=%llu\n",
reg_count, tpg->se_tpg_tfo->get_fabric_name(), reg_count, tpg->se_tpg_tfo->get_fabric_name(),
pr_reg->pr_reg_nacl->initiatorname, isid_buf, pr_reg->pr_reg_nacl->initiatorname, isid_buf,
pr_reg->pr_res_key, pr_reg->pr_reg_all_tg_pt, pr_reg->pr_res_key, pr_reg->pr_reg_all_tg_pt,
@ -1885,11 +1903,12 @@ static int core_scsi3_update_aptpl_buf(
* Include information about the associated SCSI target port. * Include information about the associated SCSI target port.
*/ */
snprintf(tmp, 512, "target_fabric=%s\ntarget_node=%s\n" snprintf(tmp, 512, "target_fabric=%s\ntarget_node=%s\n"
"tpgt=%hu\nport_rtpi=%hu\ntarget_lun=%u\nPR_REG_END:" "tpgt=%hu\nport_rtpi=%hu\ntarget_lun=%llu\nPR_REG_END:"
" %d\n", tpg->se_tpg_tfo->get_fabric_name(), " %d\n", tpg->se_tpg_tfo->get_fabric_name(),
tpg->se_tpg_tfo->tpg_get_wwn(tpg), tpg->se_tpg_tfo->tpg_get_wwn(tpg),
tpg->se_tpg_tfo->tpg_get_tag(tpg), tpg->se_tpg_tfo->tpg_get_tag(tpg),
lun->lun_sep->sep_rtpi, lun->unpacked_lun, reg_count); pr_reg->tg_pt_sep_rtpi, pr_reg->pr_aptpl_target_lun,
reg_count);
if ((len + strlen(tmp) >= pr_aptpl_buf_len)) { if ((len + strlen(tmp) >= pr_aptpl_buf_len)) {
pr_err("Unable to update renaming APTPL metadata," pr_err("Unable to update renaming APTPL metadata,"
@ -2000,7 +2019,6 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
{ {
struct se_session *se_sess = cmd->se_sess; struct se_session *se_sess = cmd->se_sess;
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct se_dev_entry *se_deve;
struct se_lun *se_lun = cmd->se_lun; struct se_lun *se_lun = cmd->se_lun;
struct se_portal_group *se_tpg; struct se_portal_group *se_tpg;
struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_reg_tmp; struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_reg_tmp;
@ -2014,7 +2032,6 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
} }
se_tpg = se_sess->se_tpg; se_tpg = se_sess->se_tpg;
se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun];
if (se_tpg->se_tpg_tfo->sess_get_initiator_sid) { if (se_tpg->se_tpg_tfo->sess_get_initiator_sid) {
memset(&isid_buf[0], 0, PR_REG_ISID_LEN); memset(&isid_buf[0], 0, PR_REG_ISID_LEN);
@ -2045,7 +2062,8 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
* Logical Unit of the SCSI device server. * Logical Unit of the SCSI device server.
*/ */
if (core_scsi3_alloc_registration(cmd->se_dev, if (core_scsi3_alloc_registration(cmd->se_dev,
se_sess->se_node_acl, se_deve, isid_ptr, se_sess->se_node_acl, cmd->se_lun,
NULL, cmd->orig_fe_lun, isid_ptr,
sa_res_key, all_tg_pt, aptpl, sa_res_key, all_tg_pt, aptpl,
register_type, 0)) { register_type, 0)) {
pr_err("Unable to allocate" pr_err("Unable to allocate"
@ -2066,7 +2084,6 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
if (ret != 0) if (ret != 0)
return ret; return ret;
} }
return core_scsi3_update_and_write_aptpl(dev, aptpl); return core_scsi3_update_and_write_aptpl(dev, aptpl);
} }
@ -2180,7 +2197,7 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
&pr_tmpl->registration_list, &pr_tmpl->registration_list,
pr_reg_list) { pr_reg_list) {
core_scsi3_ua_allocate( target_ua_allocate_lun(
pr_reg_p->pr_reg_nacl, pr_reg_p->pr_reg_nacl,
pr_reg_p->pr_res_mapped_lun, pr_reg_p->pr_res_mapped_lun,
0x2A, 0x2A,
@ -2607,7 +2624,7 @@ core_scsi3_emulate_pro_release(struct se_cmd *cmd, int type, int scope,
if (pr_reg_p == pr_reg) if (pr_reg_p == pr_reg)
continue; continue;
core_scsi3_ua_allocate(pr_reg_p->pr_reg_nacl, target_ua_allocate_lun(pr_reg_p->pr_reg_nacl,
pr_reg_p->pr_res_mapped_lun, pr_reg_p->pr_res_mapped_lun,
0x2A, ASCQ_2AH_RESERVATIONS_RELEASED); 0x2A, ASCQ_2AH_RESERVATIONS_RELEASED);
} }
@ -2630,7 +2647,7 @@ core_scsi3_emulate_pro_clear(struct se_cmd *cmd, u64 res_key)
struct se_session *se_sess = cmd->se_sess; struct se_session *se_sess = cmd->se_sess;
struct t10_reservation *pr_tmpl = &dev->t10_pr; struct t10_reservation *pr_tmpl = &dev->t10_pr;
struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_reg_n, *pr_res_holder; struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_reg_n, *pr_res_holder;
u32 pr_res_mapped_lun = 0; u64 pr_res_mapped_lun = 0;
int calling_it_nexus = 0; int calling_it_nexus = 0;
/* /*
* Locate the existing *pr_reg via struct se_node_acl pointers * Locate the existing *pr_reg via struct se_node_acl pointers
@ -2692,7 +2709,7 @@ core_scsi3_emulate_pro_clear(struct se_cmd *cmd, u64 res_key)
* additional sense code set to RESERVATIONS PREEMPTED. * additional sense code set to RESERVATIONS PREEMPTED.
*/ */
if (!calling_it_nexus) if (!calling_it_nexus)
core_scsi3_ua_allocate(pr_reg_nacl, pr_res_mapped_lun, target_ua_allocate_lun(pr_reg_nacl, pr_res_mapped_lun,
0x2A, ASCQ_2AH_RESERVATIONS_PREEMPTED); 0x2A, ASCQ_2AH_RESERVATIONS_PREEMPTED);
} }
spin_unlock(&pr_tmpl->registration_lock); spin_unlock(&pr_tmpl->registration_lock);
@ -2786,7 +2803,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
LIST_HEAD(preempt_and_abort_list); LIST_HEAD(preempt_and_abort_list);
struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_reg_n, *pr_res_holder; struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_reg_n, *pr_res_holder;
struct t10_reservation *pr_tmpl = &dev->t10_pr; struct t10_reservation *pr_tmpl = &dev->t10_pr;
u32 pr_res_mapped_lun = 0; u64 pr_res_mapped_lun = 0;
int all_reg = 0, calling_it_nexus = 0; int all_reg = 0, calling_it_nexus = 0;
bool sa_res_key_unmatched = sa_res_key != 0; bool sa_res_key_unmatched = sa_res_key != 0;
int prh_type = 0, prh_scope = 0; int prh_type = 0, prh_scope = 0;
@ -2901,7 +2918,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
NULL, 0); NULL, 0);
} }
if (!calling_it_nexus) if (!calling_it_nexus)
core_scsi3_ua_allocate(pr_reg_nacl, target_ua_allocate_lun(pr_reg_nacl,
pr_res_mapped_lun, 0x2A, pr_res_mapped_lun, 0x2A,
ASCQ_2AH_REGISTRATIONS_PREEMPTED); ASCQ_2AH_REGISTRATIONS_PREEMPTED);
} }
@ -3007,7 +3024,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
* persistent reservation and/or registration, with the * persistent reservation and/or registration, with the
* additional sense code set to REGISTRATIONS PREEMPTED; * additional sense code set to REGISTRATIONS PREEMPTED;
*/ */
core_scsi3_ua_allocate(pr_reg_nacl, pr_res_mapped_lun, 0x2A, target_ua_allocate_lun(pr_reg_nacl, pr_res_mapped_lun, 0x2A,
ASCQ_2AH_REGISTRATIONS_PREEMPTED); ASCQ_2AH_REGISTRATIONS_PREEMPTED);
} }
spin_unlock(&pr_tmpl->registration_lock); spin_unlock(&pr_tmpl->registration_lock);
@ -3040,7 +3057,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
if (calling_it_nexus) if (calling_it_nexus)
continue; continue;
core_scsi3_ua_allocate(pr_reg->pr_reg_nacl, target_ua_allocate_lun(pr_reg->pr_reg_nacl,
pr_reg->pr_res_mapped_lun, 0x2A, pr_reg->pr_res_mapped_lun, 0x2A,
ASCQ_2AH_RESERVATIONS_RELEASED); ASCQ_2AH_RESERVATIONS_RELEASED);
} }
@ -3099,15 +3116,14 @@ core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key,
struct se_session *se_sess = cmd->se_sess; struct se_session *se_sess = cmd->se_sess;
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct se_dev_entry *dest_se_deve = NULL; struct se_dev_entry *dest_se_deve = NULL;
struct se_lun *se_lun = cmd->se_lun; struct se_lun *se_lun = cmd->se_lun, *tmp_lun;
struct se_node_acl *pr_res_nacl, *pr_reg_nacl, *dest_node_acl = NULL; struct se_node_acl *pr_res_nacl, *pr_reg_nacl, *dest_node_acl = NULL;
struct se_port *se_port;
struct se_portal_group *se_tpg, *dest_se_tpg = NULL; struct se_portal_group *se_tpg, *dest_se_tpg = NULL;
const struct target_core_fabric_ops *dest_tf_ops = NULL, *tf_ops; const struct target_core_fabric_ops *dest_tf_ops = NULL, *tf_ops;
struct t10_pr_registration *pr_reg, *pr_res_holder, *dest_pr_reg; struct t10_pr_registration *pr_reg, *pr_res_holder, *dest_pr_reg;
struct t10_reservation *pr_tmpl = &dev->t10_pr; struct t10_reservation *pr_tmpl = &dev->t10_pr;
unsigned char *buf; unsigned char *buf;
unsigned char *initiator_str; const unsigned char *initiator_str;
char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN]; char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN];
u32 tid_len, tmp_tid_len; u32 tid_len, tmp_tid_len;
int new_reg = 0, type, scope, matching_iname; int new_reg = 0, type, scope, matching_iname;
@ -3186,12 +3202,10 @@ core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key,
} }
spin_lock(&dev->se_port_lock); spin_lock(&dev->se_port_lock);
list_for_each_entry(se_port, &dev->dev_sep_list, sep_list) { list_for_each_entry(tmp_lun, &dev->dev_sep_list, lun_dev_link) {
if (se_port->sep_rtpi != rtpi) if (tmp_lun->lun_rtpi != rtpi)
continue;
dest_se_tpg = se_port->sep_tpg;
if (!dest_se_tpg)
continue; continue;
dest_se_tpg = tmp_lun->lun_tpg;
dest_tf_ops = dest_se_tpg->se_tpg_tfo; dest_tf_ops = dest_se_tpg->se_tpg_tfo;
if (!dest_tf_ops) if (!dest_tf_ops)
continue; continue;
@ -3230,23 +3244,16 @@ core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key,
pr_debug("SPC-3 PR REGISTER_AND_MOVE: Extracted Protocol Identifier:" pr_debug("SPC-3 PR REGISTER_AND_MOVE: Extracted Protocol Identifier:"
" 0x%02x\n", proto_ident); " 0x%02x\n", proto_ident);
if (proto_ident != dest_tf_ops->get_fabric_proto_ident(dest_se_tpg)) { if (proto_ident != dest_se_tpg->proto_id) {
pr_err("SPC-3 PR REGISTER_AND_MOVE: Received" pr_err("SPC-3 PR REGISTER_AND_MOVE: Received"
" proto_ident: 0x%02x does not match ident: 0x%02x" " proto_ident: 0x%02x does not match ident: 0x%02x"
" from fabric: %s\n", proto_ident, " from fabric: %s\n", proto_ident,
dest_tf_ops->get_fabric_proto_ident(dest_se_tpg), dest_se_tpg->proto_id,
dest_tf_ops->get_fabric_name()); dest_tf_ops->get_fabric_name());
ret = TCM_INVALID_PARAMETER_LIST; ret = TCM_INVALID_PARAMETER_LIST;
goto out; goto out;
} }
if (dest_tf_ops->tpg_parse_pr_out_transport_id == NULL) { initiator_str = target_parse_pr_out_transport_id(dest_se_tpg,
pr_err("SPC-3 PR REGISTER_AND_MOVE: Fabric does not"
" containg a valid tpg_parse_pr_out_transport_id"
" function pointer\n");
ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
goto out;
}
initiator_str = dest_tf_ops->tpg_parse_pr_out_transport_id(dest_se_tpg,
(const char *)&buf[24], &tmp_tid_len, &iport_ptr); (const char *)&buf[24], &tmp_tid_len, &iport_ptr);
if (!initiator_str) { if (!initiator_str) {
pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate" pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate"
@ -3295,12 +3302,12 @@ after_iport_check:
/* /*
* Locate the destination struct se_node_acl from the received Transport ID * Locate the destination struct se_node_acl from the received Transport ID
*/ */
spin_lock_irq(&dest_se_tpg->acl_node_lock); mutex_lock(&dest_se_tpg->acl_node_mutex);
dest_node_acl = __core_tpg_get_initiator_node_acl(dest_se_tpg, dest_node_acl = __core_tpg_get_initiator_node_acl(dest_se_tpg,
initiator_str); initiator_str);
if (dest_node_acl) if (dest_node_acl)
atomic_inc_mb(&dest_node_acl->acl_pr_ref_count); atomic_inc_mb(&dest_node_acl->acl_pr_ref_count);
spin_unlock_irq(&dest_se_tpg->acl_node_lock); mutex_unlock(&dest_se_tpg->acl_node_mutex);
if (!dest_node_acl) { if (!dest_node_acl) {
pr_err("Unable to locate %s dest_node_acl for" pr_err("Unable to locate %s dest_node_acl for"
@ -3337,14 +3344,14 @@ after_iport_check:
if (core_scsi3_lunacl_depend_item(dest_se_deve)) { if (core_scsi3_lunacl_depend_item(dest_se_deve)) {
pr_err("core_scsi3_lunacl_depend_item() failed\n"); pr_err("core_scsi3_lunacl_depend_item() failed\n");
atomic_dec_mb(&dest_se_deve->pr_ref_count); kref_put(&dest_se_deve->pr_kref, target_pr_kref_release);
dest_se_deve = NULL; dest_se_deve = NULL;
ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
goto out; goto out;
} }
pr_debug("SPC-3 PR REGISTER_AND_MOVE: Located %s node %s LUN" pr_debug("SPC-3 PR REGISTER_AND_MOVE: Located %s node %s LUN"
" ACL for dest_se_deve->mapped_lun: %u\n", " ACL for dest_se_deve->mapped_lun: %llu\n",
dest_tf_ops->get_fabric_name(), dest_node_acl->initiatorname, dest_tf_ops->get_fabric_name(), dest_node_acl->initiatorname,
dest_se_deve->mapped_lun); dest_se_deve->mapped_lun);
@ -3421,13 +3428,17 @@ after_iport_check:
dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl, dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl,
iport_ptr); iport_ptr);
if (!dest_pr_reg) { if (!dest_pr_reg) {
if (core_scsi3_alloc_registration(cmd->se_dev, struct se_lun *dest_lun = rcu_dereference_check(dest_se_deve->se_lun,
dest_node_acl, dest_se_deve, iport_ptr, atomic_read(&dest_se_deve->pr_kref.refcount) != 0);
sa_res_key, 0, aptpl, 2, 1)) {
spin_unlock(&dev->dev_reservation_lock); spin_unlock(&dev->dev_reservation_lock);
if (core_scsi3_alloc_registration(cmd->se_dev, dest_node_acl,
dest_lun, dest_se_deve, dest_se_deve->mapped_lun,
iport_ptr, sa_res_key, 0, aptpl, 2, 1)) {
ret = TCM_INVALID_PARAMETER_LIST; ret = TCM_INVALID_PARAMETER_LIST;
goto out; goto out;
} }
spin_lock(&dev->dev_reservation_lock);
dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl, dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl,
iport_ptr); iport_ptr);
new_reg = 1; new_reg = 1;
@ -3883,9 +3894,10 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd)
struct t10_pr_registration *pr_reg, *pr_reg_tmp; struct t10_pr_registration *pr_reg, *pr_reg_tmp;
struct t10_reservation *pr_tmpl = &dev->t10_pr; struct t10_reservation *pr_tmpl = &dev->t10_pr;
unsigned char *buf; unsigned char *buf;
u32 add_desc_len = 0, add_len = 0, desc_len, exp_desc_len; u32 add_desc_len = 0, add_len = 0;
u32 off = 8; /* off into first Full Status descriptor */ u32 off = 8; /* off into first Full Status descriptor */
int format_code = 0, pr_res_type = 0, pr_res_scope = 0; int format_code = 0, pr_res_type = 0, pr_res_scope = 0;
int exp_desc_len, desc_len;
bool all_reg = false; bool all_reg = false;
if (cmd->data_length < 8) { if (cmd->data_length < 8) {
@ -3930,10 +3942,10 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd)
* Determine expected length of $FABRIC_MOD specific * Determine expected length of $FABRIC_MOD specific
* TransportID full status descriptor.. * TransportID full status descriptor..
*/ */
exp_desc_len = se_tpg->se_tpg_tfo->tpg_get_pr_transport_id_len( exp_desc_len = target_get_pr_transport_id_len(se_nacl, pr_reg,
se_tpg, se_nacl, pr_reg, &format_code); &format_code);
if (exp_desc_len < 0 ||
if ((exp_desc_len + add_len) > cmd->data_length) { exp_desc_len + add_len > cmd->data_length) {
pr_warn("SPC-3 PRIN READ_FULL_STATUS ran" pr_warn("SPC-3 PRIN READ_FULL_STATUS ran"
" out of buffer: %d\n", cmd->data_length); " out of buffer: %d\n", cmd->data_length);
spin_lock(&pr_tmpl->registration_lock); spin_lock(&pr_tmpl->registration_lock);
@ -3990,21 +4002,26 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd)
* IDENTIFIER field are not defined by this standard. * IDENTIFIER field are not defined by this standard.
*/ */
if (!pr_reg->pr_reg_all_tg_pt) { if (!pr_reg->pr_reg_all_tg_pt) {
struct se_port *port = pr_reg->pr_reg_tg_pt_lun->lun_sep; u16 sep_rtpi = pr_reg->tg_pt_sep_rtpi;
buf[off++] = ((port->sep_rtpi >> 8) & 0xff); buf[off++] = ((sep_rtpi >> 8) & 0xff);
buf[off++] = (port->sep_rtpi & 0xff); buf[off++] = (sep_rtpi & 0xff);
} else } else
off += 2; /* Skip over RELATIVE TARGET PORT IDENTIFIER */ off += 2; /* Skip over RELATIVE TARGET PORT IDENTIFIER */
buf[off+4] = se_tpg->proto_id;
/* /*
* Now, have the $FABRIC_MOD fill in the protocol identifier * Now, have the $FABRIC_MOD fill in the transport ID.
*/ */
desc_len = se_tpg->se_tpg_tfo->tpg_get_pr_transport_id(se_tpg, desc_len = target_get_pr_transport_id(se_nacl, pr_reg,
se_nacl, pr_reg, &format_code, &buf[off+4]); &format_code, &buf[off+4]);
spin_lock(&pr_tmpl->registration_lock); spin_lock(&pr_tmpl->registration_lock);
atomic_dec_mb(&pr_reg->pr_res_holders); atomic_dec_mb(&pr_reg->pr_res_holders);
if (desc_len < 0)
break;
/* /*
* Set the ADDITIONAL DESCRIPTOR LENGTH * Set the ADDITIONAL DESCRIPTOR LENGTH
*/ */

View File

@ -56,11 +56,11 @@ extern sense_reason_t target_scsi2_reservation_release(struct se_cmd *);
extern sense_reason_t target_scsi2_reservation_reserve(struct se_cmd *); extern sense_reason_t target_scsi2_reservation_reserve(struct se_cmd *);
extern int core_scsi3_alloc_aptpl_registration( extern int core_scsi3_alloc_aptpl_registration(
struct t10_reservation *, u64, struct t10_reservation *, u64,
unsigned char *, unsigned char *, u32, unsigned char *, unsigned char *, u64,
unsigned char *, u16, u32, int, int, u8); unsigned char *, u16, u64, int, int, u8);
extern int core_scsi3_check_aptpl_registration(struct se_device *, extern int core_scsi3_check_aptpl_registration(struct se_device *,
struct se_portal_group *, struct se_lun *, struct se_portal_group *, struct se_lun *,
struct se_node_acl *, u32); struct se_node_acl *, u64);
extern void core_scsi3_free_pr_reg_from_nacl(struct se_device *, extern void core_scsi3_free_pr_reg_from_nacl(struct se_device *,
struct se_node_acl *); struct se_node_acl *);
extern void core_scsi3_free_all_registrations(struct se_device *); extern void core_scsi3_free_all_registrations(struct se_device *);

View File

@ -42,9 +42,9 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_backend.h> #include <target/target_core_backend.h>
#include <target/target_core_backend_configfs.h>
#include "target_core_alua.h" #include "target_core_alua.h"
#include "target_core_internal.h"
#include "target_core_pscsi.h" #include "target_core_pscsi.h"
#define ISPRINT(a) ((a >= ' ') && (a <= '~')) #define ISPRINT(a) ((a >= ' ') && (a <= '~'))
@ -54,8 +54,6 @@ static inline struct pscsi_dev_virt *PSCSI_DEV(struct se_device *dev)
return container_of(dev, struct pscsi_dev_virt, dev); return container_of(dev, struct pscsi_dev_virt, dev);
} }
static struct se_subsystem_api pscsi_template;
static sense_reason_t pscsi_execute_cmd(struct se_cmd *cmd); static sense_reason_t pscsi_execute_cmd(struct se_cmd *cmd);
static void pscsi_req_done(struct request *, int); static void pscsi_req_done(struct request *, int);
@ -80,7 +78,7 @@ static int pscsi_attach_hba(struct se_hba *hba, u32 host_id)
pr_debug("CORE_HBA[%d] - TCM SCSI HBA Driver %s on" pr_debug("CORE_HBA[%d] - TCM SCSI HBA Driver %s on"
" Generic Target Core Stack %s\n", hba->hba_id, " Generic Target Core Stack %s\n", hba->hba_id,
PSCSI_VERSION, TARGET_CORE_MOD_VERSION); PSCSI_VERSION, TARGET_CORE_VERSION);
pr_debug("CORE_HBA[%d] - Attached SCSI HBA to Generic\n", pr_debug("CORE_HBA[%d] - Attached SCSI HBA to Generic\n",
hba->hba_id); hba->hba_id);
@ -579,6 +577,14 @@ static int pscsi_configure_device(struct se_device *dev)
return -ENODEV; return -ENODEV;
} }
static void pscsi_dev_call_rcu(struct rcu_head *p)
{
struct se_device *dev = container_of(p, struct se_device, rcu_head);
struct pscsi_dev_virt *pdv = PSCSI_DEV(dev);
kfree(pdv);
}
static void pscsi_free_device(struct se_device *dev) static void pscsi_free_device(struct se_device *dev)
{ {
struct pscsi_dev_virt *pdv = PSCSI_DEV(dev); struct pscsi_dev_virt *pdv = PSCSI_DEV(dev);
@ -610,8 +616,7 @@ static void pscsi_free_device(struct se_device *dev)
pdv->pdv_sd = NULL; pdv->pdv_sd = NULL;
} }
call_rcu(&dev->rcu_head, pscsi_dev_call_rcu);
kfree(pdv);
} }
static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg, static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg,
@ -635,12 +640,14 @@ static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg,
* Hack to make sure that Write-Protect modepage is set if R/O mode is * Hack to make sure that Write-Protect modepage is set if R/O mode is
* forced. * forced.
*/ */
if (!cmd->se_deve || !cmd->data_length) if (!cmd->data_length)
goto after_mode_sense; goto after_mode_sense;
if (((cdb[0] == MODE_SENSE) || (cdb[0] == MODE_SENSE_10)) && if (((cdb[0] == MODE_SENSE) || (cdb[0] == MODE_SENSE_10)) &&
(status_byte(result) << 1) == SAM_STAT_GOOD) { (status_byte(result) << 1) == SAM_STAT_GOOD) {
if (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) { bool read_only = target_lun_is_rdonly(cmd);
if (read_only) {
unsigned char *buf; unsigned char *buf;
buf = transport_kmap_data_sg(cmd); buf = transport_kmap_data_sg(cmd);
@ -1116,27 +1123,7 @@ static void pscsi_req_done(struct request *req, int uptodate)
kfree(pt); kfree(pt);
} }
DEF_TB_DEV_ATTRIB_RO(pscsi, hw_pi_prot_type); static const struct target_backend_ops pscsi_ops = {
TB_DEV_ATTR_RO(pscsi, hw_pi_prot_type);
DEF_TB_DEV_ATTRIB_RO(pscsi, hw_block_size);
TB_DEV_ATTR_RO(pscsi, hw_block_size);
DEF_TB_DEV_ATTRIB_RO(pscsi, hw_max_sectors);
TB_DEV_ATTR_RO(pscsi, hw_max_sectors);
DEF_TB_DEV_ATTRIB_RO(pscsi, hw_queue_depth);
TB_DEV_ATTR_RO(pscsi, hw_queue_depth);
static struct configfs_attribute *pscsi_backend_dev_attrs[] = {
&pscsi_dev_attrib_hw_pi_prot_type.attr,
&pscsi_dev_attrib_hw_block_size.attr,
&pscsi_dev_attrib_hw_max_sectors.attr,
&pscsi_dev_attrib_hw_queue_depth.attr,
NULL,
};
static struct se_subsystem_api pscsi_template = {
.name = "pscsi", .name = "pscsi",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.transport_flags = TRANSPORT_FLAG_PASSTHROUGH, .transport_flags = TRANSPORT_FLAG_PASSTHROUGH,
@ -1152,21 +1139,17 @@ static struct se_subsystem_api pscsi_template = {
.show_configfs_dev_params = pscsi_show_configfs_dev_params, .show_configfs_dev_params = pscsi_show_configfs_dev_params,
.get_device_type = pscsi_get_device_type, .get_device_type = pscsi_get_device_type,
.get_blocks = pscsi_get_blocks, .get_blocks = pscsi_get_blocks,
.tb_dev_attrib_attrs = passthrough_attrib_attrs,
}; };
static int __init pscsi_module_init(void) static int __init pscsi_module_init(void)
{ {
struct target_backend_cits *tbc = &pscsi_template.tb_cits; return transport_backend_register(&pscsi_ops);
target_core_setup_sub_cits(&pscsi_template);
tbc->tb_dev_attrib_cit.ct_attrs = pscsi_backend_dev_attrs;
return transport_subsystem_register(&pscsi_template);
} }
static void __exit pscsi_module_exit(void) static void __exit pscsi_module_exit(void)
{ {
transport_subsystem_release(&pscsi_template); target_backend_unregister(&pscsi_ops);
} }
MODULE_DESCRIPTION("TCM PSCSI subsystem plugin"); MODULE_DESCRIPTION("TCM PSCSI subsystem plugin");

View File

@ -33,7 +33,6 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_backend.h> #include <target/target_core_backend.h>
#include <target/target_core_backend_configfs.h>
#include "target_core_rd.h" #include "target_core_rd.h"
@ -42,10 +41,6 @@ static inline struct rd_dev *RD_DEV(struct se_device *dev)
return container_of(dev, struct rd_dev, dev); return container_of(dev, struct rd_dev, dev);
} }
/* rd_attach_hba(): (Part of se_subsystem_api_t template)
*
*
*/
static int rd_attach_hba(struct se_hba *hba, u32 host_id) static int rd_attach_hba(struct se_hba *hba, u32 host_id)
{ {
struct rd_host *rd_host; struct rd_host *rd_host;
@ -62,7 +57,7 @@ static int rd_attach_hba(struct se_hba *hba, u32 host_id)
pr_debug("CORE_HBA[%d] - TCM Ramdisk HBA Driver %s on" pr_debug("CORE_HBA[%d] - TCM Ramdisk HBA Driver %s on"
" Generic Target Core Stack %s\n", hba->hba_id, " Generic Target Core Stack %s\n", hba->hba_id,
RD_HBA_VERSION, TARGET_CORE_MOD_VERSION); RD_HBA_VERSION, TARGET_CORE_VERSION);
return 0; return 0;
} }
@ -354,12 +349,20 @@ fail:
return ret; return ret;
} }
static void rd_dev_call_rcu(struct rcu_head *p)
{
struct se_device *dev = container_of(p, struct se_device, rcu_head);
struct rd_dev *rd_dev = RD_DEV(dev);
kfree(rd_dev);
}
static void rd_free_device(struct se_device *dev) static void rd_free_device(struct se_device *dev)
{ {
struct rd_dev *rd_dev = RD_DEV(dev); struct rd_dev *rd_dev = RD_DEV(dev);
rd_release_device_space(rd_dev); rd_release_device_space(rd_dev);
kfree(rd_dev); call_rcu(&dev->rcu_head, rd_dev_call_rcu);
} }
static struct rd_dev_sg_table *rd_get_sg_table(struct rd_dev *rd_dev, u32 page) static struct rd_dev_sg_table *rd_get_sg_table(struct rd_dev *rd_dev, u32 page)
@ -402,10 +405,7 @@ static struct rd_dev_sg_table *rd_get_prot_table(struct rd_dev *rd_dev, u32 page
return NULL; return NULL;
} }
typedef sense_reason_t (*dif_verify)(struct se_cmd *, sector_t, unsigned int, static sense_reason_t rd_do_prot_rw(struct se_cmd *cmd, bool is_read)
unsigned int, struct scatterlist *, int);
static sense_reason_t rd_do_prot_rw(struct se_cmd *cmd, dif_verify dif_verify)
{ {
struct se_device *se_dev = cmd->se_dev; struct se_device *se_dev = cmd->se_dev;
struct rd_dev *dev = RD_DEV(se_dev); struct rd_dev *dev = RD_DEV(se_dev);
@ -465,7 +465,16 @@ static sense_reason_t rd_do_prot_rw(struct se_cmd *cmd, dif_verify dif_verify)
#endif /* !CONFIG_ARCH_HAS_SG_CHAIN */ #endif /* !CONFIG_ARCH_HAS_SG_CHAIN */
rc = dif_verify(cmd, cmd->t_task_lba, sectors, 0, prot_sg, prot_offset); if (is_read)
rc = sbc_dif_verify(cmd, cmd->t_task_lba, sectors, 0,
prot_sg, prot_offset);
else
rc = sbc_dif_verify(cmd, cmd->t_task_lba, sectors, 0,
cmd->t_prot_sg, 0);
if (!rc)
sbc_dif_copy_prot(cmd, sectors, is_read, prot_sg, prot_offset);
if (need_to_release) if (need_to_release)
kfree(prot_sg); kfree(prot_sg);
@ -511,7 +520,7 @@ rd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
if (cmd->prot_type && se_dev->dev_attrib.pi_prot_type && if (cmd->prot_type && se_dev->dev_attrib.pi_prot_type &&
data_direction == DMA_TO_DEVICE) { data_direction == DMA_TO_DEVICE) {
rc = rd_do_prot_rw(cmd, sbc_dif_verify_write); rc = rd_do_prot_rw(cmd, false);
if (rc) if (rc)
return rc; return rc;
} }
@ -579,7 +588,7 @@ rd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
if (cmd->prot_type && se_dev->dev_attrib.pi_prot_type && if (cmd->prot_type && se_dev->dev_attrib.pi_prot_type &&
data_direction == DMA_FROM_DEVICE) { data_direction == DMA_FROM_DEVICE) {
rc = rd_do_prot_rw(cmd, sbc_dif_verify_read); rc = rd_do_prot_rw(cmd, true);
if (rc) if (rc)
return rc; return rc;
} }
@ -693,42 +702,7 @@ rd_parse_cdb(struct se_cmd *cmd)
return sbc_parse_cdb(cmd, &rd_sbc_ops); return sbc_parse_cdb(cmd, &rd_sbc_ops);
} }
DEF_TB_DEFAULT_ATTRIBS(rd_mcp); static const struct target_backend_ops rd_mcp_ops = {
static struct configfs_attribute *rd_mcp_backend_dev_attrs[] = {
&rd_mcp_dev_attrib_emulate_model_alias.attr,
&rd_mcp_dev_attrib_emulate_dpo.attr,
&rd_mcp_dev_attrib_emulate_fua_write.attr,
&rd_mcp_dev_attrib_emulate_fua_read.attr,
&rd_mcp_dev_attrib_emulate_write_cache.attr,
&rd_mcp_dev_attrib_emulate_ua_intlck_ctrl.attr,
&rd_mcp_dev_attrib_emulate_tas.attr,
&rd_mcp_dev_attrib_emulate_tpu.attr,
&rd_mcp_dev_attrib_emulate_tpws.attr,
&rd_mcp_dev_attrib_emulate_caw.attr,
&rd_mcp_dev_attrib_emulate_3pc.attr,
&rd_mcp_dev_attrib_pi_prot_type.attr,
&rd_mcp_dev_attrib_hw_pi_prot_type.attr,
&rd_mcp_dev_attrib_pi_prot_format.attr,
&rd_mcp_dev_attrib_enforce_pr_isids.attr,
&rd_mcp_dev_attrib_is_nonrot.attr,
&rd_mcp_dev_attrib_emulate_rest_reord.attr,
&rd_mcp_dev_attrib_force_pr_aptpl.attr,
&rd_mcp_dev_attrib_hw_block_size.attr,
&rd_mcp_dev_attrib_block_size.attr,
&rd_mcp_dev_attrib_hw_max_sectors.attr,
&rd_mcp_dev_attrib_optimal_sectors.attr,
&rd_mcp_dev_attrib_hw_queue_depth.attr,
&rd_mcp_dev_attrib_queue_depth.attr,
&rd_mcp_dev_attrib_max_unmap_lba_count.attr,
&rd_mcp_dev_attrib_max_unmap_block_desc_count.attr,
&rd_mcp_dev_attrib_unmap_granularity.attr,
&rd_mcp_dev_attrib_unmap_granularity_alignment.attr,
&rd_mcp_dev_attrib_max_write_same_len.attr,
NULL,
};
static struct se_subsystem_api rd_mcp_template = {
.name = "rd_mcp", .name = "rd_mcp",
.inquiry_prod = "RAMDISK-MCP", .inquiry_prod = "RAMDISK-MCP",
.inquiry_rev = RD_MCP_VERSION, .inquiry_rev = RD_MCP_VERSION,
@ -744,25 +718,15 @@ static struct se_subsystem_api rd_mcp_template = {
.get_blocks = rd_get_blocks, .get_blocks = rd_get_blocks,
.init_prot = rd_init_prot, .init_prot = rd_init_prot,
.free_prot = rd_free_prot, .free_prot = rd_free_prot,
.tb_dev_attrib_attrs = sbc_attrib_attrs,
}; };
int __init rd_module_init(void) int __init rd_module_init(void)
{ {
struct target_backend_cits *tbc = &rd_mcp_template.tb_cits; return transport_backend_register(&rd_mcp_ops);
int ret;
target_core_setup_sub_cits(&rd_mcp_template);
tbc->tb_dev_attrib_cit.ct_attrs = rd_mcp_backend_dev_attrs;
ret = transport_subsystem_register(&rd_mcp_template);
if (ret < 0) {
return ret;
}
return 0;
} }
void rd_module_exit(void) void rd_module_exit(void)
{ {
transport_subsystem_release(&rd_mcp_template); target_backend_unregister(&rd_mcp_ops);
} }

View File

@ -38,6 +38,7 @@
static sense_reason_t static sense_reason_t
sbc_check_prot(struct se_device *, struct se_cmd *, unsigned char *, u32, bool); sbc_check_prot(struct se_device *, struct se_cmd *, unsigned char *, u32, bool);
static sense_reason_t sbc_execute_unmap(struct se_cmd *cmd);
static sense_reason_t static sense_reason_t
sbc_emulate_readcapacity(struct se_cmd *cmd) sbc_emulate_readcapacity(struct se_cmd *cmd)
@ -176,6 +177,23 @@ sector_t sbc_get_write_same_sectors(struct se_cmd *cmd)
} }
EXPORT_SYMBOL(sbc_get_write_same_sectors); EXPORT_SYMBOL(sbc_get_write_same_sectors);
static sense_reason_t
sbc_execute_write_same_unmap(struct se_cmd *cmd)
{
struct sbc_ops *ops = cmd->protocol_data;
sector_t nolb = sbc_get_write_same_sectors(cmd);
sense_reason_t ret;
if (nolb) {
ret = ops->execute_unmap(cmd, cmd->t_task_lba, nolb);
if (ret)
return ret;
}
target_complete_cmd(cmd, GOOD);
return 0;
}
static sense_reason_t static sense_reason_t
sbc_emulate_noop(struct se_cmd *cmd) sbc_emulate_noop(struct se_cmd *cmd)
{ {
@ -299,7 +317,7 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o
* translated into block discard requests within backend code. * translated into block discard requests within backend code.
*/ */
if (flags[0] & 0x08) { if (flags[0] & 0x08) {
if (!ops->execute_write_same_unmap) if (!ops->execute_unmap)
return TCM_UNSUPPORTED_SCSI_OPCODE; return TCM_UNSUPPORTED_SCSI_OPCODE;
if (!dev->dev_attrib.emulate_tpws) { if (!dev->dev_attrib.emulate_tpws) {
@ -307,7 +325,7 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o
" has emulate_tpws disabled\n"); " has emulate_tpws disabled\n");
return TCM_UNSUPPORTED_SCSI_OPCODE; return TCM_UNSUPPORTED_SCSI_OPCODE;
} }
cmd->execute_cmd = ops->execute_write_same_unmap; cmd->execute_cmd = sbc_execute_write_same_unmap;
return 0; return 0;
} }
if (!ops->execute_write_same) if (!ops->execute_write_same)
@ -381,7 +399,9 @@ out:
static sense_reason_t static sense_reason_t
sbc_execute_rw(struct se_cmd *cmd) sbc_execute_rw(struct se_cmd *cmd)
{ {
return cmd->execute_rw(cmd, cmd->t_data_sg, cmd->t_data_nents, struct sbc_ops *ops = cmd->protocol_data;
return ops->execute_rw(cmd, cmd->t_data_sg, cmd->t_data_nents,
cmd->data_direction); cmd->data_direction);
} }
@ -560,6 +580,7 @@ out:
static sense_reason_t static sense_reason_t
sbc_compare_and_write(struct se_cmd *cmd) sbc_compare_and_write(struct se_cmd *cmd)
{ {
struct sbc_ops *ops = cmd->protocol_data;
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
sense_reason_t ret; sense_reason_t ret;
int rc; int rc;
@ -579,7 +600,7 @@ sbc_compare_and_write(struct se_cmd *cmd)
*/ */
cmd->data_length = cmd->t_task_nolb * dev->dev_attrib.block_size; cmd->data_length = cmd->t_task_nolb * dev->dev_attrib.block_size;
ret = cmd->execute_rw(cmd, cmd->t_bidi_data_sg, cmd->t_bidi_data_nents, ret = ops->execute_rw(cmd, cmd->t_bidi_data_sg, cmd->t_bidi_data_nents,
DMA_FROM_DEVICE); DMA_FROM_DEVICE);
if (ret) { if (ret) {
cmd->transport_complete_callback = NULL; cmd->transport_complete_callback = NULL;
@ -738,14 +759,15 @@ static int
sbc_check_dpofua(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb) sbc_check_dpofua(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb)
{ {
if (cdb[1] & 0x10) { if (cdb[1] & 0x10) {
if (!dev->dev_attrib.emulate_dpo) { /* see explanation in spc_emulate_modesense */
if (!target_check_fua(dev)) {
pr_err("Got CDB: 0x%02x with DPO bit set, but device" pr_err("Got CDB: 0x%02x with DPO bit set, but device"
" does not advertise support for DPO\n", cdb[0]); " does not advertise support for DPO\n", cdb[0]);
return -EINVAL; return -EINVAL;
} }
} }
if (cdb[1] & 0x8) { if (cdb[1] & 0x8) {
if (!dev->dev_attrib.emulate_fua_write || !se_dev_check_wce(dev)) { if (!target_check_fua(dev)) {
pr_err("Got CDB: 0x%02x with FUA bit set, but device" pr_err("Got CDB: 0x%02x with FUA bit set, but device"
" does not advertise support for FUA write\n", " does not advertise support for FUA write\n",
cdb[0]); cdb[0]);
@ -765,12 +787,13 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
u32 sectors = 0; u32 sectors = 0;
sense_reason_t ret; sense_reason_t ret;
cmd->protocol_data = ops;
switch (cdb[0]) { switch (cdb[0]) {
case READ_6: case READ_6:
sectors = transport_get_sectors_6(cdb); sectors = transport_get_sectors_6(cdb);
cmd->t_task_lba = transport_lba_21(cdb); cmd->t_task_lba = transport_lba_21(cdb);
cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
cmd->execute_rw = ops->execute_rw;
cmd->execute_cmd = sbc_execute_rw; cmd->execute_cmd = sbc_execute_rw;
break; break;
case READ_10: case READ_10:
@ -785,7 +808,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
return ret; return ret;
cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
cmd->execute_rw = ops->execute_rw;
cmd->execute_cmd = sbc_execute_rw; cmd->execute_cmd = sbc_execute_rw;
break; break;
case READ_12: case READ_12:
@ -800,7 +822,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
return ret; return ret;
cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
cmd->execute_rw = ops->execute_rw;
cmd->execute_cmd = sbc_execute_rw; cmd->execute_cmd = sbc_execute_rw;
break; break;
case READ_16: case READ_16:
@ -815,14 +836,12 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
return ret; return ret;
cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
cmd->execute_rw = ops->execute_rw;
cmd->execute_cmd = sbc_execute_rw; cmd->execute_cmd = sbc_execute_rw;
break; break;
case WRITE_6: case WRITE_6:
sectors = transport_get_sectors_6(cdb); sectors = transport_get_sectors_6(cdb);
cmd->t_task_lba = transport_lba_21(cdb); cmd->t_task_lba = transport_lba_21(cdb);
cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
cmd->execute_rw = ops->execute_rw;
cmd->execute_cmd = sbc_execute_rw; cmd->execute_cmd = sbc_execute_rw;
break; break;
case WRITE_10: case WRITE_10:
@ -838,7 +857,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
return ret; return ret;
cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
cmd->execute_rw = ops->execute_rw;
cmd->execute_cmd = sbc_execute_rw; cmd->execute_cmd = sbc_execute_rw;
break; break;
case WRITE_12: case WRITE_12:
@ -853,7 +871,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
return ret; return ret;
cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
cmd->execute_rw = ops->execute_rw;
cmd->execute_cmd = sbc_execute_rw; cmd->execute_cmd = sbc_execute_rw;
break; break;
case WRITE_16: case WRITE_16:
@ -868,7 +885,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
return ret; return ret;
cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
cmd->execute_rw = ops->execute_rw;
cmd->execute_cmd = sbc_execute_rw; cmd->execute_cmd = sbc_execute_rw;
break; break;
case XDWRITEREAD_10: case XDWRITEREAD_10:
@ -886,7 +902,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
/* /*
* Setup BIDI XOR callback to be run after I/O completion. * Setup BIDI XOR callback to be run after I/O completion.
*/ */
cmd->execute_rw = ops->execute_rw;
cmd->execute_cmd = sbc_execute_rw; cmd->execute_cmd = sbc_execute_rw;
cmd->transport_complete_callback = &xdreadwrite_callback; cmd->transport_complete_callback = &xdreadwrite_callback;
break; break;
@ -910,7 +925,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
* Setup BIDI XOR callback to be run during after I/O * Setup BIDI XOR callback to be run during after I/O
* completion. * completion.
*/ */
cmd->execute_rw = ops->execute_rw;
cmd->execute_cmd = sbc_execute_rw; cmd->execute_cmd = sbc_execute_rw;
cmd->transport_complete_callback = &xdreadwrite_callback; cmd->transport_complete_callback = &xdreadwrite_callback;
break; break;
@ -954,7 +968,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
cmd->t_task_lba = get_unaligned_be64(&cdb[2]); cmd->t_task_lba = get_unaligned_be64(&cdb[2]);
cmd->t_task_nolb = sectors; cmd->t_task_nolb = sectors;
cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB | SCF_COMPARE_AND_WRITE; cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB | SCF_COMPARE_AND_WRITE;
cmd->execute_rw = ops->execute_rw;
cmd->execute_cmd = sbc_compare_and_write; cmd->execute_cmd = sbc_compare_and_write;
cmd->transport_complete_callback = compare_and_write_callback; cmd->transport_complete_callback = compare_and_write_callback;
break; break;
@ -1004,7 +1017,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
return TCM_UNSUPPORTED_SCSI_OPCODE; return TCM_UNSUPPORTED_SCSI_OPCODE;
} }
size = get_unaligned_be16(&cdb[7]); size = get_unaligned_be16(&cdb[7]);
cmd->execute_cmd = ops->execute_unmap; cmd->execute_cmd = sbc_execute_unmap;
break; break;
case WRITE_SAME_16: case WRITE_SAME_16:
sectors = transport_get_sectors_16(cdb); sectors = transport_get_sectors_16(cdb);
@ -1092,12 +1105,10 @@ u32 sbc_get_device_type(struct se_device *dev)
} }
EXPORT_SYMBOL(sbc_get_device_type); EXPORT_SYMBOL(sbc_get_device_type);
sense_reason_t static sense_reason_t
sbc_execute_unmap(struct se_cmd *cmd, sbc_execute_unmap(struct se_cmd *cmd)
sense_reason_t (*do_unmap_fn)(struct se_cmd *, void *,
sector_t, sector_t),
void *priv)
{ {
struct sbc_ops *ops = cmd->protocol_data;
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
unsigned char *buf, *ptr = NULL; unsigned char *buf, *ptr = NULL;
sector_t lba; sector_t lba;
@ -1161,7 +1172,7 @@ sbc_execute_unmap(struct se_cmd *cmd,
goto err; goto err;
} }
ret = do_unmap_fn(cmd, priv, lba, range); ret = ops->execute_unmap(cmd, lba, range);
if (ret) if (ret)
goto err; goto err;
@ -1175,34 +1186,56 @@ err:
target_complete_cmd(cmd, GOOD); target_complete_cmd(cmd, GOOD);
return ret; return ret;
} }
EXPORT_SYMBOL(sbc_execute_unmap);
void void
sbc_dif_generate(struct se_cmd *cmd) sbc_dif_generate(struct se_cmd *cmd)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct se_dif_v1_tuple *sdt; struct se_dif_v1_tuple *sdt;
struct scatterlist *dsg, *psg = cmd->t_prot_sg; struct scatterlist *dsg = cmd->t_data_sg, *psg;
sector_t sector = cmd->t_task_lba; sector_t sector = cmd->t_task_lba;
void *daddr, *paddr; void *daddr, *paddr;
int i, j, offset = 0; int i, j, offset = 0;
unsigned int block_size = dev->dev_attrib.block_size;
for_each_sg(cmd->t_data_sg, dsg, cmd->t_data_nents, i) { for_each_sg(cmd->t_prot_sg, psg, cmd->t_prot_nents, i) {
daddr = kmap_atomic(sg_page(dsg)) + dsg->offset;
paddr = kmap_atomic(sg_page(psg)) + psg->offset; paddr = kmap_atomic(sg_page(psg)) + psg->offset;
daddr = kmap_atomic(sg_page(dsg)) + dsg->offset;
for (j = 0; j < dsg->length; j += dev->dev_attrib.block_size) { for (j = 0; j < psg->length;
j += sizeof(struct se_dif_v1_tuple)) {
__u16 crc;
unsigned int avail;
if (offset >= psg->length) { if (offset >= dsg->length) {
kunmap_atomic(paddr); offset -= dsg->length;
psg = sg_next(psg); kunmap_atomic(daddr - dsg->offset);
paddr = kmap_atomic(sg_page(psg)) + psg->offset; dsg = sg_next(dsg);
offset = 0; if (!dsg) {
kunmap_atomic(paddr - psg->offset);
return;
}
daddr = kmap_atomic(sg_page(dsg)) + dsg->offset;
} }
sdt = paddr + offset; sdt = paddr + j;
sdt->guard_tag = cpu_to_be16(crc_t10dif(daddr + j, avail = min(block_size, dsg->length - offset);
dev->dev_attrib.block_size)); crc = crc_t10dif(daddr + offset, avail);
if (avail < block_size) {
kunmap_atomic(daddr - dsg->offset);
dsg = sg_next(dsg);
if (!dsg) {
kunmap_atomic(paddr - psg->offset);
return;
}
daddr = kmap_atomic(sg_page(dsg)) + dsg->offset;
offset = block_size - avail;
crc = crc_t10dif_update(crc, daddr, offset);
} else {
offset += block_size;
}
sdt->guard_tag = cpu_to_be16(crc);
if (cmd->prot_type == TARGET_DIF_TYPE1_PROT) if (cmd->prot_type == TARGET_DIF_TYPE1_PROT)
sdt->ref_tag = cpu_to_be32(sector & 0xffffffff); sdt->ref_tag = cpu_to_be32(sector & 0xffffffff);
sdt->app_tag = 0; sdt->app_tag = 0;
@ -1215,26 +1248,23 @@ sbc_dif_generate(struct se_cmd *cmd)
be32_to_cpu(sdt->ref_tag)); be32_to_cpu(sdt->ref_tag));
sector++; sector++;
offset += sizeof(struct se_dif_v1_tuple);
} }
kunmap_atomic(paddr); kunmap_atomic(daddr - dsg->offset);
kunmap_atomic(daddr); kunmap_atomic(paddr - psg->offset);
} }
} }
static sense_reason_t static sense_reason_t
sbc_dif_v1_verify(struct se_cmd *cmd, struct se_dif_v1_tuple *sdt, sbc_dif_v1_verify(struct se_cmd *cmd, struct se_dif_v1_tuple *sdt,
const void *p, sector_t sector, unsigned int ei_lba) __u16 crc, sector_t sector, unsigned int ei_lba)
{ {
struct se_device *dev = cmd->se_dev;
int block_size = dev->dev_attrib.block_size;
__be16 csum; __be16 csum;
if (!(cmd->prot_checks & TARGET_DIF_CHECK_GUARD)) if (!(cmd->prot_checks & TARGET_DIF_CHECK_GUARD))
goto check_ref; goto check_ref;
csum = cpu_to_be16(crc_t10dif(p, block_size)); csum = cpu_to_be16(crc);
if (sdt->guard_tag != csum) { if (sdt->guard_tag != csum) {
pr_err("DIFv1 checksum failed on sector %llu guard tag 0x%04x" pr_err("DIFv1 checksum failed on sector %llu guard tag 0x%04x"
@ -1266,9 +1296,8 @@ check_ref:
return 0; return 0;
} }
static void void sbc_dif_copy_prot(struct se_cmd *cmd, unsigned int sectors, bool read,
sbc_dif_copy_prot(struct se_cmd *cmd, unsigned int sectors, bool read, struct scatterlist *sg, int sg_off)
struct scatterlist *sg, int sg_off)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct scatterlist *psg; struct scatterlist *psg;
@ -1300,100 +1329,54 @@ sbc_dif_copy_prot(struct se_cmd *cmd, unsigned int sectors, bool read,
copied += len; copied += len;
psg_len -= len; psg_len -= len;
kunmap_atomic(addr - sg->offset - offset);
if (offset >= sg->length) { if (offset >= sg->length) {
sg = sg_next(sg); sg = sg_next(sg);
offset = 0; offset = 0;
} }
kunmap_atomic(addr);
} }
kunmap_atomic(paddr); kunmap_atomic(paddr - psg->offset);
} }
} }
EXPORT_SYMBOL(sbc_dif_copy_prot);
sense_reason_t sense_reason_t
sbc_dif_verify_write(struct se_cmd *cmd, sector_t start, unsigned int sectors, sbc_dif_verify(struct se_cmd *cmd, sector_t start, unsigned int sectors,
unsigned int ei_lba, struct scatterlist *sg, int sg_off) unsigned int ei_lba, struct scatterlist *psg, int psg_off)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct se_dif_v1_tuple *sdt; struct se_dif_v1_tuple *sdt;
struct scatterlist *dsg, *psg = cmd->t_prot_sg; struct scatterlist *dsg = cmd->t_data_sg;
sector_t sector = start; sector_t sector = start;
void *daddr, *paddr; void *daddr, *paddr;
int i, j, offset = 0; int i;
sense_reason_t rc; sense_reason_t rc;
int dsg_off = 0;
unsigned int block_size = dev->dev_attrib.block_size;
for_each_sg(cmd->t_data_sg, dsg, cmd->t_data_nents, i) { for (; psg && sector < start + sectors; psg = sg_next(psg)) {
daddr = kmap_atomic(sg_page(dsg)) + dsg->offset;
paddr = kmap_atomic(sg_page(psg)) + psg->offset; paddr = kmap_atomic(sg_page(psg)) + psg->offset;
for (j = 0; j < dsg->length; j += dev->dev_attrib.block_size) {
if (offset >= psg->length) {
kunmap_atomic(paddr);
psg = sg_next(psg);
paddr = kmap_atomic(sg_page(psg)) + psg->offset;
offset = 0;
}
sdt = paddr + offset;
pr_debug("DIF WRITE sector: %llu guard_tag: 0x%04x"
" app_tag: 0x%04x ref_tag: %u\n",
(unsigned long long)sector, sdt->guard_tag,
sdt->app_tag, be32_to_cpu(sdt->ref_tag));
rc = sbc_dif_v1_verify(cmd, sdt, daddr + j, sector,
ei_lba);
if (rc) {
kunmap_atomic(paddr);
kunmap_atomic(daddr);
cmd->bad_sector = sector;
return rc;
}
sector++;
ei_lba++;
offset += sizeof(struct se_dif_v1_tuple);
}
kunmap_atomic(paddr);
kunmap_atomic(daddr);
}
if (!sg)
return 0;
sbc_dif_copy_prot(cmd, sectors, false, sg, sg_off);
return 0;
}
EXPORT_SYMBOL(sbc_dif_verify_write);
static sense_reason_t
__sbc_dif_verify_read(struct se_cmd *cmd, sector_t start, unsigned int sectors,
unsigned int ei_lba, struct scatterlist *sg, int sg_off)
{
struct se_device *dev = cmd->se_dev;
struct se_dif_v1_tuple *sdt;
struct scatterlist *dsg, *psg = sg;
sector_t sector = start;
void *daddr, *paddr;
int i, j, offset = sg_off;
sense_reason_t rc;
for_each_sg(cmd->t_data_sg, dsg, cmd->t_data_nents, i) {
daddr = kmap_atomic(sg_page(dsg)) + dsg->offset; daddr = kmap_atomic(sg_page(dsg)) + dsg->offset;
paddr = kmap_atomic(sg_page(psg)) + sg->offset;
for (j = 0; j < dsg->length; j += dev->dev_attrib.block_size) { for (i = psg_off; i < psg->length &&
sector < start + sectors;
i += sizeof(struct se_dif_v1_tuple)) {
__u16 crc;
unsigned int avail;
if (offset >= psg->length) { if (dsg_off >= dsg->length) {
kunmap_atomic(paddr); dsg_off -= dsg->length;
psg = sg_next(psg); kunmap_atomic(daddr - dsg->offset);
paddr = kmap_atomic(sg_page(psg)) + psg->offset; dsg = sg_next(dsg);
offset = 0; if (!dsg) {
kunmap_atomic(paddr - psg->offset);
return 0;
}
daddr = kmap_atomic(sg_page(dsg)) + dsg->offset;
} }
sdt = paddr + offset; sdt = paddr + i;
pr_debug("DIF READ sector: %llu guard_tag: 0x%04x" pr_debug("DIF READ sector: %llu guard_tag: 0x%04x"
" app_tag: 0x%04x ref_tag: %u\n", " app_tag: 0x%04x ref_tag: %u\n",
@ -1401,53 +1384,43 @@ __sbc_dif_verify_read(struct se_cmd *cmd, sector_t start, unsigned int sectors,
sdt->app_tag, be32_to_cpu(sdt->ref_tag)); sdt->app_tag, be32_to_cpu(sdt->ref_tag));
if (sdt->app_tag == cpu_to_be16(0xffff)) { if (sdt->app_tag == cpu_to_be16(0xffff)) {
sector++; dsg_off += block_size;
offset += sizeof(struct se_dif_v1_tuple); goto next;
continue;
} }
rc = sbc_dif_v1_verify(cmd, sdt, daddr + j, sector, avail = min(block_size, dsg->length - dsg_off);
ei_lba); crc = crc_t10dif(daddr + dsg_off, avail);
if (avail < block_size) {
kunmap_atomic(daddr - dsg->offset);
dsg = sg_next(dsg);
if (!dsg) {
kunmap_atomic(paddr - psg->offset);
return 0;
}
daddr = kmap_atomic(sg_page(dsg)) + dsg->offset;
dsg_off = block_size - avail;
crc = crc_t10dif_update(crc, daddr, dsg_off);
} else {
dsg_off += block_size;
}
rc = sbc_dif_v1_verify(cmd, sdt, crc, sector, ei_lba);
if (rc) { if (rc) {
kunmap_atomic(paddr); kunmap_atomic(daddr - dsg->offset);
kunmap_atomic(daddr); kunmap_atomic(paddr - psg->offset);
cmd->bad_sector = sector; cmd->bad_sector = sector;
return rc; return rc;
} }
next:
sector++; sector++;
ei_lba++; ei_lba++;
offset += sizeof(struct se_dif_v1_tuple);
} }
kunmap_atomic(paddr); psg_off = 0;
kunmap_atomic(daddr); kunmap_atomic(daddr - dsg->offset);
kunmap_atomic(paddr - psg->offset);
} }
return 0; return 0;
} }
EXPORT_SYMBOL(sbc_dif_verify);
sense_reason_t
sbc_dif_read_strip(struct se_cmd *cmd)
{
struct se_device *dev = cmd->se_dev;
u32 sectors = cmd->prot_length / dev->prot_length;
return __sbc_dif_verify_read(cmd, cmd->t_task_lba, sectors, 0,
cmd->t_prot_sg, 0);
}
sense_reason_t
sbc_dif_verify_read(struct se_cmd *cmd, sector_t start, unsigned int sectors,
unsigned int ei_lba, struct scatterlist *sg, int sg_off)
{
sense_reason_t rc;
rc = __sbc_dif_verify_read(cmd, start, sectors, ei_lba, sg, sg_off);
if (rc)
return rc;
sbc_dif_copy_prot(cmd, sectors, true, sg, sg_off);
return 0;
}
EXPORT_SYMBOL(sbc_dif_verify_read);

View File

@ -38,10 +38,9 @@
#include "target_core_ua.h" #include "target_core_ua.h"
#include "target_core_xcopy.h" #include "target_core_xcopy.h"
static void spc_fill_alua_data(struct se_port *port, unsigned char *buf) static void spc_fill_alua_data(struct se_lun *lun, unsigned char *buf)
{ {
struct t10_alua_tg_pt_gp *tg_pt_gp; struct t10_alua_tg_pt_gp *tg_pt_gp;
struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
/* /*
* Set SCCS for MAINTENANCE_IN + REPORT_TARGET_PORT_GROUPS. * Set SCCS for MAINTENANCE_IN + REPORT_TARGET_PORT_GROUPS.
@ -54,17 +53,11 @@ static void spc_fill_alua_data(struct se_port *port, unsigned char *buf)
* *
* See spc4r17 section 6.4.2 Table 135 * See spc4r17 section 6.4.2 Table 135
*/ */
if (!port) spin_lock(&lun->lun_tg_pt_gp_lock);
return; tg_pt_gp = lun->lun_tg_pt_gp;
tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
if (!tg_pt_gp_mem)
return;
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) if (tg_pt_gp)
buf[5] |= tg_pt_gp->tg_pt_gp_alua_access_type; buf[5] |= tg_pt_gp->tg_pt_gp_alua_access_type;
spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); spin_unlock(&lun->lun_tg_pt_gp_lock);
} }
sense_reason_t sense_reason_t
@ -95,7 +88,7 @@ spc_emulate_inquiry_std(struct se_cmd *cmd, unsigned char *buf)
/* /*
* Enable SCCS and TPGS fields for Emulated ALUA * Enable SCCS and TPGS fields for Emulated ALUA
*/ */
spc_fill_alua_data(lun->lun_sep, buf); spc_fill_alua_data(lun, buf);
/* /*
* Set Third-Party Copy (3PC) bit to indicate support for EXTENDED_COPY * Set Third-Party Copy (3PC) bit to indicate support for EXTENDED_COPY
@ -182,11 +175,9 @@ spc_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct se_lun *lun = cmd->se_lun; struct se_lun *lun = cmd->se_lun;
struct se_port *port = NULL;
struct se_portal_group *tpg = NULL; struct se_portal_group *tpg = NULL;
struct t10_alua_lu_gp_member *lu_gp_mem; struct t10_alua_lu_gp_member *lu_gp_mem;
struct t10_alua_tg_pt_gp *tg_pt_gp; struct t10_alua_tg_pt_gp *tg_pt_gp;
struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
unsigned char *prod = &dev->t10_wwn.model[0]; unsigned char *prod = &dev->t10_wwn.model[0];
u32 prod_len; u32 prod_len;
u32 unit_serial_len, off = 0; u32 unit_serial_len, off = 0;
@ -268,18 +259,15 @@ check_t10_vend_desc:
/* Header size for Designation descriptor */ /* Header size for Designation descriptor */
len += (id_len + 4); len += (id_len + 4);
off += (id_len + 4); off += (id_len + 4);
/*
* struct se_port is only set for INQUIRY VPD=1 through $FABRIC_MOD if (1) {
*/
port = lun->lun_sep;
if (port) {
struct t10_alua_lu_gp *lu_gp; struct t10_alua_lu_gp *lu_gp;
u32 padding, scsi_name_len, scsi_target_len; u32 padding, scsi_name_len, scsi_target_len;
u16 lu_gp_id = 0; u16 lu_gp_id = 0;
u16 tg_pt_gp_id = 0; u16 tg_pt_gp_id = 0;
u16 tpgt; u16 tpgt;
tpg = port->sep_tpg; tpg = lun->lun_tpg;
/* /*
* Relative target port identifer, see spc4r17 * Relative target port identifer, see spc4r17
* section 7.7.3.7 * section 7.7.3.7
@ -287,8 +275,7 @@ check_t10_vend_desc:
* Get the PROTOCOL IDENTIFIER as defined by spc4r17 * Get the PROTOCOL IDENTIFIER as defined by spc4r17
* section 7.5.1 Table 362 * section 7.5.1 Table 362
*/ */
buf[off] = buf[off] = tpg->proto_id << 4;
(tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4);
buf[off++] |= 0x1; /* CODE SET == Binary */ buf[off++] |= 0x1; /* CODE SET == Binary */
buf[off] = 0x80; /* Set PIV=1 */ buf[off] = 0x80; /* Set PIV=1 */
/* Set ASSOCIATION == target port: 01b */ /* Set ASSOCIATION == target port: 01b */
@ -300,8 +287,8 @@ check_t10_vend_desc:
/* Skip over Obsolete field in RTPI payload /* Skip over Obsolete field in RTPI payload
* in Table 472 */ * in Table 472 */
off += 2; off += 2;
buf[off++] = ((port->sep_rtpi >> 8) & 0xff); buf[off++] = ((lun->lun_rtpi >> 8) & 0xff);
buf[off++] = (port->sep_rtpi & 0xff); buf[off++] = (lun->lun_rtpi & 0xff);
len += 8; /* Header size + Designation descriptor */ len += 8; /* Header size + Designation descriptor */
/* /*
* Target port group identifier, see spc4r17 * Target port group identifier, see spc4r17
@ -310,21 +297,16 @@ check_t10_vend_desc:
* Get the PROTOCOL IDENTIFIER as defined by spc4r17 * Get the PROTOCOL IDENTIFIER as defined by spc4r17
* section 7.5.1 Table 362 * section 7.5.1 Table 362
*/ */
tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; spin_lock(&lun->lun_tg_pt_gp_lock);
if (!tg_pt_gp_mem) tg_pt_gp = lun->lun_tg_pt_gp;
goto check_lu_gp;
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) { if (!tg_pt_gp) {
spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); spin_unlock(&lun->lun_tg_pt_gp_lock);
goto check_lu_gp; goto check_lu_gp;
} }
tg_pt_gp_id = tg_pt_gp->tg_pt_gp_id; tg_pt_gp_id = tg_pt_gp->tg_pt_gp_id;
spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); spin_unlock(&lun->lun_tg_pt_gp_lock);
buf[off] = buf[off] = tpg->proto_id << 4;
(tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4);
buf[off++] |= 0x1; /* CODE SET == Binary */ buf[off++] |= 0x1; /* CODE SET == Binary */
buf[off] = 0x80; /* Set PIV=1 */ buf[off] = 0x80; /* Set PIV=1 */
/* Set ASSOCIATION == target port: 01b */ /* Set ASSOCIATION == target port: 01b */
@ -372,8 +354,7 @@ check_lu_gp:
* section 7.5.1 Table 362 * section 7.5.1 Table 362
*/ */
check_scsi_name: check_scsi_name:
buf[off] = buf[off] = tpg->proto_id << 4;
(tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4);
buf[off++] |= 0x3; /* CODE SET == UTF-8 */ buf[off++] |= 0x3; /* CODE SET == UTF-8 */
buf[off] = 0x80; /* Set PIV=1 */ buf[off] = 0x80; /* Set PIV=1 */
/* Set ASSOCIATION == target port: 01b */ /* Set ASSOCIATION == target port: 01b */
@ -413,8 +394,7 @@ check_scsi_name:
/* /*
* Target device designator * Target device designator
*/ */
buf[off] = buf[off] = tpg->proto_id << 4;
(tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4);
buf[off++] |= 0x3; /* CODE SET == UTF-8 */ buf[off++] |= 0x3; /* CODE SET == UTF-8 */
buf[off] = 0x80; /* Set PIV=1 */ buf[off] = 0x80; /* Set PIV=1 */
/* Set ASSOCIATION == target device: 10b */ /* Set ASSOCIATION == target device: 10b */
@ -482,7 +462,7 @@ spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf)
buf[5] = 0x07; buf[5] = 0x07;
/* If WriteCache emulation is enabled, set V_SUP */ /* If WriteCache emulation is enabled, set V_SUP */
if (se_dev_check_wce(dev)) if (target_check_wce(dev))
buf[6] = 0x01; buf[6] = 0x01;
/* If an LBA map is present set R_SUP */ /* If an LBA map is present set R_SUP */
spin_lock(&cmd->se_dev->t10_alua.lba_map_lock); spin_lock(&cmd->se_dev->t10_alua.lba_map_lock);
@ -699,7 +679,7 @@ static sense_reason_t
spc_emulate_inquiry(struct se_cmd *cmd) spc_emulate_inquiry(struct se_cmd *cmd)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct se_portal_group *tpg = cmd->se_lun->lun_sep->sep_tpg; struct se_portal_group *tpg = cmd->se_lun->lun_tpg;
unsigned char *rbuf; unsigned char *rbuf;
unsigned char *cdb = cmd->t_task_cdb; unsigned char *cdb = cmd->t_task_cdb;
unsigned char *buf; unsigned char *buf;
@ -713,7 +693,7 @@ spc_emulate_inquiry(struct se_cmd *cmd)
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
} }
if (dev == tpg->tpg_virt_lun0.lun_se_dev) if (dev == rcu_access_pointer(tpg->tpg_virt_lun0->lun_se_dev))
buf[0] = 0x3f; /* Not connected */ buf[0] = 0x3f; /* Not connected */
else else
buf[0] = dev->transport->get_device_type(dev); buf[0] = dev->transport->get_device_type(dev);
@ -889,7 +869,7 @@ static int spc_modesense_caching(struct se_cmd *cmd, u8 pc, u8 *p)
if (pc == 1) if (pc == 1)
goto out; goto out;
if (se_dev_check_wce(dev)) if (target_check_wce(dev))
p[2] = 0x04; /* Write Cache Enable */ p[2] = 0x04; /* Write Cache Enable */
p[12] = 0x20; /* Disabled Read Ahead */ p[12] = 0x20; /* Disabled Read Ahead */
@ -986,6 +966,7 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd)
int length = 0; int length = 0;
int ret; int ret;
int i; int i;
bool read_only = target_lun_is_rdonly(cmd);;
memset(buf, 0, SE_MODE_PAGE_BUF); memset(buf, 0, SE_MODE_PAGE_BUF);
@ -996,13 +977,15 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd)
length = ten ? 3 : 2; length = ten ? 3 : 2;
/* DEVICE-SPECIFIC PARAMETER */ /* DEVICE-SPECIFIC PARAMETER */
if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) || if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) || read_only)
(cmd->se_deve &&
(cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)))
spc_modesense_write_protect(&buf[length], type); spc_modesense_write_protect(&buf[length], type);
if ((se_dev_check_wce(dev)) && /*
(dev->dev_attrib.emulate_fua_write > 0)) * SBC only allows us to enable FUA and DPO together. Fortunately
* DPO is explicitly specified as a hint, so a noop is a perfectly
* valid implementation.
*/
if (target_check_fua(dev))
spc_modesense_dpofua(&buf[length], type); spc_modesense_dpofua(&buf[length], type);
++length; ++length;
@ -1212,8 +1195,9 @@ sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd)
{ {
struct se_dev_entry *deve; struct se_dev_entry *deve;
struct se_session *sess = cmd->se_sess; struct se_session *sess = cmd->se_sess;
struct se_node_acl *nacl;
unsigned char *buf; unsigned char *buf;
u32 lun_count = 0, offset = 8, i; u32 lun_count = 0, offset = 8;
if (cmd->data_length < 16) { if (cmd->data_length < 16) {
pr_warn("REPORT LUNS allocation length %u too small\n", pr_warn("REPORT LUNS allocation length %u too small\n",
@ -1235,12 +1219,10 @@ sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd)
lun_count = 1; lun_count = 1;
goto done; goto done;
} }
nacl = sess->se_node_acl;
spin_lock_irq(&sess->se_node_acl->device_list_lock); rcu_read_lock();
for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { hlist_for_each_entry_rcu(deve, &nacl->lun_entry_hlist, link) {
deve = sess->se_node_acl->device_list[i];
if (!(deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS))
continue;
/* /*
* We determine the correct LUN LIST LENGTH even once we * We determine the correct LUN LIST LENGTH even once we
* have reached the initial allocation length. * have reached the initial allocation length.
@ -1253,7 +1235,7 @@ sense_reason_t spc_emulate_report_luns(struct se_cmd *cmd)
int_to_scsilun(deve->mapped_lun, (struct scsi_lun *)&buf[offset]); int_to_scsilun(deve->mapped_lun, (struct scsi_lun *)&buf[offset]);
offset += 8; offset += 8;
} }
spin_unlock_irq(&sess->se_node_acl->device_list_lock); rcu_read_unlock();
/* /*
* See SPC3 r07, page 159. * See SPC3 r07, page 159.

View File

@ -37,7 +37,6 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_backend.h> #include <target/target_core_backend.h>
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
#include <target/configfs_macros.h> #include <target/configfs_macros.h>
#include "target_core_internal.h" #include "target_core_internal.h"
@ -104,7 +103,7 @@ static ssize_t target_stat_scsi_dev_show_attr_ports(
struct se_device *dev = struct se_device *dev =
container_of(sgrps, struct se_device, dev_stat_grps); container_of(sgrps, struct se_device, dev_stat_grps);
return snprintf(page, PAGE_SIZE, "%u\n", dev->dev_port_count); return snprintf(page, PAGE_SIZE, "%u\n", dev->export_count);
} }
DEV_STAT_SCSI_DEV_ATTR_RO(ports); DEV_STAT_SCSI_DEV_ATTR_RO(ports);
@ -540,20 +539,14 @@ static ssize_t target_stat_scsi_port_show_attr_inst(
struct se_port_stat_grps *pgrps, char *page) struct se_port_stat_grps *pgrps, char *page)
{ {
struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps); struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
struct se_port *sep; struct se_device *dev;
struct se_device *dev = lun->lun_se_dev; ssize_t ret = -ENODEV;
struct se_hba *hba;
ssize_t ret;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
sep = lun->lun_sep; dev = rcu_dereference(lun->lun_se_dev);
if (!sep) { if (dev)
spin_unlock(&lun->lun_sep_lock); ret = snprintf(page, PAGE_SIZE, "%u\n", dev->hba_index);
return -ENODEV; rcu_read_unlock();
}
hba = dev->se_hba;
ret = snprintf(page, PAGE_SIZE, "%u\n", hba->hba_index);
spin_unlock(&lun->lun_sep_lock);
return ret; return ret;
} }
DEV_STAT_SCSI_PORT_ATTR_RO(inst); DEV_STAT_SCSI_PORT_ATTR_RO(inst);
@ -562,18 +555,14 @@ static ssize_t target_stat_scsi_port_show_attr_dev(
struct se_port_stat_grps *pgrps, char *page) struct se_port_stat_grps *pgrps, char *page)
{ {
struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps); struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
struct se_port *sep; struct se_device *dev;
struct se_device *dev = lun->lun_se_dev; ssize_t ret = -ENODEV;
ssize_t ret;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
sep = lun->lun_sep; dev = rcu_dereference(lun->lun_se_dev);
if (!sep) { if (dev)
spin_unlock(&lun->lun_sep_lock); ret = snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index);
return -ENODEV; rcu_read_unlock();
}
ret = snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index);
spin_unlock(&lun->lun_sep_lock);
return ret; return ret;
} }
DEV_STAT_SCSI_PORT_ATTR_RO(dev); DEV_STAT_SCSI_PORT_ATTR_RO(dev);
@ -582,17 +571,14 @@ static ssize_t target_stat_scsi_port_show_attr_indx(
struct se_port_stat_grps *pgrps, char *page) struct se_port_stat_grps *pgrps, char *page)
{ {
struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps); struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
struct se_port *sep; struct se_device *dev;
ssize_t ret; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
sep = lun->lun_sep; dev = rcu_dereference(lun->lun_se_dev);
if (!sep) { if (dev)
spin_unlock(&lun->lun_sep_lock); ret = snprintf(page, PAGE_SIZE, "%u\n", lun->lun_rtpi);
return -ENODEV; rcu_read_unlock();
}
ret = snprintf(page, PAGE_SIZE, "%u\n", sep->sep_index);
spin_unlock(&lun->lun_sep_lock);
return ret; return ret;
} }
DEV_STAT_SCSI_PORT_ATTR_RO(indx); DEV_STAT_SCSI_PORT_ATTR_RO(indx);
@ -601,21 +587,14 @@ static ssize_t target_stat_scsi_port_show_attr_role(
struct se_port_stat_grps *pgrps, char *page) struct se_port_stat_grps *pgrps, char *page)
{ {
struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps); struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
struct se_device *dev = lun->lun_se_dev; struct se_device *dev;
struct se_port *sep; ssize_t ret = -ENODEV;
ssize_t ret;
if (!dev) rcu_read_lock();
return -ENODEV; dev = rcu_dereference(lun->lun_se_dev);
if (dev)
spin_lock(&lun->lun_sep_lock); ret = snprintf(page, PAGE_SIZE, "%s%u\n", "Device", dev->dev_index);
sep = lun->lun_sep; rcu_read_unlock();
if (!sep) {
spin_unlock(&lun->lun_sep_lock);
return -ENODEV;
}
ret = snprintf(page, PAGE_SIZE, "%s%u\n", "Device", dev->dev_index);
spin_unlock(&lun->lun_sep_lock);
return ret; return ret;
} }
DEV_STAT_SCSI_PORT_ATTR_RO(role); DEV_STAT_SCSI_PORT_ATTR_RO(role);
@ -624,18 +603,16 @@ static ssize_t target_stat_scsi_port_show_attr_busy_count(
struct se_port_stat_grps *pgrps, char *page) struct se_port_stat_grps *pgrps, char *page)
{ {
struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps); struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
struct se_port *sep; struct se_device *dev;
ssize_t ret; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
sep = lun->lun_sep; dev = rcu_dereference(lun->lun_se_dev);
if (!sep) { if (dev) {
spin_unlock(&lun->lun_sep_lock); /* FIXME: scsiPortBusyStatuses */
return -ENODEV; ret = snprintf(page, PAGE_SIZE, "%u\n", 0);
} }
/* FIXME: scsiPortBusyStatuses */ rcu_read_unlock();
ret = snprintf(page, PAGE_SIZE, "%u\n", 0);
spin_unlock(&lun->lun_sep_lock);
return ret; return ret;
} }
DEV_STAT_SCSI_PORT_ATTR_RO(busy_count); DEV_STAT_SCSI_PORT_ATTR_RO(busy_count);
@ -683,20 +660,14 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_inst(
struct se_port_stat_grps *pgrps, char *page) struct se_port_stat_grps *pgrps, char *page)
{ {
struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps); struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
struct se_device *dev = lun->lun_se_dev; struct se_device *dev;
struct se_port *sep; ssize_t ret = -ENODEV;
struct se_hba *hba;
ssize_t ret;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
sep = lun->lun_sep; dev = rcu_dereference(lun->lun_se_dev);
if (!sep) { if (dev)
spin_unlock(&lun->lun_sep_lock); ret = snprintf(page, PAGE_SIZE, "%u\n", dev->hba_index);
return -ENODEV; rcu_read_unlock();
}
hba = dev->se_hba;
ret = snprintf(page, PAGE_SIZE, "%u\n", hba->hba_index);
spin_unlock(&lun->lun_sep_lock);
return ret; return ret;
} }
DEV_STAT_SCSI_TGT_PORT_ATTR_RO(inst); DEV_STAT_SCSI_TGT_PORT_ATTR_RO(inst);
@ -705,18 +676,14 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_dev(
struct se_port_stat_grps *pgrps, char *page) struct se_port_stat_grps *pgrps, char *page)
{ {
struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps); struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
struct se_device *dev = lun->lun_se_dev; struct se_device *dev;
struct se_port *sep; ssize_t ret = -ENODEV;
ssize_t ret;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
sep = lun->lun_sep; dev = rcu_dereference(lun->lun_se_dev);
if (!sep) { if (dev)
spin_unlock(&lun->lun_sep_lock); ret = snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index);
return -ENODEV; rcu_read_unlock();
}
ret = snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index);
spin_unlock(&lun->lun_sep_lock);
return ret; return ret;
} }
DEV_STAT_SCSI_TGT_PORT_ATTR_RO(dev); DEV_STAT_SCSI_TGT_PORT_ATTR_RO(dev);
@ -725,17 +692,14 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_indx(
struct se_port_stat_grps *pgrps, char *page) struct se_port_stat_grps *pgrps, char *page)
{ {
struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps); struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
struct se_port *sep; struct se_device *dev;
ssize_t ret; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
sep = lun->lun_sep; dev = rcu_dereference(lun->lun_se_dev);
if (!sep) { if (dev)
spin_unlock(&lun->lun_sep_lock); ret = snprintf(page, PAGE_SIZE, "%u\n", lun->lun_rtpi);
return -ENODEV; rcu_read_unlock();
}
ret = snprintf(page, PAGE_SIZE, "%u\n", sep->sep_index);
spin_unlock(&lun->lun_sep_lock);
return ret; return ret;
} }
DEV_STAT_SCSI_TGT_PORT_ATTR_RO(indx); DEV_STAT_SCSI_TGT_PORT_ATTR_RO(indx);
@ -744,21 +708,17 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_name(
struct se_port_stat_grps *pgrps, char *page) struct se_port_stat_grps *pgrps, char *page)
{ {
struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps); struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
struct se_port *sep; struct se_portal_group *tpg = lun->lun_tpg;
struct se_portal_group *tpg; struct se_device *dev;
ssize_t ret; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
sep = lun->lun_sep; dev = rcu_dereference(lun->lun_se_dev);
if (!sep) { if (dev)
spin_unlock(&lun->lun_sep_lock); ret = snprintf(page, PAGE_SIZE, "%sPort#%u\n",
return -ENODEV; tpg->se_tpg_tfo->get_fabric_name(),
} lun->lun_rtpi);
tpg = sep->sep_tpg; rcu_read_unlock();
ret = snprintf(page, PAGE_SIZE, "%sPort#%u\n",
tpg->se_tpg_tfo->get_fabric_name(), sep->sep_index);
spin_unlock(&lun->lun_sep_lock);
return ret; return ret;
} }
DEV_STAT_SCSI_TGT_PORT_ATTR_RO(name); DEV_STAT_SCSI_TGT_PORT_ATTR_RO(name);
@ -767,22 +727,17 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_port_index(
struct se_port_stat_grps *pgrps, char *page) struct se_port_stat_grps *pgrps, char *page)
{ {
struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps); struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
struct se_port *sep; struct se_portal_group *tpg = lun->lun_tpg;
struct se_portal_group *tpg; struct se_device *dev;
ssize_t ret; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
sep = lun->lun_sep; dev = rcu_dereference(lun->lun_se_dev);
if (!sep) { if (dev)
spin_unlock(&lun->lun_sep_lock); ret = snprintf(page, PAGE_SIZE, "%s%s%d\n",
return -ENODEV; tpg->se_tpg_tfo->tpg_get_wwn(tpg), "+t+",
} tpg->se_tpg_tfo->tpg_get_tag(tpg));
tpg = sep->sep_tpg; rcu_read_unlock();
ret = snprintf(page, PAGE_SIZE, "%s%s%d\n",
tpg->se_tpg_tfo->tpg_get_wwn(tpg), "+t+",
tpg->se_tpg_tfo->tpg_get_tag(tpg));
spin_unlock(&lun->lun_sep_lock);
return ret; return ret;
} }
DEV_STAT_SCSI_TGT_PORT_ATTR_RO(port_index); DEV_STAT_SCSI_TGT_PORT_ATTR_RO(port_index);
@ -791,18 +746,15 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_in_cmds(
struct se_port_stat_grps *pgrps, char *page) struct se_port_stat_grps *pgrps, char *page)
{ {
struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps); struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
struct se_port *sep; struct se_device *dev;
ssize_t ret; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
sep = lun->lun_sep; dev = rcu_dereference(lun->lun_se_dev);
if (!sep) { if (dev)
spin_unlock(&lun->lun_sep_lock); ret = snprintf(page, PAGE_SIZE, "%lu\n",
return -ENODEV; atomic_long_read(&lun->lun_stats.cmd_pdus));
} rcu_read_unlock();
ret = snprintf(page, PAGE_SIZE, "%llu\n", sep->sep_stats.cmd_pdus);
spin_unlock(&lun->lun_sep_lock);
return ret; return ret;
} }
DEV_STAT_SCSI_TGT_PORT_ATTR_RO(in_cmds); DEV_STAT_SCSI_TGT_PORT_ATTR_RO(in_cmds);
@ -811,19 +763,15 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_write_mbytes(
struct se_port_stat_grps *pgrps, char *page) struct se_port_stat_grps *pgrps, char *page)
{ {
struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps); struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
struct se_port *sep; struct se_device *dev;
ssize_t ret; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
sep = lun->lun_sep; dev = rcu_dereference(lun->lun_se_dev);
if (!sep) { if (dev)
spin_unlock(&lun->lun_sep_lock); ret = snprintf(page, PAGE_SIZE, "%u\n",
return -ENODEV; (u32)(atomic_long_read(&lun->lun_stats.rx_data_octets) >> 20));
} rcu_read_unlock();
ret = snprintf(page, PAGE_SIZE, "%u\n",
(u32)(sep->sep_stats.rx_data_octets >> 20));
spin_unlock(&lun->lun_sep_lock);
return ret; return ret;
} }
DEV_STAT_SCSI_TGT_PORT_ATTR_RO(write_mbytes); DEV_STAT_SCSI_TGT_PORT_ATTR_RO(write_mbytes);
@ -832,19 +780,15 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_read_mbytes(
struct se_port_stat_grps *pgrps, char *page) struct se_port_stat_grps *pgrps, char *page)
{ {
struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps); struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
struct se_port *sep; struct se_device *dev;
ssize_t ret; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
sep = lun->lun_sep; dev = rcu_dereference(lun->lun_se_dev);
if (!sep) { if (dev)
spin_unlock(&lun->lun_sep_lock); ret = snprintf(page, PAGE_SIZE, "%u\n",
return -ENODEV; (u32)(atomic_long_read(&lun->lun_stats.tx_data_octets) >> 20));
} rcu_read_unlock();
ret = snprintf(page, PAGE_SIZE, "%u\n",
(u32)(sep->sep_stats.tx_data_octets >> 20));
spin_unlock(&lun->lun_sep_lock);
return ret; return ret;
} }
DEV_STAT_SCSI_TGT_PORT_ATTR_RO(read_mbytes); DEV_STAT_SCSI_TGT_PORT_ATTR_RO(read_mbytes);
@ -853,19 +797,16 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_hs_in_cmds(
struct se_port_stat_grps *pgrps, char *page) struct se_port_stat_grps *pgrps, char *page)
{ {
struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps); struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
struct se_port *sep; struct se_device *dev;
ssize_t ret; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
sep = lun->lun_sep; dev = rcu_dereference(lun->lun_se_dev);
if (!sep) { if (dev) {
spin_unlock(&lun->lun_sep_lock); /* FIXME: scsiTgtPortHsInCommands */
return -ENODEV; ret = snprintf(page, PAGE_SIZE, "%u\n", 0);
} }
rcu_read_unlock();
/* FIXME: scsiTgtPortHsInCommands */
ret = snprintf(page, PAGE_SIZE, "%u\n", 0);
spin_unlock(&lun->lun_sep_lock);
return ret; return ret;
} }
DEV_STAT_SCSI_TGT_PORT_ATTR_RO(hs_in_cmds); DEV_STAT_SCSI_TGT_PORT_ATTR_RO(hs_in_cmds);
@ -919,21 +860,14 @@ static ssize_t target_stat_scsi_transport_show_attr_inst(
struct se_port_stat_grps *pgrps, char *page) struct se_port_stat_grps *pgrps, char *page)
{ {
struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps); struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
struct se_device *dev = lun->lun_se_dev; struct se_device *dev;
struct se_port *sep; ssize_t ret = -ENODEV;
struct se_hba *hba;
ssize_t ret;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
sep = lun->lun_sep; dev = rcu_dereference(lun->lun_se_dev);
if (!sep) { if (dev)
spin_unlock(&lun->lun_sep_lock); ret = snprintf(page, PAGE_SIZE, "%u\n", dev->hba_index);
return -ENODEV; rcu_read_unlock();
}
hba = dev->se_hba;
ret = snprintf(page, PAGE_SIZE, "%u\n", hba->hba_index);
spin_unlock(&lun->lun_sep_lock);
return ret; return ret;
} }
DEV_STAT_SCSI_TRANSPORT_ATTR_RO(inst); DEV_STAT_SCSI_TRANSPORT_ATTR_RO(inst);
@ -942,21 +876,18 @@ static ssize_t target_stat_scsi_transport_show_attr_device(
struct se_port_stat_grps *pgrps, char *page) struct se_port_stat_grps *pgrps, char *page)
{ {
struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps); struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
struct se_port *sep; struct se_device *dev;
struct se_portal_group *tpg; struct se_portal_group *tpg = lun->lun_tpg;
ssize_t ret; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
sep = lun->lun_sep; dev = rcu_dereference(lun->lun_se_dev);
if (!sep) { if (dev) {
spin_unlock(&lun->lun_sep_lock); /* scsiTransportType */
return -ENODEV; ret = snprintf(page, PAGE_SIZE, "scsiTransport%s\n",
tpg->se_tpg_tfo->get_fabric_name());
} }
tpg = sep->sep_tpg; rcu_read_unlock();
/* scsiTransportType */
ret = snprintf(page, PAGE_SIZE, "scsiTransport%s\n",
tpg->se_tpg_tfo->get_fabric_name());
spin_unlock(&lun->lun_sep_lock);
return ret; return ret;
} }
DEV_STAT_SCSI_TRANSPORT_ATTR_RO(device); DEV_STAT_SCSI_TRANSPORT_ATTR_RO(device);
@ -965,20 +896,16 @@ static ssize_t target_stat_scsi_transport_show_attr_indx(
struct se_port_stat_grps *pgrps, char *page) struct se_port_stat_grps *pgrps, char *page)
{ {
struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps); struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
struct se_port *sep; struct se_device *dev;
struct se_portal_group *tpg; struct se_portal_group *tpg = lun->lun_tpg;
ssize_t ret; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
sep = lun->lun_sep; dev = rcu_dereference(lun->lun_se_dev);
if (!sep) { if (dev)
spin_unlock(&lun->lun_sep_lock); ret = snprintf(page, PAGE_SIZE, "%u\n",
return -ENODEV; tpg->se_tpg_tfo->tpg_get_inst_index(tpg));
} rcu_read_unlock();
tpg = sep->sep_tpg;
ret = snprintf(page, PAGE_SIZE, "%u\n",
tpg->se_tpg_tfo->tpg_get_inst_index(tpg));
spin_unlock(&lun->lun_sep_lock);
return ret; return ret;
} }
DEV_STAT_SCSI_TRANSPORT_ATTR_RO(indx); DEV_STAT_SCSI_TRANSPORT_ATTR_RO(indx);
@ -987,26 +914,22 @@ static ssize_t target_stat_scsi_transport_show_attr_dev_name(
struct se_port_stat_grps *pgrps, char *page) struct se_port_stat_grps *pgrps, char *page)
{ {
struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps); struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
struct se_device *dev = lun->lun_se_dev; struct se_device *dev;
struct se_port *sep; struct se_portal_group *tpg = lun->lun_tpg;
struct se_portal_group *tpg;
struct t10_wwn *wwn; struct t10_wwn *wwn;
ssize_t ret; ssize_t ret = -ENODEV;
spin_lock(&lun->lun_sep_lock); rcu_read_lock();
sep = lun->lun_sep; dev = rcu_dereference(lun->lun_se_dev);
if (!sep) { if (dev) {
spin_unlock(&lun->lun_sep_lock); wwn = &dev->t10_wwn;
return -ENODEV; /* scsiTransportDevName */
ret = snprintf(page, PAGE_SIZE, "%s+%s\n",
tpg->se_tpg_tfo->tpg_get_wwn(tpg),
(strlen(wwn->unit_serial)) ? wwn->unit_serial :
wwn->vendor);
} }
tpg = sep->sep_tpg; rcu_read_unlock();
wwn = &dev->t10_wwn;
/* scsiTransportDevName */
ret = snprintf(page, PAGE_SIZE, "%s+%s\n",
tpg->se_tpg_tfo->tpg_get_wwn(tpg),
(strlen(wwn->unit_serial)) ? wwn->unit_serial :
wwn->vendor);
spin_unlock(&lun->lun_sep_lock);
return ret; return ret;
} }
DEV_STAT_SCSI_TRANSPORT_ATTR_RO(dev_name); DEV_STAT_SCSI_TRANSPORT_ATTR_RO(dev_name);
@ -1082,17 +1005,17 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_inst(
struct se_portal_group *tpg; struct se_portal_group *tpg;
ssize_t ret; ssize_t ret;
spin_lock_irq(&nacl->device_list_lock); rcu_read_lock();
deve = nacl->device_list[lacl->mapped_lun]; deve = target_nacl_find_deve(nacl, lacl->mapped_lun);
if (!deve->se_lun || !deve->se_lun_acl) { if (!deve) {
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return -ENODEV; return -ENODEV;
} }
tpg = nacl->se_tpg; tpg = nacl->se_tpg;
/* scsiInstIndex */ /* scsiInstIndex */
ret = snprintf(page, PAGE_SIZE, "%u\n", ret = snprintf(page, PAGE_SIZE, "%u\n",
tpg->se_tpg_tfo->tpg_get_inst_index(tpg)); tpg->se_tpg_tfo->tpg_get_inst_index(tpg));
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(inst); DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(inst);
@ -1107,16 +1030,16 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_dev(
struct se_lun *lun; struct se_lun *lun;
ssize_t ret; ssize_t ret;
spin_lock_irq(&nacl->device_list_lock); rcu_read_lock();
deve = nacl->device_list[lacl->mapped_lun]; deve = target_nacl_find_deve(nacl, lacl->mapped_lun);
if (!deve->se_lun || !deve->se_lun_acl) { if (!deve) {
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return -ENODEV; return -ENODEV;
} }
lun = deve->se_lun; lun = rcu_dereference(deve->se_lun);
/* scsiDeviceIndex */ /* scsiDeviceIndex */
ret = snprintf(page, PAGE_SIZE, "%u\n", lun->lun_se_dev->dev_index); ret = snprintf(page, PAGE_SIZE, "%u\n", lun->lun_index);
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(dev); DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(dev);
@ -1131,16 +1054,16 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_port(
struct se_portal_group *tpg; struct se_portal_group *tpg;
ssize_t ret; ssize_t ret;
spin_lock_irq(&nacl->device_list_lock); rcu_read_lock();
deve = nacl->device_list[lacl->mapped_lun]; deve = target_nacl_find_deve(nacl, lacl->mapped_lun);
if (!deve->se_lun || !deve->se_lun_acl) { if (!deve) {
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return -ENODEV; return -ENODEV;
} }
tpg = nacl->se_tpg; tpg = nacl->se_tpg;
/* scsiAuthIntrTgtPortIndex */ /* scsiAuthIntrTgtPortIndex */
ret = snprintf(page, PAGE_SIZE, "%u\n", tpg->se_tpg_tfo->tpg_get_tag(tpg)); ret = snprintf(page, PAGE_SIZE, "%u\n", tpg->se_tpg_tfo->tpg_get_tag(tpg));
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(port); DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(port);
@ -1154,15 +1077,15 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_indx(
struct se_dev_entry *deve; struct se_dev_entry *deve;
ssize_t ret; ssize_t ret;
spin_lock_irq(&nacl->device_list_lock); rcu_read_lock();
deve = nacl->device_list[lacl->mapped_lun]; deve = target_nacl_find_deve(nacl, lacl->mapped_lun);
if (!deve->se_lun || !deve->se_lun_acl) { if (!deve) {
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return -ENODEV; return -ENODEV;
} }
/* scsiAuthIntrIndex */ /* scsiAuthIntrIndex */
ret = snprintf(page, PAGE_SIZE, "%u\n", nacl->acl_index); ret = snprintf(page, PAGE_SIZE, "%u\n", nacl->acl_index);
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(indx); DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(indx);
@ -1176,15 +1099,15 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_dev_or_port(
struct se_dev_entry *deve; struct se_dev_entry *deve;
ssize_t ret; ssize_t ret;
spin_lock_irq(&nacl->device_list_lock); rcu_read_lock();
deve = nacl->device_list[lacl->mapped_lun]; deve = target_nacl_find_deve(nacl, lacl->mapped_lun);
if (!deve->se_lun || !deve->se_lun_acl) { if (!deve) {
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return -ENODEV; return -ENODEV;
} }
/* scsiAuthIntrDevOrPort */ /* scsiAuthIntrDevOrPort */
ret = snprintf(page, PAGE_SIZE, "%u\n", 1); ret = snprintf(page, PAGE_SIZE, "%u\n", 1);
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(dev_or_port); DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(dev_or_port);
@ -1198,15 +1121,15 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_intr_name(
struct se_dev_entry *deve; struct se_dev_entry *deve;
ssize_t ret; ssize_t ret;
spin_lock_irq(&nacl->device_list_lock); rcu_read_lock();
deve = nacl->device_list[lacl->mapped_lun]; deve = target_nacl_find_deve(nacl, lacl->mapped_lun);
if (!deve->se_lun || !deve->se_lun_acl) { if (!deve) {
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return -ENODEV; return -ENODEV;
} }
/* scsiAuthIntrName */ /* scsiAuthIntrName */
ret = snprintf(page, PAGE_SIZE, "%s\n", nacl->initiatorname); ret = snprintf(page, PAGE_SIZE, "%s\n", nacl->initiatorname);
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(intr_name); DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(intr_name);
@ -1220,15 +1143,15 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_map_indx(
struct se_dev_entry *deve; struct se_dev_entry *deve;
ssize_t ret; ssize_t ret;
spin_lock_irq(&nacl->device_list_lock); rcu_read_lock();
deve = nacl->device_list[lacl->mapped_lun]; deve = target_nacl_find_deve(nacl, lacl->mapped_lun);
if (!deve->se_lun || !deve->se_lun_acl) { if (!deve) {
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return -ENODEV; return -ENODEV;
} }
/* FIXME: scsiAuthIntrLunMapIndex */ /* FIXME: scsiAuthIntrLunMapIndex */
ret = snprintf(page, PAGE_SIZE, "%u\n", 0); ret = snprintf(page, PAGE_SIZE, "%u\n", 0);
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(map_indx); DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(map_indx);
@ -1242,15 +1165,15 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_att_count(
struct se_dev_entry *deve; struct se_dev_entry *deve;
ssize_t ret; ssize_t ret;
spin_lock_irq(&nacl->device_list_lock); rcu_read_lock();
deve = nacl->device_list[lacl->mapped_lun]; deve = target_nacl_find_deve(nacl, lacl->mapped_lun);
if (!deve->se_lun || !deve->se_lun_acl) { if (!deve) {
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return -ENODEV; return -ENODEV;
} }
/* scsiAuthIntrAttachedTimes */ /* scsiAuthIntrAttachedTimes */
ret = snprintf(page, PAGE_SIZE, "%u\n", deve->attach_count); ret = snprintf(page, PAGE_SIZE, "%u\n", deve->attach_count);
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(att_count); DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(att_count);
@ -1264,15 +1187,16 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_num_cmds(
struct se_dev_entry *deve; struct se_dev_entry *deve;
ssize_t ret; ssize_t ret;
spin_lock_irq(&nacl->device_list_lock); rcu_read_lock();
deve = nacl->device_list[lacl->mapped_lun]; deve = target_nacl_find_deve(nacl, lacl->mapped_lun);
if (!deve->se_lun || !deve->se_lun_acl) { if (!deve) {
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return -ENODEV; return -ENODEV;
} }
/* scsiAuthIntrOutCommands */ /* scsiAuthIntrOutCommands */
ret = snprintf(page, PAGE_SIZE, "%u\n", deve->total_cmds); ret = snprintf(page, PAGE_SIZE, "%lu\n",
spin_unlock_irq(&nacl->device_list_lock); atomic_long_read(&deve->total_cmds));
rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(num_cmds); DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(num_cmds);
@ -1286,15 +1210,16 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_read_mbytes(
struct se_dev_entry *deve; struct se_dev_entry *deve;
ssize_t ret; ssize_t ret;
spin_lock_irq(&nacl->device_list_lock); rcu_read_lock();
deve = nacl->device_list[lacl->mapped_lun]; deve = target_nacl_find_deve(nacl, lacl->mapped_lun);
if (!deve->se_lun || !deve->se_lun_acl) { if (!deve) {
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return -ENODEV; return -ENODEV;
} }
/* scsiAuthIntrReadMegaBytes */ /* scsiAuthIntrReadMegaBytes */
ret = snprintf(page, PAGE_SIZE, "%u\n", (u32)(deve->read_bytes >> 20)); ret = snprintf(page, PAGE_SIZE, "%u\n",
spin_unlock_irq(&nacl->device_list_lock); (u32)(atomic_long_read(&deve->read_bytes) >> 20));
rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(read_mbytes); DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(read_mbytes);
@ -1308,15 +1233,16 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_write_mbytes(
struct se_dev_entry *deve; struct se_dev_entry *deve;
ssize_t ret; ssize_t ret;
spin_lock_irq(&nacl->device_list_lock); rcu_read_lock();
deve = nacl->device_list[lacl->mapped_lun]; deve = target_nacl_find_deve(nacl, lacl->mapped_lun);
if (!deve->se_lun || !deve->se_lun_acl) { if (!deve) {
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return -ENODEV; return -ENODEV;
} }
/* scsiAuthIntrWrittenMegaBytes */ /* scsiAuthIntrWrittenMegaBytes */
ret = snprintf(page, PAGE_SIZE, "%u\n", (u32)(deve->write_bytes >> 20)); ret = snprintf(page, PAGE_SIZE, "%u\n",
spin_unlock_irq(&nacl->device_list_lock); (u32)(atomic_long_read(&deve->write_bytes) >> 20));
rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(write_mbytes); DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(write_mbytes);
@ -1330,15 +1256,15 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_hs_num_cmds(
struct se_dev_entry *deve; struct se_dev_entry *deve;
ssize_t ret; ssize_t ret;
spin_lock_irq(&nacl->device_list_lock); rcu_read_lock();
deve = nacl->device_list[lacl->mapped_lun]; deve = target_nacl_find_deve(nacl, lacl->mapped_lun);
if (!deve->se_lun || !deve->se_lun_acl) { if (!deve) {
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return -ENODEV; return -ENODEV;
} }
/* FIXME: scsiAuthIntrHSOutCommands */ /* FIXME: scsiAuthIntrHSOutCommands */
ret = snprintf(page, PAGE_SIZE, "%u\n", 0); ret = snprintf(page, PAGE_SIZE, "%u\n", 0);
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(hs_num_cmds); DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(hs_num_cmds);
@ -1352,16 +1278,16 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_creation_time(
struct se_dev_entry *deve; struct se_dev_entry *deve;
ssize_t ret; ssize_t ret;
spin_lock_irq(&nacl->device_list_lock); rcu_read_lock();
deve = nacl->device_list[lacl->mapped_lun]; deve = target_nacl_find_deve(nacl, lacl->mapped_lun);
if (!deve->se_lun || !deve->se_lun_acl) { if (!deve) {
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return -ENODEV; return -ENODEV;
} }
/* scsiAuthIntrLastCreation */ /* scsiAuthIntrLastCreation */
ret = snprintf(page, PAGE_SIZE, "%u\n", (u32)(((u32)deve->creation_time - ret = snprintf(page, PAGE_SIZE, "%u\n", (u32)(((u32)deve->creation_time -
INITIAL_JIFFIES) * 100 / HZ)); INITIAL_JIFFIES) * 100 / HZ));
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(creation_time); DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(creation_time);
@ -1375,15 +1301,15 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_row_status(
struct se_dev_entry *deve; struct se_dev_entry *deve;
ssize_t ret; ssize_t ret;
spin_lock_irq(&nacl->device_list_lock); rcu_read_lock();
deve = nacl->device_list[lacl->mapped_lun]; deve = target_nacl_find_deve(nacl, lacl->mapped_lun);
if (!deve->se_lun || !deve->se_lun_acl) { if (!deve) {
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return -ENODEV; return -ENODEV;
} }
/* FIXME: scsiAuthIntrRowStatus */ /* FIXME: scsiAuthIntrRowStatus */
ret = snprintf(page, PAGE_SIZE, "Ready\n"); ret = snprintf(page, PAGE_SIZE, "Ready\n");
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(row_status); DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(row_status);
@ -1448,17 +1374,17 @@ static ssize_t target_stat_scsi_att_intr_port_show_attr_inst(
struct se_portal_group *tpg; struct se_portal_group *tpg;
ssize_t ret; ssize_t ret;
spin_lock_irq(&nacl->device_list_lock); rcu_read_lock();
deve = nacl->device_list[lacl->mapped_lun]; deve = target_nacl_find_deve(nacl, lacl->mapped_lun);
if (!deve->se_lun || !deve->se_lun_acl) { if (!deve) {
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return -ENODEV; return -ENODEV;
} }
tpg = nacl->se_tpg; tpg = nacl->se_tpg;
/* scsiInstIndex */ /* scsiInstIndex */
ret = snprintf(page, PAGE_SIZE, "%u\n", ret = snprintf(page, PAGE_SIZE, "%u\n",
tpg->se_tpg_tfo->tpg_get_inst_index(tpg)); tpg->se_tpg_tfo->tpg_get_inst_index(tpg));
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(inst); DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(inst);
@ -1473,16 +1399,16 @@ static ssize_t target_stat_scsi_att_intr_port_show_attr_dev(
struct se_lun *lun; struct se_lun *lun;
ssize_t ret; ssize_t ret;
spin_lock_irq(&nacl->device_list_lock); rcu_read_lock();
deve = nacl->device_list[lacl->mapped_lun]; deve = target_nacl_find_deve(nacl, lacl->mapped_lun);
if (!deve->se_lun || !deve->se_lun_acl) { if (!deve) {
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return -ENODEV; return -ENODEV;
} }
lun = deve->se_lun; lun = rcu_dereference(deve->se_lun);
/* scsiDeviceIndex */ /* scsiDeviceIndex */
ret = snprintf(page, PAGE_SIZE, "%u\n", lun->lun_se_dev->dev_index); ret = snprintf(page, PAGE_SIZE, "%u\n", lun->lun_index);
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(dev); DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(dev);
@ -1497,16 +1423,16 @@ static ssize_t target_stat_scsi_att_intr_port_show_attr_port(
struct se_portal_group *tpg; struct se_portal_group *tpg;
ssize_t ret; ssize_t ret;
spin_lock_irq(&nacl->device_list_lock); rcu_read_lock();
deve = nacl->device_list[lacl->mapped_lun]; deve = target_nacl_find_deve(nacl, lacl->mapped_lun);
if (!deve->se_lun || !deve->se_lun_acl) { if (!deve) {
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return -ENODEV; return -ENODEV;
} }
tpg = nacl->se_tpg; tpg = nacl->se_tpg;
/* scsiPortIndex */ /* scsiPortIndex */
ret = snprintf(page, PAGE_SIZE, "%u\n", tpg->se_tpg_tfo->tpg_get_tag(tpg)); ret = snprintf(page, PAGE_SIZE, "%u\n", tpg->se_tpg_tfo->tpg_get_tag(tpg));
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(port); DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(port);
@ -1546,15 +1472,15 @@ static ssize_t target_stat_scsi_att_intr_port_show_attr_port_auth_indx(
struct se_dev_entry *deve; struct se_dev_entry *deve;
ssize_t ret; ssize_t ret;
spin_lock_irq(&nacl->device_list_lock); rcu_read_lock();
deve = nacl->device_list[lacl->mapped_lun]; deve = target_nacl_find_deve(nacl, lacl->mapped_lun);
if (!deve->se_lun || !deve->se_lun_acl) { if (!deve) {
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return -ENODEV; return -ENODEV;
} }
/* scsiAttIntrPortAuthIntrIdx */ /* scsiAttIntrPortAuthIntrIdx */
ret = snprintf(page, PAGE_SIZE, "%u\n", nacl->acl_index); ret = snprintf(page, PAGE_SIZE, "%u\n", nacl->acl_index);
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return ret; return ret;
} }
DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(port_auth_indx); DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(port_auth_indx);

View File

@ -31,7 +31,6 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_backend.h> #include <target/target_core_backend.h>
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
#include "target_core_internal.h" #include "target_core_internal.h"
#include "target_core_alua.h" #include "target_core_alua.h"
@ -115,7 +114,7 @@ void core_tmr_abort_task(
{ {
struct se_cmd *se_cmd; struct se_cmd *se_cmd;
unsigned long flags; unsigned long flags;
int ref_tag; u64 ref_tag;
spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
list_for_each_entry(se_cmd, &se_sess->sess_cmd_list, se_cmd_list) { list_for_each_entry(se_cmd, &se_sess->sess_cmd_list, se_cmd_list) {
@ -127,16 +126,17 @@ void core_tmr_abort_task(
if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)
continue; continue;
ref_tag = se_cmd->se_tfo->get_task_tag(se_cmd); ref_tag = se_cmd->tag;
if (tmr->ref_task_tag != ref_tag) if (tmr->ref_task_tag != ref_tag)
continue; continue;
printk("ABORT_TASK: Found referenced %s task_tag: %u\n", printk("ABORT_TASK: Found referenced %s task_tag: %llu\n",
se_cmd->se_tfo->get_fabric_name(), ref_tag); se_cmd->se_tfo->get_fabric_name(), ref_tag);
spin_lock(&se_cmd->t_state_lock); spin_lock(&se_cmd->t_state_lock);
if (se_cmd->transport_state & CMD_T_COMPLETE) { if (se_cmd->transport_state & CMD_T_COMPLETE) {
printk("ABORT_TASK: ref_tag: %u already complete, skipping\n", ref_tag); printk("ABORT_TASK: ref_tag: %llu already complete,"
" skipping\n", ref_tag);
spin_unlock(&se_cmd->t_state_lock); spin_unlock(&se_cmd->t_state_lock);
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
goto out; goto out;
@ -151,18 +151,18 @@ void core_tmr_abort_task(
cancel_work_sync(&se_cmd->work); cancel_work_sync(&se_cmd->work);
transport_wait_for_tasks(se_cmd); transport_wait_for_tasks(se_cmd);
target_put_sess_cmd(se_sess, se_cmd); target_put_sess_cmd(se_cmd);
transport_cmd_finish_abort(se_cmd, true); transport_cmd_finish_abort(se_cmd, true);
printk("ABORT_TASK: Sending TMR_FUNCTION_COMPLETE for" printk("ABORT_TASK: Sending TMR_FUNCTION_COMPLETE for"
" ref_tag: %d\n", ref_tag); " ref_tag: %llu\n", ref_tag);
tmr->response = TMR_FUNCTION_COMPLETE; tmr->response = TMR_FUNCTION_COMPLETE;
return; return;
} }
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
out: out:
printk("ABORT_TASK: Sending TMR_TASK_DOES_NOT_EXIST for ref_tag: %d\n", printk("ABORT_TASK: Sending TMR_TASK_DOES_NOT_EXIST for ref_tag: %lld\n",
tmr->ref_task_tag); tmr->ref_task_tag);
tmr->response = TMR_TASK_DOES_NOT_EXIST; tmr->response = TMR_TASK_DOES_NOT_EXIST;
} }
@ -287,16 +287,16 @@ static void core_tmr_drain_state_list(
list_del(&cmd->state_list); list_del(&cmd->state_list);
pr_debug("LUN_RESET: %s cmd: %p" pr_debug("LUN_RESET: %s cmd: %p"
" ITT/CmdSN: 0x%08x/0x%08x, i_state: %d, t_state: %d" " ITT/CmdSN: 0x%08llx/0x%08x, i_state: %d, t_state: %d"
"cdb: 0x%02x\n", "cdb: 0x%02x\n",
(preempt_and_abort_list) ? "Preempt" : "", cmd, (preempt_and_abort_list) ? "Preempt" : "", cmd,
cmd->se_tfo->get_task_tag(cmd), 0, cmd->tag, 0,
cmd->se_tfo->get_cmd_state(cmd), cmd->t_state, cmd->se_tfo->get_cmd_state(cmd), cmd->t_state,
cmd->t_task_cdb[0]); cmd->t_task_cdb[0]);
pr_debug("LUN_RESET: ITT[0x%08x] - pr_res_key: 0x%016Lx" pr_debug("LUN_RESET: ITT[0x%08llx] - pr_res_key: 0x%016Lx"
" -- CMD_T_ACTIVE: %d" " -- CMD_T_ACTIVE: %d"
" CMD_T_STOP: %d CMD_T_SENT: %d\n", " CMD_T_STOP: %d CMD_T_SENT: %d\n",
cmd->se_tfo->get_task_tag(cmd), cmd->pr_res_key, cmd->tag, cmd->pr_res_key,
(cmd->transport_state & CMD_T_ACTIVE) != 0, (cmd->transport_state & CMD_T_ACTIVE) != 0,
(cmd->transport_state & CMD_T_STOP) != 0, (cmd->transport_state & CMD_T_STOP) != 0,
(cmd->transport_state & CMD_T_SENT) != 0); (cmd->transport_state & CMD_T_SENT) != 0);

View File

@ -39,6 +39,7 @@
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include "target_core_internal.h" #include "target_core_internal.h"
#include "target_core_alua.h"
#include "target_core_pr.h" #include "target_core_pr.h"
extern struct se_device *g_lun0_dev; extern struct se_device *g_lun0_dev;
@ -46,45 +47,9 @@ extern struct se_device *g_lun0_dev;
static DEFINE_SPINLOCK(tpg_lock); static DEFINE_SPINLOCK(tpg_lock);
static LIST_HEAD(tpg_list); static LIST_HEAD(tpg_list);
/* core_clear_initiator_node_from_tpg():
*
*
*/
static void core_clear_initiator_node_from_tpg(
struct se_node_acl *nacl,
struct se_portal_group *tpg)
{
int i;
struct se_dev_entry *deve;
struct se_lun *lun;
spin_lock_irq(&nacl->device_list_lock);
for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
deve = nacl->device_list[i];
if (!(deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS))
continue;
if (!deve->se_lun) {
pr_err("%s device entries device pointer is"
" NULL, but Initiator has access.\n",
tpg->se_tpg_tfo->get_fabric_name());
continue;
}
lun = deve->se_lun;
spin_unlock_irq(&nacl->device_list_lock);
core_disable_device_list_for_node(lun, NULL, deve->mapped_lun,
TRANSPORT_LUNFLAGS_NO_ACCESS, nacl, tpg);
spin_lock_irq(&nacl->device_list_lock);
}
spin_unlock_irq(&nacl->device_list_lock);
}
/* __core_tpg_get_initiator_node_acl(): /* __core_tpg_get_initiator_node_acl():
* *
* spin_lock_bh(&tpg->acl_node_lock); must be held when calling * mutex_lock(&tpg->acl_node_mutex); must be held when calling
*/ */
struct se_node_acl *__core_tpg_get_initiator_node_acl( struct se_node_acl *__core_tpg_get_initiator_node_acl(
struct se_portal_group *tpg, struct se_portal_group *tpg,
@ -110,9 +75,9 @@ struct se_node_acl *core_tpg_get_initiator_node_acl(
{ {
struct se_node_acl *acl; struct se_node_acl *acl;
spin_lock_irq(&tpg->acl_node_lock); mutex_lock(&tpg->acl_node_mutex);
acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname); acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname);
spin_unlock_irq(&tpg->acl_node_lock); mutex_unlock(&tpg->acl_node_mutex);
return acl; return acl;
} }
@ -124,22 +89,20 @@ EXPORT_SYMBOL(core_tpg_get_initiator_node_acl);
*/ */
void core_tpg_add_node_to_devs( void core_tpg_add_node_to_devs(
struct se_node_acl *acl, struct se_node_acl *acl,
struct se_portal_group *tpg) struct se_portal_group *tpg,
struct se_lun *lun_orig)
{ {
int i = 0;
u32 lun_access = 0; u32 lun_access = 0;
struct se_lun *lun; struct se_lun *lun;
struct se_device *dev; struct se_device *dev;
spin_lock(&tpg->tpg_lun_lock); mutex_lock(&tpg->tpg_lun_mutex);
for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { hlist_for_each_entry_rcu(lun, &tpg->tpg_lun_hlist, link) {
lun = tpg->tpg_lun_list[i]; if (lun_orig && lun != lun_orig)
if (lun->lun_status != TRANSPORT_LUN_STATUS_ACTIVE)
continue; continue;
spin_unlock(&tpg->tpg_lun_lock); dev = rcu_dereference_check(lun->lun_se_dev,
lockdep_is_held(&tpg->tpg_lun_mutex));
dev = lun->lun_se_dev;
/* /*
* By default in LIO-Target $FABRIC_MOD, * By default in LIO-Target $FABRIC_MOD,
* demo_mode_write_protect is ON, or READ_ONLY; * demo_mode_write_protect is ON, or READ_ONLY;
@ -157,7 +120,7 @@ void core_tpg_add_node_to_devs(
lun_access = TRANSPORT_LUNFLAGS_READ_WRITE; lun_access = TRANSPORT_LUNFLAGS_READ_WRITE;
} }
pr_debug("TARGET_CORE[%s]->TPG[%u]_LUN[%u] - Adding %s" pr_debug("TARGET_CORE[%s]->TPG[%u]_LUN[%llu] - Adding %s"
" access for LUN in Demo Mode\n", " access for LUN in Demo Mode\n",
tpg->se_tpg_tfo->get_fabric_name(), tpg->se_tpg_tfo->get_fabric_name(),
tpg->se_tpg_tfo->tpg_get_tag(tpg), lun->unpacked_lun, tpg->se_tpg_tfo->tpg_get_tag(tpg), lun->unpacked_lun,
@ -165,7 +128,7 @@ void core_tpg_add_node_to_devs(
"READ-WRITE" : "READ-ONLY"); "READ-WRITE" : "READ-ONLY");
core_enable_device_list_for_node(lun, NULL, lun->unpacked_lun, core_enable_device_list_for_node(lun, NULL, lun->unpacked_lun,
lun_access, acl, tpg); lun_access, acl, tpg);
/* /*
* Check to see if there are any existing persistent reservation * Check to see if there are any existing persistent reservation
* APTPL pre-registrations that need to be enabled for this dynamic * APTPL pre-registrations that need to be enabled for this dynamic
@ -173,9 +136,8 @@ void core_tpg_add_node_to_devs(
*/ */
core_scsi3_check_aptpl_registration(dev, tpg, lun, acl, core_scsi3_check_aptpl_registration(dev, tpg, lun, acl,
lun->unpacked_lun); lun->unpacked_lun);
spin_lock(&tpg->tpg_lun_lock);
} }
spin_unlock(&tpg->tpg_lun_lock); mutex_unlock(&tpg->tpg_lun_mutex);
} }
/* core_set_queue_depth_for_node(): /* core_set_queue_depth_for_node():
@ -196,67 +158,63 @@ static int core_set_queue_depth_for_node(
return 0; return 0;
} }
void array_free(void *array, int n) static struct se_node_acl *target_alloc_node_acl(struct se_portal_group *tpg,
const unsigned char *initiatorname)
{ {
void **a = array; struct se_node_acl *acl;
int i;
for (i = 0; i < n; i++) acl = kzalloc(max(sizeof(*acl), tpg->se_tpg_tfo->node_acl_size),
kfree(a[i]); GFP_KERNEL);
kfree(a); if (!acl)
}
static void *array_zalloc(int n, size_t size, gfp_t flags)
{
void **a;
int i;
a = kzalloc(n * sizeof(void*), flags);
if (!a)
return NULL; return NULL;
for (i = 0; i < n; i++) {
a[i] = kzalloc(size, flags); INIT_LIST_HEAD(&acl->acl_list);
if (!a[i]) { INIT_LIST_HEAD(&acl->acl_sess_list);
array_free(a, n); INIT_HLIST_HEAD(&acl->lun_entry_hlist);
return NULL; kref_init(&acl->acl_kref);
} init_completion(&acl->acl_free_comp);
} spin_lock_init(&acl->nacl_sess_lock);
return a; mutex_init(&acl->lun_entry_mutex);
atomic_set(&acl->acl_pr_ref_count, 0);
if (tpg->se_tpg_tfo->tpg_get_default_depth)
acl->queue_depth = tpg->se_tpg_tfo->tpg_get_default_depth(tpg);
else
acl->queue_depth = 1;
snprintf(acl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname);
acl->se_tpg = tpg;
acl->acl_index = scsi_get_new_index(SCSI_AUTH_INTR_INDEX);
tpg->se_tpg_tfo->set_default_node_attributes(acl);
if (core_set_queue_depth_for_node(tpg, acl) < 0)
goto out_free_acl;
return acl;
out_free_acl:
kfree(acl);
return NULL;
} }
/* core_create_device_list_for_node(): static void target_add_node_acl(struct se_node_acl *acl)
*
*
*/
static int core_create_device_list_for_node(struct se_node_acl *nacl)
{ {
struct se_dev_entry *deve; struct se_portal_group *tpg = acl->se_tpg;
int i;
nacl->device_list = array_zalloc(TRANSPORT_MAX_LUNS_PER_TPG, mutex_lock(&tpg->acl_node_mutex);
sizeof(struct se_dev_entry), GFP_KERNEL); list_add_tail(&acl->acl_list, &tpg->acl_node_list);
if (!nacl->device_list) { tpg->num_node_acls++;
pr_err("Unable to allocate memory for" mutex_unlock(&tpg->acl_node_mutex);
" struct se_node_acl->device_list\n");
return -ENOMEM;
}
for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
deve = nacl->device_list[i];
atomic_set(&deve->ua_count, 0); pr_debug("%s_TPG[%hu] - Added %s ACL with TCQ Depth: %d for %s"
atomic_set(&deve->pr_ref_count, 0); " Initiator Node: %s\n",
spin_lock_init(&deve->ua_lock); tpg->se_tpg_tfo->get_fabric_name(),
INIT_LIST_HEAD(&deve->alua_port_list); tpg->se_tpg_tfo->tpg_get_tag(tpg),
INIT_LIST_HEAD(&deve->ua_list); acl->dynamic_node_acl ? "DYNAMIC" : "",
} acl->queue_depth,
tpg->se_tpg_tfo->get_fabric_name(),
return 0; acl->initiatorname);
} }
/* core_tpg_check_initiator_node_acl()
*
*
*/
struct se_node_acl *core_tpg_check_initiator_node_acl( struct se_node_acl *core_tpg_check_initiator_node_acl(
struct se_portal_group *tpg, struct se_portal_group *tpg,
unsigned char *initiatorname) unsigned char *initiatorname)
@ -270,35 +228,11 @@ struct se_node_acl *core_tpg_check_initiator_node_acl(
if (!tpg->se_tpg_tfo->tpg_check_demo_mode(tpg)) if (!tpg->se_tpg_tfo->tpg_check_demo_mode(tpg))
return NULL; return NULL;
acl = tpg->se_tpg_tfo->tpg_alloc_fabric_acl(tpg); acl = target_alloc_node_acl(tpg, initiatorname);
if (!acl) if (!acl)
return NULL; return NULL;
INIT_LIST_HEAD(&acl->acl_list);
INIT_LIST_HEAD(&acl->acl_sess_list);
kref_init(&acl->acl_kref);
init_completion(&acl->acl_free_comp);
spin_lock_init(&acl->device_list_lock);
spin_lock_init(&acl->nacl_sess_lock);
atomic_set(&acl->acl_pr_ref_count, 0);
acl->queue_depth = tpg->se_tpg_tfo->tpg_get_default_depth(tpg);
snprintf(acl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname);
acl->se_tpg = tpg;
acl->acl_index = scsi_get_new_index(SCSI_AUTH_INTR_INDEX);
acl->dynamic_node_acl = 1; acl->dynamic_node_acl = 1;
tpg->se_tpg_tfo->set_default_node_attributes(acl);
if (core_create_device_list_for_node(acl) < 0) {
tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg, acl);
return NULL;
}
if (core_set_queue_depth_for_node(tpg, acl) < 0) {
core_free_device_list_for_node(acl, tpg);
tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg, acl);
return NULL;
}
/* /*
* Here we only create demo-mode MappedLUNs from the active * Here we only create demo-mode MappedLUNs from the active
* TPG LUNs if the fabric is not explicitly asking for * TPG LUNs if the fabric is not explicitly asking for
@ -306,18 +240,9 @@ struct se_node_acl *core_tpg_check_initiator_node_acl(
*/ */
if ((tpg->se_tpg_tfo->tpg_check_demo_mode_login_only == NULL) || if ((tpg->se_tpg_tfo->tpg_check_demo_mode_login_only == NULL) ||
(tpg->se_tpg_tfo->tpg_check_demo_mode_login_only(tpg) != 1)) (tpg->se_tpg_tfo->tpg_check_demo_mode_login_only(tpg) != 1))
core_tpg_add_node_to_devs(acl, tpg); core_tpg_add_node_to_devs(acl, tpg, NULL);
spin_lock_irq(&tpg->acl_node_lock);
list_add_tail(&acl->acl_list, &tpg->acl_node_list);
tpg->num_node_acls++;
spin_unlock_irq(&tpg->acl_node_lock);
pr_debug("%s_TPG[%u] - Added DYNAMIC ACL with TCQ Depth: %d for %s"
" Initiator Node: %s\n", tpg->se_tpg_tfo->get_fabric_name(),
tpg->se_tpg_tfo->tpg_get_tag(tpg), acl->queue_depth,
tpg->se_tpg_tfo->get_fabric_name(), initiatorname);
target_add_node_acl(acl);
return acl; return acl;
} }
EXPORT_SYMBOL(core_tpg_check_initiator_node_acl); EXPORT_SYMBOL(core_tpg_check_initiator_node_acl);
@ -328,40 +253,13 @@ void core_tpg_wait_for_nacl_pr_ref(struct se_node_acl *nacl)
cpu_relax(); cpu_relax();
} }
void core_tpg_clear_object_luns(struct se_portal_group *tpg)
{
int i;
struct se_lun *lun;
spin_lock(&tpg->tpg_lun_lock);
for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
lun = tpg->tpg_lun_list[i];
if ((lun->lun_status != TRANSPORT_LUN_STATUS_ACTIVE) ||
(lun->lun_se_dev == NULL))
continue;
spin_unlock(&tpg->tpg_lun_lock);
core_dev_del_lun(tpg, lun);
spin_lock(&tpg->tpg_lun_lock);
}
spin_unlock(&tpg->tpg_lun_lock);
}
EXPORT_SYMBOL(core_tpg_clear_object_luns);
/* core_tpg_add_initiator_node_acl():
*
*
*/
struct se_node_acl *core_tpg_add_initiator_node_acl( struct se_node_acl *core_tpg_add_initiator_node_acl(
struct se_portal_group *tpg, struct se_portal_group *tpg,
struct se_node_acl *se_nacl, const char *initiatorname)
const char *initiatorname,
u32 queue_depth)
{ {
struct se_node_acl *acl = NULL; struct se_node_acl *acl;
spin_lock_irq(&tpg->acl_node_lock); mutex_lock(&tpg->acl_node_mutex);
acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname); acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname);
if (acl) { if (acl) {
if (acl->dynamic_node_acl) { if (acl->dynamic_node_acl) {
@ -369,99 +267,42 @@ struct se_node_acl *core_tpg_add_initiator_node_acl(
pr_debug("%s_TPG[%u] - Replacing dynamic ACL" pr_debug("%s_TPG[%u] - Replacing dynamic ACL"
" for %s\n", tpg->se_tpg_tfo->get_fabric_name(), " for %s\n", tpg->se_tpg_tfo->get_fabric_name(),
tpg->se_tpg_tfo->tpg_get_tag(tpg), initiatorname); tpg->se_tpg_tfo->tpg_get_tag(tpg), initiatorname);
spin_unlock_irq(&tpg->acl_node_lock); mutex_unlock(&tpg->acl_node_mutex);
/* return acl;
* Release the locally allocated struct se_node_acl
* because * core_tpg_add_initiator_node_acl() returned
* a pointer to an existing demo mode node ACL.
*/
if (se_nacl)
tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg,
se_nacl);
goto done;
} }
pr_err("ACL entry for %s Initiator" pr_err("ACL entry for %s Initiator"
" Node %s already exists for TPG %u, ignoring" " Node %s already exists for TPG %u, ignoring"
" request.\n", tpg->se_tpg_tfo->get_fabric_name(), " request.\n", tpg->se_tpg_tfo->get_fabric_name(),
initiatorname, tpg->se_tpg_tfo->tpg_get_tag(tpg)); initiatorname, tpg->se_tpg_tfo->tpg_get_tag(tpg));
spin_unlock_irq(&tpg->acl_node_lock); mutex_unlock(&tpg->acl_node_mutex);
return ERR_PTR(-EEXIST); return ERR_PTR(-EEXIST);
} }
spin_unlock_irq(&tpg->acl_node_lock); mutex_unlock(&tpg->acl_node_mutex);
if (!se_nacl) { acl = target_alloc_node_acl(tpg, initiatorname);
pr_err("struct se_node_acl pointer is NULL\n"); if (!acl)
return ERR_PTR(-EINVAL);
}
/*
* For v4.x logic the se_node_acl_s is hanging off a fabric
* dependent structure allocated via
* struct target_core_fabric_ops->fabric_make_nodeacl()
*/
acl = se_nacl;
INIT_LIST_HEAD(&acl->acl_list);
INIT_LIST_HEAD(&acl->acl_sess_list);
kref_init(&acl->acl_kref);
init_completion(&acl->acl_free_comp);
spin_lock_init(&acl->device_list_lock);
spin_lock_init(&acl->nacl_sess_lock);
atomic_set(&acl->acl_pr_ref_count, 0);
acl->queue_depth = queue_depth;
snprintf(acl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname);
acl->se_tpg = tpg;
acl->acl_index = scsi_get_new_index(SCSI_AUTH_INTR_INDEX);
tpg->se_tpg_tfo->set_default_node_attributes(acl);
if (core_create_device_list_for_node(acl) < 0) {
tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg, acl);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
}
if (core_set_queue_depth_for_node(tpg, acl) < 0) {
core_free_device_list_for_node(acl, tpg);
tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg, acl);
return ERR_PTR(-EINVAL);
}
spin_lock_irq(&tpg->acl_node_lock);
list_add_tail(&acl->acl_list, &tpg->acl_node_list);
tpg->num_node_acls++;
spin_unlock_irq(&tpg->acl_node_lock);
done:
pr_debug("%s_TPG[%hu] - Added ACL with TCQ Depth: %d for %s"
" Initiator Node: %s\n", tpg->se_tpg_tfo->get_fabric_name(),
tpg->se_tpg_tfo->tpg_get_tag(tpg), acl->queue_depth,
tpg->se_tpg_tfo->get_fabric_name(), initiatorname);
target_add_node_acl(acl);
return acl; return acl;
} }
EXPORT_SYMBOL(core_tpg_add_initiator_node_acl);
/* core_tpg_del_initiator_node_acl(): void core_tpg_del_initiator_node_acl(struct se_node_acl *acl)
*
*
*/
int core_tpg_del_initiator_node_acl(
struct se_portal_group *tpg,
struct se_node_acl *acl,
int force)
{ {
struct se_portal_group *tpg = acl->se_tpg;
LIST_HEAD(sess_list); LIST_HEAD(sess_list);
struct se_session *sess, *sess_tmp; struct se_session *sess, *sess_tmp;
unsigned long flags; unsigned long flags;
int rc; int rc;
spin_lock_irq(&tpg->acl_node_lock); mutex_lock(&tpg->acl_node_mutex);
if (acl->dynamic_node_acl) { if (acl->dynamic_node_acl) {
acl->dynamic_node_acl = 0; acl->dynamic_node_acl = 0;
} }
list_del(&acl->acl_list); list_del(&acl->acl_list);
tpg->num_node_acls--; tpg->num_node_acls--;
spin_unlock_irq(&tpg->acl_node_lock); mutex_unlock(&tpg->acl_node_mutex);
spin_lock_irqsave(&acl->nacl_sess_lock, flags); spin_lock_irqsave(&acl->nacl_sess_lock, flags);
acl->acl_stop = 1; acl->acl_stop = 1;
@ -493,7 +334,6 @@ int core_tpg_del_initiator_node_acl(
wait_for_completion(&acl->acl_free_comp); wait_for_completion(&acl->acl_free_comp);
core_tpg_wait_for_nacl_pr_ref(acl); core_tpg_wait_for_nacl_pr_ref(acl);
core_clear_initiator_node_from_tpg(acl, tpg);
core_free_device_list_for_node(acl, tpg); core_free_device_list_for_node(acl, tpg);
pr_debug("%s_TPG[%hu] - Deleted ACL with TCQ Depth: %d for %s" pr_debug("%s_TPG[%hu] - Deleted ACL with TCQ Depth: %d for %s"
@ -501,9 +341,8 @@ int core_tpg_del_initiator_node_acl(
tpg->se_tpg_tfo->tpg_get_tag(tpg), acl->queue_depth, tpg->se_tpg_tfo->tpg_get_tag(tpg), acl->queue_depth,
tpg->se_tpg_tfo->get_fabric_name(), acl->initiatorname); tpg->se_tpg_tfo->get_fabric_name(), acl->initiatorname);
return 0; kfree(acl);
} }
EXPORT_SYMBOL(core_tpg_del_initiator_node_acl);
/* core_tpg_set_initiator_node_queue_depth(): /* core_tpg_set_initiator_node_queue_depth():
* *
@ -520,21 +359,21 @@ int core_tpg_set_initiator_node_queue_depth(
unsigned long flags; unsigned long flags;
int dynamic_acl = 0; int dynamic_acl = 0;
spin_lock_irq(&tpg->acl_node_lock); mutex_lock(&tpg->acl_node_mutex);
acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname); acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname);
if (!acl) { if (!acl) {
pr_err("Access Control List entry for %s Initiator" pr_err("Access Control List entry for %s Initiator"
" Node %s does not exists for TPG %hu, ignoring" " Node %s does not exists for TPG %hu, ignoring"
" request.\n", tpg->se_tpg_tfo->get_fabric_name(), " request.\n", tpg->se_tpg_tfo->get_fabric_name(),
initiatorname, tpg->se_tpg_tfo->tpg_get_tag(tpg)); initiatorname, tpg->se_tpg_tfo->tpg_get_tag(tpg));
spin_unlock_irq(&tpg->acl_node_lock); mutex_unlock(&tpg->acl_node_mutex);
return -ENODEV; return -ENODEV;
} }
if (acl->dynamic_node_acl) { if (acl->dynamic_node_acl) {
acl->dynamic_node_acl = 0; acl->dynamic_node_acl = 0;
dynamic_acl = 1; dynamic_acl = 1;
} }
spin_unlock_irq(&tpg->acl_node_lock); mutex_unlock(&tpg->acl_node_mutex);
spin_lock_irqsave(&tpg->session_lock, flags); spin_lock_irqsave(&tpg->session_lock, flags);
list_for_each_entry(sess, &tpg->tpg_sess_list, sess_list) { list_for_each_entry(sess, &tpg->tpg_sess_list, sess_list) {
@ -550,10 +389,10 @@ int core_tpg_set_initiator_node_queue_depth(
tpg->se_tpg_tfo->get_fabric_name(), initiatorname); tpg->se_tpg_tfo->get_fabric_name(), initiatorname);
spin_unlock_irqrestore(&tpg->session_lock, flags); spin_unlock_irqrestore(&tpg->session_lock, flags);
spin_lock_irq(&tpg->acl_node_lock); mutex_lock(&tpg->acl_node_mutex);
if (dynamic_acl) if (dynamic_acl)
acl->dynamic_node_acl = 1; acl->dynamic_node_acl = 1;
spin_unlock_irq(&tpg->acl_node_lock); mutex_unlock(&tpg->acl_node_mutex);
return -EEXIST; return -EEXIST;
} }
/* /*
@ -588,10 +427,10 @@ int core_tpg_set_initiator_node_queue_depth(
if (init_sess) if (init_sess)
tpg->se_tpg_tfo->close_session(init_sess); tpg->se_tpg_tfo->close_session(init_sess);
spin_lock_irq(&tpg->acl_node_lock); mutex_lock(&tpg->acl_node_mutex);
if (dynamic_acl) if (dynamic_acl)
acl->dynamic_node_acl = 1; acl->dynamic_node_acl = 1;
spin_unlock_irq(&tpg->acl_node_lock); mutex_unlock(&tpg->acl_node_mutex);
return -EINVAL; return -EINVAL;
} }
spin_unlock_irqrestore(&tpg->session_lock, flags); spin_unlock_irqrestore(&tpg->session_lock, flags);
@ -607,10 +446,10 @@ int core_tpg_set_initiator_node_queue_depth(
initiatorname, tpg->se_tpg_tfo->get_fabric_name(), initiatorname, tpg->se_tpg_tfo->get_fabric_name(),
tpg->se_tpg_tfo->tpg_get_tag(tpg)); tpg->se_tpg_tfo->tpg_get_tag(tpg));
spin_lock_irq(&tpg->acl_node_lock); mutex_lock(&tpg->acl_node_mutex);
if (dynamic_acl) if (dynamic_acl)
acl->dynamic_node_acl = 1; acl->dynamic_node_acl = 1;
spin_unlock_irq(&tpg->acl_node_lock); mutex_unlock(&tpg->acl_node_mutex);
return 0; return 0;
} }
@ -646,78 +485,54 @@ static void core_tpg_lun_ref_release(struct percpu_ref *ref)
complete(&lun->lun_ref_comp); complete(&lun->lun_ref_comp);
} }
static int core_tpg_setup_virtual_lun0(struct se_portal_group *se_tpg)
{
/* Set in core_dev_setup_virtual_lun0() */
struct se_device *dev = g_lun0_dev;
struct se_lun *lun = &se_tpg->tpg_virt_lun0;
u32 lun_access = TRANSPORT_LUNFLAGS_READ_ONLY;
int ret;
lun->unpacked_lun = 0;
lun->lun_status = TRANSPORT_LUN_STATUS_FREE;
atomic_set(&lun->lun_acl_count, 0);
init_completion(&lun->lun_shutdown_comp);
INIT_LIST_HEAD(&lun->lun_acl_list);
spin_lock_init(&lun->lun_acl_lock);
spin_lock_init(&lun->lun_sep_lock);
init_completion(&lun->lun_ref_comp);
ret = core_tpg_add_lun(se_tpg, lun, lun_access, dev);
if (ret < 0)
return ret;
return 0;
}
int core_tpg_register( int core_tpg_register(
const struct target_core_fabric_ops *tfo,
struct se_wwn *se_wwn, struct se_wwn *se_wwn,
struct se_portal_group *se_tpg, struct se_portal_group *se_tpg,
void *tpg_fabric_ptr, int proto_id)
int se_tpg_type)
{ {
struct se_lun *lun; int ret;
u32 i;
se_tpg->tpg_lun_list = array_zalloc(TRANSPORT_MAX_LUNS_PER_TPG, if (!se_tpg)
sizeof(struct se_lun), GFP_KERNEL); return -EINVAL;
if (!se_tpg->tpg_lun_list) { /*
pr_err("Unable to allocate struct se_portal_group->" * For the typical case where core_tpg_register() is called by a
"tpg_lun_list\n"); * fabric driver from target_core_fabric_ops->fabric_make_tpg()
return -ENOMEM; * configfs context, use the original tf_ops pointer already saved
* by target-core in target_fabric_make_wwn().
*
* Otherwise, for special cases like iscsi-target discovery TPGs
* the caller is responsible for setting ->se_tpg_tfo ahead of
* calling core_tpg_register().
*/
if (se_wwn)
se_tpg->se_tpg_tfo = se_wwn->wwn_tf->tf_ops;
if (!se_tpg->se_tpg_tfo) {
pr_err("Unable to locate se_tpg->se_tpg_tfo pointer\n");
return -EINVAL;
} }
for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { INIT_HLIST_HEAD(&se_tpg->tpg_lun_hlist);
lun = se_tpg->tpg_lun_list[i]; se_tpg->proto_id = proto_id;
lun->unpacked_lun = i;
lun->lun_link_magic = SE_LUN_LINK_MAGIC;
lun->lun_status = TRANSPORT_LUN_STATUS_FREE;
atomic_set(&lun->lun_acl_count, 0);
init_completion(&lun->lun_shutdown_comp);
INIT_LIST_HEAD(&lun->lun_acl_list);
spin_lock_init(&lun->lun_acl_lock);
spin_lock_init(&lun->lun_sep_lock);
init_completion(&lun->lun_ref_comp);
}
se_tpg->se_tpg_type = se_tpg_type;
se_tpg->se_tpg_fabric_ptr = tpg_fabric_ptr;
se_tpg->se_tpg_tfo = tfo;
se_tpg->se_tpg_wwn = se_wwn; se_tpg->se_tpg_wwn = se_wwn;
atomic_set(&se_tpg->tpg_pr_ref_count, 0); atomic_set(&se_tpg->tpg_pr_ref_count, 0);
INIT_LIST_HEAD(&se_tpg->acl_node_list); INIT_LIST_HEAD(&se_tpg->acl_node_list);
INIT_LIST_HEAD(&se_tpg->se_tpg_node); INIT_LIST_HEAD(&se_tpg->se_tpg_node);
INIT_LIST_HEAD(&se_tpg->tpg_sess_list); INIT_LIST_HEAD(&se_tpg->tpg_sess_list);
spin_lock_init(&se_tpg->acl_node_lock);
spin_lock_init(&se_tpg->session_lock); spin_lock_init(&se_tpg->session_lock);
spin_lock_init(&se_tpg->tpg_lun_lock); mutex_init(&se_tpg->tpg_lun_mutex);
mutex_init(&se_tpg->acl_node_mutex);
if (se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL) { if (se_tpg->proto_id >= 0) {
if (core_tpg_setup_virtual_lun0(se_tpg) < 0) { se_tpg->tpg_virt_lun0 = core_tpg_alloc_lun(se_tpg, 0);
array_free(se_tpg->tpg_lun_list, if (IS_ERR(se_tpg->tpg_virt_lun0))
TRANSPORT_MAX_LUNS_PER_TPG); return PTR_ERR(se_tpg->tpg_virt_lun0);
return -ENOMEM;
ret = core_tpg_add_lun(se_tpg, se_tpg->tpg_virt_lun0,
TRANSPORT_LUNFLAGS_READ_ONLY, g_lun0_dev);
if (ret < 0) {
kfree(se_tpg->tpg_virt_lun0);
return ret;
} }
} }
@ -725,11 +540,11 @@ int core_tpg_register(
list_add_tail(&se_tpg->se_tpg_node, &tpg_list); list_add_tail(&se_tpg->se_tpg_node, &tpg_list);
spin_unlock_bh(&tpg_lock); spin_unlock_bh(&tpg_lock);
pr_debug("TARGET_CORE[%s]: Allocated %s struct se_portal_group for" pr_debug("TARGET_CORE[%s]: Allocated portal_group for endpoint: %s, "
" endpoint: %s, Portal Tag: %u\n", tfo->get_fabric_name(), "Proto: %d, Portal Tag: %u\n", se_tpg->se_tpg_tfo->get_fabric_name(),
(se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL) ? se_tpg->se_tpg_tfo->tpg_get_wwn(se_tpg) ?
"Normal" : "Discovery", (tfo->tpg_get_wwn(se_tpg) == NULL) ? se_tpg->se_tpg_tfo->tpg_get_wwn(se_tpg) : NULL,
"None" : tfo->tpg_get_wwn(se_tpg), tfo->tpg_get_tag(se_tpg)); se_tpg->proto_id, se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg));
return 0; return 0;
} }
@ -737,14 +552,14 @@ EXPORT_SYMBOL(core_tpg_register);
int core_tpg_deregister(struct se_portal_group *se_tpg) int core_tpg_deregister(struct se_portal_group *se_tpg)
{ {
const struct target_core_fabric_ops *tfo = se_tpg->se_tpg_tfo;
struct se_node_acl *nacl, *nacl_tmp; struct se_node_acl *nacl, *nacl_tmp;
LIST_HEAD(node_list);
pr_debug("TARGET_CORE[%s]: Deallocating %s struct se_portal_group" pr_debug("TARGET_CORE[%s]: Deallocating portal_group for endpoint: %s, "
" for endpoint: %s Portal Tag %u\n", "Proto: %d, Portal Tag: %u\n", tfo->get_fabric_name(),
(se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL) ? tfo->tpg_get_wwn(se_tpg) ? tfo->tpg_get_wwn(se_tpg) : NULL,
"Normal" : "Discovery", se_tpg->se_tpg_tfo->get_fabric_name(), se_tpg->proto_id, tfo->tpg_get_tag(se_tpg));
se_tpg->se_tpg_tfo->tpg_get_wwn(se_tpg),
se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg));
spin_lock_bh(&tpg_lock); spin_lock_bh(&tpg_lock);
list_del(&se_tpg->se_tpg_node); list_del(&se_tpg->se_tpg_node);
@ -752,61 +567,56 @@ int core_tpg_deregister(struct se_portal_group *se_tpg)
while (atomic_read(&se_tpg->tpg_pr_ref_count) != 0) while (atomic_read(&se_tpg->tpg_pr_ref_count) != 0)
cpu_relax(); cpu_relax();
mutex_lock(&se_tpg->acl_node_mutex);
list_splice_init(&se_tpg->acl_node_list, &node_list);
mutex_unlock(&se_tpg->acl_node_mutex);
/* /*
* Release any remaining demo-mode generated se_node_acl that have * Release any remaining demo-mode generated se_node_acl that have
* not been released because of TFO->tpg_check_demo_mode_cache() == 1 * not been released because of TFO->tpg_check_demo_mode_cache() == 1
* in transport_deregister_session(). * in transport_deregister_session().
*/ */
spin_lock_irq(&se_tpg->acl_node_lock); list_for_each_entry_safe(nacl, nacl_tmp, &node_list, acl_list) {
list_for_each_entry_safe(nacl, nacl_tmp, &se_tpg->acl_node_list,
acl_list) {
list_del(&nacl->acl_list); list_del(&nacl->acl_list);
se_tpg->num_node_acls--; se_tpg->num_node_acls--;
spin_unlock_irq(&se_tpg->acl_node_lock);
core_tpg_wait_for_nacl_pr_ref(nacl); core_tpg_wait_for_nacl_pr_ref(nacl);
core_free_device_list_for_node(nacl, se_tpg); core_free_device_list_for_node(nacl, se_tpg);
se_tpg->se_tpg_tfo->tpg_release_fabric_acl(se_tpg, nacl); kfree(nacl);
spin_lock_irq(&se_tpg->acl_node_lock);
} }
spin_unlock_irq(&se_tpg->acl_node_lock);
if (se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL) if (se_tpg->proto_id >= 0) {
core_tpg_remove_lun(se_tpg, &se_tpg->tpg_virt_lun0); core_tpg_remove_lun(se_tpg, se_tpg->tpg_virt_lun0);
kfree_rcu(se_tpg->tpg_virt_lun0, rcu_head);
}
se_tpg->se_tpg_fabric_ptr = NULL;
array_free(se_tpg->tpg_lun_list, TRANSPORT_MAX_LUNS_PER_TPG);
return 0; return 0;
} }
EXPORT_SYMBOL(core_tpg_deregister); EXPORT_SYMBOL(core_tpg_deregister);
struct se_lun *core_tpg_alloc_lun( struct se_lun *core_tpg_alloc_lun(
struct se_portal_group *tpg, struct se_portal_group *tpg,
u32 unpacked_lun) u64 unpacked_lun)
{ {
struct se_lun *lun; struct se_lun *lun;
if (unpacked_lun > (TRANSPORT_MAX_LUNS_PER_TPG-1)) { lun = kzalloc(sizeof(*lun), GFP_KERNEL);
pr_err("%s LUN: %u exceeds TRANSPORT_MAX_LUNS_PER_TPG" if (!lun) {
"-1: %u for Target Portal Group: %u\n", pr_err("Unable to allocate se_lun memory\n");
tpg->se_tpg_tfo->get_fabric_name(), return ERR_PTR(-ENOMEM);
unpacked_lun, TRANSPORT_MAX_LUNS_PER_TPG-1,
tpg->se_tpg_tfo->tpg_get_tag(tpg));
return ERR_PTR(-EOVERFLOW);
} }
lun->unpacked_lun = unpacked_lun;
spin_lock(&tpg->tpg_lun_lock); lun->lun_link_magic = SE_LUN_LINK_MAGIC;
lun = tpg->tpg_lun_list[unpacked_lun]; atomic_set(&lun->lun_acl_count, 0);
if (lun->lun_status == TRANSPORT_LUN_STATUS_ACTIVE) { init_completion(&lun->lun_ref_comp);
pr_err("TPG Logical Unit Number: %u is already active" INIT_LIST_HEAD(&lun->lun_deve_list);
" on %s Target Portal Group: %u, ignoring request.\n", INIT_LIST_HEAD(&lun->lun_dev_link);
unpacked_lun, tpg->se_tpg_tfo->get_fabric_name(), atomic_set(&lun->lun_tg_pt_secondary_offline, 0);
tpg->se_tpg_tfo->tpg_get_tag(tpg)); spin_lock_init(&lun->lun_deve_lock);
spin_unlock(&tpg->tpg_lun_lock); mutex_init(&lun->lun_tg_pt_md_mutex);
return ERR_PTR(-EINVAL); INIT_LIST_HEAD(&lun->lun_tg_pt_gp_link);
} spin_lock_init(&lun->lun_tg_pt_gp_lock);
spin_unlock(&tpg->tpg_lun_lock); lun->lun_tpg = tpg;
return lun; return lun;
} }
@ -822,34 +632,70 @@ int core_tpg_add_lun(
ret = percpu_ref_init(&lun->lun_ref, core_tpg_lun_ref_release, 0, ret = percpu_ref_init(&lun->lun_ref, core_tpg_lun_ref_release, 0,
GFP_KERNEL); GFP_KERNEL);
if (ret < 0) if (ret < 0)
return ret; goto out;
ret = core_dev_export(dev, tpg, lun); ret = core_alloc_rtpi(lun, dev);
if (ret < 0) { if (ret)
percpu_ref_exit(&lun->lun_ref); goto out_kill_ref;
return ret;
} if (!(dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH) &&
!(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE))
target_attach_tg_pt_gp(lun, dev->t10_alua.default_tg_pt_gp);
mutex_lock(&tpg->tpg_lun_mutex);
spin_lock(&dev->se_port_lock);
lun->lun_index = dev->dev_index;
rcu_assign_pointer(lun->lun_se_dev, dev);
dev->export_count++;
list_add_tail(&lun->lun_dev_link, &dev->dev_sep_list);
spin_unlock(&dev->se_port_lock);
spin_lock(&tpg->tpg_lun_lock);
lun->lun_access = lun_access; lun->lun_access = lun_access;
lun->lun_status = TRANSPORT_LUN_STATUS_ACTIVE; if (!(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE))
spin_unlock(&tpg->tpg_lun_lock); hlist_add_head_rcu(&lun->link, &tpg->tpg_lun_hlist);
mutex_unlock(&tpg->tpg_lun_mutex);
return 0; return 0;
out_kill_ref:
percpu_ref_exit(&lun->lun_ref);
out:
return ret;
} }
void core_tpg_remove_lun( void core_tpg_remove_lun(
struct se_portal_group *tpg, struct se_portal_group *tpg,
struct se_lun *lun) struct se_lun *lun)
{ {
/*
* rcu_dereference_raw protected by se_lun->lun_group symlink
* reference to se_device->dev_group.
*/
struct se_device *dev = rcu_dereference_raw(lun->lun_se_dev);
core_clear_lun_from_tpg(lun, tpg); core_clear_lun_from_tpg(lun, tpg);
/*
* Wait for any active I/O references to percpu se_lun->lun_ref to
* be released. Also, se_lun->lun_ref is now used by PR and ALUA
* logic when referencing a remote target port during ALL_TGT_PT=1
* and generating UNIT_ATTENTIONs for ALUA access state transition.
*/
transport_clear_lun_ref(lun); transport_clear_lun_ref(lun);
core_dev_unexport(lun->lun_se_dev, tpg, lun); mutex_lock(&tpg->tpg_lun_mutex);
if (lun->lun_se_dev) {
target_detach_tg_pt_gp(lun);
spin_lock(&tpg->tpg_lun_lock); spin_lock(&dev->se_port_lock);
lun->lun_status = TRANSPORT_LUN_STATUS_FREE; list_del(&lun->lun_dev_link);
spin_unlock(&tpg->tpg_lun_lock); dev->export_count--;
rcu_assign_pointer(lun->lun_se_dev, NULL);
spin_unlock(&dev->se_port_lock);
}
if (!(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE))
hlist_del_rcu(&lun->link);
mutex_unlock(&tpg->tpg_lun_mutex);
percpu_ref_exit(&lun->lun_ref); percpu_ref_exit(&lun->lun_ref);
} }

View File

@ -43,7 +43,6 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_backend.h> #include <target/target_core_backend.h>
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
#include "target_core_internal.h" #include "target_core_internal.h"
#include "target_core_alua.h" #include "target_core_alua.h"
@ -60,7 +59,6 @@ struct kmem_cache *t10_pr_reg_cache;
struct kmem_cache *t10_alua_lu_gp_cache; struct kmem_cache *t10_alua_lu_gp_cache;
struct kmem_cache *t10_alua_lu_gp_mem_cache; struct kmem_cache *t10_alua_lu_gp_mem_cache;
struct kmem_cache *t10_alua_tg_pt_gp_cache; struct kmem_cache *t10_alua_tg_pt_gp_cache;
struct kmem_cache *t10_alua_tg_pt_gp_mem_cache;
struct kmem_cache *t10_alua_lba_map_cache; struct kmem_cache *t10_alua_lba_map_cache;
struct kmem_cache *t10_alua_lba_map_mem_cache; struct kmem_cache *t10_alua_lba_map_mem_cache;
@ -119,16 +117,6 @@ int init_se_kmem_caches(void)
"cache failed\n"); "cache failed\n");
goto out_free_lu_gp_mem_cache; goto out_free_lu_gp_mem_cache;
} }
t10_alua_tg_pt_gp_mem_cache = kmem_cache_create(
"t10_alua_tg_pt_gp_mem_cache",
sizeof(struct t10_alua_tg_pt_gp_member),
__alignof__(struct t10_alua_tg_pt_gp_member),
0, NULL);
if (!t10_alua_tg_pt_gp_mem_cache) {
pr_err("kmem_cache_create() for t10_alua_tg_pt_gp_"
"mem_t failed\n");
goto out_free_tg_pt_gp_cache;
}
t10_alua_lba_map_cache = kmem_cache_create( t10_alua_lba_map_cache = kmem_cache_create(
"t10_alua_lba_map_cache", "t10_alua_lba_map_cache",
sizeof(struct t10_alua_lba_map), sizeof(struct t10_alua_lba_map),
@ -136,7 +124,7 @@ int init_se_kmem_caches(void)
if (!t10_alua_lba_map_cache) { if (!t10_alua_lba_map_cache) {
pr_err("kmem_cache_create() for t10_alua_lba_map_" pr_err("kmem_cache_create() for t10_alua_lba_map_"
"cache failed\n"); "cache failed\n");
goto out_free_tg_pt_gp_mem_cache; goto out_free_tg_pt_gp_cache;
} }
t10_alua_lba_map_mem_cache = kmem_cache_create( t10_alua_lba_map_mem_cache = kmem_cache_create(
"t10_alua_lba_map_mem_cache", "t10_alua_lba_map_mem_cache",
@ -159,8 +147,6 @@ out_free_lba_map_mem_cache:
kmem_cache_destroy(t10_alua_lba_map_mem_cache); kmem_cache_destroy(t10_alua_lba_map_mem_cache);
out_free_lba_map_cache: out_free_lba_map_cache:
kmem_cache_destroy(t10_alua_lba_map_cache); kmem_cache_destroy(t10_alua_lba_map_cache);
out_free_tg_pt_gp_mem_cache:
kmem_cache_destroy(t10_alua_tg_pt_gp_mem_cache);
out_free_tg_pt_gp_cache: out_free_tg_pt_gp_cache:
kmem_cache_destroy(t10_alua_tg_pt_gp_cache); kmem_cache_destroy(t10_alua_tg_pt_gp_cache);
out_free_lu_gp_mem_cache: out_free_lu_gp_mem_cache:
@ -186,7 +172,6 @@ void release_se_kmem_caches(void)
kmem_cache_destroy(t10_alua_lu_gp_cache); kmem_cache_destroy(t10_alua_lu_gp_cache);
kmem_cache_destroy(t10_alua_lu_gp_mem_cache); kmem_cache_destroy(t10_alua_lu_gp_mem_cache);
kmem_cache_destroy(t10_alua_tg_pt_gp_cache); kmem_cache_destroy(t10_alua_tg_pt_gp_cache);
kmem_cache_destroy(t10_alua_tg_pt_gp_mem_cache);
kmem_cache_destroy(t10_alua_lba_map_cache); kmem_cache_destroy(t10_alua_lba_map_cache);
kmem_cache_destroy(t10_alua_lba_map_mem_cache); kmem_cache_destroy(t10_alua_lba_map_mem_cache);
} }
@ -406,12 +391,6 @@ EXPORT_SYMBOL(target_get_session);
void target_put_session(struct se_session *se_sess) void target_put_session(struct se_session *se_sess)
{ {
struct se_portal_group *tpg = se_sess->se_tpg;
if (tpg->se_tpg_tfo->put_session != NULL) {
tpg->se_tpg_tfo->put_session(se_sess);
return;
}
kref_put(&se_sess->sess_kref, target_release_session); kref_put(&se_sess->sess_kref, target_release_session);
} }
EXPORT_SYMBOL(target_put_session); EXPORT_SYMBOL(target_put_session);
@ -498,7 +477,7 @@ void transport_deregister_session(struct se_session *se_sess)
const struct target_core_fabric_ops *se_tfo; const struct target_core_fabric_ops *se_tfo;
struct se_node_acl *se_nacl; struct se_node_acl *se_nacl;
unsigned long flags; unsigned long flags;
bool comp_nacl = true; bool comp_nacl = true, drop_nacl = false;
if (!se_tpg) { if (!se_tpg) {
transport_free_session(se_sess); transport_free_session(se_sess);
@ -518,22 +497,22 @@ void transport_deregister_session(struct se_session *se_sess)
*/ */
se_nacl = se_sess->se_node_acl; se_nacl = se_sess->se_node_acl;
spin_lock_irqsave(&se_tpg->acl_node_lock, flags); mutex_lock(&se_tpg->acl_node_mutex);
if (se_nacl && se_nacl->dynamic_node_acl) { if (se_nacl && se_nacl->dynamic_node_acl) {
if (!se_tfo->tpg_check_demo_mode_cache(se_tpg)) { if (!se_tfo->tpg_check_demo_mode_cache(se_tpg)) {
list_del(&se_nacl->acl_list); list_del(&se_nacl->acl_list);
se_tpg->num_node_acls--; se_tpg->num_node_acls--;
spin_unlock_irqrestore(&se_tpg->acl_node_lock, flags); drop_nacl = true;
core_tpg_wait_for_nacl_pr_ref(se_nacl);
core_free_device_list_for_node(se_nacl, se_tpg);
se_tfo->tpg_release_fabric_acl(se_tpg, se_nacl);
comp_nacl = false;
spin_lock_irqsave(&se_tpg->acl_node_lock, flags);
} }
} }
spin_unlock_irqrestore(&se_tpg->acl_node_lock, flags); mutex_unlock(&se_tpg->acl_node_mutex);
if (drop_nacl) {
core_tpg_wait_for_nacl_pr_ref(se_nacl);
core_free_device_list_for_node(se_nacl, se_tpg);
kfree(se_nacl);
comp_nacl = false;
}
pr_debug("TARGET_CORE[%s]: Deregistered fabric_sess\n", pr_debug("TARGET_CORE[%s]: Deregistered fabric_sess\n",
se_tpg->se_tpg_tfo->get_fabric_name()); se_tpg->se_tpg_tfo->get_fabric_name());
/* /*
@ -593,9 +572,8 @@ static int transport_cmd_check_stop(struct se_cmd *cmd, bool remove_from_lists,
* this command for frontend exceptions. * this command for frontend exceptions.
*/ */
if (cmd->transport_state & CMD_T_STOP) { if (cmd->transport_state & CMD_T_STOP) {
pr_debug("%s:%d CMD_T_STOP for ITT: 0x%08x\n", pr_debug("%s:%d CMD_T_STOP for ITT: 0x%08llx\n",
__func__, __LINE__, __func__, __LINE__, cmd->tag);
cmd->se_tfo->get_task_tag(cmd));
spin_unlock_irqrestore(&cmd->t_state_lock, flags); spin_unlock_irqrestore(&cmd->t_state_lock, flags);
@ -1148,6 +1126,8 @@ target_cmd_size_check(struct se_cmd *cmd, unsigned int size)
/* /*
* Used by fabric modules containing a local struct se_cmd within their * Used by fabric modules containing a local struct se_cmd within their
* fabric dependent per I/O descriptor. * fabric dependent per I/O descriptor.
*
* Preserves the value of @cmd->tag.
*/ */
void transport_init_se_cmd( void transport_init_se_cmd(
struct se_cmd *cmd, struct se_cmd *cmd,
@ -1274,11 +1254,7 @@ target_setup_cmd_from_cdb(struct se_cmd *cmd, unsigned char *cdb)
return ret; return ret;
cmd->se_cmd_flags |= SCF_SUPPORTED_SAM_OPCODE; cmd->se_cmd_flags |= SCF_SUPPORTED_SAM_OPCODE;
atomic_long_inc(&cmd->se_lun->lun_stats.cmd_pdus);
spin_lock(&cmd->se_lun->lun_sep_lock);
if (cmd->se_lun->lun_sep)
cmd->se_lun->lun_sep->sep_stats.cmd_pdus++;
spin_unlock(&cmd->se_lun->lun_sep_lock);
return 0; return 0;
} }
EXPORT_SYMBOL(target_setup_cmd_from_cdb); EXPORT_SYMBOL(target_setup_cmd_from_cdb);
@ -1346,11 +1322,9 @@ transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *sgl,
cmd->t_data_sg = sgl; cmd->t_data_sg = sgl;
cmd->t_data_nents = sgl_count; cmd->t_data_nents = sgl_count;
cmd->t_bidi_data_sg = sgl_bidi;
cmd->t_bidi_data_nents = sgl_bidi_count;
if (sgl_bidi && sgl_bidi_count) {
cmd->t_bidi_data_sg = sgl_bidi;
cmd->t_bidi_data_nents = sgl_bidi_count;
}
cmd->se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC; cmd->se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
return 0; return 0;
} }
@ -1375,6 +1349,8 @@ transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *sgl,
* @sgl_prot: struct scatterlist memory protection information * @sgl_prot: struct scatterlist memory protection information
* @sgl_prot_count: scatterlist count for protection information * @sgl_prot_count: scatterlist count for protection information
* *
* Task tags are supported if the caller has set @se_cmd->tag.
*
* Returns non zero to signal active I/O shutdown failure. All other * Returns non zero to signal active I/O shutdown failure. All other
* setup exceptions will be returned as a SCSI CHECK_CONDITION response, * setup exceptions will be returned as a SCSI CHECK_CONDITION response,
* but still return zero here. * but still return zero here.
@ -1383,7 +1359,7 @@ transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *sgl,
* assumes internal allocation of fabric payload buffer by target-core. * assumes internal allocation of fabric payload buffer by target-core.
*/ */
int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess, int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess,
unsigned char *cdb, unsigned char *sense, u32 unpacked_lun, unsigned char *cdb, unsigned char *sense, u64 unpacked_lun,
u32 data_length, int task_attr, int data_dir, int flags, u32 data_length, int task_attr, int data_dir, int flags,
struct scatterlist *sgl, u32 sgl_count, struct scatterlist *sgl, u32 sgl_count,
struct scatterlist *sgl_bidi, u32 sgl_bidi_count, struct scatterlist *sgl_bidi, u32 sgl_bidi_count,
@ -1412,7 +1388,7 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess
* for fabrics using TARGET_SCF_ACK_KREF that expect a second * for fabrics using TARGET_SCF_ACK_KREF that expect a second
* kref_put() to happen during fabric packet acknowledgement. * kref_put() to happen during fabric packet acknowledgement.
*/ */
ret = target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF)); ret = target_get_sess_cmd(se_cmd, flags & TARGET_SCF_ACK_KREF);
if (ret) if (ret)
return ret; return ret;
/* /*
@ -1426,7 +1402,7 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess
rc = transport_lookup_cmd_lun(se_cmd, unpacked_lun); rc = transport_lookup_cmd_lun(se_cmd, unpacked_lun);
if (rc) { if (rc) {
transport_send_check_condition_and_sense(se_cmd, rc, 0); transport_send_check_condition_and_sense(se_cmd, rc, 0);
target_put_sess_cmd(se_sess, se_cmd); target_put_sess_cmd(se_cmd);
return 0; return 0;
} }
@ -1443,6 +1419,7 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess
if (sgl_prot_count) { if (sgl_prot_count) {
se_cmd->t_prot_sg = sgl_prot; se_cmd->t_prot_sg = sgl_prot;
se_cmd->t_prot_nents = sgl_prot_count; se_cmd->t_prot_nents = sgl_prot_count;
se_cmd->se_cmd_flags |= SCF_PASSTHROUGH_PROT_SG_TO_MEM_NOALLOC;
} }
/* /*
@ -1506,6 +1483,8 @@ EXPORT_SYMBOL(target_submit_cmd_map_sgls);
* @data_dir: DMA data direction * @data_dir: DMA data direction
* @flags: flags for command submission from target_sc_flags_tables * @flags: flags for command submission from target_sc_flags_tables
* *
* Task tags are supported if the caller has set @se_cmd->tag.
*
* Returns non zero to signal active I/O shutdown failure. All other * Returns non zero to signal active I/O shutdown failure. All other
* setup exceptions will be returned as a SCSI CHECK_CONDITION response, * setup exceptions will be returned as a SCSI CHECK_CONDITION response,
* but still return zero here. * but still return zero here.
@ -1516,7 +1495,7 @@ EXPORT_SYMBOL(target_submit_cmd_map_sgls);
* It also assumes interal target core SGL memory allocation. * It also assumes interal target core SGL memory allocation.
*/ */
int target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess, int target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
unsigned char *cdb, unsigned char *sense, u32 unpacked_lun, unsigned char *cdb, unsigned char *sense, u64 unpacked_lun,
u32 data_length, int task_attr, int data_dir, int flags) u32 data_length, int task_attr, int data_dir, int flags)
{ {
return target_submit_cmd_map_sgls(se_cmd, se_sess, cdb, sense, return target_submit_cmd_map_sgls(se_cmd, se_sess, cdb, sense,
@ -1553,7 +1532,7 @@ static void target_complete_tmr_failure(struct work_struct *work)
**/ **/
int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess, int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess,
unsigned char *sense, u32 unpacked_lun, unsigned char *sense, u64 unpacked_lun,
void *fabric_tmr_ptr, unsigned char tm_type, void *fabric_tmr_ptr, unsigned char tm_type,
gfp_t gfp, unsigned int tag, int flags) gfp_t gfp, unsigned int tag, int flags)
{ {
@ -1577,7 +1556,7 @@ int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess,
se_cmd->se_tmr_req->ref_task_tag = tag; se_cmd->se_tmr_req->ref_task_tag = tag;
/* See target_submit_cmd for commentary */ /* See target_submit_cmd for commentary */
ret = target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF)); ret = target_get_sess_cmd(se_cmd, flags & TARGET_SCF_ACK_KREF);
if (ret) { if (ret) {
core_tmr_release_req(se_cmd->se_tmr_req); core_tmr_release_req(se_cmd->se_tmr_req);
return ret; return ret;
@ -1633,9 +1612,8 @@ void transport_generic_request_failure(struct se_cmd *cmd,
{ {
int ret = 0; int ret = 0;
pr_debug("-----[ Storage Engine Exception for cmd: %p ITT: 0x%08x" pr_debug("-----[ Storage Engine Exception for cmd: %p ITT: 0x%08llx"
" CDB: 0x%02x\n", cmd, cmd->se_tfo->get_task_tag(cmd), " CDB: 0x%02x\n", cmd, cmd->tag, cmd->t_task_cdb[0]);
cmd->t_task_cdb[0]);
pr_debug("-----[ i_state: %d t_state: %d sense_reason: %d\n", pr_debug("-----[ i_state: %d t_state: %d sense_reason: %d\n",
cmd->se_tfo->get_cmd_state(cmd), cmd->se_tfo->get_cmd_state(cmd),
cmd->t_state, sense_reason); cmd->t_state, sense_reason);
@ -1692,13 +1670,13 @@ void transport_generic_request_failure(struct se_cmd *cmd,
* See spc4r17, section 7.4.6 Control Mode Page, Table 349 * See spc4r17, section 7.4.6 Control Mode Page, Table 349
*/ */
if (cmd->se_sess && if (cmd->se_sess &&
cmd->se_dev->dev_attrib.emulate_ua_intlck_ctrl == 2) cmd->se_dev->dev_attrib.emulate_ua_intlck_ctrl == 2) {
core_scsi3_ua_allocate(cmd->se_sess->se_node_acl, target_ua_allocate_lun(cmd->se_sess->se_node_acl,
cmd->orig_fe_lun, 0x2C, cmd->orig_fe_lun, 0x2C,
ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS); ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS);
}
trace_target_cmd_complete(cmd); trace_target_cmd_complete(cmd);
ret = cmd->se_tfo-> queue_status(cmd); ret = cmd->se_tfo->queue_status(cmd);
if (ret == -EAGAIN || ret == -ENOMEM) if (ret == -EAGAIN || ret == -ENOMEM)
goto queue_full; goto queue_full;
goto check_stop; goto check_stop;
@ -1759,8 +1737,8 @@ static int target_write_prot_action(struct se_cmd *cmd)
break; break;
sectors = cmd->data_length >> ilog2(cmd->se_dev->dev_attrib.block_size); sectors = cmd->data_length >> ilog2(cmd->se_dev->dev_attrib.block_size);
cmd->pi_err = sbc_dif_verify_write(cmd, cmd->t_task_lba, cmd->pi_err = sbc_dif_verify(cmd, cmd->t_task_lba,
sectors, 0, NULL, 0); sectors, 0, cmd->t_prot_sg, 0);
if (unlikely(cmd->pi_err)) { if (unlikely(cmd->pi_err)) {
spin_lock_irq(&cmd->t_state_lock); spin_lock_irq(&cmd->t_state_lock);
cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT); cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT);
@ -1843,9 +1821,8 @@ void target_execute_cmd(struct se_cmd *cmd)
*/ */
spin_lock_irq(&cmd->t_state_lock); spin_lock_irq(&cmd->t_state_lock);
if (cmd->transport_state & CMD_T_STOP) { if (cmd->transport_state & CMD_T_STOP) {
pr_debug("%s:%d CMD_T_STOP for ITT: 0x%08x\n", pr_debug("%s:%d CMD_T_STOP for ITT: 0x%08llx\n",
__func__, __LINE__, __func__, __LINE__, cmd->tag);
cmd->se_tfo->get_task_tag(cmd));
spin_unlock_irq(&cmd->t_state_lock); spin_unlock_irq(&cmd->t_state_lock);
complete_all(&cmd->t_transport_stop_comp); complete_all(&cmd->t_transport_stop_comp);
@ -1984,16 +1961,17 @@ static void transport_handle_queue_full(
static bool target_read_prot_action(struct se_cmd *cmd) static bool target_read_prot_action(struct se_cmd *cmd)
{ {
sense_reason_t rc;
switch (cmd->prot_op) { switch (cmd->prot_op) {
case TARGET_PROT_DIN_STRIP: case TARGET_PROT_DIN_STRIP:
if (!(cmd->se_sess->sup_prot_ops & TARGET_PROT_DIN_STRIP)) { if (!(cmd->se_sess->sup_prot_ops & TARGET_PROT_DIN_STRIP)) {
rc = sbc_dif_read_strip(cmd); u32 sectors = cmd->data_length >>
if (rc) { ilog2(cmd->se_dev->dev_attrib.block_size);
cmd->pi_err = rc;
cmd->pi_err = sbc_dif_verify(cmd, cmd->t_task_lba,
sectors, 0, cmd->t_prot_sg,
0);
if (cmd->pi_err)
return true; return true;
}
} }
break; break;
case TARGET_PROT_DIN_INSERT: case TARGET_PROT_DIN_INSERT:
@ -2072,12 +2050,8 @@ static void target_complete_ok_work(struct work_struct *work)
queue_rsp: queue_rsp:
switch (cmd->data_direction) { switch (cmd->data_direction) {
case DMA_FROM_DEVICE: case DMA_FROM_DEVICE:
spin_lock(&cmd->se_lun->lun_sep_lock); atomic_long_add(cmd->data_length,
if (cmd->se_lun->lun_sep) { &cmd->se_lun->lun_stats.tx_data_octets);
cmd->se_lun->lun_sep->sep_stats.tx_data_octets +=
cmd->data_length;
}
spin_unlock(&cmd->se_lun->lun_sep_lock);
/* /*
* Perform READ_STRIP of PI using software emulation when * Perform READ_STRIP of PI using software emulation when
* backend had PI enabled, if the transport will not be * backend had PI enabled, if the transport will not be
@ -2100,22 +2074,14 @@ queue_rsp:
goto queue_full; goto queue_full;
break; break;
case DMA_TO_DEVICE: case DMA_TO_DEVICE:
spin_lock(&cmd->se_lun->lun_sep_lock); atomic_long_add(cmd->data_length,
if (cmd->se_lun->lun_sep) { &cmd->se_lun->lun_stats.rx_data_octets);
cmd->se_lun->lun_sep->sep_stats.rx_data_octets +=
cmd->data_length;
}
spin_unlock(&cmd->se_lun->lun_sep_lock);
/* /*
* Check if we need to send READ payload for BIDI-COMMAND * Check if we need to send READ payload for BIDI-COMMAND
*/ */
if (cmd->se_cmd_flags & SCF_BIDI) { if (cmd->se_cmd_flags & SCF_BIDI) {
spin_lock(&cmd->se_lun->lun_sep_lock); atomic_long_add(cmd->data_length,
if (cmd->se_lun->lun_sep) { &cmd->se_lun->lun_stats.tx_data_octets);
cmd->se_lun->lun_sep->sep_stats.tx_data_octets +=
cmd->data_length;
}
spin_unlock(&cmd->se_lun->lun_sep_lock);
ret = cmd->se_tfo->queue_data_in(cmd); ret = cmd->se_tfo->queue_data_in(cmd);
if (ret == -EAGAIN || ret == -ENOMEM) if (ret == -EAGAIN || ret == -ENOMEM)
goto queue_full; goto queue_full;
@ -2172,6 +2138,12 @@ static inline void transport_reset_sgl_orig(struct se_cmd *cmd)
static inline void transport_free_pages(struct se_cmd *cmd) static inline void transport_free_pages(struct se_cmd *cmd)
{ {
if (!(cmd->se_cmd_flags & SCF_PASSTHROUGH_PROT_SG_TO_MEM_NOALLOC)) {
transport_free_sgl(cmd->t_prot_sg, cmd->t_prot_nents);
cmd->t_prot_sg = NULL;
cmd->t_prot_nents = 0;
}
if (cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC) { if (cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC) {
/* /*
* Release special case READ buffer payload required for * Release special case READ buffer payload required for
@ -2195,10 +2167,6 @@ static inline void transport_free_pages(struct se_cmd *cmd)
transport_free_sgl(cmd->t_bidi_data_sg, cmd->t_bidi_data_nents); transport_free_sgl(cmd->t_bidi_data_sg, cmd->t_bidi_data_nents);
cmd->t_bidi_data_sg = NULL; cmd->t_bidi_data_sg = NULL;
cmd->t_bidi_data_nents = 0; cmd->t_bidi_data_nents = 0;
transport_free_sgl(cmd->t_prot_sg, cmd->t_prot_nents);
cmd->t_prot_sg = NULL;
cmd->t_prot_nents = 0;
} }
/** /**
@ -2220,7 +2188,7 @@ static int transport_release_cmd(struct se_cmd *cmd)
* If this cmd has been setup with target_get_sess_cmd(), drop * If this cmd has been setup with target_get_sess_cmd(), drop
* the kref and call ->release_cmd() in kref callback. * the kref and call ->release_cmd() in kref callback.
*/ */
return target_put_sess_cmd(cmd->se_sess, cmd); return target_put_sess_cmd(cmd);
} }
/** /**
@ -2337,6 +2305,14 @@ transport_generic_new_cmd(struct se_cmd *cmd)
int ret = 0; int ret = 0;
bool zero_flag = !(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB); bool zero_flag = !(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB);
if (cmd->prot_op != TARGET_PROT_NORMAL &&
!(cmd->se_cmd_flags & SCF_PASSTHROUGH_PROT_SG_TO_MEM_NOALLOC)) {
ret = target_alloc_sgl(&cmd->t_prot_sg, &cmd->t_prot_nents,
cmd->prot_length, true);
if (ret < 0)
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
}
/* /*
* Determine is the TCM fabric module has already allocated physical * Determine is the TCM fabric module has already allocated physical
* memory, and is directly calling transport_generic_map_mem_to_cmd() * memory, and is directly calling transport_generic_map_mem_to_cmd()
@ -2362,14 +2338,6 @@ transport_generic_new_cmd(struct se_cmd *cmd)
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
} }
if (cmd->prot_op != TARGET_PROT_NORMAL) {
ret = target_alloc_sgl(&cmd->t_prot_sg,
&cmd->t_prot_nents,
cmd->prot_length, true);
if (ret < 0)
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
}
ret = target_alloc_sgl(&cmd->t_data_sg, &cmd->t_data_nents, ret = target_alloc_sgl(&cmd->t_data_sg, &cmd->t_data_nents,
cmd->data_length, zero_flag); cmd->data_length, zero_flag);
if (ret < 0) if (ret < 0)
@ -2464,13 +2432,12 @@ int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks)
EXPORT_SYMBOL(transport_generic_free_cmd); EXPORT_SYMBOL(transport_generic_free_cmd);
/* target_get_sess_cmd - Add command to active ->sess_cmd_list /* target_get_sess_cmd - Add command to active ->sess_cmd_list
* @se_sess: session to reference
* @se_cmd: command descriptor to add * @se_cmd: command descriptor to add
* @ack_kref: Signal that fabric will perform an ack target_put_sess_cmd() * @ack_kref: Signal that fabric will perform an ack target_put_sess_cmd()
*/ */
int target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd, int target_get_sess_cmd(struct se_cmd *se_cmd, bool ack_kref)
bool ack_kref)
{ {
struct se_session *se_sess = se_cmd->se_sess;
unsigned long flags; unsigned long flags;
int ret = 0; int ret = 0;
@ -2492,7 +2459,7 @@ out:
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
if (ret && ack_kref) if (ret && ack_kref)
target_put_sess_cmd(se_sess, se_cmd); target_put_sess_cmd(se_cmd);
return ret; return ret;
} }
@ -2521,11 +2488,12 @@ static void target_release_cmd_kref(struct kref *kref)
} }
/* target_put_sess_cmd - Check for active I/O shutdown via kref_put /* target_put_sess_cmd - Check for active I/O shutdown via kref_put
* @se_sess: session to reference
* @se_cmd: command descriptor to drop * @se_cmd: command descriptor to drop
*/ */
int target_put_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd) int target_put_sess_cmd(struct se_cmd *se_cmd)
{ {
struct se_session *se_sess = se_cmd->se_sess;
if (!se_sess) { if (!se_sess) {
se_cmd->se_tfo->release_cmd(se_cmd); se_cmd->se_tfo->release_cmd(se_cmd);
return 1; return 1;
@ -2591,31 +2559,10 @@ void target_wait_for_sess_cmds(struct se_session *se_sess)
} }
EXPORT_SYMBOL(target_wait_for_sess_cmds); EXPORT_SYMBOL(target_wait_for_sess_cmds);
static int transport_clear_lun_ref_thread(void *p) void transport_clear_lun_ref(struct se_lun *lun)
{ {
struct se_lun *lun = p;
percpu_ref_kill(&lun->lun_ref); percpu_ref_kill(&lun->lun_ref);
wait_for_completion(&lun->lun_ref_comp); wait_for_completion(&lun->lun_ref_comp);
complete(&lun->lun_shutdown_comp);
return 0;
}
int transport_clear_lun_ref(struct se_lun *lun)
{
struct task_struct *kt;
kt = kthread_run(transport_clear_lun_ref_thread, lun,
"tcm_cl_%u", lun->unpacked_lun);
if (IS_ERR(kt)) {
pr_err("Unable to start clear_lun thread\n");
return PTR_ERR(kt);
}
wait_for_completion(&lun->lun_shutdown_comp);
return 0;
} }
/** /**
@ -2649,10 +2596,8 @@ bool transport_wait_for_tasks(struct se_cmd *cmd)
cmd->transport_state |= CMD_T_STOP; cmd->transport_state |= CMD_T_STOP;
pr_debug("wait_for_tasks: Stopping %p ITT: 0x%08x" pr_debug("wait_for_tasks: Stopping %p ITT: 0x%08llx i_state: %d, t_state: %d, CMD_T_STOP\n",
" i_state: %d, t_state: %d, CMD_T_STOP\n", cmd, cmd->tag, cmd->se_tfo->get_cmd_state(cmd), cmd->t_state);
cmd, cmd->se_tfo->get_task_tag(cmd),
cmd->se_tfo->get_cmd_state(cmd), cmd->t_state);
spin_unlock_irqrestore(&cmd->t_state_lock, flags); spin_unlock_irqrestore(&cmd->t_state_lock, flags);
@ -2661,9 +2606,8 @@ bool transport_wait_for_tasks(struct se_cmd *cmd)
spin_lock_irqsave(&cmd->t_state_lock, flags); spin_lock_irqsave(&cmd->t_state_lock, flags);
cmd->transport_state &= ~(CMD_T_ACTIVE | CMD_T_STOP); cmd->transport_state &= ~(CMD_T_ACTIVE | CMD_T_STOP);
pr_debug("wait_for_tasks: Stopped wait_for_completion(" pr_debug("wait_for_tasks: Stopped wait_for_completion(&cmd->t_transport_stop_comp) for ITT: 0x%08llx\n",
"&cmd->t_transport_stop_comp) for ITT: 0x%08x\n", cmd->tag);
cmd->se_tfo->get_task_tag(cmd));
spin_unlock_irqrestore(&cmd->t_state_lock, flags); spin_unlock_irqrestore(&cmd->t_state_lock, flags);
@ -2965,8 +2909,8 @@ int transport_check_aborted_status(struct se_cmd *cmd, int send_status)
if (!send_status || !(cmd->se_cmd_flags & SCF_SEND_DELAYED_TAS)) if (!send_status || !(cmd->se_cmd_flags & SCF_SEND_DELAYED_TAS))
return 1; return 1;
pr_debug("Sending delayed SAM_STAT_TASK_ABORTED status for CDB: 0x%02x ITT: 0x%08x\n", pr_debug("Sending delayed SAM_STAT_TASK_ABORTED status for CDB: 0x%02x ITT: 0x%08llx\n",
cmd->t_task_cdb[0], cmd->se_tfo->get_task_tag(cmd)); cmd->t_task_cdb[0], cmd->tag);
cmd->se_cmd_flags &= ~SCF_SEND_DELAYED_TAS; cmd->se_cmd_flags &= ~SCF_SEND_DELAYED_TAS;
cmd->scsi_status = SAM_STAT_TASK_ABORTED; cmd->scsi_status = SAM_STAT_TASK_ABORTED;
@ -3005,9 +2949,8 @@ void transport_send_task_abort(struct se_cmd *cmd)
transport_lun_remove_cmd(cmd); transport_lun_remove_cmd(cmd);
pr_debug("Setting SAM_STAT_TASK_ABORTED status for CDB: 0x%02x," pr_debug("Setting SAM_STAT_TASK_ABORTED status for CDB: 0x%02x, ITT: 0x%08llx\n",
" ITT: 0x%08x\n", cmd->t_task_cdb[0], cmd->t_task_cdb[0], cmd->tag);
cmd->se_tfo->get_task_tag(cmd));
trace_target_cmd_complete(cmd); trace_target_cmd_complete(cmd);
cmd->se_tfo->queue_status(cmd); cmd->se_tfo->queue_status(cmd);
@ -3033,6 +2976,11 @@ static void target_tmr_work(struct work_struct *work)
ret = core_tmr_lun_reset(dev, tmr, NULL, NULL); ret = core_tmr_lun_reset(dev, tmr, NULL, NULL);
tmr->response = (!ret) ? TMR_FUNCTION_COMPLETE : tmr->response = (!ret) ? TMR_FUNCTION_COMPLETE :
TMR_FUNCTION_REJECTED; TMR_FUNCTION_REJECTED;
if (tmr->response == TMR_FUNCTION_COMPLETE) {
target_ua_allocate_lun(cmd->se_sess->se_node_acl,
cmd->orig_fe_lun, 0x29,
ASCQ_29H_BUS_DEVICE_RESET_FUNCTION_OCCURRED);
}
break; break;
case TMR_TARGET_WARM_RESET: case TMR_TARGET_WARM_RESET:
tmr->response = TMR_FUNCTION_REJECTED; tmr->response = TMR_FUNCTION_REJECTED;
@ -3067,3 +3015,22 @@ int transport_generic_handle_tmr(
return 0; return 0;
} }
EXPORT_SYMBOL(transport_generic_handle_tmr); EXPORT_SYMBOL(transport_generic_handle_tmr);
bool
target_check_wce(struct se_device *dev)
{
bool wce = false;
if (dev->transport->get_write_cache)
wce = dev->transport->get_write_cache(dev);
else if (dev->dev_attrib.emulate_write_cache > 0)
wce = true;
return wce;
}
bool
target_check_fua(struct se_device *dev)
{
return target_check_wce(dev) && dev->dev_attrib.emulate_fua_write > 0;
}

View File

@ -29,7 +29,6 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
#include "target_core_internal.h" #include "target_core_internal.h"
#include "target_core_alua.h" #include "target_core_alua.h"
@ -50,9 +49,17 @@ target_scsi3_ua_check(struct se_cmd *cmd)
if (!nacl) if (!nacl)
return 0; return 0;
deve = nacl->device_list[cmd->orig_fe_lun]; rcu_read_lock();
if (!atomic_read(&deve->ua_count)) deve = target_nacl_find_deve(nacl, cmd->orig_fe_lun);
if (!deve) {
rcu_read_unlock();
return 0; return 0;
}
if (!atomic_read(&deve->ua_count)) {
rcu_read_unlock();
return 0;
}
rcu_read_unlock();
/* /*
* From sam4r14, section 5.14 Unit attention condition: * From sam4r14, section 5.14 Unit attention condition:
* *
@ -79,18 +86,11 @@ target_scsi3_ua_check(struct se_cmd *cmd)
} }
int core_scsi3_ua_allocate( int core_scsi3_ua_allocate(
struct se_node_acl *nacl, struct se_dev_entry *deve,
u32 unpacked_lun,
u8 asc, u8 asc,
u8 ascq) u8 ascq)
{ {
struct se_dev_entry *deve;
struct se_ua *ua, *ua_p, *ua_tmp; struct se_ua *ua, *ua_p, *ua_tmp;
/*
* PASSTHROUGH OPS
*/
if (!nacl)
return -EINVAL;
ua = kmem_cache_zalloc(se_ua_cache, GFP_ATOMIC); ua = kmem_cache_zalloc(se_ua_cache, GFP_ATOMIC);
if (!ua) { if (!ua) {
@ -99,13 +99,9 @@ int core_scsi3_ua_allocate(
} }
INIT_LIST_HEAD(&ua->ua_nacl_list); INIT_LIST_HEAD(&ua->ua_nacl_list);
ua->ua_nacl = nacl;
ua->ua_asc = asc; ua->ua_asc = asc;
ua->ua_ascq = ascq; ua->ua_ascq = ascq;
spin_lock_irq(&nacl->device_list_lock);
deve = nacl->device_list[unpacked_lun];
spin_lock(&deve->ua_lock); spin_lock(&deve->ua_lock);
list_for_each_entry_safe(ua_p, ua_tmp, &deve->ua_list, ua_nacl_list) { list_for_each_entry_safe(ua_p, ua_tmp, &deve->ua_list, ua_nacl_list) {
/* /*
@ -113,7 +109,6 @@ int core_scsi3_ua_allocate(
*/ */
if ((ua_p->ua_asc == asc) && (ua_p->ua_ascq == ascq)) { if ((ua_p->ua_asc == asc) && (ua_p->ua_ascq == ascq)) {
spin_unlock(&deve->ua_lock); spin_unlock(&deve->ua_lock);
spin_unlock_irq(&nacl->device_list_lock);
kmem_cache_free(se_ua_cache, ua); kmem_cache_free(se_ua_cache, ua);
return 0; return 0;
} }
@ -158,24 +153,40 @@ int core_scsi3_ua_allocate(
list_add_tail(&ua->ua_nacl_list, list_add_tail(&ua->ua_nacl_list,
&deve->ua_list); &deve->ua_list);
spin_unlock(&deve->ua_lock); spin_unlock(&deve->ua_lock);
spin_unlock_irq(&nacl->device_list_lock);
atomic_inc_mb(&deve->ua_count); atomic_inc_mb(&deve->ua_count);
return 0; return 0;
} }
list_add_tail(&ua->ua_nacl_list, &deve->ua_list); list_add_tail(&ua->ua_nacl_list, &deve->ua_list);
spin_unlock(&deve->ua_lock); spin_unlock(&deve->ua_lock);
spin_unlock_irq(&nacl->device_list_lock);
pr_debug("[%s]: Allocated UNIT ATTENTION, mapped LUN: %u, ASC:" pr_debug("Allocated UNIT ATTENTION, mapped LUN: %llu, ASC:"
" 0x%02x, ASCQ: 0x%02x\n", " 0x%02x, ASCQ: 0x%02x\n", deve->mapped_lun,
nacl->se_tpg->se_tpg_tfo->get_fabric_name(), unpacked_lun,
asc, ascq); asc, ascq);
atomic_inc_mb(&deve->ua_count); atomic_inc_mb(&deve->ua_count);
return 0; return 0;
} }
void target_ua_allocate_lun(struct se_node_acl *nacl,
u32 unpacked_lun, u8 asc, u8 ascq)
{
struct se_dev_entry *deve;
if (!nacl)
return;
rcu_read_lock();
deve = target_nacl_find_deve(nacl, unpacked_lun);
if (!deve) {
rcu_read_unlock();
return;
}
core_scsi3_ua_allocate(deve, asc, ascq);
rcu_read_unlock();
}
void core_scsi3_ua_release_all( void core_scsi3_ua_release_all(
struct se_dev_entry *deve) struct se_dev_entry *deve)
{ {
@ -210,10 +221,14 @@ void core_scsi3_ua_for_check_condition(
if (!nacl) if (!nacl)
return; return;
spin_lock_irq(&nacl->device_list_lock); rcu_read_lock();
deve = nacl->device_list[cmd->orig_fe_lun]; deve = target_nacl_find_deve(nacl, cmd->orig_fe_lun);
if (!deve) {
rcu_read_unlock();
return;
}
if (!atomic_read(&deve->ua_count)) { if (!atomic_read(&deve->ua_count)) {
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return; return;
} }
/* /*
@ -249,10 +264,10 @@ void core_scsi3_ua_for_check_condition(
atomic_dec_mb(&deve->ua_count); atomic_dec_mb(&deve->ua_count);
} }
spin_unlock(&deve->ua_lock); spin_unlock(&deve->ua_lock);
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
pr_debug("[%s]: %s UNIT ATTENTION condition with" pr_debug("[%s]: %s UNIT ATTENTION condition with"
" INTLCK_CTRL: %d, mapped LUN: %u, got CDB: 0x%02x" " INTLCK_CTRL: %d, mapped LUN: %llu, got CDB: 0x%02x"
" reported ASC: 0x%02x, ASCQ: 0x%02x\n", " reported ASC: 0x%02x, ASCQ: 0x%02x\n",
nacl->se_tpg->se_tpg_tfo->get_fabric_name(), nacl->se_tpg->se_tpg_tfo->get_fabric_name(),
(dev->dev_attrib.emulate_ua_intlck_ctrl != 0) ? "Reporting" : (dev->dev_attrib.emulate_ua_intlck_ctrl != 0) ? "Reporting" :
@ -278,10 +293,14 @@ int core_scsi3_ua_clear_for_request_sense(
if (!nacl) if (!nacl)
return -EINVAL; return -EINVAL;
spin_lock_irq(&nacl->device_list_lock); rcu_read_lock();
deve = nacl->device_list[cmd->orig_fe_lun]; deve = target_nacl_find_deve(nacl, cmd->orig_fe_lun);
if (!deve) {
rcu_read_unlock();
return -EINVAL;
}
if (!atomic_read(&deve->ua_count)) { if (!atomic_read(&deve->ua_count)) {
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
return -EPERM; return -EPERM;
} }
/* /*
@ -307,10 +326,10 @@ int core_scsi3_ua_clear_for_request_sense(
atomic_dec_mb(&deve->ua_count); atomic_dec_mb(&deve->ua_count);
} }
spin_unlock(&deve->ua_lock); spin_unlock(&deve->ua_lock);
spin_unlock_irq(&nacl->device_list_lock); rcu_read_unlock();
pr_debug("[%s]: Released UNIT ATTENTION condition, mapped" pr_debug("[%s]: Released UNIT ATTENTION condition, mapped"
" LUN: %u, got REQUEST_SENSE reported ASC: 0x%02x," " LUN: %llu, got REQUEST_SENSE reported ASC: 0x%02x,"
" ASCQ: 0x%02x\n", nacl->se_tpg->se_tpg_tfo->get_fabric_name(), " ASCQ: 0x%02x\n", nacl->se_tpg->se_tpg_tfo->get_fabric_name(),
cmd->orig_fe_lun, *asc, *ascq); cmd->orig_fe_lun, *asc, *ascq);

View File

@ -25,10 +25,14 @@
#define ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS 0x09 #define ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS 0x09
#define ASCQ_3FH_INQUIRY_DATA_HAS_CHANGED 0x03
#define ASCQ_3FH_REPORTED_LUNS_DATA_HAS_CHANGED 0x0E
extern struct kmem_cache *se_ua_cache; extern struct kmem_cache *se_ua_cache;
extern sense_reason_t target_scsi3_ua_check(struct se_cmd *); extern sense_reason_t target_scsi3_ua_check(struct se_cmd *);
extern int core_scsi3_ua_allocate(struct se_node_acl *, u32, u8, u8); extern int core_scsi3_ua_allocate(struct se_dev_entry *, u8, u8);
extern void target_ua_allocate_lun(struct se_node_acl *, u32, u8, u8);
extern void core_scsi3_ua_release_all(struct se_dev_entry *); extern void core_scsi3_ua_release_all(struct se_dev_entry *);
extern void core_scsi3_ua_for_check_condition(struct se_cmd *, u8 *, u8 *); extern void core_scsi3_ua_for_check_condition(struct se_cmd *, u8 *, u8 *);
extern int core_scsi3_ua_clear_for_request_sense(struct se_cmd *, extern int core_scsi3_ua_clear_for_request_sense(struct se_cmd *,

View File

@ -1,6 +1,7 @@
/* /*
* Copyright (C) 2013 Shaohua Li <shli@kernel.org> * Copyright (C) 2013 Shaohua Li <shli@kernel.org>
* Copyright (C) 2014 Red Hat, Inc. * Copyright (C) 2014 Red Hat, Inc.
* Copyright (C) 2015 Arrikto, Inc.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@ -30,7 +31,6 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/target_core_backend.h> #include <target/target_core_backend.h>
#include <target/target_core_backend_configfs.h>
#include <linux/target_core_user.h> #include <linux/target_core_user.h>
@ -168,6 +168,11 @@ static struct tcmu_cmd *tcmu_alloc_cmd(struct se_cmd *se_cmd)
tcmu_cmd->tcmu_dev = udev; tcmu_cmd->tcmu_dev = udev;
tcmu_cmd->data_length = se_cmd->data_length; tcmu_cmd->data_length = se_cmd->data_length;
if (se_cmd->se_cmd_flags & SCF_BIDI) {
BUG_ON(!(se_cmd->t_bidi_data_sg && se_cmd->t_bidi_data_nents));
tcmu_cmd->data_length += se_cmd->t_bidi_data_sg->length;
}
tcmu_cmd->deadline = jiffies + msecs_to_jiffies(TCMU_TIME_OUT); tcmu_cmd->deadline = jiffies + msecs_to_jiffies(TCMU_TIME_OUT);
idr_preload(GFP_KERNEL); idr_preload(GFP_KERNEL);
@ -226,9 +231,106 @@ static inline size_t head_to_end(size_t head, size_t size)
#define UPDATE_HEAD(head, used, size) smp_store_release(&head, ((head % size) + used) % size) #define UPDATE_HEAD(head, used, size) smp_store_release(&head, ((head % size) + used) % size)
static void alloc_and_scatter_data_area(struct tcmu_dev *udev,
struct scatterlist *data_sg, unsigned int data_nents,
struct iovec **iov, int *iov_cnt, bool copy_data)
{
int i;
void *from, *to;
size_t copy_bytes;
struct scatterlist *sg;
for_each_sg(data_sg, sg, data_nents, i) {
copy_bytes = min_t(size_t, sg->length,
head_to_end(udev->data_head, udev->data_size));
from = kmap_atomic(sg_page(sg)) + sg->offset;
to = (void *) udev->mb_addr + udev->data_off + udev->data_head;
if (copy_data) {
memcpy(to, from, copy_bytes);
tcmu_flush_dcache_range(to, copy_bytes);
}
/* Even iov_base is relative to mb_addr */
(*iov)->iov_len = copy_bytes;
(*iov)->iov_base = (void __user *) udev->data_off +
udev->data_head;
(*iov_cnt)++;
(*iov)++;
UPDATE_HEAD(udev->data_head, copy_bytes, udev->data_size);
/* Uh oh, we wrapped the buffer. Must split sg across 2 iovs. */
if (sg->length != copy_bytes) {
void *from_skip = from + copy_bytes;
copy_bytes = sg->length - copy_bytes;
(*iov)->iov_len = copy_bytes;
(*iov)->iov_base = (void __user *) udev->data_off +
udev->data_head;
if (copy_data) {
to = (void *) udev->mb_addr +
udev->data_off + udev->data_head;
memcpy(to, from_skip, copy_bytes);
tcmu_flush_dcache_range(to, copy_bytes);
}
(*iov_cnt)++;
(*iov)++;
UPDATE_HEAD(udev->data_head,
copy_bytes, udev->data_size);
}
kunmap_atomic(from - sg->offset);
}
}
static void gather_and_free_data_area(struct tcmu_dev *udev,
struct scatterlist *data_sg, unsigned int data_nents)
{
int i;
void *from, *to;
size_t copy_bytes;
struct scatterlist *sg;
/* It'd be easier to look at entry's iovec again, but UAM */
for_each_sg(data_sg, sg, data_nents, i) {
copy_bytes = min_t(size_t, sg->length,
head_to_end(udev->data_tail, udev->data_size));
to = kmap_atomic(sg_page(sg)) + sg->offset;
WARN_ON(sg->length + sg->offset > PAGE_SIZE);
from = (void *) udev->mb_addr +
udev->data_off + udev->data_tail;
tcmu_flush_dcache_range(from, copy_bytes);
memcpy(to, from, copy_bytes);
UPDATE_HEAD(udev->data_tail, copy_bytes, udev->data_size);
/* Uh oh, wrapped the data buffer for this sg's data */
if (sg->length != copy_bytes) {
void *to_skip = to + copy_bytes;
from = (void *) udev->mb_addr +
udev->data_off + udev->data_tail;
WARN_ON(udev->data_tail);
copy_bytes = sg->length - copy_bytes;
tcmu_flush_dcache_range(from, copy_bytes);
memcpy(to_skip, from, copy_bytes);
UPDATE_HEAD(udev->data_tail,
copy_bytes, udev->data_size);
}
kunmap_atomic(to - sg->offset);
}
}
/* /*
* We can't queue a command until we have space available on the cmd ring *and* space * We can't queue a command until we have space available on the cmd ring *and*
* space avail on the data ring. * space available on the data ring.
* *
* Called with ring lock held. * Called with ring lock held.
*/ */
@ -276,12 +378,11 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
size_t base_command_size, command_size; size_t base_command_size, command_size;
struct tcmu_mailbox *mb; struct tcmu_mailbox *mb;
struct tcmu_cmd_entry *entry; struct tcmu_cmd_entry *entry;
int i;
struct scatterlist *sg;
struct iovec *iov; struct iovec *iov;
int iov_cnt = 0; int iov_cnt;
uint32_t cmd_head; uint32_t cmd_head;
uint64_t cdb_off; uint64_t cdb_off;
bool copy_to_data_area;
if (test_bit(TCMU_DEV_BIT_BROKEN, &udev->flags)) if (test_bit(TCMU_DEV_BIT_BROKEN, &udev->flags))
return -EINVAL; return -EINVAL;
@ -294,7 +395,8 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
* b/c size == offsetof one-past-element. * b/c size == offsetof one-past-element.
*/ */
base_command_size = max(offsetof(struct tcmu_cmd_entry, base_command_size = max(offsetof(struct tcmu_cmd_entry,
req.iov[se_cmd->t_data_nents + 2]), req.iov[se_cmd->t_bidi_data_nents +
se_cmd->t_data_nents + 2]),
sizeof(struct tcmu_cmd_entry)); sizeof(struct tcmu_cmd_entry));
command_size = base_command_size command_size = base_command_size
+ round_up(scsi_command_size(se_cmd->t_task_cdb), TCMU_OP_ALIGN_SIZE); + round_up(scsi_command_size(se_cmd->t_task_cdb), TCMU_OP_ALIGN_SIZE);
@ -362,53 +464,20 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
* Fix up iovecs, and handle if allocation in data ring wrapped. * Fix up iovecs, and handle if allocation in data ring wrapped.
*/ */
iov = &entry->req.iov[0]; iov = &entry->req.iov[0];
for_each_sg(se_cmd->t_data_sg, sg, se_cmd->t_data_nents, i) { iov_cnt = 0;
size_t copy_bytes = min((size_t)sg->length, copy_to_data_area = (se_cmd->data_direction == DMA_TO_DEVICE
head_to_end(udev->data_head, udev->data_size)); || se_cmd->se_cmd_flags & SCF_BIDI);
void *from = kmap_atomic(sg_page(sg)) + sg->offset; alloc_and_scatter_data_area(udev, se_cmd->t_data_sg,
void *to = (void *) mb + udev->data_off + udev->data_head; se_cmd->t_data_nents, &iov, &iov_cnt, copy_to_data_area);
if (tcmu_cmd->se_cmd->data_direction == DMA_TO_DEVICE) {
memcpy(to, from, copy_bytes);
tcmu_flush_dcache_range(to, copy_bytes);
}
/* Even iov_base is relative to mb_addr */
iov->iov_len = copy_bytes;
iov->iov_base = (void __user *) udev->data_off +
udev->data_head;
iov_cnt++;
iov++;
UPDATE_HEAD(udev->data_head, copy_bytes, udev->data_size);
/* Uh oh, we wrapped the buffer. Must split sg across 2 iovs. */
if (sg->length != copy_bytes) {
from += copy_bytes;
copy_bytes = sg->length - copy_bytes;
iov->iov_len = copy_bytes;
iov->iov_base = (void __user *) udev->data_off +
udev->data_head;
if (se_cmd->data_direction == DMA_TO_DEVICE) {
to = (void *) mb + udev->data_off + udev->data_head;
memcpy(to, from, copy_bytes);
tcmu_flush_dcache_range(to, copy_bytes);
}
iov_cnt++;
iov++;
UPDATE_HEAD(udev->data_head, copy_bytes, udev->data_size);
}
kunmap_atomic(from);
}
entry->req.iov_cnt = iov_cnt; entry->req.iov_cnt = iov_cnt;
entry->req.iov_bidi_cnt = 0;
entry->req.iov_dif_cnt = 0; entry->req.iov_dif_cnt = 0;
/* Handle BIDI commands */
iov_cnt = 0;
alloc_and_scatter_data_area(udev, se_cmd->t_bidi_data_sg,
se_cmd->t_bidi_data_nents, &iov, &iov_cnt, false);
entry->req.iov_bidi_cnt = iov_cnt;
/* All offsets relative to mb_addr, not start of entry! */ /* All offsets relative to mb_addr, not start of entry! */
cdb_off = CMDR_OFF + cmd_head + base_command_size; cdb_off = CMDR_OFF + cmd_head + base_command_size;
memcpy((void *) mb + cdb_off, se_cmd->t_task_cdb, scsi_command_size(se_cmd->t_task_cdb)); memcpy((void *) mb + cdb_off, se_cmd->t_task_cdb, scsi_command_size(se_cmd->t_task_cdb));
@ -481,47 +550,22 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry *
se_cmd->scsi_sense_length); se_cmd->scsi_sense_length);
UPDATE_HEAD(udev->data_tail, cmd->data_length, udev->data_size); UPDATE_HEAD(udev->data_tail, cmd->data_length, udev->data_size);
} } else if (se_cmd->se_cmd_flags & SCF_BIDI) {
else if (se_cmd->data_direction == DMA_FROM_DEVICE) { /* Discard data_out buffer */
struct scatterlist *sg; UPDATE_HEAD(udev->data_tail,
int i; (size_t)se_cmd->t_data_sg->length, udev->data_size);
/* It'd be easier to look at entry's iovec again, but UAM */
for_each_sg(se_cmd->t_data_sg, sg, se_cmd->t_data_nents, i) {
size_t copy_bytes;
void *to;
void *from;
copy_bytes = min((size_t)sg->length,
head_to_end(udev->data_tail, udev->data_size));
to = kmap_atomic(sg_page(sg)) + sg->offset;
WARN_ON(sg->length + sg->offset > PAGE_SIZE);
from = (void *) udev->mb_addr + udev->data_off + udev->data_tail;
tcmu_flush_dcache_range(from, copy_bytes);
memcpy(to, from, copy_bytes);
UPDATE_HEAD(udev->data_tail, copy_bytes, udev->data_size);
/* Uh oh, wrapped the data buffer for this sg's data */
if (sg->length != copy_bytes) {
from = (void *) udev->mb_addr + udev->data_off + udev->data_tail;
WARN_ON(udev->data_tail);
to += copy_bytes;
copy_bytes = sg->length - copy_bytes;
tcmu_flush_dcache_range(from, copy_bytes);
memcpy(to, from, copy_bytes);
UPDATE_HEAD(udev->data_tail, copy_bytes, udev->data_size);
}
kunmap_atomic(to);
}
/* Get Data-In buffer */
gather_and_free_data_area(udev,
se_cmd->t_bidi_data_sg, se_cmd->t_bidi_data_nents);
} else if (se_cmd->data_direction == DMA_FROM_DEVICE) {
gather_and_free_data_area(udev,
se_cmd->t_data_sg, se_cmd->t_data_nents);
} else if (se_cmd->data_direction == DMA_TO_DEVICE) { } else if (se_cmd->data_direction == DMA_TO_DEVICE) {
UPDATE_HEAD(udev->data_tail, cmd->data_length, udev->data_size); UPDATE_HEAD(udev->data_tail, cmd->data_length, udev->data_size);
} else { } else if (se_cmd->data_direction != DMA_NONE) {
pr_warn("TCMU: data direction was %d!\n", se_cmd->data_direction); pr_warn("TCMU: data direction was %d!\n",
se_cmd->data_direction);
} }
target_complete_cmd(cmd->se_cmd, entry->rsp.scsi_status); target_complete_cmd(cmd->se_cmd, entry->rsp.scsi_status);
@ -910,6 +954,14 @@ static int tcmu_check_pending_cmd(int id, void *p, void *data)
return -EINVAL; return -EINVAL;
} }
static void tcmu_dev_call_rcu(struct rcu_head *p)
{
struct se_device *dev = container_of(p, struct se_device, rcu_head);
struct tcmu_dev *udev = TCMU_DEV(dev);
kfree(udev);
}
static void tcmu_free_device(struct se_device *dev) static void tcmu_free_device(struct se_device *dev)
{ {
struct tcmu_dev *udev = TCMU_DEV(dev); struct tcmu_dev *udev = TCMU_DEV(dev);
@ -935,8 +987,7 @@ static void tcmu_free_device(struct se_device *dev)
kfree(udev->uio_info.name); kfree(udev->uio_info.name);
kfree(udev->name); kfree(udev->name);
} }
call_rcu(&dev->rcu_head, tcmu_dev_call_rcu);
kfree(udev);
} }
enum { enum {
@ -1054,27 +1105,7 @@ tcmu_parse_cdb(struct se_cmd *cmd)
return passthrough_parse_cdb(cmd, tcmu_pass_op); return passthrough_parse_cdb(cmd, tcmu_pass_op);
} }
DEF_TB_DEV_ATTRIB_RO(tcmu, hw_pi_prot_type); static const struct target_backend_ops tcmu_ops = {
TB_DEV_ATTR_RO(tcmu, hw_pi_prot_type);
DEF_TB_DEV_ATTRIB_RO(tcmu, hw_block_size);
TB_DEV_ATTR_RO(tcmu, hw_block_size);
DEF_TB_DEV_ATTRIB_RO(tcmu, hw_max_sectors);
TB_DEV_ATTR_RO(tcmu, hw_max_sectors);
DEF_TB_DEV_ATTRIB_RO(tcmu, hw_queue_depth);
TB_DEV_ATTR_RO(tcmu, hw_queue_depth);
static struct configfs_attribute *tcmu_backend_dev_attrs[] = {
&tcmu_dev_attrib_hw_pi_prot_type.attr,
&tcmu_dev_attrib_hw_block_size.attr,
&tcmu_dev_attrib_hw_max_sectors.attr,
&tcmu_dev_attrib_hw_queue_depth.attr,
NULL,
};
static struct se_subsystem_api tcmu_template = {
.name = "user", .name = "user",
.inquiry_prod = "USER", .inquiry_prod = "USER",
.inquiry_rev = TCMU_VERSION, .inquiry_rev = TCMU_VERSION,
@ -1090,11 +1121,11 @@ static struct se_subsystem_api tcmu_template = {
.show_configfs_dev_params = tcmu_show_configfs_dev_params, .show_configfs_dev_params = tcmu_show_configfs_dev_params,
.get_device_type = sbc_get_device_type, .get_device_type = sbc_get_device_type,
.get_blocks = tcmu_get_blocks, .get_blocks = tcmu_get_blocks,
.tb_dev_attrib_attrs = passthrough_attrib_attrs,
}; };
static int __init tcmu_module_init(void) static int __init tcmu_module_init(void)
{ {
struct target_backend_cits *tbc = &tcmu_template.tb_cits;
int ret; int ret;
BUILD_BUG_ON((sizeof(struct tcmu_cmd_entry) % TCMU_OP_ALIGN_SIZE) != 0); BUILD_BUG_ON((sizeof(struct tcmu_cmd_entry) % TCMU_OP_ALIGN_SIZE) != 0);
@ -1117,10 +1148,7 @@ static int __init tcmu_module_init(void)
goto out_unreg_device; goto out_unreg_device;
} }
target_core_setup_sub_cits(&tcmu_template); ret = transport_backend_register(&tcmu_ops);
tbc->tb_dev_attrib_cit.ct_attrs = tcmu_backend_dev_attrs;
ret = transport_subsystem_register(&tcmu_template);
if (ret) if (ret)
goto out_unreg_genl; goto out_unreg_genl;
@ -1138,7 +1166,7 @@ out_free_cache:
static void __exit tcmu_module_exit(void) static void __exit tcmu_module_exit(void)
{ {
transport_subsystem_release(&tcmu_template); target_backend_unregister(&tcmu_ops);
genl_unregister_family(&tcmu_genl_family); genl_unregister_family(&tcmu_genl_family);
root_device_unregister(tcmu_root_device); root_device_unregister(tcmu_root_device);
kmem_cache_destroy(tcmu_cmd_cache); kmem_cache_destroy(tcmu_cmd_cache);

View File

@ -31,7 +31,6 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_backend.h> #include <target/target_core_backend.h>
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
#include "target_core_internal.h" #include "target_core_internal.h"
#include "target_core_pr.h" #include "target_core_pr.h"
@ -348,8 +347,7 @@ struct xcopy_pt_cmd {
unsigned char sense_buffer[TRANSPORT_SENSE_BUFFER]; unsigned char sense_buffer[TRANSPORT_SENSE_BUFFER];
}; };
static struct se_port xcopy_pt_port; struct se_portal_group xcopy_pt_tpg;
static struct se_portal_group xcopy_pt_tpg;
static struct se_session xcopy_pt_sess; static struct se_session xcopy_pt_sess;
static struct se_node_acl xcopy_pt_nacl; static struct se_node_acl xcopy_pt_nacl;
@ -358,11 +356,6 @@ static char *xcopy_pt_get_fabric_name(void)
return "xcopy-pt"; return "xcopy-pt";
} }
static u32 xcopy_pt_get_tag(struct se_cmd *se_cmd)
{
return 0;
}
static int xcopy_pt_get_cmd_state(struct se_cmd *se_cmd) static int xcopy_pt_get_cmd_state(struct se_cmd *se_cmd)
{ {
return 0; return 0;
@ -423,7 +416,6 @@ static int xcopy_pt_queue_status(struct se_cmd *se_cmd)
static const struct target_core_fabric_ops xcopy_pt_tfo = { static const struct target_core_fabric_ops xcopy_pt_tfo = {
.get_fabric_name = xcopy_pt_get_fabric_name, .get_fabric_name = xcopy_pt_get_fabric_name,
.get_task_tag = xcopy_pt_get_tag,
.get_cmd_state = xcopy_pt_get_cmd_state, .get_cmd_state = xcopy_pt_get_cmd_state,
.release_cmd = xcopy_pt_release_cmd, .release_cmd = xcopy_pt_release_cmd,
.check_stop_free = xcopy_pt_check_stop_free, .check_stop_free = xcopy_pt_check_stop_free,
@ -445,17 +437,11 @@ int target_xcopy_setup_pt(void)
return -ENOMEM; return -ENOMEM;
} }
memset(&xcopy_pt_port, 0, sizeof(struct se_port));
INIT_LIST_HEAD(&xcopy_pt_port.sep_alua_list);
INIT_LIST_HEAD(&xcopy_pt_port.sep_list);
mutex_init(&xcopy_pt_port.sep_tg_pt_md_mutex);
memset(&xcopy_pt_tpg, 0, sizeof(struct se_portal_group)); memset(&xcopy_pt_tpg, 0, sizeof(struct se_portal_group));
INIT_LIST_HEAD(&xcopy_pt_tpg.se_tpg_node); INIT_LIST_HEAD(&xcopy_pt_tpg.se_tpg_node);
INIT_LIST_HEAD(&xcopy_pt_tpg.acl_node_list); INIT_LIST_HEAD(&xcopy_pt_tpg.acl_node_list);
INIT_LIST_HEAD(&xcopy_pt_tpg.tpg_sess_list); INIT_LIST_HEAD(&xcopy_pt_tpg.tpg_sess_list);
xcopy_pt_port.sep_tpg = &xcopy_pt_tpg;
xcopy_pt_tpg.se_tpg_tfo = &xcopy_pt_tfo; xcopy_pt_tpg.se_tpg_tfo = &xcopy_pt_tfo;
memset(&xcopy_pt_nacl, 0, sizeof(struct se_node_acl)); memset(&xcopy_pt_nacl, 0, sizeof(struct se_node_acl));
@ -496,10 +482,6 @@ static void target_xcopy_setup_pt_port(
*/ */
if (remote_port) { if (remote_port) {
xpt_cmd->remote_port = remote_port; xpt_cmd->remote_port = remote_port;
pt_cmd->se_lun->lun_sep = &xcopy_pt_port;
pr_debug("Setup emulated remote DEST xcopy_pt_port: %p to"
" cmd->se_lun->lun_sep for X-COPY data PUSH\n",
pt_cmd->se_lun->lun_sep);
} else { } else {
pt_cmd->se_lun = ec_cmd->se_lun; pt_cmd->se_lun = ec_cmd->se_lun;
pt_cmd->se_dev = ec_cmd->se_dev; pt_cmd->se_dev = ec_cmd->se_dev;
@ -519,10 +501,6 @@ static void target_xcopy_setup_pt_port(
*/ */
if (remote_port) { if (remote_port) {
xpt_cmd->remote_port = remote_port; xpt_cmd->remote_port = remote_port;
pt_cmd->se_lun->lun_sep = &xcopy_pt_port;
pr_debug("Setup emulated remote SRC xcopy_pt_port: %p to"
" cmd->se_lun->lun_sep for X-COPY data PULL\n",
pt_cmd->se_lun->lun_sep);
} else { } else {
pt_cmd->se_lun = ec_cmd->se_lun; pt_cmd->se_lun = ec_cmd->se_lun;
pt_cmd->se_dev = ec_cmd->se_dev; pt_cmd->se_dev = ec_cmd->se_dev;
@ -574,6 +552,7 @@ static int target_xcopy_setup_pt_cmd(
xpt_cmd->xcopy_op = xop; xpt_cmd->xcopy_op = xop;
target_xcopy_setup_pt_port(xpt_cmd, xop, remote_port); target_xcopy_setup_pt_port(xpt_cmd, xop, remote_port);
cmd->tag = 0;
sense_rc = target_setup_cmd_from_cdb(cmd, cdb); sense_rc = target_setup_cmd_from_cdb(cmd, cdb);
if (sense_rc) { if (sense_rc) {
ret = -EINVAL; ret = -EINVAL;

View File

@ -80,8 +80,8 @@ struct ft_node_auth {
* Node ACL for FC remote port session. * Node ACL for FC remote port session.
*/ */
struct ft_node_acl { struct ft_node_acl {
struct ft_node_auth node_auth;
struct se_node_acl se_node_acl; struct se_node_acl se_node_acl;
struct ft_node_auth node_auth;
}; };
struct ft_lun { struct ft_lun {
@ -157,7 +157,6 @@ int ft_queue_status(struct se_cmd *);
int ft_queue_data_in(struct se_cmd *); int ft_queue_data_in(struct se_cmd *);
int ft_write_pending(struct se_cmd *); int ft_write_pending(struct se_cmd *);
int ft_write_pending_status(struct se_cmd *); int ft_write_pending_status(struct se_cmd *);
u32 ft_get_task_tag(struct se_cmd *);
int ft_get_cmd_state(struct se_cmd *); int ft_get_cmd_state(struct se_cmd *);
void ft_queue_tm_resp(struct se_cmd *); void ft_queue_tm_resp(struct se_cmd *);
void ft_aborted_task(struct se_cmd *); void ft_aborted_task(struct se_cmd *);

View File

@ -36,7 +36,6 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
#include <target/configfs_macros.h> #include <target/configfs_macros.h>
#include "tcm_fc.h" #include "tcm_fc.h"
@ -243,15 +242,6 @@ int ft_write_pending(struct se_cmd *se_cmd)
return 0; return 0;
} }
u32 ft_get_task_tag(struct se_cmd *se_cmd)
{
struct ft_cmd *cmd = container_of(se_cmd, struct ft_cmd, se_cmd);
if (cmd->aborted)
return ~0;
return fc_seq_exch(cmd->seq)->rxid;
}
int ft_get_cmd_state(struct se_cmd *se_cmd) int ft_get_cmd_state(struct se_cmd *se_cmd)
{ {
return 0; return 0;
@ -564,6 +554,7 @@ static void ft_send_work(struct work_struct *work)
} }
fc_seq_exch(cmd->seq)->lp->tt.seq_set_resp(cmd->seq, ft_recv_seq, cmd); fc_seq_exch(cmd->seq)->lp->tt.seq_set_resp(cmd->seq, ft_recv_seq, cmd);
cmd->se_cmd.tag = fc_seq_exch(cmd->seq)->rxid;
/* /*
* Use a single se_cmd->cmd_kref as we expect to release se_cmd * Use a single se_cmd->cmd_kref as we expect to release se_cmd
* directly from ft_check_stop_free callback in response path. * directly from ft_check_stop_free callback in response path.

View File

@ -39,13 +39,10 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/target_core_fabric_configfs.h> #include <target/target_core_fabric_configfs.h>
#include <target/target_core_configfs.h>
#include <target/configfs_macros.h> #include <target/configfs_macros.h>
#include "tcm_fc.h" #include "tcm_fc.h"
static const struct target_core_fabric_ops ft_fabric_ops;
static LIST_HEAD(ft_wwn_list); static LIST_HEAD(ft_wwn_list);
DEFINE_MUTEX(ft_lport_lock); DEFINE_MUTEX(ft_lport_lock);
@ -194,48 +191,17 @@ static struct configfs_attribute *ft_nacl_base_attrs[] = {
* Add ACL for an initiator. The ACL is named arbitrarily. * Add ACL for an initiator. The ACL is named arbitrarily.
* The port_name and/or node_name are attributes. * The port_name and/or node_name are attributes.
*/ */
static struct se_node_acl *ft_add_acl( static int ft_init_nodeacl(struct se_node_acl *nacl, const char *name)
struct se_portal_group *se_tpg,
struct config_group *group,
const char *name)
{ {
struct ft_node_acl *acl; struct ft_node_acl *acl =
struct ft_tpg *tpg; container_of(nacl, struct ft_node_acl, se_node_acl);
u64 wwpn; u64 wwpn;
u32 q_depth;
pr_debug("add acl %s\n", name);
tpg = container_of(se_tpg, struct ft_tpg, se_tpg);
if (ft_parse_wwn(name, &wwpn, 1) < 0) if (ft_parse_wwn(name, &wwpn, 1) < 0)
return ERR_PTR(-EINVAL); return -EINVAL;
acl = kzalloc(sizeof(struct ft_node_acl), GFP_KERNEL);
if (!acl)
return ERR_PTR(-ENOMEM);
acl->node_auth.port_name = wwpn; acl->node_auth.port_name = wwpn;
return 0;
q_depth = 32; /* XXX bogus default - get from tpg? */
return core_tpg_add_initiator_node_acl(&tpg->se_tpg,
&acl->se_node_acl, name, q_depth);
}
static void ft_del_acl(struct se_node_acl *se_acl)
{
struct se_portal_group *se_tpg = se_acl->se_tpg;
struct ft_tpg *tpg;
struct ft_node_acl *acl = container_of(se_acl,
struct ft_node_acl, se_node_acl);
pr_debug("del acl %s\n",
config_item_name(&se_acl->acl_group.cg_item));
tpg = container_of(se_tpg, struct ft_tpg, se_tpg);
pr_debug("del acl %p se_acl %p tpg %p se_tpg %p\n",
acl, se_acl, tpg, &tpg->se_tpg);
core_tpg_del_initiator_node_acl(&tpg->se_tpg, se_acl, 1);
kfree(acl);
} }
struct ft_node_acl *ft_acl_get(struct ft_tpg *tpg, struct fc_rport_priv *rdata) struct ft_node_acl *ft_acl_get(struct ft_tpg *tpg, struct fc_rport_priv *rdata)
@ -245,7 +211,7 @@ struct ft_node_acl *ft_acl_get(struct ft_tpg *tpg, struct fc_rport_priv *rdata)
struct se_portal_group *se_tpg = &tpg->se_tpg; struct se_portal_group *se_tpg = &tpg->se_tpg;
struct se_node_acl *se_acl; struct se_node_acl *se_acl;
spin_lock_irq(&se_tpg->acl_node_lock); mutex_lock(&se_tpg->acl_node_mutex);
list_for_each_entry(se_acl, &se_tpg->acl_node_list, acl_list) { list_for_each_entry(se_acl, &se_tpg->acl_node_list, acl_list) {
acl = container_of(se_acl, struct ft_node_acl, se_node_acl); acl = container_of(se_acl, struct ft_node_acl, se_node_acl);
pr_debug("acl %p port_name %llx\n", pr_debug("acl %p port_name %llx\n",
@ -259,33 +225,10 @@ struct ft_node_acl *ft_acl_get(struct ft_tpg *tpg, struct fc_rport_priv *rdata)
break; break;
} }
} }
spin_unlock_irq(&se_tpg->acl_node_lock); mutex_unlock(&se_tpg->acl_node_mutex);
return found; return found;
} }
static struct se_node_acl *ft_tpg_alloc_fabric_acl(struct se_portal_group *se_tpg)
{
struct ft_node_acl *acl;
acl = kzalloc(sizeof(*acl), GFP_KERNEL);
if (!acl) {
pr_err("Unable to allocate struct ft_node_acl\n");
return NULL;
}
pr_debug("acl %p\n", acl);
return &acl->se_node_acl;
}
static void ft_tpg_release_fabric_acl(struct se_portal_group *se_tpg,
struct se_node_acl *se_acl)
{
struct ft_node_acl *acl = container_of(se_acl,
struct ft_node_acl, se_node_acl);
pr_debug("acl %p\n", acl);
kfree(acl);
}
/* /*
* local_port port_group (tpg) ops. * local_port port_group (tpg) ops.
*/ */
@ -333,8 +276,7 @@ static struct se_portal_group *ft_add_tpg(
return NULL; return NULL;
} }
ret = core_tpg_register(&ft_fabric_ops, wwn, &tpg->se_tpg, ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_FCP);
tpg, TRANSPORT_TPG_TYPE_NORMAL);
if (ret < 0) { if (ret < 0) {
destroy_workqueue(wq); destroy_workqueue(wq);
kfree(tpg); kfree(tpg);
@ -459,6 +401,11 @@ static struct configfs_attribute *ft_wwn_attrs[] = {
NULL, NULL,
}; };
static inline struct ft_tpg *ft_tpg(struct se_portal_group *se_tpg)
{
return container_of(se_tpg, struct ft_tpg, se_tpg);
}
static char *ft_get_fabric_name(void) static char *ft_get_fabric_name(void)
{ {
return "fc"; return "fc";
@ -466,25 +413,16 @@ static char *ft_get_fabric_name(void)
static char *ft_get_fabric_wwn(struct se_portal_group *se_tpg) static char *ft_get_fabric_wwn(struct se_portal_group *se_tpg)
{ {
struct ft_tpg *tpg = se_tpg->se_tpg_fabric_ptr; return ft_tpg(se_tpg)->lport_wwn->name;
return tpg->lport_wwn->name;
} }
static u16 ft_get_tag(struct se_portal_group *se_tpg) static u16 ft_get_tag(struct se_portal_group *se_tpg)
{ {
struct ft_tpg *tpg = se_tpg->se_tpg_fabric_ptr;
/* /*
* This tag is used when forming SCSI Name identifier in EVPD=1 0x83 * This tag is used when forming SCSI Name identifier in EVPD=1 0x83
* to represent the SCSI Target Port. * to represent the SCSI Target Port.
*/ */
return tpg->index; return ft_tpg(se_tpg)->index;
}
static u32 ft_get_default_depth(struct se_portal_group *se_tpg)
{
return 1;
} }
static int ft_check_false(struct se_portal_group *se_tpg) static int ft_check_false(struct se_portal_group *se_tpg)
@ -498,28 +436,20 @@ static void ft_set_default_node_attr(struct se_node_acl *se_nacl)
static u32 ft_tpg_get_inst_index(struct se_portal_group *se_tpg) static u32 ft_tpg_get_inst_index(struct se_portal_group *se_tpg)
{ {
struct ft_tpg *tpg = se_tpg->se_tpg_fabric_ptr; return ft_tpg(se_tpg)->index;
return tpg->index;
} }
static const struct target_core_fabric_ops ft_fabric_ops = { static const struct target_core_fabric_ops ft_fabric_ops = {
.module = THIS_MODULE, .module = THIS_MODULE,
.name = "fc", .name = "fc",
.node_acl_size = sizeof(struct ft_node_acl),
.get_fabric_name = ft_get_fabric_name, .get_fabric_name = ft_get_fabric_name,
.get_fabric_proto_ident = fc_get_fabric_proto_ident,
.tpg_get_wwn = ft_get_fabric_wwn, .tpg_get_wwn = ft_get_fabric_wwn,
.tpg_get_tag = ft_get_tag, .tpg_get_tag = ft_get_tag,
.tpg_get_default_depth = ft_get_default_depth,
.tpg_get_pr_transport_id = fc_get_pr_transport_id,
.tpg_get_pr_transport_id_len = fc_get_pr_transport_id_len,
.tpg_parse_pr_out_transport_id = fc_parse_pr_out_transport_id,
.tpg_check_demo_mode = ft_check_false, .tpg_check_demo_mode = ft_check_false,
.tpg_check_demo_mode_cache = ft_check_false, .tpg_check_demo_mode_cache = ft_check_false,
.tpg_check_demo_mode_write_protect = ft_check_false, .tpg_check_demo_mode_write_protect = ft_check_false,
.tpg_check_prod_mode_write_protect = ft_check_false, .tpg_check_prod_mode_write_protect = ft_check_false,
.tpg_alloc_fabric_acl = ft_tpg_alloc_fabric_acl,
.tpg_release_fabric_acl = ft_tpg_release_fabric_acl,
.tpg_get_inst_index = ft_tpg_get_inst_index, .tpg_get_inst_index = ft_tpg_get_inst_index,
.check_stop_free = ft_check_stop_free, .check_stop_free = ft_check_stop_free,
.release_cmd = ft_release_cmd, .release_cmd = ft_release_cmd,
@ -530,7 +460,6 @@ static const struct target_core_fabric_ops ft_fabric_ops = {
.write_pending = ft_write_pending, .write_pending = ft_write_pending,
.write_pending_status = ft_write_pending_status, .write_pending_status = ft_write_pending_status,
.set_default_node_attributes = ft_set_default_node_attr, .set_default_node_attributes = ft_set_default_node_attr,
.get_task_tag = ft_get_task_tag,
.get_cmd_state = ft_get_cmd_state, .get_cmd_state = ft_get_cmd_state,
.queue_data_in = ft_queue_data_in, .queue_data_in = ft_queue_data_in,
.queue_status = ft_queue_status, .queue_status = ft_queue_status,
@ -544,12 +473,7 @@ static const struct target_core_fabric_ops ft_fabric_ops = {
.fabric_drop_wwn = &ft_del_wwn, .fabric_drop_wwn = &ft_del_wwn,
.fabric_make_tpg = &ft_add_tpg, .fabric_make_tpg = &ft_add_tpg,
.fabric_drop_tpg = &ft_del_tpg, .fabric_drop_tpg = &ft_del_tpg,
.fabric_post_link = NULL, .fabric_init_nodeacl = &ft_init_nodeacl,
.fabric_pre_unlink = NULL,
.fabric_make_np = NULL,
.fabric_drop_np = NULL,
.fabric_make_nodeacl = &ft_add_acl,
.fabric_drop_nodeacl = &ft_del_acl,
.tfc_wwn_attrs = ft_wwn_attrs, .tfc_wwn_attrs = ft_wwn_attrs,
.tfc_tpg_nacl_base_attrs = ft_nacl_base_attrs, .tfc_tpg_nacl_base_attrs = ft_nacl_base_attrs,

View File

@ -44,7 +44,6 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
#include <target/configfs_macros.h> #include <target/configfs_macros.h>
#include "tcm_fc.h" #include "tcm_fc.h"

View File

@ -36,7 +36,6 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
#include <target/configfs_macros.h> #include <target/configfs_macros.h>
#include "tcm_fc.h" #include "tcm_fc.h"

View File

@ -20,7 +20,6 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/target_core_fabric_configfs.h> #include <target/target_core_fabric_configfs.h>
#include <target/target_core_configfs.h>
#include <target/configfs_macros.h> #include <target/configfs_macros.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
@ -28,8 +27,6 @@
USB_GADGET_COMPOSITE_OPTIONS(); USB_GADGET_COMPOSITE_OPTIONS();
static const struct target_core_fabric_ops usbg_ops;
static inline struct f_uas *to_f_uas(struct usb_function *f) static inline struct f_uas *to_f_uas(struct usb_function *f)
{ {
return container_of(f, struct f_uas, function); return container_of(f, struct f_uas, function);
@ -1111,6 +1108,7 @@ static int usbg_submit_command(struct f_uas *fu,
memcpy(cmd->cmd_buf, cmd_iu->cdb, cmd_len); memcpy(cmd->cmd_buf, cmd_iu->cdb, cmd_len);
cmd->tag = be16_to_cpup(&cmd_iu->tag); cmd->tag = be16_to_cpup(&cmd_iu->tag);
cmd->se_cmd.tag = cmd->tag;
if (fu->flags & USBG_USE_STREAMS) { if (fu->flags & USBG_USE_STREAMS) {
if (cmd->tag > UASP_SS_EP_COMP_NUM_STREAMS) if (cmd->tag > UASP_SS_EP_COMP_NUM_STREAMS)
goto err; goto err;
@ -1244,6 +1242,7 @@ static int bot_submit_command(struct f_uas *fu,
cmd->unpacked_lun = cbw->Lun; cmd->unpacked_lun = cbw->Lun;
cmd->is_read = cbw->Flags & US_BULK_FLAG_IN ? 1 : 0; cmd->is_read = cbw->Flags & US_BULK_FLAG_IN ? 1 : 0;
cmd->data_len = le32_to_cpu(cbw->DataTransferLength); cmd->data_len = le32_to_cpu(cbw->DataTransferLength);
cmd->se_cmd.tag = le32_to_cpu(cmd->bot_tag);
INIT_WORK(&cmd->work, bot_cmd_work); INIT_WORK(&cmd->work, bot_cmd_work);
ret = queue_work(tpg->workqueue, &cmd->work); ret = queue_work(tpg->workqueue, &cmd->work);
@ -1273,23 +1272,6 @@ static char *usbg_get_fabric_name(void)
return "usb_gadget"; return "usb_gadget";
} }
static u8 usbg_get_fabric_proto_ident(struct se_portal_group *se_tpg)
{
struct usbg_tpg *tpg = container_of(se_tpg,
struct usbg_tpg, se_tpg);
struct usbg_tport *tport = tpg->tport;
u8 proto_id;
switch (tport->tport_proto_id) {
case SCSI_PROTOCOL_SAS:
default:
proto_id = sas_get_fabric_proto_ident(se_tpg);
break;
}
return proto_id;
}
static char *usbg_get_fabric_wwn(struct se_portal_group *se_tpg) static char *usbg_get_fabric_wwn(struct se_portal_group *se_tpg)
{ {
struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg *tpg = container_of(se_tpg,
@ -1306,97 +1288,6 @@ static u16 usbg_get_tag(struct se_portal_group *se_tpg)
return tpg->tport_tpgt; return tpg->tport_tpgt;
} }
static u32 usbg_get_default_depth(struct se_portal_group *se_tpg)
{
return 1;
}
static u32 usbg_get_pr_transport_id(
struct se_portal_group *se_tpg,
struct se_node_acl *se_nacl,
struct t10_pr_registration *pr_reg,
int *format_code,
unsigned char *buf)
{
struct usbg_tpg *tpg = container_of(se_tpg,
struct usbg_tpg, se_tpg);
struct usbg_tport *tport = tpg->tport;
int ret = 0;
switch (tport->tport_proto_id) {
case SCSI_PROTOCOL_SAS:
default:
ret = sas_get_pr_transport_id(se_tpg, se_nacl, pr_reg,
format_code, buf);
break;
}
return ret;
}
static u32 usbg_get_pr_transport_id_len(
struct se_portal_group *se_tpg,
struct se_node_acl *se_nacl,
struct t10_pr_registration *pr_reg,
int *format_code)
{
struct usbg_tpg *tpg = container_of(se_tpg,
struct usbg_tpg, se_tpg);
struct usbg_tport *tport = tpg->tport;
int ret = 0;
switch (tport->tport_proto_id) {
case SCSI_PROTOCOL_SAS:
default:
ret = sas_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,
format_code);
break;
}
return ret;
}
static char *usbg_parse_pr_out_transport_id(
struct se_portal_group *se_tpg,
const char *buf,
u32 *out_tid_len,
char **port_nexus_ptr)
{
struct usbg_tpg *tpg = container_of(se_tpg,
struct usbg_tpg, se_tpg);
struct usbg_tport *tport = tpg->tport;
char *tid = NULL;
switch (tport->tport_proto_id) {
case SCSI_PROTOCOL_SAS:
default:
tid = sas_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,
port_nexus_ptr);
}
return tid;
}
static struct se_node_acl *usbg_alloc_fabric_acl(struct se_portal_group *se_tpg)
{
struct usbg_nacl *nacl;
nacl = kzalloc(sizeof(struct usbg_nacl), GFP_KERNEL);
if (!nacl)
return NULL;
return &nacl->se_node_acl;
}
static void usbg_release_fabric_acl(
struct se_portal_group *se_tpg,
struct se_node_acl *se_nacl)
{
struct usbg_nacl *nacl = container_of(se_nacl,
struct usbg_nacl, se_node_acl);
kfree(nacl);
}
static u32 usbg_tpg_get_inst_index(struct se_portal_group *se_tpg) static u32 usbg_tpg_get_inst_index(struct se_portal_group *se_tpg)
{ {
return 1; return 1;
@ -1447,18 +1338,6 @@ static void usbg_set_default_node_attrs(struct se_node_acl *nacl)
return; return;
} }
static u32 usbg_get_task_tag(struct se_cmd *se_cmd)
{
struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
se_cmd);
struct f_uas *fu = cmd->fu;
if (fu->flags & USBG_IS_BOT)
return le32_to_cpu(cmd->bot_tag);
else
return cmd->tag;
}
static int usbg_get_cmd_state(struct se_cmd *se_cmd) static int usbg_get_cmd_state(struct se_cmd *se_cmd)
{ {
return 0; return 0;
@ -1488,50 +1367,11 @@ static const char *usbg_check_wwn(const char *name)
return n; return n;
} }
static struct se_node_acl *usbg_make_nodeacl( static int usbg_init_nodeacl(struct se_node_acl *se_nacl, const char *name)
struct se_portal_group *se_tpg,
struct config_group *group,
const char *name)
{ {
struct se_node_acl *se_nacl, *se_nacl_new; if (!usbg_check_wwn(name))
struct usbg_nacl *nacl; return -EINVAL;
u64 wwpn = 0; return 0;
u32 nexus_depth;
const char *wnn_name;
wnn_name = usbg_check_wwn(name);
if (!wnn_name)
return ERR_PTR(-EINVAL);
se_nacl_new = usbg_alloc_fabric_acl(se_tpg);
if (!(se_nacl_new))
return ERR_PTR(-ENOMEM);
nexus_depth = 1;
/*
* se_nacl_new may be released by core_tpg_add_initiator_node_acl()
* when converting a NodeACL from demo mode -> explict
*/
se_nacl = core_tpg_add_initiator_node_acl(se_tpg, se_nacl_new,
name, nexus_depth);
if (IS_ERR(se_nacl)) {
usbg_release_fabric_acl(se_tpg, se_nacl_new);
return se_nacl;
}
/*
* Locate our struct usbg_nacl and set the FC Nport WWPN
*/
nacl = container_of(se_nacl, struct usbg_nacl, se_node_acl);
nacl->iport_wwpn = wwpn;
snprintf(nacl->iport_name, sizeof(nacl->iport_name), "%s", name);
return se_nacl;
}
static void usbg_drop_nodeacl(struct se_node_acl *se_acl)
{
struct usbg_nacl *nacl = container_of(se_acl,
struct usbg_nacl, se_node_acl);
core_tpg_del_initiator_node_acl(se_acl->se_tpg, se_acl, 1);
kfree(nacl);
} }
struct usbg_tpg *the_only_tpg_I_currently_have; struct usbg_tpg *the_only_tpg_I_currently_have;
@ -1571,8 +1411,11 @@ static struct se_portal_group *usbg_make_tpg(
tpg->tport = tport; tpg->tport = tport;
tpg->tport_tpgt = tpgt; tpg->tport_tpgt = tpgt;
ret = core_tpg_register(&usbg_ops, wwn, &tpg->se_tpg, tpg, /*
TRANSPORT_TPG_TYPE_NORMAL); * SPC doesn't assign a protocol identifier for USB-SCSI, so we
* pretend to be SAS..
*/
ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_SAS);
if (ret < 0) { if (ret < 0) {
destroy_workqueue(tpg->workqueue); destroy_workqueue(tpg->workqueue);
kfree(tpg); kfree(tpg);
@ -1866,19 +1709,12 @@ static const struct target_core_fabric_ops usbg_ops = {
.module = THIS_MODULE, .module = THIS_MODULE,
.name = "usb_gadget", .name = "usb_gadget",
.get_fabric_name = usbg_get_fabric_name, .get_fabric_name = usbg_get_fabric_name,
.get_fabric_proto_ident = usbg_get_fabric_proto_ident,
.tpg_get_wwn = usbg_get_fabric_wwn, .tpg_get_wwn = usbg_get_fabric_wwn,
.tpg_get_tag = usbg_get_tag, .tpg_get_tag = usbg_get_tag,
.tpg_get_default_depth = usbg_get_default_depth,
.tpg_get_pr_transport_id = usbg_get_pr_transport_id,
.tpg_get_pr_transport_id_len = usbg_get_pr_transport_id_len,
.tpg_parse_pr_out_transport_id = usbg_parse_pr_out_transport_id,
.tpg_check_demo_mode = usbg_check_true, .tpg_check_demo_mode = usbg_check_true,
.tpg_check_demo_mode_cache = usbg_check_false, .tpg_check_demo_mode_cache = usbg_check_false,
.tpg_check_demo_mode_write_protect = usbg_check_false, .tpg_check_demo_mode_write_protect = usbg_check_false,
.tpg_check_prod_mode_write_protect = usbg_check_false, .tpg_check_prod_mode_write_protect = usbg_check_false,
.tpg_alloc_fabric_acl = usbg_alloc_fabric_acl,
.tpg_release_fabric_acl = usbg_release_fabric_acl,
.tpg_get_inst_index = usbg_tpg_get_inst_index, .tpg_get_inst_index = usbg_tpg_get_inst_index,
.release_cmd = usbg_release_cmd, .release_cmd = usbg_release_cmd,
.shutdown_session = usbg_shutdown_session, .shutdown_session = usbg_shutdown_session,
@ -1888,7 +1724,6 @@ static const struct target_core_fabric_ops usbg_ops = {
.write_pending = usbg_send_write_request, .write_pending = usbg_send_write_request,
.write_pending_status = usbg_write_pending_status, .write_pending_status = usbg_write_pending_status,
.set_default_node_attributes = usbg_set_default_node_attrs, .set_default_node_attributes = usbg_set_default_node_attrs,
.get_task_tag = usbg_get_task_tag,
.get_cmd_state = usbg_get_cmd_state, .get_cmd_state = usbg_get_cmd_state,
.queue_data_in = usbg_send_read_response, .queue_data_in = usbg_send_read_response,
.queue_status = usbg_send_status_response, .queue_status = usbg_send_status_response,
@ -1902,10 +1737,7 @@ static const struct target_core_fabric_ops usbg_ops = {
.fabric_drop_tpg = usbg_drop_tpg, .fabric_drop_tpg = usbg_drop_tpg,
.fabric_post_link = usbg_port_link, .fabric_post_link = usbg_port_link,
.fabric_pre_unlink = usbg_port_unlink, .fabric_pre_unlink = usbg_port_unlink,
.fabric_make_np = NULL, .fabric_init_nodeacl = usbg_init_nodeacl,
.fabric_drop_np = NULL,
.fabric_make_nodeacl = usbg_make_nodeacl,
.fabric_drop_nodeacl = usbg_drop_nodeacl,
.tfc_wwn_attrs = usbg_wwn_attrs, .tfc_wwn_attrs = usbg_wwn_attrs,
.tfc_tpg_base_attrs = usbg_base_attrs, .tfc_tpg_base_attrs = usbg_base_attrs,

View File

@ -24,15 +24,6 @@ enum {
#define USB_G_ALT_INT_BBB 0 #define USB_G_ALT_INT_BBB 0
#define USB_G_ALT_INT_UAS 1 #define USB_G_ALT_INT_UAS 1
struct usbg_nacl {
/* Binary World Wide unique Port Name for SAS Initiator port */
u64 iport_wwpn;
/* ASCII formatted WWPN for Sas Initiator port */
char iport_name[USBG_NAMELEN];
/* Returned by usbg_make_nodeacl() */
struct se_node_acl se_node_acl;
};
struct tcm_usbg_nexus { struct tcm_usbg_nexus {
struct se_session *tvn_se_sess; struct se_session *tvn_se_sess;
}; };
@ -52,8 +43,6 @@ struct usbg_tpg {
}; };
struct usbg_tport { struct usbg_tport {
/* SCSI protocol the tport is providing */
u8 tport_proto_id;
/* Binary World Wide unique Port Name for SAS Target port */ /* Binary World Wide unique Port Name for SAS Target port */
u64 tport_wwpn; u64 tport_wwpn;
/* ASCII formatted WWPN for SAS Target port */ /* ASCII formatted WWPN for SAS Target port */

View File

@ -43,7 +43,6 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/target_core_fabric_configfs.h> #include <target/target_core_fabric_configfs.h>
#include <target/target_core_configfs.h>
#include <target/configfs_macros.h> #include <target/configfs_macros.h>
#include <linux/vhost.h> #include <linux/vhost.h>
#include <linux/virtio_scsi.h> #include <linux/virtio_scsi.h>
@ -117,15 +116,6 @@ struct vhost_scsi_nexus {
struct se_session *tvn_se_sess; struct se_session *tvn_se_sess;
}; };
struct vhost_scsi_nacl {
/* Binary World Wide unique Port Name for Vhost Initiator port */
u64 iport_wwpn;
/* ASCII formatted WWPN for Sas Initiator port */
char iport_name[VHOST_SCSI_NAMELEN];
/* Returned by vhost_scsi_make_nodeacl() */
struct se_node_acl se_node_acl;
};
struct vhost_scsi_tpg { struct vhost_scsi_tpg {
/* Vhost port target portal group tag for TCM */ /* Vhost port target portal group tag for TCM */
u16 tport_tpgt; u16 tport_tpgt;
@ -218,7 +208,6 @@ struct vhost_scsi {
int vs_events_nr; /* num of pending events, protected by vq->mutex */ int vs_events_nr; /* num of pending events, protected by vq->mutex */
}; };
static struct target_core_fabric_ops vhost_scsi_ops;
static struct workqueue_struct *vhost_scsi_workqueue; static struct workqueue_struct *vhost_scsi_workqueue;
/* Global spinlock to protect vhost_scsi TPG list for vhost IOCTL access */ /* Global spinlock to protect vhost_scsi TPG list for vhost IOCTL access */
@ -299,28 +288,6 @@ static char *vhost_scsi_get_fabric_name(void)
return "vhost"; return "vhost";
} }
static u8 vhost_scsi_get_fabric_proto_ident(struct se_portal_group *se_tpg)
{
struct vhost_scsi_tpg *tpg = container_of(se_tpg,
struct vhost_scsi_tpg, se_tpg);
struct vhost_scsi_tport *tport = tpg->tport;
switch (tport->tport_proto_id) {
case SCSI_PROTOCOL_SAS:
return sas_get_fabric_proto_ident(se_tpg);
case SCSI_PROTOCOL_FCP:
return fc_get_fabric_proto_ident(se_tpg);
case SCSI_PROTOCOL_ISCSI:
return iscsi_get_fabric_proto_ident(se_tpg);
default:
pr_err("Unknown tport_proto_id: 0x%02x, using"
" SAS emulation\n", tport->tport_proto_id);
break;
}
return sas_get_fabric_proto_ident(se_tpg);
}
static char *vhost_scsi_get_fabric_wwn(struct se_portal_group *se_tpg) static char *vhost_scsi_get_fabric_wwn(struct se_portal_group *se_tpg)
{ {
struct vhost_scsi_tpg *tpg = container_of(se_tpg, struct vhost_scsi_tpg *tpg = container_of(se_tpg,
@ -337,102 +304,6 @@ static u16 vhost_scsi_get_tpgt(struct se_portal_group *se_tpg)
return tpg->tport_tpgt; return tpg->tport_tpgt;
} }
static u32 vhost_scsi_get_default_depth(struct se_portal_group *se_tpg)
{
return 1;
}
static u32
vhost_scsi_get_pr_transport_id(struct se_portal_group *se_tpg,
struct se_node_acl *se_nacl,
struct t10_pr_registration *pr_reg,
int *format_code,
unsigned char *buf)
{
struct vhost_scsi_tpg *tpg = container_of(se_tpg,
struct vhost_scsi_tpg, se_tpg);
struct vhost_scsi_tport *tport = tpg->tport;
switch (tport->tport_proto_id) {
case SCSI_PROTOCOL_SAS:
return sas_get_pr_transport_id(se_tpg, se_nacl, pr_reg,
format_code, buf);
case SCSI_PROTOCOL_FCP:
return fc_get_pr_transport_id(se_tpg, se_nacl, pr_reg,
format_code, buf);
case SCSI_PROTOCOL_ISCSI:
return iscsi_get_pr_transport_id(se_tpg, se_nacl, pr_reg,
format_code, buf);
default:
pr_err("Unknown tport_proto_id: 0x%02x, using"
" SAS emulation\n", tport->tport_proto_id);
break;
}
return sas_get_pr_transport_id(se_tpg, se_nacl, pr_reg,
format_code, buf);
}
static u32
vhost_scsi_get_pr_transport_id_len(struct se_portal_group *se_tpg,
struct se_node_acl *se_nacl,
struct t10_pr_registration *pr_reg,
int *format_code)
{
struct vhost_scsi_tpg *tpg = container_of(se_tpg,
struct vhost_scsi_tpg, se_tpg);
struct vhost_scsi_tport *tport = tpg->tport;
switch (tport->tport_proto_id) {
case SCSI_PROTOCOL_SAS:
return sas_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,
format_code);
case SCSI_PROTOCOL_FCP:
return fc_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,
format_code);
case SCSI_PROTOCOL_ISCSI:
return iscsi_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,
format_code);
default:
pr_err("Unknown tport_proto_id: 0x%02x, using"
" SAS emulation\n", tport->tport_proto_id);
break;
}
return sas_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,
format_code);
}
static char *
vhost_scsi_parse_pr_out_transport_id(struct se_portal_group *se_tpg,
const char *buf,
u32 *out_tid_len,
char **port_nexus_ptr)
{
struct vhost_scsi_tpg *tpg = container_of(se_tpg,
struct vhost_scsi_tpg, se_tpg);
struct vhost_scsi_tport *tport = tpg->tport;
switch (tport->tport_proto_id) {
case SCSI_PROTOCOL_SAS:
return sas_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,
port_nexus_ptr);
case SCSI_PROTOCOL_FCP:
return fc_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,
port_nexus_ptr);
case SCSI_PROTOCOL_ISCSI:
return iscsi_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,
port_nexus_ptr);
default:
pr_err("Unknown tport_proto_id: 0x%02x, using"
" SAS emulation\n", tport->tport_proto_id);
break;
}
return sas_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,
port_nexus_ptr);
}
static int vhost_scsi_check_prot_fabric_only(struct se_portal_group *se_tpg) static int vhost_scsi_check_prot_fabric_only(struct se_portal_group *se_tpg)
{ {
struct vhost_scsi_tpg *tpg = container_of(se_tpg, struct vhost_scsi_tpg *tpg = container_of(se_tpg,
@ -441,29 +312,6 @@ static int vhost_scsi_check_prot_fabric_only(struct se_portal_group *se_tpg)
return tpg->tv_fabric_prot_type; return tpg->tv_fabric_prot_type;
} }
static struct se_node_acl *
vhost_scsi_alloc_fabric_acl(struct se_portal_group *se_tpg)
{
struct vhost_scsi_nacl *nacl;
nacl = kzalloc(sizeof(struct vhost_scsi_nacl), GFP_KERNEL);
if (!nacl) {
pr_err("Unable to allocate struct vhost_scsi_nacl\n");
return NULL;
}
return &nacl->se_node_acl;
}
static void
vhost_scsi_release_fabric_acl(struct se_portal_group *se_tpg,
struct se_node_acl *se_nacl)
{
struct vhost_scsi_nacl *nacl = container_of(se_nacl,
struct vhost_scsi_nacl, se_node_acl);
kfree(nacl);
}
static u32 vhost_scsi_tpg_get_inst_index(struct se_portal_group *se_tpg) static u32 vhost_scsi_tpg_get_inst_index(struct se_portal_group *se_tpg)
{ {
return 1; return 1;
@ -521,11 +369,6 @@ static void vhost_scsi_set_default_node_attrs(struct se_node_acl *nacl)
return; return;
} }
static u32 vhost_scsi_get_task_tag(struct se_cmd *se_cmd)
{
return 0;
}
static int vhost_scsi_get_cmd_state(struct se_cmd *se_cmd) static int vhost_scsi_get_cmd_state(struct se_cmd *se_cmd)
{ {
return 0; return 0;
@ -609,7 +452,7 @@ static void vhost_scsi_free_cmd(struct vhost_scsi_cmd *cmd)
static int vhost_scsi_check_stop_free(struct se_cmd *se_cmd) static int vhost_scsi_check_stop_free(struct se_cmd *se_cmd)
{ {
return target_put_sess_cmd(se_cmd->se_sess, se_cmd); return target_put_sess_cmd(se_cmd);
} }
static void static void
@ -970,6 +813,7 @@ static void vhost_scsi_submission_work(struct work_struct *work)
} }
tv_nexus = cmd->tvc_nexus; tv_nexus = cmd->tvc_nexus;
se_cmd->tag = 0;
rc = target_submit_cmd_map_sgls(se_cmd, tv_nexus->tvn_se_sess, rc = target_submit_cmd_map_sgls(se_cmd, tv_nexus->tvn_se_sess,
cmd->tvc_cdb, &cmd->tvc_sense_buf[0], cmd->tvc_cdb, &cmd->tvc_sense_buf[0],
cmd->tvc_lun, cmd->tvc_exp_data_len, cmd->tvc_lun, cmd->tvc_exp_data_len,
@ -1824,50 +1668,6 @@ static void vhost_scsi_port_unlink(struct se_portal_group *se_tpg,
mutex_unlock(&vhost_scsi_mutex); mutex_unlock(&vhost_scsi_mutex);
} }
static struct se_node_acl *
vhost_scsi_make_nodeacl(struct se_portal_group *se_tpg,
struct config_group *group,
const char *name)
{
struct se_node_acl *se_nacl, *se_nacl_new;
struct vhost_scsi_nacl *nacl;
u64 wwpn = 0;
u32 nexus_depth;
/* vhost_scsi_parse_wwn(name, &wwpn, 1) < 0)
return ERR_PTR(-EINVAL); */
se_nacl_new = vhost_scsi_alloc_fabric_acl(se_tpg);
if (!se_nacl_new)
return ERR_PTR(-ENOMEM);
nexus_depth = 1;
/*
* se_nacl_new may be released by core_tpg_add_initiator_node_acl()
* when converting a NodeACL from demo mode -> explict
*/
se_nacl = core_tpg_add_initiator_node_acl(se_tpg, se_nacl_new,
name, nexus_depth);
if (IS_ERR(se_nacl)) {
vhost_scsi_release_fabric_acl(se_tpg, se_nacl_new);
return se_nacl;
}
/*
* Locate our struct vhost_scsi_nacl and set the FC Nport WWPN
*/
nacl = container_of(se_nacl, struct vhost_scsi_nacl, se_node_acl);
nacl->iport_wwpn = wwpn;
return se_nacl;
}
static void vhost_scsi_drop_nodeacl(struct se_node_acl *se_acl)
{
struct vhost_scsi_nacl *nacl = container_of(se_acl,
struct vhost_scsi_nacl, se_node_acl);
core_tpg_del_initiator_node_acl(se_acl->se_tpg, se_acl, 1);
kfree(nacl);
}
static void vhost_scsi_free_cmd_map_res(struct vhost_scsi_nexus *nexus, static void vhost_scsi_free_cmd_map_res(struct vhost_scsi_nexus *nexus,
struct se_session *se_sess) struct se_session *se_sess)
{ {
@ -2202,8 +2002,7 @@ vhost_scsi_make_tpg(struct se_wwn *wwn,
tpg->tport = tport; tpg->tport = tport;
tpg->tport_tpgt = tpgt; tpg->tport_tpgt = tpgt;
ret = core_tpg_register(&vhost_scsi_ops, wwn, ret = core_tpg_register(wwn, &tpg->se_tpg, tport->tport_proto_id);
&tpg->se_tpg, tpg, TRANSPORT_TPG_TYPE_NORMAL);
if (ret < 0) { if (ret < 0) {
kfree(tpg); kfree(tpg);
return NULL; return NULL;
@ -2327,20 +2126,13 @@ static struct target_core_fabric_ops vhost_scsi_ops = {
.module = THIS_MODULE, .module = THIS_MODULE,
.name = "vhost", .name = "vhost",
.get_fabric_name = vhost_scsi_get_fabric_name, .get_fabric_name = vhost_scsi_get_fabric_name,
.get_fabric_proto_ident = vhost_scsi_get_fabric_proto_ident,
.tpg_get_wwn = vhost_scsi_get_fabric_wwn, .tpg_get_wwn = vhost_scsi_get_fabric_wwn,
.tpg_get_tag = vhost_scsi_get_tpgt, .tpg_get_tag = vhost_scsi_get_tpgt,
.tpg_get_default_depth = vhost_scsi_get_default_depth,
.tpg_get_pr_transport_id = vhost_scsi_get_pr_transport_id,
.tpg_get_pr_transport_id_len = vhost_scsi_get_pr_transport_id_len,
.tpg_parse_pr_out_transport_id = vhost_scsi_parse_pr_out_transport_id,
.tpg_check_demo_mode = vhost_scsi_check_true, .tpg_check_demo_mode = vhost_scsi_check_true,
.tpg_check_demo_mode_cache = vhost_scsi_check_true, .tpg_check_demo_mode_cache = vhost_scsi_check_true,
.tpg_check_demo_mode_write_protect = vhost_scsi_check_false, .tpg_check_demo_mode_write_protect = vhost_scsi_check_false,
.tpg_check_prod_mode_write_protect = vhost_scsi_check_false, .tpg_check_prod_mode_write_protect = vhost_scsi_check_false,
.tpg_check_prot_fabric_only = vhost_scsi_check_prot_fabric_only, .tpg_check_prot_fabric_only = vhost_scsi_check_prot_fabric_only,
.tpg_alloc_fabric_acl = vhost_scsi_alloc_fabric_acl,
.tpg_release_fabric_acl = vhost_scsi_release_fabric_acl,
.tpg_get_inst_index = vhost_scsi_tpg_get_inst_index, .tpg_get_inst_index = vhost_scsi_tpg_get_inst_index,
.release_cmd = vhost_scsi_release_cmd, .release_cmd = vhost_scsi_release_cmd,
.check_stop_free = vhost_scsi_check_stop_free, .check_stop_free = vhost_scsi_check_stop_free,
@ -2351,7 +2143,6 @@ static struct target_core_fabric_ops vhost_scsi_ops = {
.write_pending = vhost_scsi_write_pending, .write_pending = vhost_scsi_write_pending,
.write_pending_status = vhost_scsi_write_pending_status, .write_pending_status = vhost_scsi_write_pending_status,
.set_default_node_attributes = vhost_scsi_set_default_node_attrs, .set_default_node_attributes = vhost_scsi_set_default_node_attrs,
.get_task_tag = vhost_scsi_get_task_tag,
.get_cmd_state = vhost_scsi_get_cmd_state, .get_cmd_state = vhost_scsi_get_cmd_state,
.queue_data_in = vhost_scsi_queue_data_in, .queue_data_in = vhost_scsi_queue_data_in,
.queue_status = vhost_scsi_queue_status, .queue_status = vhost_scsi_queue_status,
@ -2366,10 +2157,6 @@ static struct target_core_fabric_ops vhost_scsi_ops = {
.fabric_drop_tpg = vhost_scsi_drop_tpg, .fabric_drop_tpg = vhost_scsi_drop_tpg,
.fabric_post_link = vhost_scsi_port_link, .fabric_post_link = vhost_scsi_port_link,
.fabric_pre_unlink = vhost_scsi_port_unlink, .fabric_pre_unlink = vhost_scsi_port_unlink,
.fabric_make_np = NULL,
.fabric_drop_np = NULL,
.fabric_make_nodeacl = vhost_scsi_make_nodeacl,
.fabric_drop_nodeacl = vhost_scsi_drop_nodeacl,
.tfc_wwn_attrs = vhost_scsi_wwn_attrs, .tfc_wwn_attrs = vhost_scsi_wwn_attrs,
.tfc_tpg_base_attrs = vhost_scsi_tpg_attrs, .tfc_tpg_base_attrs = vhost_scsi_tpg_attrs,

View File

@ -53,7 +53,6 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/target_core_configfs.h>
#include <target/target_core_fabric_configfs.h> #include <target/target_core_fabric_configfs.h>
#include <asm/hypervisor.h> #include <asm/hypervisor.h>
@ -201,8 +200,6 @@ static LIST_HEAD(scsiback_free_pages);
static DEFINE_MUTEX(scsiback_mutex); static DEFINE_MUTEX(scsiback_mutex);
static LIST_HEAD(scsiback_list); static LIST_HEAD(scsiback_list);
static const struct target_core_fabric_ops scsiback_ops;
static void scsiback_get(struct vscsibk_info *info) static void scsiback_get(struct vscsibk_info *info)
{ {
atomic_inc(&info->nr_unreplied_reqs); atomic_inc(&info->nr_unreplied_reqs);
@ -397,6 +394,7 @@ static void scsiback_cmd_exec(struct vscsibk_pend *pending_req)
memset(se_cmd, 0, sizeof(*se_cmd)); memset(se_cmd, 0, sizeof(*se_cmd));
scsiback_get(pending_req->info); scsiback_get(pending_req->info);
se_cmd->tag = pending_req->rqid;
rc = target_submit_cmd_map_sgls(se_cmd, sess, pending_req->cmnd, rc = target_submit_cmd_map_sgls(se_cmd, sess, pending_req->cmnd,
pending_req->sense_buffer, pending_req->v2p->lun, pending_req->sense_buffer, pending_req->v2p->lun,
pending_req->data_len, 0, pending_req->data_len, 0,
@ -863,7 +861,8 @@ static int scsiback_add_translation_entry(struct vscsibk_info *info,
struct list_head *head = &(info->v2p_entry_lists); struct list_head *head = &(info->v2p_entry_lists);
unsigned long flags; unsigned long flags;
char *lunp; char *lunp;
unsigned int lun; unsigned long long unpacked_lun;
struct se_lun *se_lun;
struct scsiback_tpg *tpg_entry, *tpg = NULL; struct scsiback_tpg *tpg_entry, *tpg = NULL;
char *error = "doesn't exist"; char *error = "doesn't exist";
@ -874,24 +873,27 @@ static int scsiback_add_translation_entry(struct vscsibk_info *info,
} }
*lunp = 0; *lunp = 0;
lunp++; lunp++;
if (kstrtouint(lunp, 10, &lun) || lun >= TRANSPORT_MAX_LUNS_PER_TPG) { err = kstrtoull(lunp, 10, &unpacked_lun);
if (err < 0) {
pr_err("lun number not valid: %s\n", lunp); pr_err("lun number not valid: %s\n", lunp);
return -EINVAL; return err;
} }
mutex_lock(&scsiback_mutex); mutex_lock(&scsiback_mutex);
list_for_each_entry(tpg_entry, &scsiback_list, tv_tpg_list) { list_for_each_entry(tpg_entry, &scsiback_list, tv_tpg_list) {
if (!strcmp(phy, tpg_entry->tport->tport_name) || if (!strcmp(phy, tpg_entry->tport->tport_name) ||
!strcmp(phy, tpg_entry->param_alias)) { !strcmp(phy, tpg_entry->param_alias)) {
spin_lock(&tpg_entry->se_tpg.tpg_lun_lock); mutex_lock(&tpg_entry->se_tpg.tpg_lun_mutex);
if (tpg_entry->se_tpg.tpg_lun_list[lun]->lun_status == hlist_for_each_entry(se_lun, &tpg_entry->se_tpg.tpg_lun_hlist, link) {
TRANSPORT_LUN_STATUS_ACTIVE) { if (se_lun->unpacked_lun == unpacked_lun) {
if (!tpg_entry->tpg_nexus) if (!tpg_entry->tpg_nexus)
error = "nexus undefined"; error = "nexus undefined";
else else
tpg = tpg_entry; tpg = tpg_entry;
break;
}
} }
spin_unlock(&tpg_entry->se_tpg.tpg_lun_lock); mutex_unlock(&tpg_entry->se_tpg.tpg_lun_mutex);
break; break;
} }
} }
@ -903,7 +905,7 @@ static int scsiback_add_translation_entry(struct vscsibk_info *info,
mutex_unlock(&scsiback_mutex); mutex_unlock(&scsiback_mutex);
if (!tpg) { if (!tpg) {
pr_err("%s:%d %s\n", phy, lun, error); pr_err("%s:%llu %s\n", phy, unpacked_lun, error);
return -ENODEV; return -ENODEV;
} }
@ -931,7 +933,7 @@ static int scsiback_add_translation_entry(struct vscsibk_info *info,
kref_init(&new->kref); kref_init(&new->kref);
new->v = *v; new->v = *v;
new->tpg = tpg; new->tpg = tpg;
new->lun = lun; new->lun = unpacked_lun;
list_add_tail(&new->l, head); list_add_tail(&new->l, head);
out: out:
@ -1251,28 +1253,6 @@ static char *scsiback_dump_proto_id(struct scsiback_tport *tport)
return "Unknown"; return "Unknown";
} }
static u8 scsiback_get_fabric_proto_ident(struct se_portal_group *se_tpg)
{
struct scsiback_tpg *tpg = container_of(se_tpg,
struct scsiback_tpg, se_tpg);
struct scsiback_tport *tport = tpg->tport;
switch (tport->tport_proto_id) {
case SCSI_PROTOCOL_SAS:
return sas_get_fabric_proto_ident(se_tpg);
case SCSI_PROTOCOL_FCP:
return fc_get_fabric_proto_ident(se_tpg);
case SCSI_PROTOCOL_ISCSI:
return iscsi_get_fabric_proto_ident(se_tpg);
default:
pr_err("Unknown tport_proto_id: 0x%02x, using SAS emulation\n",
tport->tport_proto_id);
break;
}
return sas_get_fabric_proto_ident(se_tpg);
}
static char *scsiback_get_fabric_wwn(struct se_portal_group *se_tpg) static char *scsiback_get_fabric_wwn(struct se_portal_group *se_tpg)
{ {
struct scsiback_tpg *tpg = container_of(se_tpg, struct scsiback_tpg *tpg = container_of(se_tpg,
@ -1289,102 +1269,6 @@ static u16 scsiback_get_tag(struct se_portal_group *se_tpg)
return tpg->tport_tpgt; return tpg->tport_tpgt;
} }
static u32 scsiback_get_default_depth(struct se_portal_group *se_tpg)
{
return 1;
}
static u32
scsiback_get_pr_transport_id(struct se_portal_group *se_tpg,
struct se_node_acl *se_nacl,
struct t10_pr_registration *pr_reg,
int *format_code,
unsigned char *buf)
{
struct scsiback_tpg *tpg = container_of(se_tpg,
struct scsiback_tpg, se_tpg);
struct scsiback_tport *tport = tpg->tport;
switch (tport->tport_proto_id) {
case SCSI_PROTOCOL_SAS:
return sas_get_pr_transport_id(se_tpg, se_nacl, pr_reg,
format_code, buf);
case SCSI_PROTOCOL_FCP:
return fc_get_pr_transport_id(se_tpg, se_nacl, pr_reg,
format_code, buf);
case SCSI_PROTOCOL_ISCSI:
return iscsi_get_pr_transport_id(se_tpg, se_nacl, pr_reg,
format_code, buf);
default:
pr_err("Unknown tport_proto_id: 0x%02x, using SAS emulation\n",
tport->tport_proto_id);
break;
}
return sas_get_pr_transport_id(se_tpg, se_nacl, pr_reg,
format_code, buf);
}
static u32
scsiback_get_pr_transport_id_len(struct se_portal_group *se_tpg,
struct se_node_acl *se_nacl,
struct t10_pr_registration *pr_reg,
int *format_code)
{
struct scsiback_tpg *tpg = container_of(se_tpg,
struct scsiback_tpg, se_tpg);
struct scsiback_tport *tport = tpg->tport;
switch (tport->tport_proto_id) {
case SCSI_PROTOCOL_SAS:
return sas_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,
format_code);
case SCSI_PROTOCOL_FCP:
return fc_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,
format_code);
case SCSI_PROTOCOL_ISCSI:
return iscsi_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,
format_code);
default:
pr_err("Unknown tport_proto_id: 0x%02x, using SAS emulation\n",
tport->tport_proto_id);
break;
}
return sas_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,
format_code);
}
static char *
scsiback_parse_pr_out_transport_id(struct se_portal_group *se_tpg,
const char *buf,
u32 *out_tid_len,
char **port_nexus_ptr)
{
struct scsiback_tpg *tpg = container_of(se_tpg,
struct scsiback_tpg, se_tpg);
struct scsiback_tport *tport = tpg->tport;
switch (tport->tport_proto_id) {
case SCSI_PROTOCOL_SAS:
return sas_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,
port_nexus_ptr);
case SCSI_PROTOCOL_FCP:
return fc_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,
port_nexus_ptr);
case SCSI_PROTOCOL_ISCSI:
return iscsi_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,
port_nexus_ptr);
default:
pr_err("Unknown tport_proto_id: 0x%02x, using SAS emulation\n",
tport->tport_proto_id);
break;
}
return sas_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,
port_nexus_ptr);
}
static struct se_wwn * static struct se_wwn *
scsiback_make_tport(struct target_fabric_configfs *tf, scsiback_make_tport(struct target_fabric_configfs *tf,
struct config_group *group, struct config_group *group,
@ -1451,19 +1335,6 @@ static void scsiback_drop_tport(struct se_wwn *wwn)
kfree(tport); kfree(tport);
} }
static struct se_node_acl *
scsiback_alloc_fabric_acl(struct se_portal_group *se_tpg)
{
return kzalloc(sizeof(struct se_node_acl), GFP_KERNEL);
}
static void
scsiback_release_fabric_acl(struct se_portal_group *se_tpg,
struct se_node_acl *se_nacl)
{
kfree(se_nacl);
}
static u32 scsiback_tpg_get_inst_index(struct se_portal_group *se_tpg) static u32 scsiback_tpg_get_inst_index(struct se_portal_group *se_tpg)
{ {
return 1; return 1;
@ -1522,14 +1393,6 @@ static void scsiback_set_default_node_attrs(struct se_node_acl *nacl)
{ {
} }
static u32 scsiback_get_task_tag(struct se_cmd *se_cmd)
{
struct vscsibk_pend *pending_req = container_of(se_cmd,
struct vscsibk_pend, se_cmd);
return pending_req->rqid;
}
static int scsiback_get_cmd_state(struct se_cmd *se_cmd) static int scsiback_get_cmd_state(struct se_cmd *se_cmd)
{ {
return 0; return 0;
@ -1898,8 +1761,7 @@ scsiback_make_tpg(struct se_wwn *wwn,
tpg->tport = tport; tpg->tport = tport;
tpg->tport_tpgt = tpgt; tpg->tport_tpgt = tpgt;
ret = core_tpg_register(&scsiback_ops, wwn, ret = core_tpg_register(wwn, &tpg->se_tpg, tport->tport_proto_id);
&tpg->se_tpg, tpg, TRANSPORT_TPG_TYPE_NORMAL);
if (ret < 0) { if (ret < 0) {
kfree(tpg); kfree(tpg);
return NULL; return NULL;
@ -1944,23 +1806,15 @@ static const struct target_core_fabric_ops scsiback_ops = {
.module = THIS_MODULE, .module = THIS_MODULE,
.name = "xen-pvscsi", .name = "xen-pvscsi",
.get_fabric_name = scsiback_get_fabric_name, .get_fabric_name = scsiback_get_fabric_name,
.get_fabric_proto_ident = scsiback_get_fabric_proto_ident,
.tpg_get_wwn = scsiback_get_fabric_wwn, .tpg_get_wwn = scsiback_get_fabric_wwn,
.tpg_get_tag = scsiback_get_tag, .tpg_get_tag = scsiback_get_tag,
.tpg_get_default_depth = scsiback_get_default_depth,
.tpg_get_pr_transport_id = scsiback_get_pr_transport_id,
.tpg_get_pr_transport_id_len = scsiback_get_pr_transport_id_len,
.tpg_parse_pr_out_transport_id = scsiback_parse_pr_out_transport_id,
.tpg_check_demo_mode = scsiback_check_true, .tpg_check_demo_mode = scsiback_check_true,
.tpg_check_demo_mode_cache = scsiback_check_true, .tpg_check_demo_mode_cache = scsiback_check_true,
.tpg_check_demo_mode_write_protect = scsiback_check_false, .tpg_check_demo_mode_write_protect = scsiback_check_false,
.tpg_check_prod_mode_write_protect = scsiback_check_false, .tpg_check_prod_mode_write_protect = scsiback_check_false,
.tpg_alloc_fabric_acl = scsiback_alloc_fabric_acl,
.tpg_release_fabric_acl = scsiback_release_fabric_acl,
.tpg_get_inst_index = scsiback_tpg_get_inst_index, .tpg_get_inst_index = scsiback_tpg_get_inst_index,
.check_stop_free = scsiback_check_stop_free, .check_stop_free = scsiback_check_stop_free,
.release_cmd = scsiback_release_cmd, .release_cmd = scsiback_release_cmd,
.put_session = NULL,
.shutdown_session = scsiback_shutdown_session, .shutdown_session = scsiback_shutdown_session,
.close_session = scsiback_close_session, .close_session = scsiback_close_session,
.sess_get_index = scsiback_sess_get_index, .sess_get_index = scsiback_sess_get_index,
@ -1968,7 +1822,6 @@ static const struct target_core_fabric_ops scsiback_ops = {
.write_pending = scsiback_write_pending, .write_pending = scsiback_write_pending,
.write_pending_status = scsiback_write_pending_status, .write_pending_status = scsiback_write_pending_status,
.set_default_node_attributes = scsiback_set_default_node_attrs, .set_default_node_attributes = scsiback_set_default_node_attrs,
.get_task_tag = scsiback_get_task_tag,
.get_cmd_state = scsiback_get_cmd_state, .get_cmd_state = scsiback_get_cmd_state,
.queue_data_in = scsiback_queue_data_in, .queue_data_in = scsiback_queue_data_in,
.queue_status = scsiback_queue_status, .queue_status = scsiback_queue_status,
@ -1983,12 +1836,6 @@ static const struct target_core_fabric_ops scsiback_ops = {
.fabric_drop_tpg = scsiback_drop_tpg, .fabric_drop_tpg = scsiback_drop_tpg,
.fabric_post_link = scsiback_port_link, .fabric_post_link = scsiback_port_link,
.fabric_pre_unlink = scsiback_port_unlink, .fabric_pre_unlink = scsiback_port_unlink,
.fabric_make_np = NULL,
.fabric_drop_np = NULL,
#if 0
.fabric_make_nodeacl = scsiback_make_nodeacl,
.fabric_drop_nodeacl = scsiback_drop_nodeacl,
#endif
.tfc_wwn_attrs = scsiback_wwn_attrs, .tfc_wwn_attrs = scsiback_wwn_attrs,
.tfc_tpg_base_attrs = scsiback_tpg_attrs, .tfc_tpg_base_attrs = scsiback_tpg_attrs,

View File

@ -9,5 +9,6 @@
extern __u16 crc_t10dif_generic(__u16 crc, const unsigned char *buffer, extern __u16 crc_t10dif_generic(__u16 crc, const unsigned char *buffer,
size_t len); size_t len);
extern __u16 crc_t10dif(unsigned char const *, size_t); extern __u16 crc_t10dif(unsigned char const *, size_t);
extern __u16 crc_t10dif_update(__u16 crc, unsigned char const *, size_t);
#endif #endif

View File

@ -247,10 +247,6 @@ struct iscsi_conn_ops {
u8 DataDigest; /* [0,1] == [None,CRC32C] */ u8 DataDigest; /* [0,1] == [None,CRC32C] */
u32 MaxRecvDataSegmentLength; /* [512..2**24-1] */ u32 MaxRecvDataSegmentLength; /* [512..2**24-1] */
u32 MaxXmitDataSegmentLength; /* [512..2**24-1] */ u32 MaxXmitDataSegmentLength; /* [512..2**24-1] */
u8 OFMarker; /* [0,1] == [No,Yes] */
u8 IFMarker; /* [0,1] == [No,Yes] */
u32 OFMarkInt; /* [1..65535] */
u32 IFMarkInt; /* [1..65535] */
/* /*
* iSER specific connection parameters * iSER specific connection parameters
*/ */
@ -531,12 +527,6 @@ struct iscsi_conn {
u32 exp_statsn; u32 exp_statsn;
/* Per connection status sequence number */ /* Per connection status sequence number */
u32 stat_sn; u32 stat_sn;
/* IFMarkInt's Current Value */
u32 if_marker;
/* OFMarkInt's Current Value */
u32 of_marker;
/* Used for calculating OFMarker offset to next PDU */
u32 of_marker_offset;
#define IPV6_ADDRESS_SPACE 48 #define IPV6_ADDRESS_SPACE 48
unsigned char login_ip[IPV6_ADDRESS_SPACE]; unsigned char login_ip[IPV6_ADDRESS_SPACE];
unsigned char local_ip[IPV6_ADDRESS_SPACE]; unsigned char local_ip[IPV6_ADDRESS_SPACE];
@ -754,10 +744,10 @@ struct iscsi_node_stat_grps {
}; };
struct iscsi_node_acl { struct iscsi_node_acl {
struct se_node_acl se_node_acl;
struct iscsi_node_attrib node_attrib; struct iscsi_node_attrib node_attrib;
struct iscsi_node_auth node_auth; struct iscsi_node_auth node_auth;
struct iscsi_node_stat_grps node_stat_grps; struct iscsi_node_stat_grps node_stat_grps;
struct se_node_acl se_node_acl;
}; };
struct iscsi_tpg_attrib { struct iscsi_tpg_attrib {

View File

@ -3,18 +3,7 @@
#define TRANSPORT_FLAG_PASSTHROUGH 1 #define TRANSPORT_FLAG_PASSTHROUGH 1
struct target_backend_cits { struct target_backend_ops {
struct config_item_type tb_dev_cit;
struct config_item_type tb_dev_attrib_cit;
struct config_item_type tb_dev_pr_cit;
struct config_item_type tb_dev_wwn_cit;
struct config_item_type tb_dev_alua_tg_pt_gps_cit;
struct config_item_type tb_dev_stat_cit;
};
struct se_subsystem_api {
struct list_head sub_api_list;
char name[16]; char name[16];
char inquiry_prod[16]; char inquiry_prod[16];
char inquiry_rev[4]; char inquiry_rev[4];
@ -52,7 +41,7 @@ struct se_subsystem_api {
int (*format_prot)(struct se_device *); int (*format_prot)(struct se_device *);
void (*free_prot)(struct se_device *); void (*free_prot)(struct se_device *);
struct target_backend_cits tb_cits; struct configfs_attribute **tb_dev_attrib_attrs;
}; };
struct sbc_ops { struct sbc_ops {
@ -60,12 +49,12 @@ struct sbc_ops {
u32, enum dma_data_direction); u32, enum dma_data_direction);
sense_reason_t (*execute_sync_cache)(struct se_cmd *cmd); sense_reason_t (*execute_sync_cache)(struct se_cmd *cmd);
sense_reason_t (*execute_write_same)(struct se_cmd *cmd); sense_reason_t (*execute_write_same)(struct se_cmd *cmd);
sense_reason_t (*execute_write_same_unmap)(struct se_cmd *cmd); sense_reason_t (*execute_unmap)(struct se_cmd *cmd,
sense_reason_t (*execute_unmap)(struct se_cmd *cmd); sector_t lba, sector_t nolb);
}; };
int transport_subsystem_register(struct se_subsystem_api *); int transport_backend_register(const struct target_backend_ops *);
void transport_subsystem_release(struct se_subsystem_api *); void target_backend_unregister(const struct target_backend_ops *);
void target_complete_cmd(struct se_cmd *, u8); void target_complete_cmd(struct se_cmd *, u8);
void target_complete_cmd_with_length(struct se_cmd *, u8, int); void target_complete_cmd_with_length(struct se_cmd *, u8, int);
@ -79,22 +68,19 @@ sense_reason_t sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops);
u32 sbc_get_device_rev(struct se_device *dev); u32 sbc_get_device_rev(struct se_device *dev);
u32 sbc_get_device_type(struct se_device *dev); u32 sbc_get_device_type(struct se_device *dev);
sector_t sbc_get_write_same_sectors(struct se_cmd *cmd); sector_t sbc_get_write_same_sectors(struct se_cmd *cmd);
sense_reason_t sbc_execute_unmap(struct se_cmd *cmd,
sense_reason_t (*do_unmap_fn)(struct se_cmd *cmd, void *priv,
sector_t lba, sector_t nolb),
void *priv);
void sbc_dif_generate(struct se_cmd *); void sbc_dif_generate(struct se_cmd *);
sense_reason_t sbc_dif_verify_write(struct se_cmd *, sector_t, unsigned int, sense_reason_t sbc_dif_verify(struct se_cmd *, sector_t, unsigned int,
unsigned int, struct scatterlist *, int); unsigned int, struct scatterlist *, int);
sense_reason_t sbc_dif_verify_read(struct se_cmd *, sector_t, unsigned int, void sbc_dif_copy_prot(struct se_cmd *, unsigned int, bool,
unsigned int, struct scatterlist *, int); struct scatterlist *, int);
sense_reason_t sbc_dif_read_strip(struct se_cmd *);
void transport_set_vpd_proto_id(struct t10_vpd *, unsigned char *); void transport_set_vpd_proto_id(struct t10_vpd *, unsigned char *);
int transport_set_vpd_assoc(struct t10_vpd *, unsigned char *); int transport_set_vpd_assoc(struct t10_vpd *, unsigned char *);
int transport_set_vpd_ident_type(struct t10_vpd *, unsigned char *); int transport_set_vpd_ident_type(struct t10_vpd *, unsigned char *);
int transport_set_vpd_ident(struct t10_vpd *, unsigned char *); int transport_set_vpd_ident(struct t10_vpd *, unsigned char *);
extern struct configfs_attribute *sbc_attrib_attrs[];
extern struct configfs_attribute *passthrough_attrib_attrs[];
/* core helpers also used by command snooping in pscsi */ /* core helpers also used by command snooping in pscsi */
void *transport_kmap_data_sg(struct se_cmd *); void *transport_kmap_data_sg(struct se_cmd *);
void transport_kunmap_data_sg(struct se_cmd *); void transport_kunmap_data_sg(struct se_cmd *);
@ -103,39 +89,7 @@ int target_alloc_sgl(struct scatterlist **, unsigned int *, u32, bool);
sense_reason_t transport_generic_map_mem_to_cmd(struct se_cmd *, sense_reason_t transport_generic_map_mem_to_cmd(struct se_cmd *,
struct scatterlist *, u32, struct scatterlist *, u32); struct scatterlist *, u32, struct scatterlist *, u32);
void array_free(void *array, int n); bool target_lun_is_rdonly(struct se_cmd *);
/* From target_core_configfs.c to setup default backend config_item_types */
void target_core_setup_sub_cits(struct se_subsystem_api *);
/* attribute helpers from target_core_device.c for backend drivers */
bool se_dev_check_wce(struct se_device *);
int se_dev_set_max_unmap_lba_count(struct se_device *, u32);
int se_dev_set_max_unmap_block_desc_count(struct se_device *, u32);
int se_dev_set_unmap_granularity(struct se_device *, u32);
int se_dev_set_unmap_granularity_alignment(struct se_device *, u32);
int se_dev_set_max_write_same_len(struct se_device *, u32);
int se_dev_set_emulate_model_alias(struct se_device *, int);
int se_dev_set_emulate_dpo(struct se_device *, int);
int se_dev_set_emulate_fua_write(struct se_device *, int);
int se_dev_set_emulate_fua_read(struct se_device *, int);
int se_dev_set_emulate_write_cache(struct se_device *, int);
int se_dev_set_emulate_ua_intlck_ctrl(struct se_device *, int);
int se_dev_set_emulate_tas(struct se_device *, int);
int se_dev_set_emulate_tpu(struct se_device *, int);
int se_dev_set_emulate_tpws(struct se_device *, int);
int se_dev_set_emulate_caw(struct se_device *, int);
int se_dev_set_emulate_3pc(struct se_device *, int);
int se_dev_set_pi_prot_type(struct se_device *, int);
int se_dev_set_pi_prot_format(struct se_device *, int);
int se_dev_set_enforce_pr_isids(struct se_device *, int);
int se_dev_set_force_pr_aptpl(struct se_device *, int);
int se_dev_set_is_nonrot(struct se_device *, int);
int se_dev_set_emulate_rest_reord(struct se_device *dev, int);
int se_dev_set_queue_depth(struct se_device *, u32);
int se_dev_set_max_sectors(struct se_device *, u32);
int se_dev_set_optimal_sectors(struct se_device *, u32);
int se_dev_set_block_size(struct se_device *, u32);
sense_reason_t passthrough_parse_cdb(struct se_cmd *cmd, sense_reason_t passthrough_parse_cdb(struct se_cmd *cmd,
sense_reason_t (*exec_cmd)(struct se_cmd *cmd)); sense_reason_t (*exec_cmd)(struct se_cmd *cmd));

View File

@ -1,118 +0,0 @@
#ifndef TARGET_CORE_BACKEND_CONFIGFS_H
#define TARGET_CORE_BACKEND_CONFIGFS_H
#include <target/configfs_macros.h>
#define DEF_TB_DEV_ATTRIB_SHOW(_backend, _name) \
static ssize_t _backend##_dev_show_attr_##_name( \
struct se_dev_attrib *da, \
char *page) \
{ \
return snprintf(page, PAGE_SIZE, "%u\n", \
(u32)da->da_dev->dev_attrib._name); \
}
#define DEF_TB_DEV_ATTRIB_STORE(_backend, _name) \
static ssize_t _backend##_dev_store_attr_##_name( \
struct se_dev_attrib *da, \
const char *page, \
size_t count) \
{ \
unsigned long val; \
int ret; \
\
ret = kstrtoul(page, 0, &val); \
if (ret < 0) { \
pr_err("kstrtoul() failed with ret: %d\n", ret); \
return -EINVAL; \
} \
ret = se_dev_set_##_name(da->da_dev, (u32)val); \
\
return (!ret) ? count : -EINVAL; \
}
#define DEF_TB_DEV_ATTRIB(_backend, _name) \
DEF_TB_DEV_ATTRIB_SHOW(_backend, _name); \
DEF_TB_DEV_ATTRIB_STORE(_backend, _name);
#define DEF_TB_DEV_ATTRIB_RO(_backend, name) \
DEF_TB_DEV_ATTRIB_SHOW(_backend, name);
CONFIGFS_EATTR_STRUCT(target_backend_dev_attrib, se_dev_attrib);
#define TB_DEV_ATTR(_backend, _name, _mode) \
static struct target_backend_dev_attrib_attribute _backend##_dev_attrib_##_name = \
__CONFIGFS_EATTR(_name, _mode, \
_backend##_dev_show_attr_##_name, \
_backend##_dev_store_attr_##_name);
#define TB_DEV_ATTR_RO(_backend, _name) \
static struct target_backend_dev_attrib_attribute _backend##_dev_attrib_##_name = \
__CONFIGFS_EATTR_RO(_name, \
_backend##_dev_show_attr_##_name);
/*
* Default list of target backend device attributes as defined by
* struct se_dev_attrib
*/
#define DEF_TB_DEFAULT_ATTRIBS(_backend) \
DEF_TB_DEV_ATTRIB(_backend, emulate_model_alias); \
TB_DEV_ATTR(_backend, emulate_model_alias, S_IRUGO | S_IWUSR); \
DEF_TB_DEV_ATTRIB(_backend, emulate_dpo); \
TB_DEV_ATTR(_backend, emulate_dpo, S_IRUGO | S_IWUSR); \
DEF_TB_DEV_ATTRIB(_backend, emulate_fua_write); \
TB_DEV_ATTR(_backend, emulate_fua_write, S_IRUGO | S_IWUSR); \
DEF_TB_DEV_ATTRIB(_backend, emulate_fua_read); \
TB_DEV_ATTR(_backend, emulate_fua_read, S_IRUGO | S_IWUSR); \
DEF_TB_DEV_ATTRIB(_backend, emulate_write_cache); \
TB_DEV_ATTR(_backend, emulate_write_cache, S_IRUGO | S_IWUSR); \
DEF_TB_DEV_ATTRIB(_backend, emulate_ua_intlck_ctrl); \
TB_DEV_ATTR(_backend, emulate_ua_intlck_ctrl, S_IRUGO | S_IWUSR); \
DEF_TB_DEV_ATTRIB(_backend, emulate_tas); \
TB_DEV_ATTR(_backend, emulate_tas, S_IRUGO | S_IWUSR); \
DEF_TB_DEV_ATTRIB(_backend, emulate_tpu); \
TB_DEV_ATTR(_backend, emulate_tpu, S_IRUGO | S_IWUSR); \
DEF_TB_DEV_ATTRIB(_backend, emulate_tpws); \
TB_DEV_ATTR(_backend, emulate_tpws, S_IRUGO | S_IWUSR); \
DEF_TB_DEV_ATTRIB(_backend, emulate_caw); \
TB_DEV_ATTR(_backend, emulate_caw, S_IRUGO | S_IWUSR); \
DEF_TB_DEV_ATTRIB(_backend, emulate_3pc); \
TB_DEV_ATTR(_backend, emulate_3pc, S_IRUGO | S_IWUSR); \
DEF_TB_DEV_ATTRIB(_backend, pi_prot_type); \
TB_DEV_ATTR(_backend, pi_prot_type, S_IRUGO | S_IWUSR); \
DEF_TB_DEV_ATTRIB_RO(_backend, hw_pi_prot_type); \
TB_DEV_ATTR_RO(_backend, hw_pi_prot_type); \
DEF_TB_DEV_ATTRIB(_backend, pi_prot_format); \
TB_DEV_ATTR(_backend, pi_prot_format, S_IRUGO | S_IWUSR); \
DEF_TB_DEV_ATTRIB(_backend, enforce_pr_isids); \
TB_DEV_ATTR(_backend, enforce_pr_isids, S_IRUGO | S_IWUSR); \
DEF_TB_DEV_ATTRIB(_backend, is_nonrot); \
TB_DEV_ATTR(_backend, is_nonrot, S_IRUGO | S_IWUSR); \
DEF_TB_DEV_ATTRIB(_backend, emulate_rest_reord); \
TB_DEV_ATTR(_backend, emulate_rest_reord, S_IRUGO | S_IWUSR); \
DEF_TB_DEV_ATTRIB(_backend, force_pr_aptpl); \
TB_DEV_ATTR(_backend, force_pr_aptpl, S_IRUGO | S_IWUSR); \
DEF_TB_DEV_ATTRIB_RO(_backend, hw_block_size); \
TB_DEV_ATTR_RO(_backend, hw_block_size); \
DEF_TB_DEV_ATTRIB(_backend, block_size); \
TB_DEV_ATTR(_backend, block_size, S_IRUGO | S_IWUSR); \
DEF_TB_DEV_ATTRIB_RO(_backend, hw_max_sectors); \
TB_DEV_ATTR_RO(_backend, hw_max_sectors); \
DEF_TB_DEV_ATTRIB(_backend, optimal_sectors); \
TB_DEV_ATTR(_backend, optimal_sectors, S_IRUGO | S_IWUSR); \
DEF_TB_DEV_ATTRIB_RO(_backend, hw_queue_depth); \
TB_DEV_ATTR_RO(_backend, hw_queue_depth); \
DEF_TB_DEV_ATTRIB(_backend, queue_depth); \
TB_DEV_ATTR(_backend, queue_depth, S_IRUGO | S_IWUSR); \
DEF_TB_DEV_ATTRIB(_backend, max_unmap_lba_count); \
TB_DEV_ATTR(_backend, max_unmap_lba_count, S_IRUGO | S_IWUSR); \
DEF_TB_DEV_ATTRIB(_backend, max_unmap_block_desc_count); \
TB_DEV_ATTR(_backend, max_unmap_block_desc_count, S_IRUGO | S_IWUSR); \
DEF_TB_DEV_ATTRIB(_backend, unmap_granularity); \
TB_DEV_ATTR(_backend, unmap_granularity, S_IRUGO | S_IWUSR); \
DEF_TB_DEV_ATTRIB(_backend, unmap_granularity_alignment); \
TB_DEV_ATTR(_backend, unmap_granularity_alignment, S_IRUGO | S_IWUSR); \
DEF_TB_DEV_ATTRIB(_backend, max_write_same_len); \
TB_DEV_ATTR(_backend, max_write_same_len, S_IRUGO | S_IWUSR);
#endif /* TARGET_CORE_BACKEND_CONFIGFS_H */

View File

@ -9,12 +9,8 @@
#include <net/sock.h> #include <net/sock.h>
#include <net/tcp.h> #include <net/tcp.h>
#define TARGET_CORE_MOD_VERSION "v4.1.0" #define TARGET_CORE_VERSION "v5.0"
#define TARGET_CORE_VERSION TARGET_CORE_MOD_VERSION
/* Maximum Number of LUNs per Target Portal Group */
/* Don't raise above 511 or REPORT_LUNS needs to handle >1 page */
#define TRANSPORT_MAX_LUNS_PER_TPG 256
/* /*
* Maximum size of a CDB that can be stored in se_cmd without allocating * Maximum size of a CDB that can be stored in se_cmd without allocating
* memory dynamically for the CDB. * memory dynamically for the CDB.
@ -70,12 +66,6 @@
#define DA_MAX_WRITE_SAME_LEN 0 #define DA_MAX_WRITE_SAME_LEN 0
/* Use a model alias based on the configfs backend device name */ /* Use a model alias based on the configfs backend device name */
#define DA_EMULATE_MODEL_ALIAS 0 #define DA_EMULATE_MODEL_ALIAS 0
/* Emulation for Direct Page Out */
#define DA_EMULATE_DPO 0
/* Emulation for Forced Unit Access WRITEs */
#define DA_EMULATE_FUA_WRITE 1
/* Emulation for Forced Unit Access READs */
#define DA_EMULATE_FUA_READ 0
/* Emulation for WriteCache and SYNCHRONIZE_CACHE */ /* Emulation for WriteCache and SYNCHRONIZE_CACHE */
#define DA_EMULATE_WRITE_CACHE 0 #define DA_EMULATE_WRITE_CACHE 0
/* Emulation for UNIT ATTENTION Interlock Control */ /* Emulation for UNIT ATTENTION Interlock Control */
@ -116,18 +106,6 @@ enum hba_flags_table {
HBA_FLAGS_PSCSI_MODE = 0x02, HBA_FLAGS_PSCSI_MODE = 0x02,
}; };
/* struct se_lun->lun_status */
enum transport_lun_status_table {
TRANSPORT_LUN_STATUS_FREE = 0,
TRANSPORT_LUN_STATUS_ACTIVE = 1,
};
/* struct se_portal_group->se_tpg_type */
enum transport_tpg_type_table {
TRANSPORT_TPG_TYPE_NORMAL = 0,
TRANSPORT_TPG_TYPE_DISCOVERY = 1,
};
/* Special transport agnostic struct se_cmd->t_states */ /* Special transport agnostic struct se_cmd->t_states */
enum transport_state_table { enum transport_state_table {
TRANSPORT_NO_STATE = 0, TRANSPORT_NO_STATE = 0,
@ -158,14 +136,13 @@ enum se_cmd_flags_table {
SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC = 0x00020000, SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC = 0x00020000,
SCF_COMPARE_AND_WRITE = 0x00080000, SCF_COMPARE_AND_WRITE = 0x00080000,
SCF_COMPARE_AND_WRITE_POST = 0x00100000, SCF_COMPARE_AND_WRITE_POST = 0x00100000,
SCF_PASSTHROUGH_PROT_SG_TO_MEM_NOALLOC = 0x00200000,
}; };
/* struct se_dev_entry->lun_flags and struct se_lun->lun_access */ /* struct se_dev_entry->lun_flags and struct se_lun->lun_access */
enum transport_lunflags_table { enum transport_lunflags_table {
TRANSPORT_LUNFLAGS_NO_ACCESS = 0x00, TRANSPORT_LUNFLAGS_READ_ONLY = 0x01,
TRANSPORT_LUNFLAGS_INITIATOR_ACCESS = 0x01, TRANSPORT_LUNFLAGS_READ_WRITE = 0x02,
TRANSPORT_LUNFLAGS_READ_ONLY = 0x02,
TRANSPORT_LUNFLAGS_READ_WRITE = 0x04,
}; };
/* /*
@ -314,22 +291,13 @@ struct t10_alua_tg_pt_gp {
struct se_device *tg_pt_gp_dev; struct se_device *tg_pt_gp_dev;
struct config_group tg_pt_gp_group; struct config_group tg_pt_gp_group;
struct list_head tg_pt_gp_list; struct list_head tg_pt_gp_list;
struct list_head tg_pt_gp_mem_list; struct list_head tg_pt_gp_lun_list;
struct se_port *tg_pt_gp_alua_port; struct se_lun *tg_pt_gp_alua_lun;
struct se_node_acl *tg_pt_gp_alua_nacl; struct se_node_acl *tg_pt_gp_alua_nacl;
struct delayed_work tg_pt_gp_transition_work; struct delayed_work tg_pt_gp_transition_work;
struct completion *tg_pt_gp_transition_complete; struct completion *tg_pt_gp_transition_complete;
}; };
struct t10_alua_tg_pt_gp_member {
bool tg_pt_gp_assoc;
atomic_t tg_pt_gp_mem_ref_cnt;
spinlock_t tg_pt_gp_mem_lock;
struct t10_alua_tg_pt_gp *tg_pt_gp;
struct se_port *tg_pt;
struct list_head tg_pt_gp_mem_list;
};
struct t10_vpd { struct t10_vpd {
unsigned char device_identifier[INQUIRY_VPD_DEVICE_IDENTIFIER_LEN]; unsigned char device_identifier[INQUIRY_VPD_DEVICE_IDENTIFIER_LEN];
int protocol_identifier_set; int protocol_identifier_set;
@ -374,15 +342,16 @@ struct t10_pr_registration {
int pr_res_scope; int pr_res_scope;
/* Used for fabric initiator WWPNs using a ISID */ /* Used for fabric initiator WWPNs using a ISID */
bool isid_present_at_reg; bool isid_present_at_reg;
u32 pr_res_mapped_lun; u64 pr_res_mapped_lun;
u32 pr_aptpl_target_lun; u64 pr_aptpl_target_lun;
u16 tg_pt_sep_rtpi;
u32 pr_res_generation; u32 pr_res_generation;
u64 pr_reg_bin_isid; u64 pr_reg_bin_isid;
u64 pr_res_key; u64 pr_res_key;
atomic_t pr_res_holders; atomic_t pr_res_holders;
struct se_node_acl *pr_reg_nacl; struct se_node_acl *pr_reg_nacl;
/* Used by ALL_TG_PT=1 registration with deve->pr_ref taken */
struct se_dev_entry *pr_reg_deve; struct se_dev_entry *pr_reg_deve;
struct se_lun *pr_reg_tg_pt_lun;
struct list_head pr_reg_list; struct list_head pr_reg_list;
struct list_head pr_reg_abort_list; struct list_head pr_reg_abort_list;
struct list_head pr_reg_aptpl_list; struct list_head pr_reg_aptpl_list;
@ -422,7 +391,7 @@ struct se_tmr_req {
u8 response; u8 response;
int call_transport; int call_transport;
/* Reference to ITT that Task Mgmt should be performed */ /* Reference to ITT that Task Mgmt should be performed */
u32 ref_task_tag; u64 ref_task_tag;
void *fabric_tmr_ptr; void *fabric_tmr_ptr;
struct se_cmd *task_cmd; struct se_cmd *task_cmd;
struct se_device *tmr_dev; struct se_device *tmr_dev;
@ -475,6 +444,7 @@ struct se_cmd {
u8 scsi_asc; u8 scsi_asc;
u8 scsi_ascq; u8 scsi_ascq;
u16 scsi_sense_length; u16 scsi_sense_length;
u64 tag; /* SAM command identifier aka task tag */
/* Delay for ALUA Active/NonOptimized state access in milliseconds */ /* Delay for ALUA Active/NonOptimized state access in milliseconds */
int alua_nonop_delay; int alua_nonop_delay;
/* See include/linux/dma-mapping.h */ /* See include/linux/dma-mapping.h */
@ -493,7 +463,7 @@ struct se_cmd {
/* Total size in bytes associated with command */ /* Total size in bytes associated with command */
u32 data_length; u32 data_length;
u32 residual_count; u32 residual_count;
u32 orig_fe_lun; u64 orig_fe_lun;
/* Persistent Reservation key */ /* Persistent Reservation key */
u64 pr_res_key; u64 pr_res_key;
/* Used for sense data */ /* Used for sense data */
@ -501,7 +471,6 @@ struct se_cmd {
struct list_head se_delayed_node; struct list_head se_delayed_node;
struct list_head se_qf_node; struct list_head se_qf_node;
struct se_device *se_dev; struct se_device *se_dev;
struct se_dev_entry *se_deve;
struct se_lun *se_lun; struct se_lun *se_lun;
/* Only used for internal passthrough and legacy TCM fabric modules */ /* Only used for internal passthrough and legacy TCM fabric modules */
struct se_session *se_sess; struct se_session *se_sess;
@ -511,9 +480,8 @@ struct se_cmd {
struct kref cmd_kref; struct kref cmd_kref;
const struct target_core_fabric_ops *se_tfo; const struct target_core_fabric_ops *se_tfo;
sense_reason_t (*execute_cmd)(struct se_cmd *); sense_reason_t (*execute_cmd)(struct se_cmd *);
sense_reason_t (*execute_rw)(struct se_cmd *, struct scatterlist *,
u32, enum dma_data_direction);
sense_reason_t (*transport_complete_callback)(struct se_cmd *, bool); sense_reason_t (*transport_complete_callback)(struct se_cmd *, bool);
void *protocol_data;
unsigned char *t_task_cdb; unsigned char *t_task_cdb;
unsigned char __t_task_cdb[TCM_MAX_COMMAND_SIZE]; unsigned char __t_task_cdb[TCM_MAX_COMMAND_SIZE];
@ -569,7 +537,6 @@ struct se_cmd {
struct se_ua { struct se_ua {
u8 ua_asc; u8 ua_asc;
u8 ua_ascq; u8 ua_ascq;
struct se_node_acl *ua_nacl;
struct list_head ua_nacl_list; struct list_head ua_nacl_list;
}; };
@ -585,10 +552,10 @@ struct se_node_acl {
char acl_tag[MAX_ACL_TAG_SIZE]; char acl_tag[MAX_ACL_TAG_SIZE];
/* Used for PR SPEC_I_PT=1 and REGISTER_AND_MOVE */ /* Used for PR SPEC_I_PT=1 and REGISTER_AND_MOVE */
atomic_t acl_pr_ref_count; atomic_t acl_pr_ref_count;
struct se_dev_entry **device_list; struct hlist_head lun_entry_hlist;
struct se_session *nacl_sess; struct se_session *nacl_sess;
struct se_portal_group *se_tpg; struct se_portal_group *se_tpg;
spinlock_t device_list_lock; struct mutex lun_entry_mutex;
spinlock_t nacl_sess_lock; spinlock_t nacl_sess_lock;
struct config_group acl_group; struct config_group acl_group;
struct config_group acl_attrib_group; struct config_group acl_attrib_group;
@ -632,33 +599,37 @@ struct se_ml_stat_grps {
struct se_lun_acl { struct se_lun_acl {
char initiatorname[TRANSPORT_IQN_LEN]; char initiatorname[TRANSPORT_IQN_LEN];
u32 mapped_lun; u64 mapped_lun;
struct se_node_acl *se_lun_nacl; struct se_node_acl *se_lun_nacl;
struct se_lun *se_lun; struct se_lun *se_lun;
struct list_head lacl_list;
struct config_group se_lun_group; struct config_group se_lun_group;
struct se_ml_stat_grps ml_stat_grps; struct se_ml_stat_grps ml_stat_grps;
}; };
struct se_dev_entry { struct se_dev_entry {
bool def_pr_registered;
/* See transport_lunflags_table */ /* See transport_lunflags_table */
u32 lun_flags; u64 mapped_lun;
u32 mapped_lun;
u32 total_cmds;
u64 pr_res_key; u64 pr_res_key;
u64 creation_time; u64 creation_time;
u32 lun_flags;
u32 attach_count; u32 attach_count;
u64 read_bytes; atomic_long_t total_cmds;
u64 write_bytes; atomic_long_t read_bytes;
atomic_long_t write_bytes;
atomic_t ua_count; atomic_t ua_count;
/* Used for PR SPEC_I_PT=1 and REGISTER_AND_MOVE */ /* Used for PR SPEC_I_PT=1 and REGISTER_AND_MOVE */
atomic_t pr_ref_count; struct kref pr_kref;
struct se_lun_acl *se_lun_acl; struct completion pr_comp;
struct se_lun_acl __rcu *se_lun_acl;
spinlock_t ua_lock; spinlock_t ua_lock;
struct se_lun *se_lun; struct se_lun __rcu *se_lun;
#define DEF_PR_REG_ACTIVE 1
unsigned long deve_flags;
struct list_head alua_port_list; struct list_head alua_port_list;
struct list_head lun_link;
struct list_head ua_list; struct list_head ua_list;
struct hlist_node link;
struct rcu_head rcu_head;
}; };
struct se_dev_attrib { struct se_dev_attrib {
@ -703,25 +674,48 @@ struct se_port_stat_grps {
struct config_group scsi_transport_group; struct config_group scsi_transport_group;
}; };
struct scsi_port_stats {
atomic_long_t cmd_pdus;
atomic_long_t tx_data_octets;
atomic_long_t rx_data_octets;
};
struct se_lun { struct se_lun {
u64 unpacked_lun;
#define SE_LUN_LINK_MAGIC 0xffff7771 #define SE_LUN_LINK_MAGIC 0xffff7771
u32 lun_link_magic; u32 lun_link_magic;
/* See transport_lun_status_table */
enum transport_lun_status_table lun_status;
u32 lun_access; u32 lun_access;
u32 lun_flags; u32 lun_flags;
u32 unpacked_lun; u32 lun_index;
/* RELATIVE TARGET PORT IDENTIFER */
u16 lun_rtpi;
atomic_t lun_acl_count; atomic_t lun_acl_count;
spinlock_t lun_acl_lock; struct se_device __rcu *lun_se_dev;
spinlock_t lun_sep_lock;
struct completion lun_shutdown_comp; struct list_head lun_deve_list;
struct list_head lun_acl_list; spinlock_t lun_deve_lock;
struct se_device *lun_se_dev;
struct se_port *lun_sep; /* ALUA state */
int lun_tg_pt_secondary_stat;
int lun_tg_pt_secondary_write_md;
atomic_t lun_tg_pt_secondary_offline;
struct mutex lun_tg_pt_md_mutex;
/* ALUA target port group linkage */
struct list_head lun_tg_pt_gp_link;
struct t10_alua_tg_pt_gp *lun_tg_pt_gp;
spinlock_t lun_tg_pt_gp_lock;
struct se_portal_group *lun_tpg;
struct scsi_port_stats lun_stats;
struct config_group lun_group; struct config_group lun_group;
struct se_port_stat_grps port_stat_grps; struct se_port_stat_grps port_stat_grps;
struct completion lun_ref_comp; struct completion lun_ref_comp;
struct percpu_ref lun_ref; struct percpu_ref lun_ref;
struct list_head lun_dev_link;
struct hlist_node link;
struct rcu_head rcu_head;
}; };
struct se_dev_stat_grps { struct se_dev_stat_grps {
@ -744,7 +738,6 @@ struct se_device {
#define DF_EMULATED_VPD_UNIT_SERIAL 0x00000004 #define DF_EMULATED_VPD_UNIT_SERIAL 0x00000004
#define DF_USING_UDEV_PATH 0x00000008 #define DF_USING_UDEV_PATH 0x00000008
#define DF_USING_ALIAS 0x00000010 #define DF_USING_ALIAS 0x00000010
u32 dev_port_count;
/* Physical device queue depth */ /* Physical device queue depth */
u32 queue_depth; u32 queue_depth;
/* Used for SPC-2 reservations enforce of ISIDs */ /* Used for SPC-2 reservations enforce of ISIDs */
@ -761,7 +754,7 @@ struct se_device {
atomic_t dev_ordered_id; atomic_t dev_ordered_id;
atomic_t dev_ordered_sync; atomic_t dev_ordered_sync;
atomic_t dev_qf_count; atomic_t dev_qf_count;
int export_count; u32 export_count;
spinlock_t delayed_cmd_lock; spinlock_t delayed_cmd_lock;
spinlock_t execute_task_lock; spinlock_t execute_task_lock;
spinlock_t dev_reservation_lock; spinlock_t dev_reservation_lock;
@ -803,12 +796,15 @@ struct se_device {
#define SE_UDEV_PATH_LEN 512 /* must be less than PAGE_SIZE */ #define SE_UDEV_PATH_LEN 512 /* must be less than PAGE_SIZE */
unsigned char udev_path[SE_UDEV_PATH_LEN]; unsigned char udev_path[SE_UDEV_PATH_LEN];
/* Pointer to template of function pointers for transport */ /* Pointer to template of function pointers for transport */
struct se_subsystem_api *transport; const struct target_backend_ops *transport;
/* Linked list for struct se_hba struct se_device list */ /* Linked list for struct se_hba struct se_device list */
struct list_head dev_list; struct list_head dev_list;
struct se_lun xcopy_lun; struct se_lun xcopy_lun;
/* Protection Information */ /* Protection Information */
int prot_length; int prot_length;
/* For se_lun->lun_se_dev RCU read-side critical access */
u32 hba_index;
struct rcu_head rcu_head;
}; };
struct se_hba { struct se_hba {
@ -825,33 +821,7 @@ struct se_hba {
spinlock_t device_lock; spinlock_t device_lock;
struct config_group hba_group; struct config_group hba_group;
struct mutex hba_access_mutex; struct mutex hba_access_mutex;
struct se_subsystem_api *transport; struct target_backend *backend;
};
struct scsi_port_stats {
u64 cmd_pdus;
u64 tx_data_octets;
u64 rx_data_octets;
};
struct se_port {
/* RELATIVE TARGET PORT IDENTIFER */
u16 sep_rtpi;
int sep_tg_pt_secondary_stat;
int sep_tg_pt_secondary_write_md;
u32 sep_index;
struct scsi_port_stats sep_stats;
/* Used for ALUA Target Port Groups membership */
atomic_t sep_tg_pt_secondary_offline;
/* Used for PR ALL_TG_PT=1 */
atomic_t sep_tg_pt_ref_cnt;
spinlock_t sep_alua_lock;
struct mutex sep_tg_pt_md_mutex;
struct t10_alua_tg_pt_gp_member *sep_alua_tg_pt_gp_mem;
struct se_lun *sep_lun;
struct se_portal_group *sep_tpg;
struct list_head sep_alua_list;
struct list_head sep_list;
}; };
struct se_tpg_np { struct se_tpg_np {
@ -860,24 +830,26 @@ struct se_tpg_np {
}; };
struct se_portal_group { struct se_portal_group {
/* Type of target portal group, see transport_tpg_type_table */ /*
enum transport_tpg_type_table se_tpg_type; * PROTOCOL IDENTIFIER value per SPC4, 7.5.1.
*
* Negative values can be used by fabric drivers for internal use TPGs.
*/
int proto_id;
/* Number of ACLed Initiator Nodes for this TPG */ /* Number of ACLed Initiator Nodes for this TPG */
u32 num_node_acls; u32 num_node_acls;
/* Used for PR SPEC_I_PT=1 and REGISTER_AND_MOVE */ /* Used for PR SPEC_I_PT=1 and REGISTER_AND_MOVE */
atomic_t tpg_pr_ref_count; atomic_t tpg_pr_ref_count;
/* Spinlock for adding/removing ACLed Nodes */ /* Spinlock for adding/removing ACLed Nodes */
spinlock_t acl_node_lock; struct mutex acl_node_mutex;
/* Spinlock for adding/removing sessions */ /* Spinlock for adding/removing sessions */
spinlock_t session_lock; spinlock_t session_lock;
spinlock_t tpg_lun_lock; struct mutex tpg_lun_mutex;
/* Pointer to $FABRIC_MOD portal group */
void *se_tpg_fabric_ptr;
struct list_head se_tpg_node; struct list_head se_tpg_node;
/* linked list for initiator ACL list */ /* linked list for initiator ACL list */
struct list_head acl_node_list; struct list_head acl_node_list;
struct se_lun **tpg_lun_list; struct hlist_head tpg_lun_hlist;
struct se_lun tpg_virt_lun0; struct se_lun *tpg_virt_lun0;
/* List of TCM sessions associated wth this TPG */ /* List of TCM sessions associated wth this TPG */
struct list_head tpg_sess_list; struct list_head tpg_sess_list;
/* Pointer to $FABRIC_MOD dependent code */ /* Pointer to $FABRIC_MOD dependent code */

View File

@ -1,48 +0,0 @@
#define TARGET_CORE_CONFIGFS_VERSION TARGET_CORE_MOD_VERSION
#define TARGET_CORE_CONFIG_ROOT "/sys/kernel/config"
#define TARGET_CORE_NAME_MAX_LEN 64
#define TARGET_FABRIC_NAME_SIZE 32
struct target_fabric_configfs_template {
struct config_item_type tfc_discovery_cit;
struct config_item_type tfc_wwn_cit;
struct config_item_type tfc_wwn_fabric_stats_cit;
struct config_item_type tfc_tpg_cit;
struct config_item_type tfc_tpg_base_cit;
struct config_item_type tfc_tpg_lun_cit;
struct config_item_type tfc_tpg_port_cit;
struct config_item_type tfc_tpg_port_stat_cit;
struct config_item_type tfc_tpg_np_cit;
struct config_item_type tfc_tpg_np_base_cit;
struct config_item_type tfc_tpg_attrib_cit;
struct config_item_type tfc_tpg_auth_cit;
struct config_item_type tfc_tpg_param_cit;
struct config_item_type tfc_tpg_nacl_cit;
struct config_item_type tfc_tpg_nacl_base_cit;
struct config_item_type tfc_tpg_nacl_attrib_cit;
struct config_item_type tfc_tpg_nacl_auth_cit;
struct config_item_type tfc_tpg_nacl_param_cit;
struct config_item_type tfc_tpg_nacl_stat_cit;
struct config_item_type tfc_tpg_mappedlun_cit;
struct config_item_type tfc_tpg_mappedlun_stat_cit;
};
struct target_fabric_configfs {
char tf_name[TARGET_FABRIC_NAME_SIZE];
atomic_t tf_access_cnt;
struct list_head tf_list;
struct config_group tf_group;
struct config_group tf_disc_group;
struct config_group *tf_default_groups[2];
/* Pointer to fabric's config_item */
struct config_item *tf_fabric;
/* Passed from fabric modules */
struct config_item_type *tf_fabric_cit;
/* Pointer to fabric's struct module */
struct module *tf_module;
struct target_core_fabric_ops tf_ops;
struct target_fabric_configfs_template tf_cit_tmpl;
};

View File

@ -4,20 +4,11 @@
struct target_core_fabric_ops { struct target_core_fabric_ops {
struct module *module; struct module *module;
const char *name; const char *name;
size_t node_acl_size;
char *(*get_fabric_name)(void); char *(*get_fabric_name)(void);
u8 (*get_fabric_proto_ident)(struct se_portal_group *);
char *(*tpg_get_wwn)(struct se_portal_group *); char *(*tpg_get_wwn)(struct se_portal_group *);
u16 (*tpg_get_tag)(struct se_portal_group *); u16 (*tpg_get_tag)(struct se_portal_group *);
u32 (*tpg_get_default_depth)(struct se_portal_group *); u32 (*tpg_get_default_depth)(struct se_portal_group *);
u32 (*tpg_get_pr_transport_id)(struct se_portal_group *,
struct se_node_acl *,
struct t10_pr_registration *, int *,
unsigned char *);
u32 (*tpg_get_pr_transport_id_len)(struct se_portal_group *,
struct se_node_acl *,
struct t10_pr_registration *, int *);
char *(*tpg_parse_pr_out_transport_id)(struct se_portal_group *,
const char *, u32 *, char **);
int (*tpg_check_demo_mode)(struct se_portal_group *); int (*tpg_check_demo_mode)(struct se_portal_group *);
int (*tpg_check_demo_mode_cache)(struct se_portal_group *); int (*tpg_check_demo_mode_cache)(struct se_portal_group *);
int (*tpg_check_demo_mode_write_protect)(struct se_portal_group *); int (*tpg_check_demo_mode_write_protect)(struct se_portal_group *);
@ -36,10 +27,6 @@ struct target_core_fabric_ops {
* WRITE_STRIP and READ_INSERT operations. * WRITE_STRIP and READ_INSERT operations.
*/ */
int (*tpg_check_prot_fabric_only)(struct se_portal_group *); int (*tpg_check_prot_fabric_only)(struct se_portal_group *);
struct se_node_acl *(*tpg_alloc_fabric_acl)(
struct se_portal_group *);
void (*tpg_release_fabric_acl)(struct se_portal_group *,
struct se_node_acl *);
u32 (*tpg_get_inst_index)(struct se_portal_group *); u32 (*tpg_get_inst_index)(struct se_portal_group *);
/* /*
* Optional to release struct se_cmd and fabric dependent allocated * Optional to release struct se_cmd and fabric dependent allocated
@ -50,7 +37,6 @@ struct target_core_fabric_ops {
*/ */
int (*check_stop_free)(struct se_cmd *); int (*check_stop_free)(struct se_cmd *);
void (*release_cmd)(struct se_cmd *); void (*release_cmd)(struct se_cmd *);
void (*put_session)(struct se_session *);
/* /*
* Called with spin_lock_bh(struct se_portal_group->session_lock held. * Called with spin_lock_bh(struct se_portal_group->session_lock held.
*/ */
@ -66,7 +52,6 @@ struct target_core_fabric_ops {
int (*write_pending)(struct se_cmd *); int (*write_pending)(struct se_cmd *);
int (*write_pending_status)(struct se_cmd *); int (*write_pending_status)(struct se_cmd *);
void (*set_default_node_attributes)(struct se_node_acl *); void (*set_default_node_attributes)(struct se_node_acl *);
u32 (*get_task_tag)(struct se_cmd *);
int (*get_cmd_state)(struct se_cmd *); int (*get_cmd_state)(struct se_cmd *);
int (*queue_data_in)(struct se_cmd *); int (*queue_data_in)(struct se_cmd *);
int (*queue_status)(struct se_cmd *); int (*queue_status)(struct se_cmd *);
@ -88,9 +73,8 @@ struct target_core_fabric_ops {
struct se_tpg_np *(*fabric_make_np)(struct se_portal_group *, struct se_tpg_np *(*fabric_make_np)(struct se_portal_group *,
struct config_group *, const char *); struct config_group *, const char *);
void (*fabric_drop_np)(struct se_tpg_np *); void (*fabric_drop_np)(struct se_tpg_np *);
struct se_node_acl *(*fabric_make_nodeacl)(struct se_portal_group *, int (*fabric_init_nodeacl)(struct se_node_acl *, const char *);
struct config_group *, const char *); void (*fabric_cleanup_nodeacl)(struct se_node_acl *);
void (*fabric_drop_nodeacl)(struct se_node_acl *);
struct configfs_attribute **tfc_discovery_attrs; struct configfs_attribute **tfc_discovery_attrs;
struct configfs_attribute **tfc_wwn_attrs; struct configfs_attribute **tfc_wwn_attrs;
@ -132,16 +116,16 @@ void transport_deregister_session(struct se_session *);
void transport_init_se_cmd(struct se_cmd *, void transport_init_se_cmd(struct se_cmd *,
const struct target_core_fabric_ops *, const struct target_core_fabric_ops *,
struct se_session *, u32, int, int, unsigned char *); struct se_session *, u32, int, int, unsigned char *);
sense_reason_t transport_lookup_cmd_lun(struct se_cmd *, u32); sense_reason_t transport_lookup_cmd_lun(struct se_cmd *, u64);
sense_reason_t target_setup_cmd_from_cdb(struct se_cmd *, unsigned char *); sense_reason_t target_setup_cmd_from_cdb(struct se_cmd *, unsigned char *);
int target_submit_cmd_map_sgls(struct se_cmd *, struct se_session *, int target_submit_cmd_map_sgls(struct se_cmd *, struct se_session *,
unsigned char *, unsigned char *, u32, u32, int, int, int, unsigned char *, unsigned char *, u64, u32, int, int, int,
struct scatterlist *, u32, struct scatterlist *, u32, struct scatterlist *, u32, struct scatterlist *, u32,
struct scatterlist *, u32); struct scatterlist *, u32);
int target_submit_cmd(struct se_cmd *, struct se_session *, unsigned char *, int target_submit_cmd(struct se_cmd *, struct se_session *, unsigned char *,
unsigned char *, u32, u32, int, int, int); unsigned char *, u64, u32, int, int, int);
int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess, int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess,
unsigned char *sense, u32 unpacked_lun, unsigned char *sense, u64 unpacked_lun,
void *fabric_tmr_ptr, unsigned char tm_type, void *fabric_tmr_ptr, unsigned char tm_type,
gfp_t, unsigned int, int); gfp_t, unsigned int, int);
int transport_handle_cdb_direct(struct se_cmd *); int transport_handle_cdb_direct(struct se_cmd *);
@ -155,8 +139,8 @@ bool transport_wait_for_tasks(struct se_cmd *);
int transport_check_aborted_status(struct se_cmd *, int); int transport_check_aborted_status(struct se_cmd *, int);
int transport_send_check_condition_and_sense(struct se_cmd *, int transport_send_check_condition_and_sense(struct se_cmd *,
sense_reason_t, int); sense_reason_t, int);
int target_get_sess_cmd(struct se_session *, struct se_cmd *, bool); int target_get_sess_cmd(struct se_cmd *, bool);
int target_put_sess_cmd(struct se_session *, struct se_cmd *); int target_put_sess_cmd(struct se_cmd *);
void target_sess_cmd_list_set_waiting(struct se_session *); void target_sess_cmd_list_set_waiting(struct se_session *);
void target_wait_for_sess_cmds(struct se_session *); void target_wait_for_sess_cmds(struct se_session *);
@ -167,52 +151,19 @@ void core_tmr_release_req(struct se_tmr_req *);
int transport_generic_handle_tmr(struct se_cmd *); int transport_generic_handle_tmr(struct se_cmd *);
void transport_generic_request_failure(struct se_cmd *, sense_reason_t); void transport_generic_request_failure(struct se_cmd *, sense_reason_t);
void __target_execute_cmd(struct se_cmd *); void __target_execute_cmd(struct se_cmd *);
int transport_lookup_tmr_lun(struct se_cmd *, u32); int transport_lookup_tmr_lun(struct se_cmd *, u64);
struct se_node_acl *core_tpg_get_initiator_node_acl(struct se_portal_group *tpg, struct se_node_acl *core_tpg_get_initiator_node_acl(struct se_portal_group *tpg,
unsigned char *); unsigned char *);
struct se_node_acl *core_tpg_check_initiator_node_acl(struct se_portal_group *, struct se_node_acl *core_tpg_check_initiator_node_acl(struct se_portal_group *,
unsigned char *); unsigned char *);
void core_tpg_clear_object_luns(struct se_portal_group *);
struct se_node_acl *core_tpg_add_initiator_node_acl(struct se_portal_group *,
struct se_node_acl *, const char *, u32);
int core_tpg_del_initiator_node_acl(struct se_portal_group *,
struct se_node_acl *, int);
int core_tpg_set_initiator_node_queue_depth(struct se_portal_group *, int core_tpg_set_initiator_node_queue_depth(struct se_portal_group *,
unsigned char *, u32, int); unsigned char *, u32, int);
int core_tpg_set_initiator_node_tag(struct se_portal_group *, int core_tpg_set_initiator_node_tag(struct se_portal_group *,
struct se_node_acl *, const char *); struct se_node_acl *, const char *);
int core_tpg_register(const struct target_core_fabric_ops *, int core_tpg_register(struct se_wwn *, struct se_portal_group *, int);
struct se_wwn *, struct se_portal_group *, void *, int);
int core_tpg_deregister(struct se_portal_group *); int core_tpg_deregister(struct se_portal_group *);
/* SAS helpers */
u8 sas_get_fabric_proto_ident(struct se_portal_group *);
u32 sas_get_pr_transport_id(struct se_portal_group *, struct se_node_acl *,
struct t10_pr_registration *, int *, unsigned char *);
u32 sas_get_pr_transport_id_len(struct se_portal_group *, struct se_node_acl *,
struct t10_pr_registration *, int *);
char *sas_parse_pr_out_transport_id(struct se_portal_group *, const char *,
u32 *, char **);
/* FC helpers */
u8 fc_get_fabric_proto_ident(struct se_portal_group *);
u32 fc_get_pr_transport_id(struct se_portal_group *, struct se_node_acl *,
struct t10_pr_registration *, int *, unsigned char *);
u32 fc_get_pr_transport_id_len(struct se_portal_group *, struct se_node_acl *,
struct t10_pr_registration *, int *);
char *fc_parse_pr_out_transport_id(struct se_portal_group *, const char *,
u32 *, char **);
/* iSCSI helpers */
u8 iscsi_get_fabric_proto_ident(struct se_portal_group *);
u32 iscsi_get_pr_transport_id(struct se_portal_group *, struct se_node_acl *,
struct t10_pr_registration *, int *, unsigned char *);
u32 iscsi_get_pr_transport_id_len(struct se_portal_group *, struct se_node_acl *,
struct t10_pr_registration *, int *);
char *iscsi_parse_pr_out_transport_id(struct se_portal_group *, const char *,
u32 *, char **);
/* /*
* The LIO target core uses DMA_TO_DEVICE to mean that data is going * The LIO target core uses DMA_TO_DEVICE to mean that data is going
* to the target (eg handling a WRITE) and DMA_FROM_DEVICE to mean * to the target (eg handling a WRITE) and DMA_FROM_DEVICE to mean

View File

@ -19,7 +19,7 @@
static struct crypto_shash *crct10dif_tfm; static struct crypto_shash *crct10dif_tfm;
static struct static_key crct10dif_fallback __read_mostly; static struct static_key crct10dif_fallback __read_mostly;
__u16 crc_t10dif(const unsigned char *buffer, size_t len) __u16 crc_t10dif_update(__u16 crc, const unsigned char *buffer, size_t len)
{ {
struct { struct {
struct shash_desc shash; struct shash_desc shash;
@ -28,17 +28,23 @@ __u16 crc_t10dif(const unsigned char *buffer, size_t len)
int err; int err;
if (static_key_false(&crct10dif_fallback)) if (static_key_false(&crct10dif_fallback))
return crc_t10dif_generic(0, buffer, len); return crc_t10dif_generic(crc, buffer, len);
desc.shash.tfm = crct10dif_tfm; desc.shash.tfm = crct10dif_tfm;
desc.shash.flags = 0; desc.shash.flags = 0;
*(__u16 *)desc.ctx = 0; *(__u16 *)desc.ctx = crc;
err = crypto_shash_update(&desc.shash, buffer, len); err = crypto_shash_update(&desc.shash, buffer, len);
BUG_ON(err); BUG_ON(err);
return *(__u16 *)desc.ctx; return *(__u16 *)desc.ctx;
} }
EXPORT_SYMBOL(crc_t10dif_update);
__u16 crc_t10dif(const unsigned char *buffer, size_t len)
{
return crc_t10dif_update(0, buffer, len);
}
EXPORT_SYMBOL(crc_t10dif); EXPORT_SYMBOL(crc_t10dif);
static int __init crc_t10dif_mod_init(void) static int __init crc_t10dif_mod_init(void)