Commit e4cf639f authored by Shuhei Matsumoto's avatar Shuhei Matsumoto Committed by Tomasz Zawadzki
Browse files

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: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Change-Id: I78acaf054360254dffbdc282c2d0d8bb5868e5d4
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/473783


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent 0326031e
Loading
Loading
Loading
Loading
+12 −2
Original line number Diff line number Diff line
@@ -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);