diff options
Diffstat (limited to 'drivers/scsi/libiscsi.c')
-rw-r--r-- | drivers/scsi/libiscsi.c | 75 |
1 files changed, 40 insertions, 35 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 59365864c989..d43f909a022c 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -1413,59 +1413,64 @@ done: | |||
1413 | } | 1413 | } |
1414 | EXPORT_SYMBOL_GPL(iscsi_eh_device_reset); | 1414 | EXPORT_SYMBOL_GPL(iscsi_eh_device_reset); |
1415 | 1415 | ||
1416 | /* | ||
1417 | * Pre-allocate a pool of @max items of @item_size. By default, the pool | ||
1418 | * should be accessed via kfifo_{get,put} on q->queue. | ||
1419 | * Optionally, the caller can obtain the array of object pointers | ||
1420 | * by passing in a non-NULL @items pointer | ||
1421 | */ | ||
1416 | int | 1422 | int |
1417 | iscsi_pool_init(struct iscsi_queue *q, int max, void ***items, int item_size) | 1423 | iscsi_pool_init(struct iscsi_pool *q, int max, void ***items, int item_size) |
1418 | { | 1424 | { |
1419 | int i; | 1425 | int i, num_arrays = 1; |
1420 | 1426 | ||
1421 | *items = kmalloc(max * sizeof(void*), GFP_KERNEL); | 1427 | memset(q, 0, sizeof(*q)); |
1422 | if (*items == NULL) | ||
1423 | return -ENOMEM; | ||
1424 | 1428 | ||
1425 | q->max = max; | 1429 | q->max = max; |
1426 | q->pool = kmalloc(max * sizeof(void*), GFP_KERNEL); | 1430 | |
1427 | if (q->pool == NULL) { | 1431 | /* If the user passed an items pointer, he wants a copy of |
1428 | kfree(*items); | 1432 | * the array. */ |
1429 | return -ENOMEM; | 1433 | if (items) |
1430 | } | 1434 | num_arrays++; |
1435 | q->pool = kzalloc(num_arrays * max * sizeof(void*), GFP_KERNEL); | ||
1436 | if (q->pool == NULL) | ||
1437 | goto enomem; | ||
1431 | 1438 | ||
1432 | q->queue = kfifo_init((void*)q->pool, max * sizeof(void*), | 1439 | q->queue = kfifo_init((void*)q->pool, max * sizeof(void*), |
1433 | GFP_KERNEL, NULL); | 1440 | GFP_KERNEL, NULL); |
1434 | if (q->queue == ERR_PTR(-ENOMEM)) { | 1441 | if (q->queue == ERR_PTR(-ENOMEM)) |
1435 | kfree(q->pool); | 1442 | goto enomem; |
1436 | kfree(*items); | ||
1437 | return -ENOMEM; | ||
1438 | } | ||
1439 | 1443 | ||
1440 | for (i = 0; i < max; i++) { | 1444 | for (i = 0; i < max; i++) { |
1441 | q->pool[i] = kmalloc(item_size, GFP_KERNEL); | 1445 | q->pool[i] = kzalloc(item_size, GFP_KERNEL); |
1442 | if (q->pool[i] == NULL) { | 1446 | if (q->pool[i] == NULL) { |
1443 | int j; | 1447 | q->max = i; |
1444 | 1448 | goto enomem; | |
1445 | for (j = 0; j < i; j++) | ||
1446 | kfree(q->pool[j]); | ||
1447 | |||
1448 | kfifo_free(q->queue); | ||
1449 | kfree(q->pool); | ||
1450 | kfree(*items); | ||
1451 | return -ENOMEM; | ||
1452 | } | 1449 | } |
1453 | memset(q->pool[i], 0, item_size); | ||
1454 | (*items)[i] = q->pool[i]; | ||
1455 | __kfifo_put(q->queue, (void*)&q->pool[i], sizeof(void*)); | 1450 | __kfifo_put(q->queue, (void*)&q->pool[i], sizeof(void*)); |
1456 | } | 1451 | } |
1452 | |||
1453 | if (items) { | ||
1454 | *items = q->pool + max; | ||
1455 | memcpy(*items, q->pool, max * sizeof(void *)); | ||
1456 | } | ||
1457 | |||
1457 | return 0; | 1458 | return 0; |
1459 | |||
1460 | enomem: | ||
1461 | iscsi_pool_free(q); | ||
1462 | return -ENOMEM; | ||
1458 | } | 1463 | } |
1459 | EXPORT_SYMBOL_GPL(iscsi_pool_init); | 1464 | EXPORT_SYMBOL_GPL(iscsi_pool_init); |
1460 | 1465 | ||
1461 | void iscsi_pool_free(struct iscsi_queue *q, void **items) | 1466 | void iscsi_pool_free(struct iscsi_pool *q) |
1462 | { | 1467 | { |
1463 | int i; | 1468 | int i; |
1464 | 1469 | ||
1465 | for (i = 0; i < q->max; i++) | 1470 | for (i = 0; i < q->max; i++) |
1466 | kfree(items[i]); | 1471 | kfree(q->pool[i]); |
1467 | kfree(q->pool); | 1472 | if (q->pool) |
1468 | kfree(items); | 1473 | kfree(q->pool); |
1469 | } | 1474 | } |
1470 | EXPORT_SYMBOL_GPL(iscsi_pool_free); | 1475 | EXPORT_SYMBOL_GPL(iscsi_pool_free); |
1471 | 1476 | ||
@@ -1610,9 +1615,9 @@ module_put: | |||
1610 | cls_session_fail: | 1615 | cls_session_fail: |
1611 | scsi_remove_host(shost); | 1616 | scsi_remove_host(shost); |
1612 | add_host_fail: | 1617 | add_host_fail: |
1613 | iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); | 1618 | iscsi_pool_free(&session->mgmtpool); |
1614 | mgmtpool_alloc_fail: | 1619 | mgmtpool_alloc_fail: |
1615 | iscsi_pool_free(&session->cmdpool, (void**)session->cmds); | 1620 | iscsi_pool_free(&session->cmdpool); |
1616 | cmdpool_alloc_fail: | 1621 | cmdpool_alloc_fail: |
1617 | scsi_host_put(shost); | 1622 | scsi_host_put(shost); |
1618 | return NULL; | 1623 | return NULL; |
@@ -1635,8 +1640,8 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session) | |||
1635 | iscsi_unblock_session(cls_session); | 1640 | iscsi_unblock_session(cls_session); |
1636 | scsi_remove_host(shost); | 1641 | scsi_remove_host(shost); |
1637 | 1642 | ||
1638 | iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); | 1643 | iscsi_pool_free(&session->mgmtpool); |
1639 | iscsi_pool_free(&session->cmdpool, (void**)session->cmds); | 1644 | iscsi_pool_free(&session->cmdpool); |
1640 | 1645 | ||
1641 | kfree(session->password); | 1646 | kfree(session->password); |
1642 | kfree(session->password_in); | 1647 | kfree(session->password_in); |