bdevperf: Add DIF/DIX verification for read I/O at completion

If verify is enabled, both data and metadata are checked. However,
if verify is disabled, read data is not checked even if dif_check_flags
is not zero. Add DIF/DIX verification for read I/O at completion.

Signed-off-by: Shuhei Matsumoto <smatsumoto@nvidia.com>
Change-Id: Ibde44bc244f84e40cef68653978191363acca5ce
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/15074
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com>
Reviewed-by: Krzysztof Karas <krzysztof.karas@intel.com>
Community-CI: Mellanox Build Bot
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Shuhei Matsumoto 2022-10-19 21:10:02 +09:00 committed by Tomasz Zawadzki
parent 00bff560dd
commit 02e1823a38

View File

@ -506,6 +506,47 @@ bdevperf_abort_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg
bdevperf_end_task(task); bdevperf_end_task(task);
} }
static int
bdevperf_verify_dif(struct bdevperf_task *task, struct iovec *iovs, int iovcnt)
{
struct bdevperf_job *job = task->job;
struct spdk_bdev *bdev = job->bdev;
struct spdk_dif_ctx dif_ctx;
struct spdk_dif_error err_blk = {};
int rc;
rc = spdk_dif_ctx_init(&dif_ctx,
spdk_bdev_get_block_size(bdev),
spdk_bdev_get_md_size(bdev),
spdk_bdev_is_md_interleaved(bdev),
spdk_bdev_is_dif_head_of_md(bdev),
spdk_bdev_get_dif_type(bdev),
job->dif_check_flags,
task->offset_blocks, 0, 0, 0, 0);
if (rc != 0) {
fprintf(stderr, "Initialization of DIF context failed\n");
return rc;
}
if (spdk_bdev_is_md_interleaved(bdev)) {
rc = spdk_dif_verify(iovs, iovcnt, job->io_size_blocks, &dif_ctx, &err_blk);
} else {
struct iovec md_iov = {
.iov_base = task->md_buf,
.iov_len = spdk_bdev_get_md_size(bdev) * job->io_size_blocks,
};
rc = spdk_dix_verify(iovs, iovcnt, &md_iov, job->io_size_blocks, &dif_ctx, &err_blk);
}
if (rc != 0) {
fprintf(stderr, "DIF/DIX error detected. type=%d, offset=%" PRIu32 "\n",
err_blk.err_type, err_blk.err_offset);
}
return rc;
}
static void static void
bdevperf_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) bdevperf_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
{ {
@ -515,6 +556,7 @@ bdevperf_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
int iovcnt; int iovcnt;
bool md_check; bool md_check;
uint64_t offset_in_ios; uint64_t offset_in_ios;
int rc;
job = task->job; job = task->job;
md_check = spdk_bdev_get_dif_type(job->bdev) == SPDK_DIF_DISABLE; md_check = spdk_bdev_get_dif_type(job->bdev) == SPDK_DIF_DISABLE;
@ -543,6 +585,24 @@ bdevperf_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
bdevperf_job_drain(job); bdevperf_job_drain(job);
g_run_rc = -1; g_run_rc = -1;
} }
} else if (job->dif_check_flags != 0) {
if (task->io_type == SPDK_BDEV_IO_TYPE_READ && spdk_bdev_get_md_size(job->bdev) != 0) {
spdk_bdev_io_get_iovec(bdev_io, &iovs, &iovcnt);
assert(iovcnt == 1);
assert(iovs != NULL);
rc = bdevperf_verify_dif(task, iovs, iovcnt);
if (rc != 0) {
printf("DIF error detected. task offset: %" PRIu64 " on job bdev=%s\n",
task->offset_blocks, job->name);
success = false;
if (!job->reset && !job->continue_on_failure) {
bdevperf_job_drain(job);
g_run_rc = -1;
g_error_to_exit = true;
}
}
}
} }
job->current_queue_depth--; job->current_queue_depth--;