diff mbox series

[2/7] scsi: target: core: Add RTPI field to target port

Message ID 20220906154519.27487-3-d.bogdanov@yadro.com
State New
Headers show
Series scsi: target: make RTPI an TPG identifier | expand

Commit Message

Dmitry Bogdanov Sept. 6, 2022, 3:45 p.m. UTC
From: Roman Bolshakov <r.bolshakov@yadro.com>

SAM-5 4.6.5.2 (Relative Port Identifier attribute) defines the attribute
as unique across SCSI target ports.

The change introduces RTPI attribute to se_portal group. The value is
auto-incremented and unique across all SCSI target ports. It also limits
number of SCSI target ports to 65535.

Signed-off-by: Roman Bolshakov <r.bolshakov@yadro.com>
Signed-off-by: Dmitry Bogdanov <d.bogdanov@yadro.com>
---
 drivers/target/target_core_tpg.c  | 78 +++++++++++++++++++++++++++++--
 include/target/target_core_base.h |  4 ++
 2 files changed, 77 insertions(+), 5 deletions(-)

Comments

Mike Christie Sept. 29, 2022, 10:26 p.m. UTC | #1
On 9/6/22 10:45 AM, Dmitry Bogdanov wrote:
> From: Roman Bolshakov <r.bolshakov@yadro.com>
> 
> SAM-5 4.6.5.2 (Relative Port Identifier attribute) defines the attribute
> as unique across SCSI target ports.
> 
> The change introduces RTPI attribute to se_portal group. The value is
> auto-incremented and unique across all SCSI target ports. It also limits
> number of SCSI target ports to 65535.
> 
> Signed-off-by: Roman Bolshakov <r.bolshakov@yadro.com>
> Signed-off-by: Dmitry Bogdanov <d.bogdanov@yadro.com>
> ---
>  drivers/target/target_core_tpg.c  | 78 +++++++++++++++++++++++++++++--
>  include/target/target_core_base.h |  4 ++
>  2 files changed, 77 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c
> index f0d38d77edcc..325ef439fb42 100644
> --- a/drivers/target/target_core_tpg.c
> +++ b/drivers/target/target_core_tpg.c
> @@ -31,6 +31,10 @@
>  #include "target_core_ua.h"
>  
>  extern struct se_device *g_lun0_dev;
> +static u16 g_tpg_count;
> +static u16 g_tpg_rtpi_counter = 1;
> +static LIST_HEAD(g_tpg_list);
> +static DEFINE_SPINLOCK(g_tpg_lock);
>  
>  /*	__core_tpg_get_initiator_node_acl():
>   *
> @@ -439,6 +443,57 @@ static void core_tpg_lun_ref_release(struct percpu_ref *ref)
>  	complete(&lun->lun_shutdown_comp);
>  }
>  
> +static int core_tpg_register_rtpi(struct se_portal_group *se_tpg)
> +{
> +	struct se_portal_group *tpg;
> +
> +	/*
> +	 * Allocate the next RELATIVE TARGET PORT IDENTIFIER.
> +	 * Here is the table from SPC-4 4.3.4:
> +	 *
> +	 *    Table 34 -- Relative target port identifier values
> +	 *
> +	 * Value		Description
> +	 * 0h			Reserved
> +	 * 1h			Relative port 1, historically known as port A
> +	 * 2h			Relative port 2, historically known as port B
> +	 * 3h to FFFFh		Relative port 3 through 65 535
> +	 */
> +	spin_lock(&g_tpg_lock);
> +
> +	if (g_tpg_count == 0xffff) {
> +		spin_unlock(&g_tpg_lock);
> +		pr_warn("Reached g_tpg_count == 0xffff\n");
> +		return -ENOSPC;
> +	}
> +again:
> +	se_tpg->tpg_rtpi = g_tpg_rtpi_counter++;
> +	if (!se_tpg->tpg_rtpi)
> +		goto again;
> +
> +	list_for_each_entry(tpg, &g_tpg_list, tpg_list) {
> +		/*
> +		 * Make sure RELATIVE TARGET PORT IDENTIFIER is unique
> +		 * for 16-bit wrap..
> +		 */
> +		if (se_tpg->tpg_rtpi == tpg->tpg_rtpi)
> +			goto again;
> +	}
> +	list_add(&se_tpg->tpg_list, &g_tpg_list);
> +	g_tpg_count++;
> +	spin_unlock(&g_tpg_lock);
> +

