lib/iscsi: Check if data comes really after processing logout request

When the PDU receive handler processes the header of the logout request PDU,
conn->is_logged_out is set to true.

However, if conn->is_logged_out is true, conn->pdu_recv_state is set to ERROR
before the PDU receive handler completes processing the logout request PDU.

Then if conn->pdu_recv_state is ERROR, conn->state is set to EXITING
after returning from the PDU receive handler.

Response PDUs are sent asynchronously now and may not be sent even after
returning from the PDU receive handler.

On the other hand, outside the PDU receive handler, the current connection
is closed if conn->state is EXITING.

Hence logout response PDU may not be sent to the initiator.

For the case that the initiator logs out and then reconnects when receiving
asynchronous logout request, missing logout response is critical
because initiator waits until receiving logout request and gets timeout.

This patch moves the check if PDU comes after logout to the place
just after getting a PDU header.

At the new location, data segment of the PDU is not received yet. But
logout request PDU does not have data segment and initiator will not
send additional PDU after sending logout request PDU, and by this patch,
iSCSI target will continue to stop receiving any new PDU after processing
logout request. Furthermore, even if there is any remaining data in the
kernel buffer, the kernel will discard or flush it when closing the socket.

Fixes issue #1571

Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Change-Id: I9554f4d54f3db80bf86abd6bffe81bac8c234531
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/3928
Community-CI: Mellanox Build Bot
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>
Reviewed-by: Ziye Yang <ziye.yang@intel.com>
This commit is contained in:
Shuhei Matsumoto 2020-08-25 21:51:47 +09:00 committed by Tomasz Zawadzki
parent 59ad0a04fa
commit 438fa38e4a

View File

@ -4582,6 +4582,17 @@ iscsi_read_pdu(struct spdk_iscsi_conn *conn)
}
}
/* conn->is_logged_out must be checked after completing to process
* logout request, i.e., before processing PDU header in this state
* machine, otherwise logout response may not be sent to initiator
* and initiator may get logout timeout.
*/
if (spdk_unlikely(conn->is_logged_out)) {
SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "pdu received after logout\n");
conn->pdu_recv_state = ISCSI_PDU_RECV_STATE_ERROR;
break;
}
pdu->data_segment_len = ISCSI_ALIGN(DGET24(pdu->bhs.data_segment_len));
/* AHS */
@ -4709,12 +4720,6 @@ iscsi_read_pdu(struct spdk_iscsi_conn *conn)
}
}
if (conn->is_logged_out) {
SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "pdu received after logout\n");
conn->pdu_recv_state = ISCSI_PDU_RECV_STATE_ERROR;
break;
}
if (!pdu->is_rejected) {
rc = iscsi_pdu_payload_handle(conn, pdu);
} else {