bdev/nvme: add timer-based admin queue poller

This is necessary to process asynchronous events, as well as keep-alive
support for NVMe over Fabrics connections.

Based on a patch by Edward Yang <eyang@us.fujitsu.com>

Change-Id: I3e81f3d5061f75b12b625fa1a06629c6dc3dc61b
Signed-off-by: Daniel Verkamp <daniel.verkamp@intel.com>
This commit is contained in:
Daniel Verkamp 2017-01-13 12:58:23 -07:00
parent 5eacff59cd
commit 5de35015b9
3 changed files with 31 additions and 0 deletions

View File

@ -113,6 +113,9 @@
ResetControllerOnTimeout Yes ResetControllerOnTimeout Yes
# Timeout value. # Timeout value.
NvmeTimeoutValue 30 NvmeTimeoutValue 30
# Set how often the admin queue is polled for asynchronous events.
# Units in microseconds.
AdminPollRate 100000
# Users may change this section to create a different number or size of # Users may change this section to create a different number or size of
# malloc LUNs. # malloc LUNs.

View File

@ -67,10 +67,14 @@
# poll. Units in microseconds. # poll. Units in microseconds.
AcceptorPollRate 10000 AcceptorPollRate 10000
[Nvme]
# Registers the application to receive timeout callback and to reset the controller. # Registers the application to receive timeout callback and to reset the controller.
ResetControllerOnTimeout Yes ResetControllerOnTimeout Yes
# Timeout value. # Timeout value.
NvmeTimeoutValue 30 NvmeTimeoutValue 30
# Set how often the admin queue is polled for asynchronous events
# Units in microseconds.
AdminPollRate 100000
# Define an NVMf Subsystem. # Define an NVMf Subsystem.
# - NQN is required and must be unique. # - NQN is required and must be unique.

View File

@ -64,6 +64,8 @@ struct nvme_device {
struct spdk_nvme_ctrlr *ctrlr; struct spdk_nvme_ctrlr *ctrlr;
struct spdk_pci_addr pci_addr; struct spdk_pci_addr pci_addr;
struct spdk_poller *adminq_timer_poller;
/** linked list pointer for device list */ /** linked list pointer for device list */
TAILQ_ENTRY(nvme_device) tailq; TAILQ_ENTRY(nvme_device) tailq;
@ -113,6 +115,7 @@ static int lun_size_in_mb = 0;
static int num_controllers = -1; static int num_controllers = -1;
static int g_reset_controller_on_timeout = 0; static int g_reset_controller_on_timeout = 0;
static int g_timeout = 0; static int g_timeout = 0;
static int g_nvme_adminq_poll_timeout_us = 0;
static TAILQ_HEAD(, nvme_device) g_nvme_devices = TAILQ_HEAD_INITIALIZER(g_nvme_devices);; static TAILQ_HEAD(, nvme_device) g_nvme_devices = TAILQ_HEAD_INITIALIZER(g_nvme_devices);;
@ -181,6 +184,14 @@ blockdev_nvme_poll(void *arg)
spdk_nvme_qpair_process_completions(qpair, 0); spdk_nvme_qpair_process_completions(qpair, 0);
} }
static void
blockdev_nvme_poll_adminq(void *arg)
{
struct spdk_nvme_ctrlr *ctrlr = arg;
spdk_nvme_ctrlr_process_admin_completions(ctrlr);
}
static int static int
blockdev_nvme_destruct(struct spdk_bdev *bdev) blockdev_nvme_destruct(struct spdk_bdev *bdev)
{ {
@ -526,6 +537,10 @@ attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
dev->id = nvme_controller_index++; dev->id = nvme_controller_index++;
nvme_ctrlr_initialize_blockdevs(dev, nvme_luns_per_ns, dev->id); nvme_ctrlr_initialize_blockdevs(dev, nvme_luns_per_ns, dev->id);
spdk_poller_register(&dev->adminq_timer_poller, blockdev_nvme_poll_adminq, ctrlr,
spdk_app_get_current_core(), g_nvme_adminq_poll_timeout_us);
spdk_io_device_register(ctrlr, blockdev_nvme_create_cb, blockdev_nvme_destroy_cb, spdk_io_device_register(ctrlr, blockdev_nvme_create_cb, blockdev_nvme_destroy_cb,
sizeof(struct nvme_io_channel)); sizeof(struct nvme_io_channel));
TAILQ_INSERT_TAIL(&g_nvme_devices, dev, tailq); TAILQ_INSERT_TAIL(&g_nvme_devices, dev, tailq);
@ -658,6 +673,11 @@ nvme_library_init(void)
g_timeout = 0; g_timeout = 0;
} }
g_nvme_adminq_poll_timeout_us = spdk_conf_section_get_intval(sp, "AdminPollRate");
if (g_nvme_adminq_poll_timeout_us <= 0) {
g_nvme_adminq_poll_timeout_us = 1000000;
}
return spdk_bdev_nvme_create(&probe_ctx); return spdk_bdev_nvme_create(&probe_ctx);
} }
@ -669,6 +689,7 @@ nvme_library_fini(void)
while (!TAILQ_EMPTY(&g_nvme_devices)) { while (!TAILQ_EMPTY(&g_nvme_devices)) {
dev = TAILQ_FIRST(&g_nvme_devices); dev = TAILQ_FIRST(&g_nvme_devices);
TAILQ_REMOVE(&g_nvme_devices, dev, tailq); TAILQ_REMOVE(&g_nvme_devices, dev, tailq);
spdk_poller_unregister(&dev->adminq_timer_poller, NULL);
spdk_nvme_detach(dev->ctrlr); spdk_nvme_detach(dev->ctrlr);
free(dev); free(dev);
} }
@ -898,6 +919,9 @@ blockdev_nvme_get_spdk_running_config(FILE *fp)
if (lun_size_in_mb != 0) { if (lun_size_in_mb != 0) {
fprintf(fp, " LunSizeInMB %d\n", lun_size_in_mb); fprintf(fp, " LunSizeInMB %d\n", lun_size_in_mb);
} }
fprintf(fp, " # Set how often the admin queue is polled for asynchronous events.\n"
" # Units in microseconds.\n"
" AdminPollRate %d\n", g_nvme_adminq_poll_timeout_us);
} }
SPDK_LOG_REGISTER_TRACE_FLAG("bdev_nvme", SPDK_TRACE_BDEV_NVME) SPDK_LOG_REGISTER_TRACE_FLAG("bdev_nvme", SPDK_TRACE_BDEV_NVME)