From 466ca6d494d1f60b8db76a9ff2268f8c3f929ee4 Mon Sep 17 00:00:00 2001 From: Shuhei Matsumoto Date: Fri, 1 Mar 2019 17:49:23 +0900 Subject: [PATCH] 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 Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/446594 Tested-by: SPDK CI Jenkins Reviewed-by: Jim Harris Reviewed-by: Changpeng Liu Reviewed-by: Ziye Yang Reviewed-by: wuzhouhui --- include/spdk/dif.h | 15 +++++++ lib/util/dif.c | 39 +++++++++++++++++++ test/unit/lib/util/dif.c/dif_ut.c | 65 ++++++++++++++++++++++++++++++- 3 files changed, 117 insertions(+), 2 deletions(-) diff --git a/include/spdk/dif.h b/include/spdk/dif.h index f78e88fc3..45605f4e4 100644 --- a/include/spdk/dif.h +++ b/include/spdk/dif.h @@ -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 */ diff --git a/lib/util/dif.c b/lib/util/dif.c index 9291daa7a..51ce8d057 100644 --- a/lib/util/dif.c +++ b/lib/util/dif.c @@ -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; +} diff --git a/test/unit/lib/util/dif.c/dif_ut.c b/test/unit/lib/util/dif.c/dif_ut.c index 761e8855c..0ec3c78b2 100644 --- a/test/unit/lib/util/dif.c/dif_ut.c +++ b/test/unit/lib/util/dif.c/dif_ut.c @@ -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();