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 static void
bdev_nvme_poll(void *arg) 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 static void
@ -235,20 +237,65 @@ bdev_nvme_flush(struct nvme_bdev *nbdev, struct nvme_bdev_io *bio,
return 0; 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 static int
bdev_nvme_reset(struct nvme_bdev *nbdev, struct nvme_bdev_io *bio) bdev_nvme_reset(struct nvme_bdev *nbdev, struct nvme_bdev_io *bio)
{ {
int rc; /* First, delete all NVMe I/O queue pairs. */
enum spdk_bdev_io_status status; spdk_for_each_channel(nbdev->nvme_ctrlr->ctrlr,
_bdev_nvme_reset_destroy_qpair,
bio,
_bdev_nvme_reset);
status = SPDK_BDEV_IO_STATUS_SUCCESS; return 0;
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;
} }
static int static int
@ -278,6 +325,12 @@ bdev_nvme_get_buf_cb(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
static int static int
_bdev_nvme_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io) _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) { switch (bdev_io->type) {
case SPDK_BDEV_IO_TYPE_READ: case SPDK_BDEV_IO_TYPE_READ:
spdk_bdev_io_get_buf(bdev_io, bdev_nvme_get_buf_cb); 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; 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); spdk_env_get_current_core(), 0);
return 0; return 0;
} }