@@ -1650,6 +1650,7 @@ struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(struct se_device *dev,
}
INIT_LIST_HEAD(&tg_pt_gp->tg_pt_gp_list);
INIT_LIST_HEAD(&tg_pt_gp->tg_pt_gp_lun_list);
+ INIT_LIST_HEAD(&tg_pt_gp->tg_pt_gp_peer_list);
mutex_init(&tg_pt_gp->tg_pt_gp_transition_mutex);
spin_lock_init(&tg_pt_gp->tg_pt_gp_lock);
atomic_set(&tg_pt_gp->tg_pt_gp_ref_cnt, 0);
@@ -79,6 +79,7 @@
extern struct kmem_cache *t10_alua_lu_gp_cache;
extern struct kmem_cache *t10_alua_lu_gp_mem_cache;
extern struct kmem_cache *t10_alua_tg_pt_gp_cache;
+extern struct kmem_cache *t10_alua_tg_pt_gp_peer_cache;
extern struct kmem_cache *t10_alua_lba_map_cache;
extern struct kmem_cache *t10_alua_lba_map_mem_cache;
@@ -3078,6 +3078,87 @@ static const struct config_item_type target_core_alua_tg_pt_gp_cit = {
.ct_owner = THIS_MODULE,
};
+static void target_core_alua_tg_pt_gp_peer_release(struct config_item *item)
+{
+ struct t10_alua_tg_pt_gp_peer *peer_port = container_of(item,
+ struct t10_alua_tg_pt_gp_peer, tg_pt_gp_peer_item);
+ kmem_cache_free(t10_alua_tg_pt_gp_peer_cache, peer_port);
+}
+
+static struct configfs_item_operations target_core_alua_tg_pt_gp_peer_ops = {
+ .release = target_core_alua_tg_pt_gp_peer_release,
+};
+
+static struct config_item_type target_core_alua_tg_pt_gp_peer_cit = {
+ .ct_item_ops = &target_core_alua_tg_pt_gp_peer_ops,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct config_item *
+target_core_alua_tg_pt_gp_peers_make(struct config_group *group,
+ const char *name)
+{
+ struct t10_alua_tg_pt_gp *tg_pt_gp = container_of(group,
+ struct t10_alua_tg_pt_gp, tg_pt_gp_peers_group);
+ struct t10_alua_tg_pt_gp_peer *peer_port;
+ u16 val;
+ int ret;
+
+ peer_port = kmem_cache_zalloc(t10_alua_tg_pt_gp_peer_cache, GFP_KERNEL);
+ if (!peer_port) {
+ pr_err("Unable to allocate struct t10_alua_tg_pt_gp_peer\n");
+ return ERR_PTR(-ENOMEM);
+ }
+ INIT_LIST_HEAD(&peer_port->tg_pt_gp_peer_list);
+
+ ret = kstrtou16(name, 0, &val);
+ if (ret < 0)
+ goto out_free;
+ if (!val) {
+ ret = -EINVAL;
+ goto out_free;
+ }
+
+ peer_port->tg_pt_gp_peer_rtpi = val;
+ config_item_init_type_name(&peer_port->tg_pt_gp_peer_item,
+ name,
+ &target_core_alua_tg_pt_gp_peer_cit);
+
+ spin_lock(&tg_pt_gp->tg_pt_gp_lock);
+ list_add_tail(&peer_port->tg_pt_gp_peer_list,
+ &tg_pt_gp->tg_pt_gp_peer_list);
+ spin_unlock(&tg_pt_gp->tg_pt_gp_lock);
+
+ return &peer_port->tg_pt_gp_peer_item;
+out_free:
+ kfree(peer_port);
+ return ERR_PTR(ret);
+}
+
+static void target_core_alua_tg_pt_gp_peers_drop(struct config_group *group,
+ struct config_item *item)
+{
+ struct t10_alua_tg_pt_gp_peer *peer_port = container_of(item,
+ struct t10_alua_tg_pt_gp_peer, tg_pt_gp_peer_item);
+ struct t10_alua_tg_pt_gp *tg_pt_gp = container_of(group,
+ struct t10_alua_tg_pt_gp, tg_pt_gp_peers_group);
+ spin_lock(&tg_pt_gp->tg_pt_gp_lock);
+ list_del(&peer_port->tg_pt_gp_peer_list);
+ spin_unlock(&tg_pt_gp->tg_pt_gp_lock);
+
+ config_item_put(item);
+}
+
+static struct configfs_group_operations target_core_alua_tg_pt_gp_peers_ops = {
+ .make_item = &target_core_alua_tg_pt_gp_peers_make,
+ .drop_item = &target_core_alua_tg_pt_gp_peers_drop,
+};
+
+static struct config_item_type target_core_alua_tg_pt_gp_peers_cit = {
+ .ct_group_ops = &target_core_alua_tg_pt_gp_peers_ops,
+ .ct_owner = THIS_MODULE,
+};
+
/* End functions for struct config_item_type target_core_alua_tg_pt_gp_cit */
/* Start functions for struct config_item_type tb_alua_tg_pt_gps_cit */
@@ -3101,6 +3182,11 @@ static struct config_group *target_core_alua_create_tg_pt_gp(
config_group_init_type_name(alua_tg_pt_gp_cg, name,
&target_core_alua_tg_pt_gp_cit);
+ config_group_init_type_name(&tg_pt_gp->tg_pt_gp_peers_group,
+ "peers",
+ &target_core_alua_tg_pt_gp_peers_cit);
+ configfs_add_default_group(&tg_pt_gp->tg_pt_gp_peers_group,
+ alua_tg_pt_gp_cg);
pr_debug("Target_Core_ConfigFS: Allocated ALUA Target Port"
" Group: alua/tg_pt_gps/%s\n",
@@ -47,6 +47,7 @@ struct kmem_cache *t10_pr_reg_cache;
struct kmem_cache *t10_alua_lu_gp_cache;
struct kmem_cache *t10_alua_lu_gp_mem_cache;
struct kmem_cache *t10_alua_tg_pt_gp_cache;
+struct kmem_cache *t10_alua_tg_pt_gp_peer_cache;
struct kmem_cache *t10_alua_lba_map_cache;
struct kmem_cache *t10_alua_lba_map_mem_cache;
@@ -105,6 +106,15 @@ int init_se_kmem_caches(void)
"cache failed\n");
goto out_free_lu_gp_mem_cache;
}
+ t10_alua_tg_pt_gp_peer_cache = kmem_cache_create(
+ "t10_alua_tg_pt_gp_peer_cache",
+ sizeof(struct t10_alua_tg_pt_gp_peer),
+ __alignof__(struct t10_alua_tg_pt_gp_peer), 0, NULL);
+ if (!t10_alua_tg_pt_gp_peer_cache) {
+ pr_err("kmem_cache_create() for t10_alua_tg_pt_gp_peer_cache"
+ " failed\n");
+ goto out_free_tg_pt_gp_cache;
+ }
t10_alua_lba_map_cache = kmem_cache_create(
"t10_alua_lba_map_cache",
sizeof(struct t10_alua_lba_map),
@@ -112,7 +122,7 @@ int init_se_kmem_caches(void)
if (!t10_alua_lba_map_cache) {
pr_err("kmem_cache_create() for t10_alua_lba_map_"
"cache failed\n");
- goto out_free_tg_pt_gp_cache;
+ goto out_free_tg_pt_gp_peer_cache;
}
t10_alua_lba_map_mem_cache = kmem_cache_create(
"t10_alua_lba_map_mem_cache",
@@ -135,6 +145,8 @@ int init_se_kmem_caches(void)
kmem_cache_destroy(t10_alua_lba_map_mem_cache);
out_free_lba_map_cache:
kmem_cache_destroy(t10_alua_lba_map_cache);
+out_free_tg_pt_gp_peer_cache:
+ kmem_cache_destroy(t10_alua_tg_pt_gp_peer_cache);
out_free_tg_pt_gp_cache:
kmem_cache_destroy(t10_alua_tg_pt_gp_cache);
out_free_lu_gp_mem_cache:
@@ -160,6 +172,7 @@ void release_se_kmem_caches(void)
kmem_cache_destroy(t10_alua_lu_gp_cache);
kmem_cache_destroy(t10_alua_lu_gp_mem_cache);
kmem_cache_destroy(t10_alua_tg_pt_gp_cache);
+ kmem_cache_destroy(t10_alua_tg_pt_gp_peer_cache);
kmem_cache_destroy(t10_alua_lba_map_cache);
kmem_cache_destroy(t10_alua_lba_map_mem_cache);
}
@@ -301,12 +301,20 @@ struct t10_alua_tg_pt_gp {
struct mutex tg_pt_gp_transition_mutex;
struct se_device *tg_pt_gp_dev;
struct config_group tg_pt_gp_group;
+ struct config_group tg_pt_gp_peers_group;
struct list_head tg_pt_gp_list;
struct list_head tg_pt_gp_lun_list;
+ struct list_head tg_pt_gp_peer_list;
struct se_lun *tg_pt_gp_alua_lun;
struct se_node_acl *tg_pt_gp_alua_nacl;
};
+struct t10_alua_tg_pt_gp_peer {
+ u16 tg_pt_gp_peer_rtpi;
+ struct config_item tg_pt_gp_peer_item;
+ struct list_head tg_pt_gp_peer_list;
+};
+
struct t10_vpd {
unsigned char device_identifier[INQUIRY_VPD_DEVICE_IDENTIFIER_LEN];
int protocol_identifier_set;
TCM can't report about ports of peer node in REPORT TARGET PORT GROUPS command if TCM is used in a cluster. The change introduces a way to store information about such ports in configfs. Each port group except default_tg_pt_gp has "peers" subdirectory. It can be used to store RTPI (RELATIVE TARGET PORT IDENTIFIER) of SCSI target ports that reside on peer nodes: mkdir $BACKSTORE/alua/pg1/peers/$RTPI Signed-off-by: Roman Bolshakov <r.bolshakov@yadro.com> --- drivers/target/target_core_alua.c | 1 + drivers/target/target_core_alua.h | 1 + drivers/target/target_core_configfs.c | 86 ++++++++++++++++++++++++++ drivers/target/target_core_transport.c | 15 ++++- include/target/target_core_base.h | 8 +++ 5 files changed, 110 insertions(+), 1 deletion(-)