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: Ziye Yang <ziye.yang@intel.com>
This commit is contained in:
Ziye Yang 2017-02-16 00:23:46 +08:00 committed by Jim Harris
parent 5a3b89a679
commit 97e15fedb8

View File

@ -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;
}