Commit 466ca6d4 authored by Shuhei Matsumoto's avatar Shuhei Matsumoto Committed by Changpeng Liu
Browse files

dif: Insert DIF into newly read data block by stream fashion



Add an new API spdk_dif_generate_stream() to insert DIF into
the metadata space of newly read data block by stream fashion.

This API is tested by replacing the previous DIF generation such
that DIF is generated once all data was read.

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


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 avatarZiye Yang <ziye.yang@intel.com>
Reviewed-by: default avatarwuzhouhui <wuzhouhui@kingsoft.com>
parent daf2206e
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -285,4 +285,19 @@ int spdk_dif_set_md_interleave_iovs(struct iovec *iovs, int num_iovs,
				    uint32_t data_offset, uint32_t data_len,
				    uint32_t *mapped_len,
				    const struct spdk_dif_ctx *ctx);

/**
 * Generate and insert DIF into metadata space for newly read data block.
 *
 * \param buf Buffer to create extended LBA payload.
 * \param buf_len Length of the buffer to create extended LBA payload.
 * \param offset Offset to the newly read data.
 * \param read_len Length of the newly read data.
 * \param ctx DIF context.
 *
 * \return 0 on success and negated errno otherwise.
 */
int spdk_dif_generate_stream(uint8_t *buf, uint32_t buf_len,
			     uint32_t offset, uint32_t read_len,
			     const struct spdk_dif_ctx *ctx);
#endif /* SPDK_DIF_H */
+39 −0
Original line number Diff line number Diff line
@@ -1370,3 +1370,42 @@ spdk_dif_set_md_interleave_iovs(struct iovec *iovs, int num_iovs,

	return iovcnt;
}

int
spdk_dif_generate_stream(uint8_t *buf, uint32_t buf_len,
			 uint32_t offset, uint32_t read_len,
			 const struct spdk_dif_ctx *ctx)
{
	uint32_t data_block_size, offset_blocks, num_blocks, i;
	uint16_t guard = 0;

	if (buf == NULL) {
		return -EINVAL;
	}

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

	offset_blocks = offset / data_block_size;
	read_len += offset % data_block_size;

	offset = offset_blocks * ctx->block_size;
	num_blocks = read_len / data_block_size;

	if (offset + num_blocks * ctx->block_size > buf_len) {
		return -ERANGE;
	}

	buf += offset;

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

		_dif_generate(buf + ctx->guard_interval, guard, offset_blocks + i, ctx);

		buf += ctx->block_size;
	}

	return 0;
}
+63 −2
Original line number Diff line number Diff line
@@ -1420,6 +1420,9 @@ set_md_interleave_iovs_test(void)
	read_base = ut_readv(0, 1024, dif_iovs, 4);
	CU_ASSERT(read_base == 1024);

	rc = spdk_dif_generate_stream(buf1, (4096 + 128) * 4, 0, 1024, &ctx);
	CU_ASSERT(rc == 0);

	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, buf1, (4096 + 128) * 4,
					     read_base, 4096 * 4, &mapped_len, &ctx);
	CU_ASSERT(rc == 4);
@@ -1432,6 +1435,9 @@ set_md_interleave_iovs_test(void)
	read_base += ut_readv(read_base, 3071, dif_iovs, 4);
	CU_ASSERT(read_base == 4095);

	rc = spdk_dif_generate_stream(buf1, (4096 + 128) * 4, 1024, 3071, &ctx);
	CU_ASSERT(rc == 0);

	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, buf1, (4096 + 128) * 4,
					     read_base, 4096 * 4, &mapped_len, &ctx);
	CU_ASSERT(rc == 4);
@@ -1444,6 +1450,9 @@ set_md_interleave_iovs_test(void)
	read_base += ut_readv(read_base, 1 + 4096 * 2 + 512, dif_iovs, 4);
	CU_ASSERT(read_base == 4096 * 3 + 512);

	rc = spdk_dif_generate_stream(buf1, (4096 + 128) * 4, 4095, 1 + 4096 * 2 + 512, &ctx);
	CU_ASSERT(rc == 0);

	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, buf1, (4096 + 128) * 4,
					     read_base, 4096 * 4, &mapped_len, &ctx);
	CU_ASSERT(rc == 1);
@@ -1453,7 +1462,7 @@ set_md_interleave_iovs_test(void)
	read_base += ut_readv(read_base, 3584, dif_iovs, 1);
	CU_ASSERT(read_base == 4096 * 4);

	rc = spdk_dif_generate(&iov1, 1, 4, &ctx);
	rc = spdk_dif_generate_stream(buf1, (4096 + 128) * 4, 4096 * 3 + 512, 3584, &ctx);
	CU_ASSERT(rc == 0);

	/* The second data buffer:
@@ -1482,6 +1491,57 @@ set_md_interleave_iovs_test(void)
	free(buf2);
}

static void
dif_generate_stream_test(void)
{
	struct iovec iov;
	struct spdk_dif_ctx ctx;
	struct spdk_dif_error err_blk;
	uint32_t dif_flags;
	int rc;

	_iov_alloc_buf(&iov, (512 + 8) * 5);

	rc = ut_data_pattern_generate(&iov, 1, 512, 8, 5);
	CU_ASSERT(rc == 0);

	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
		    SPDK_DIF_FLAGS_REFTAG_CHECK;

	rc = spdk_dif_ctx_init(&ctx, 512, 8, true, false, SPDK_DIF_TYPE1, dif_flags,
			       22, 0xFFFF, 0x22, GUARD_SEED);
	CU_ASSERT(rc == 0);

	rc = spdk_dif_generate_stream(iov.iov_base, (512 + 8) * 5, 0, 511, &ctx);
	CU_ASSERT(rc == 0);

	rc = spdk_dif_generate_stream(iov.iov_base, (512 + 8) * 5, 511, 1, &ctx);
	CU_ASSERT(rc == 0);

	rc = spdk_dif_generate_stream(iov.iov_base, (512 + 8) * 5, 512, 256, &ctx);
	CU_ASSERT(rc == 0);

	rc = spdk_dif_generate_stream(iov.iov_base, (512 + 8) * 5, 768, 512, &ctx);
	CU_ASSERT(rc == 0);

	rc = spdk_dif_generate_stream(iov.iov_base, (512 + 8) * 5, 1280, 1024, &ctx);
	CU_ASSERT(rc == 0);

	rc = spdk_dif_generate_stream(iov.iov_base, (512 + 8) * 5, 2304, 256, &ctx);
	CU_ASSERT(rc == 0);

	rc = spdk_dif_generate_stream(iov.iov_base, (512 + 8) * 5, 2560, 512, &ctx);
	CU_ASSERT(rc == -ERANGE);

	rc = spdk_dif_verify(&iov, 1, 5, &ctx, &err_blk);
	CU_ASSERT(rc == 0);

	rc = ut_data_pattern_verify(&iov, 1, 512, 8, 5);
	CU_ASSERT(rc == 0);

	_iov_free_buf(&iov);
}

int
main(int argc, char **argv)
{
@@ -1566,7 +1626,8 @@ main(int argc, char **argv)
			    dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test) == NULL ||
		CU_add_test(suite, "dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test",
			    dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test) == NULL ||
		CU_add_test(suite, "set_md_interleave_iovs_test", set_md_interleave_iovs_test) == NULL
		CU_add_test(suite, "set_md_interleave_iovs_test", set_md_interleave_iovs_test) == NULL ||
		CU_add_test(suite, "dif_generate_stream_test", dif_generate_stream_test) == NULL
	) {
		CU_cleanup_registry();
		return CU_get_error();