dix: Return DIF error information at verification for separate metadata payload
For separate metadata 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 separate metadata payload. Merging this patch to the previous is possible but add this as a separate patch to reduce the patch size. Change-Id: Ifce2130e902bc090cbe205fa8df12559739ced57 Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Reviewed-on: https://review.gerrithub.io/c/435097 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> Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
This commit is contained in:
parent
65624bd5e4
commit
ed45352564
@ -221,9 +221,29 @@ int spdk_dix_generate(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
|
||||
* \param md_iov A contiguous buffer for metadata.
|
||||
* \param num_blocks Number of blocks of the separate metadata 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_dix_verify(struct iovec *iovs, int iovcnt, struct iovec *md_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 separate metadata payload.
|
||||
*
|
||||
* \param iovs iovec array describing the extended LBA payload.
|
||||
* \param iovcnt Number of elements in the iovec array.
|
||||
* \param md_iov A contiguous buffer for metadata.
|
||||
* \param num_blocks Number of blocks of the payload.
|
||||
* \param ctx DIF context.
|
||||
* \param inject_flags Flag to specify the action of error injection.
|
||||
* \param inject_offset Offset, in blocks, to which error is injected.
|
||||
* If multiple error is injected, only the last injection is stored.
|
||||
*
|
||||
* \return 0 on success and negated errno otherwise including no metadata.
|
||||
*/
|
||||
int spdk_dix_inject_error(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
|
||||
uint32_t num_blocks, const struct spdk_dif_ctx *ctx,
|
||||
uint32_t inject_flags, uint32_t *inject_offset);
|
||||
#endif /* SPDK_DIF_H */
|
||||
|
@ -1114,7 +1114,8 @@ spdk_dix_generate(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
|
||||
|
||||
static int
|
||||
dix_verify(struct iovec *iovs, int iovcnt, struct iovec *md_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 data_iter, md_iter;
|
||||
uint32_t offset_blocks;
|
||||
@ -1138,7 +1139,7 @@ dix_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
|
||||
guard = spdk_crc16_t10dif(guard, md_buf, ctx->guard_interval);
|
||||
}
|
||||
|
||||
rc = _dif_verify(md_buf + ctx->guard_interval, guard, offset_blocks, ctx, NULL);
|
||||
rc = _dif_verify(md_buf + ctx->guard_interval, guard, offset_blocks, ctx, err_blk);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
@ -1153,7 +1154,8 @@ dix_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
|
||||
|
||||
static int
|
||||
_dix_verify_split(struct _iov_iter *data_iter, struct _iov_iter *md_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, data_buf_len;
|
||||
uint16_t guard;
|
||||
@ -1182,12 +1184,13 @@ _dix_verify_split(struct _iov_iter *data_iter, struct _iov_iter *md_iter,
|
||||
|
||||
_iov_iter_advance(md_iter, ctx->md_size);
|
||||
|
||||
return _dif_verify(md_buf + ctx->guard_interval, guard, offset_blocks, ctx, NULL);
|
||||
return _dif_verify(md_buf + ctx->guard_interval, guard, offset_blocks, ctx, err_blk);
|
||||
}
|
||||
|
||||
static int
|
||||
dix_verify_split(struct iovec *iovs, int iovcnt, struct iovec *md_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 data_iter, md_iter;
|
||||
uint32_t offset_blocks;
|
||||
@ -1199,7 +1202,7 @@ dix_verify_split(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
|
||||
|
||||
while (offset_blocks < num_blocks &&
|
||||
_iov_iter_cont(&data_iter) && _iov_iter_cont(&md_iter)) {
|
||||
rc = _dix_verify_split(&data_iter, &md_iter, offset_blocks, ctx);
|
||||
rc = _dix_verify_split(&data_iter, &md_iter, offset_blocks, ctx, err_blk);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
@ -1211,7 +1214,8 @@ dix_verify_split(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
|
||||
|
||||
int
|
||||
spdk_dix_verify(struct iovec *iovs, int iovcnt, struct iovec *md_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)
|
||||
{
|
||||
if (!_are_iovs_valid(iovs, iovcnt, ctx->block_size * num_blocks) ||
|
||||
!_are_iovs_valid(md_iov, 1, ctx->md_size * num_blocks)) {
|
||||
@ -1224,8 +1228,71 @@ spdk_dix_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
|
||||
}
|
||||
|
||||
if (_are_iovs_bytes_multiple(iovs, iovcnt, ctx->block_size)) {
|
||||
return dix_verify(iovs, iovcnt, md_iov, num_blocks, ctx);
|
||||
return dix_verify(iovs, iovcnt, md_iov, num_blocks, ctx, err_blk);
|
||||
} else {
|
||||
return dix_verify_split(iovs, iovcnt, md_iov, num_blocks, ctx);
|
||||
return dix_verify_split(iovs, iovcnt, md_iov, num_blocks, ctx, err_blk);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
spdk_dix_inject_error(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
|
||||
uint32_t num_blocks, const struct spdk_dif_ctx *ctx,
|
||||
uint32_t inject_flags, uint32_t *inject_offset)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (!_are_iovs_valid(iovs, iovcnt, ctx->block_size * num_blocks) ||
|
||||
!_are_iovs_valid(md_iov, 1, ctx->md_size * num_blocks)) {
|
||||
SPDK_ERRLOG("Size of iovec array is not valid.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (inject_flags & SPDK_DIF_REFTAG_ERROR) {
|
||||
rc = dif_inject_error(md_iov, 1, ctx->md_size, num_blocks,
|
||||
ctx->guard_interval + offsetof(struct spdk_dif, ref_tag),
|
||||
_member_size(struct spdk_dif, ref_tag),
|
||||
inject_offset);
|
||||
if (rc != 0) {
|
||||
SPDK_ERRLOG("Failed to inject error to Reference Tag.\n");
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if (inject_flags & SPDK_DIF_APPTAG_ERROR) {
|
||||
rc = dif_inject_error(md_iov, 1, ctx->md_size, num_blocks,
|
||||
ctx->guard_interval + offsetof(struct spdk_dif, app_tag),
|
||||
_member_size(struct spdk_dif, app_tag),
|
||||
inject_offset);
|
||||
if (rc != 0) {
|
||||
SPDK_ERRLOG("Failed to inject error to Application Tag.\n");
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if (inject_flags & SPDK_DIF_GUARD_ERROR) {
|
||||
rc = dif_inject_error(md_iov, 1, ctx->md_size, num_blocks,
|
||||
ctx->guard_interval,
|
||||
_member_size(struct spdk_dif, guard),
|
||||
inject_offset);
|
||||
if (rc != 0) {
|
||||
SPDK_ERRLOG("Failed to inject error to Guard.\n");
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if (inject_flags & SPDK_DIF_DATA_ERROR) {
|
||||
/* Note: Error injection to data block is expected to be detected
|
||||
* as guard error.
|
||||
*/
|
||||
rc = dif_inject_error(iovs, iovcnt, ctx->block_size, num_blocks,
|
||||
0,
|
||||
ctx->block_size,
|
||||
inject_offset);
|
||||
if (rc != 0) {
|
||||
SPDK_ERRLOG("Failed to inject error to Guard.\n");
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1036,7 +1036,7 @@ dix_generate_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
|
||||
rc = spdk_dix_generate(iovs, iovcnt, md_iov, num_blocks, &ctx);
|
||||
CU_ASSERT(rc == 0);
|
||||
|
||||
rc = spdk_dix_verify(iovs, iovcnt, md_iov, num_blocks, &ctx);
|
||||
rc = spdk_dix_verify(iovs, iovcnt, md_iov, num_blocks, &ctx, NULL);
|
||||
CU_ASSERT(rc == 0);
|
||||
|
||||
rc = ut_data_pattern_verify(iovs, iovcnt, block_size, 0, num_blocks);
|
||||
@ -1176,6 +1176,106 @@ dix_sec_512_md_8_prchk_7_multi_iovs_complex_splits(void)
|
||||
_iov_free_buf(&md_iov);
|
||||
}
|
||||
|
||||
static void
|
||||
_dix_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_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, 0, num_blocks);
|
||||
CU_ASSERT(rc == 0);
|
||||
|
||||
rc = spdk_dif_ctx_init(&ctx, block_size, md_size, false, dif_loc, SPDK_DIF_TYPE1, dif_flags,
|
||||
88, 0xFFFF, 0x88);
|
||||
CU_ASSERT(rc == 0);
|
||||
|
||||
rc = spdk_dix_generate(iovs, iovcnt, md_iov, num_blocks, &ctx);
|
||||
CU_ASSERT(rc == 0);
|
||||
|
||||
rc = spdk_dix_inject_error(iovs, iovcnt, md_iov, num_blocks, &ctx, inject_flags, &inject_offset);
|
||||
CU_ASSERT(rc == 0);
|
||||
|
||||
rc = spdk_dix_verify(iovs, iovcnt, md_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
|
||||
dix_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_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. */
|
||||
_dix_inject_error_and_verify(iovs, iovcnt, md_iov, block_size, md_size, num_blocks,
|
||||
inject_flags, false);
|
||||
|
||||
/* The case that DIF is contained in the last 8 bytes of metadata. */
|
||||
_dix_inject_error_and_verify(iovs, iovcnt, md_iov, block_size, md_size, num_blocks,
|
||||
inject_flags, true);
|
||||
}
|
||||
|
||||
static void
|
||||
dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test(void)
|
||||
{
|
||||
struct iovec iovs[4], md_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(&md_iov, 128 * num_blocks);
|
||||
|
||||
dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, SPDK_DIF_GUARD_ERROR);
|
||||
dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, SPDK_DIF_APPTAG_ERROR);
|
||||
dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, SPDK_DIF_REFTAG_ERROR);
|
||||
dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, SPDK_DIF_DATA_ERROR);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
_iov_free_buf(&iovs[i]);
|
||||
}
|
||||
_iov_free_buf(&md_iov);
|
||||
}
|
||||
|
||||
static void
|
||||
dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test(void)
|
||||
{
|
||||
struct iovec iovs[4], md_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(&md_iov, 128 * 2);
|
||||
|
||||
dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2, SPDK_DIF_GUARD_ERROR);
|
||||
dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2, SPDK_DIF_APPTAG_ERROR);
|
||||
dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2, SPDK_DIF_REFTAG_ERROR);
|
||||
dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2, SPDK_DIF_DATA_ERROR);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
_iov_free_buf(&iovs[i]);
|
||||
}
|
||||
_iov_free_buf(&md_iov);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@ -1254,7 +1354,11 @@ main(int argc, char **argv)
|
||||
CU_add_test(suite, "dix_sec_512_md_8_prchk_7_multi_iovs_split_data",
|
||||
dix_sec_512_md_8_prchk_7_multi_iovs_split_data) == NULL ||
|
||||
CU_add_test(suite, "dix_sec_512_md_8_prchk_7_multi_iovs_complex_splits",
|
||||
dix_sec_512_md_8_prchk_7_multi_iovs_complex_splits) == NULL
|
||||
dix_sec_512_md_8_prchk_7_multi_iovs_complex_splits) == NULL ||
|
||||
CU_add_test(suite, "dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test",
|
||||
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_cleanup_registry();
|
||||
return CU_get_error();
|
||||
|
Loading…
Reference in New Issue
Block a user