diff --git a/examples/nvme/fio_plugin/fio_plugin.c b/examples/nvme/fio_plugin/fio_plugin.c index bf7d50f4e..c2fbe622f 100644 --- a/examples/nvme/fio_plugin/fio_plugin.c +++ b/examples/nvme/fio_plugin/fio_plugin.c @@ -38,7 +38,7 @@ #include "spdk/string.h" #include "spdk/log.h" #include "spdk/endian.h" -#include "spdk/crc16.h" +#include "spdk/dif.h" #include "config-host.h" #include "fio.h" @@ -66,11 +66,10 @@ struct spdk_fio_options { struct spdk_fio_request { struct io_u *io; /** Offset in current iovec, fio only uses 1 vector */ - uint32_t iov_offset; + uint32_t iov_offset; - /** Application tag and its mask for NVMe PI */ - uint16_t appmask; - uint16_t apptag; + /** Context for NVMe PI */ + struct spdk_dif_ctx dif_ctx; struct spdk_fio_thread *fio_thread; }; @@ -219,12 +218,6 @@ fio_do_nvme_pi_check(struct spdk_fio_qpair *fio_qpair) return false; } - /* Type3 don't support REFTAG */ - if (spdk_nvme_ns_get_pi_type(ns) == - SPDK_NVME_FMT_NVM_PROTECTION_TYPE3) { - return false; - } - return true; } @@ -537,104 +530,61 @@ static void spdk_fio_io_u_free(struct thread_data *td, struct io_u *io_u) static void fio_extended_lba_setup_pi(struct spdk_fio_qpair *fio_qpair, struct io_u *io_u) { - struct spdk_nvme_ns *ns = NULL; + struct spdk_nvme_ns *ns = fio_qpair->ns; struct spdk_fio_request *fio_req = io_u->engine_data; - struct spdk_nvme_protection_info *pi; - uint16_t crc16; - uint32_t i, md_size, sector_size, pi_offset, extended_lba_size, lba_count; + uint32_t md_size, extended_lba_size, lba_count; uint64_t lba; + struct iovec iov; + int rc; - ns = fio_qpair->ns; - - sector_size = spdk_nvme_ns_get_sector_size(ns); + extended_lba_size = spdk_nvme_ns_get_extended_sector_size(ns); md_size = spdk_nvme_ns_get_md_size(ns); - extended_lba_size = sector_size + md_size; lba = io_u->offset / extended_lba_size; lba_count = io_u->xfer_buflen / extended_lba_size; - if (fio_qpair->io_flags & SPDK_NVME_IO_FLAGS_PRCHK_APPTAG) { - /* Let's use number of lbas for application tag */ - fio_req->appmask = 0xffff; - fio_req->apptag = FIO_NVME_PI_APPTAG; + rc = spdk_dif_ctx_init(&fio_req->dif_ctx, extended_lba_size, md_size, + true, false, + (enum spdk_dif_type)spdk_nvme_ns_get_pi_type(ns), + fio_qpair->io_flags, lba, 0xFFFF, FIO_NVME_PI_APPTAG); + if (rc != 0) { + fprintf(stderr, "Initialization of DIF context failed\n"); + return; } - for (i = 0; i < lba_count; i++) { - pi_offset = (extended_lba_size * (i + 1)) - 8; - pi = (struct spdk_nvme_protection_info *)(io_u->buf + pi_offset); - memset(pi, 0, sizeof(*pi)); + if (io_u->ddir != DDIR_WRITE) { + return; + } - if (io_u->ddir == DDIR_WRITE) { - if (fio_qpair->io_flags & SPDK_NVME_IO_FLAGS_PRCHK_GUARD) { - /* CRC buffer should not include PI */ - crc16 = spdk_crc16_t10dif(0, io_u->buf + extended_lba_size * i, - extended_lba_size - 8); - to_be16(&pi->guard, crc16); - } - if (fio_qpair->io_flags & SPDK_NVME_IO_FLAGS_PRCHK_APPTAG) { - /* Let's use number of lbas for application tag */ - to_be16(&pi->app_tag, FIO_NVME_PI_APPTAG); - } - if (fio_qpair->io_flags & SPDK_NVME_IO_FLAGS_PRCHK_REFTAG) { - to_be32(&pi->ref_tag, (uint32_t)lba + i); - } - } + iov.iov_base = io_u->buf; + iov.iov_len = io_u->xfer_buflen; + rc = spdk_dif_generate(&iov, 1, lba_count, &fio_req->dif_ctx); + if (rc != 0) { + fprintf(stderr, "Generation of DIF failed\n"); } } static void fio_extended_lba_verify_pi(struct spdk_fio_qpair *fio_qpair, struct io_u *io_u) { - struct spdk_nvme_ns *ns = NULL; - struct spdk_nvme_protection_info *pi; - uint16_t crc16, guard, app_tag; - uint32_t i, md_size, sector_size, pi_offset, extended_lba_size, ref_tag, lba_count; - uint64_t lba; + struct spdk_nvme_ns *ns = fio_qpair->ns; + struct spdk_fio_request *fio_req = io_u->engine_data; + uint32_t lba_count; + struct iovec iov; + struct spdk_dif_error err_blk = {}; + int rc; - ns = fio_qpair->ns; - sector_size = spdk_nvme_ns_get_sector_size(ns); - md_size = spdk_nvme_ns_get_md_size(ns); - extended_lba_size = sector_size + md_size; - lba = io_u->offset / extended_lba_size; - lba_count = io_u->xfer_buflen / extended_lba_size; + if (io_u->ddir != DDIR_READ) { + return; + } - for (i = 0; i < lba_count; i++) { - pi_offset = (extended_lba_size * (i + 1)) - 8; - pi = (struct spdk_nvme_protection_info *)(io_u->buf + pi_offset); + iov.iov_base = io_u->buf; + iov.iov_len = io_u->xfer_buflen; + lba_count = io_u->xfer_buflen / spdk_nvme_ns_get_extended_sector_size(ns); - if (fio_qpair->io_flags & SPDK_NVME_IO_FLAGS_PRCHK_GUARD) { - /* CRC buffer should not include last 8 bytes of PI */ - crc16 = spdk_crc16_t10dif(0, io_u->buf + extended_lba_size * i, - extended_lba_size - 8); - to_be16(&guard, crc16); - if (pi->guard != guard) { - fprintf(stdout, "Get Guard Error LBA 0x%16.16"PRIx64"," - " Expected 0x%04x but returned with 0x%04x," - " may read the LBA without write it first\n", - lba + i, guard, pi->guard); - } - - } - if (fio_qpair->io_flags & SPDK_NVME_IO_FLAGS_PRCHK_APPTAG) { - /* Previously we used the number of lbas as - * application tag for writes - */ - to_be16(&app_tag, FIO_NVME_PI_APPTAG); - if (pi->app_tag != app_tag) { - fprintf(stdout, "Get Application Tag Error LBA 0x%16.16"PRIx64"," - " Expected 0x%04x but returned with 0x%04x," - " may read the LBA without write it first\n", - lba + i, app_tag, pi->app_tag); - } - } - if (fio_qpair->io_flags & SPDK_NVME_IO_FLAGS_PRCHK_REFTAG) { - to_be32(&ref_tag, (uint32_t)lba + i); - if (pi->ref_tag != ref_tag) { - fprintf(stdout, "Get Reference Tag Error LBA 0x%16.16"PRIx64"," - " Expected 0x%08x but returned with 0x%08x," - " may read the LBA without write it first\n", - lba + i, ref_tag, pi->ref_tag); - } - } + rc = spdk_dif_verify(&iov, 1, lba_count, &fio_req->dif_ctx, &err_blk); + if (rc != 0) { + fprintf(stderr, "DIF error detected. type=%d, offset=%" PRIu32 "\n", + err_blk.err_type, err_blk.err_offset); } } @@ -691,6 +641,7 @@ spdk_fio_queue(struct thread_data *td, struct io_u *io_u) struct spdk_fio_request *fio_req = io_u->engine_data; struct spdk_fio_qpair *fio_qpair; struct spdk_nvme_ns *ns = NULL; + struct spdk_dif_ctx *dif_ctx = &fio_req->dif_ctx; uint32_t block_size; uint64_t lba; uint32_t lba_count; @@ -723,24 +674,24 @@ spdk_fio_queue(struct thread_data *td, struct io_u *io_u) if (!g_spdk_enable_sgl) { rc = spdk_nvme_ns_cmd_read_with_md(ns, fio_qpair->qpair, io_u->buf, NULL, lba, lba_count, spdk_fio_completion_cb, fio_req, - fio_qpair->io_flags, fio_req->appmask, fio_req->apptag); + dif_ctx->dif_flags, dif_ctx->apptag_mask, dif_ctx->app_tag); } else { rc = spdk_nvme_ns_cmd_readv_with_md(ns, fio_qpair->qpair, lba, - lba_count, spdk_fio_completion_cb, fio_req, fio_qpair->io_flags, + lba_count, spdk_fio_completion_cb, fio_req, dif_ctx->dif_flags, spdk_nvme_io_reset_sgl, spdk_nvme_io_next_sge, NULL, - fio_req->appmask, fio_req->apptag); + dif_ctx->apptag_mask, dif_ctx->app_tag); } break; case DDIR_WRITE: if (!g_spdk_enable_sgl) { rc = spdk_nvme_ns_cmd_write_with_md(ns, fio_qpair->qpair, io_u->buf, NULL, lba, lba_count, spdk_fio_completion_cb, fio_req, - fio_qpair->io_flags, fio_req->appmask, fio_req->apptag); + dif_ctx->dif_flags, dif_ctx->apptag_mask, dif_ctx->app_tag); } else { rc = spdk_nvme_ns_cmd_writev_with_md(ns, fio_qpair->qpair, lba, - lba_count, spdk_fio_completion_cb, fio_req, fio_qpair->io_flags, + lba_count, spdk_fio_completion_cb, fio_req, dif_ctx->dif_flags, spdk_nvme_io_reset_sgl, spdk_nvme_io_next_sge, NULL, - fio_req->appmask, fio_req->apptag); + dif_ctx->apptag_mask, dif_ctx->app_tag); } break; default: