From 7545e8c829c0ddbbc88bf310e6afc7cfa5cf6bcb Mon Sep 17 00:00:00 2001 From: Alexey Marchuk Date: Tue, 30 Jul 2019 05:42:40 +0000 Subject: [PATCH] rdma: add DIF support for read operation Add DIF verification after IO operation completion Change-Id: Iaf4f29d07ca84b0341498eb4e44fc8cc159ecb9c Signed-off-by: Alexey Marchuk Signed-off-by: Sasha Kotchubievsky Signed-off-by: Evgenii Kochetov Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/465249 Tested-by: SPDK CI Jenkins Reviewed-by: Ben Walker Reviewed-by: Shuhei Matsumoto Reviewed-by: Changpeng Liu --- lib/nvmf/rdma.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/lib/nvmf/rdma.c b/lib/nvmf/rdma.c index b5163a547b..ad968472b8 100644 --- a/lib/nvmf/rdma.c +++ b/lib/nvmf/rdma.c @@ -528,6 +528,27 @@ spdk_nvmf_rdma_check_ibv_state(enum ibv_qp_state state) } } +static inline enum spdk_nvme_media_error_status_code +spdk_nvmf_rdma_dif_error_to_compl_status(uint8_t err_type) { + enum spdk_nvme_media_error_status_code result; + switch (err_type) + { + case SPDK_DIF_REFTAG_ERROR: + result = SPDK_NVME_SC_REFERENCE_TAG_CHECK_ERROR; + break; + case SPDK_DIF_APPTAG_ERROR: + result = SPDK_NVME_SC_APPLICATION_TAG_CHECK_ERROR; + break; + case SPDK_DIF_GUARD_ERROR: + result = SPDK_NVME_SC_GUARD_CHECK_ERROR; + break; + default: + SPDK_UNREACHABLE(); + } + + return result; +} + static enum ibv_qp_state spdk_nvmf_rdma_update_ibv_state(struct spdk_nvmf_rdma_qpair *rqpair) { enum ibv_qp_state old_state, new_state; @@ -2148,6 +2169,25 @@ spdk_nvmf_rdma_request_process(struct spdk_nvmf_rdma_transport *rtransport, if (spdk_unlikely(rdma_req->dif_insert_or_strip)) { /* restore the original length */ rdma_req->req.length = rdma_req->orig_length; + + if (rdma_req->req.xfer == SPDK_NVME_DATA_CONTROLLER_TO_HOST) { + struct spdk_dif_error error_blk; + + num_blocks = SPDK_CEIL_DIV(rdma_req->elba_length, rdma_req->dif_ctx.block_size); + + rc = spdk_dif_verify(rdma_req->req.iov, rdma_req->req.iovcnt, num_blocks, &rdma_req->dif_ctx, + &error_blk); + if (rc) { + struct spdk_nvme_cpl *rsp = &rdma_req->req.rsp->nvme_cpl; + + SPDK_ERRLOG("DIF error detected. type=%d, offset=%" PRIu32 "\n", error_blk.err_type, + error_blk.err_offset); + rsp->status.sct = SPDK_NVME_SCT_MEDIA_ERROR; + rsp->status.sc = spdk_nvmf_rdma_dif_error_to_compl_status(error_blk.err_type); + rdma_req->state = RDMA_REQUEST_STATE_READY_TO_COMPLETE; + STAILQ_REMOVE(&rqpair->pending_rdma_write_queue, rdma_req, spdk_nvmf_rdma_request, state_link); + } + } } break; case RDMA_REQUEST_STATE_DATA_TRANSFER_TO_HOST_PENDING: