From e7b7af6e98b390c1f7d5d208d18cb7d8b7beb0f1 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Fri, 14 Nov 2014 12:54:36 -0800 Subject: target: Fix target_core_register_fabric() for built-in fabric modules If we try to create a fabric directory in configfs for one of the default hard-coded fabric modules (iscsi and loopback), and that fabric is actually built into the kernel, then the operation will spuriously fail because request_module() (for the code that's already linked into the kernel) fails. Fix this by running the autoprobing code only if an initial target_core_get_fabric() fails. Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_configfs.c | 75 ++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 33 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 79f9296a08ae..41498b696641 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -126,48 +126,57 @@ static struct config_group *target_core_register_fabric( pr_debug("Target_Core_ConfigFS: REGISTER -> group: %p name:" " %s\n", group, name); - /* - * Below are some hardcoded request_module() calls to automatically - * local fabric modules when the following is called: - * - * mkdir -p /sys/kernel/config/target/$MODULE_NAME - * - * Note that this does not limit which TCM fabric module can be - * registered, but simply provids auto loading logic for modules with - * mkdir(2) system calls with known TCM fabric modules. - */ - if (!strncmp(name, "iscsi", 5)) { + + tf = target_core_get_fabric(name); + if (!tf) { + pr_err("target_core_register_fabric() trying autoload for %s\n", + name); + /* - * Automatically load the LIO Target fabric module when the - * following is called: + * Below are some hardcoded request_module() calls to automatically + * local fabric modules when the following is called: * - * mkdir -p $CONFIGFS/target/iscsi - */ - ret = request_module("iscsi_target_mod"); - if (ret < 0) { - pr_err("request_module() failed for" - " iscsi_target_mod.ko: %d\n", ret); - return ERR_PTR(-EINVAL); - } - } else if (!strncmp(name, "loopback", 8)) { - /* - * Automatically load the tcm_loop fabric module when the - * following is called: + * mkdir -p /sys/kernel/config/target/$MODULE_NAME * - * mkdir -p $CONFIGFS/target/loopback + * Note that this does not limit which TCM fabric module can be + * registered, but simply provids auto loading logic for modules with + * mkdir(2) system calls with known TCM fabric modules. */ - ret = request_module("tcm_loop"); - if (ret < 0) { - pr_err("request_module() failed for" - " tcm_loop.ko: %d\n", ret); - return ERR_PTR(-EINVAL); + + if (!strncmp(name, "iscsi", 5)) { + /* + * Automatically load the LIO Target fabric module when the + * following is called: + * + * mkdir -p $CONFIGFS/target/iscsi + */ + ret = request_module("iscsi_target_mod"); + if (ret < 0) { + pr_err("request_module() failed for" + " iscsi_target_mod.ko: %d\n", ret); + return ERR_PTR(-EINVAL); + } + } else if (!strncmp(name, "loopback", 8)) { + /* + * Automatically load the tcm_loop fabric module when the + * following is called: + * + * mkdir -p $CONFIGFS/target/loopback + */ + ret = request_module("tcm_loop"); + if (ret < 0) { + pr_err("request_module() failed for" + " tcm_loop.ko: %d\n", ret); + return ERR_PTR(-EINVAL); + } } + + tf = target_core_get_fabric(name); } - tf = target_core_get_fabric(name); if (!tf) { pr_err("target_core_get_fabric() failed for %s\n", - name); + name); return ERR_PTR(-EINVAL); } pr_debug("Target_Core_ConfigFS: REGISTER -> Located fabric:" -- cgit v1.2.3 From 2ed37f6c9b69092afbbf2a990336f8cbd303947d Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Fri, 21 Nov 2014 10:25:45 +0100 Subject: target: Deletion of unnecessary checks before the function call "module_put" The module_put() function tests whether its argument is NULL and then returns immediately. Thus the test around the call is not needed. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_transport.c | 3 +-- drivers/target/target_core_hba.c | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/iscsi/iscsi_target_transport.c b/drivers/target/iscsi/iscsi_target_transport.c index 882728fac30c..08217d62fb0d 100644 --- a/drivers/target/iscsi/iscsi_target_transport.c +++ b/drivers/target/iscsi/iscsi_target_transport.c @@ -26,8 +26,7 @@ struct iscsit_transport *iscsit_get_transport(int type) void iscsit_put_transport(struct iscsit_transport *t) { - if (t->owner) - module_put(t->owner); + module_put(t->owner); } int iscsit_register_transport(struct iscsit_transport *t) diff --git a/drivers/target/target_core_hba.c b/drivers/target/target_core_hba.c index a25051a37dd7..e6e496ff9546 100644 --- a/drivers/target/target_core_hba.c +++ b/drivers/target/target_core_hba.c @@ -137,8 +137,7 @@ core_alloc_hba(const char *plugin_name, u32 plugin_dep_id, u32 hba_flags) return hba; out_module_put: - if (hba->transport->owner) - module_put(hba->transport->owner); + module_put(hba->transport->owner); hba->transport = NULL; out_free_hba: kfree(hba); @@ -159,8 +158,7 @@ core_delete_hba(struct se_hba *hba) pr_debug("CORE_HBA[%d] - Detached HBA from Generic Target" " Core\n", hba->hba_id); - if (hba->transport->owner) - module_put(hba->transport->owner); + module_put(hba->transport->owner); hba->transport = NULL; kfree(hba); -- cgit v1.2.3 From 73112edca9be1d7c37d0b94348c82c3742c3ef58 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 27 Nov 2014 13:59:20 -0800 Subject: target: Move dev_cit to struct se_subsystem_api This patch adds initial support for dev_cit as external config_item_type. This includes a new struct target_backend_cits to hold the external CITs within struct se_subsystem_api, and target_core_setup_sub_cits() to be used by backend drivers ahead of transport_subsystem_register(). It adds a TB_CIT_SETUP() helper following target_core_fabric_configfs.c to perform the config_item_type assignments. Also, drop left-over target_core_dev_cit from target_core_configfs.c code and update comments. Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_configfs.c | 33 ++++++++++++++++++++++++--------- drivers/target/target_core_hba.c | 1 + 2 files changed, 25 insertions(+), 9 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 41498b696641..f7b2186ba57b 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -50,6 +50,19 @@ #include "target_core_rd.h" #include "target_core_xcopy.h" +#define TB_CIT_SETUP(_name, _item_ops, _group_ops, _attrs) \ +static void target_core_setup_##_name##_cit(struct se_subsystem_api *sa) \ +{ \ + struct target_backend_cits *tbc = &sa->tb_cits; \ + struct config_item_type *cit = &tbc->tb_##_name##_cit; \ + \ + cit->ct_item_ops = _item_ops; \ + cit->ct_group_ops = _group_ops; \ + cit->ct_attrs = _attrs; \ + cit->ct_owner = sa->owner; \ + pr_debug("Setup generic %s\n", __stringify(_name)); \ +} + extern struct t10_alua_lu_gp *default_lu_gp; static LIST_HEAD(g_tf_list); @@ -1470,7 +1483,7 @@ static struct config_item_type target_core_dev_pr_cit = { /* End functions for struct config_item_type target_core_dev_pr_cit */ -/* Start functions for struct config_item_type target_core_dev_cit */ +/* Start functions for struct config_item_type tb_dev_cit */ static ssize_t target_core_show_dev_info(void *p, char *page) { @@ -1934,7 +1947,7 @@ static struct target_core_configfs_attribute target_core_attr_dev_lba_map = { .store = target_core_store_dev_lba_map, }; -static struct configfs_attribute *lio_core_dev_attrs[] = { +static struct configfs_attribute *target_core_dev_attrs[] = { &target_core_attr_dev_info.attr, &target_core_attr_dev_control.attr, &target_core_attr_dev_alias.attr, @@ -1993,13 +2006,9 @@ static struct configfs_item_operations target_core_dev_item_ops = { .store_attribute = target_core_dev_store, }; -static struct config_item_type target_core_dev_cit = { - .ct_item_ops = &target_core_dev_item_ops, - .ct_attrs = lio_core_dev_attrs, - .ct_owner = THIS_MODULE, -}; +TB_CIT_SETUP(dev, &target_core_dev_item_ops, NULL, target_core_dev_attrs); -/* End functions for struct config_item_type target_core_dev_cit */ +/* End functions for struct config_item_type tb_dev_cit */ /* Start functions for struct config_item_type target_core_alua_lu_gp_cit */ @@ -2815,7 +2824,7 @@ static struct config_group *target_core_make_subdev( if (!dev_cg->default_groups) goto out_free_device; - config_group_init_type_name(dev_cg, name, &target_core_dev_cit); + config_group_init_type_name(dev_cg, name, &t->tb_cits.tb_dev_cit); config_group_init_type_name(&dev->dev_attrib.da_group, "attrib", &target_core_dev_attrib_cit); config_group_init_type_name(&dev->dev_pr_group, "pr", @@ -3119,6 +3128,12 @@ static struct config_item_type target_core_cit = { /* Stop functions for struct config_item_type target_core_hba_cit */ +void target_core_setup_sub_cits(struct se_subsystem_api *sa) +{ + target_core_setup_dev_cit(sa); +} +EXPORT_SYMBOL(target_core_setup_sub_cits); + static int __init target_core_init_configfs(void) { struct config_group *target_cg, *hba_cg = NULL, *alua_cg = NULL; diff --git a/drivers/target/target_core_hba.c b/drivers/target/target_core_hba.c index e6e496ff9546..ff95f95dcd13 100644 --- a/drivers/target/target_core_hba.c +++ b/drivers/target/target_core_hba.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "target_core_internal.h" -- cgit v1.2.3 From f79a897efa6a95d698c4064e48e0a5afddc0ad9f Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 27 Nov 2014 14:51:14 -0800 Subject: target: Move dev_attrib_cit to struct se_subsystem_api This patch adds support for dev_attrib_cit as an external config_item_type using TB_CIT_SETUP() helper macro, and sets both ct_item_ops + ct_attr following existing code. It updates target_core_make_subdev() + target_core_setup_dev_attrib_cit() + struct target_backend_cits, and drops left-over target_core_dev_attrib_cit from target_core_configfs.c code and update comments. This patch introduces no functional change from existing code. Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_configfs.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index f7b2186ba57b..78ed857cc7b9 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -584,7 +584,7 @@ EXPORT_SYMBOL(target_fabric_configfs_deregister); // Stop functions called by external Target Fabrics Modules //############################################################################*/ -/* Start functions for struct config_item_type target_core_dev_attrib_cit */ +/* Start functions for struct config_item_type tb_dev_attrib_cit */ #define DEF_DEV_ATTRIB_SHOW(_name) \ static ssize_t target_core_dev_show_attr_##_name( \ @@ -767,13 +767,10 @@ static struct configfs_item_operations target_core_dev_attrib_ops = { .store_attribute = target_core_dev_attrib_attr_store, }; -static struct config_item_type target_core_dev_attrib_cit = { - .ct_item_ops = &target_core_dev_attrib_ops, - .ct_attrs = target_core_dev_attrib_attrs, - .ct_owner = THIS_MODULE, -}; +TB_CIT_SETUP(dev_attrib, &target_core_dev_attrib_ops, NULL, + target_core_dev_attrib_attrs); -/* End functions for struct config_item_type target_core_dev_attrib_cit */ +/* End functions for struct config_item_type tb_dev_attrib_cit */ /* Start functions for struct config_item_type target_core_dev_wwn_cit */ @@ -2826,7 +2823,7 @@ static struct config_group *target_core_make_subdev( config_group_init_type_name(dev_cg, name, &t->tb_cits.tb_dev_cit); config_group_init_type_name(&dev->dev_attrib.da_group, "attrib", - &target_core_dev_attrib_cit); + &t->tb_cits.tb_dev_attrib_cit); config_group_init_type_name(&dev->dev_pr_group, "pr", &target_core_dev_pr_cit); config_group_init_type_name(&dev->t10_wwn.t10_wwn_group, "wwn", @@ -3131,6 +3128,7 @@ static struct config_item_type target_core_cit = { void target_core_setup_sub_cits(struct se_subsystem_api *sa) { target_core_setup_dev_cit(sa); + target_core_setup_dev_attrib_cit(sa); } EXPORT_SYMBOL(target_core_setup_sub_cits); -- cgit v1.2.3 From 91e2e39ba89cd627beddafea2a760684adcec89d Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 27 Nov 2014 14:57:01 -0800 Subject: target: Move dev_pr_cit to struct se_subsystem_api This patch adds support for dev_pr_cit as an external config_item_type using TB_CIT_SETUP() helper macro, and sets both ct_item_ops + ct_attr following existing code. It updates target_core_make_subdev() + target_core_setup_dev_attrib_cit() + struct target_backend_cits, and drops left-over target_core_dev_pr_cit from target_core_configfs.c code and update comments. This patch introduces no functional change from existing code. Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_configfs.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 78ed857cc7b9..49d51ba40fca 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -1011,7 +1011,7 @@ static struct config_item_type target_core_dev_wwn_cit = { /* End functions for struct config_item_type target_core_dev_wwn_cit */ -/* Start functions for struct config_item_type target_core_dev_pr_cit */ +/* Start functions for struct config_item_type tb_dev_pr_cit */ CONFIGFS_EATTR_STRUCT(target_core_dev_pr, se_device); #define SE_DEV_PR_ATTR(_name, _mode) \ @@ -1472,13 +1472,9 @@ static struct configfs_item_operations target_core_dev_pr_ops = { .store_attribute = target_core_dev_pr_attr_store, }; -static struct config_item_type target_core_dev_pr_cit = { - .ct_item_ops = &target_core_dev_pr_ops, - .ct_attrs = target_core_dev_pr_attrs, - .ct_owner = THIS_MODULE, -}; +TB_CIT_SETUP(dev_pr, &target_core_dev_pr_ops, NULL, target_core_dev_pr_attrs); -/* End functions for struct config_item_type target_core_dev_pr_cit */ +/* End functions for struct config_item_type tb_dev_pr_cit */ /* Start functions for struct config_item_type tb_dev_cit */ @@ -2825,7 +2821,7 @@ static struct config_group *target_core_make_subdev( config_group_init_type_name(&dev->dev_attrib.da_group, "attrib", &t->tb_cits.tb_dev_attrib_cit); config_group_init_type_name(&dev->dev_pr_group, "pr", - &target_core_dev_pr_cit); + &t->tb_cits.tb_dev_pr_cit); config_group_init_type_name(&dev->t10_wwn.t10_wwn_group, "wwn", &target_core_dev_wwn_cit); config_group_init_type_name(&dev->t10_alua.alua_tg_pt_gps_group, @@ -3129,6 +3125,7 @@ void target_core_setup_sub_cits(struct se_subsystem_api *sa) { target_core_setup_dev_cit(sa); target_core_setup_dev_attrib_cit(sa); + target_core_setup_dev_pr_cit(sa); } EXPORT_SYMBOL(target_core_setup_sub_cits); -- cgit v1.2.3 From f8d389c6f6074aa382963ae13f9d77d99ec3e92d Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 27 Nov 2014 15:01:12 -0800 Subject: target: Move dev_wwn_cit to struct se_subsystem_api This patch adds support for dev_wwn_cit as an external config_item_type using TB_CIT_SETUP() helper macro, and sets both ct_item_ops + ct_attr following existing code. It updates target_core_make_subdev() + target_core_setup_dev_attrib_cit() + struct target_backend_cits, and drops left-over target_core_dev_wwn_cit from target_core_configfs.c code and update comments. This patch introduces no functional change from existing code. Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_configfs.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 49d51ba40fca..43d180e03931 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -772,7 +772,7 @@ TB_CIT_SETUP(dev_attrib, &target_core_dev_attrib_ops, NULL, /* End functions for struct config_item_type tb_dev_attrib_cit */ -/* Start functions for struct config_item_type target_core_dev_wwn_cit */ +/* Start functions for struct config_item_type tb_dev_wwn_cit */ CONFIGFS_EATTR_STRUCT(target_core_dev_wwn, t10_wwn); #define SE_DEV_WWN_ATTR(_name, _mode) \ @@ -1003,13 +1003,9 @@ static struct configfs_item_operations target_core_dev_wwn_ops = { .store_attribute = target_core_dev_wwn_attr_store, }; -static struct config_item_type target_core_dev_wwn_cit = { - .ct_item_ops = &target_core_dev_wwn_ops, - .ct_attrs = target_core_dev_wwn_attrs, - .ct_owner = THIS_MODULE, -}; +TB_CIT_SETUP(dev_wwn, &target_core_dev_wwn_ops, NULL, target_core_dev_wwn_attrs); -/* End functions for struct config_item_type target_core_dev_wwn_cit */ +/* End functions for struct config_item_type tb_dev_wwn_cit */ /* Start functions for struct config_item_type tb_dev_pr_cit */ @@ -2823,7 +2819,7 @@ static struct config_group *target_core_make_subdev( config_group_init_type_name(&dev->dev_pr_group, "pr", &t->tb_cits.tb_dev_pr_cit); config_group_init_type_name(&dev->t10_wwn.t10_wwn_group, "wwn", - &target_core_dev_wwn_cit); + &t->tb_cits.tb_dev_wwn_cit); config_group_init_type_name(&dev->t10_alua.alua_tg_pt_gps_group, "alua", &target_core_alua_tg_pt_gps_cit); config_group_init_type_name(&dev->dev_stat_grps.stat_group, @@ -3126,6 +3122,7 @@ void target_core_setup_sub_cits(struct se_subsystem_api *sa) target_core_setup_dev_cit(sa); target_core_setup_dev_attrib_cit(sa); target_core_setup_dev_pr_cit(sa); + target_core_setup_dev_wwn_cit(sa); } EXPORT_SYMBOL(target_core_setup_sub_cits); -- cgit v1.2.3 From 72aca57bd3fef535972b64c9cd76a088107c589c Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 27 Nov 2014 15:06:23 -0800 Subject: target: Move dev_alua_tg_pt_gps_cit to struct se_subsystem_api This patch adds support for dev_alua_tg_pt_gps_cit as an external config_item_type using TB_CIT_SETUP() helper macro, and sets only ct_group_ops following existing code. It updates target_core_make_subdev() + target_core_setup_dev_attrib_cit() + struct target_backend_cits, and drops left-over target_core_dev_alua_tg_pt_gps_cit from target_core_configfs.c code and update comments. This patch introduces no functional change from existing code. Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_configfs.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 43d180e03931..0cf41ad54bbf 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -2677,7 +2677,7 @@ static struct config_item_type target_core_alua_tg_pt_gp_cit = { /* End functions for struct config_item_type target_core_alua_tg_pt_gp_cit */ -/* Start functions for struct config_item_type target_core_alua_tg_pt_gps_cit */ +/* Start functions for struct config_item_type tb_alua_tg_pt_gps_cit */ static struct config_group *target_core_alua_create_tg_pt_gp( struct config_group *group, @@ -2728,12 +2728,9 @@ static struct configfs_group_operations target_core_alua_tg_pt_gps_group_ops = { .drop_item = &target_core_alua_drop_tg_pt_gp, }; -static struct config_item_type target_core_alua_tg_pt_gps_cit = { - .ct_group_ops = &target_core_alua_tg_pt_gps_group_ops, - .ct_owner = THIS_MODULE, -}; +TB_CIT_SETUP(dev_alua_tg_pt_gps, NULL, &target_core_alua_tg_pt_gps_group_ops, NULL); -/* End functions for struct config_item_type target_core_alua_tg_pt_gps_cit */ +/* End functions for struct config_item_type tb_alua_tg_pt_gps_cit */ /* Start functions for struct config_item_type target_core_alua_cit */ @@ -2821,7 +2818,7 @@ static struct config_group *target_core_make_subdev( config_group_init_type_name(&dev->t10_wwn.t10_wwn_group, "wwn", &t->tb_cits.tb_dev_wwn_cit); config_group_init_type_name(&dev->t10_alua.alua_tg_pt_gps_group, - "alua", &target_core_alua_tg_pt_gps_cit); + "alua", &t->tb_cits.tb_dev_alua_tg_pt_gps_cit); config_group_init_type_name(&dev->dev_stat_grps.stat_group, "statistics", &target_core_stat_cit); @@ -3123,6 +3120,7 @@ void target_core_setup_sub_cits(struct se_subsystem_api *sa) target_core_setup_dev_attrib_cit(sa); target_core_setup_dev_pr_cit(sa); target_core_setup_dev_wwn_cit(sa); + target_core_setup_dev_alua_tg_pt_gps_cit(sa); } EXPORT_SYMBOL(target_core_setup_sub_cits); -- cgit v1.2.3 From d23ab570bcb1de0256f1dcea0b8ad3af8e534e40 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 27 Nov 2014 15:09:32 -0800 Subject: target: Move dev_stat_cit to struct se_subsystem_api This patch adds support for dev_stat_cit as an external config_item_type using TB_CIT_SETUP() helper macro, and sets only ct_group_ops following existing code. It updates target_core_make_subdev() + target_core_setup_dev_attrib_cit() + struct target_backend_cits, and drops left-over target_core_dev_stat_cit from target_core_configfs.c code and update comments. This patch introduces no functional change from existing code. Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_configfs.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 0cf41ad54bbf..2903d8931625 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -2748,7 +2748,7 @@ static struct config_item_type target_core_alua_cit = { /* End functions for struct config_item_type target_core_alua_cit */ -/* Start functions for struct config_item_type target_core_stat_cit */ +/* Start functions for struct config_item_type tb_dev_stat_cit */ static struct config_group *target_core_stat_mkdir( struct config_group *group, @@ -2769,12 +2769,9 @@ static struct configfs_group_operations target_core_stat_group_ops = { .drop_item = &target_core_stat_rmdir, }; -static struct config_item_type target_core_stat_cit = { - .ct_group_ops = &target_core_stat_group_ops, - .ct_owner = THIS_MODULE, -}; +TB_CIT_SETUP(dev_stat, NULL, &target_core_stat_group_ops, NULL); -/* End functions for struct config_item_type target_core_stat_cit */ +/* End functions for struct config_item_type tb_dev_stat_cit */ /* Start functions for struct config_item_type target_core_hba_cit */ @@ -2820,7 +2817,7 @@ static struct config_group *target_core_make_subdev( config_group_init_type_name(&dev->t10_alua.alua_tg_pt_gps_group, "alua", &t->tb_cits.tb_dev_alua_tg_pt_gps_cit); config_group_init_type_name(&dev->dev_stat_grps.stat_group, - "statistics", &target_core_stat_cit); + "statistics", &t->tb_cits.tb_dev_stat_cit); dev_cg->default_groups[0] = &dev->dev_attrib.da_group; dev_cg->default_groups[1] = &dev->dev_pr_group; @@ -3121,6 +3118,7 @@ void target_core_setup_sub_cits(struct se_subsystem_api *sa) target_core_setup_dev_pr_cit(sa); target_core_setup_dev_wwn_cit(sa); target_core_setup_dev_alua_tg_pt_gps_cit(sa); + target_core_setup_dev_stat_cit(sa); } EXPORT_SYMBOL(target_core_setup_sub_cits); -- cgit v1.2.3 From d30cd1238c2f89662c82d5d2c4686971a6dc3693 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 27 Nov 2014 19:15:48 -0800 Subject: target: Add EXPORT_SYMBOL for existing se_dev_set_* Now that target_core_backend_configfs.h macros will be using these se_dev_set attribute functions externally to allow backend drivers to populate different attributes, go ahead and add EXPORT_SYMBOL() for the existing default set of 30 device attributes. Also update target_core_backend.h with proper function prototypes. Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_device.c | 26 ++++++++++++++++++++++++++ drivers/target/target_core_iblock.c | 1 + drivers/target/target_core_internal.h | 28 ---------------------------- 3 files changed, 27 insertions(+), 28 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index c45f9e907e44..953fff79bc14 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -659,6 +659,7 @@ int se_dev_set_max_unmap_lba_count( dev, dev->dev_attrib.max_unmap_lba_count); return 0; } +EXPORT_SYMBOL(se_dev_set_max_unmap_lba_count); int se_dev_set_max_unmap_block_desc_count( struct se_device *dev, @@ -670,6 +671,7 @@ int se_dev_set_max_unmap_block_desc_count( dev, dev->dev_attrib.max_unmap_block_desc_count); return 0; } +EXPORT_SYMBOL(se_dev_set_max_unmap_block_desc_count); int se_dev_set_unmap_granularity( struct se_device *dev, @@ -680,6 +682,7 @@ int se_dev_set_unmap_granularity( dev, dev->dev_attrib.unmap_granularity); return 0; } +EXPORT_SYMBOL(se_dev_set_unmap_granularity); int se_dev_set_unmap_granularity_alignment( struct se_device *dev, @@ -690,6 +693,7 @@ int se_dev_set_unmap_granularity_alignment( dev, dev->dev_attrib.unmap_granularity_alignment); return 0; } +EXPORT_SYMBOL(se_dev_set_unmap_granularity_alignment); int se_dev_set_max_write_same_len( struct se_device *dev, @@ -700,6 +704,7 @@ int se_dev_set_max_write_same_len( dev, dev->dev_attrib.max_write_same_len); return 0; } +EXPORT_SYMBOL(se_dev_set_max_write_same_len); static void dev_set_t10_wwn_model_alias(struct se_device *dev) { @@ -738,6 +743,7 @@ int se_dev_set_emulate_model_alias(struct se_device *dev, int flag) return 0; } +EXPORT_SYMBOL(se_dev_set_emulate_model_alias); int se_dev_set_emulate_dpo(struct se_device *dev, int flag) { @@ -753,6 +759,7 @@ int se_dev_set_emulate_dpo(struct se_device *dev, int flag) return 0; } +EXPORT_SYMBOL(se_dev_set_emulate_dpo); int se_dev_set_emulate_fua_write(struct se_device *dev, int flag) { @@ -771,6 +778,7 @@ int se_dev_set_emulate_fua_write(struct se_device *dev, int flag) dev, dev->dev_attrib.emulate_fua_write); return 0; } +EXPORT_SYMBOL(se_dev_set_emulate_fua_write); int se_dev_set_emulate_fua_read(struct se_device *dev, int flag) { @@ -786,6 +794,7 @@ int se_dev_set_emulate_fua_read(struct se_device *dev, int flag) return 0; } +EXPORT_SYMBOL(se_dev_set_emulate_fua_read); int se_dev_set_emulate_write_cache(struct se_device *dev, int flag) { @@ -809,6 +818,7 @@ int se_dev_set_emulate_write_cache(struct se_device *dev, int flag) dev, dev->dev_attrib.emulate_write_cache); return 0; } +EXPORT_SYMBOL(se_dev_set_emulate_write_cache); int se_dev_set_emulate_ua_intlck_ctrl(struct se_device *dev, int flag) { @@ -829,6 +839,7 @@ int se_dev_set_emulate_ua_intlck_ctrl(struct se_device *dev, int flag) return 0; } +EXPORT_SYMBOL(se_dev_set_emulate_ua_intlck_ctrl); int se_dev_set_emulate_tas(struct se_device *dev, int flag) { @@ -849,6 +860,7 @@ int se_dev_set_emulate_tas(struct se_device *dev, int flag) return 0; } +EXPORT_SYMBOL(se_dev_set_emulate_tas); int se_dev_set_emulate_tpu(struct se_device *dev, int flag) { @@ -870,6 +882,7 @@ int se_dev_set_emulate_tpu(struct se_device *dev, int flag) dev, flag); return 0; } +EXPORT_SYMBOL(se_dev_set_emulate_tpu); int se_dev_set_emulate_tpws(struct se_device *dev, int flag) { @@ -891,6 +904,7 @@ int se_dev_set_emulate_tpws(struct se_device *dev, int flag) dev, flag); return 0; } +EXPORT_SYMBOL(se_dev_set_emulate_tpws); int se_dev_set_emulate_caw(struct se_device *dev, int flag) { @@ -904,6 +918,7 @@ int se_dev_set_emulate_caw(struct se_device *dev, int flag) return 0; } +EXPORT_SYMBOL(se_dev_set_emulate_caw); int se_dev_set_emulate_3pc(struct se_device *dev, int flag) { @@ -917,6 +932,7 @@ int se_dev_set_emulate_3pc(struct se_device *dev, int flag) return 0; } +EXPORT_SYMBOL(se_dev_set_emulate_3pc); int se_dev_set_pi_prot_type(struct se_device *dev, int flag) { @@ -970,6 +986,7 @@ int se_dev_set_pi_prot_type(struct se_device *dev, int flag) return 0; } +EXPORT_SYMBOL(se_dev_set_pi_prot_type); int se_dev_set_pi_prot_format(struct se_device *dev, int flag) { @@ -1005,6 +1022,7 @@ int se_dev_set_pi_prot_format(struct se_device *dev, int flag) return 0; } +EXPORT_SYMBOL(se_dev_set_pi_prot_format); int se_dev_set_enforce_pr_isids(struct se_device *dev, int flag) { @@ -1017,6 +1035,7 @@ int se_dev_set_enforce_pr_isids(struct se_device *dev, int flag) (dev->dev_attrib.enforce_pr_isids) ? "Enabled" : "Disabled"); return 0; } +EXPORT_SYMBOL(se_dev_set_enforce_pr_isids); int se_dev_set_force_pr_aptpl(struct se_device *dev, int flag) { @@ -1034,6 +1053,7 @@ int se_dev_set_force_pr_aptpl(struct se_device *dev, int flag) pr_debug("dev[%p]: SE Device force_pr_aptpl: %d\n", dev, flag); return 0; } +EXPORT_SYMBOL(se_dev_set_force_pr_aptpl); int se_dev_set_is_nonrot(struct se_device *dev, int flag) { @@ -1046,6 +1066,7 @@ int se_dev_set_is_nonrot(struct se_device *dev, int flag) dev, flag); return 0; } +EXPORT_SYMBOL(se_dev_set_is_nonrot); int se_dev_set_emulate_rest_reord(struct se_device *dev, int flag) { @@ -1058,6 +1079,7 @@ int se_dev_set_emulate_rest_reord(struct se_device *dev, int flag) pr_debug("dev[%p]: SE Device emulate_rest_reord: %d\n", dev, flag); return 0; } +EXPORT_SYMBOL(se_dev_set_emulate_rest_reord); /* * Note, this can only be called on unexported SE Device Object. @@ -1101,6 +1123,7 @@ int se_dev_set_queue_depth(struct se_device *dev, u32 queue_depth) dev, queue_depth); return 0; } +EXPORT_SYMBOL(se_dev_set_queue_depth); int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors) { @@ -1155,6 +1178,7 @@ int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors) dev, fabric_max_sectors); return 0; } +EXPORT_SYMBOL(se_dev_set_fabric_max_sectors); int se_dev_set_optimal_sectors(struct se_device *dev, u32 optimal_sectors) { @@ -1181,6 +1205,7 @@ int se_dev_set_optimal_sectors(struct se_device *dev, u32 optimal_sectors) dev, optimal_sectors); return 0; } +EXPORT_SYMBOL(se_dev_set_optimal_sectors); int se_dev_set_block_size(struct se_device *dev, u32 block_size) { @@ -1218,6 +1243,7 @@ int se_dev_set_block_size(struct se_device *dev, u32 block_size) return 0; } +EXPORT_SYMBOL(se_dev_set_block_size); struct se_lun *core_dev_add_lun( struct se_portal_group *tpg, diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 7e6b857c6b3f..5e69d36af105 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -858,6 +858,7 @@ static bool iblock_get_write_cache(struct se_device *dev) return q->flush_flags & REQ_FLUSH; } + static struct se_subsystem_api iblock_template = { .name = "iblock", .inquiry_prod = "IBLOCK", diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h index e31f42f369ff..60381db90026 100644 --- a/drivers/target/target_core_internal.h +++ b/drivers/target/target_core_internal.h @@ -18,34 +18,6 @@ int core_dev_export(struct se_device *, struct se_portal_group *, struct se_lun *); void core_dev_unexport(struct se_device *, struct se_portal_group *, struct se_lun *); -int se_dev_set_task_timeout(struct se_device *, u32); -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_fabric_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); 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 *); struct se_lun *core_get_lun_from_tpg(struct se_portal_group *, u32); -- cgit v1.2.3 From 5645cba011ddaf7dc46a636e5657bb764e11a472 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 27 Nov 2014 19:53:28 -0800 Subject: target/iblock: Convert to external iblock_backend_dev_attrs This patch converts IBLOCK to use an external set of device attributes, and utilizes target_core_backend_configfs.h macros to generate a default set of configfs extended-attr handlers. It calls target_core_setup_sub_cits() to setup the initial config_item_type based on existing target_core_configfs.c defaults, and using configfs_attribute generated by DEF_TB_DEFAULT_ATTRIBS(iblock) populates iblock_backend_dev_attrs[] It introduces no functional change for existing IBLOCK device attributes. Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_iblock.c | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'drivers/target') diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 5e69d36af105..3efff94fbd97 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -41,6 +41,7 @@ #include #include +#include #include "target_core_iblock.h" @@ -858,6 +859,41 @@ static bool iblock_get_write_cache(struct se_device *dev) return q->flush_flags & REQ_FLUSH; } +DEF_TB_DEFAULT_ATTRIBS(iblock); + +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_fabric_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", @@ -884,6 +920,11 @@ static struct se_subsystem_api iblock_template = { static int __init iblock_module_init(void) { + struct target_backend_cits *tbc = &iblock_template.tb_cits; + + target_core_setup_sub_cits(&iblock_template); + tbc->tb_dev_attrib_cit.ct_attrs = iblock_backend_dev_attrs; + return transport_subsystem_register(&iblock_template); } -- cgit v1.2.3 From b23204970af2ce59c160f87f42baeacac33becb4 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 28 Nov 2014 04:56:30 +0000 Subject: target/file: Convert to external fileio_backend_dev_attrs This patch converts FILEIO to use an external set of device attributes, and utilizes target_core_backend_configfs.h macros to generate a default set of configfs extended-attr handlers. It calls target_core_setup_sub_cits() to setup the initial config_item_type based on existing target_core_configfs.c defaults, and using configfs_attribute generated by DEF_TB_DEFAULT_ATTRIBS(fileio) populates fileio_backend_dev_attrs[] It introduces no functional change for existing FILEIO device attributes. Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_file.c | 42 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'drivers/target') diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 72c83d98662b..c2aea099ea4a 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -37,6 +37,7 @@ #include #include +#include #include "target_core_file.h" @@ -934,6 +935,42 @@ fd_parse_cdb(struct se_cmd *cmd) return sbc_parse_cdb(cmd, &fd_sbc_ops); } +DEF_TB_DEFAULT_ATTRIBS(fileio); + +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_fabric_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", .inquiry_prod = "FILEIO", @@ -957,6 +994,11 @@ static struct se_subsystem_api fileio_template = { static int __init fileio_module_init(void) { + struct target_backend_cits *tbc = &fileio_template.tb_cits; + + target_core_setup_sub_cits(&fileio_template); + tbc->tb_dev_attrib_cit.ct_attrs = fileio_backend_dev_attrs; + return transport_subsystem_register(&fileio_template); } -- cgit v1.2.3 From 03a627457e8440fe09e173dcc7d59a7c0a202d03 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 28 Nov 2014 05:06:10 +0000 Subject: target/rd: Convert to external rd_mcp_backend_dev_attrs This patch converts RAMDISK to use an external set of device attributes, and utilizes target_core_backend_configfs.h macros to generate a default set of configfs extended-attr handlers. It calls target_core_setup_sub_cits() to setup the initial config_item_type based on existing target_core_configfs.c defaults, and using configfs_attribute generated by DEF_TB_DEFAULT_ATTRIBS(rc_mcp) populates rd_mcp_backend_dev_attrs[] It introduces no functional change for existing RD_MCP device attributes. Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_rd.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'drivers/target') diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c index b920db3388cd..60ebd170a561 100644 --- a/drivers/target/target_core_rd.c +++ b/drivers/target/target_core_rd.c @@ -34,6 +34,7 @@ #include #include +#include #include "target_core_rd.h" @@ -632,6 +633,42 @@ rd_parse_cdb(struct se_cmd *cmd) return sbc_parse_cdb(cmd, &rd_sbc_ops); } +DEF_TB_DEFAULT_ATTRIBS(rd_mcp); + +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_fabric_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", .inquiry_prod = "RAMDISK-MCP", @@ -653,8 +690,12 @@ static struct se_subsystem_api rd_mcp_template = { int __init rd_module_init(void) { + struct target_backend_cits *tbc = &rd_mcp_template.tb_cits; 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; -- cgit v1.2.3 From e9f720d63b476c9dc2a936c186878f1795b8b4c5 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 28 Nov 2014 05:11:24 +0000 Subject: target/user: Convert to external tcmu_backend_dev_attrs This patch converts TCM-USER to use an external set of device attributes, and utilizes target_core_backend_configfs.h macros to generate a default set of configfs extended-attr handlers. It calls target_core_setup_sub_cits() to setup the initial config_item_type based on existing target_core_configfs.c defaults, and using configfs_attribute generated by DEF_TB_DEFAULT_ATTRIBS(tcmu) populates tcmu_backend_dev_attrs[] It introduces no function change for existing TCMU device attributes. Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_user.c | 42 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'drivers/target') diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c index 9a1b314f6482..8bfa61c9693d 100644 --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c @@ -28,6 +28,8 @@ #include #include #include +#include + #include /* @@ -1092,6 +1094,42 @@ tcmu_parse_cdb(struct se_cmd *cmd) return ret; } +DEF_TB_DEFAULT_ATTRIBS(tcmu); + +static struct configfs_attribute *tcmu_backend_dev_attrs[] = { + &tcmu_dev_attrib_emulate_model_alias.attr, + &tcmu_dev_attrib_emulate_dpo.attr, + &tcmu_dev_attrib_emulate_fua_write.attr, + &tcmu_dev_attrib_emulate_fua_read.attr, + &tcmu_dev_attrib_emulate_write_cache.attr, + &tcmu_dev_attrib_emulate_ua_intlck_ctrl.attr, + &tcmu_dev_attrib_emulate_tas.attr, + &tcmu_dev_attrib_emulate_tpu.attr, + &tcmu_dev_attrib_emulate_tpws.attr, + &tcmu_dev_attrib_emulate_caw.attr, + &tcmu_dev_attrib_emulate_3pc.attr, + &tcmu_dev_attrib_pi_prot_type.attr, + &tcmu_dev_attrib_hw_pi_prot_type.attr, + &tcmu_dev_attrib_pi_prot_format.attr, + &tcmu_dev_attrib_enforce_pr_isids.attr, + &tcmu_dev_attrib_is_nonrot.attr, + &tcmu_dev_attrib_emulate_rest_reord.attr, + &tcmu_dev_attrib_force_pr_aptpl.attr, + &tcmu_dev_attrib_hw_block_size.attr, + &tcmu_dev_attrib_block_size.attr, + &tcmu_dev_attrib_hw_max_sectors.attr, + &tcmu_dev_attrib_fabric_max_sectors.attr, + &tcmu_dev_attrib_optimal_sectors.attr, + &tcmu_dev_attrib_hw_queue_depth.attr, + &tcmu_dev_attrib_queue_depth.attr, + &tcmu_dev_attrib_max_unmap_lba_count.attr, + &tcmu_dev_attrib_max_unmap_block_desc_count.attr, + &tcmu_dev_attrib_unmap_granularity.attr, + &tcmu_dev_attrib_unmap_granularity_alignment.attr, + &tcmu_dev_attrib_max_write_same_len.attr, + NULL, +}; + static struct se_subsystem_api tcmu_template = { .name = "user", .inquiry_prod = "USER", @@ -1112,6 +1150,7 @@ static struct se_subsystem_api tcmu_template = { static int __init tcmu_module_init(void) { + struct target_backend_cits *tbc = &tcmu_template.tb_cits; int ret; BUILD_BUG_ON((sizeof(struct tcmu_cmd_entry) % TCMU_OP_ALIGN_SIZE) != 0); @@ -1134,6 +1173,9 @@ static int __init tcmu_module_init(void) goto out_unreg_device; } + target_core_setup_sub_cits(&tcmu_template); + tbc->tb_dev_attrib_cit.ct_attrs = tcmu_backend_dev_attrs; + ret = transport_subsystem_register(&tcmu_template); if (ret) goto out_unreg_genl; -- cgit v1.2.3 From 6cfb546bfce644bd4fb6662a5049a73406f655c9 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 28 Nov 2014 05:26:18 +0000 Subject: target/pscsi: Convert to external pscsi_backend_dev_attrs This patch converts PSCSI to use an external set of device attributes, and utilizes target_core_backend_configfs.h macros to generate a default set of configfs extended-attr handlers. It calls target_core_setup_sub_cits() to setup the initial config_item_type based on existing target_core_configfs.c defaults, and using configfs_attribute for hw_pi_prot_type, hw_block_size, hw_max_sectors, hw_queue_depth populates pscsi_backend_dev_attrs[] Only these four hw_* read-only device attributes are exports for PSCSI. Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pscsi.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers/target') diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 7c8291f0bbbc..74873e42cf7e 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -44,6 +44,7 @@ #include #include +#include #include "target_core_alua.h" #include "target_core_pscsi.h" @@ -1165,6 +1166,26 @@ static void pscsi_req_done(struct request *req, int uptodate) kfree(pt); } +DEF_TB_DEV_ATTRIB_RO(pscsi, hw_pi_prot_type); +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", .owner = THIS_MODULE, @@ -1185,6 +1206,11 @@ static struct se_subsystem_api pscsi_template = { static int __init pscsi_module_init(void) { + struct target_backend_cits *tbc = &pscsi_template.tb_cits; + + target_core_setup_sub_cits(&pscsi_template); + tbc->tb_dev_attrib_cit.ct_attrs = pscsi_backend_dev_attrs; + return transport_subsystem_register(&pscsi_template); } -- cgit v1.2.3 From 43cf208cbe2080ff0212bd3527d915395b6129f6 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 28 Nov 2014 05:34:39 +0000 Subject: target: Drop left-over internal dev attribute code Now that backend drivers are populating their own device attributes, go ahead and remove left-over definitions + internal attribute list of device attributes from target_core_configfs.c code Also update TB_CIT_SETUP(dev_attrib,...) to signal ct_attr = NULL. Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_configfs.c | 176 +--------------------------------- 1 file changed, 1 insertion(+), 175 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 2903d8931625..75d89adfccc0 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -586,189 +586,15 @@ EXPORT_SYMBOL(target_fabric_configfs_deregister); /* Start functions for struct config_item_type tb_dev_attrib_cit */ -#define DEF_DEV_ATTRIB_SHOW(_name) \ -static ssize_t target_core_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_DEV_ATTRIB_STORE(_name) \ -static ssize_t target_core_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_DEV_ATTRIB(_name) \ -DEF_DEV_ATTRIB_SHOW(_name); \ -DEF_DEV_ATTRIB_STORE(_name); - -#define DEF_DEV_ATTRIB_RO(_name) \ -DEF_DEV_ATTRIB_SHOW(_name); - CONFIGFS_EATTR_STRUCT(target_core_dev_attrib, se_dev_attrib); -#define SE_DEV_ATTR(_name, _mode) \ -static struct target_core_dev_attrib_attribute \ - target_core_dev_attrib_##_name = \ - __CONFIGFS_EATTR(_name, _mode, \ - target_core_dev_show_attr_##_name, \ - target_core_dev_store_attr_##_name); - -#define SE_DEV_ATTR_RO(_name); \ -static struct target_core_dev_attrib_attribute \ - target_core_dev_attrib_##_name = \ - __CONFIGFS_EATTR_RO(_name, \ - target_core_dev_show_attr_##_name); - -DEF_DEV_ATTRIB(emulate_model_alias); -SE_DEV_ATTR(emulate_model_alias, S_IRUGO | S_IWUSR); - -DEF_DEV_ATTRIB(emulate_dpo); -SE_DEV_ATTR(emulate_dpo, S_IRUGO | S_IWUSR); - -DEF_DEV_ATTRIB(emulate_fua_write); -SE_DEV_ATTR(emulate_fua_write, S_IRUGO | S_IWUSR); - -DEF_DEV_ATTRIB(emulate_fua_read); -SE_DEV_ATTR(emulate_fua_read, S_IRUGO | S_IWUSR); - -DEF_DEV_ATTRIB(emulate_write_cache); -SE_DEV_ATTR(emulate_write_cache, S_IRUGO | S_IWUSR); - -DEF_DEV_ATTRIB(emulate_ua_intlck_ctrl); -SE_DEV_ATTR(emulate_ua_intlck_ctrl, S_IRUGO | S_IWUSR); - -DEF_DEV_ATTRIB(emulate_tas); -SE_DEV_ATTR(emulate_tas, S_IRUGO | S_IWUSR); - -DEF_DEV_ATTRIB(emulate_tpu); -SE_DEV_ATTR(emulate_tpu, S_IRUGO | S_IWUSR); - -DEF_DEV_ATTRIB(emulate_tpws); -SE_DEV_ATTR(emulate_tpws, S_IRUGO | S_IWUSR); - -DEF_DEV_ATTRIB(emulate_caw); -SE_DEV_ATTR(emulate_caw, S_IRUGO | S_IWUSR); - -DEF_DEV_ATTRIB(emulate_3pc); -SE_DEV_ATTR(emulate_3pc, S_IRUGO | S_IWUSR); - -DEF_DEV_ATTRIB(pi_prot_type); -SE_DEV_ATTR(pi_prot_type, S_IRUGO | S_IWUSR); - -DEF_DEV_ATTRIB_RO(hw_pi_prot_type); -SE_DEV_ATTR_RO(hw_pi_prot_type); - -DEF_DEV_ATTRIB(pi_prot_format); -SE_DEV_ATTR(pi_prot_format, S_IRUGO | S_IWUSR); - -DEF_DEV_ATTRIB(enforce_pr_isids); -SE_DEV_ATTR(enforce_pr_isids, S_IRUGO | S_IWUSR); - -DEF_DEV_ATTRIB(is_nonrot); -SE_DEV_ATTR(is_nonrot, S_IRUGO | S_IWUSR); - -DEF_DEV_ATTRIB(emulate_rest_reord); -SE_DEV_ATTR(emulate_rest_reord, S_IRUGO | S_IWUSR); - -DEF_DEV_ATTRIB(force_pr_aptpl); -SE_DEV_ATTR(force_pr_aptpl, S_IRUGO | S_IWUSR); - -DEF_DEV_ATTRIB_RO(hw_block_size); -SE_DEV_ATTR_RO(hw_block_size); - -DEF_DEV_ATTRIB(block_size); -SE_DEV_ATTR(block_size, S_IRUGO | S_IWUSR); - -DEF_DEV_ATTRIB_RO(hw_max_sectors); -SE_DEV_ATTR_RO(hw_max_sectors); - -DEF_DEV_ATTRIB(fabric_max_sectors); -SE_DEV_ATTR(fabric_max_sectors, S_IRUGO | S_IWUSR); - -DEF_DEV_ATTRIB(optimal_sectors); -SE_DEV_ATTR(optimal_sectors, S_IRUGO | S_IWUSR); - -DEF_DEV_ATTRIB_RO(hw_queue_depth); -SE_DEV_ATTR_RO(hw_queue_depth); - -DEF_DEV_ATTRIB(queue_depth); -SE_DEV_ATTR(queue_depth, S_IRUGO | S_IWUSR); - -DEF_DEV_ATTRIB(max_unmap_lba_count); -SE_DEV_ATTR(max_unmap_lba_count, S_IRUGO | S_IWUSR); - -DEF_DEV_ATTRIB(max_unmap_block_desc_count); -SE_DEV_ATTR(max_unmap_block_desc_count, S_IRUGO | S_IWUSR); - -DEF_DEV_ATTRIB(unmap_granularity); -SE_DEV_ATTR(unmap_granularity, S_IRUGO | S_IWUSR); - -DEF_DEV_ATTRIB(unmap_granularity_alignment); -SE_DEV_ATTR(unmap_granularity_alignment, S_IRUGO | S_IWUSR); - -DEF_DEV_ATTRIB(max_write_same_len); -SE_DEV_ATTR(max_write_same_len, S_IRUGO | S_IWUSR); - CONFIGFS_EATTR_OPS(target_core_dev_attrib, se_dev_attrib, da_group); -static struct configfs_attribute *target_core_dev_attrib_attrs[] = { - &target_core_dev_attrib_emulate_model_alias.attr, - &target_core_dev_attrib_emulate_dpo.attr, - &target_core_dev_attrib_emulate_fua_write.attr, - &target_core_dev_attrib_emulate_fua_read.attr, - &target_core_dev_attrib_emulate_write_cache.attr, - &target_core_dev_attrib_emulate_ua_intlck_ctrl.attr, - &target_core_dev_attrib_emulate_tas.attr, - &target_core_dev_attrib_emulate_tpu.attr, - &target_core_dev_attrib_emulate_tpws.attr, - &target_core_dev_attrib_emulate_caw.attr, - &target_core_dev_attrib_emulate_3pc.attr, - &target_core_dev_attrib_pi_prot_type.attr, - &target_core_dev_attrib_hw_pi_prot_type.attr, - &target_core_dev_attrib_pi_prot_format.attr, - &target_core_dev_attrib_enforce_pr_isids.attr, - &target_core_dev_attrib_force_pr_aptpl.attr, - &target_core_dev_attrib_is_nonrot.attr, - &target_core_dev_attrib_emulate_rest_reord.attr, - &target_core_dev_attrib_hw_block_size.attr, - &target_core_dev_attrib_block_size.attr, - &target_core_dev_attrib_hw_max_sectors.attr, - &target_core_dev_attrib_fabric_max_sectors.attr, - &target_core_dev_attrib_optimal_sectors.attr, - &target_core_dev_attrib_hw_queue_depth.attr, - &target_core_dev_attrib_queue_depth.attr, - &target_core_dev_attrib_max_unmap_lba_count.attr, - &target_core_dev_attrib_max_unmap_block_desc_count.attr, - &target_core_dev_attrib_unmap_granularity.attr, - &target_core_dev_attrib_unmap_granularity_alignment.attr, - &target_core_dev_attrib_max_write_same_len.attr, - NULL, -}; - static struct configfs_item_operations target_core_dev_attrib_ops = { .show_attribute = target_core_dev_attrib_attr_show, .store_attribute = target_core_dev_attrib_attr_store, }; -TB_CIT_SETUP(dev_attrib, &target_core_dev_attrib_ops, NULL, - target_core_dev_attrib_attrs); +TB_CIT_SETUP(dev_attrib, &target_core_dev_attrib_ops, NULL, NULL); /* End functions for struct config_item_type tb_dev_attrib_cit */ -- cgit v1.2.3 From 4b2f57e5ced40e91cbf8886d7dc40a9474d2f5c0 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 28 Nov 2014 05:39:12 +0000 Subject: target: Drop left-over PHBA_PDEV set attr checks Now that PSCSI is only exposing four hw_* read-only device attributes, go ahead and drop the left-over -> legacy PHBA_PDEV checks in various se_dev_set_* code, since it's now only used by virtual devices. Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_device.c | 64 ++++++------------------------------- 1 file changed, 10 insertions(+), 54 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 953fff79bc14..7653cfb027a2 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -767,12 +767,6 @@ int se_dev_set_emulate_fua_write(struct se_device *dev, int flag) pr_err("Illegal value %d\n", flag); return -EINVAL; } - - if (flag && - dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) { - pr_err("emulate_fua_write not supported for pSCSI\n"); - return -EINVAL; - } dev->dev_attrib.emulate_fua_write = flag; pr_debug("dev[%p]: SE Device Forced Unit Access WRITEs: %d\n", dev, dev->dev_attrib.emulate_fua_write); @@ -802,11 +796,6 @@ int se_dev_set_emulate_write_cache(struct se_device *dev, int flag) pr_err("Illegal value %d\n", flag); return -EINVAL; } - if (flag && - dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) { - pr_err("emulate_write_cache not supported for pSCSI\n"); - return -EINVAL; - } if (flag && dev->transport->get_write_cache) { pr_err("emulate_write_cache not supported for this device\n"); @@ -1098,26 +1087,15 @@ int se_dev_set_queue_depth(struct se_device *dev, u32 queue_depth) return -EINVAL; } - if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) { + if (queue_depth > dev->dev_attrib.queue_depth) { if (queue_depth > dev->dev_attrib.hw_queue_depth) { - pr_err("dev[%p]: Passed queue_depth: %u" - " exceeds TCM/SE_Device TCQ: %u\n", - dev, queue_depth, + pr_err("dev[%p]: Passed queue_depth:" + " %u exceeds TCM/SE_Device MAX" + " TCQ: %u\n", dev, queue_depth, dev->dev_attrib.hw_queue_depth); return -EINVAL; } - } else { - if (queue_depth > dev->dev_attrib.queue_depth) { - if (queue_depth > dev->dev_attrib.hw_queue_depth) { - pr_err("dev[%p]: Passed queue_depth:" - " %u exceeds TCM/SE_Device MAX" - " TCQ: %u\n", dev, queue_depth, - dev->dev_attrib.hw_queue_depth); - return -EINVAL; - } - } } - dev->dev_attrib.queue_depth = dev->queue_depth = queue_depth; pr_debug("dev[%p]: SE Device TCQ Depth changed to: %u\n", dev, queue_depth); @@ -1146,22 +1124,12 @@ int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors) DA_STATUS_MAX_SECTORS_MIN); return -EINVAL; } - if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) { - if (fabric_max_sectors > dev->dev_attrib.hw_max_sectors) { - pr_err("dev[%p]: Passed fabric_max_sectors: %u" - " greater than TCM/SE_Device max_sectors:" - " %u\n", dev, fabric_max_sectors, - dev->dev_attrib.hw_max_sectors); - return -EINVAL; - } - } else { - if (fabric_max_sectors > DA_STATUS_MAX_SECTORS_MAX) { - pr_err("dev[%p]: Passed fabric_max_sectors: %u" - " greater than DA_STATUS_MAX_SECTORS_MAX:" - " %u\n", dev, fabric_max_sectors, - DA_STATUS_MAX_SECTORS_MAX); - return -EINVAL; - } + if (fabric_max_sectors > DA_STATUS_MAX_SECTORS_MAX) { + pr_err("dev[%p]: Passed fabric_max_sectors: %u" + " greater than DA_STATUS_MAX_SECTORS_MAX:" + " %u\n", dev, fabric_max_sectors, + DA_STATUS_MAX_SECTORS_MAX); + return -EINVAL; } /* * Align max_sectors down to PAGE_SIZE to follow transport_allocate_data_tasks() @@ -1188,11 +1156,6 @@ int se_dev_set_optimal_sectors(struct se_device *dev, u32 optimal_sectors) dev, dev->export_count); return -EINVAL; } - if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) { - pr_err("dev[%p]: Passed optimal_sectors cannot be" - " changed for TCM/pSCSI\n", dev); - return -EINVAL; - } if (optimal_sectors > dev->dev_attrib.fabric_max_sectors) { pr_err("dev[%p]: Passed optimal_sectors %u cannot be" " greater than fabric_max_sectors: %u\n", dev, @@ -1226,13 +1189,6 @@ int se_dev_set_block_size(struct se_device *dev, u32 block_size) return -EINVAL; } - if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) { - pr_err("dev[%p]: Not allowed to change block_size for" - " Physical Device, use for Linux/SCSI to change" - " block_size for underlying hardware\n", dev); - return -EINVAL; - } - dev->dev_attrib.block_size = block_size; pr_debug("dev[%p]: SE Device block_size changed to %u\n", dev, block_size); -- cgit v1.2.3 From 506787a2c7daed45f0a213674ca706cbc83a9089 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Wed, 26 Nov 2014 14:58:57 +0100 Subject: tcm_loop: Fix wrong I_T nexus association tcm_loop has the I_T nexus associated with the HBA. This causes commands to become misdirected if the HBA has more than one target portal group; any command is then being sent to the first target portal group instead of the correct one. The nexus needs to be associated with the target portal group instead. Signed-off-by: Hannes Reinecke Cc: # 3.0+ Signed-off-by: Nicholas Bellinger --- drivers/target/loopback/tcm_loop.c | 66 +++++++++++++------------------------- drivers/target/loopback/tcm_loop.h | 7 +--- 2 files changed, 24 insertions(+), 49 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c index ab3ab27d49b7..0be83e788df2 100644 --- a/drivers/target/loopback/tcm_loop.c +++ b/drivers/target/loopback/tcm_loop.c @@ -190,7 +190,7 @@ static void tcm_loop_submission_work(struct work_struct *work) set_host_byte(sc, DID_TRANSPORT_DISRUPTED); goto out_done; } - tl_nexus = tl_hba->tl_nexus; + tl_nexus = tl_tpg->tl_nexus; if (!tl_nexus) { scmd_printk(KERN_ERR, sc, "TCM_Loop I_T Nexus" " does not exist\n"); @@ -270,16 +270,26 @@ static int tcm_loop_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc) * to struct scsi_device */ static int tcm_loop_issue_tmr(struct tcm_loop_tpg *tl_tpg, - struct tcm_loop_nexus *tl_nexus, int lun, int task, enum tcm_tmreq_table tmr) { struct se_cmd *se_cmd = NULL; struct se_session *se_sess; struct se_portal_group *se_tpg; + struct tcm_loop_nexus *tl_nexus; struct tcm_loop_cmd *tl_cmd = NULL; struct tcm_loop_tmr *tl_tmr = NULL; int ret = TMR_FUNCTION_FAILED, rc; + /* + * Locate the tl_nexus and se_sess pointers + */ + tl_nexus = tl_tpg->tl_nexus; + if (!tl_nexus) { + pr_err("Unable to perform device reset without" + " active I_T Nexus\n"); + return ret; + } + tl_cmd = kmem_cache_zalloc(tcm_loop_cmd_cache, GFP_KERNEL); if (!tl_cmd) { pr_err("Unable to allocate memory for tl_cmd\n"); @@ -295,7 +305,7 @@ static int tcm_loop_issue_tmr(struct tcm_loop_tpg *tl_tpg, se_cmd = &tl_cmd->tl_se_cmd; se_tpg = &tl_tpg->tl_se_tpg; - se_sess = tl_nexus->se_sess; + se_sess = tl_tpg->tl_nexus->se_sess; /* * Initialize struct se_cmd descriptor from target_core_mod infrastructure */ @@ -340,7 +350,6 @@ release: static int tcm_loop_abort_task(struct scsi_cmnd *sc) { struct tcm_loop_hba *tl_hba; - struct tcm_loop_nexus *tl_nexus; struct tcm_loop_tpg *tl_tpg; int ret = FAILED; @@ -348,21 +357,8 @@ static int tcm_loop_abort_task(struct scsi_cmnd *sc) * Locate the tcm_loop_hba_t pointer */ tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host); - /* - * Locate the tl_nexus and se_sess pointers - */ - tl_nexus = tl_hba->tl_nexus; - if (!tl_nexus) { - pr_err("Unable to perform device reset without" - " active I_T Nexus\n"); - return FAILED; - } - - /* - * Locate the tl_tpg pointer from TargetID in sc->device->id - */ tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id]; - ret = tcm_loop_issue_tmr(tl_tpg, tl_nexus, sc->device->lun, + ret = tcm_loop_issue_tmr(tl_tpg, sc->device->lun, sc->request->tag, TMR_ABORT_TASK); return (ret == TMR_FUNCTION_COMPLETE) ? SUCCESS : FAILED; } @@ -374,7 +370,6 @@ static int tcm_loop_abort_task(struct scsi_cmnd *sc) static int tcm_loop_device_reset(struct scsi_cmnd *sc) { struct tcm_loop_hba *tl_hba; - struct tcm_loop_nexus *tl_nexus; struct tcm_loop_tpg *tl_tpg; int ret = FAILED; @@ -382,20 +377,9 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc) * Locate the tcm_loop_hba_t pointer */ tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host); - /* - * Locate the tl_nexus and se_sess pointers - */ - tl_nexus = tl_hba->tl_nexus; - if (!tl_nexus) { - pr_err("Unable to perform device reset without" - " active I_T Nexus\n"); - return FAILED; - } - /* - * Locate the tl_tpg pointer from TargetID in sc->device->id - */ tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id]; - ret = tcm_loop_issue_tmr(tl_tpg, tl_nexus, sc->device->lun, + + ret = tcm_loop_issue_tmr(tl_tpg, sc->device->lun, 0, TMR_LUN_RESET); return (ret == TMR_FUNCTION_COMPLETE) ? SUCCESS : FAILED; } @@ -1005,8 +989,8 @@ static int tcm_loop_make_nexus( struct tcm_loop_nexus *tl_nexus; int ret = -ENOMEM; - if (tl_tpg->tl_hba->tl_nexus) { - pr_debug("tl_tpg->tl_hba->tl_nexus already exists\n"); + if (tl_tpg->tl_nexus) { + pr_debug("tl_tpg->tl_nexus already exists\n"); return -EEXIST; } se_tpg = &tl_tpg->tl_se_tpg; @@ -1041,7 +1025,7 @@ static int tcm_loop_make_nexus( */ __transport_register_session(se_tpg, tl_nexus->se_sess->se_node_acl, tl_nexus->se_sess, tl_nexus); - tl_tpg->tl_hba->tl_nexus = tl_nexus; + tl_tpg->tl_nexus = tl_nexus; pr_debug("TCM_Loop_ConfigFS: Established I_T Nexus to emulated" " %s Initiator Port: %s\n", tcm_loop_dump_proto_id(tl_hba), name); @@ -1057,12 +1041,8 @@ static int tcm_loop_drop_nexus( { struct se_session *se_sess; struct tcm_loop_nexus *tl_nexus; - struct tcm_loop_hba *tl_hba = tpg->tl_hba; - if (!tl_hba) - return -ENODEV; - - tl_nexus = tl_hba->tl_nexus; + tl_nexus = tpg->tl_nexus; if (!tl_nexus) return -ENODEV; @@ -1078,13 +1058,13 @@ static int tcm_loop_drop_nexus( } pr_debug("TCM_Loop_ConfigFS: Removing I_T Nexus to emulated" - " %s Initiator Port: %s\n", tcm_loop_dump_proto_id(tl_hba), + " %s Initiator Port: %s\n", tcm_loop_dump_proto_id(tpg->tl_hba), tl_nexus->se_sess->se_node_acl->initiatorname); /* * Release the SCSI I_T Nexus to the emulated SAS Target Port */ transport_deregister_session(tl_nexus->se_sess); - tpg->tl_hba->tl_nexus = NULL; + tpg->tl_nexus = NULL; kfree(tl_nexus); return 0; } @@ -1100,7 +1080,7 @@ static ssize_t tcm_loop_tpg_show_nexus( struct tcm_loop_nexus *tl_nexus; ssize_t ret; - tl_nexus = tl_tpg->tl_hba->tl_nexus; + tl_nexus = tl_tpg->tl_nexus; if (!tl_nexus) return -ENODEV; diff --git a/drivers/target/loopback/tcm_loop.h b/drivers/target/loopback/tcm_loop.h index 54c59d0b6608..6ae49f272ba6 100644 --- a/drivers/target/loopback/tcm_loop.h +++ b/drivers/target/loopback/tcm_loop.h @@ -27,11 +27,6 @@ struct tcm_loop_tmr { }; struct tcm_loop_nexus { - int it_nexus_active; - /* - * Pointer to Linux/SCSI HBA from linux/include/scsi_host.h - */ - struct scsi_host *sh; /* * Pointer to TCM session for I_T Nexus */ @@ -51,6 +46,7 @@ struct tcm_loop_tpg { atomic_t tl_tpg_port_count; struct se_portal_group tl_se_tpg; struct tcm_loop_hba *tl_hba; + struct tcm_loop_nexus *tl_nexus; }; struct tcm_loop_hba { @@ -59,7 +55,6 @@ struct tcm_loop_hba { struct se_hba_s *se_hba; struct se_lun *tl_hba_lun; struct se_port *tl_hba_lun_sep; - struct tcm_loop_nexus *tl_nexus; struct device dev; struct Scsi_Host *sh; struct tcm_loop_tpg tl_hba_tpgs[TL_TPGS_PER_HBA]; -- cgit v1.2.3 From 7f2c53bb9512bd6c6c55ce0eed27f5c5da8b7ec2 Mon Sep 17 00:00:00 2001 From: Lino Sanfilippo Date: Sun, 30 Nov 2014 12:00:11 +0100 Subject: iscsi-target: fix error path in iscsi_target_init_module() In iscsi_target_init_module() unwind transport protocol registration in case that iscsit_load_discovery_tpg() failed. Signed-off-by: Lino Sanfilippo Reviewed-by: Sagi Grimberg Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/target') diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 73e58d22e325..f8ec32298906 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -609,6 +609,7 @@ static int __init iscsi_target_init_module(void) return ret; r2t_out: + iscsit_unregister_transport(&iscsi_target_transport); kmem_cache_destroy(lio_r2t_cache); ooo_out: kmem_cache_destroy(lio_ooo_cache); -- cgit v1.2.3 From 13ba564c956d8584d661aeb6ff7c9fa161b84f12 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 30 Nov 2014 19:14:12 +0100 Subject: target: remove unneeded array Delete a local array that is only used to be initialized by memset. A semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ identifier x; type T; @@ { ... when any -T x[...]; <+... when != x - memset(x,...); ...+> } // Signed-off-by: Julia Lawall Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pr.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 9f93b8234095..f91b6a1b846e 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -1429,14 +1429,12 @@ core_scsi3_decode_spec_i_port( struct target_core_fabric_ops *tmp_tf_ops; unsigned char *buf; unsigned char *ptr, *i_str = NULL, proto_ident, tmp_proto_ident; - char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN]; + char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN]; sense_reason_t ret; u32 tpdl, tid_len = 0; int dest_local_nexus; u32 dest_rtpi = 0; - memset(dest_iport, 0, 64); - local_se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun]; /* * Allocate a struct pr_transport_id_holder and setup the @@ -3059,7 +3057,7 @@ core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key, struct t10_reservation *pr_tmpl = &dev->t10_pr; unsigned char *buf; unsigned char *initiator_str; - char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN]; + char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN]; u32 tid_len, tmp_tid_len; int new_reg = 0, type, scope, matching_iname; sense_reason_t ret; @@ -3071,7 +3069,6 @@ core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key, return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } - memset(dest_iport, 0, 64); memset(i_buf, 0, PR_REG_ISID_ID_LEN); se_tpg = se_sess->se_tpg; tf_ops = se_tpg->se_tpg_tfo; -- cgit v1.2.3 From 954f23722b5753305be490330cf2680b7a25f4a3 Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Tue, 2 Dec 2014 16:57:17 +0200 Subject: iscsi,iser-target: Initiate termination only once Since commit 0fc4ea701fcf ("Target/iser: Don't put isert_conn inside disconnected handler") we put the conn kref in isert_wait_conn, so we need .wait_conn to be invoked also in the error path. Introduce call to isert_conn_terminate (called under lock) which transitions the connection state to TERMINATING and calls rdma_disconnect. If the state is already teminating, just bail out back (temination started). Also, make sure to destroy the connection when getting a connect error event if didn't get to connected (state UP). Same for the handling of REJECTED and UNREACHABLE cma events. Squashed: iscsi-target: Add call to wait_conn in establishment error flow Reported-by: Slava Shwartsman Signed-off-by: Sagi Grimberg Cc: # v3.10+ Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_login.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/target') diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 480f2e0ecc11..05ad5c7128f2 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -1204,6 +1204,9 @@ old_sess_out: conn->sock = NULL; } + if (conn->conn_transport->iscsit_wait_conn) + conn->conn_transport->iscsit_wait_conn(conn); + if (conn->conn_transport->iscsit_free_conn) conn->conn_transport->iscsit_free_conn(conn); -- cgit v1.2.3 From 23a548ee656c8ba6da8cb2412070edcd62e2ac5d Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Tue, 2 Dec 2014 16:57:35 +0200 Subject: iscsi,iser-target: Expose supported protection ops according to t10_pi iSER will report supported protection operations based on the tpg attribute t10_pi settings and HCA PI offload capabilities. If the HCA does not support PI offload or tpg attribute t10_pi is not set, we fall to SW PI mode. In order to do that, we move iscsit_get_sup_prot_ops after connection tpg assignment. Signed-off-by: Sagi Grimberg Cc: # v3.14+ Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_login.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 05ad5c7128f2..18e2601527df 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -281,7 +281,6 @@ static int iscsi_login_zero_tsih_s1( { struct iscsi_session *sess = NULL; struct iscsi_login_req *pdu = (struct iscsi_login_req *)buf; - enum target_prot_op sup_pro_ops; int ret; sess = kzalloc(sizeof(struct iscsi_session), GFP_KERNEL); @@ -343,9 +342,8 @@ static int iscsi_login_zero_tsih_s1( kfree(sess); return -ENOMEM; } - sup_pro_ops = conn->conn_transport->iscsit_get_sup_prot_ops(conn); - sess->se_sess = transport_init_session(sup_pro_ops); + sess->se_sess = transport_init_session(TARGET_PROT_NORMAL); if (IS_ERR(sess->se_sess)) { iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, ISCSI_LOGIN_STATUS_NO_RESOURCES); @@ -1367,6 +1365,9 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) } login->zero_tsih = zero_tsih; + conn->sess->se_sess->sup_prot_ops = + conn->conn_transport->iscsit_get_sup_prot_ops(conn); + tpg = conn->tpg; if (!tpg) { pr_err("Unable to locate struct iscsi_conn->tpg\n"); -- cgit v1.2.3 From ee8e3ad96e04749aa043c7fcb7fe6a562f8b9c48 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 12 Dec 2014 23:27:06 -0800 Subject: iscsi-target: Drop left-over bogus iscsi_np->tpg_np This patch drops the left-over iscsi_np->tpg_np pointer, now that iser-target PI is able to dynamically allocate PI contexts per I/O, instead of needing to determine support using a TPG attribute with this bogus reference. Cc: Sagi Grimberg Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_core.h | 1 - drivers/target/iscsi/iscsi_target_tpg.c | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index 302eb3b78715..09a522bae222 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -790,7 +790,6 @@ struct iscsi_np { void *np_context; struct iscsit_transport *np_transport; struct list_head np_list; - struct iscsi_tpg_np *tpg_np; } ____cacheline_aligned; struct iscsi_tpg_np { diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c index c3cb5c15efda..9053a3c0c6e5 100644 --- a/drivers/target/iscsi/iscsi_target_tpg.c +++ b/drivers/target/iscsi/iscsi_target_tpg.c @@ -501,7 +501,6 @@ struct iscsi_tpg_np *iscsit_tpg_add_network_portal( init_completion(&tpg_np->tpg_np_comp); kref_init(&tpg_np->tpg_np_kref); tpg_np->tpg_np = np; - np->tpg_np = tpg_np; tpg_np->tpg = tpg; spin_lock(&tpg->tpg_np_lock); -- cgit v1.2.3 From d16ca7c5198fd668db10d2c7b048ed3359c12c54 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Sun, 14 Dec 2014 01:47:19 -0800 Subject: target: Fix R_HOLDER bit usage for AllRegistrants This patch fixes the usage of R_HOLDER bit for an All Registrants reservation in READ_FULL_STATUS, where only the registration who issued RESERVE was being reported as having an active reservation. It changes core_scsi3_pri_read_full_status() to check ahead of the list walk of active registrations to see if All Registrants is active, and if so set R_HOLDER bit and scope/type fields for all active registrations. Reported-by: Ilias Tsitsimpis Cc: James Bottomley Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pr.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index f91b6a1b846e..c4a8da5415c5 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -3834,7 +3834,8 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd) unsigned char *buf; u32 add_desc_len = 0, add_len = 0, desc_len, exp_desc_len; u32 off = 8; /* off into first Full Status descriptor */ - int format_code = 0; + int format_code = 0, pr_res_type = 0, pr_res_scope = 0; + bool all_reg = false; if (cmd->data_length < 8) { pr_err("PRIN SA READ_FULL_STATUS SCSI Data Length: %u" @@ -3851,6 +3852,19 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd) buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff); buf[3] = (dev->t10_pr.pr_generation & 0xff); + spin_lock(&dev->dev_reservation_lock); + if (dev->dev_pr_res_holder) { + struct t10_pr_registration *pr_holder = dev->dev_pr_res_holder; + + if (pr_holder->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG || + pr_holder->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG) { + all_reg = true; + pr_res_type = pr_holder->pr_res_type; + pr_res_scope = pr_holder->pr_res_scope; + } + } + spin_unlock(&dev->dev_reservation_lock); + spin_lock(&pr_tmpl->registration_lock); list_for_each_entry_safe(pr_reg, pr_reg_tmp, &pr_tmpl->registration_list, pr_reg_list) { @@ -3898,14 +3912,20 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd) * reservation holder for PR_HOLDER bit. * * Also, if this registration is the reservation - * holder, fill in SCOPE and TYPE in the next byte. + * holder or there is an All Registrants reservation + * active, fill in SCOPE and TYPE in the next byte. */ if (pr_reg->pr_res_holder) { buf[off++] |= 0x01; buf[off++] = (pr_reg->pr_res_scope & 0xf0) | (pr_reg->pr_res_type & 0x0f); - } else + } else if (all_reg) { + buf[off++] |= 0x01; + buf[off++] = (pr_res_scope & 0xf0) | + (pr_res_type & 0x0f); + } else { off += 2; + } off += 4; /* Skip over reserved area */ /* -- cgit v1.2.3 From 6c3c9baa0debeb4bcc52a78c4463a0a97518de10 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Mon, 15 Dec 2014 11:50:26 -0800 Subject: target: Avoid dropping AllRegistrants reservation during unregister This patch fixes an issue with AllRegistrants reservations where an unregister operation by the I_T nexus reservation holder would incorrectly drop the reservation, instead of waiting until the last active I_T nexus is unregistered as per SPC-4. This includes updating __core_scsi3_complete_pro_release() to reset dev->dev_pr_res_holder with another pr_reg for this special case, as well as a new 'unreg' parameter to determine when the release is occuring from an implicit unregister, vs. explicit RELEASE. It also adds special handling in core_scsi3_free_pr_reg_from_nacl() to release the left-over pr_res_holder, now that pr_reg is deleted from pr_reg_list within __core_scsi3_complete_pro_release(). Reported-by: Ilias Tsitsimpis Cc: James Bottomley Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pr.c | 87 ++++++++++++++++++++++++++++++----------- 1 file changed, 65 insertions(+), 22 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index c4a8da5415c5..703890c12071 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -76,7 +76,7 @@ enum preempt_type { }; static void __core_scsi3_complete_pro_release(struct se_device *, struct se_node_acl *, - struct t10_pr_registration *, int); + struct t10_pr_registration *, int, int); static sense_reason_t target_scsi2_reservation_check(struct se_cmd *cmd) @@ -1177,7 +1177,7 @@ static int core_scsi3_check_implicit_release( * service action with the SERVICE ACTION RESERVATION KEY * field set to zero (see 5.7.11.3). */ - __core_scsi3_complete_pro_release(dev, nacl, pr_reg, 0); + __core_scsi3_complete_pro_release(dev, nacl, pr_reg, 0, 1); ret = 1; /* * For 'All Registrants' reservation types, all existing @@ -1219,7 +1219,8 @@ static void __core_scsi3_free_registration( pr_reg->pr_reg_deve->def_pr_registered = 0; pr_reg->pr_reg_deve->pr_res_key = 0; - list_del(&pr_reg->pr_reg_list); + if (!list_empty(&pr_reg->pr_reg_list)) + list_del(&pr_reg->pr_reg_list); /* * Caller accessing *pr_reg using core_scsi3_locate_pr_reg(), * so call core_scsi3_put_pr_reg() to decrement our reference. @@ -1271,6 +1272,7 @@ void core_scsi3_free_pr_reg_from_nacl( { struct t10_reservation *pr_tmpl = &dev->t10_pr; struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_res_holder; + bool free_reg = false; /* * If the passed se_node_acl matches the reservation holder, * release the reservation. @@ -1278,13 +1280,18 @@ void core_scsi3_free_pr_reg_from_nacl( spin_lock(&dev->dev_reservation_lock); pr_res_holder = dev->dev_pr_res_holder; if ((pr_res_holder != NULL) && - (pr_res_holder->pr_reg_nacl == nacl)) - __core_scsi3_complete_pro_release(dev, nacl, pr_res_holder, 0); + (pr_res_holder->pr_reg_nacl == nacl)) { + __core_scsi3_complete_pro_release(dev, nacl, pr_res_holder, 0, 1); + free_reg = true; + } spin_unlock(&dev->dev_reservation_lock); /* * Release any registration associated with the struct se_node_acl. */ spin_lock(&pr_tmpl->registration_lock); + if (pr_res_holder && free_reg) + __core_scsi3_free_registration(dev, pr_res_holder, NULL, 0); + list_for_each_entry_safe(pr_reg, pr_reg_tmp, &pr_tmpl->registration_list, pr_reg_list) { @@ -1307,7 +1314,7 @@ void core_scsi3_free_all_registrations( if (pr_res_holder != NULL) { struct se_node_acl *pr_res_nacl = pr_res_holder->pr_reg_nacl; __core_scsi3_complete_pro_release(dev, pr_res_nacl, - pr_res_holder, 0); + pr_res_holder, 0, 0); } spin_unlock(&dev->dev_reservation_lock); @@ -2103,13 +2110,13 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, /* * sa_res_key=0 Unregister Reservation Key for registered I_T Nexus. */ - pr_holder = core_scsi3_check_implicit_release( - cmd->se_dev, pr_reg); + type = pr_reg->pr_res_type; + pr_holder = core_scsi3_check_implicit_release(cmd->se_dev, + pr_reg); if (pr_holder < 0) { ret = TCM_RESERVATION_CONFLICT; goto out; } - type = pr_reg->pr_res_type; spin_lock(&pr_tmpl->registration_lock); /* @@ -2383,23 +2390,59 @@ static void __core_scsi3_complete_pro_release( struct se_device *dev, struct se_node_acl *se_nacl, struct t10_pr_registration *pr_reg, - int explicit) + int explicit, + int unreg) { struct target_core_fabric_ops *tfo = se_nacl->se_tpg->se_tpg_tfo; char i_buf[PR_REG_ISID_ID_LEN]; + int pr_res_type = 0, pr_res_scope = 0; memset(i_buf, 0, PR_REG_ISID_ID_LEN); core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN); /* * Go ahead and release the current PR reservation holder. + * If an All Registrants reservation is currently active and + * a unregister operation is requested, replace the current + * dev_pr_res_holder with another active registration. */ - dev->dev_pr_res_holder = NULL; + if (dev->dev_pr_res_holder) { + pr_res_type = dev->dev_pr_res_holder->pr_res_type; + pr_res_scope = dev->dev_pr_res_holder->pr_res_scope; + dev->dev_pr_res_holder->pr_res_type = 0; + dev->dev_pr_res_holder->pr_res_scope = 0; + dev->dev_pr_res_holder->pr_res_holder = 0; + dev->dev_pr_res_holder = NULL; + } + if (!unreg) + goto out; - pr_debug("SPC-3 PR [%s] Service Action: %s RELEASE cleared" - " reservation holder TYPE: %s ALL_TG_PT: %d\n", - tfo->get_fabric_name(), (explicit) ? "explicit" : "implicit", - core_scsi3_pr_dump_type(pr_reg->pr_res_type), - (pr_reg->pr_reg_all_tg_pt) ? 1 : 0); + spin_lock(&dev->t10_pr.registration_lock); + list_del_init(&pr_reg->pr_reg_list); + /* + * If the I_T nexus is a reservation holder, the persistent reservation + * is of an all registrants type, and the I_T nexus is the last remaining + * registered I_T nexus, then the device server shall also release the + * persistent reservation. + */ + if (!list_empty(&dev->t10_pr.registration_list) && + ((pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG) || + (pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG))) { + dev->dev_pr_res_holder = + list_entry(dev->t10_pr.registration_list.next, + struct t10_pr_registration, pr_reg_list); + dev->dev_pr_res_holder->pr_res_type = pr_res_type; + dev->dev_pr_res_holder->pr_res_scope = pr_res_scope; + dev->dev_pr_res_holder->pr_res_holder = 1; + } + spin_unlock(&dev->t10_pr.registration_lock); +out: + if (!dev->dev_pr_res_holder) { + pr_debug("SPC-3 PR [%s] Service Action: %s RELEASE cleared" + " reservation holder TYPE: %s ALL_TG_PT: %d\n", + tfo->get_fabric_name(), (explicit) ? "explicit" : + "implicit", core_scsi3_pr_dump_type(pr_res_type), + (pr_reg->pr_reg_all_tg_pt) ? 1 : 0); + } pr_debug("SPC-3 PR [%s] RELEASE Node: %s%s\n", tfo->get_fabric_name(), se_nacl->initiatorname, i_buf); @@ -2530,7 +2573,7 @@ core_scsi3_emulate_pro_release(struct se_cmd *cmd, int type, int scope, * server shall not establish a unit attention condition. */ __core_scsi3_complete_pro_release(dev, se_sess->se_node_acl, - pr_reg, 1); + pr_reg, 1, 0); spin_unlock(&dev->dev_reservation_lock); @@ -2618,7 +2661,7 @@ core_scsi3_emulate_pro_clear(struct se_cmd *cmd, u64 res_key) if (pr_res_holder) { struct se_node_acl *pr_res_nacl = pr_res_holder->pr_reg_nacl; __core_scsi3_complete_pro_release(dev, pr_res_nacl, - pr_res_holder, 0); + pr_res_holder, 0, 0); } spin_unlock(&dev->dev_reservation_lock); /* @@ -2677,7 +2720,7 @@ static void __core_scsi3_complete_pro_preempt( */ if (dev->dev_pr_res_holder) __core_scsi3_complete_pro_release(dev, nacl, - dev->dev_pr_res_holder, 0); + dev->dev_pr_res_holder, 0, 0); dev->dev_pr_res_holder = pr_reg; pr_reg->pr_res_holder = 1; @@ -2922,8 +2965,8 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, */ if (pr_reg_n != pr_res_holder) __core_scsi3_complete_pro_release(dev, - pr_res_holder->pr_reg_nacl, - dev->dev_pr_res_holder, 0); + pr_res_holder->pr_reg_nacl, + dev->dev_pr_res_holder, 0, 0); /* * b) Remove the registrations for all I_T nexuses identified * by the SERVICE ACTION RESERVATION KEY field, except the @@ -3386,7 +3429,7 @@ after_iport_check: * holder (i.e., the I_T nexus on which the */ __core_scsi3_complete_pro_release(dev, pr_res_nacl, - dev->dev_pr_res_holder, 0); + dev->dev_pr_res_holder, 0, 0); /* * g) Move the persistent reservation to the specified I_T nexus using * the same scope and type as the persistent reservation released in -- cgit v1.2.3 From a0b3b9b2409b409c677f7eb1e0485b816a5848f7 Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Mon, 15 Dec 2014 15:08:54 +0200 Subject: iscsi-target: nullify session in failed login sequence In case login sequence failed, make sure conn->sess is NULL before calling wait_conn as some transports (iser) may rely on that (waiting for session commands). Signed-off-by: Sagi Grimberg Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_login.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/target') diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 18e2601527df..713c0c1877ab 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -1159,6 +1159,7 @@ void iscsi_target_login_sess_out(struct iscsi_conn *conn, } kfree(conn->sess->sess_ops); kfree(conn->sess); + conn->sess = NULL; old_sess_out: iscsi_stop_login_thread_timer(np); -- cgit v1.2.3 From 6bf6ca7515c1df06f5c03737537f5e0eb191e29e Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 20 Nov 2014 20:50:07 -0800 Subject: iscsi-target: Fail connection on short sendmsg writes This patch changes iscsit_do_tx_data() to fail on short writes when kernel_sendmsg() returns a value different than requested transfer length, returning -EPIPE and thus causing a connection reset to occur. This avoids a potential bug in the original code where a short write would result in kernel_sendmsg() being called again with the original iovec base + length. In practice this has not been an issue because iscsit_do_tx_data() is only used for transferring 48 byte headers + 4 byte digests, along with seldom used control payloads from NOPIN + TEXT_RSP + REJECT with less than 32k of data. So following Al's audit of iovec consumers, go ahead and fail the connection on short writes for now, and remove the bogus logic ahead of his proper upstream fix. Reported-by: Al Viro Cc: David S. Miller Cc: # v3.1+ Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_util.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index ce87ce9bdb9c..0b68c2ebce95 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -1358,15 +1358,15 @@ static int iscsit_do_tx_data( struct iscsi_conn *conn, struct iscsi_data_count *count) { - int data = count->data_length, total_tx = 0, tx_loop = 0, iov_len; + int ret, iov_len; struct kvec *iov_p; struct msghdr msg; if (!conn || !conn->sock || !conn->conn_ops) return -1; - if (data <= 0) { - pr_err("Data length is: %d\n", data); + if (count->data_length <= 0) { + pr_err("Data length is: %d\n", count->data_length); return -1; } @@ -1375,20 +1375,16 @@ static int iscsit_do_tx_data( iov_p = count->iov; iov_len = count->iov_count; - while (total_tx < data) { - tx_loop = kernel_sendmsg(conn->sock, &msg, iov_p, iov_len, - (data - total_tx)); - if (tx_loop <= 0) { - pr_debug("tx_loop: %d total_tx %d\n", - tx_loop, total_tx); - return tx_loop; - } - total_tx += tx_loop; - pr_debug("tx_loop: %d, total_tx: %d, data: %d\n", - tx_loop, total_tx, data); + ret = kernel_sendmsg(conn->sock, &msg, iov_p, iov_len, + count->data_length); + if (ret != count->data_length) { + pr_err("Unexpected ret: %d send data %d\n", + ret, count->data_length); + return -EPIPE; } + pr_debug("ret: %d, sent data: %d\n", ret, count->data_length); - return total_tx; + return ret; } int rx_data( -- cgit v1.2.3 From ae450e246e8540300699480a3780a420a028b73f Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 19 Dec 2014 00:49:23 +0000 Subject: target: Allow AllRegistrants to re-RESERVE existing reservation This patch changes core_scsi3_pro_release() logic to allow an existing AllRegistrants type reservation to be re-reserved by any registered I_T nexus. This addresses a issue where AllRegistrants type RESERVE was receiving RESERVATION_CONFLICT status if dev_pr_res_holder did not match the same I_T nexus, instead of just returning GOOD status following spc4r34 Section 5.9.9: "If the device server receives a PERSISTENT RESERVE OUT command with RESERVE service action where the TYPE field and the SCOPE field contain the same values as the existing type and scope from a persistent reservation holder, it shall not make any change to the existing persistent reservation and shall complete the command with GOOD status." Reported-by: Ilias Tsitsimpis Cc: Ilias Tsitsimpis Cc: Lee Duncan Cc: James Bottomley Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pr.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/target') diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 703890c12071..f75a4baf6e56 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -2274,6 +2274,7 @@ core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key) spin_lock(&dev->dev_reservation_lock); pr_res_holder = dev->dev_pr_res_holder; if (pr_res_holder) { + int pr_res_type = pr_res_holder->pr_res_type; /* * From spc4r17 Section 5.7.9: Reserving: * @@ -2284,7 +2285,9 @@ core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key) * the logical unit, then the command shall be completed with * RESERVATION CONFLICT status. */ - if (pr_res_holder != pr_reg) { + if ((pr_res_holder != pr_reg) && + (pr_res_type != PR_TYPE_WRITE_EXCLUSIVE_ALLREG) && + (pr_res_type != PR_TYPE_EXCLUSIVE_ACCESS_ALLREG)) { struct se_node_acl *pr_res_nacl = pr_res_holder->pr_reg_nacl; pr_err("SPC-3 PR: Attempted RESERVE from" " [%s]: %s while reservation already held by" -- cgit v1.2.3