dif: Support multiple iovecs for data buffer in spdk_dif_set_md_interleave_iovs

This patch allows multiple iovecs as argument of
spdk_dif_set_md_interleave_iovs.

Subsequent patches will support SGL data buffer in
spdk_dif_generate_stream too. UT code tests only
spdk_dif_set_md_interleave until then.

Change-Id: I7ac03a3c8f7bcd922af4f29b404ebf3acc4b89e5
Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/453736
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Shuhei Matsumoto 2019-05-09 07:07:39 +09:00 committed by Jim Harris
parent 2821762a60
commit 079ad446d2
2 changed files with 152 additions and 1 deletions

View File

@ -1333,6 +1333,64 @@ dif_set_md_interleave_iovs(struct iovec *iovs, int iovcnt,
return iovcnt - sgl.iovcnt; return iovcnt - sgl.iovcnt;
} }
static int
dif_set_md_interleave_iovs_split(struct iovec *iovs, int iovcnt,
struct iovec *buf_iovs, int buf_iovcnt,
uint32_t data_offset, uint32_t data_len,
uint32_t *_mapped_len,
const struct spdk_dif_ctx *ctx)
{
uint32_t data_block_size, head_unalign;
uint32_t num_blocks, offset_blocks;
struct _dif_sgl dif_sgl;
struct _dif_sgl buf_sgl;
uint8_t *buf;
uint32_t buf_len, remaining;
data_block_size = ctx->block_size - ctx->md_size;
num_blocks = data_len / data_block_size;
_dif_sgl_init(&dif_sgl, iovs, iovcnt);
_dif_sgl_init(&buf_sgl, buf_iovs, buf_iovcnt);
if (!_dif_sgl_is_valid(&buf_sgl, num_blocks * ctx->block_size)) {
SPDK_ERRLOG("Buffer overflow will occur.\n");
return -ERANGE;
}
offset_blocks = data_offset / data_block_size;
head_unalign = data_offset % data_block_size;
_dif_sgl_fast_forward(&buf_sgl, offset_blocks * ctx->block_size);
while (offset_blocks < num_blocks) {
_dif_sgl_fast_forward(&buf_sgl, head_unalign);
remaining = data_block_size - head_unalign;
while (remaining != 0) {
_dif_sgl_get_buf(&buf_sgl, (void *)&buf, &buf_len);
buf_len = spdk_min(buf_len, remaining);
if (!_dif_sgl_append(&dif_sgl, buf, buf_len)) {
goto end;
}
_dif_sgl_advance(&buf_sgl, buf_len);
remaining -= buf_len;
}
_dif_sgl_fast_forward(&buf_sgl, ctx->md_size);
offset_blocks++;
head_unalign = 0;
}
end:
if (_mapped_len != NULL) {
*_mapped_len = dif_sgl.total_size;
}
return iovcnt - dif_sgl.iovcnt;
}
int int
spdk_dif_set_md_interleave_iovs(struct iovec *iovs, int iovcnt, spdk_dif_set_md_interleave_iovs(struct iovec *iovs, int iovcnt,
struct iovec *buf_iovs, int buf_iovcnt, struct iovec *buf_iovs, int buf_iovcnt,
@ -1363,7 +1421,8 @@ spdk_dif_set_md_interleave_iovs(struct iovec *iovs, int iovcnt,
buf_iovs[0].iov_base, buf_iovs[0].iov_len, buf_iovs[0].iov_base, buf_iovs[0].iov_len,
data_offset, data_len, _mapped_len, ctx); data_offset, data_len, _mapped_len, ctx);
} else { } else {
return -EINVAL; return dif_set_md_interleave_iovs_split(iovs, iovcnt, buf_iovs, buf_iovcnt,
data_offset, data_len, _mapped_len, ctx);
} }
} }

View File

