Commit 8696cd42 authored by Shuhei Matsumoto's avatar Shuhei Matsumoto Committed by Ben Walker
Browse files

dif: Add seed value for guard to avoid 0 in case of all zero data.



Allow user to add seed value for guard compuation to DIF context.
This will avoid the guard being zero in case of all zero data.

NVMe controller doesn't support seed value for guard computation
explicitly, and hence if we want to use such a seed value in
NVMe controller, we have to format metadata more than 8 byte,
and add seed value into the reserved metadata field.

But some popular iSCSI/FC HBAs and SAS controllers have supported
seed value for guard computation, and so supporting seed value
in the SPDK DIF library is very helpful for some use cases.

Hence this patch makes the DIF library possible to specify seed
value for those use cases.

Change-Id: I7e9e87cb441bf263e64605c7820409fdc22dd977
Signed-off-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/c/444334


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarwuzhouhui <wuzhouhui@kingsoft.com>
parent fda97cff
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -545,7 +545,7 @@ fio_extended_lba_setup_pi(struct spdk_fio_qpair *fio_qpair, struct io_u *io_u)
	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);
			       fio_qpair->io_flags, lba, 0xFFFF, FIO_NVME_PI_APPTAG, 0);
	if (rc != 0) {
		fprintf(stderr, "Initialization of DIF context failed\n");
		return;
+1 −1
Original line number Diff line number Diff line
@@ -469,7 +469,7 @@ nvme_submit_io(struct perf_task *task, struct ns_worker_ctx *ns_ctx,
		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,
				       lba, 0xFFFF, (uint16_t)entry->io_size_blocks);
				       lba, 0xFFFF, (uint16_t)entry->io_size_blocks, 0);
		if (rc != 0) {
			fprintf(stderr, "Initialization of DIF context failed\n");
			exit(1);
+6 −1
Original line number Diff line number Diff line
@@ -91,6 +91,9 @@ struct spdk_dif_ctx {

	/* Application tag mask */
	uint16_t		apptag_mask;

	/* Seed value for guard computation */
	uint16_t		guard_seed;
};

/** DIF error information */
@@ -124,12 +127,14 @@ struct spdk_dif_error {
 * starting block address.
 * \param apptag_mask Application tag mask.
 * \param app_tag Application tag.
 * \param guard_seed Seed value for guard computation.
 *
 * \return 0 on success and negated errno otherwise.
 */
int spdk_dif_ctx_init(struct spdk_dif_ctx *ctx, uint32_t block_size, uint32_t md_size,
		      bool md_interleave, bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags,
		      uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag);
		      uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag,
		      uint16_t guard_seed);

/**
 * Generate DIF for extended LBA payload.
+1 −1
Original line number Diff line number Diff line
@@ -1604,7 +1604,7 @@ bdev_nvme_verify_pi_error(struct spdk_bdev_io *bdev_io)
	rc = spdk_dif_ctx_init(&dif_ctx,
			       bdev->blocklen, bdev->md_len, bdev->md_interleave,
			       bdev->dif_is_head_of_md, bdev->dif_type, bdev->dif_check_flags,
			       bdev_io->u.bdev.offset_blocks, 0, 0);
			       bdev_io->u.bdev.offset_blocks, 0, 0, 0);
	if (rc != 0) {
		SPDK_ERRLOG("Initialization of DIF context failed\n");
		return;
+33 −19
Original line number Diff line number Diff line
@@ -184,7 +184,8 @@ _get_guard_interval(uint32_t block_size, uint32_t md_size, bool dif_loc, bool md
int
spdk_dif_ctx_init(struct spdk_dif_ctx *ctx, uint32_t block_size, uint32_t md_size,
		  bool md_interleave, bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags,
		  uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag)
		  uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag,
		  uint16_t guard_seed)
{
	if (md_size < sizeof(struct spdk_dif)) {
		SPDK_ERRLOG("Metadata size is smaller than DIF size.\n");
@@ -216,6 +217,7 @@ spdk_dif_ctx_init(struct spdk_dif_ctx *ctx, uint32_t block_size, uint32_t md_siz
	ctx->init_ref_tag = init_ref_tag;
	ctx->apptag_mask = apptag_mask;
	ctx->app_tag = app_tag;
	ctx->guard_seed = guard_seed;

	return 0;
}
@@ -266,7 +268,7 @@ dif_generate(struct iovec *iovs, int iovcnt, uint32_t num_blocks,
		_iov_iter_get_buf(&iter, &buf, NULL);

		if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
			guard = spdk_crc16_t10dif(0, buf, ctx->guard_interval);
			guard = spdk_crc16_t10dif(ctx->guard_seed, buf, ctx->guard_interval);
		}

		_dif_generate(buf + ctx->guard_interval, guard, offset_blocks, ctx);
@@ -282,10 +284,12 @@ _dif_generate_split(struct _iov_iter *iter, uint32_t offset_blocks,
{
	uint32_t offset_in_block, offset_in_dif, buf_len;
	void *buf;
	uint16_t guard;
	uint16_t guard = 0;
	struct spdk_dif dif = {};

	guard = 0;
	if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
		guard = ctx->guard_seed;
	}
	offset_in_block = 0;

	while (offset_in_block < ctx->block_size) {
@@ -491,7 +495,7 @@ dif_verify(struct iovec *iovs, int iovcnt, uint32_t num_blocks,
		_iov_iter_get_buf(&iter, &buf, NULL);

		if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
			guard = spdk_crc16_t10dif(0, buf, ctx->guard_interval);
			guard = spdk_crc16_t10dif(ctx->guard_seed, buf, ctx->guard_interval);
		}

		rc = _dif_verify(buf + ctx->guard_interval, guard, offset_blocks, ctx, err_blk);
@@ -512,10 +516,12 @@ _dif_verify_split(struct _iov_iter *iter, uint32_t offset_blocks,
{
	uint32_t offset_in_block, offset_in_dif, buf_len;
	void *buf;
	uint16_t guard;
	uint16_t guard = 0;
	struct spdk_dif dif = {};

	guard = 0;
	if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
		guard = ctx->guard_seed;
	}
	offset_in_block = 0;

	while (offset_in_block < ctx->block_size) {
@@ -610,7 +616,7 @@ dif_generate_copy(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,

		guard = 0;
		if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
			guard = spdk_crc16_t10dif_copy(0, dst, src, data_block_size);
			guard = spdk_crc16_t10dif_copy(ctx->guard_seed, dst, src, data_block_size);
			guard = spdk_crc16_t10dif(guard, dst + data_block_size,
						  ctx->guard_interval - data_block_size);
		} else {
@@ -630,14 +636,16 @@ _dif_generate_copy_split(struct _iov_iter *src_iter, struct _iov_iter *dst_iter,
			 uint32_t offset_blocks, const struct spdk_dif_ctx *ctx)
{
	uint32_t offset_in_block, src_len, data_block_size;
	uint16_t guard;
	uint16_t guard = 0;
	void *src, *dst;

	_iov_iter_get_buf(dst_iter, &dst, NULL);

	data_block_size = ctx->block_size - ctx->md_size;

	guard = 0;
	if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
		guard = ctx->guard_seed;
	}
	offset_in_block = 0;

	while (offset_in_block < data_block_size) {
@@ -736,7 +744,7 @@ dif_verify_copy(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,

		guard = 0;
		if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
			guard = spdk_crc16_t10dif_copy(0, dst, src, data_block_size);
			guard = spdk_crc16_t10dif_copy(ctx->guard_seed, dst, src, data_block_size);
			guard = spdk_crc16_t10dif(guard, src + data_block_size,
						  ctx->guard_interval - data_block_size);
		} else {
@@ -762,14 +770,16 @@ _dif_verify_copy_split(struct _iov_iter *src_iter, struct _iov_iter *dst_iter,
		       struct spdk_dif_error *err_blk)
{
	uint32_t offset_in_block, dst_len, data_block_size;
	uint16_t guard;
	uint16_t guard = 0;
	void *src, *dst;

	_iov_iter_get_buf(src_iter, &src, NULL);

	data_block_size = ctx->block_size - ctx->md_size;

	guard = 0;
	if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
		guard = ctx->guard_seed;
	}
	offset_in_block = 0;

	while (offset_in_block < data_block_size) {
@@ -1015,7 +1025,7 @@ dix_generate(struct iovec *iovs, int iovcnt, struct iovec *md_iov,

		guard = 0;
		if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
			guard = spdk_crc16_t10dif(0, data_buf, ctx->block_size);
			guard = spdk_crc16_t10dif(ctx->guard_seed, data_buf, ctx->block_size);
			guard = spdk_crc16_t10dif(guard, md_buf, ctx->guard_interval);
		}

@@ -1032,12 +1042,14 @@ _dix_generate_split(struct _iov_iter *data_iter, struct _iov_iter *md_iter,
		    uint32_t offset_blocks, const struct spdk_dif_ctx *ctx)
{
	uint32_t offset_in_block, data_buf_len;
	uint16_t guard;
	uint16_t guard = 0;
	void *data_buf, *md_buf;

	_iov_iter_get_buf(md_iter, &md_buf, NULL);

	guard = 0;
	if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
		guard = ctx->guard_seed;
	}
	offset_in_block = 0;

	while (offset_in_block < ctx->block_size) {
@@ -1123,7 +1135,7 @@ dix_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov,

		guard = 0;
		if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
			guard = spdk_crc16_t10dif(0, data_buf, ctx->block_size);
			guard = spdk_crc16_t10dif(ctx->guard_seed, data_buf, ctx->block_size);
			guard = spdk_crc16_t10dif(guard, md_buf, ctx->guard_interval);
		}

@@ -1146,12 +1158,14 @@ _dix_verify_split(struct _iov_iter *data_iter, struct _iov_iter *md_iter,
		  struct spdk_dif_error *err_blk)
{
	uint32_t offset_in_block, data_buf_len;
	uint16_t guard;
	uint16_t guard = 0;
	void *data_buf, *md_buf;

	_iov_iter_get_buf(md_iter, &md_buf, NULL);

	guard = 0;
	if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
		guard = ctx->guard_seed;
	}
	offset_in_block = 0;

	while (offset_in_block < ctx->block_size) {
Loading