int iscsi_tcp_r2tpool_alloc(struct iscsi_session *session) { int i; int cmd_i; /* * initialize per-task: R2T pool and xmit queue */ for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { struct iscsi_task *task = session->cmds[cmd_i]; struct iscsi_tcp_task *tcp_task = task->dd_data; /* * pre-allocated x2 as much r2ts to handle race when * target acks DataOut faster than we data_xmit() queues * could replenish r2tqueue. */ /* R2T pool */ if (iscsi_pool_init(&tcp_task->r2tpool, session->max_r2t * 2, NULL, sizeof(struct iscsi_r2t_info))) { goto r2t_alloc_fail; } /* R2T xmit queue */ if (kfifo_alloc(&tcp_task->r2tqueue, session->max_r2t * 4 * sizeof(void*), GFP_KERNEL)) { iscsi_pool_free(&tcp_task->r2tpool); goto r2t_alloc_fail; } spin_lock_init(&tcp_task->pool2queue); spin_lock_init(&tcp_task->queue2pool); } return 0; r2t_alloc_fail: for (i = 0; i < cmd_i; i++) { struct iscsi_task *task = session->cmds[i]; struct iscsi_tcp_task *tcp_task = task->dd_data; kfifo_free(&tcp_task->r2tqueue); iscsi_pool_free(&tcp_task->r2tpool); } return -ENOMEM; }
void iscsi_tcp_r2tpool_free(struct iscsi_session *session) { int i; for (i = 0; i < session->cmds_max; i++) { struct iscsi_task *task = session->cmds[i]; struct iscsi_tcp_task *tcp_task = task->dd_data; kfifo_free(&tcp_task->r2tqueue); iscsi_pool_free(&tcp_task->r2tpool); } }