mirror of https://gitee.com/openkylin/linux.git
[SCSI] libiscsi, iscsi_tcp: iscsi pool cleanup
iscsi_pool_init simplified iscsi_pool_init currently has a lot of duplicate kfree() calls it does when some allocation fails. This patch simplifies the code a little by using iscsi_pool_free to tear down the pool in case of an error. iscsi_pool_init also returns a copy of the item array to the caller. Not all callers use this array, so we make it optional. Instead of allocating a second array and return that, allocate just one array, of twice the size. Update users of iscsi_pool_{init,free} This patch drops the (now useless) second argument to iscsi_pool_free, and updates all callers. It also removes the ctask->r2ts array, which was never used anyway. Since the items argument to iscsi_pool_init is now optional, we can pass NULL instead. Signed-off-by: Olaf Kirch <olaf.kirch@oracle.com> Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
This commit is contained in:
parent
38ad03de3f
commit
6320377fd9
|
@ -1998,8 +1998,7 @@ iscsi_r2tpool_alloc(struct iscsi_session *session)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* R2T pool */
|
/* R2T pool */
|
||||||
if (iscsi_pool_init(&tcp_ctask->r2tpool, session->max_r2t * 4,
|
if (iscsi_pool_init(&tcp_ctask->r2tpool, session->max_r2t * 4, NULL,
|
||||||
(void***)&tcp_ctask->r2ts,
|
|
||||||
sizeof(struct iscsi_r2t_info))) {
|
sizeof(struct iscsi_r2t_info))) {
|
||||||
goto r2t_alloc_fail;
|
goto r2t_alloc_fail;
|
||||||
}
|
}
|
||||||
|
@ -2008,8 +2007,7 @@ iscsi_r2tpool_alloc(struct iscsi_session *session)
|
||||||
tcp_ctask->r2tqueue = kfifo_alloc(
|
tcp_ctask->r2tqueue = kfifo_alloc(
|
||||||
session->max_r2t * 4 * sizeof(void*), GFP_KERNEL, NULL);
|
session->max_r2t * 4 * sizeof(void*), GFP_KERNEL, NULL);
|
||||||
if (tcp_ctask->r2tqueue == ERR_PTR(-ENOMEM)) {
|
if (tcp_ctask->r2tqueue == ERR_PTR(-ENOMEM)) {
|
||||||
iscsi_pool_free(&tcp_ctask->r2tpool,
|
iscsi_pool_free(&tcp_ctask->r2tpool);
|
||||||
(void**)tcp_ctask->r2ts);
|
|
||||||
goto r2t_alloc_fail;
|
goto r2t_alloc_fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2022,8 +2020,7 @@ iscsi_r2tpool_alloc(struct iscsi_session *session)
|
||||||
struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
|
struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
|
||||||
|
|
||||||
kfifo_free(tcp_ctask->r2tqueue);
|
kfifo_free(tcp_ctask->r2tqueue);
|
||||||
iscsi_pool_free(&tcp_ctask->r2tpool,
|
iscsi_pool_free(&tcp_ctask->r2tpool);
|
||||||
(void**)tcp_ctask->r2ts);
|
|
||||||
}
|
}
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
@ -2038,8 +2035,7 @@ iscsi_r2tpool_free(struct iscsi_session *session)
|
||||||
struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
|
struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
|
||||||
|
|
||||||
kfifo_free(tcp_ctask->r2tqueue);
|
kfifo_free(tcp_ctask->r2tqueue);
|
||||||
iscsi_pool_free(&tcp_ctask->r2tpool,
|
iscsi_pool_free(&tcp_ctask->r2tpool);
|
||||||
(void**)tcp_ctask->r2ts);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -175,9 +175,8 @@ struct iscsi_tcp_cmd_task {
|
||||||
uint32_t exp_datasn; /* expected target's R2TSN/DataSN */
|
uint32_t exp_datasn; /* expected target's R2TSN/DataSN */
|
||||||
int data_offset;
|
int data_offset;
|
||||||
struct iscsi_r2t_info *r2t; /* in progress R2T */
|
struct iscsi_r2t_info *r2t; /* in progress R2T */
|
||||||
struct iscsi_queue r2tpool;
|
struct iscsi_pool r2tpool;
|
||||||
struct kfifo *r2tqueue;
|
struct kfifo *r2tqueue;
|
||||||
struct iscsi_r2t_info **r2ts;
|
|
||||||
int digest_count;
|
int digest_count;
|
||||||
uint32_t immdigest; /* for imm data */
|
uint32_t immdigest; /* for imm data */
|
||||||
struct iscsi_buf immbuf; /* for imm data digest */
|
struct iscsi_buf immbuf; /* for imm data digest */
|
||||||
|
|
|
@ -1413,59 +1413,64 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(iscsi_eh_device_reset);
|
EXPORT_SYMBOL_GPL(iscsi_eh_device_reset);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pre-allocate a pool of @max items of @item_size. By default, the pool
|
||||||
|
* should be accessed via kfifo_{get,put} on q->queue.
|
||||||
|
* Optionally, the caller can obtain the array of object pointers
|
||||||
|
* by passing in a non-NULL @items pointer
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
iscsi_pool_init(struct iscsi_queue *q, int max, void ***items, int item_size)
|
iscsi_pool_init(struct iscsi_pool *q, int max, void ***items, int item_size)
|
||||||
{
|
{
|
||||||
int i;
|
int i, num_arrays = 1;
|
||||||
|
|
||||||
*items = kmalloc(max * sizeof(void*), GFP_KERNEL);
|
memset(q, 0, sizeof(*q));
|
||||||
if (*items == NULL)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
q->max = max;
|
q->max = max;
|
||||||
q->pool = kmalloc(max * sizeof(void*), GFP_KERNEL);
|
|
||||||
if (q->pool == NULL) {
|
/* If the user passed an items pointer, he wants a copy of
|
||||||
kfree(*items);
|
* the array. */
|
||||||
return -ENOMEM;
|
if (items)
|
||||||
}
|
num_arrays++;
|
||||||
|
q->pool = kzalloc(num_arrays * max * sizeof(void*), GFP_KERNEL);
|
||||||
|
if (q->pool == NULL)
|
||||||
|
goto enomem;
|
||||||
|
|
||||||
q->queue = kfifo_init((void*)q->pool, max * sizeof(void*),
|
q->queue = kfifo_init((void*)q->pool, max * sizeof(void*),
|
||||||
GFP_KERNEL, NULL);
|
GFP_KERNEL, NULL);
|
||||||
if (q->queue == ERR_PTR(-ENOMEM)) {
|
if (q->queue == ERR_PTR(-ENOMEM))
|
||||||
kfree(q->pool);
|
goto enomem;
|
||||||
kfree(*items);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < max; i++) {
|
for (i = 0; i < max; i++) {
|
||||||
q->pool[i] = kmalloc(item_size, GFP_KERNEL);
|
q->pool[i] = kzalloc(item_size, GFP_KERNEL);
|
||||||
if (q->pool[i] == NULL) {
|
if (q->pool[i] == NULL) {
|
||||||
int j;
|
q->max = i;
|
||||||
|
goto enomem;
|
||||||
for (j = 0; j < i; j++)
|
|
||||||
kfree(q->pool[j]);
|
|
||||||
|
|
||||||
kfifo_free(q->queue);
|
|
||||||
kfree(q->pool);
|
|
||||||
kfree(*items);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
}
|
||||||
memset(q->pool[i], 0, item_size);
|
|
||||||
(*items)[i] = q->pool[i];
|
|
||||||
__kfifo_put(q->queue, (void*)&q->pool[i], sizeof(void*));
|
__kfifo_put(q->queue, (void*)&q->pool[i], sizeof(void*));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (items) {
|
||||||
|
*items = q->pool + max;
|
||||||
|
memcpy(*items, q->pool, max * sizeof(void *));
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
enomem:
|
||||||
|
iscsi_pool_free(q);
|
||||||
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(iscsi_pool_init);
|
EXPORT_SYMBOL_GPL(iscsi_pool_init);
|
||||||
|
|
||||||
void iscsi_pool_free(struct iscsi_queue *q, void **items)
|
void iscsi_pool_free(struct iscsi_pool *q)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < q->max; i++)
|
for (i = 0; i < q->max; i++)
|
||||||
kfree(items[i]);
|
kfree(q->pool[i]);
|
||||||
kfree(q->pool);
|
if (q->pool)
|
||||||
kfree(items);
|
kfree(q->pool);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(iscsi_pool_free);
|
EXPORT_SYMBOL_GPL(iscsi_pool_free);
|
||||||
|
|
||||||
|
@ -1610,9 +1615,9 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
|
||||||
cls_session_fail:
|
cls_session_fail:
|
||||||
scsi_remove_host(shost);
|
scsi_remove_host(shost);
|
||||||
add_host_fail:
|
add_host_fail:
|
||||||
iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
|
iscsi_pool_free(&session->mgmtpool);
|
||||||
mgmtpool_alloc_fail:
|
mgmtpool_alloc_fail:
|
||||||
iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
|
iscsi_pool_free(&session->cmdpool);
|
||||||
cmdpool_alloc_fail:
|
cmdpool_alloc_fail:
|
||||||
scsi_host_put(shost);
|
scsi_host_put(shost);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1635,8 +1640,8 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
|
||||||
iscsi_unblock_session(cls_session);
|
iscsi_unblock_session(cls_session);
|
||||||
scsi_remove_host(shost);
|
scsi_remove_host(shost);
|
||||||
|
|
||||||
iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
|
iscsi_pool_free(&session->mgmtpool);
|
||||||
iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
|
iscsi_pool_free(&session->cmdpool);
|
||||||
|
|
||||||
kfree(session->password);
|
kfree(session->password);
|
||||||
kfree(session->password_in);
|
kfree(session->password_in);
|
||||||
|
|
|
@ -215,7 +215,7 @@ struct iscsi_conn {
|
||||||
uint32_t eh_abort_cnt;
|
uint32_t eh_abort_cnt;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct iscsi_queue {
|
struct iscsi_pool {
|
||||||
struct kfifo *queue; /* FIFO Queue */
|
struct kfifo *queue; /* FIFO Queue */
|
||||||
void **pool; /* Pool of elements */
|
void **pool; /* Pool of elements */
|
||||||
int max; /* Max number of elements */
|
int max; /* Max number of elements */
|
||||||
|
@ -274,10 +274,10 @@ struct iscsi_session {
|
||||||
|
|
||||||
int cmds_max; /* size of cmds array */
|
int cmds_max; /* size of cmds array */
|
||||||
struct iscsi_cmd_task **cmds; /* Original Cmds arr */
|
struct iscsi_cmd_task **cmds; /* Original Cmds arr */
|
||||||
struct iscsi_queue cmdpool; /* PDU's pool */
|
struct iscsi_pool cmdpool; /* PDU's pool */
|
||||||
int mgmtpool_max; /* size of mgmt array */
|
int mgmtpool_max; /* size of mgmt array */
|
||||||
struct iscsi_mgmt_task **mgmt_cmds; /* Original mgmt arr */
|
struct iscsi_mgmt_task **mgmt_cmds; /* Original mgmt arr */
|
||||||
struct iscsi_queue mgmtpool; /* Mgmt PDU's pool */
|
struct iscsi_pool mgmtpool; /* Mgmt PDU's pool */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -350,8 +350,8 @@ extern void iscsi_requeue_ctask(struct iscsi_cmd_task *ctask);
|
||||||
/*
|
/*
|
||||||
* generic helpers
|
* generic helpers
|
||||||
*/
|
*/
|
||||||
extern void iscsi_pool_free(struct iscsi_queue *, void **);
|
extern void iscsi_pool_free(struct iscsi_pool *);
|
||||||
extern int iscsi_pool_init(struct iscsi_queue *, int, void ***, int);
|
extern int iscsi_pool_init(struct iscsi_pool *, int, void ***, int);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* inline functions to deal with padding.
|
* inline functions to deal with padding.
|
||||||
|
|
Loading…
Reference in New Issue