From 5bc79e9c3d72414fab95fa2bfa8b94fee57feb4c Mon Sep 17 00:00:00 2001 From: Isaac Otsiabah Date: Sat, 10 Dec 2016 15:43:18 -0700 Subject: [PATCH] bdev/nvme: add option to reset on I/O timeout Change-Id: I7128a1f2916af8470b0564025f5f30e299ab992b Signed-off-by: Daniel Verkamp --- etc/spdk/iscsi.conf.in | 4 ++++ etc/spdk/nvmf.conf.in | 5 +++++ lib/bdev/nvme/blockdev_nvme.c | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/etc/spdk/iscsi.conf.in b/etc/spdk/iscsi.conf.in index a649e7c95..66ec12fad 100644 --- a/etc/spdk/iscsi.conf.in +++ b/etc/spdk/iscsi.conf.in @@ -106,6 +106,10 @@ # The maximum number of NVMe controllers to claim. Do not include this key to # claim all of them. NumControllers 2 + # Registers the application to receive timeout callback and to reset the controller. + ResetControllerOnTimeout Yes + # Timeout value. + NvmeTimeoutValue 30 # Users may change this section to create a different number or size of # malloc LUNs. diff --git a/etc/spdk/nvmf.conf.in b/etc/spdk/nvmf.conf.in index c23924edd..bd7e7e2c0 100644 --- a/etc/spdk/nvmf.conf.in +++ b/etc/spdk/nvmf.conf.in @@ -64,6 +64,11 @@ # poll. Units in microseconds. AcceptorPollRate 10000 + # Registers the application to receive timeout callback and to reset the controller. + ResetControllerOnTimeout Yes + # Timeout value. + NvmeTimeoutValue 30 + # Define an NVMf Subsystem. # - NQN is required and must be unique. # - Core may be set or not. If set, the specified subsystem will run on diff --git a/lib/bdev/nvme/blockdev_nvme.c b/lib/bdev/nvme/blockdev_nvme.c index f50d8a1a3..19717dad1 100644 --- a/lib/bdev/nvme/blockdev_nvme.c +++ b/lib/bdev/nvme/blockdev_nvme.c @@ -112,6 +112,8 @@ static int nvme_luns_per_ns = 1; static int nvme_controller_index = 0; static int lun_size_in_mb = 0; static int num_controllers = -1; +static int g_reset_controller_on_timeout = 0; +static int g_timeout = 0; static TAILQ_HEAD(, nvme_device) g_nvme_devices = TAILQ_HEAD_INITIALIZER(g_nvme_devices);; @@ -445,6 +447,20 @@ probe_cb(void *cb_ctx, const struct spdk_nvme_probe_info *probe_info, return true; } +static void +blockdev_nvme_timeout_cb(struct spdk_nvme_ctrlr *ctrlr, + struct spdk_nvme_qpair *qpair, void *cb_arg) +{ + int rc; + + SPDK_WARNLOG("Warning: Detected a timeout. ctrlr=%p qpair=%p\n", ctrlr, qpair); + + rc = spdk_nvme_ctrlr_reset(ctrlr); + if (rc) { + SPDK_ERRLOG("resetting controller failed\n"); + } +} + static void attach_cb(void *cb_ctx, const struct spdk_nvme_probe_info *probe_info, struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_ctrlr_opts *opts) @@ -470,6 +486,11 @@ attach_cb(void *cb_ctx, const struct spdk_nvme_probe_info *probe_info, if (ctx->controllers_remaining > 0) { ctx->controllers_remaining--; } + + if (g_reset_controller_on_timeout) { + spdk_nvme_ctrlr_register_timeout_callback(ctrlr, g_timeout, + blockdev_nvme_timeout_cb, NULL); + } } static bool @@ -579,6 +600,17 @@ nvme_library_init(void) probe_ctx.controllers_remaining = num_controllers; + val = spdk_conf_section_get_val(sp, "ResetControllerOnTimeout"); + if (val != NULL) { + if (!strcmp(val, "Yes")) { + g_reset_controller_on_timeout = 1; + } + } + + if ((g_timeout = spdk_conf_section_get_intval(sp, "NvmeTimeoutValue")) < 0) { + g_timeout = 0; + } + return spdk_bdev_nvme_create(&probe_ctx); }