From e6d5f6c4181ea865323b4f35981655766d66370b Mon Sep 17 00:00:00 2001 From: Ben Walker Date: Thu, 8 Jun 2017 11:49:22 -0700 Subject: [PATCH] bdev/nvme: Delete+Recreate I/O queues around a reset This ensures all I/O will be aborted and that no I/O will be submitted while the reset is ocurring. Change-Id: I0f5c993b91d9be6073c6ddf66ae12010f56f864c Signed-off-by: Ben Walker Reviewed-on: https://review.gerrithub.io/364682 Tested-by: SPDK Automated Test System Reviewed-by: Daniel Verkamp Reviewed-by: Jim Harris --- lib/bdev/nvme/blockdev_nvme.c | 79 +++++++++++++++++++++++++++++------ 1 file changed, 66 insertions(+), 13 deletions(-) diff --git a/lib/bdev/nvme/blockdev_nvme.c b/lib/bdev/nvme/blockdev_nvme.c index c6e155d65..e398b910c 100644 --- a/lib/bdev/nvme/blockdev_nvme.c +++ b/lib/bdev/nvme/blockdev_nvme.c @@ -184,9 +184,11 @@ bdev_nvme_writev(struct nvme_bdev *nbdev, struct spdk_io_channel *ch, static void bdev_nvme_poll(void *arg) { - struct spdk_nvme_qpair *qpair = arg; + struct nvme_io_channel *ch = arg; - spdk_nvme_qpair_process_completions(qpair, 0); + if (ch->qpair != NULL) { + spdk_nvme_qpair_process_completions(ch->qpair, 0); + } } static void @@ -235,20 +237,65 @@ bdev_nvme_flush(struct nvme_bdev *nbdev, struct nvme_bdev_io *bio, return 0; } +static void +_bdev_nvme_reset_done(void *io_device, void *ctx) +{ + spdk_bdev_io_complete(spdk_bdev_io_from_ctx(ctx), SPDK_BDEV_IO_STATUS_SUCCESS); +} + +static void +_bdev_nvme_reset_create_qpair(void *io_device, struct spdk_io_channel *ch, + void *ctx) +{ + struct spdk_nvme_ctrlr *ctrlr = io_device; + struct nvme_io_channel *nvme_ch = spdk_io_channel_get_ctx(ch); + + nvme_ch->qpair = spdk_nvme_ctrlr_alloc_io_qpair(ctrlr, 0); + assert(nvme_ch->qpair != NULL); /* Currently, no good way to handle this error */ +} + +static void +_bdev_nvme_reset(void *io_device, void *ctx) +{ + struct spdk_nvme_ctrlr *ctrlr = io_device; + struct nvme_bdev_io *bio = ctx; + int rc; + + rc = spdk_nvme_ctrlr_reset(ctrlr); + if (rc != 0) { + spdk_bdev_io_complete(spdk_bdev_io_from_ctx(bio), SPDK_BDEV_IO_STATUS_FAILED); + return; + } + + /* Recreate all of the I/O queue pairs */ + spdk_for_each_channel(ctrlr, + _bdev_nvme_reset_create_qpair, + ctx, + _bdev_nvme_reset_done); + + +} + +static void +_bdev_nvme_reset_destroy_qpair(void *io_device, struct spdk_io_channel *ch, + void *ctx) +{ + struct nvme_io_channel *nvme_ch = spdk_io_channel_get_ctx(ch); + + spdk_nvme_ctrlr_free_io_qpair(nvme_ch->qpair); + nvme_ch->qpair = NULL; +} + static int bdev_nvme_reset(struct nvme_bdev *nbdev, struct nvme_bdev_io *bio) { - int rc; - enum spdk_bdev_io_status status; + /* First, delete all NVMe I/O queue pairs. */ + spdk_for_each_channel(nbdev->nvme_ctrlr->ctrlr, + _bdev_nvme_reset_destroy_qpair, + bio, + _bdev_nvme_reset); - status = SPDK_BDEV_IO_STATUS_SUCCESS; - rc = spdk_nvme_ctrlr_reset(nbdev->nvme_ctrlr->ctrlr); - if (rc != 0) { - status = SPDK_BDEV_IO_STATUS_FAILED; - } - - spdk_bdev_io_complete(spdk_bdev_io_from_ctx(bio), status); - return rc; + return 0; } static int @@ -278,6 +325,12 @@ bdev_nvme_get_buf_cb(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io) static int _bdev_nvme_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io) { + struct nvme_io_channel *nvme_ch = spdk_io_channel_get_ctx(ch); + if (nvme_ch->qpair == NULL) { + /* The device is currently resetting */ + return -1; + } + switch (bdev_io->type) { case SPDK_BDEV_IO_TYPE_READ: spdk_bdev_io_get_buf(bdev_io, bdev_nvme_get_buf_cb); @@ -374,7 +427,7 @@ bdev_nvme_create_cb(void *io_device, void *ctx_buf) return -1; } - spdk_poller_register(&ch->poller, bdev_nvme_poll, ch->qpair, + spdk_poller_register(&ch->poller, bdev_nvme_poll, ch, spdk_env_get_current_core(), 0); return 0; }