nvmf/rdma: Speed up qpair lookup by using RB tree
To speed up qpair lookup, an idea to use the DPDK hash library was proposed. But we have some concerns for the idea, we may see performance regression for small configuration, lib/nvmf is depending on the DPDK feature, and so on. On the other hand, RB tree is simple to use and is not likely to have negative side effect. To use RB tree easily, cache QP num into struct spdk_nvmf_rdma_qpair. Change-Id: Id4ea4e75692f86335b3e984c3fc128e187f22c72 Signed-off-by: Shuhei Matsumoto <smatsumoto@nvidia.com> Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/11798 Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com> Community-CI: Mellanox Build Bot Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
parent
7613e3fefb
commit
52f7aeb703
@ -40,6 +40,7 @@
|
||||
#include "spdk/nvmf_transport.h"
|
||||
#include "spdk/string.h"
|
||||
#include "spdk/trace.h"
|
||||
#include "spdk/tree.h"
|
||||
#include "spdk/util.h"
|
||||
|
||||
#include "spdk_internal/assert.h"
|
||||
@ -327,6 +328,9 @@ struct spdk_nvmf_rdma_qpair {
|
||||
struct spdk_rdma_srq *srq;
|
||||
struct rdma_cm_id *listen_id;
|
||||
|
||||
/* Cache the QP number to improve QP search by RB tree. */
|
||||
uint32_t qp_num;
|
||||
|
||||
/* The maximum number of I/O outstanding on this connection at one time */
|
||||
uint16_t max_queue_depth;
|
||||
|
||||
@ -364,7 +368,7 @@ struct spdk_nvmf_rdma_qpair {
|
||||
/* Number of requests not in the free state */
|
||||
uint32_t qd;
|
||||
|
||||
TAILQ_ENTRY(spdk_nvmf_rdma_qpair) link;
|
||||
RB_ENTRY(spdk_nvmf_rdma_qpair) node;
|
||||
|
||||
STAILQ_ENTRY(spdk_nvmf_rdma_qpair) recv_link;
|
||||
|
||||
@ -419,7 +423,7 @@ struct spdk_nvmf_rdma_poller {
|
||||
struct spdk_nvmf_rdma_resources *resources;
|
||||
struct spdk_nvmf_rdma_poller_stat stat;
|
||||
|
||||
TAILQ_HEAD(, spdk_nvmf_rdma_qpair) qpairs;
|
||||
RB_HEAD(qpairs_tree, spdk_nvmf_rdma_qpair) qpairs;
|
||||
|
||||
STAILQ_HEAD(, spdk_nvmf_rdma_qpair) qpairs_pending_recv;
|
||||
|
||||
@ -517,6 +521,14 @@ static const struct spdk_json_object_decoder rdma_transport_opts_decoder[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static int
|
||||
nvmf_rdma_qpair_compare(struct spdk_nvmf_rdma_qpair *rqpair1, struct spdk_nvmf_rdma_qpair *rqpair2)
|
||||
{
|
||||
return rqpair1->qp_num - rqpair2->qp_num;
|
||||
}
|
||||
|
||||
RB_GENERATE_STATIC(qpairs_tree, spdk_nvmf_rdma_qpair, node, nvmf_rdma_qpair_compare);
|
||||
|
||||
static bool
|
||||
nvmf_rdma_request_process(struct spdk_nvmf_rdma_transport *rtransport,
|
||||
struct spdk_nvmf_rdma_request *rdma_req);
|
||||
@ -893,7 +905,7 @@ nvmf_rdma_qpair_destroy(struct spdk_nvmf_rdma_qpair *rqpair)
|
||||
}
|
||||
|
||||
if (rqpair->poller) {
|
||||
TAILQ_REMOVE(&rqpair->poller->qpairs, rqpair, link);
|
||||
RB_REMOVE(qpairs_tree, &rqpair->poller->qpairs, rqpair);
|
||||
|
||||
if (rqpair->srq != NULL && rqpair->resources != NULL) {
|
||||
/* Drop all received but unprocessed commands for this queue and return them to SRQ */
|
||||
@ -1017,6 +1029,8 @@ nvmf_rdma_qpair_initialize(struct spdk_nvmf_qpair *qpair)
|
||||
goto error;
|
||||
}
|
||||
|
||||
rqpair->qp_num = rqpair->rdma_qp->qp->qp_num;
|
||||
|
||||
rqpair->max_send_depth = spdk_min((uint32_t)(rqpair->max_queue_depth * 2),
|
||||
qp_init_attr.cap.max_send_wr);
|
||||
rqpair->max_send_sge = spdk_min(NVMF_DEFAULT_TX_SGE, qp_init_attr.cap.max_send_sge);
|
||||
@ -1205,7 +1219,7 @@ nvmf_rdma_event_accept(struct rdma_cm_id *id, struct spdk_nvmf_rdma_qpair *rqpai
|
||||
* Fields below are ignored by rdma cm if qpair has been
|
||||
* created using rdma cm API. */
|
||||
ctrlr_event_data.srq = rqpair->srq ? 1 : 0;
|
||||
ctrlr_event_data.qp_num = rqpair->rdma_qp->qp->qp_num;
|
||||
ctrlr_event_data.qp_num = rqpair->qp_num;
|
||||
|
||||
rc = spdk_rdma_qp_accept(rqpair->rdma_qp, &ctrlr_event_data);
|
||||
if (rc) {
|
||||
@ -2847,7 +2861,7 @@ nvmf_rdma_disconnect_qpairs_on_port(struct spdk_nvmf_rdma_transport *rtransport,
|
||||
|
||||
TAILQ_FOREACH(rgroup, &rtransport->poll_groups, link) {
|
||||
TAILQ_FOREACH(rpoller, &rgroup->pollers, link) {
|
||||
TAILQ_FOREACH(rqpair, &rpoller->qpairs, link) {
|
||||
RB_FOREACH(rqpair, qpairs_tree, &rpoller->qpairs) {
|
||||
if (rqpair->listen_id == port->id) {
|
||||
spdk_nvmf_qpair_disconnect(&rqpair->qpair, NULL, NULL);
|
||||
}
|
||||
@ -3275,7 +3289,7 @@ nvmf_rdma_poll_group_create(struct spdk_nvmf_transport *transport,
|
||||
poller->device = device;
|
||||
poller->group = rgroup;
|
||||
|
||||
TAILQ_INIT(&poller->qpairs);
|
||||
RB_INIT(&poller->qpairs);
|
||||
STAILQ_INIT(&poller->qpairs_pending_send);
|
||||
STAILQ_INIT(&poller->qpairs_pending_recv);
|
||||
|
||||
@ -3401,7 +3415,7 @@ nvmf_rdma_poll_group_destroy(struct spdk_nvmf_transport_poll_group *group)
|
||||
TAILQ_FOREACH_SAFE(poller, &rgroup->pollers, link, tmp) {
|
||||
TAILQ_REMOVE(&rgroup->pollers, poller, link);
|
||||
|
||||
TAILQ_FOREACH_SAFE(qpair, &poller->qpairs, link, tmp_qpair) {
|
||||
RB_FOREACH_SAFE(qpair, qpairs_tree, &poller->qpairs, tmp_qpair) {
|
||||
nvmf_rdma_qpair_destroy(qpair);
|
||||
}
|
||||
|
||||
@ -3491,7 +3505,7 @@ nvmf_rdma_poll_group_add(struct spdk_nvmf_transport_poll_group *group,
|
||||
return -1;
|
||||
}
|
||||
|
||||
TAILQ_INSERT_TAIL(&poller->qpairs, rqpair, link);
|
||||
RB_INSERT(qpairs_tree, &poller->qpairs, rqpair);
|
||||
|
||||
rc = nvmf_rdma_event_accept(rqpair->cm_id, rqpair);
|
||||
if (rc) {
|
||||
@ -3614,15 +3628,11 @@ nvmf_rdma_close_qpair(struct spdk_nvmf_qpair *qpair,
|
||||
static struct spdk_nvmf_rdma_qpair *
|
||||
get_rdma_qpair_from_wc(struct spdk_nvmf_rdma_poller *rpoller, struct ibv_wc *wc)
|
||||
{
|
||||
struct spdk_nvmf_rdma_qpair *rqpair;
|
||||
/* @todo: improve QP search */
|
||||
TAILQ_FOREACH(rqpair, &rpoller->qpairs, link) {
|
||||
if (wc->qp_num == rqpair->rdma_qp->qp->qp_num) {
|
||||
return rqpair;
|
||||
}
|
||||
}
|
||||
SPDK_ERRLOG("Didn't find QP with qp_num %u\n", wc->qp_num);
|
||||
return NULL;
|
||||
struct spdk_nvmf_rdma_qpair find;
|
||||
|
||||
find.qp_num = wc->qp_num;
|
||||
|
||||
return RB_FIND(qpairs_tree, &rpoller->qpairs, &find);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
Loading…
Reference in New Issue
Block a user