From 144065f30c682f9228b9a8a891f3f8223d9f2fbf Mon Sep 17 00:00:00 2001 From: Changpeng Liu Date: Wed, 7 Dec 2016 13:02:40 +0800 Subject: [PATCH] iscsi: fix big READ task release process for ERL1 When we enabled the ERL1 configuation, for the DATAIN task release process, we will queue the task to the SNACK list firstly, and then remove the list when got ACK from initiator, but for this part of logic, the reference count of primary task was not released correctly. Change-Id: Ic5959cf644c74f676be0b84c5650292dc426b2d8 Signed-off-by: Changpeng Liu --- lib/iscsi/conn.c | 36 +++++++++++++++++++++--------------- lib/iscsi/conn.h | 2 ++ lib/iscsi/iscsi.c | 5 +---- test/lib/iscsi/pdu/pdu.c | 5 +++++ 4 files changed, 29 insertions(+), 19 deletions(-) diff --git a/lib/iscsi/conn.c b/lib/iscsi/conn.c index 36dfe5fd5..dbf5c6bdc 100644 --- a/lib/iscsi/conn.c +++ b/lib/iscsi/conn.c @@ -413,6 +413,26 @@ error_return: return 0; } +void +spdk_iscsi_conn_free_pdu(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu) +{ + if (pdu->task) { + if (pdu->bhs.opcode == ISCSI_OP_SCSI_DATAIN) { + if (pdu->task->scsi.offset > 0) { + conn->data_in_cnt--; + if (pdu->bhs.flags & ISCSI_DATAIN_STATUS) { + /* Free the primary task after the last subtask done */ + conn->data_in_cnt--; + spdk_iscsi_task_put(spdk_iscsi_task_get_primary(pdu->task)); + } + spdk_iscsi_conn_handle_queued_tasks(conn); + } + } + spdk_iscsi_task_put(pdu->task); + } + spdk_put_pdu(pdu); +} + static int spdk_iscsi_conn_free_tasks(struct spdk_iscsi_conn *conn) { struct spdk_iscsi_pdu *pdu; @@ -1102,21 +1122,7 @@ spdk_iscsi_conn_flush_pdus_internal(struct spdk_iscsi_conn *conn) TAILQ_INSERT_TAIL(&conn->snack_pdu_list, pdu, tailq); } else { - if (pdu->task) { - if (pdu->bhs.opcode == ISCSI_OP_SCSI_DATAIN) { - if (pdu->task->scsi.offset > 0) { - conn->data_in_cnt--; - if (pdu->bhs.flags & ISCSI_DATAIN_STATUS) { - /* Free the primary task after the last subtask done */ - conn->data_in_cnt--; - spdk_iscsi_task_put(spdk_iscsi_task_get_primary(pdu->task)); - } - spdk_iscsi_conn_handle_queued_tasks(conn); - } - } - spdk_iscsi_task_put(pdu->task); - } - spdk_put_pdu(pdu); + spdk_iscsi_conn_free_pdu(conn, pdu); } pdu = TAILQ_FIRST(&conn->write_pdu_list); diff --git a/lib/iscsi/conn.h b/lib/iscsi/conn.h index e4e9ae66e..1d088bf4b 100644 --- a/lib/iscsi/conn.h +++ b/lib/iscsi/conn.h @@ -176,4 +176,6 @@ void spdk_iscsi_set_min_conn_idle_interval(int interval_in_us); int spdk_iscsi_conn_read_data(struct spdk_iscsi_conn *conn, int len, void *buf); +void spdk_iscsi_conn_free_pdu(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu); + #endif /* SPDK_ISCSI_CONN_H */ diff --git a/lib/iscsi/iscsi.c b/lib/iscsi/iscsi.c index d005210bf..36db6134f 100644 --- a/lib/iscsi/iscsi.c +++ b/lib/iscsi/iscsi.c @@ -3992,10 +3992,7 @@ spdk_remove_acked_pdu(struct spdk_iscsi_conn *conn, stat_sn = from_be32(&pdu->bhs.stat_sn); if (SN32_LT(stat_sn, conn->exp_statsn)) { TAILQ_REMOVE(&conn->snack_pdu_list, pdu, tailq); - if (pdu->task) { - spdk_iscsi_task_put(pdu->task); - } - spdk_put_pdu(pdu); + spdk_iscsi_conn_free_pdu(conn, pdu); } } } diff --git a/test/lib/iscsi/pdu/pdu.c b/test/lib/iscsi/pdu/pdu.c index 38112b2fb..446114180 100644 --- a/test/lib/iscsi/pdu/pdu.c +++ b/test/lib/iscsi/pdu/pdu.c @@ -77,6 +77,11 @@ spdk_iscsi_portal_grp_close_all(void) return 0; } +void +spdk_iscsi_conn_free_pdu(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu) +{ +} + static void maxburstlength_test(void) {