nvme_perf: Support NVMe formatted with DIX
This patch adds DIF generation and verification for NVMe namespace formatted with DIX. Change-Id: Ic67c88c485aacffa40fd0c73ba164f2cb1f88991 Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Reviewed-on: https://review.gerrithub.io/c/439969 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
parent
35cdee26ad
commit
21b049f939
@ -140,6 +140,7 @@ struct ns_worker_ctx {
|
||||
struct perf_task {
|
||||
struct ns_worker_ctx *ns_ctx;
|
||||
struct iovec iov;
|
||||
struct iovec md_iov;
|
||||
uint64_t submit_tsc;
|
||||
bool is_read;
|
||||
struct spdk_dif_ctx dif_ctx;
|
||||
@ -410,7 +411,7 @@ static void io_complete(void *ctx, const struct spdk_nvme_cpl *cpl);
|
||||
static void
|
||||
nvme_setup_payload(struct perf_task *task, uint8_t pattern)
|
||||
{
|
||||
uint32_t max_io_size_bytes;
|
||||
uint32_t max_io_size_bytes, max_io_md_size;
|
||||
|
||||
/* maximum extended lba format size from all active namespace,
|
||||
* it's same with g_io_size_bytes for namespace without metadata.
|
||||
@ -423,6 +424,17 @@ nvme_setup_payload(struct perf_task *task, uint8_t pattern)
|
||||
exit(1);
|
||||
}
|
||||
memset(task->iov.iov_base, pattern, task->iov.iov_len);
|
||||
|
||||
max_io_md_size = g_max_io_md_size * g_max_io_size_blocks;
|
||||
if (max_io_md_size != 0) {
|
||||
task->md_iov.iov_base = spdk_dma_zmalloc(max_io_md_size, g_io_align, NULL);
|
||||
task->md_iov.iov_len = max_io_md_size;
|
||||
if (task->md_iov.iov_base == NULL) {
|
||||
fprintf(stderr, "task->md_buf spdk_dma_zmalloc failed\n");
|
||||
spdk_dma_free(task->iov.iov_base);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
@ -430,15 +442,25 @@ nvme_submit_io(struct perf_task *task, struct ns_worker_ctx *ns_ctx,
|
||||
struct ns_entry *entry, uint64_t offset_in_ios)
|
||||
{
|
||||
uint64_t lba;
|
||||
bool dif_enabled;
|
||||
int rc;
|
||||
|
||||
enum dif_mode {
|
||||
DIF_MODE_NONE = 0,
|
||||
DIF_MODE_DIF = 1,
|
||||
DIF_MODE_DIX = 2,
|
||||
} mode = DIF_MODE_NONE;
|
||||
|
||||
lba = offset_in_ios * entry->io_size_blocks;
|
||||
|
||||
dif_enabled = entry->md_size != 0 && entry->md_interleave &&
|
||||
!(entry->io_flags & SPDK_NVME_IO_FLAGS_PRACT);
|
||||
if (entry->md_size != 0 && !(entry->io_flags & SPDK_NVME_IO_FLAGS_PRACT)) {
|
||||
if (entry->md_interleave) {
|
||||
mode = DIF_MODE_DIF;
|
||||
} else {
|
||||
mode = DIF_MODE_DIX;
|
||||
}
|
||||
}
|
||||
|
||||
if (dif_enabled) {
|
||||
if (mode != DIF_MODE_NONE) {
|
||||
rc = spdk_dif_ctx_init(&task->dif_ctx, entry->block_size, entry->md_size,
|
||||
entry->md_interleave, entry->pi_loc,
|
||||
(enum spdk_dif_type)entry->pi_type, entry->io_flags,
|
||||
@ -451,22 +473,34 @@ nvme_submit_io(struct perf_task *task, struct ns_worker_ctx *ns_ctx,
|
||||
|
||||
if (task->is_read) {
|
||||
return spdk_nvme_ns_cmd_read_with_md(entry->u.nvme.ns, ns_ctx->u.nvme.qpair,
|
||||
task->iov.iov_base, NULL,
|
||||
task->iov.iov_base, task->md_iov.iov_base,
|
||||
lba,
|
||||
entry->io_size_blocks, io_complete,
|
||||
task, entry->io_flags,
|
||||
task->dif_ctx.apptag_mask, task->dif_ctx.app_tag);
|
||||
} else {
|
||||
if (dif_enabled) {
|
||||
switch (mode) {
|
||||
case DIF_MODE_DIF:
|
||||
rc = spdk_dif_generate(&task->iov, 1, entry->io_size_blocks, &task->dif_ctx);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "Generation of DIF failed\n");
|
||||
return rc;
|
||||
}
|
||||
break;
|
||||
case DIF_MODE_DIX:
|
||||
rc = spdk_dix_generate(&task->iov, 1, &task->md_iov, entry->io_size_blocks,
|
||||
&task->dif_ctx);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "Generation of DIX failed\n");
|
||||
return rc;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return spdk_nvme_ns_cmd_write_with_md(entry->u.nvme.ns, ns_ctx->u.nvme.qpair,
|
||||
task->iov.iov_base, NULL,
|
||||
task->iov.iov_base, task->md_iov.iov_base,
|
||||
lba,
|
||||
entry->io_size_blocks, io_complete,
|
||||
task, entry->io_flags,
|
||||
@ -486,14 +520,25 @@ nvme_verify_io(struct perf_task *task, struct ns_entry *entry)
|
||||
struct spdk_dif_error err_blk = {};
|
||||
int rc;
|
||||
|
||||
if (task->is_read && entry->md_size != 0 && entry->md_interleave &&
|
||||
!(entry->io_flags & SPDK_NVME_IO_FLAGS_PRACT)) {
|
||||
if (!task->is_read || entry->md_size == 0 ||
|
||||
(entry->io_flags & SPDK_NVME_IO_FLAGS_PRACT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry->md_interleave) {
|
||||
rc = spdk_dif_verify(&task->iov, 1, entry->io_size_blocks, &task->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);
|
||||
}
|
||||
} else {
|
||||
rc = spdk_dix_verify(&task->iov, 1, &task->md_iov, entry->io_size_blocks,
|
||||
&task->dif_ctx, &err_blk);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "DIX error detected. type=%d, offset=%" PRIu32 "\n",
|
||||
err_blk.err_type, err_blk.err_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -795,6 +840,7 @@ task_complete(struct perf_task *task)
|
||||
*/
|
||||
if (ns_ctx->is_draining) {
|
||||
spdk_dma_free(task->iov.iov_base);
|
||||
spdk_dma_free(task->md_iov.iov_base);
|
||||
free(task);
|
||||
} else {
|
||||
submit_single_io(task);
|
||||
|
Loading…
Reference in New Issue
Block a user