[PATCH 1/2] Target: Use array_zalloc for tpg_lun_list

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Turns an order-10 allocation into slab-sized ones, thereby preventing
allocation failures with memory fragmentation.

This likely saves memory as well, as the slab allocator can pack objects
more tightly than the buddy allocator.

Signed-off-by: Joern Engel <joern@xxxxxxxxx>
---
 drivers/target/target_core_device.c  |    4 +-
 drivers/target/target_core_tpg.c     |   42 ++++++++++++++++++++++++++++-----
 include/target/target_core_backend.h |    2 +
 include/target/target_core_base.h    |    2 +-
 4 files changed, 40 insertions(+), 10 deletions(-)

diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c
index c96f248..d8dedc2 100644
--- a/drivers/target/target_core_device.c
+++ b/drivers/target/target_core_device.c
@@ -1403,7 +1403,7 @@ struct se_lun *core_get_lun_from_tpg(struct se_portal_group *tpg, u32 unpacked_l
 		spin_unlock(&tpg->tpg_lun_lock);
 		return NULL;
 	}
-	lun = &tpg->tpg_lun_list[unpacked_lun];
+	lun = tpg->tpg_lun_list[unpacked_lun];
 
 	if (lun->lun_status != TRANSPORT_LUN_STATUS_FREE) {
 		pr_err("%s Logical Unit Number: %u is not free on"
@@ -1436,7 +1436,7 @@ static struct se_lun *core_dev_get_lun(struct se_portal_group *tpg, u32 unpacked
 		spin_unlock(&tpg->tpg_lun_lock);
 		return NULL;
 	}
-	lun = &tpg->tpg_lun_list[unpacked_lun];
+	lun = tpg->tpg_lun_list[unpacked_lun];
 
 	if (lun->lun_status != TRANSPORT_LUN_STATUS_ACTIVE) {
 		pr_err("%s Logical Unit Number: %u is not active on"
diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c
index a3ece61..a096eac 100644
--- a/drivers/target/target_core_tpg.c
+++ b/drivers/target/target_core_tpg.c
@@ -163,7 +163,7 @@ void core_tpg_add_node_to_devs(
 
 	spin_lock(&tpg->tpg_lun_lock);
 	for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
-		lun = &tpg->tpg_lun_list[i];
+		lun = tpg->tpg_lun_list[i];
 		if (lun->lun_status != TRANSPORT_LUN_STATUS_ACTIVE)
 			continue;
 
@@ -222,6 +222,34 @@ static int core_set_queue_depth_for_node(
 	return 0;
 }
 
+void array_free(void *array, int n)
+{
+	void **a = array;
+	int i;
+
+	for (i = 0; i < n; i++)
+		kfree(a[i]);
+	kfree(a);
+}
+
+static void *array_zalloc(int n, size_t size, gfp_t flags)
+{
+	void **a;
+	int i;
+
+	a = kzalloc(n * sizeof(void*), flags);
+	if (!a)
+		return NULL;
+	for (i = 0; i < n; i++) {
+		a[i] = kzalloc(size, flags);
+		if (!a[i]) {
+			array_free(a, n);
+			return NULL;
+		}
+	}
+	return a;
+}
+
 /*      core_create_device_list_for_node():
  *
  *
@@ -335,7 +363,7 @@ void core_tpg_clear_object_luns(struct se_portal_group *tpg)
 
 	spin_lock(&tpg->tpg_lun_lock);
 	for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
-		lun = &tpg->tpg_lun_list[i];
+		lun = tpg->tpg_lun_list[i];
 
 		if ((lun->lun_status != TRANSPORT_LUN_STATUS_ACTIVE) ||
 		    (lun->lun_se_dev == NULL))
@@ -650,8 +678,8 @@ int core_tpg_register(
 	struct se_lun *lun;
 	u32 i;
 
-	se_tpg->tpg_lun_list = kzalloc((sizeof(struct se_lun) *
-				TRANSPORT_MAX_LUNS_PER_TPG), GFP_KERNEL);
+	se_tpg->tpg_lun_list = array_zalloc(TRANSPORT_MAX_LUNS_PER_TPG,
+			sizeof(struct se_lun), GFP_KERNEL);
 	if (!se_tpg->tpg_lun_list) {
 		pr_err("Unable to allocate struct se_portal_group->"
 				"tpg_lun_list\n");
@@ -745,7 +773,7 @@ int core_tpg_deregister(struct se_portal_group *se_tpg)
 		core_tpg_release_virtual_lun0(se_tpg);
 
 	se_tpg->se_tpg_fabric_ptr = NULL;
-	kfree(se_tpg->tpg_lun_list);
+	array_free(se_tpg->tpg_lun_list, TRANSPORT_MAX_LUNS_PER_TPG);
 	return 0;
 }
 EXPORT_SYMBOL(core_tpg_deregister);
@@ -766,7 +794,7 @@ struct se_lun *core_tpg_pre_addlun(
 	}
 
 	spin_lock(&tpg->tpg_lun_lock);
-	lun = &tpg->tpg_lun_list[unpacked_lun];
+	lun = tpg->tpg_lun_list[unpacked_lun];
 	if (lun->lun_status == TRANSPORT_LUN_STATUS_ACTIVE) {
 		pr_err("TPG Logical Unit Number: %u is already active"
 			" on %s Target Portal Group: %u, ignoring request.\n",
@@ -824,7 +852,7 @@ struct se_lun *core_tpg_pre_dellun(
 	}
 
 	spin_lock(&tpg->tpg_lun_lock);
-	lun = &tpg->tpg_lun_list[unpacked_lun];
+	lun = tpg->tpg_lun_list[unpacked_lun];
 	if (lun->lun_status != TRANSPORT_LUN_STATUS_ACTIVE) {
 		pr_err("%s Logical Unit Number: %u is not active on"
 			" Target Portal Group: %u, ignoring request.\n",
diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h
index 5148138..047f6a2 100644
--- a/include/target/target_core_backend.h
+++ b/include/target/target_core_backend.h
@@ -64,4 +64,6 @@ int	transport_set_vpd_ident(struct t10_vpd *, unsigned char *);
 void	*transport_kmap_data_sg(struct se_cmd *);
 void	transport_kunmap_data_sg(struct se_cmd *);
 
+void	array_free(void *array, int n);
+
 #endif /* TARGET_CORE_BACKEND_H */
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 82db05a..fc0f816 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -936,7 +936,7 @@ struct se_portal_group {
 	struct list_head	se_tpg_node;
 	/* linked list for initiator ACL list */
 	struct list_head	acl_node_list;
-	struct se_lun		*tpg_lun_list;
+	struct se_lun		**tpg_lun_list;
 	struct se_lun		tpg_virt_lun0;
 	/* List of TCM sessions associated wth this TPG */
 	struct list_head	tpg_sess_list;
-- 
1.7.9

--
To unsubscribe from this list: send the line "unsubscribe target-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux SCSI]     [Kernel Newbies]     [Linux SCSI Target Infrastructure]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Device Mapper]

  Powered by Linux