Commit 02e1823a authored by Shuhei Matsumoto's avatar Shuhei Matsumoto Committed by Tomasz Zawadzki
Browse files

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: default avatarShuhei Matsumoto <smatsumoto@nvidia.com>
Change-Id: Ibde44bc244f84e40cef68653978191363acca5ce
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/15074


Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-by: default avatarAleksey Marchuk <alexeymar@nvidia.com>
Reviewed-by: default avatarKrzysztof Karas <krzysztof.karas@intel.com>
Community-CI: Mellanox Build Bot
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
parent 00bff560
Loading
Loading
Loading
Loading
+60 −0
Original line number Diff line number Diff line
@@ -506,6 +506,47 @@ bdevperf_abort_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg
	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
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;
	bool			md_check;
	uint64_t		offset_in_ios;
	int			rc;

	job = task->job;
	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);
			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--;