fio_plugin: Use the new DIF library in FIO plugin

Apply the new DIF library to DIF generation and verification.

Condition to use DIF generation and verification are changed
only about DIF type. DIF type 3 is supported in this patch.

DIX is not supported in this patch.

The case that PI is located to the first 8 bytes of the metadata
is not supported in this patch too to because how to pass PI location
is not fixed yet. But this limitation will not be critical because
PI is located to the last 8 bytes of the metadata by default.

DIF insertion and strip will be required not to destroy data by
DIF generation. But this is still added in the TODO list even after
this patch.

Change-Id: If08bcaaaa9f4e0fb4f373ef844b88b38cfffc6b5
Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/c/441283
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
This commit is contained in:
Shuhei Matsumoto 2019-01-21 14:39:57 +09:00 committed by Darek Stojaczyk
parent fa92414ce4
commit 6e769bec2c

View File

@ -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: