From e4cf639f7d4ba106e3be81af96009fdf9e98dba5 Mon Sep 17 00:00:00 2001 From: Shuhei Matsumoto Date: Sun, 10 Nov 2019 07:25:19 +0900 Subject: [PATCH] lib/iscsi: Free primary after last subtask done for read I/O For large split read I/O, the primary task have to be freed by the last subtask. However, if LUN is removed in the middle of the split read I/O sequence, the primary task is freed by the not last subtask. This had caused critical system failure by LUN hotplug. This patch fixes that. Signed-off-by: Shuhei Matsumoto Change-Id: I78acaf054360254dffbdc282c2d0d8bb5868e5d4 Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/473783 Tested-by: SPDK CI Jenkins Reviewed-by: Ben Walker Reviewed-by: Jim Harris --- lib/iscsi/conn.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/iscsi/conn.c b/lib/iscsi/conn.c index b3687a608..c72bf857a 100644 --- a/lib/iscsi/conn.c +++ b/lib/iscsi/conn.c @@ -313,21 +313,31 @@ error_return: void spdk_iscsi_conn_free_pdu(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu) { + struct spdk_iscsi_task *primary; + if (pdu->task) { + primary = spdk_iscsi_task_get_primary(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_task_put(primary); } 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) { - spdk_iscsi_task_put(spdk_iscsi_task_get_primary(pdu->task)); + if (spdk_iscsi_task_is_read(primary)) { + if (primary->bytes_completed == primary->scsi.transfer_len) { + /* Free the primary task after the last subtask done */ + spdk_iscsi_task_put(primary); + } + } else { + spdk_iscsi_task_put(primary); + } } } spdk_iscsi_task_put(pdu->task);