From adf90938b1c426b66c9fc4f178fac92004873a8a Mon Sep 17 00:00:00 2001 From: Maciej Szwed Date: Wed, 15 Jan 2020 09:53:12 +0100 Subject: [PATCH] bdev: Add spdk_bdev_io_get_nvme_fused_status function Added new function for getting NVMe specific return code for fused commands. Also changed one of the return codes in fused commands so that we could distinguish error cases. Signed-off-by: Maciej Szwed Change-Id: I86417ea4f5b8f3e6496162be3d6c6128076e35d4 Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/481666 Community-CI: Broadcom SPDK FC-NVMe CI Tested-by: SPDK CI Jenkins Reviewed-by: Jim Harris Reviewed-by: Shuhei Matsumoto --- CHANGELOG.md | 5 ++++ include/spdk/bdev.h | 17 +++++++++++++ include/spdk/bdev_module.h | 1 + lib/bdev/bdev.c | 50 +++++++++++++++++++++++++++++++++++++- 4 files changed, 72 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36f844f8e..920930334 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -130,6 +130,11 @@ The functions `spdk_reactor_enable_framework_monitor_context_switch()` and `spdk_framework_enable_context_switch_monitor()` and `spdk_framework_context_switch_monitor_enabled()`, respectively. +### bdev + +Added spdk_bdev_io_get_nvme_fused_status function for translating bdev_io status to NVMe status +code for fused compare-and-write operation. + ## v19.10: ### rpc diff --git a/include/spdk/bdev.h b/include/spdk/bdev.h index 477a0e324..1729b9ded 100644 --- a/include/spdk/bdev.h +++ b/include/spdk/bdev.h @@ -1139,6 +1139,9 @@ int spdk_bdev_comparev_blocks_with_md(struct spdk_bdev_desc *desc, struct spdk_i * data and may not be able to directly transfer out of the buffers provided. In * this case, the request may fail. * + * spdk_bdev_io_get_nvme_fused_status() function should be called in callback function + * to get status for the individual operation. + * * \ingroup bdev_io_submit_functions * * \param desc Block device descriptor. @@ -1559,6 +1562,20 @@ void spdk_bdev_get_device_stat(struct spdk_bdev *bdev, struct spdk_bdev_io_stat void spdk_bdev_io_get_nvme_status(const struct spdk_bdev_io *bdev_io, uint32_t *cdw0, int *sct, int *sc); +/** + * Get the status of bdev_io as an NVMe status codes and command specific + * completion queue value for fused operations such as compare-and-write. + * + * \param bdev_io I/O to get the status from. + * \param cdw0 Command specific completion queue value + * \param first_sct Status Code Type return value for the first operation, as defined by the NVMe specification. + * \param first_sc Status Code return value for the first operation, as defined by the NVMe specification. + * \param second_sct Status Code Type return value for the second operation, as defined by the NVMe specification. + * \param second_sc Status Code return value for the second operation, as defined by the NVMe specification. + */ +void spdk_bdev_io_get_nvme_fused_status(const struct spdk_bdev_io *bdev_io, uint32_t *cdw0, + int *first_sct, int *first_sc, int *second_sct, int *second_sc); + /** * Get the status of bdev_io as a SCSI status code. * diff --git a/include/spdk/bdev_module.h b/include/spdk/bdev_module.h index e9bb8f166..9b74ad9d3 100644 --- a/include/spdk/bdev_module.h +++ b/include/spdk/bdev_module.h @@ -222,6 +222,7 @@ struct spdk_bdev_fn_table { /** bdev I/O completion status */ enum spdk_bdev_io_status { + SPDK_BDEV_IO_STATUS_FIRST_FUSED_FAILED = -6, SPDK_BDEV_IO_STATUS_MISCOMPARE = -5, /* * NOMEM should be returned when a bdev module cannot start an I/O because of diff --git a/lib/bdev/bdev.c b/lib/bdev/bdev.c index 23eba9865..99bb4e15d 100644 --- a/lib/bdev/bdev.c +++ b/lib/bdev/bdev.c @@ -3691,7 +3691,7 @@ bdev_compare_and_write_do_compare(void *_bdev_io) if (rc == -ENOMEM) { bdev_queue_io_wait_with_cb(bdev_io, bdev_compare_and_write_do_compare); } else if (rc != 0) { - bdev_io->internal.status = SPDK_BDEV_IO_STATUS_FAILED; + bdev_io->internal.status = SPDK_BDEV_IO_STATUS_FIRST_FUSED_FAILED; bdev_io->internal.cb(bdev_io, false, bdev_io->internal.caller_ctx); } } @@ -4639,6 +4639,54 @@ spdk_bdev_io_get_nvme_status(const struct spdk_bdev_io *bdev_io, uint32_t *cdw0, *cdw0 = bdev_io->internal.error.nvme.cdw0; } +void +spdk_bdev_io_get_nvme_fused_status(const struct spdk_bdev_io *bdev_io, uint32_t *cdw0, + int *first_sct, int *first_sc, int *second_sct, int *second_sc) +{ + assert(first_sct != NULL); + assert(first_sc != NULL); + assert(second_sct != NULL); + assert(second_sc != NULL); + assert(cdw0 != NULL); + + if (bdev_io->internal.status == SPDK_BDEV_IO_STATUS_NVME_ERROR) { + if (bdev_io->internal.error.nvme.sct == SPDK_NVME_SCT_MEDIA_ERROR && + bdev_io->internal.error.nvme.sc == SPDK_NVME_SC_COMPARE_FAILURE) { + *first_sct = bdev_io->internal.error.nvme.sct; + *first_sc = bdev_io->internal.error.nvme.sc; + *second_sct = SPDK_NVME_SCT_GENERIC; + *second_sc = SPDK_NVME_SC_ABORTED_FAILED_FUSED; + } else { + *first_sct = SPDK_NVME_SCT_GENERIC; + *first_sc = SPDK_NVME_SC_SUCCESS; + *second_sct = bdev_io->internal.error.nvme.sct; + *second_sc = bdev_io->internal.error.nvme.sc; + } + } else if (bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS) { + *first_sct = SPDK_NVME_SCT_GENERIC; + *first_sc = SPDK_NVME_SC_SUCCESS; + *second_sct = SPDK_NVME_SCT_GENERIC; + *second_sc = SPDK_NVME_SC_SUCCESS; + } else if (bdev_io->internal.status == SPDK_BDEV_IO_STATUS_FIRST_FUSED_FAILED) { + *first_sct = SPDK_NVME_SCT_GENERIC; + *first_sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; + *second_sct = SPDK_NVME_SCT_GENERIC; + *second_sc = SPDK_NVME_SC_ABORTED_FAILED_FUSED; + } else if (bdev_io->internal.status == SPDK_BDEV_IO_STATUS_MISCOMPARE) { + *first_sct = SPDK_NVME_SCT_MEDIA_ERROR; + *first_sc = SPDK_NVME_SC_COMPARE_FAILURE; + *second_sct = SPDK_NVME_SCT_GENERIC; + *second_sc = SPDK_NVME_SC_ABORTED_FAILED_FUSED; + } else { + *first_sct = SPDK_NVME_SCT_GENERIC; + *first_sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; + *second_sct = SPDK_NVME_SCT_GENERIC; + *second_sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; + } + + *cdw0 = bdev_io->internal.error.nvme.cdw0; +} + struct spdk_thread * spdk_bdev_io_get_thread(struct spdk_bdev_io *bdev_io) {