diff --git a/CHANGELOG.md b/CHANGELOG.md index 0cb265a6a..d89a5f09a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ ## v22.05: (Upcoming Release) +### util + +A new parameter `bounce_iovcnt` was added to `spdk_dif_generate_copy` and `spdk_dif_verify_copy`. +The `bounce_iovcnt` is used to specify the number of bounce_iov to support multiple block-aligned +fragment copies. + ### bdev Removed deprecated spdk_bdev_module_finish_done(). Use spdk_bdev_module_fini_done() instead. diff --git a/include/spdk/dif.h b/include/spdk/dif.h index 7d4006dab..98694adc2 100644 --- a/include/spdk/dif.h +++ b/include/spdk/dif.h @@ -220,29 +220,33 @@ int spdk_dif_update_crc32c(struct iovec *iovs, int iovcnt, uint32_t num_blocks, * * \param iovs iovec array describing the LBA payload. * \param iovcnt Number of elements in the iovec array. - * \param bounce_iov A contiguous buffer forming extended LBA payload. + * \param bounce_iovs A contiguous buffer forming extended LBA payload. + * \param bounce_iovcnt Number of elements in the bounce_iovs array. * \param num_blocks Number of blocks of the LBA payload. * \param ctx DIF context. * * \return 0 on success and negated errno otherwise. */ -int spdk_dif_generate_copy(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov, - uint32_t num_blocks, const struct spdk_dif_ctx *ctx); +int spdk_dif_generate_copy(struct iovec *iovs, int iovcnt, struct iovec *bounce_iovs, + int bounce_iovcnt, uint32_t num_blocks, + const struct spdk_dif_ctx *ctx); /** * Verify DIF and copy data for extended LBA payload. * * \param iovs iovec array describing the LBA payload. * \param iovcnt Number of elements in the iovec array. - * \param bounce_iov A contiguous buffer forming extended LBA payload. + * \param bounce_iovs A contiguous buffer forming extended LBA payload. + * \param bounce_iovcnt Number of elements in the bounce_iovs array. * \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, +int spdk_dif_verify_copy(struct iovec *iovs, int iovcnt, struct iovec *bounce_iovs, + int bounce_iovcnt, uint32_t num_blocks, + const struct spdk_dif_ctx *ctx, struct spdk_dif_error *err_blk); /** diff --git a/lib/util/dif.c b/lib/util/dif.c index f661c6748..cc76dbb53 100644 --- a/lib/util/dif.c +++ b/lib/util/dif.c @@ -143,6 +143,22 @@ _dif_sgl_is_bytes_multiple(struct _dif_sgl *s, uint32_t bytes) return true; } +static bool +_dif_sgl_is_valid_block_aligned(struct _dif_sgl *s, uint32_t num_blocks, uint32_t block_size) +{ + uint32_t count = 0; + int i; + + for (i = 0; i < s->iovcnt; i++) { + if (s->iov[i].iov_len % block_size) { + return false; + } + count += s->iov[i].iov_len / block_size; + } + + return count >= num_blocks; +} + /* This function must be used before starting iteration. */ static bool _dif_sgl_is_valid(struct _dif_sgl *s, uint32_t bytes) @@ -880,23 +896,28 @@ dif_generate_copy_split(struct _dif_sgl *src_sgl, struct _dif_sgl *dst_sgl, } int -spdk_dif_generate_copy(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov, - uint32_t num_blocks, const struct spdk_dif_ctx *ctx) +spdk_dif_generate_copy(struct iovec *iovs, int iovcnt, struct iovec *bounce_iovs, + int bounce_iovcnt, uint32_t num_blocks, + const struct spdk_dif_ctx *ctx) { struct _dif_sgl src_sgl, dst_sgl; uint32_t data_block_size; _dif_sgl_init(&src_sgl, iovs, iovcnt); - _dif_sgl_init(&dst_sgl, bounce_iov, 1); + _dif_sgl_init(&dst_sgl, bounce_iovs, bounce_iovcnt); data_block_size = ctx->block_size - ctx->md_size; - if (!_dif_sgl_is_valid(&src_sgl, data_block_size * num_blocks) || - !_dif_sgl_is_valid(&dst_sgl, ctx->block_size * num_blocks)) { + if (!_dif_sgl_is_valid(&src_sgl, data_block_size * num_blocks)) { SPDK_ERRLOG("Size of iovec arrays are not valid.\n"); return -EINVAL; } + if (!_dif_sgl_is_valid_block_aligned(&dst_sgl, num_blocks, ctx->block_size)) { + SPDK_ERRLOG("Size of bounce_iovs arrays are not valid or misaligned with block_size.\n"); + return -EINVAL; + } + if (_dif_is_disabled(ctx->dif_type)) { return 0; } @@ -1013,24 +1034,29 @@ dif_verify_copy_split(struct _dif_sgl *src_sgl, struct _dif_sgl *dst_sgl, } int -spdk_dif_verify_copy(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov, - uint32_t num_blocks, const struct spdk_dif_ctx *ctx, +spdk_dif_verify_copy(struct iovec *iovs, int iovcnt, struct iovec *bounce_iovs, + int bounce_iovcnt, uint32_t num_blocks, + const struct spdk_dif_ctx *ctx, struct spdk_dif_error *err_blk) { struct _dif_sgl src_sgl, dst_sgl; uint32_t data_block_size; - _dif_sgl_init(&src_sgl, bounce_iov, 1); + _dif_sgl_init(&src_sgl, bounce_iovs, bounce_iovcnt); _dif_sgl_init(&dst_sgl, iovs, iovcnt); data_block_size = ctx->block_size - ctx->md_size; - if (!_dif_sgl_is_valid(&dst_sgl, data_block_size * num_blocks) || - !_dif_sgl_is_valid(&src_sgl, ctx->block_size * num_blocks)) { + if (!_dif_sgl_is_valid(&dst_sgl, data_block_size * num_blocks)) { SPDK_ERRLOG("Size of iovec arrays are not valid\n"); return -EINVAL; } + if (!_dif_sgl_is_valid_block_aligned(&src_sgl, num_blocks, ctx->block_size)) { + SPDK_ERRLOG("Size of bounce_iovs arrays are not valid or misaligned with block_size.\n"); + return -EINVAL; + } + if (_dif_is_disabled(ctx->dif_type)) { return 0; } diff --git a/test/unit/lib/util/dif.c/dif_ut.c b/test/unit/lib/util/dif.c/dif_ut.c index e493f6e44..471017efc 100644 --- a/test/unit/lib/util/dif.c/dif_ut.c +++ b/test/unit/lib/util/dif.c/dif_ut.c @@ -824,10 +824,10 @@ dif_copy_gen_and_verify(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov init_ref_tag, apptag_mask, app_tag, 0, GUARD_SEED); CU_ASSERT(rc == 0); - rc = spdk_dif_generate_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx); + rc = spdk_dif_generate_copy(iovs, iovcnt, bounce_iov, 1, num_blocks, &ctx); CU_ASSERT(rc == 0); - rc = spdk_dif_verify_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx, NULL); + rc = spdk_dif_verify_copy(iovs, iovcnt, bounce_iov, 1, num_blocks, &ctx, NULL); CU_ASSERT(rc == 0); rc = ut_data_pattern_verify(iovs, iovcnt, block_size - md_size, 0, num_blocks); @@ -995,13 +995,13 @@ _dif_copy_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec * 88, 0xFFFF, 0x88, 0, GUARD_SEED); SPDK_CU_ASSERT_FATAL(rc == 0); - rc = spdk_dif_generate_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx); + rc = spdk_dif_generate_copy(iovs, iovcnt, bounce_iov, 1, 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); + rc = spdk_dif_verify_copy(iovs, iovcnt, bounce_iov, 1, 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);