d296fcd8d9
There is a problem with TCP zcopy enabled: 1. TCP initiator sends icreq and start polling a qpair. Polling of qpair actively calls nvme_tcp_read_pdu function 2. nvme_tcp_read_pdu: qpair is in NVME_TCP_PDU_RECV_STATE_AWAIT_PDU_CH state, it reads 8 bytes of common PDU header. It determines the type of the PDU and finds the size of PDU_PSH header. 3. nvme_tcp_read_pdu: qpair is in NVME_TCP_PDU_RECV_STATE_AWAIT_PDU_PSH state. It should read 120 bytes of icresp PDU. The number of bytes which needs to be read is pdu->psh_len - pdu->psh_valid_bytes. qpair receives 120 bytes (the full PDU) and calls nvme_tcp_pdu_psh_handle -> nvme_tcp_icresp_handle. Here we check that we haven't yet received buffer reclaim notification and simply return from this function. At the same time we continue to poll the qpair. 4. nvme_tcp_read_pdu: qpair is in NVME_TCP_PDU_RECV_STATE_AWAIT_PDU_PSH state and tries to read data from a socket again. The number of bytes is pdu->psh_len - pdu->psh_valid_bytes. But now pdu->psh_len == pdu->psh_valid_bytes, so we call nvme_tcp_read_data with zero length. readv with zero length is commonly used to check errors on the socket, but in our case there is no errors and readv returns 0. 5. nvme_tcp_read_data treats zero as error and return NVME_TCP_CONNECTION_FATAL. Fix is to handle icresp, but leave qpair in INITIALIZING state until we receive acknowledgement for icreqsend_ack. We also move qpair to NVME_TCP_PDU_RECV_STATE_AWAIT_PDU_READY recv_state so recv_pdu will be zerofied and qpair will try to read a common PDU header. But since it is not initialized yet, it won't receive anything from the target. Fixes issue #1633 Change-Id: I22cedefe530a8ac3b51495988ed6265d8fad15bb Signed-off-by: Alexey Marchuk <alexeymar@mellanox.com> Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/4969 Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> |
||
---|---|---|
.. | ||
Makefile | ||
nvme_ctrlr_cmd.c | ||
nvme_ctrlr_ocssd_cmd.c | ||
nvme_ctrlr.c | ||
nvme_cuse.c | ||
nvme_cuse.h | ||
nvme_fabric.c | ||
nvme_internal.h | ||
nvme_io_msg.c | ||
nvme_io_msg.h | ||
nvme_ns_cmd.c | ||
nvme_ns_ocssd_cmd.c | ||
nvme_ns.c | ||
nvme_opal_internal.h | ||
nvme_opal.c | ||
nvme_pcie.c | ||
nvme_poll_group.c | ||
nvme_qpair.c | ||
nvme_quirks.c | ||
nvme_rdma.c | ||
nvme_tcp.c | ||
nvme_transport.c | ||
nvme_uevent.c | ||
nvme_uevent.h | ||
nvme_zns.c | ||
nvme.c | ||
spdk_nvme.map |