From 3612ab7a3c61b1ae6aa25828e710836a29654170 Mon Sep 17 00:00:00 2001 From: Shuhei Matsumoto Date: Thu, 9 May 2019 10:22:55 +0900 Subject: [PATCH] dif: Support multiple iovecs for data buffer in spdk_dif_generate_stream This patch allows multiple iovecs as argument in spdk_dif_generate_stream. Subsequent patches will support DIF strip and insert in SPDK NVMe-TCP target based on the patch series. Change-Id: I1f3d6c5b9f924bb52525e1611db403846d087563 Signed-off-by: Shuhei Matsumoto Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/453756 Tested-by: SPDK CI Jenkins Reviewed-by: Changpeng Liu Reviewed-by: Jim Harris --- lib/util/dif.c | 33 ++++++++++++++++++++++- test/unit/lib/util/dif.c/dif_ut.c | 45 ++++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 2 deletions(-) diff --git a/lib/util/dif.c b/lib/util/dif.c index c5c377153..a00612793 100644 --- a/lib/util/dif.c +++ b/lib/util/dif.c @@ -1461,6 +1461,37 @@ dif_generate_stream(uint8_t *buf, uint32_t buf_len, return 0; } +static int +dif_generate_stream_split(struct iovec *iovs, int iovcnt, + uint32_t offset, uint32_t read_len, + const struct spdk_dif_ctx *ctx) +{ + uint32_t data_block_size, offset_blocks, num_blocks, i; + struct _dif_sgl sgl; + + 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; + + _dif_sgl_init(&sgl, iovs, iovcnt); + + if (!_dif_sgl_is_valid(&sgl, offset + num_blocks * ctx->block_size)) { + return -ERANGE; + } + + _dif_sgl_fast_forward(&sgl, offset); + + for (i = 0; i < num_blocks; i++) { + _dif_generate_split(&sgl, offset_blocks + i, ctx); + } + + return 0; +} + int spdk_dif_generate_stream(struct iovec *iovs, int iovcnt, uint32_t offset, uint32_t read_len, @@ -1474,6 +1505,6 @@ spdk_dif_generate_stream(struct iovec *iovs, int iovcnt, return dif_generate_stream(iovs[0].iov_base, iovs[0].iov_len, offset, read_len, ctx); } else { - return -EINVAL; + return dif_generate_stream_split(iovs, iovcnt, offset, read_len, ctx); } } diff --git a/test/unit/lib/util/dif.c/dif_ut.c b/test/unit/lib/util/dif.c/dif_ut.c index e45a23c39..b7532e0f5 100644 --- a/test/unit/lib/util/dif.c/dif_ut.c +++ b/test/unit/lib/util/dif.c/dif_ut.c @@ -1497,7 +1497,8 @@ static void set_md_interleave_iovs_split_test(void) { struct spdk_dif_ctx ctx = {}; - struct iovec iovs1[7], dif_iovs[8]; + struct spdk_dif_error err_blk = {}; + struct iovec iovs1[7], iovs2[7], dif_iovs[8]; uint32_t dif_check_flags, mapped_len = 0, read_base = 0; int rc, i; @@ -1536,6 +1537,9 @@ set_md_interleave_iovs_split_test(void) read_base = ut_readv(0, 128, dif_iovs, 8); CU_ASSERT(read_base == 128); + rc = spdk_dif_generate_stream(iovs1, 7, 0, 128, &ctx); + CU_ASSERT(rc == 0); + rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 8, iovs1, 7, read_base, 512 * 4, &mapped_len, &ctx); CU_ASSERT(rc == 8); @@ -1552,6 +1556,9 @@ set_md_interleave_iovs_split_test(void) read_base += ut_readv(read_base, 383, dif_iovs, 8); CU_ASSERT(read_base == 511); + rc = spdk_dif_generate_stream(iovs1, 7, 128, 383, &ctx); + CU_ASSERT(rc == 0); + rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 8, iovs1, 7, read_base, 512 * 4, &mapped_len, &ctx); CU_ASSERT(rc == 8); @@ -1568,6 +1575,9 @@ set_md_interleave_iovs_split_test(void) read_base += ut_readv(read_base, 1 + 512 * 2 + 128, dif_iovs, 8); CU_ASSERT(read_base == 512 * 3 + 128); + rc = spdk_dif_generate_stream(iovs1, 7, 383, 1 + 512 * 2 + 128, &ctx); + CU_ASSERT(rc == 0); + rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 8, iovs1, 7, read_base, 512 * 4, &mapped_len, &ctx); CU_ASSERT(rc == 2); @@ -1578,8 +1588,41 @@ set_md_interleave_iovs_split_test(void) read_base += ut_readv(read_base, 384, dif_iovs, 8); CU_ASSERT(read_base == 512 * 4); + rc = spdk_dif_generate_stream(iovs1, 7, 512 * 3 + 128, 384, &ctx); + CU_ASSERT(rc == 0); + + /* The second SGL data buffer: + * - Set data pattern with a space for metadata for each block. + */ + _iov_alloc_buf(&iovs2[0], 512 + 8 + 128); + _iov_alloc_buf(&iovs2[1], 128); + _iov_alloc_buf(&iovs2[2], 256 + 8); + _iov_alloc_buf(&iovs2[3], 100); + _iov_alloc_buf(&iovs2[4], 412 + 5); + _iov_alloc_buf(&iovs2[5], 3 + 300); + _iov_alloc_buf(&iovs2[6], 212 + 8); + + rc = ut_data_pattern_generate(iovs2, 7, 512 + 8, 8, 4); + CU_ASSERT(rc == 0); + rc = spdk_dif_generate(iovs2, 7, 4, &ctx); + CU_ASSERT(rc == 0); + + rc = spdk_dif_verify(iovs1, 7, 4, &ctx, &err_blk); + CU_ASSERT(rc == 0); + + rc = spdk_dif_verify(iovs2, 7, 4, &ctx, &err_blk); + CU_ASSERT(rc == 0); + + /* Compare the first and the second SGL data buffer by byte. */ + for (i = 0; i < 7; i++) { + rc = memcmp(iovs1[i].iov_base, iovs2[i].iov_base, + iovs1[i].iov_len); + CU_ASSERT(rc == 0); + } + for (i = 0; i < 7; i++) { _iov_free_buf(&iovs1[i]); + _iov_free_buf(&iovs2[i]); } }