nvmf: move poll groups to public API

The end goal is to have the application create one poll group per core.
Then each poll group will have a single CQ per network device and an I/O
channel per back-end storage device to poll.

This is just the first step toward that, which is to wire up the
creation of the per-core poll groups in the application.

Note that the app poll groups don't do anything yet.  We'll need
additional library API changes to make the library use the existing poll
groups, rather than creating a new poll group per subsystem as we do
right now.

Change-Id: I2d4e2a5e5aa354d37714750f1d5b1d1e4ab9edce
Signed-off-by: Daniel Verkamp <daniel.verkamp@intel.com>
Reviewed-on: https://review.gerrithub.io/381887
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Daniel Verkamp 2017-09-25 15:27:01 -07:00 committed by Jim Harris
parent 6a0e6abcd3
commit 7ea544b46a
3 changed files with 96 additions and 5 deletions

View File

@ -39,9 +39,19 @@
#include "spdk/event.h"
#include "spdk/log.h"
#include "spdk/nvme.h"
#include "spdk/util.h"
struct nvmf_tgt_poll_group {
struct spdk_nvmf_poll_group *group;
struct spdk_poller *poller;
};
struct spdk_nvmf_tgt *g_tgt = NULL;
static struct nvmf_tgt_poll_group *g_poll_groups = NULL;
static size_t g_num_poll_groups = 0;
static size_t g_active_poll_groups = 0;
static struct spdk_poller *g_acceptor_poller = NULL;
static TAILQ_HEAD(, nvmf_tgt_subsystem) g_subsystems = TAILQ_HEAD_INITIALIZER(g_subsystems);
@ -96,10 +106,41 @@ shutdown_subsystems(void)
}
}
static void
nvmf_tgt_poll_group_stopped_event(void *arg1, void *arg2)
{
uint32_t core;
g_active_poll_groups--;
if (g_active_poll_groups == 0) {
/* All of the poll group pollers are stopped, so we can now delete the poll groups safely. */
SPDK_ENV_FOREACH_CORE(core) {
struct nvmf_tgt_poll_group *app_poll_group = &g_poll_groups[core];
spdk_nvmf_poll_group_destroy(app_poll_group->group);
}
shutdown_subsystems();
}
}
static void
acceptor_poller_unregistered_event(void *arg1, void *arg2)
{
shutdown_subsystems();
struct nvmf_tgt_poll_group *app_poll_group;
struct spdk_event *event;
uint32_t core;
/* Stop poll group pollers on all cores */
SPDK_ENV_FOREACH_CORE(core) {
app_poll_group = &g_poll_groups[core];
event = spdk_event_allocate(spdk_env_get_current_core(),
nvmf_tgt_poll_group_stopped_event,
NULL, NULL);
spdk_poller_unregister(&app_poll_group->poller, event);
}
}
static void
@ -231,9 +272,18 @@ acceptor_poll(void *arg)
spdk_nvmf_tgt_accept(tgt);
}
static void
nvmf_tgt_poll_group_poll(void *arg)
{
struct nvmf_tgt_poll_group *app_poll_group = arg;
spdk_nvmf_poll_group_poll(app_poll_group->group);
}
static void
spdk_nvmf_startup(void *arg1, void *arg2)
{
uint32_t core;
int rc;
rc = spdk_nvmf_parse_conf();
@ -247,6 +297,35 @@ spdk_nvmf_startup(void *arg1, void *arg2)
goto initialize_error;
}
/* Find the maximum core number */
SPDK_ENV_FOREACH_CORE(core) {
g_num_poll_groups = spdk_max(g_num_poll_groups, core + 1);
}
assert(g_num_poll_groups > 0);
g_poll_groups = calloc(g_num_poll_groups, sizeof(*g_poll_groups));
if (g_poll_groups == NULL) {
goto initialize_error;
}
/* Create a poll group on each core in the app core mask. */
g_active_poll_groups = 0;
SPDK_ENV_FOREACH_CORE(core) {
struct nvmf_tgt_poll_group *app_poll_group = &g_poll_groups[core];
app_poll_group->group = spdk_nvmf_poll_group_create(g_tgt);
if (app_poll_group->group == NULL) {
SPDK_ERRLOG("Failed to create poll group for core %u\n", core);
goto initialize_error;
}
spdk_poller_register(&app_poll_group->poller,
nvmf_tgt_poll_group_poll, app_poll_group,
core, 0);
g_active_poll_groups++;
}
spdk_poller_register(&g_acceptor_poller, acceptor_poll, g_tgt,
g_spdk_nvmf_tgt_conf.acceptor_lcore,
g_spdk_nvmf_tgt_conf.acceptor_poll_rate);

View File

@ -99,6 +99,22 @@ struct spdk_bdev;
struct spdk_nvmf_request;
struct spdk_nvmf_host;
struct spdk_nvmf_listener;
struct spdk_nvmf_poll_group;
/**
* Create a poll group.
*/
struct spdk_nvmf_poll_group *spdk_nvmf_poll_group_create(struct spdk_nvmf_tgt *tgt);
/**
* Destroy a poll group.
*/
void spdk_nvmf_poll_group_destroy(struct spdk_nvmf_poll_group *group);
/**
* Check a poll group for work completions.
*/
int spdk_nvmf_poll_group_poll(struct spdk_nvmf_poll_group *group);
/*
* The NVMf subsystem, as indicated in the specification, is a collection

View File

@ -197,14 +197,10 @@ struct spdk_nvmf_subsystem {
struct spdk_nvmf_transport *spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt *tgt,
enum spdk_nvme_transport_type);
struct spdk_nvmf_poll_group *spdk_nvmf_poll_group_create(
struct spdk_nvmf_tgt *tgt);
void spdk_nvmf_poll_group_destroy(struct spdk_nvmf_poll_group *group);
int spdk_nvmf_poll_group_add(struct spdk_nvmf_poll_group *group,
struct spdk_nvmf_qpair *qpair);
int spdk_nvmf_poll_group_remove(struct spdk_nvmf_poll_group *group,
struct spdk_nvmf_qpair *qpair);
int spdk_nvmf_poll_group_poll(struct spdk_nvmf_poll_group *group);
void spdk_nvmf_request_exec(struct spdk_nvmf_request *req);
int spdk_nvmf_request_complete(struct spdk_nvmf_request *req);