target: Use array_zalloc for tpg_lun_list
Jörn Engel [Thu, 15 Mar 2012 19:05:12 +0000 (15:05 -0400)]
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@logfs.org>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>

drivers/target/target_core_device.c
drivers/target/target_core_tpg.c
include/target/target_core_backend.h
include/target/target_core_base.h

index 5cfaa4b..fd7f17c 100644 (file)
@@ -1429,7 +1429,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"
@@ -1462,7 +1462,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"
index f3ea385..146fe47 100644 (file)
@@ -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():
  *
  *
@@ -336,7 +364,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))
@@ -661,8 +689,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");
@@ -670,7 +698,7 @@ int core_tpg_register(
        }
 
        for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
-               lun = &se_tpg->tpg_lun_list[i];
+               lun = se_tpg->tpg_lun_list[i];
                lun->unpacked_lun = i;
                lun->lun_status = TRANSPORT_LUN_STATUS_FREE;
                atomic_set(&lun->lun_acl_count, 0);
@@ -756,7 +784,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);
@@ -777,7 +805,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",
@@ -835,7 +863,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",
index e5e6ff9..8c9ff1b 100644 (file)
@@ -62,4 +62,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 */
index c333409..fc918a7 100644 (file)
@@ -934,7 +934,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;