@@ -464,13 +464,19 @@ int target_register_template(const struct target_core_fabric_ops *fo)
INIT_LIST_HEAD(&tf->tf_list);
atomic_set(&tf->tf_access_cnt, 0);
tf->tf_ops = fo;
- target_fabric_setup_cits(tf);
+ ret = target_fabric_setup_cits(tf);
+ if (ret)
+ goto out;
mutex_lock(&g_tf_lock);
list_add_tail(&tf->tf_list, &g_tf_list);
mutex_unlock(&g_tf_lock);
return 0;
+
+out:
+ kfree(tf);
+ return ret;
}
EXPORT_SYMBOL(target_register_template);
@@ -490,6 +496,7 @@ void target_unregister_template(const struct target_core_fabric_ops *fo)
* fabric driver unload of TFO->module to proceed.
*/
rcu_barrier();
+ kfree(t->tf_tpg_attrib_cit.ct_attrs);
kfree(t);
return;
}
@@ -795,7 +795,38 @@ TF_CIT_SETUP(tpg_lun, NULL, &target_fabric_lun_group_ops, NULL);
/* End of tfc_tpg_lun_cit */
-TF_CIT_SETUP_DRV(tpg_attrib, NULL, NULL);
+static int
+target_fabric_setup_tpg_attrib_cit(struct target_fabric_configfs *tf)
+{
+ int i, k, len = 0;
+ struct config_item_type *cit = &tf->tf_tpg_attrib_cit;
+ struct configfs_attribute **attrs;
+
+ for (i = 0; core_tpg_attrib_attrs[i]; i++)
+ len += sizeof(struct configfs_attribute *);
+ if (tf->tf_ops->tfc_tpg_attrib_attrs)
+ for (i = 0; tf->tf_ops->tfc_tpg_attrib_attrs[i]; i++)
+ len += sizeof(struct configfs_attribute *);
+ len += sizeof(struct configfs_attribute *);
+
+ attrs = kzalloc(len, GFP_KERNEL);
+ if (!attrs)
+ return -ENOMEM;
+
+ for (i = 0; core_tpg_attrib_attrs[i]; i++)
+ attrs[i] = core_tpg_attrib_attrs[i];
+ if (tf->tf_ops->tfc_tpg_attrib_attrs)
+ for (k = 0; tf->tf_ops->tfc_tpg_attrib_attrs[k]; k++, i++)
+ attrs[i] = tf->tf_ops->tfc_tpg_attrib_attrs[k];
+ attrs[i] = NULL;
+
+ cit->ct_attrs = attrs;
+ cit->ct_owner = tf->tf_ops->module;
+ pr_debug("Setup generic tpg_attrib\n");
+
+ return 0;
+}
+
TF_CIT_SETUP_DRV(tpg_auth, NULL, NULL);
TF_CIT_SETUP_DRV(tpg_param, NULL, NULL);
@@ -971,6 +1002,8 @@ TF_CIT_SETUP_DRV(discovery, NULL, NULL);
int target_fabric_setup_cits(struct target_fabric_configfs *tf)
{
+ int ret;
+
target_fabric_setup_discovery_cit(tf);
target_fabric_setup_wwn_cit(tf);
target_fabric_setup_wwn_fabric_stats_cit(tf);
@@ -981,7 +1014,11 @@ int target_fabric_setup_cits(struct target_fabric_configfs *tf)
target_fabric_setup_tpg_lun_cit(tf);
target_fabric_setup_tpg_np_cit(tf);
target_fabric_setup_tpg_np_base_cit(tf);
- target_fabric_setup_tpg_attrib_cit(tf);
+
+ ret = target_fabric_setup_tpg_attrib_cit(tf);
+ if (ret)
+ return ret;
+
target_fabric_setup_tpg_auth_cit(tf);
target_fabric_setup_tpg_param_cit(tf);
target_fabric_setup_tpg_nacl_cit(tf);
@@ -116,6 +116,7 @@ int core_tmr_lun_reset(struct se_device *, struct se_tmr_req *,
/* target_core_tpg.c */
extern struct se_device *g_lun0_dev;
+extern struct configfs_attribute *core_tpg_attrib_attrs[];
struct se_node_acl *__core_tpg_get_initiator_node_acl(struct se_portal_group *tpg,
const char *);
@@ -719,3 +719,7 @@ void core_tpg_remove_lun(
percpu_ref_exit(&lun->lun_ref);
}
+
+struct configfs_attribute *core_tpg_attrib_attrs[] = {
+ NULL,
+};
All SCSI target port attributes (tpgN/attribs/attrname) are defined and implemented in fabric modules in existing implementation. The change introduces a way to have common tpg attribs in configfs for all fabrics without code duplication. Signed-off-by: Roman Bolshakov <r.bolshakov@yadro.com> --- drivers/target/target_core_configfs.c | 9 ++++- drivers/target/target_core_fabric_configfs.c | 41 +++++++++++++++++++- drivers/target/target_core_internal.h | 1 + drivers/target/target_core_tpg.c | 4 ++ 4 files changed, 52 insertions(+), 3 deletions(-)