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: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/446594
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Ziye Yang <ziye.yang@intel.com>
Reviewed-by: wuzhouhui <wuzhouhui@kingsoft.com>
This commit is contained in:
Shuhei Matsumoto 2019-03-01 17:49:23 +09:00 committed by Changpeng Liu
parent daf2206ec4
commit 466ca6d494
3 changed files with 117 additions and 2 deletions

View File

@ -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 */

View File

@ -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;
}

View File

@ -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();