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 <shuhei.matsumoto.xt@hitachi.com>
Change-Id: I78acaf054360254dffbdc282c2d0d8bb5868e5d4
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/473783
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Shuhei Matsumoto 2019-11-10 07:25:19 +09:00 committed by Tomasz Zawadzki
parent 0326031ecd
commit e4cf639f7d

View File

@ -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);