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 <benjamin.walker@intel.com>
Reviewed-on: https://review.gerrithub.io/364682
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Ben Walker 2017-06-08 11:49:22 -07:00 committed by Jim Harris
parent 8025dee513
commit e6d5f6c418

View File

@ -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;
}