@ -1493,6 +1493,96 @@ set_md_interleave_iovs_test(void)
free(buf2); free(buf2);
} }
static void
set_md_interleave_iovs_split_test(void)
{
struct spdk_dif_ctx ctx = {};
struct iovec iovs1[7], dif_iovs[8];
uint32_t dif_check_flags, mapped_len = 0, read_base = 0;
int rc, i;
dif_check_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
SPDK_DIF_FLAGS_REFTAG_CHECK;
rc = spdk_dif_ctx_init(&ctx, 512 + 8, 8, true, false, SPDK_DIF_TYPE1,
dif_check_flags, 22, 0xFFFF, 0x22, GUARD_SEED);
CU_ASSERT(rc == 0);
/* The first SGL data buffer:
* - Create iovec array to leave a space for metadata for each block
* - Split vectored read and so creating iovec array is done before every vectored read.
*/
_iov_alloc_buf(&iovs1[0], 512 + 8 + 128);
_iov_alloc_buf(&iovs1[1], 128);
_iov_alloc_buf(&iovs1[2], 256 + 8);
_iov_alloc_buf(&iovs1[3], 100);
_iov_alloc_buf(&iovs1[4], 412 + 5);
_iov_alloc_buf(&iovs1[5], 3 + 300);
_iov_alloc_buf(&iovs1[6], 212 + 8);
rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 8, iovs1, 7,
0, 512 * 4, &mapped_len, &ctx);
CU_ASSERT(rc == 8);
CU_ASSERT(mapped_len == 512 * 4);
CU_ASSERT(_iov_check(&dif_iovs[0], iovs1[0].iov_base, 512) == true);
CU_ASSERT(_iov_check(&dif_iovs[1], iovs1[0].iov_base + 512 + 8, 128) == true);
CU_ASSERT(_iov_check(&dif_iovs[2], iovs1[1].iov_base, 128) == true);
CU_ASSERT(_iov_check(&dif_iovs[3], iovs1[2].iov_base, 256) == true);
CU_ASSERT(_iov_check(&dif_iovs[4], iovs1[3].iov_base, 100) == true);
CU_ASSERT(_iov_check(&dif_iovs[5], iovs1[4].iov_base, 412) == true);
CU_ASSERT(_iov_check(&dif_iovs[6], iovs1[5].iov_base + 3, 300) == true);
CU_ASSERT(_iov_check(&dif_iovs[7], iovs1[6].iov_base, 212) == true);
read_base = ut_readv(0, 128, dif_iovs, 8);
CU_ASSERT(read_base == 128);
rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 8, iovs1, 7,
read_base, 512 * 4, &mapped_len, &ctx);
CU_ASSERT(rc == 8);
CU_ASSERT(mapped_len == 384 + 512 * 3);
CU_ASSERT(_iov_check(&dif_iovs[0], iovs1[0].iov_base + 128, 384) == true);
CU_ASSERT(_iov_check(&dif_iovs[1], iovs1[0].iov_base + 512 + 8, 128) == true);
CU_ASSERT(_iov_check(&dif_iovs[2], iovs1[1].iov_base, 128) == true);
CU_ASSERT(_iov_check(&dif_iovs[3], iovs1[2].iov_base, 256) == true);
CU_ASSERT(_iov_check(&dif_iovs[4], iovs1[3].iov_base, 100) == true);
CU_ASSERT(_iov_check(&dif_iovs[5], iovs1[4].iov_base, 412) == true);
CU_ASSERT(_iov_check(&dif_iovs[6], iovs1[5].iov_base + 3, 300) == true);
CU_ASSERT(_iov_check(&dif_iovs[7], iovs1[6].iov_base, 212) == true);
read_base += ut_readv(read_base, 383, dif_iovs, 8);
CU_ASSERT(read_base == 511);
rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 8, iovs1, 7,
read_base, 512 * 4, &mapped_len, &ctx);
CU_ASSERT(rc == 8);
CU_ASSERT(mapped_len == 1 + 512 * 3);
CU_ASSERT(_iov_check(&dif_iovs[0], iovs1[0].iov_base + 511, 1) == true);
CU_ASSERT(_iov_check(&dif_iovs[1], iovs1[0].iov_base + 512 + 8, 128) == true);
CU_ASSERT(_iov_check(&dif_iovs[2], iovs1[1].iov_base, 128) == true);
CU_ASSERT(_iov_check(&dif_iovs[3], iovs1[2].iov_base, 256) == true);
CU_ASSERT(_iov_check(&dif_iovs[4], iovs1[3].iov_base, 100) == true);
CU_ASSERT(_iov_check(&dif_iovs[5], iovs1[4].iov_base, 412) == true);
CU_ASSERT(_iov_check(&dif_iovs[6], iovs1[5].iov_base + 3, 300) == true);
CU_ASSERT(_iov_check(&dif_iovs[7], iovs1[6].iov_base, 212) == true);
read_base += ut_readv(read_base, 1 + 512 * 2 + 128, dif_iovs, 8);
CU_ASSERT(read_base == 512 * 3 + 128);
rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 8, iovs1, 7,
read_base, 512 * 4, &mapped_len, &ctx);
CU_ASSERT(rc == 2);
CU_ASSERT(mapped_len == 384);
CU_ASSERT(_iov_check(&dif_iovs[0], iovs1[5].iov_base + 3 + 128, 172) == true);
CU_ASSERT(_iov_check(&dif_iovs[1], iovs1[6].iov_base, 212) == true);
read_base += ut_readv(read_base, 384, dif_iovs, 8);
CU_ASSERT(read_base == 512 * 4);
for (i = 0; i < 7; i++) {
_iov_free_buf(&iovs1[i]);
}
}
static void static void
dif_generate_stream_test(void) dif_generate_stream_test(void)
{ {
@ -1629,6 +1719,8 @@ main(int argc, char **argv)
CU_add_test(suite, "dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test", 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 || 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, "set_md_interleave_iovs_split_test",
set_md_interleave_iovs_split_test) == NULL ||
CU_add_test(suite, "dif_generate_stream_test", dif_generate_stream_test) == NULL CU_add_test(suite, "dif_generate_stream_test", dif_generate_stream_test) == NULL
) { ) {
CU_cleanup_registry(); CU_cleanup_registry();