I think you could just use an ida.
Mike Christie Sept. 29, 2022, 11:57 p.m. UTC | #2
On 9/29/22 5:26 PM, Mike Christie wrote:
> 
> I think you could just use an ida.
>

After seeing the other patches I guess you need a idr.
Dmitry Bogdanov Oct. 4, 2022, 4:11 p.m. UTC | #3
On Thu, Sep 29, 2022 at 06:57:03PM -0500, Mike Christie wrote:
> 
> On 9/29/22 5:26 PM, Mike Christie wrote:
> >
> > I think you could just use an ida.
> >
> 
> After seeing the other patches I guess you need a idr.
> 

idr is deprecated, I looked at xarray. Looks good, I will rewrite
the patches using it. 

Thanks!
diff mbox series

Patch

diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c
index f0d38d77edcc..325ef439fb42 100644
--- a/drivers/target/target_core_tpg.c
+++ b/drivers/target/target_core_tpg.c
@@ -31,6 +31,10 @@ 
 #include "target_core_ua.h"
 
 extern struct se_device *g_lun0_dev;
+static u16 g_tpg_count;
+static u16 g_tpg_rtpi_counter = 1;
+static LIST_HEAD(g_tpg_list);
+static DEFINE_SPINLOCK(g_tpg_lock);
 
 /*	__core_tpg_get_initiator_node_acl():
  *
@@ -439,6 +443,57 @@  static void core_tpg_lun_ref_release(struct percpu_ref *ref)
 	complete(&lun->lun_shutdown_comp);
 }
 
+static int core_tpg_register_rtpi(struct se_portal_group *se_tpg)
+{
+	struct se_portal_group *tpg;
+
+	/*
+	 * Allocate the next RELATIVE TARGET PORT IDENTIFIER.
+	 * Here is the table from SPC-4 4.3.4:
+	 *
+	 *    Table 34 -- Relative target port identifier values
+	 *
+	 * Value		Description
+	 * 0h			Reserved
+	 * 1h			Relative port 1, historically known as port A
+	 * 2h			Relative port 2, historically known as port B
+	 * 3h to FFFFh		Relative port 3 through 65 535
+	 */
+	spin_lock(&g_tpg_lock);
+
+	if (g_tpg_count == 0xffff) {
+		spin_unlock(&g_tpg_lock);
+		pr_warn("Reached g_tpg_count == 0xffff\n");
+		return -ENOSPC;
+	}
+again:
+	se_tpg->tpg_rtpi = g_tpg_rtpi_counter++;
+	if (!se_tpg->tpg_rtpi)
+		goto again;
+
+	list_for_each_entry(tpg, &g_tpg_list, tpg_list) {
+		/*
+		 * Make sure RELATIVE TARGET PORT IDENTIFIER is unique
+		 * for 16-bit wrap..
+		 */
+		if (se_tpg->tpg_rtpi == tpg->tpg_rtpi)
+			goto again;
+	}
+	list_add(&se_tpg->tpg_list, &g_tpg_list);
+	g_tpg_count++;
+	spin_unlock(&g_tpg_lock);
+
+	return 0;
+}
+
+static void core_tpg_deregister_rtpi(struct se_portal_group *se_tpg)
+{
+	spin_lock(&g_tpg_lock);
+	list_del(&se_tpg->tpg_list);
+	g_tpg_count--;
+	spin_unlock(&g_tpg_lock);
+}
+
 /* Does not change se_wwn->priv. */
 int core_tpg_register(
 	struct se_wwn *se_wwn,
@@ -471,6 +526,7 @@  int core_tpg_register(
 	se_tpg->proto_id = proto_id;
 	se_tpg->se_tpg_wwn = se_wwn;
 	atomic_set(&se_tpg->tpg_pr_ref_count, 0);
+	INIT_LIST_HEAD(&se_tpg->tpg_list);
 	INIT_LIST_HEAD(&se_tpg->acl_node_list);
 	INIT_LIST_HEAD(&se_tpg->tpg_sess_list);
 	spin_lock_init(&se_tpg->session_lock);
@@ -478,9 +534,15 @@  int core_tpg_register(
 	mutex_init(&se_tpg->acl_node_mutex);
 
 	if (se_tpg->proto_id >= 0) {
+		ret = core_tpg_register_rtpi(se_tpg);
+		if (ret < 0)
+			return ret;
+
 		se_tpg->tpg_virt_lun0 = core_tpg_alloc_lun(se_tpg, 0);
-		if (IS_ERR(se_tpg->tpg_virt_lun0))
-			return PTR_ERR(se_tpg->tpg_virt_lun0);
+		if (IS_ERR(se_tpg->tpg_virt_lun0)) {
+			ret = PTR_ERR(se_tpg->tpg_virt_lun0);
+			goto out_deregister_rtpi;
+		}
 
 		ret = core_tpg_add_lun(se_tpg, se_tpg->tpg_virt_lun0,
 				true, g_lun0_dev);
@@ -488,16 +550,20 @@  int core_tpg_register(
 			goto out_free_lun0;
 	}
 
-	pr_debug("TARGET_CORE[%s]: Allocated portal_group for endpoint: %s, "
-		 "Proto: %d, Portal Tag: %u\n", se_tpg->se_tpg_tfo->fabric_name,
+	pr_debug("TARGET_CORE[%s]: Allocated portal_group for endpoint: %s, Proto: %d, Portal Tag: %u, RTPI: %#2x\n",
+		se_tpg->se_tpg_tfo->fabric_name,
 		se_tpg->se_tpg_tfo->tpg_get_wwn(se_tpg) ?
 		se_tpg->se_tpg_tfo->tpg_get_wwn(se_tpg) : NULL,
-		se_tpg->proto_id, se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg));
+		se_tpg->proto_id,
+		se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg),
+		se_tpg->tpg_rtpi);
 
 	return 0;
 
 out_free_lun0:
 	kfree(se_tpg->tpg_virt_lun0);
+out_deregister_rtpi:
+	core_tpg_deregister_rtpi(se_tpg);
 	return ret;
 }
 EXPORT_SYMBOL(core_tpg_register);
@@ -535,6 +601,8 @@  int core_tpg_deregister(struct se_portal_group *se_tpg)
 	if (se_tpg->proto_id >= 0) {
 		core_tpg_remove_lun(se_tpg, se_tpg->tpg_virt_lun0);
 		kfree_rcu(se_tpg->tpg_virt_lun0, rcu_head);
+
+		core_tpg_deregister_rtpi(se_tpg);
 	}
 
 	return 0;
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 28cce4ed3f0e..08e76e400816 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -904,6 +904,8 @@  struct se_portal_group {
 	 */
 	int			proto_id;
 	bool			enabled;
+	/* RELATIVE TARGET PORT IDENTIFIER */
+	u16			tpg_rtpi;
 	/* Used for PR SPEC_I_PT=1 and REGISTER_AND_MOVE */
 	atomic_t		tpg_pr_ref_count;
 	/* Spinlock for adding/removing ACLed Nodes */
@@ -911,6 +913,8 @@  struct se_portal_group {
 	/* Spinlock for adding/removing sessions */
 	spinlock_t		session_lock;
 	struct mutex		tpg_lun_mutex;
+	/* List of all SCSI target ports */
+	struct list_head	tpg_list;
 	/* linked list for initiator ACL list */
 	struct list_head	acl_node_list;
 	struct hlist_head	tpg_lun_hlist;