Commit 97e15fed authored by Ziye Yang's avatar Ziye Yang Committed by Jim Harris
Browse files

nvmf,rdma: Solve nvmf host reconnect issue.



Kernel nvmf host always tries to connect nvmf target
when we does not issue nvme disconnect command. Thus,
we face rdma_create_qp issue, the reason is that we call
rdma_listen too early, and the event retrieved from
rdma_cm_get_event is too late.

And this patch solves this issue.

Change-Id: I153a8aea7420a86a236301dad9bd54af97f60865
Signed-off-by: default avatarZiye Yang <ziye.yang@intel.com>
parent 5a3b89a6
Loading
Loading
Loading
Loading
+34 −11
Original line number Diff line number Diff line
@@ -152,6 +152,7 @@ struct spdk_nvmf_rdma_listen_addr {
	struct ibv_device_attr 			attr;
	struct ibv_comp_channel			*comp_channel;
	uint32_t				ref;
	bool					is_listened;
	TAILQ_ENTRY(spdk_nvmf_rdma_listen_addr)	link;
};

@@ -1062,17 +1063,49 @@ spdk_nvmf_rdma_listen_remove(struct spdk_nvmf_listen_addr *listen_addr)
static int
spdk_nvmf_rdma_poll(struct spdk_nvmf_conn *conn);

static void
spdk_nvmf_rdma_addr_listen_init(struct spdk_nvmf_rdma_listen_addr *addr)
{
	int rc;

	rc = rdma_listen(addr->id, 10); /* 10 = backlog */
	if (rc < 0) {
		SPDK_ERRLOG("rdma_listen() failed\n");
		addr->ref--;
		assert(addr->ref == 0);
		TAILQ_REMOVE(&g_rdma.listen_addrs, addr, link);
		ibv_destroy_comp_channel(addr->comp_channel);
		rdma_destroy_id(addr->id);
		spdk_nvmf_rdma_listen_addr_free(addr);
		return;
	}

	addr->is_listened = true;

	SPDK_NOTICELOG("*** NVMf Target Listening on %s port %d ***\n",
		       addr->traddr, ntohs(rdma_get_src_port(addr->id)));
}

static void
spdk_nvmf_rdma_acceptor_poll(void)
{
	struct rdma_cm_event		*event;
	int				rc;
	struct spdk_nvmf_rdma_conn	*rdma_conn, *tmp;
	struct spdk_nvmf_rdma_listen_addr *addr = NULL, *addr_tmp;

	if (g_rdma.event_channel == NULL) {
		return;
	}

	pthread_mutex_lock(&g_rdma.lock);
	TAILQ_FOREACH_SAFE(addr, &g_rdma.listen_addrs, link, addr_tmp) {
		if (!addr->is_listened) {
			spdk_nvmf_rdma_addr_listen_init(addr);
		}
	}
	pthread_mutex_unlock(&g_rdma.lock);

	/* Process pending connections for incoming capsules. The only capsule
	 * this should ever find is a CONNECT request. */
	TAILQ_FOREACH_SAFE(rdma_conn, &g_pending_conns, link, tmp) {
@@ -1187,15 +1220,6 @@ spdk_nvmf_rdma_listen(struct spdk_nvmf_listen_addr *listen_addr)
		return -1;
	}

	rc = rdma_listen(addr->id, 10); /* 10 = backlog */
	if (rc < 0) {
		SPDK_ERRLOG("rdma_listen() failed\n");
		rdma_destroy_id(addr->id);
		spdk_nvmf_rdma_listen_addr_free(addr);
		pthread_mutex_unlock(&g_rdma.lock);
		return -1;
	}

	rc = ibv_query_device(addr->id->verbs, &addr->attr);
	if (rc < 0) {
		SPDK_ERRLOG("Failed to query RDMA device attributes.\n");
@@ -1226,12 +1250,11 @@ spdk_nvmf_rdma_listen(struct spdk_nvmf_listen_addr *listen_addr)
		return -1;
	}


	addr->ref = 1;
	TAILQ_INSERT_TAIL(&g_rdma.listen_addrs, addr, link);
	pthread_mutex_unlock(&g_rdma.lock);

	SPDK_NOTICELOG("*** NVMf Target Listening on %s port %d ***\n",
		       addr->traddr, ntohs(rdma_get_src_port(addr->id)));

	return 0;
}