From e816c8fda8dd0eace8c8597f7044a6f98b92cc63 Mon Sep 17 00:00:00 2001 From: Seth Howell Date: Mon, 7 Jan 2019 11:07:59 -0700 Subject: [PATCH] nvmf: add a buffer_cache to transport opts This patch series is geared at solving github issue 555. Ultimately the goal of this series is to add a per-poll-group buffer cache to prevent starvation. Change-Id: I8ddaa47487665c2f9adce2109eb71b8fa71a7927 Signed-off-by: Seth Howell Reviewed-on: https://review.gerrithub.io/c/439415 Tested-by: SPDK CI Jenkins Reviewed-by: Jim Harris Reviewed-by: Shuhei Matsumoto Reviewed-by: Ben Walker --- include/spdk/nvmf.h | 1 + lib/nvmf/rdma.c | 13 +++++++++++ lib/nvmf/tcp.c | 55 ++++++++++++++++++++++++++++----------------- 3 files changed, 48 insertions(+), 21 deletions(-) diff --git a/include/spdk/nvmf.h b/include/spdk/nvmf.h index 110e31007..d095105f1 100644 --- a/include/spdk/nvmf.h +++ b/include/spdk/nvmf.h @@ -71,6 +71,7 @@ struct spdk_nvmf_transport_opts { uint32_t io_unit_size; uint32_t max_aq_depth; uint32_t num_shared_buffers; + uint32_t buf_cache_size; }; /** diff --git a/lib/nvmf/rdma.c b/lib/nvmf/rdma.c index eec86ba12..e677151f1 100644 --- a/lib/nvmf/rdma.c +++ b/lib/nvmf/rdma.c @@ -1578,6 +1578,7 @@ spdk_nvmf_rdma_request_process(struct spdk_nvmf_rdma_transport *rtransport, #define SPDK_NVMF_RDMA_DEFAULT_MAX_IO_SIZE 131072 #define SPDK_NVMF_RDMA_MIN_IO_BUFFER_SIZE 4096 #define SPDK_NVMF_RDMA_DEFAULT_NUM_SHARED_BUFFERS 512 +#define SPDK_NVMF_RDMA_DEFAULT_BUFFER_CACHE_SIZE 32 #define SPDK_NVMF_RDMA_DEFAULT_IO_BUFFER_SIZE (SPDK_NVMF_RDMA_DEFAULT_MAX_IO_SIZE / SPDK_NVMF_MAX_SGL_ENTRIES) static void @@ -1591,6 +1592,7 @@ spdk_nvmf_rdma_opts_init(struct spdk_nvmf_transport_opts *opts) SPDK_NVMF_RDMA_MIN_IO_BUFFER_SIZE); opts->max_aq_depth = SPDK_NVMF_RDMA_DEFAULT_AQ_DEPTH; opts->num_shared_buffers = SPDK_NVMF_RDMA_DEFAULT_NUM_SHARED_BUFFERS; + opts->buf_cache_size = SPDK_NVMF_RDMA_DEFAULT_BUFFER_CACHE_SIZE; } static int spdk_nvmf_rdma_destroy(struct spdk_nvmf_transport *transport); @@ -1605,6 +1607,7 @@ spdk_nvmf_rdma_create(struct spdk_nvmf_transport_opts *opts) uint32_t i; int flag; uint32_t sge_count; + uint32_t min_shared_buffers; const struct spdk_mem_map_ops nvmf_rdma_map_ops = { .notify_cb = spdk_nvmf_rdma_mem_notify, @@ -1658,6 +1661,16 @@ spdk_nvmf_rdma_create(struct spdk_nvmf_transport_opts *opts) return NULL; } + min_shared_buffers = spdk_thread_get_count() * opts->buf_cache_size; + if (min_shared_buffers > opts->num_shared_buffers) { + SPDK_ERRLOG("There are not enough buffers to satisfy" + "per-poll group caches for each thread. (%" PRIu32 ")" + "supplied. (%" PRIu32 ") required\n", opts->num_shared_buffers, min_shared_buffers); + SPDK_ERRLOG("Please specify a larger number of shared buffers\n"); + spdk_nvmf_rdma_destroy(&rtransport->transport); + return NULL; + } + sge_count = opts->max_io_size / opts->io_unit_size; if (sge_count > NVMF_DEFAULT_TX_SGE) { SPDK_ERRLOG("Unsupported IO Unit size specified, %d bytes\n", opts->io_unit_size); diff --git a/lib/nvmf/tcp.c b/lib/nvmf/tcp.c index e6156915f..570415882 100644 --- a/lib/nvmf/tcp.c +++ b/lib/nvmf/tcp.c @@ -527,11 +527,33 @@ spdk_nvmf_tcp_qpair_destroy(struct nvme_tcp_qpair *tqpair) SPDK_DEBUGLOG(SPDK_LOG_NVMF_TCP, "Leave\n"); } +static int +spdk_nvmf_tcp_destroy(struct spdk_nvmf_transport *transport) +{ + struct spdk_nvmf_tcp_transport *ttransport; + + assert(transport != NULL); + ttransport = SPDK_CONTAINEROF(transport, struct spdk_nvmf_tcp_transport, transport); + + if (spdk_mempool_count(ttransport->data_buf_pool) != (transport->opts.num_shared_buffers)) { + SPDK_ERRLOG("transport buffer pool count is %zu but should be %u\n", + spdk_mempool_count(ttransport->data_buf_pool), + transport->opts.num_shared_buffers); + } + + spdk_mempool_free(ttransport->data_buf_pool); + spdk_io_device_unregister(ttransport, NULL); + pthread_mutex_destroy(&ttransport->lock); + free(ttransport); + return 0; +} + static struct spdk_nvmf_transport * spdk_nvmf_tcp_create(struct spdk_nvmf_transport_opts *opts) { struct spdk_nvmf_tcp_transport *ttransport; uint32_t sge_count; + uint32_t min_shared_buffers; ttransport = calloc(1, sizeof(*ttransport)); if (!ttransport) { @@ -581,6 +603,16 @@ spdk_nvmf_tcp_create(struct spdk_nvmf_transport_opts *opts) return NULL; } + min_shared_buffers = spdk_thread_get_count() * opts->buf_cache_size; + if (min_shared_buffers > opts->num_shared_buffers) { + SPDK_ERRLOG("There are not enough buffers to satisfy" + "per-poll group caches for each thread. (%" PRIu32 ")" + "supplied. (%" PRIu32 ") required\n", opts->num_shared_buffers, min_shared_buffers); + SPDK_ERRLOG("Please specify a larger number of shared buffers\n"); + spdk_nvmf_tcp_destroy(&ttransport->transport); + return NULL; + } + pthread_mutex_init(&ttransport->lock, NULL); spdk_io_device_register(ttransport, spdk_nvmf_tcp_mgmt_channel_create, @@ -590,27 +622,6 @@ spdk_nvmf_tcp_create(struct spdk_nvmf_transport_opts *opts) return &ttransport->transport; } -static int -spdk_nvmf_tcp_destroy(struct spdk_nvmf_transport *transport) -{ - struct spdk_nvmf_tcp_transport *ttransport; - - assert(transport != NULL); - ttransport = SPDK_CONTAINEROF(transport, struct spdk_nvmf_tcp_transport, transport); - - if (spdk_mempool_count(ttransport->data_buf_pool) != (transport->opts.num_shared_buffers)) { - SPDK_ERRLOG("transport buffer pool count is %zu but should be %u\n", - spdk_mempool_count(ttransport->data_buf_pool), - transport->opts.num_shared_buffers); - } - - spdk_mempool_free(ttransport->data_buf_pool); - spdk_io_device_unregister(ttransport, NULL); - pthread_mutex_destroy(&ttransport->lock); - free(ttransport); - return 0; -} - static int _spdk_nvmf_tcp_trsvcid_to_int(const char *trsvcid) { @@ -2855,6 +2866,7 @@ spdk_nvmf_tcp_qpair_set_sq_size(struct spdk_nvmf_qpair *qpair) #define SPDK_NVMF_TCP_DEFAULT_MAX_IO_SIZE 131072 #define SPDK_NVMF_TCP_DEFAULT_IO_UNIT_SIZE 131072 #define SPDK_NVMF_TCP_DEFAULT_NUM_SHARED_BUFFERS 512 +#define SPDK_NVMF_TCP_DEFAULT_BUFFER_CACHE_SIZE 32 static void spdk_nvmf_tcp_opts_init(struct spdk_nvmf_transport_opts *opts) @@ -2866,6 +2878,7 @@ spdk_nvmf_tcp_opts_init(struct spdk_nvmf_transport_opts *opts) opts->io_unit_size = SPDK_NVMF_TCP_DEFAULT_IO_UNIT_SIZE; opts->max_aq_depth = SPDK_NVMF_TCP_DEFAULT_AQ_DEPTH; opts->num_shared_buffers = SPDK_NVMF_TCP_DEFAULT_NUM_SHARED_BUFFERS; + opts->buf_cache_size = SPDK_NVMF_TCP_DEFAULT_BUFFER_CACHE_SIZE; } const struct spdk_nvmf_transport_ops spdk_nvmf_transport_tcp = {