Commit bb3e4413 authored by Seth Howell's avatar Seth Howell Committed by Jim Harris
Browse files

rdma: destroy qpairs based on num_outstanding_wr.



Both Mellanox and Soft-RoCE NICs work with this approach.

Change-Id: I7b05e54037761c4d5e58484e1c55934c47ac1ab9
Signed-off-by: default avatarSeth Howell <seth.howell@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/446134


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 4a5e97c9
Loading
Loading
Loading
Loading
+16 −54
Original line number Diff line number Diff line
@@ -197,8 +197,6 @@ enum spdk_nvmf_rdma_wr_type {
	RDMA_WR_TYPE_RECV,
	RDMA_WR_TYPE_SEND,
	RDMA_WR_TYPE_DATA,
	RDMA_WR_TYPE_DRAIN_SEND,
	RDMA_WR_TYPE_DRAIN_RECV
};

struct spdk_nvmf_rdma_wr {
@@ -343,8 +341,6 @@ struct spdk_nvmf_rdma_qpair {
	struct ibv_qp_attr			ibv_attr;

	uint32_t				disconnect_flags;
	struct spdk_nvmf_rdma_wr		drain_send_wr;
	struct spdk_nvmf_rdma_wr		drain_recv_wr;

	/* Poller registered in case the qpair doesn't properly
	 * complete the qpair destruct process and becomes defunct.
@@ -2235,6 +2231,16 @@ spdk_nvmf_rdma_start_disconnect(struct spdk_nvmf_rdma_qpair *rqpair)
	}
}

static void spdk_nvmf_rdma_destroy_drained_qpair(struct spdk_nvmf_rdma_qpair *rqpair,
		struct spdk_nvmf_rdma_transport *rtransport)
{
	if (rqpair->current_send_depth == 0 && rqpair->current_recv_depth == rqpair->max_queue_depth) {
		/* The qpair has been drained. Free the resources. */
		spdk_nvmf_rdma_qpair_process_pending(rtransport, rqpair, true);
		spdk_nvmf_rdma_qpair_destroy(rqpair);
	}
}


static int
nvmf_rdma_disconnect(struct rdma_cm_event *evt)
@@ -2686,11 +2692,6 @@ static void
spdk_nvmf_rdma_close_qpair(struct spdk_nvmf_qpair *qpair)
{
	struct spdk_nvmf_rdma_qpair *rqpair = SPDK_CONTAINEROF(qpair, struct spdk_nvmf_rdma_qpair, qpair);
	struct ibv_recv_wr recv_wr = {};
	struct ibv_recv_wr *bad_recv_wr;
	struct ibv_send_wr send_wr = {};
	struct ibv_send_wr *bad_send_wr;
	int rc;

	if (rqpair->disconnect_flags & RDMA_QP_DISCONNECTING) {
		return;
@@ -2712,26 +2713,6 @@ spdk_nvmf_rdma_close_qpair(struct spdk_nvmf_qpair *qpair)
		spdk_nvmf_rdma_set_ibv_state(rqpair, IBV_QPS_ERR);
	}

	rqpair->drain_recv_wr.type = RDMA_WR_TYPE_DRAIN_RECV;
	recv_wr.wr_id = (uintptr_t)&rqpair->drain_recv_wr;
	rc = ibv_post_recv(rqpair->cm_id->qp, &recv_wr, &bad_recv_wr);
	if (rc) {
		SPDK_ERRLOG("Failed to post dummy receive WR, errno %d\n", errno);
		assert(false);
		return;
	}

	rqpair->drain_send_wr.type = RDMA_WR_TYPE_DRAIN_SEND;
	send_wr.wr_id = (uintptr_t)&rqpair->drain_send_wr;
	send_wr.opcode = IBV_WR_SEND;
	rc = ibv_post_send(rqpair->cm_id->qp, &send_wr, &bad_send_wr);
	if (rc) {
		SPDK_ERRLOG("Failed to post dummy send WR, errno %d\n", errno);
		assert(false);
		return;
	}
	rqpair->current_send_depth++;

	rqpair->destruct_poller = spdk_poller_register(spdk_nvmf_rdma_destroy_defunct_qpair, (void *)rqpair,
				  NVMF_RDMA_QPAIR_DESTROY_TIMEOUT_US);
}
@@ -2821,31 +2802,6 @@ spdk_nvmf_rdma_poller_poll(struct spdk_nvmf_rdma_transport *rtransport,
				}
				rqpair->current_send_depth--;
				break;
			case RDMA_WR_TYPE_DRAIN_RECV:
				rqpair = SPDK_CONTAINEROF(rdma_wr, struct spdk_nvmf_rdma_qpair, drain_recv_wr);
				assert(rqpair->disconnect_flags & RDMA_QP_DISCONNECTING);
				SPDK_DEBUGLOG(SPDK_LOG_RDMA, "Drained QP RECV %u (%p)\n", rqpair->qpair.qid, rqpair);
				rqpair->disconnect_flags |= RDMA_QP_RECV_DRAINED;
				assert(rqpair->current_recv_depth == rqpair->max_queue_depth);
				/* Don't worry about responding to recv overflow, we are disconnecting anyways */
				if (rqpair->disconnect_flags & RDMA_QP_SEND_DRAINED) {
					spdk_nvmf_rdma_qpair_process_pending(rtransport, rqpair, true);
					spdk_nvmf_rdma_qpair_destroy(rqpair);
				}
				/* Continue so that this does not trigger the disconnect path below. */
				continue;
			case RDMA_WR_TYPE_DRAIN_SEND:
				rqpair = SPDK_CONTAINEROF(rdma_wr, struct spdk_nvmf_rdma_qpair, drain_send_wr);
				assert(rqpair->disconnect_flags & RDMA_QP_DISCONNECTING);
				SPDK_DEBUGLOG(SPDK_LOG_RDMA, "Drained QP SEND %u (%p)\n", rqpair->qpair.qid, rqpair);
				rqpair->disconnect_flags |= RDMA_QP_SEND_DRAINED;
				rqpair->current_send_depth--;
				if (rqpair->disconnect_flags & RDMA_QP_RECV_DRAINED) {
					spdk_nvmf_rdma_qpair_process_pending(rtransport, rqpair, true);
					spdk_nvmf_rdma_qpair_destroy(rqpair);
				}
				/* Continue so that this does not trigger the disconnect path below. */
				continue;
			default:
				SPDK_ERRLOG("Received an unknown opcode on the CQ: %d\n", wc[i].opcode);
				continue;
@@ -2854,6 +2810,8 @@ spdk_nvmf_rdma_poller_poll(struct spdk_nvmf_rdma_transport *rtransport,
			if (rqpair->qpair.state == SPDK_NVMF_QPAIR_ACTIVE) {
				/* Disconnect the connection. */
				spdk_nvmf_rdma_start_disconnect(rqpair);
			} else {
				spdk_nvmf_rdma_destroy_drained_qpair(rqpair, rtransport);
			}
			continue;
		}
@@ -2927,6 +2885,10 @@ spdk_nvmf_rdma_poller_poll(struct spdk_nvmf_rdma_transport *rtransport,
			SPDK_ERRLOG("Received an unknown opcode on the CQ: %d\n", wc[i].opcode);
			continue;
		}

		if (rqpair->qpair.state != SPDK_NVMF_QPAIR_ACTIVE) {
			spdk_nvmf_rdma_destroy_drained_qpair(rqpair, rtransport);
		}
	}

	if (error == true) {