diff --git a/include/spdk/dif.h b/include/spdk/dif.h index e68d77654..578af0c62 100644 --- a/include/spdk/dif.h +++ b/include/spdk/dif.h @@ -382,4 +382,26 @@ int spdk_dif_verify_stream(struct iovec *iovs, int iovcnt, int spdk_dif_update_crc32c_stream(struct iovec *iovs, int iovcnt, uint32_t data_offset, uint32_t data_len, uint32_t *crc32c, const struct spdk_dif_ctx *ctx); +/** + * Convert offset and size from LBA based to extended LBA based. + * + * \param data_offset Data offset + * \param data_len Data length + * \param buf_offset Buffer offset converted from data offset. + * \param buf_len Buffer length converted from data length + * \param ctx DIF context. + */ +void spdk_dif_get_range_with_md(uint32_t data_offset, uint32_t data_len, + uint32_t *buf_offset, uint32_t *buf_len, + const struct spdk_dif_ctx *ctx); + +/** + * Convert length from LBA based to extended LBA based. + * + * \param data_len Data length + * \param ctx DIF context. + * + * \return Extended LBA based data length. + */ +uint32_t spdk_dif_get_length_with_md(uint32_t data_len, const struct spdk_dif_ctx *ctx); #endif /* SPDK_DIF_H */ diff --git a/lib/util/dif.c b/lib/util/dif.c index a176ce021..c01e26911 100644 --- a/lib/util/dif.c +++ b/lib/util/dif.c @@ -1681,3 +1681,48 @@ spdk_dif_update_crc32c_stream(struct iovec *iovs, int iovcnt, return 0; } + +void +spdk_dif_get_range_with_md(uint32_t data_offset, uint32_t data_len, + uint32_t *_buf_offset, uint32_t *_buf_len, + const struct spdk_dif_ctx *ctx) +{ + uint32_t data_block_size, data_unalign, buf_offset, buf_len; + + if (!ctx->md_interleave) { + buf_offset = data_offset; + buf_len = data_len; + } else { + data_block_size = ctx->block_size - ctx->md_size; + + data_unalign = data_offset % data_block_size; + + buf_offset = (data_offset / data_block_size) * ctx->block_size + + (data_offset % data_block_size); + buf_len = ((data_unalign + data_len) / data_block_size) * ctx->block_size + + ((data_unalign + data_len) % data_block_size) - data_unalign; + } + + if (_buf_offset != NULL) { + *_buf_offset = buf_offset; + } + + if (_buf_len != NULL) { + *_buf_len = buf_len; + } +} + +uint32_t +spdk_dif_get_length_with_md(uint32_t data_len, const struct spdk_dif_ctx *ctx) +{ + uint32_t data_block_size; + + if (!ctx->md_interleave) { + return data_len; + } else { + data_block_size = ctx->block_size - ctx->md_size; + + return (data_len / data_block_size) * ctx->block_size + + (data_len % data_block_size); + } +} diff --git a/test/unit/lib/util/dif.c/dif_ut.c b/test/unit/lib/util/dif.c/dif_ut.c index ac7a7f624..3018308e4 100644 --- a/test/unit/lib/util/dif.c/dif_ut.c +++ b/test/unit/lib/util/dif.c/dif_ut.c @@ -2343,6 +2343,36 @@ dif_update_crc32c_stream_multi_segments_test(void) free(buf); } +static void +get_range_with_md_test(void) +{ + struct spdk_dif_ctx ctx = {}; + uint32_t buf_offset, buf_len; + int rc; + + rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, 0, 0, 0, 0, 0, 0, 0); + CU_ASSERT(rc == 0); + + spdk_dif_get_range_with_md(0, 2048, &buf_offset, &buf_len, &ctx); + CU_ASSERT(buf_offset == 0); + CU_ASSERT(buf_len == 2048); + + spdk_dif_get_range_with_md(2048, 4096, &buf_offset, &buf_len, &ctx); + CU_ASSERT(buf_offset == 2048); + CU_ASSERT(buf_len == 4096 + 128); + + spdk_dif_get_range_with_md(4096, 10240, &buf_offset, &buf_len, &ctx); + CU_ASSERT(buf_offset == 4096 + 128); + CU_ASSERT(buf_len == 10240 + 256); + + spdk_dif_get_range_with_md(10240, 2048, &buf_offset, &buf_len, &ctx); + CU_ASSERT(buf_offset == 10240 + 256); + CU_ASSERT(buf_len == 2048 + 128); + + buf_len = spdk_dif_get_length_with_md(6144, &ctx); + CU_ASSERT(buf_len == 6144 + 128); +} + int main(int argc, char **argv) { @@ -2443,7 +2473,8 @@ main(int argc, char **argv) CU_add_test(suite, "_dif_update_crc32c_split_test", _dif_update_crc32c_split_test) == NULL || CU_add_test(suite, "dif_update_crc32c_stream_multi_segments_test", - dif_update_crc32c_stream_multi_segments_test) == NULL + dif_update_crc32c_stream_multi_segments_test) == NULL || + CU_add_test(suite, "get_range_with_md_test", get_range_with_md_test) == NULL ) { CU_cleanup_registry(); return CU_get_error();