lib/iscsi: Fix iscsi_del_transfer_task deletes from both array and tailq
Previously iscsi_del_transfer_task() dequeued the task only from the array conn->outstanding_r2t_tasks[]. process_non_read_task_completion() had dequeued the task from the tailq conn->active_r2t_tasks then. However abort_transfer_task_in_task_mgmt_resp had not dequeued the task from the tailq conn->active_r2t_tasks then. This was an apparent bug, and is fixed here. Update unit tests accordingly. Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Change-Id: I93f02b2fb670dcee4c32d61c264e3ad5b4f9f43e Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/3108 Community-CI: Mellanox Build Bot Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
parent
41f59559e1
commit
d5f3f48b60
@ -1226,14 +1226,11 @@ process_non_read_task_completion(struct spdk_iscsi_conn *conn,
|
|||||||
* iscsi_clear_all_transfer_task() in iscsi.c.)
|
* iscsi_clear_all_transfer_task() in iscsi.c.)
|
||||||
*/
|
*/
|
||||||
if (primary->is_r2t_active) {
|
if (primary->is_r2t_active) {
|
||||||
iscsi_del_transfer_task(conn, primary->tag);
|
|
||||||
if (primary->rsp_scsi_status != SPDK_SCSI_STATUS_GOOD) {
|
if (primary->rsp_scsi_status != SPDK_SCSI_STATUS_GOOD) {
|
||||||
iscsi_task_copy_from_rsp_scsi_status(&primary->scsi, primary);
|
iscsi_task_copy_from_rsp_scsi_status(&primary->scsi, primary);
|
||||||
}
|
}
|
||||||
iscsi_task_response(conn, primary);
|
iscsi_task_response(conn, primary);
|
||||||
TAILQ_REMOVE(&conn->active_r2t_tasks, primary, link);
|
iscsi_del_transfer_task(conn, primary->tag);
|
||||||
primary->is_r2t_active = false;
|
|
||||||
iscsi_task_put(primary);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
iscsi_task_response(conn, task);
|
iscsi_task_response(conn, task);
|
||||||
|
@ -2827,6 +2827,12 @@ iscsi_del_transfer_task(struct spdk_iscsi_conn *conn, uint32_t task_tag)
|
|||||||
conn->outstanding_r2t_tasks[i] = conn->outstanding_r2t_tasks[i + 1];
|
conn->outstanding_r2t_tasks[i] = conn->outstanding_r2t_tasks[i + 1];
|
||||||
}
|
}
|
||||||
conn->outstanding_r2t_tasks[conn->pending_r2t] = NULL;
|
conn->outstanding_r2t_tasks[conn->pending_r2t] = NULL;
|
||||||
|
|
||||||
|
assert(task->is_r2t_active == true);
|
||||||
|
TAILQ_REMOVE(&conn->active_r2t_tasks, task, link);
|
||||||
|
task->is_r2t_active = false;
|
||||||
|
iscsi_task_put(task);
|
||||||
|
|
||||||
start_queued_transfer_tasks(conn);
|
start_queued_transfer_tasks(conn);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -209,8 +209,22 @@ DEFINE_STUB_V(iscsi_task_mgmt_response,
|
|||||||
|
|
||||||
DEFINE_STUB_V(iscsi_send_nopin, (struct spdk_iscsi_conn *conn));
|
DEFINE_STUB_V(iscsi_send_nopin, (struct spdk_iscsi_conn *conn));
|
||||||
|
|
||||||
DEFINE_STUB(iscsi_del_transfer_task, bool,
|
bool
|
||||||
(struct spdk_iscsi_conn *conn, uint32_t task_tag), true);
|
iscsi_del_transfer_task(struct spdk_iscsi_conn *conn, uint32_t task_tag)
|
||||||
|
{
|
||||||
|
struct spdk_iscsi_task *task;
|
||||||
|
|
||||||
|
task = TAILQ_FIRST(&conn->active_r2t_tasks);
|
||||||
|
if (task == NULL || task->tag != task_tag) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
TAILQ_REMOVE(&conn->active_r2t_tasks, task, link);
|
||||||
|
task->is_r2t_active = false;
|
||||||
|
iscsi_task_put(task);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
DEFINE_STUB(iscsi_handle_incoming_pdus, int, (struct spdk_iscsi_conn *conn), 0);
|
DEFINE_STUB(iscsi_handle_incoming_pdus, int, (struct spdk_iscsi_conn *conn), 0);
|
||||||
|
|
||||||
@ -424,6 +438,7 @@ process_non_read_task_completion_test(void)
|
|||||||
primary.scsi.ref = 1;
|
primary.scsi.ref = 1;
|
||||||
TAILQ_INSERT_TAIL(&conn.active_r2t_tasks, &primary, link);
|
TAILQ_INSERT_TAIL(&conn.active_r2t_tasks, &primary, link);
|
||||||
primary.is_r2t_active = true;
|
primary.is_r2t_active = true;
|
||||||
|
primary.tag = 1;
|
||||||
|
|
||||||
/* First subtask which failed. */
|
/* First subtask which failed. */
|
||||||
task.scsi.length = 4096;
|
task.scsi.length = 4096;
|
||||||
|
@ -779,7 +779,7 @@ del_transfer_task_test(void)
|
|||||||
{
|
{
|
||||||
struct spdk_iscsi_sess sess = {};
|
struct spdk_iscsi_sess sess = {};
|
||||||
struct spdk_iscsi_conn conn = {};
|
struct spdk_iscsi_conn conn = {};
|
||||||
struct spdk_iscsi_task task1 = {}, task2 = {}, task3 = {}, task4 = {}, task5 = {}, *task;
|
struct spdk_iscsi_task *task1, *task2, *task3, *task4, *task5;
|
||||||
struct spdk_iscsi_pdu *pdu1, *pdu2, *pdu3, *pdu4, *pdu5, *pdu;
|
struct spdk_iscsi_pdu *pdu1, *pdu2, *pdu3, *pdu4, *pdu5, *pdu;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
@ -794,83 +794,100 @@ del_transfer_task_test(void)
|
|||||||
SPDK_CU_ASSERT_FATAL(pdu1 != NULL);
|
SPDK_CU_ASSERT_FATAL(pdu1 != NULL);
|
||||||
|
|
||||||
pdu1->data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
|
pdu1->data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
|
||||||
task1.scsi.transfer_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
|
|
||||||
iscsi_task_set_pdu(&task1, pdu1);
|
|
||||||
task1.tag = 11;
|
|
||||||
|
|
||||||
rc = add_transfer_task(&conn, &task1);
|
task1 = iscsi_task_get(&conn, NULL, NULL);
|
||||||
|
SPDK_CU_ASSERT_FATAL(task1 != NULL);
|
||||||
|
|
||||||
|
task1->scsi.transfer_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
|
||||||
|
iscsi_task_set_pdu(task1, pdu1);
|
||||||
|
task1->tag = 11;
|
||||||
|
|
||||||
|
rc = add_transfer_task(&conn, task1);
|
||||||
CU_ASSERT(rc == 0);
|
CU_ASSERT(rc == 0);
|
||||||
|
|
||||||
pdu2 = iscsi_get_pdu(&conn);
|
pdu2 = iscsi_get_pdu(&conn);
|
||||||
SPDK_CU_ASSERT_FATAL(pdu2 != NULL);
|
SPDK_CU_ASSERT_FATAL(pdu2 != NULL);
|
||||||
|
|
||||||
pdu2->data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
|
pdu2->data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
|
||||||
task2.scsi.transfer_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
|
|
||||||
iscsi_task_set_pdu(&task2, pdu2);
|
|
||||||
task2.tag = 12;
|
|
||||||
|
|
||||||
rc = add_transfer_task(&conn, &task2);
|
task2 = iscsi_task_get(&conn, NULL, NULL);
|
||||||
|
SPDK_CU_ASSERT_FATAL(task2 != NULL);
|
||||||
|
|
||||||
|
task2->scsi.transfer_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
|
||||||
|
iscsi_task_set_pdu(task2, pdu2);
|
||||||
|
task2->tag = 12;
|
||||||
|
|
||||||
|
rc = add_transfer_task(&conn, task2);
|
||||||
CU_ASSERT(rc == 0);
|
CU_ASSERT(rc == 0);
|
||||||
|
|
||||||
pdu3 = iscsi_get_pdu(&conn);
|
pdu3 = iscsi_get_pdu(&conn);
|
||||||
SPDK_CU_ASSERT_FATAL(pdu3 != NULL);
|
SPDK_CU_ASSERT_FATAL(pdu3 != NULL);
|
||||||
|
|
||||||
pdu3->data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
|
pdu3->data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
|
||||||
task3.scsi.transfer_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
|
|
||||||
iscsi_task_set_pdu(&task3, pdu3);
|
|
||||||
task3.tag = 13;
|
|
||||||
|
|
||||||
rc = add_transfer_task(&conn, &task3);
|
task3 = iscsi_task_get(&conn, NULL, NULL);
|
||||||
|
SPDK_CU_ASSERT_FATAL(task3 != NULL);
|
||||||
|
|
||||||
|
task3->scsi.transfer_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
|
||||||
|
iscsi_task_set_pdu(task3, pdu3);
|
||||||
|
task3->tag = 13;
|
||||||
|
|
||||||
|
rc = add_transfer_task(&conn, task3);
|
||||||
CU_ASSERT(rc == 0);
|
CU_ASSERT(rc == 0);
|
||||||
|
|
||||||
pdu4 = iscsi_get_pdu(&conn);
|
pdu4 = iscsi_get_pdu(&conn);
|
||||||
SPDK_CU_ASSERT_FATAL(pdu4 != NULL);
|
SPDK_CU_ASSERT_FATAL(pdu4 != NULL);
|
||||||
|
|
||||||
pdu4->data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
|
pdu4->data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
|
||||||
task4.scsi.transfer_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
|
|
||||||
iscsi_task_set_pdu(&task4, pdu4);
|
|
||||||
task4.tag = 14;
|
|
||||||
|
|
||||||
rc = add_transfer_task(&conn, &task4);
|
task4 = iscsi_task_get(&conn, NULL, NULL);
|
||||||
|
SPDK_CU_ASSERT_FATAL(task4 != NULL);
|
||||||
|
|
||||||
|
task4->scsi.transfer_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
|
||||||
|
iscsi_task_set_pdu(task4, pdu4);
|
||||||
|
task4->tag = 14;
|
||||||
|
|
||||||
|
rc = add_transfer_task(&conn, task4);
|
||||||
CU_ASSERT(rc == 0);
|
CU_ASSERT(rc == 0);
|
||||||
|
|
||||||
pdu5 = iscsi_get_pdu(&conn);
|
pdu5 = iscsi_get_pdu(&conn);
|
||||||
SPDK_CU_ASSERT_FATAL(pdu5 != NULL);
|
SPDK_CU_ASSERT_FATAL(pdu5 != NULL);
|
||||||
|
|
||||||
pdu5->data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
|
pdu5->data_segment_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
|
||||||
task5.scsi.transfer_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
|
|
||||||
iscsi_task_set_pdu(&task5, pdu5);
|
|
||||||
task5.tag = 15;
|
|
||||||
|
|
||||||
rc = add_transfer_task(&conn, &task5);
|
task5 = iscsi_task_get(&conn, NULL, NULL);
|
||||||
|
SPDK_CU_ASSERT_FATAL(task5 != NULL);
|
||||||
|
|
||||||
|
task5->scsi.transfer_len = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH;
|
||||||
|
iscsi_task_set_pdu(task5, pdu5);
|
||||||
|
task5->tag = 15;
|
||||||
|
|
||||||
|
rc = add_transfer_task(&conn, task5);
|
||||||
CU_ASSERT(rc == 0);
|
CU_ASSERT(rc == 0);
|
||||||
|
|
||||||
CU_ASSERT(get_transfer_task(&conn, 1) == &task1);
|
CU_ASSERT(get_transfer_task(&conn, 1) == task1);
|
||||||
CU_ASSERT(get_transfer_task(&conn, 5) == NULL);
|
CU_ASSERT(get_transfer_task(&conn, 5) == NULL);
|
||||||
iscsi_del_transfer_task(&conn, 11);
|
iscsi_del_transfer_task(&conn, 11);
|
||||||
CU_ASSERT(get_transfer_task(&conn, 1) == NULL);
|
CU_ASSERT(get_transfer_task(&conn, 1) == NULL);
|
||||||
CU_ASSERT(get_transfer_task(&conn, 5) == &task5);
|
CU_ASSERT(get_transfer_task(&conn, 5) == task5);
|
||||||
|
|
||||||
CU_ASSERT(get_transfer_task(&conn, 2) == &task2);
|
CU_ASSERT(get_transfer_task(&conn, 2) == task2);
|
||||||
iscsi_del_transfer_task(&conn, 12);
|
iscsi_del_transfer_task(&conn, 12);
|
||||||
CU_ASSERT(get_transfer_task(&conn, 2) == NULL);
|
CU_ASSERT(get_transfer_task(&conn, 2) == NULL);
|
||||||
|
|
||||||
CU_ASSERT(get_transfer_task(&conn, 3) == &task3);
|
CU_ASSERT(get_transfer_task(&conn, 3) == task3);
|
||||||
iscsi_del_transfer_task(&conn, 13);
|
iscsi_del_transfer_task(&conn, 13);
|
||||||
CU_ASSERT(get_transfer_task(&conn, 3) == NULL);
|
CU_ASSERT(get_transfer_task(&conn, 3) == NULL);
|
||||||
|
|
||||||
CU_ASSERT(get_transfer_task(&conn, 4) == &task4);
|
CU_ASSERT(get_transfer_task(&conn, 4) == task4);
|
||||||
iscsi_del_transfer_task(&conn, 14);
|
iscsi_del_transfer_task(&conn, 14);
|
||||||
CU_ASSERT(get_transfer_task(&conn, 4) == NULL);
|
CU_ASSERT(get_transfer_task(&conn, 4) == NULL);
|
||||||
|
|
||||||
CU_ASSERT(get_transfer_task(&conn, 5) == &task5);
|
CU_ASSERT(get_transfer_task(&conn, 5) == task5);
|
||||||
iscsi_del_transfer_task(&conn, 15);
|
iscsi_del_transfer_task(&conn, 15);
|
||||||
CU_ASSERT(get_transfer_task(&conn, 5) == NULL);
|
CU_ASSERT(get_transfer_task(&conn, 5) == NULL);
|
||||||
|
|
||||||
while (!TAILQ_EMPTY(&conn.active_r2t_tasks)) {
|
CU_ASSERT(TAILQ_EMPTY(&conn.active_r2t_tasks));
|
||||||
task = TAILQ_FIRST(&conn.active_r2t_tasks);
|
|
||||||
TAILQ_REMOVE(&conn.active_r2t_tasks, task, link);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!TAILQ_EMPTY(&g_write_pdu_list)) {
|
while (!TAILQ_EMPTY(&g_write_pdu_list)) {
|
||||||
pdu = TAILQ_FIRST(&g_write_pdu_list);
|
pdu = TAILQ_FIRST(&g_write_pdu_list);
|
||||||
|
Loading…
Reference in New Issue
Block a user