From 76675f6f603d24501e56aec24f51e31078350d96 Mon Sep 17 00:00:00 2001 From: JinYu Date: Wed, 12 Dec 2018 22:38:22 +0800 Subject: [PATCH] rdma: check ibv state after rdma update it We found ibv state value may be unreasonable, so before we use the state value we do some judgement. The unreasonable state probably means hardware issue, so the process flow become unpredicatable. Fix GitHub issue #508. Change-Id: I213f4d684b103cce7bc072aecd591e2c491e0596 Signed-off-by: JinYu Reviewed-on: https://review.gerrithub.io/c/436920 Tested-by: SPDK CI Jenkins Chandler-Test-Pool: SPDK Automated Test System Reviewed-by: Ziye Yang Reviewed-by: Ben Walker Reviewed-by: Changpeng Liu --- lib/nvmf/rdma.c | 47 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/lib/nvmf/rdma.c b/lib/nvmf/rdma.c index de706856e..47f4e42ca 100644 --- a/lib/nvmf/rdma.c +++ b/lib/nvmf/rdma.c @@ -408,6 +408,23 @@ spdk_nvmf_rdma_qpair_dec_refcnt(struct spdk_nvmf_rdma_qpair *rqpair) return new_refcnt; } +static inline int +spdk_nvmf_rdma_check_ibv_state(enum ibv_qp_state state) +{ + switch (state) { + case IBV_QPS_RESET: + case IBV_QPS_INIT: + case IBV_QPS_RTR: + case IBV_QPS_RTS: + case IBV_QPS_SQD: + case IBV_QPS_SQE: + case IBV_QPS_ERR: + return 0; + default: + return -1; + } +} + 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; @@ -443,6 +460,18 @@ spdk_nvmf_rdma_update_ibv_state(struct spdk_nvmf_rdma_qpair *rqpair) { } new_state = rqpair->ibv_attr.qp_state; + + rc = spdk_nvmf_rdma_check_ibv_state(new_state); + if (rc) + { + SPDK_ERRLOG("QP#%d: bad state updated: %u, maybe hardware issue\n", rqpair->qpair.qid, new_state); + /* + * IBV_QPS_UNKNOWN undefined if lib version smaller than libibverbs-1.1.8 + * IBV_QPS_UNKNOWN is the enum element after IBV_QPS_ERR + */ + return IBV_QPS_ERR + 1; + } + if (old_state != new_state) { spdk_trace_record(TRACE_RDMA_QP_STATE_CHANGE, 0, 0, @@ -458,7 +487,8 @@ static const char *str_ibv_qp_state[] = { "IBV_QPS_RTS", "IBV_QPS_SQD", "IBV_QPS_SQE", - "IBV_QPS_ERR" + "IBV_QPS_ERR", + "IBV_QPS_UNKNOWN" }; static int @@ -491,20 +521,13 @@ spdk_nvmf_rdma_set_ibv_state(struct spdk_nvmf_rdma_qpair *rqpair, [IBV_QPS_ERR] = IBV_QP_STATE, }; - switch (new_state) { - case IBV_QPS_RESET: - case IBV_QPS_INIT: - case IBV_QPS_RTR: - case IBV_QPS_RTS: - case IBV_QPS_SQD: - case IBV_QPS_SQE: - case IBV_QPS_ERR: - break; - default: + rc = spdk_nvmf_rdma_check_ibv_state(new_state); + if (rc) { SPDK_ERRLOG("QP#%d: bad state requested: %u\n", rqpair->qpair.qid, new_state); - return -1; + return rc; } + rqpair->ibv_attr.cur_qp_state = rqpair->ibv_attr.qp_state; rqpair->ibv_attr.qp_state = new_state; rqpair->ibv_attr.ah_attr.port_num = rqpair->ibv_attr.port_num;