dif: Return DIF error information at verification for copied extended LBA payload.

For copied extended LBA payload, Introduce a struct to collect DIF error
information and pass the reference to the struct to bit-flip error injection
and verification.

This change will make logging of DIF error and comparison between
injection and verification possible for copied extended LBA payload.

Merging this patch to the previous is possible but add this as a separate patch
to reduce the patch size.

Change-Id: I9f7ac1332fe63cb206c692d0876c8de41ef9286f
Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/c/435227
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: wuzhouhui <wuzhouhui@kingsoft.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Shuhei Matsumoto 2018-12-28 10:32:13 +09:00 committed by Jim Harris
parent bc5507e440
commit 045e77c235
3 changed files with 137 additions and 12 deletions

View File

@ -172,11 +172,13 @@ int spdk_dif_generate_copy(struct iovec *iovs, int iovcnt, struct iovec *bounce_
* \param bounce_iov A contiguous buffer forming extended LBA payload.
* \param num_blocks Number of blocks of the LBA payload.
* \param ctx DIF context.
* \param err_blk Error information of the block in which DIF error is found.
*
* \return 0 on success and negated errno otherwise.
*/
int spdk_dif_verify_copy(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,
uint32_t num_blocks, const struct spdk_dif_ctx *ctx);
uint32_t num_blocks, const struct spdk_dif_ctx *ctx,
struct spdk_dif_error *err_blk);
/**
* Inject bit flip error to extended LBA payload.

View File

@ -705,7 +705,8 @@ spdk_dif_generate_copy(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,
static int
dif_verify_copy(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,
uint32_t num_blocks, const struct spdk_dif_ctx *ctx)
uint32_t num_blocks, const struct spdk_dif_ctx *ctx,
struct spdk_dif_error *err_blk)
{
struct _iov_iter src_iter, dst_iter;
uint32_t offset_blocks, data_block_size;
@ -734,7 +735,7 @@ dif_verify_copy(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,
memcpy(dst, src, data_block_size);
}
rc = _dif_verify(src + ctx->guard_interval, guard, offset_blocks, ctx, NULL);
rc = _dif_verify(src + ctx->guard_interval, guard, offset_blocks, ctx, err_blk);
if (rc != 0) {
return rc;
}
@ -749,7 +750,8 @@ dif_verify_copy(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,
static int
_dif_verify_copy_split(struct _iov_iter *src_iter, struct _iov_iter *dst_iter,
uint32_t offset_blocks, const struct spdk_dif_ctx *ctx)
uint32_t offset_blocks, const struct spdk_dif_ctx *ctx,
struct spdk_dif_error *err_blk)
{
uint32_t offset_in_block, dst_len, data_block_size;
uint16_t guard;
@ -787,12 +789,13 @@ _dif_verify_copy_split(struct _iov_iter *src_iter, struct _iov_iter *dst_iter,
_iov_iter_advance(src_iter, ctx->block_size);
return _dif_verify(src + ctx->guard_interval, guard, offset_blocks, ctx, NULL);
return _dif_verify(src + ctx->guard_interval, guard, offset_blocks, ctx, err_blk);
}
static int
dif_verify_copy_split(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,
uint32_t num_blocks, const struct spdk_dif_ctx *ctx)
uint32_t num_blocks, const struct spdk_dif_ctx *ctx,
struct spdk_dif_error *err_blk)
{
struct _iov_iter src_iter, dst_iter;
uint32_t offset_blocks;
@ -804,7 +807,7 @@ dif_verify_copy_split(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,
while (offset_blocks < num_blocks &&
_iov_iter_cont(&src_iter) && _iov_iter_cont(&dst_iter)) {
rc = _dif_verify_copy_split(&src_iter, &dst_iter, offset_blocks, ctx);
rc = _dif_verify_copy_split(&src_iter, &dst_iter, offset_blocks, ctx, err_blk);
if (rc != 0) {
return rc;
}
@ -816,7 +819,8 @@ dif_verify_copy_split(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,
int
spdk_dif_verify_copy(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,
uint32_t num_blocks, const struct spdk_dif_ctx *ctx)
uint32_t num_blocks, const struct spdk_dif_ctx *ctx,
struct spdk_dif_error *err_blk)
{
uint32_t data_block_size;
@ -833,9 +837,9 @@ spdk_dif_verify_copy(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,
}
if (_are_iovs_bytes_multiple(iovs, iovcnt, data_block_size)) {
return dif_verify_copy(iovs, iovcnt, bounce_iov, num_blocks, ctx);
return dif_verify_copy(iovs, iovcnt, bounce_iov, num_blocks, ctx, err_blk);
} else {
return dif_verify_copy_split(iovs, iovcnt, bounce_iov, num_blocks, ctx);
return dif_verify_copy_split(iovs, iovcnt, bounce_iov, num_blocks, ctx, err_blk);
}
}

View File

@ -747,7 +747,7 @@ dif_copy_gen_and_verify(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov
rc = spdk_dif_generate_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx);
CU_ASSERT(rc == 0);
rc = spdk_dif_verify_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx);
rc = spdk_dif_verify_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx, NULL);
CU_ASSERT(rc == 0);
rc = ut_data_pattern_verify(iovs, iovcnt, block_size - md_size, 0, num_blocks);
@ -892,6 +892,121 @@ dif_copy_sec_512_md_8_prchk_7_multi_iovs_complex_splits(void)
_iov_free_buf(&bounce_iov);
}
static void
_dif_copy_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,
uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
uint32_t inject_flags, bool dif_loc)
{
struct spdk_dif_ctx ctx = {};
struct spdk_dif_error err_blk = {};
uint32_t inject_offset = 0, dif_flags;
int rc;
dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK;
rc = ut_data_pattern_generate(iovs, iovcnt, block_size - md_size, 0, num_blocks);
CU_ASSERT(rc == 0);
rc = spdk_dif_ctx_init(&ctx, block_size, md_size, dif_loc, SPDK_DIF_TYPE1, dif_flags,
88, 0xFFFF, 0x88);
SPDK_CU_ASSERT_FATAL(rc == 0);
rc = spdk_dif_generate_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx);
CU_ASSERT(rc == 0);
rc = spdk_dif_inject_error(bounce_iov, 1, num_blocks, &ctx, inject_flags, &inject_offset);
CU_ASSERT(rc == 0);
rc = spdk_dif_verify_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx, &err_blk);
CU_ASSERT(rc != 0);
if (inject_flags == SPDK_DIF_DATA_ERROR) {
CU_ASSERT(SPDK_DIF_GUARD_ERROR == err_blk.err_type);
} else {
CU_ASSERT(inject_flags == err_blk.err_type);
}
CU_ASSERT(inject_offset == err_blk.err_offset);
}
static void
dif_copy_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,
uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
uint32_t inject_flags)
{
/* The case that DIF is contained in the first 8 bytes of metadata. */
_dif_copy_inject_error_and_verify(iovs, iovcnt, bounce_iov,
block_size, md_size, num_blocks,
inject_flags, false);
/* The case that DIF is contained in the last 8 bytes of metadata. */
_dif_copy_inject_error_and_verify(iovs, iovcnt, bounce_iov,
block_size, md_size, num_blocks,
inject_flags, true);
}
static void
dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test(void)
{
struct iovec iovs[4], bounce_iov;
int i, num_blocks;
num_blocks = 0;
for (i = 0; i < 4; i++) {
_iov_alloc_buf(&iovs[i], 4096 * (i + 1));
num_blocks += i + 1;
}
_iov_alloc_buf(&bounce_iov, (4096 + 128) * num_blocks);
dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
num_blocks, SPDK_DIF_GUARD_ERROR);
dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
num_blocks, SPDK_DIF_APPTAG_ERROR);
dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
num_blocks, SPDK_DIF_REFTAG_ERROR);
dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
num_blocks, SPDK_DIF_DATA_ERROR);
for (i = 0; i < 4; i++) {
_iov_free_buf(&iovs[i]);
}
_iov_free_buf(&bounce_iov);
}
static void
dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test(void)
{
struct iovec iovs[4], bounce_iov;
int i;
_iov_alloc_buf(&iovs[0], 2048);
_iov_alloc_buf(&iovs[1], 2048);
_iov_alloc_buf(&iovs[2], 1);
_iov_alloc_buf(&iovs[3], 4095);
_iov_alloc_buf(&bounce_iov, (4096 + 128) * 2);
dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
2, SPDK_DIF_GUARD_ERROR);
dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
2, SPDK_DIF_APPTAG_ERROR);
dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
2, SPDK_DIF_REFTAG_ERROR);
dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
2, SPDK_DIF_DATA_ERROR);
for (i = 0; i < 4; i++) {
_iov_free_buf(&iovs[i]);
}
_iov_free_buf(&bounce_iov);
}
int
main(int argc, char **argv)
{
@ -955,7 +1070,11 @@ main(int argc, char **argv)
CU_add_test(suite, "dif_copy_sec_512_md_8_prchk_7_multi_iovs_split_data",
dif_copy_sec_512_md_8_prchk_7_multi_iovs_split_data) == NULL ||
CU_add_test(suite, "dif_copy_sec_512_md_8_prchk_7_multi_iovs_complex_splits",
dif_copy_sec_512_md_8_prchk_7_multi_iovs_complex_splits) == NULL
dif_copy_sec_512_md_8_prchk_7_multi_iovs_complex_splits) == NULL ||
CU_add_test(suite, "dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test",
dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test) == NULL ||
CU_add_test(suite, "dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test",
dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test) == NULL
) {
CU_cleanup_registry();
return CU_get_error();