diff --git a/app/nvmf_tgt/nvmf_tgt.c b/app/nvmf_tgt/nvmf_tgt.c index 1551759df..c8bac339a 100644 --- a/app/nvmf_tgt/nvmf_tgt.c +++ b/app/nvmf_tgt/nvmf_tgt.c @@ -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); diff --git a/include/spdk/nvmf.h b/include/spdk/nvmf.h index 17b9efc60..95e8b25d0 100644 --- a/include/spdk/nvmf.h +++ b/include/spdk/nvmf.h @@ -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 diff --git a/lib/nvmf/nvmf_internal.h b/lib/nvmf/nvmf_internal.h index 524e96d63..219a7ea57 100644 --- a/lib/nvmf/nvmf_internal.h +++ b/lib/nvmf/nvmf_internal.h @@ -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);