iscsi: fix the recursive calling issue.

After I review the function iscsi_conn_flush_pdus_internal,
I think that it may cause recursive function call issue. One of
the recursive calls in iscsi_conn_flush_pdus_internal
is:

spdk_iscsi_conn_free_pdu
spdk_iscsi_conn_handle_queued_datain_tasks
...
spdk_iscsi_task_cpl(&task->scsi);
...
process_read_task_completion
spdk_iscsi_task_response
iscsi_transfer_in
iscsi_send_datain
spdk_iscsi_conn_write_pdu
iscsi_conn_flush_pdus
iscsi_conn_flush_pdus_internal

So we have to create another list to solve this recursive issue
in the while loop. And we face the the similar issue in
NVMe/TCP before. With this patch, we can fix issues caused by
recursive calls.

Fixes #issue 1023

Signed-off-by: Ziye Yang <ziye.yang@intel.com>
Change-Id: I7150b962bfb30e74f53ba1a2a826fb78c73d8ea6
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/472999
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Ziye Yang 2019-11-01 18:41:06 +08:00 committed by Tomasz Zawadzki
parent e3d18b5052
commit fbb59ae25a

View File

@ -1253,6 +1253,7 @@ iscsi_conn_flush_pdus_internal(struct spdk_iscsi_conn *conn)
uint32_t mapped_length = 0;
struct spdk_iscsi_pdu *pdu;
int pdu_length;
TAILQ_HEAD(, spdk_iscsi_pdu) completed_pdus_list;
pdu = TAILQ_FIRST(&conn->write_pdu_list);
@ -1297,6 +1298,7 @@ iscsi_conn_flush_pdus_internal(struct spdk_iscsi_conn *conn)
* partially written, update its writev_offset so that next
* time only the unwritten portion will be sent to writev().
*/
TAILQ_INIT(&completed_pdus_list);
while (bytes > 0) {
pdu_length = iscsi_get_pdu_length(pdu, conn->header_digest,
conn->data_digest);
@ -1305,7 +1307,17 @@ iscsi_conn_flush_pdus_internal(struct spdk_iscsi_conn *conn)
if (bytes >= pdu_length) {
bytes -= pdu_length;
TAILQ_REMOVE(&conn->write_pdu_list, pdu, tailq);
TAILQ_INSERT_TAIL(&completed_pdus_list, pdu, tailq);
pdu = TAILQ_FIRST(&conn->write_pdu_list);
} else {
pdu->writev_offset += bytes;
bytes = 0;
}
}
while (!TAILQ_EMPTY(&completed_pdus_list)) {
pdu = TAILQ_FIRST(&completed_pdus_list);
TAILQ_REMOVE(&completed_pdus_list, pdu, tailq);
if ((conn->full_feature) &&
(conn->sess->ErrorRecoveryLevel >= 1) &&
spdk_iscsi_is_deferred_free_pdu(pdu)) {
@ -1316,12 +1328,6 @@ iscsi_conn_flush_pdus_internal(struct spdk_iscsi_conn *conn)
} else {
spdk_iscsi_conn_free_pdu(conn, pdu);
}
pdu = TAILQ_FIRST(&conn->write_pdu_list);
} else {
pdu->writev_offset += bytes;
bytes = 0;
}
}
return TAILQ_EMPTY(&conn->write_pdu_list) ? 0 : 1;