lib/iscsi: Make the data_in_cnt only used for subread tasks.
Purpose: Do not let the primary task do the I/O if it is splitted into subtasks. This will make the code simplier, when all the sub I/Os are finished, we can free the primary task. Update the corresponding unit test also. As a result of this change, when read I/O is split into subtasks, the primary task uses only some of its data. Hence separate iscsi_pdu_payload_op_scsi_read() into split and non-split case explicitly. Signed-off-by: Ziye Yang <ziye.yang@intel.com> Change-Id: I9bbe4b8dd92a2996f35ad810b33676e34670c77e Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/473532 Reviewed-by: Changpeng Liu <changpeng.liu@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
parent
eb7e1f7e97
commit
1435ee36fa
@ -304,35 +304,15 @@ error_return:
|
|||||||
void
|
void
|
||||||
spdk_iscsi_conn_free_pdu(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
|
spdk_iscsi_conn_free_pdu(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
|
||||||
{
|
{
|
||||||
struct spdk_iscsi_task *primary;
|
|
||||||
|
|
||||||
if (pdu->task) {
|
if (pdu->task) {
|
||||||
primary = spdk_iscsi_task_get_primary(pdu->task);
|
|
||||||
if (pdu->bhs.opcode == ISCSI_OP_SCSI_DATAIN) {
|
if (pdu->bhs.opcode == ISCSI_OP_SCSI_DATAIN) {
|
||||||
if (pdu->task->scsi.offset > 0) {
|
if (pdu->task != spdk_iscsi_task_get_primary(pdu->task)) {
|
||||||
assert(conn->data_in_cnt > 0);
|
assert(conn->data_in_cnt > 0);
|
||||||
conn->data_in_cnt--;
|
conn->data_in_cnt--;
|
||||||
if (pdu->bhs.flags & ISCSI_DATAIN_STATUS) {
|
|
||||||
/* Free the primary task after the last subtask done */
|
|
||||||
assert(conn->data_in_cnt > 0);
|
|
||||||
conn->data_in_cnt--;
|
|
||||||
spdk_iscsi_task_put(primary);
|
|
||||||
}
|
|
||||||
spdk_iscsi_conn_handle_queued_datain_tasks(conn);
|
spdk_iscsi_conn_handle_queued_datain_tasks(conn);
|
||||||
}
|
}
|
||||||
} else if (pdu->bhs.opcode == ISCSI_OP_SCSI_RSP &&
|
|
||||||
pdu->task->scsi.status != SPDK_SCSI_STATUS_GOOD) {
|
|
||||||
if (pdu->task->scsi.offset > 0) {
|
|
||||||
if (spdk_iscsi_task_is_read(primary)) {
|
|
||||||
if (primary->bytes_completed == primary->scsi.transfer_len) {
|
|
||||||
/* Free the primary task after the last subtask done */
|
|
||||||
assert(conn->data_in_cnt > 0);
|
|
||||||
conn->data_in_cnt--;
|
|
||||||
spdk_iscsi_task_put(primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spdk_iscsi_task_put(pdu->task);
|
spdk_iscsi_task_put(pdu->task);
|
||||||
}
|
}
|
||||||
spdk_put_pdu(pdu);
|
spdk_put_pdu(pdu);
|
||||||
@ -1035,6 +1015,10 @@ process_completed_read_subtask_list(struct spdk_iscsi_conn *conn,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (primary->bytes_completed == primary->scsi.transfer_len) {
|
||||||
|
spdk_iscsi_task_put(primary);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1063,27 +1047,27 @@ process_read_task_completion(struct spdk_iscsi_conn *conn,
|
|||||||
iscsi_task_copy_from_rsp_scsi_status(&task->scsi, primary);
|
iscsi_task_copy_from_rsp_scsi_status(&task->scsi, primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((task != primary) &&
|
if (task == primary) {
|
||||||
(task->scsi.offset != primary->bytes_completed)) {
|
primary->bytes_completed = task->scsi.length;
|
||||||
TAILQ_FOREACH(tmp, &primary->subtask_list, subtask_link) {
|
/* For non split read I/O */
|
||||||
if (task->scsi.offset < tmp->scsi.offset) {
|
assert(primary->bytes_completed == task->scsi.transfer_len);
|
||||||
TAILQ_INSERT_BEFORE(tmp, task, subtask_link);
|
spdk_iscsi_task_response(conn, task);
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TAILQ_INSERT_TAIL(&primary->subtask_list, task, subtask_link);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
primary->bytes_completed += task->scsi.length;
|
|
||||||
spdk_iscsi_task_response(conn, task);
|
|
||||||
|
|
||||||
if ((task != primary) ||
|
|
||||||
(task->scsi.transfer_len == task->scsi.length)) {
|
|
||||||
spdk_iscsi_task_put(task);
|
spdk_iscsi_task_put(task);
|
||||||
|
} else {
|
||||||
|
if (task->scsi.offset != primary->bytes_completed) {
|
||||||
|
TAILQ_FOREACH(tmp, &primary->subtask_list, subtask_link) {
|
||||||
|
if (task->scsi.offset < tmp->scsi.offset) {
|
||||||
|
TAILQ_INSERT_BEFORE(tmp, task, subtask_link);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TAILQ_INSERT_TAIL(&primary->subtask_list, task, subtask_link);
|
||||||
|
} else {
|
||||||
|
TAILQ_INSERT_HEAD(&primary->subtask_list, task, subtask_link);
|
||||||
|
process_completed_read_subtask_list(conn, primary);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
process_completed_read_subtask_list(conn, primary);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -3039,7 +3039,6 @@ iscsi_transfer_in(struct spdk_iscsi_conn *conn, struct spdk_iscsi_task *task)
|
|||||||
assert(conn->data_in_cnt > 0);
|
assert(conn->data_in_cnt > 0);
|
||||||
conn->data_in_cnt--;
|
conn->data_in_cnt--;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3253,19 +3252,6 @@ int spdk_iscsi_conn_handle_queued_datain_tasks(struct spdk_iscsi_conn *conn)
|
|||||||
conn->data_in_cnt < MAX_LARGE_DATAIN_PER_CONNECTION) {
|
conn->data_in_cnt < MAX_LARGE_DATAIN_PER_CONNECTION) {
|
||||||
task = TAILQ_FIRST(&conn->queued_datain_tasks);
|
task = TAILQ_FIRST(&conn->queued_datain_tasks);
|
||||||
assert(task->current_datain_offset <= task->scsi.transfer_len);
|
assert(task->current_datain_offset <= task->scsi.transfer_len);
|
||||||
|
|
||||||
if (task->current_datain_offset == 0) {
|
|
||||||
if (spdk_scsi_dev_get_lun(conn->dev, task->lun_id) == NULL) {
|
|
||||||
TAILQ_REMOVE(&conn->queued_datain_tasks, task, link);
|
|
||||||
spdk_scsi_task_process_null_lun(&task->scsi);
|
|
||||||
spdk_iscsi_task_cpl(&task->scsi);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
task->current_datain_offset = task->scsi.length;
|
|
||||||
conn->data_in_cnt++;
|
|
||||||
iscsi_queue_task(conn, task);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (task->current_datain_offset < task->scsi.transfer_len) {
|
if (task->current_datain_offset < task->scsi.transfer_len) {
|
||||||
struct spdk_iscsi_task *subtask;
|
struct spdk_iscsi_task *subtask;
|
||||||
uint32_t remaining_size = 0;
|
uint32_t remaining_size = 0;
|
||||||
@ -3274,22 +3260,22 @@ int spdk_iscsi_conn_handle_queued_datain_tasks(struct spdk_iscsi_conn *conn)
|
|||||||
subtask = spdk_iscsi_task_get(conn, task, spdk_iscsi_task_cpl);
|
subtask = spdk_iscsi_task_get(conn, task, spdk_iscsi_task_cpl);
|
||||||
assert(subtask != NULL);
|
assert(subtask != NULL);
|
||||||
subtask->scsi.offset = task->current_datain_offset;
|
subtask->scsi.offset = task->current_datain_offset;
|
||||||
subtask->scsi.length = DMIN32(SPDK_BDEV_LARGE_BUF_MAX_SIZE, remaining_size);
|
|
||||||
spdk_scsi_task_set_data(&subtask->scsi, NULL, 0);
|
spdk_scsi_task_set_data(&subtask->scsi, NULL, 0);
|
||||||
task->current_datain_offset += subtask->scsi.length;
|
|
||||||
conn->data_in_cnt++;
|
conn->data_in_cnt++;
|
||||||
|
|
||||||
if (spdk_scsi_dev_get_lun(conn->dev, task->lun_id) == NULL) {
|
if (spdk_scsi_dev_get_lun(conn->dev, task->lun_id) == NULL) {
|
||||||
/* Remove the primary task from the list if this is the last subtask */
|
/* Stop submitting split read I/Os for remaining data. */
|
||||||
if (task->current_datain_offset == task->scsi.transfer_len) {
|
TAILQ_REMOVE(&conn->queued_datain_tasks, task, link);
|
||||||
TAILQ_REMOVE(&conn->queued_datain_tasks, task, link);
|
task->current_datain_offset += remaining_size;
|
||||||
}
|
assert(task->current_datain_offset == task->scsi.transfer_len);
|
||||||
subtask->scsi.transfer_len = subtask->scsi.length;
|
subtask->scsi.transfer_len = remaining_size;
|
||||||
spdk_scsi_task_process_null_lun(&subtask->scsi);
|
spdk_scsi_task_process_null_lun(&subtask->scsi);
|
||||||
spdk_iscsi_task_cpl(&subtask->scsi);
|
spdk_iscsi_task_cpl(&subtask->scsi);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
subtask->scsi.length = DMIN32(SPDK_BDEV_LARGE_BUF_MAX_SIZE, remaining_size);
|
||||||
|
task->current_datain_offset += subtask->scsi.length;
|
||||||
iscsi_queue_task(conn, subtask);
|
iscsi_queue_task(conn, subtask);
|
||||||
}
|
}
|
||||||
if (task->current_datain_offset == task->scsi.transfer_len) {
|
if (task->current_datain_offset == task->scsi.transfer_len) {
|
||||||
@ -3302,25 +3288,21 @@ int spdk_iscsi_conn_handle_queued_datain_tasks(struct spdk_iscsi_conn *conn)
|
|||||||
static int
|
static int
|
||||||
iscsi_pdu_payload_op_scsi_read(struct spdk_iscsi_conn *conn, struct spdk_iscsi_task *task)
|
iscsi_pdu_payload_op_scsi_read(struct spdk_iscsi_conn *conn, struct spdk_iscsi_task *task)
|
||||||
{
|
{
|
||||||
int32_t remaining_size;
|
if (task->scsi.transfer_len <= SPDK_BDEV_LARGE_BUF_MAX_SIZE) {
|
||||||
|
task->parent = NULL;
|
||||||
|
task->scsi.offset = 0;
|
||||||
|
task->scsi.length = DMIN32(SPDK_BDEV_LARGE_BUF_MAX_SIZE, task->scsi.transfer_len);
|
||||||
|
spdk_scsi_task_set_data(&task->scsi, NULL, 0);
|
||||||
|
|
||||||
TAILQ_INIT(&task->subtask_list);
|
|
||||||
task->parent = NULL;
|
|
||||||
task->scsi.offset = 0;
|
|
||||||
task->scsi.length = DMIN32(SPDK_BDEV_LARGE_BUF_MAX_SIZE, task->scsi.transfer_len);
|
|
||||||
spdk_scsi_task_set_data(&task->scsi, NULL, 0);
|
|
||||||
|
|
||||||
remaining_size = task->scsi.transfer_len - task->scsi.length;
|
|
||||||
task->current_datain_offset = 0;
|
|
||||||
|
|
||||||
if (remaining_size == 0) {
|
|
||||||
iscsi_queue_task(conn, task);
|
iscsi_queue_task(conn, task);
|
||||||
return 0;
|
return 0;
|
||||||
|
} else {
|
||||||
|
TAILQ_INIT(&task->subtask_list);
|
||||||
|
task->current_datain_offset = 0;
|
||||||
|
TAILQ_INSERT_TAIL(&conn->queued_datain_tasks, task, link);
|
||||||
|
|
||||||
|
return spdk_iscsi_conn_handle_queued_datain_tasks(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
TAILQ_INSERT_TAIL(&conn->queued_datain_tasks, task, link);
|
|
||||||
|
|
||||||
return spdk_iscsi_conn_handle_queued_datain_tasks(conn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -3613,15 +3595,6 @@ _iscsi_conn_abort_queued_datain_task(struct spdk_iscsi_conn *conn,
|
|||||||
|
|
||||||
while (conn->data_in_cnt < MAX_LARGE_DATAIN_PER_CONNECTION) {
|
while (conn->data_in_cnt < MAX_LARGE_DATAIN_PER_CONNECTION) {
|
||||||
assert(task->current_datain_offset <= task->scsi.transfer_len);
|
assert(task->current_datain_offset <= task->scsi.transfer_len);
|
||||||
|
|
||||||
/* If no IO is submitted yet, just abort the primary task. */
|
|
||||||
if (task->current_datain_offset == 0) {
|
|
||||||
TAILQ_REMOVE(&conn->queued_datain_tasks, task, link);
|
|
||||||
spdk_scsi_task_process_abort(&task->scsi);
|
|
||||||
spdk_iscsi_task_cpl(&task->scsi);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If any IO is submitted already, abort all subtasks by repetition. */
|
/* If any IO is submitted already, abort all subtasks by repetition. */
|
||||||
if (task->current_datain_offset < task->scsi.transfer_len) {
|
if (task->current_datain_offset < task->scsi.transfer_len) {
|
||||||
remaining_size = task->scsi.transfer_len - task->current_datain_offset;
|
remaining_size = task->scsi.transfer_len - task->current_datain_offset;
|
||||||
|
@ -34,6 +34,22 @@ spdk_iscsi_task_get(struct spdk_iscsi_conn *conn,
|
|||||||
if (!task) {
|
if (!task) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task->conn = conn;
|
||||||
|
task->scsi.cpl_fn = cpl_fn;
|
||||||
|
if (parent) {
|
||||||
|
parent->scsi.ref++;
|
||||||
|
task->parent = parent;
|
||||||
|
task->tag = parent->tag;
|
||||||
|
task->lun_id = parent->lun_id;
|
||||||
|
task->scsi.dxfer_dir = parent->scsi.dxfer_dir;
|
||||||
|
task->scsi.transfer_len = parent->scsi.transfer_len;
|
||||||
|
task->scsi.lun = parent->scsi.lun;
|
||||||
|
task->scsi.cdb = parent->scsi.cdb;
|
||||||
|
task->scsi.target_port = parent->scsi.target_port;
|
||||||
|
task->scsi.initiator_port = parent->scsi.initiator_port;
|
||||||
|
}
|
||||||
|
|
||||||
task->scsi.iovs = &task->scsi.iov;
|
task->scsi.iovs = &task->scsi.iov;
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
@ -141,6 +157,11 @@ spdk_iscsi_task_cpl(struct spdk_scsi_task *scsi_task)
|
|||||||
|
|
||||||
if (scsi_task != NULL) {
|
if (scsi_task != NULL) {
|
||||||
iscsi_task = spdk_iscsi_task_from_scsi_task(scsi_task);
|
iscsi_task = spdk_iscsi_task_from_scsi_task(scsi_task);
|
||||||
|
if (iscsi_task->parent && (iscsi_task->scsi.dxfer_dir == SPDK_SCSI_DIR_FROM_DEV)) {
|
||||||
|
assert(iscsi_task->conn->data_in_cnt > 0);
|
||||||
|
iscsi_task->conn->data_in_cnt--;
|
||||||
|
}
|
||||||
|
|
||||||
free(iscsi_task);
|
free(iscsi_task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,49 +197,27 @@ ut_conn_task_get(struct spdk_iscsi_task *parent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ut_conn_create_read_tasks(int transfer_len)
|
ut_conn_create_read_tasks(struct spdk_iscsi_task *primary)
|
||||||
{
|
{
|
||||||
struct spdk_iscsi_task *task, *subtask;
|
struct spdk_iscsi_task *subtask;
|
||||||
int32_t remaining_size = 0;
|
int32_t remaining_size = 0;
|
||||||
|
|
||||||
task = ut_conn_task_get(NULL);
|
|
||||||
|
|
||||||
TAILQ_INIT(&task->subtask_list);
|
|
||||||
task->scsi.transfer_len = transfer_len;
|
|
||||||
task->scsi.offset = 0;
|
|
||||||
task->scsi.length = DMIN32(SPDK_BDEV_LARGE_BUF_MAX_SIZE, task->scsi.transfer_len);
|
|
||||||
task->scsi.status = SPDK_SCSI_STATUS_GOOD;
|
|
||||||
|
|
||||||
remaining_size = task->scsi.transfer_len - task->scsi.length;
|
|
||||||
task->current_datain_offset = 0;
|
|
||||||
|
|
||||||
if (remaining_size == 0) {
|
|
||||||
TAILQ_INSERT_TAIL(&g_ut_read_tasks, task, link);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (task->current_datain_offset == 0) {
|
if (primary->current_datain_offset < primary->scsi.transfer_len) {
|
||||||
task->current_datain_offset = task->scsi.length;
|
remaining_size = primary->scsi.transfer_len - primary->current_datain_offset;
|
||||||
TAILQ_INSERT_TAIL(&g_ut_read_tasks, task, link);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (task->current_datain_offset < task->scsi.transfer_len) {
|
subtask = ut_conn_task_get(primary);
|
||||||
remaining_size = task->scsi.transfer_len - task->current_datain_offset;
|
|
||||||
|
|
||||||
subtask = ut_conn_task_get(task);
|
subtask->scsi.offset = primary->current_datain_offset;
|
||||||
|
|
||||||
subtask->scsi.offset = task->current_datain_offset;
|
|
||||||
subtask->scsi.length = DMIN32(SPDK_BDEV_LARGE_BUF_MAX_SIZE, remaining_size);
|
subtask->scsi.length = DMIN32(SPDK_BDEV_LARGE_BUF_MAX_SIZE, remaining_size);
|
||||||
subtask->scsi.status = SPDK_SCSI_STATUS_GOOD;
|
subtask->scsi.status = SPDK_SCSI_STATUS_GOOD;
|
||||||
|
|
||||||
task->current_datain_offset += subtask->scsi.length;
|
primary->current_datain_offset += subtask->scsi.length;
|
||||||
|
|
||||||
TAILQ_INSERT_TAIL(&g_ut_read_tasks, subtask, link);
|
TAILQ_INSERT_TAIL(&g_ut_read_tasks, subtask, link);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (task->current_datain_offset == task->scsi.transfer_len) {
|
if (primary->current_datain_offset == primary->scsi.transfer_len) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -248,51 +226,55 @@ ut_conn_create_read_tasks(int transfer_len)
|
|||||||
static void
|
static void
|
||||||
read_task_split_in_order_case(void)
|
read_task_split_in_order_case(void)
|
||||||
{
|
{
|
||||||
struct spdk_iscsi_task *primary, *task, *tmp;
|
struct spdk_iscsi_task primary = {};
|
||||||
|
struct spdk_iscsi_task *task, *tmp;
|
||||||
|
|
||||||
ut_conn_create_read_tasks(SPDK_BDEV_LARGE_BUF_MAX_SIZE * 8);
|
primary.scsi.transfer_len = SPDK_BDEV_LARGE_BUF_MAX_SIZE * 8;
|
||||||
|
TAILQ_INIT(&primary.subtask_list);
|
||||||
|
primary.current_datain_offset = 0;
|
||||||
|
primary.bytes_completed = 0;
|
||||||
|
|
||||||
|
ut_conn_create_read_tasks(&primary);
|
||||||
|
SPDK_CU_ASSERT_FATAL(!TAILQ_EMPTY(&g_ut_read_tasks));
|
||||||
|
|
||||||
TAILQ_FOREACH(task, &g_ut_read_tasks, link) {
|
TAILQ_FOREACH(task, &g_ut_read_tasks, link) {
|
||||||
primary = spdk_iscsi_task_get_primary(task);
|
CU_ASSERT(&primary == spdk_iscsi_task_get_primary(task));
|
||||||
process_read_task_completion(NULL, task, primary);
|
process_read_task_completion(NULL, task, &primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
primary = TAILQ_FIRST(&g_ut_read_tasks);
|
CU_ASSERT(primary.bytes_completed == primary.scsi.transfer_len);
|
||||||
SPDK_CU_ASSERT_FATAL(primary != NULL);
|
|
||||||
|
|
||||||
CU_ASSERT(primary->bytes_completed == primary->scsi.transfer_len);
|
|
||||||
|
|
||||||
TAILQ_FOREACH_SAFE(task, &g_ut_read_tasks, link, tmp) {
|
TAILQ_FOREACH_SAFE(task, &g_ut_read_tasks, link, tmp) {
|
||||||
TAILQ_REMOVE(&g_ut_read_tasks, task, link);
|
TAILQ_REMOVE(&g_ut_read_tasks, task, link);
|
||||||
free(task);
|
free(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
CU_ASSERT(TAILQ_EMPTY(&g_ut_read_tasks));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
read_task_split_reverse_order_case(void)
|
read_task_split_reverse_order_case(void)
|
||||||
{
|
{
|
||||||
struct spdk_iscsi_task *primary, *task, *tmp;
|
struct spdk_iscsi_task primary = {};
|
||||||
|
struct spdk_iscsi_task *task, *tmp;
|
||||||
|
|
||||||
ut_conn_create_read_tasks(SPDK_BDEV_LARGE_BUF_MAX_SIZE * 8);
|
primary.scsi.transfer_len = SPDK_BDEV_LARGE_BUF_MAX_SIZE * 8;
|
||||||
|
TAILQ_INIT(&primary.subtask_list);
|
||||||
|
primary.current_datain_offset = 0;
|
||||||
|
primary.bytes_completed = 0;
|
||||||
|
|
||||||
|
ut_conn_create_read_tasks(&primary);
|
||||||
|
SPDK_CU_ASSERT_FATAL(!TAILQ_EMPTY(&g_ut_read_tasks));
|
||||||
|
|
||||||
TAILQ_FOREACH_REVERSE(task, &g_ut_read_tasks, read_tasks_head, link) {
|
TAILQ_FOREACH_REVERSE(task, &g_ut_read_tasks, read_tasks_head, link) {
|
||||||
primary = spdk_iscsi_task_get_primary(task);
|
CU_ASSERT(&primary == spdk_iscsi_task_get_primary(task));
|
||||||
process_read_task_completion(NULL, task, primary);
|
process_read_task_completion(NULL, task, &primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
primary = TAILQ_FIRST(&g_ut_read_tasks);
|
CU_ASSERT(primary.bytes_completed == primary.scsi.transfer_len);
|
||||||
SPDK_CU_ASSERT_FATAL(primary != NULL);
|
|
||||||
|
|
||||||
CU_ASSERT(primary->bytes_completed == primary->scsi.transfer_len);
|
|
||||||
|
|
||||||
TAILQ_FOREACH_SAFE(task, &g_ut_read_tasks, link, tmp) {
|
TAILQ_FOREACH_SAFE(task, &g_ut_read_tasks, link, tmp) {
|
||||||
TAILQ_REMOVE(&g_ut_read_tasks, task, link);
|
TAILQ_REMOVE(&g_ut_read_tasks, task, link);
|
||||||
free(task);
|
free(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
CU_ASSERT(TAILQ_EMPTY(&g_ut_read_tasks));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -301,38 +283,37 @@ propagate_scsi_error_status_for_split_read_tasks(void)
|
|||||||
struct spdk_iscsi_task primary, task1, task2, task3, task4, task5, task6;
|
struct spdk_iscsi_task primary, task1, task2, task3, task4, task5, task6;
|
||||||
|
|
||||||
memset(&primary, 0, sizeof(struct spdk_iscsi_task));
|
memset(&primary, 0, sizeof(struct spdk_iscsi_task));
|
||||||
primary.scsi.length = 512;
|
primary.scsi.transfer_len = 512 * 6;
|
||||||
primary.scsi.status = SPDK_SCSI_STATUS_GOOD;
|
|
||||||
primary.rsp_scsi_status = SPDK_SCSI_STATUS_GOOD;
|
primary.rsp_scsi_status = SPDK_SCSI_STATUS_GOOD;
|
||||||
TAILQ_INIT(&primary.subtask_list);
|
TAILQ_INIT(&primary.subtask_list);
|
||||||
|
|
||||||
memset(&task1, 0, sizeof(struct spdk_iscsi_task));
|
memset(&task1, 0, sizeof(struct spdk_iscsi_task));
|
||||||
task1.scsi.offset = 512;
|
task1.scsi.offset = 0;
|
||||||
task1.scsi.length = 512;
|
task1.scsi.length = 512;
|
||||||
task1.scsi.status = SPDK_SCSI_STATUS_GOOD;
|
task1.scsi.status = SPDK_SCSI_STATUS_GOOD;
|
||||||
|
|
||||||
memset(&task2, 0, sizeof(struct spdk_iscsi_task));
|
memset(&task2, 0, sizeof(struct spdk_iscsi_task));
|
||||||
task2.scsi.offset = 512 * 2;
|
task2.scsi.offset = 512;
|
||||||
task2.scsi.length = 512;
|
task2.scsi.length = 512;
|
||||||
task2.scsi.status = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
task2.scsi.status = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||||
|
|
||||||
memset(&task3, 0, sizeof(struct spdk_iscsi_task));
|
memset(&task3, 0, sizeof(struct spdk_iscsi_task));
|
||||||
task3.scsi.offset = 512 * 3;
|
task3.scsi.offset = 512 * 2;
|
||||||
task3.scsi.length = 512;
|
task3.scsi.length = 512;
|
||||||
task3.scsi.status = SPDK_SCSI_STATUS_GOOD;
|
task3.scsi.status = SPDK_SCSI_STATUS_GOOD;
|
||||||
|
|
||||||
memset(&task4, 0, sizeof(struct spdk_iscsi_task));
|
memset(&task4, 0, sizeof(struct spdk_iscsi_task));
|
||||||
task4.scsi.offset = 512 * 4;
|
task4.scsi.offset = 512 * 3;
|
||||||
task4.scsi.length = 512;
|
task4.scsi.length = 512;
|
||||||
task4.scsi.status = SPDK_SCSI_STATUS_GOOD;
|
task4.scsi.status = SPDK_SCSI_STATUS_GOOD;
|
||||||
|
|
||||||
memset(&task5, 0, sizeof(struct spdk_iscsi_task));
|
memset(&task5, 0, sizeof(struct spdk_iscsi_task));
|
||||||
task5.scsi.offset = 512 * 5;
|
task5.scsi.offset = 512 * 4;
|
||||||
task5.scsi.length = 512;
|
task5.scsi.length = 512;
|
||||||
task5.scsi.status = SPDK_SCSI_STATUS_GOOD;
|
task5.scsi.status = SPDK_SCSI_STATUS_GOOD;
|
||||||
|
|
||||||
memset(&task6, 0, sizeof(struct spdk_iscsi_task));
|
memset(&task6, 0, sizeof(struct spdk_iscsi_task));
|
||||||
task6.scsi.offset = 512 * 6;
|
task6.scsi.offset = 512 * 5;
|
||||||
task6.scsi.length = 512;
|
task6.scsi.length = 512;
|
||||||
task6.scsi.status = SPDK_SCSI_STATUS_GOOD;
|
task6.scsi.status = SPDK_SCSI_STATUS_GOOD;
|
||||||
|
|
||||||
@ -344,17 +325,17 @@ propagate_scsi_error_status_for_split_read_tasks(void)
|
|||||||
process_read_task_completion(NULL, &task3, &primary);
|
process_read_task_completion(NULL, &task3, &primary);
|
||||||
process_read_task_completion(NULL, &task2, &primary);
|
process_read_task_completion(NULL, &task2, &primary);
|
||||||
process_read_task_completion(NULL, &task1, &primary);
|
process_read_task_completion(NULL, &task1, &primary);
|
||||||
process_read_task_completion(NULL, &primary, &primary);
|
|
||||||
process_read_task_completion(NULL, &task5, &primary);
|
process_read_task_completion(NULL, &task5, &primary);
|
||||||
process_read_task_completion(NULL, &task6, &primary);
|
process_read_task_completion(NULL, &task6, &primary);
|
||||||
|
|
||||||
CU_ASSERT(primary.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
|
CU_ASSERT(primary.rsp_scsi_status == SPDK_SCSI_STATUS_CHECK_CONDITION);
|
||||||
CU_ASSERT(task1.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
|
CU_ASSERT(task1.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
|
||||||
CU_ASSERT(task2.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
|
CU_ASSERT(task2.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
|
||||||
CU_ASSERT(task3.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
|
CU_ASSERT(task3.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
|
||||||
CU_ASSERT(task4.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
|
CU_ASSERT(task4.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
|
||||||
CU_ASSERT(task5.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
|
CU_ASSERT(task5.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
|
||||||
CU_ASSERT(task6.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
|
CU_ASSERT(task6.scsi.status == SPDK_SCSI_STATUS_CHECK_CONDITION);
|
||||||
|
CU_ASSERT(primary.bytes_completed == primary.scsi.transfer_len);
|
||||||
CU_ASSERT(TAILQ_EMPTY(&primary.subtask_list));
|
CU_ASSERT(TAILQ_EMPTY(&primary.subtask_list));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1104,73 +1104,79 @@ clear_all_transfer_tasks_test(void)
|
|||||||
static void
|
static void
|
||||||
abort_queued_datain_task_test(void)
|
abort_queued_datain_task_test(void)
|
||||||
{
|
{
|
||||||
struct spdk_iscsi_conn conn;
|
struct spdk_iscsi_conn conn = {};
|
||||||
struct spdk_iscsi_task *task, *task2, *task3;
|
struct spdk_iscsi_task *task, *task2, *task3;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
TAILQ_INIT(&conn.queued_datain_tasks);
|
TAILQ_INIT(&conn.queued_datain_tasks);
|
||||||
|
|
||||||
|
/* Case1: Queue one task, and this task is not executed */
|
||||||
task = spdk_iscsi_task_get(&conn, NULL, NULL);
|
task = spdk_iscsi_task_get(&conn, NULL, NULL);
|
||||||
SPDK_CU_ASSERT_FATAL(task != NULL);
|
SPDK_CU_ASSERT_FATAL(task != NULL);
|
||||||
TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, task, link);
|
task->scsi.dxfer_dir = SPDK_SCSI_DIR_FROM_DEV;
|
||||||
|
|
||||||
/* Slot of data in tasks are full */
|
/* No slots for sub read tasks */
|
||||||
conn.data_in_cnt = MAX_LARGE_DATAIN_PER_CONNECTION;
|
conn.data_in_cnt = MAX_LARGE_DATAIN_PER_CONNECTION;
|
||||||
|
task->scsi.transfer_len = SPDK_BDEV_LARGE_BUF_MAX_SIZE * 3;
|
||||||
|
task->scsi.offset = 0;
|
||||||
|
TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, task, link);
|
||||||
|
|
||||||
rc = _iscsi_conn_abort_queued_datain_task(&conn, task);
|
rc = _iscsi_conn_abort_queued_datain_task(&conn, task);
|
||||||
CU_ASSERT(rc != 0);
|
CU_ASSERT(rc != 0);
|
||||||
|
CU_ASSERT(!TAILQ_EMPTY(&conn.queued_datain_tasks));
|
||||||
|
assert(conn.data_in_cnt == MAX_LARGE_DATAIN_PER_CONNECTION);
|
||||||
|
|
||||||
/* Only one slot remains and no subtasks are submitted yet. */
|
/* havs slots for sub read tasks */
|
||||||
conn.data_in_cnt--;
|
conn.data_in_cnt = 0;
|
||||||
task->current_datain_offset = 0;
|
|
||||||
|
|
||||||
rc = _iscsi_conn_abort_queued_datain_task(&conn, task);
|
rc = _iscsi_conn_abort_queued_datain_task(&conn, task);
|
||||||
CU_ASSERT(rc == 0);
|
CU_ASSERT(rc == 0);
|
||||||
CU_ASSERT(TAILQ_EMPTY(&conn.queued_datain_tasks));
|
CU_ASSERT(TAILQ_EMPTY(&conn.queued_datain_tasks));
|
||||||
|
assert(conn.data_in_cnt == 0);
|
||||||
|
|
||||||
task = spdk_iscsi_task_get(&conn, NULL, NULL);
|
/* Case2: Queue one task, and this task is partially executed,
|
||||||
SPDK_CU_ASSERT_FATAL(task != NULL);
|
* and the slot of sub read tasks are full
|
||||||
TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, task, link);
|
*/
|
||||||
|
conn.data_in_cnt = MAX_LARGE_DATAIN_PER_CONNECTION;
|
||||||
/* Only one slot remains and a subtask is submitted. */
|
|
||||||
task->scsi.transfer_len = SPDK_BDEV_LARGE_BUF_MAX_SIZE * 3;
|
task->scsi.transfer_len = SPDK_BDEV_LARGE_BUF_MAX_SIZE * 3;
|
||||||
task->current_datain_offset = SPDK_BDEV_LARGE_BUF_MAX_SIZE;
|
task->current_datain_offset = SPDK_BDEV_LARGE_BUF_MAX_SIZE;
|
||||||
|
TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, task, link);
|
||||||
|
|
||||||
rc = _iscsi_conn_abort_queued_datain_task(&conn, task);
|
rc = _iscsi_conn_abort_queued_datain_task(&conn, task);
|
||||||
CU_ASSERT(rc != 0);
|
CU_ASSERT(rc != 0);
|
||||||
CU_ASSERT(task->current_datain_offset == SPDK_BDEV_LARGE_BUF_MAX_SIZE * 2);
|
|
||||||
CU_ASSERT(conn.data_in_cnt == MAX_LARGE_DATAIN_PER_CONNECTION);
|
|
||||||
|
|
||||||
/* Additional one slot becomes vacant. */
|
|
||||||
conn.data_in_cnt--;
|
|
||||||
|
|
||||||
|
/* Case3: Queue one task, and this task is partially executed,
|
||||||
|
* and the slot of sub read tasks is not full.
|
||||||
|
*/
|
||||||
|
conn.data_in_cnt = MAX_LARGE_DATAIN_PER_CONNECTION - 2;
|
||||||
rc = _iscsi_conn_abort_queued_datain_task(&conn, task);
|
rc = _iscsi_conn_abort_queued_datain_task(&conn, task);
|
||||||
CU_ASSERT(rc == 0);
|
CU_ASSERT(rc == 0);
|
||||||
|
assert(conn.data_in_cnt == MAX_LARGE_DATAIN_PER_CONNECTION - 2);
|
||||||
CU_ASSERT(TAILQ_EMPTY(&conn.queued_datain_tasks));
|
CU_ASSERT(TAILQ_EMPTY(&conn.queued_datain_tasks));
|
||||||
|
|
||||||
spdk_iscsi_task_cpl(&task->scsi);
|
/* Case4: Queue three tasks and abort each task sequentially */
|
||||||
|
conn.data_in_cnt = 0;
|
||||||
|
|
||||||
/* Queue three data in tasks and abort each task sequentially */
|
|
||||||
task = spdk_iscsi_task_get(&conn, NULL, NULL);
|
|
||||||
SPDK_CU_ASSERT_FATAL(task != NULL);
|
|
||||||
task->tag = 1;
|
task->tag = 1;
|
||||||
|
task->scsi.transfer_len = SPDK_BDEV_LARGE_BUF_MAX_SIZE * 3;
|
||||||
task->current_datain_offset = 0;
|
task->current_datain_offset = 0;
|
||||||
TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, task, link);
|
TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, task, link);
|
||||||
|
|
||||||
task2 = spdk_iscsi_task_get(&conn, NULL, NULL);
|
task2 = spdk_iscsi_task_get(&conn, NULL, NULL);
|
||||||
SPDK_CU_ASSERT_FATAL(task2 != NULL);
|
SPDK_CU_ASSERT_FATAL(task2 != NULL);
|
||||||
task2->tag = 2;
|
task2->tag = 2;
|
||||||
task2->current_datain_offset = 0;
|
task2->scsi.dxfer_dir = SPDK_SCSI_DIR_FROM_DEV;
|
||||||
|
task2->scsi.transfer_len = SPDK_BDEV_LARGE_BUF_MAX_SIZE * 4;
|
||||||
|
task2->current_datain_offset = SPDK_BDEV_LARGE_BUF_MAX_SIZE;
|
||||||
TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, task2, link);
|
TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, task2, link);
|
||||||
|
|
||||||
task3 = spdk_iscsi_task_get(&conn, NULL, NULL);
|
task3 = spdk_iscsi_task_get(&conn, NULL, NULL);
|
||||||
SPDK_CU_ASSERT_FATAL(task3 != NULL);
|
SPDK_CU_ASSERT_FATAL(task3 != NULL);
|
||||||
task3->tag = 3;
|
task3->tag = 3;
|
||||||
task3->current_datain_offset = 0;
|
task3->scsi.dxfer_dir = SPDK_SCSI_DIR_FROM_DEV;
|
||||||
|
task3->scsi.transfer_len = SPDK_BDEV_LARGE_BUF_MAX_SIZE * 5;
|
||||||
|
task3->current_datain_offset = SPDK_BDEV_LARGE_BUF_MAX_SIZE * 2;
|
||||||
TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, task3, link);
|
TAILQ_INSERT_TAIL(&conn.queued_datain_tasks, task3, link);
|
||||||
|
|
||||||
conn.data_in_cnt--;
|
|
||||||
|
|
||||||
rc = iscsi_conn_abort_queued_datain_task(&conn, 1);
|
rc = iscsi_conn_abort_queued_datain_task(&conn, 1);
|
||||||
CU_ASSERT(rc == 0);
|
CU_ASSERT(rc == 0);
|
||||||
|
|
||||||
@ -1181,6 +1187,11 @@ abort_queued_datain_task_test(void)
|
|||||||
CU_ASSERT(rc == 0);
|
CU_ASSERT(rc == 0);
|
||||||
|
|
||||||
CU_ASSERT(TAILQ_EMPTY(&conn.queued_datain_tasks));
|
CU_ASSERT(TAILQ_EMPTY(&conn.queued_datain_tasks));
|
||||||
|
assert(conn.data_in_cnt == 0);
|
||||||
|
|
||||||
|
spdk_iscsi_task_cpl(&task->scsi);
|
||||||
|
spdk_iscsi_task_cpl(&task2->scsi);
|
||||||
|
spdk_iscsi_task_cpl(&task3->scsi);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@ -1306,6 +1317,7 @@ abort_queued_datain_tasks_test(void)
|
|||||||
CU_ASSERT(datain_task_is_queued(&conn, task4));
|
CU_ASSERT(datain_task_is_queued(&conn, task4));
|
||||||
CU_ASSERT(datain_task_is_queued(&conn, task5));
|
CU_ASSERT(datain_task_is_queued(&conn, task5));
|
||||||
CU_ASSERT(datain_task_is_queued(&conn, task6));
|
CU_ASSERT(datain_task_is_queued(&conn, task6));
|
||||||
|
spdk_iscsi_task_cpl(&task1->scsi);
|
||||||
|
|
||||||
rc = iscsi_conn_abort_queued_datain_tasks(&conn, &lun2, mgmt_pdu2);
|
rc = iscsi_conn_abort_queued_datain_tasks(&conn, &lun2, mgmt_pdu2);
|
||||||
CU_ASSERT(rc == 0);
|
CU_ASSERT(rc == 0);
|
||||||
@ -1314,6 +1326,8 @@ abort_queued_datain_tasks_test(void)
|
|||||||
CU_ASSERT(!datain_task_is_queued(&conn, task4));
|
CU_ASSERT(!datain_task_is_queued(&conn, task4));
|
||||||
CU_ASSERT(datain_task_is_queued(&conn, task5));
|
CU_ASSERT(datain_task_is_queued(&conn, task5));
|
||||||
CU_ASSERT(datain_task_is_queued(&conn, task6));
|
CU_ASSERT(datain_task_is_queued(&conn, task6));
|
||||||
|
spdk_iscsi_task_cpl(&task2->scsi);
|
||||||
|
spdk_iscsi_task_cpl(&task4->scsi);
|
||||||
|
|
||||||
TAILQ_FOREACH_SAFE(task, &conn.queued_datain_tasks, link, tmp) {
|
TAILQ_FOREACH_SAFE(task, &conn.queued_datain_tasks, link, tmp) {
|
||||||
TAILQ_REMOVE(&conn.queued_datain_tasks, task, link);
|
TAILQ_REMOVE(&conn.queued_datain_tasks, task, link);
|
||||||
|
Loading…
Reference in New Issue
Block a user