Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

target: Use array_zalloc for tpg_lun_list

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>

authored by

Jörn Engel and committed by
Nicholas Bellinger
4a5a75f3 b168fe8c

+41 -11
+2 -2
drivers/target/target_core_device.c
··· 1429 1429 spin_unlock(&tpg->tpg_lun_lock); 1430 1430 return NULL; 1431 1431 } 1432 - lun = &tpg->tpg_lun_list[unpacked_lun]; 1432 + lun = tpg->tpg_lun_list[unpacked_lun]; 1433 1433 1434 1434 if (lun->lun_status != TRANSPORT_LUN_STATUS_FREE) { 1435 1435 pr_err("%s Logical Unit Number: %u is not free on" ··· 1462 1462 spin_unlock(&tpg->tpg_lun_lock); 1463 1463 return NULL; 1464 1464 } 1465 - lun = &tpg->tpg_lun_list[unpacked_lun]; 1465 + lun = tpg->tpg_lun_list[unpacked_lun]; 1466 1466 1467 1467 if (lun->lun_status != TRANSPORT_LUN_STATUS_ACTIVE) { 1468 1468 pr_err("%s Logical Unit Number: %u is not active on"
+36 -8
drivers/target/target_core_tpg.c
··· 163 163 164 164 spin_lock(&tpg->tpg_lun_lock); 165 165 for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { 166 - lun = &tpg->tpg_lun_list[i]; 166 + lun = tpg->tpg_lun_list[i]; 167 167 if (lun->lun_status != TRANSPORT_LUN_STATUS_ACTIVE) 168 168 continue; 169 169 ··· 220 220 } 221 221 222 222 return 0; 223 + } 224 + 225 + void array_free(void *array, int n) 226 + { 227 + void **a = array; 228 + int i; 229 + 230 + for (i = 0; i < n; i++) 231 + kfree(a[i]); 232 + kfree(a); 233 + } 234 + 235 + static void *array_zalloc(int n, size_t size, gfp_t flags) 236 + { 237 + void **a; 238 + int i; 239 + 240 + a = kzalloc(n * sizeof(void*), flags); 241 + if (!a) 242 + return NULL; 243 + for (i = 0; i < n; i++) { 244 + a[i] = kzalloc(size, flags); 245 + if (!a[i]) { 246 + array_free(a, n); 247 + return NULL; 248 + } 249 + } 250 + return a; 223 251 } 224 252 225 253 /* core_create_device_list_for_node(): ··· 364 336 365 337 spin_lock(&tpg->tpg_lun_lock); 366 338 for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { 367 - lun = &tpg->tpg_lun_list[i]; 339 + lun = tpg->tpg_lun_list[i]; 368 340 369 341 if ((lun->lun_status != TRANSPORT_LUN_STATUS_ACTIVE) || 370 342 (lun->lun_se_dev == NULL)) ··· 689 661 struct se_lun *lun; 690 662 u32 i; 691 663 692 - se_tpg->tpg_lun_list = kzalloc((sizeof(struct se_lun) * 693 - TRANSPORT_MAX_LUNS_PER_TPG), GFP_KERNEL); 664 + se_tpg->tpg_lun_list = array_zalloc(TRANSPORT_MAX_LUNS_PER_TPG, 665 + sizeof(struct se_lun), GFP_KERNEL); 694 666 if (!se_tpg->tpg_lun_list) { 695 667 pr_err("Unable to allocate struct se_portal_group->" 696 668 "tpg_lun_list\n"); ··· 698 670 } 699 671 700 672 for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { 701 - lun = &se_tpg->tpg_lun_list[i]; 673 + lun = se_tpg->tpg_lun_list[i]; 702 674 lun->unpacked_lun = i; 703 675 lun->lun_status = TRANSPORT_LUN_STATUS_FREE; 704 676 atomic_set(&lun->lun_acl_count, 0); ··· 784 756 core_tpg_release_virtual_lun0(se_tpg); 785 757 786 758 se_tpg->se_tpg_fabric_ptr = NULL; 787 - kfree(se_tpg->tpg_lun_list); 759 + array_free(se_tpg->tpg_lun_list, TRANSPORT_MAX_LUNS_PER_TPG); 788 760 return 0; 789 761 } 790 762 EXPORT_SYMBOL(core_tpg_deregister); ··· 805 777 } 806 778 807 779 spin_lock(&tpg->tpg_lun_lock); 808 - lun = &tpg->tpg_lun_list[unpacked_lun]; 780 + lun = tpg->tpg_lun_list[unpacked_lun]; 809 781 if (lun->lun_status == TRANSPORT_LUN_STATUS_ACTIVE) { 810 782 pr_err("TPG Logical Unit Number: %u is already active" 811 783 " on %s Target Portal Group: %u, ignoring request.\n", ··· 863 835 } 864 836 865 837 spin_lock(&tpg->tpg_lun_lock); 866 - lun = &tpg->tpg_lun_list[unpacked_lun]; 838 + lun = tpg->tpg_lun_list[unpacked_lun]; 867 839 if (lun->lun_status != TRANSPORT_LUN_STATUS_ACTIVE) { 868 840 pr_err("%s Logical Unit Number: %u is not active on" 869 841 " Target Portal Group: %u, ignoring request.\n",
+2
include/target/target_core_backend.h
··· 62 62 void *transport_kmap_data_sg(struct se_cmd *); 63 63 void transport_kunmap_data_sg(struct se_cmd *); 64 64 65 + void array_free(void *array, int n); 66 + 65 67 #endif /* TARGET_CORE_BACKEND_H */
+1 -1
include/target/target_core_base.h
··· 934 934 struct list_head se_tpg_node; 935 935 /* linked list for initiator ACL list */ 936 936 struct list_head acl_node_list; 937 - struct se_lun *tpg_lun_list; 937 + struct se_lun **tpg_lun_list; 938 938 struct se_lun tpg_virt_lun0; 939 939 /* List of TCM sessions associated wth this TPG */ 940 940 struct list_head tpg_sess_list;