dif: Add spdk_dif_verify_stream to verify DIF by stream fashion
Add spdk_dif_verify_stream to verify DIF by stream fashion. spdk_dif_verify_stream utilizes the updated _dif_verify_split. spdk_dif_verify_stream is very similar with spdk_dif_generate_stream(). UT code demonstrates how it is realized. Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Change-Id: I1c5d197cf4c0bbc82c8e7f4fa45ddc0b94051058 Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/458330 Reviewed-by: Changpeng Liu <changpeng.liu@intel.com> Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
parent
80f2ca0d90
commit
6db126c24c
@ -350,4 +350,20 @@ int spdk_dif_set_md_interleave_iovs(struct iovec *iovs, int iovcnt,
|
||||
int spdk_dif_generate_stream(struct iovec *iovs, int iovcnt,
|
||||
uint32_t data_offset, uint32_t data_len,
|
||||
struct spdk_dif_ctx *ctx);
|
||||
|
||||
/**
|
||||
* Verify DIF for the to-be-written block of the extended LBA payload.
|
||||
*
|
||||
* \param iovs iovec array describing the extended LBA payload.
|
||||
* \param iovcnt Number of elements in the iovec array.
|
||||
* \param data_offset Offset to the to-be-written data in the extended LBA payload.
|
||||
* \param data_len Length of the to-be-written data in the extended LBA payload.
|
||||
* \param ctx DIF context.
|
||||
*
|
||||
* \return 0 on success and negated errno otherwise.
|
||||
*/
|
||||
int spdk_dif_verify_stream(struct iovec *iovs, int iovcnt,
|
||||
uint32_t data_offset, uint32_t data_len,
|
||||
struct spdk_dif_ctx *ctx,
|
||||
struct spdk_dif_error *err_blk);
|
||||
#endif /* SPDK_DIF_H */
|
||||
|
@ -1575,3 +1575,71 @@ spdk_dif_generate_stream(struct iovec *iovs, int iovcnt,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_dif_verify_stream(struct iovec *iovs, int iovcnt,
|
||||
uint32_t data_offset, uint32_t data_len,
|
||||
struct spdk_dif_ctx *ctx,
|
||||
struct spdk_dif_error *err_blk)
|
||||
{
|
||||
uint32_t data_block_size, data_unalign, buf_len, buf_offset;
|
||||
uint32_t len, offset_in_block, offset_blocks;
|
||||
uint16_t guard = 0;
|
||||
struct _dif_sgl sgl;
|
||||
int rc = 0;
|
||||
|
||||
if (iovs == NULL || iovcnt == 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
data_block_size = ctx->block_size - ctx->md_size;
|
||||
|
||||
if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
|
||||
guard = ctx->last_guard;
|
||||
}
|
||||
|
||||
data_unalign = ctx->data_offset % data_block_size;
|
||||
|
||||
/* If the last data block is complete, DIF of the data block is
|
||||
* verified in this function.;
|
||||
*/
|
||||
buf_len = ((data_unalign + data_offset + data_len) / data_block_size) * ctx->block_size +
|
||||
((data_unalign + data_offset + data_len) % data_block_size);
|
||||
buf_len -= data_unalign;
|
||||
|
||||
_dif_sgl_init(&sgl, iovs, iovcnt);
|
||||
|
||||
if (!_dif_sgl_is_valid(&sgl, buf_len)) {
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
buf_offset = ((data_unalign + data_offset) / data_block_size) * ctx->block_size +
|
||||
((data_unalign + data_offset) % data_block_size);
|
||||
buf_offset -= data_unalign;
|
||||
|
||||
_dif_sgl_advance(&sgl, buf_offset);
|
||||
buf_len -= buf_offset;
|
||||
|
||||
buf_offset += data_unalign;
|
||||
|
||||
while (buf_len != 0) {
|
||||
len = spdk_min(buf_len, _to_next_boundary(buf_offset, ctx->block_size));
|
||||
offset_in_block = buf_offset % ctx->block_size;
|
||||
offset_blocks = buf_offset / ctx->block_size;
|
||||
|
||||
rc = _dif_verify_split(&sgl, offset_in_block, len, &guard, offset_blocks,
|
||||
ctx, err_blk);
|
||||
if (rc != 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
buf_len -= len;
|
||||
buf_offset += len;
|
||||
}
|
||||
|
||||
if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
|
||||
ctx->last_guard = guard;
|
||||
}
|
||||
error:
|
||||
return rc;
|
||||
}
|
||||
|
@ -2079,6 +2079,67 @@ _dif_verify_split_test(void)
|
||||
free(buf);
|
||||
}
|
||||
|
||||
static void
|
||||
dif_verify_stream_multi_segments_test(void)
|
||||
{
|
||||
struct spdk_dif_ctx ctx = {};
|
||||
struct spdk_dif_error err_blk = {};
|
||||
struct iovec iov = {};
|
||||
uint8_t *buf;
|
||||
uint32_t dif_flags;
|
||||
int rc;
|
||||
|
||||
dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
|
||||
SPDK_DIF_FLAGS_REFTAG_CHECK;
|
||||
|
||||
rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, SPDK_DIF_TYPE1,
|
||||
dif_flags, 22, 0xFFFF, 0x22, 0, GUARD_SEED);
|
||||
CU_ASSERT(rc == 0);
|
||||
|
||||
buf = calloc(1, (4096 + 128) * 4);
|
||||
SPDK_CU_ASSERT_FATAL(buf != NULL);
|
||||
_iov_set_buf(&iov, buf, (4096 + 128) * 4);
|
||||
|
||||
rc = ut_data_pattern_generate(&iov, 1, 4096 + 128, 128, 4);
|
||||
CU_ASSERT(rc == 0);
|
||||
|
||||
rc = spdk_dif_generate(&iov, 1, 4, &ctx);
|
||||
CU_ASSERT(rc == 0);
|
||||
|
||||
/* 1st data segment */
|
||||
_iov_set_buf(&iov, buf, 1024);
|
||||
spdk_dif_ctx_set_data_offset(&ctx, 0);
|
||||
|
||||
rc = spdk_dif_verify_stream(&iov, 1, 0, 1024, &ctx, &err_blk);
|
||||
CU_ASSERT(rc == 0);
|
||||
|
||||
/* 2nd data segment */
|
||||
_iov_set_buf(&iov, buf + 1024, (3072 + 128) + (4096 + 128) * 2 + 512);
|
||||
spdk_dif_ctx_set_data_offset(&ctx, 1024);
|
||||
|
||||
rc = spdk_dif_verify_stream(&iov, 1, 0, 3072 + 4096 * 2 + 512, &ctx, &err_blk);
|
||||
CU_ASSERT(rc == 0);
|
||||
|
||||
/* 3rd data segment */
|
||||
_iov_set_buf(&iov, buf + (4096 + 128) * 3 + 512, 3584 + 128);
|
||||
spdk_dif_ctx_set_data_offset(&ctx, 4096 * 3);
|
||||
|
||||
rc = spdk_dif_verify_stream(&iov, 1, 0, 3584, &ctx, &err_blk);
|
||||
CU_ASSERT(rc == 0);
|
||||
|
||||
/* verify all data segments once */
|
||||
_iov_set_buf(&iov, buf, (4096 + 128) * 4);
|
||||
spdk_dif_ctx_set_data_offset(&ctx, 0);
|
||||
|
||||
rc = spdk_dif_verify(&iov, 1, 4, &ctx, &err_blk);
|
||||
CU_ASSERT(rc == 0);
|
||||
|
||||
rc = ut_data_pattern_verify(&iov, 1, 4096 + 128, 128, 4);
|
||||
CU_ASSERT(rc == 0);
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
||||
#define UT_CRC32C_XOR 0xffffffffUL
|
||||
|
||||
static void
|
||||
@ -2266,6 +2327,8 @@ main(int argc, char **argv)
|
||||
CU_add_test(suite, "set_md_interleave_iovs_multi_segments_test",
|
||||
set_md_interleave_iovs_multi_segments_test) == NULL ||
|
||||
CU_add_test(suite, "_dif_verify_split_test", _dif_verify_split_test) == NULL ||
|
||||
CU_add_test(suite, "dif_verify_stream_multi_segments_test",
|
||||
dif_verify_stream_multi_segments_test) == NULL ||
|
||||
CU_add_test(suite, "update_crc32c_test", update_crc32c_test) == NULL
|
||||
) {
|
||||
CU_cleanup_registry();
|
||||
|
Loading…
Reference in New Issue
Block a user