diff --git a/include/spdk/dif.h b/include/spdk/dif.h index 6840b7791..9f030d4c0 100644 --- a/include/spdk/dif.h +++ b/include/spdk/dif.h @@ -269,8 +269,8 @@ int spdk_dix_inject_error(struct iovec *iovs, int iovcnt, struct iovec *md_iov, * * \param iovs iovec array set by this function. * \param iovcnt Number of elements in the iovec array. - * \param buf Buffer to create extended LBA payload. - * \param buf_len Length of the buffer to create extended LBA payload. + * \param buf_iovs SGL for the buffer to create extended LBA payload. + * \param buf_iovcnt Size of the SGL for the buffer to create extended LBA payload. * \param data_offset Offset to store the next incoming data. * \param data_len Expected data length of the payload. * \param mapped_len Output parameter that will contain data length mapped by @@ -281,7 +281,7 @@ int spdk_dix_inject_error(struct iovec *iovs, int iovcnt, struct iovec *md_iov, * errno otherwise. */ int spdk_dif_set_md_interleave_iovs(struct iovec *iovs, int iovcnt, - uint8_t *buf, uint32_t buf_len, + struct iovec *buf_iovs, int buf_iovcnt, uint32_t data_offset, uint32_t data_len, uint32_t *mapped_len, const struct spdk_dif_ctx *ctx); diff --git a/lib/iscsi/iscsi.c b/lib/iscsi/iscsi.c index 5b637f406..3855d521e 100644 --- a/lib/iscsi/iscsi.c +++ b/lib/iscsi/iscsi.c @@ -367,7 +367,7 @@ iscsi_conn_read_data_segment(struct spdk_iscsi_conn *conn, uint32_t segment_len) { struct spdk_dif_ctx dif_ctx; - struct iovec iovs[32]; + struct iovec buf_iov, iovs[32]; int rc, _rc; if (spdk_likely(!spdk_iscsi_get_dif_ctx(conn, pdu, &dif_ctx))) { @@ -376,8 +376,9 @@ iscsi_conn_read_data_segment(struct spdk_iscsi_conn *conn, pdu->data_buf + pdu->data_valid_bytes); } else { pdu->dif_insert_or_strip = true; - rc = spdk_dif_set_md_interleave_iovs(iovs, 32, - pdu->data_buf, pdu->data_buf_len, + buf_iov.iov_base = pdu->data_buf; + buf_iov.iov_len = pdu->data_buf_len; + rc = spdk_dif_set_md_interleave_iovs(iovs, 32, &buf_iov, 1, pdu->data_valid_bytes, segment_len, NULL, &dif_ctx); if (rc > 0) { @@ -637,12 +638,15 @@ _iov_ctx_set_md_interleave_iov(struct _iov_ctx *ctx, { int rc; uint32_t mapped_len = 0; + struct iovec buf_iov; if (ctx->iov_offset >= data_len) { ctx->iov_offset -= buf_len; } else { + buf_iov.iov_base = buf; + buf_iov.iov_len = buf_len; rc = spdk_dif_set_md_interleave_iovs(ctx->iov, ctx->num_iovs - ctx->iovcnt, - buf, buf_len, + &buf_iov, 1, ctx->iov_offset, data_len, &mapped_len, dif_ctx); if (rc < 0) { diff --git a/lib/util/dif.c b/lib/util/dif.c index 337aa6ed5..d3a08285e 100644 --- a/lib/util/dif.c +++ b/lib/util/dif.c @@ -1285,33 +1285,19 @@ spdk_dix_inject_error(struct iovec *iovs, int iovcnt, struct iovec *md_iov, return 0; } -int -spdk_dif_set_md_interleave_iovs(struct iovec *iovs, int iovcnt, - uint8_t *buf, uint32_t buf_len, - uint32_t data_offset, uint32_t data_len, - uint32_t *_mapped_len, - const struct spdk_dif_ctx *ctx) +static int +dif_set_md_interleave_iovs(struct iovec *iovs, int iovcnt, + uint8_t *buf, uint32_t buf_len, + uint32_t data_offset, uint32_t data_len, + uint32_t *_mapped_len, + const struct spdk_dif_ctx *ctx) { uint32_t data_block_size, head_unalign; uint32_t num_blocks, offset_blocks; struct _dif_sgl sgl; - if (iovs == NULL || iovcnt == 0) { - return -EINVAL; - } - data_block_size = ctx->block_size - ctx->md_size; - if ((data_len % data_block_size) != 0) { - SPDK_ERRLOG("Data length must be a multiple of data block size\n"); - return -EINVAL; - } - - if (data_offset >= data_len) { - SPDK_ERRLOG("Data offset must be smaller than data length\n"); - return -ERANGE; - } - num_blocks = data_len / data_block_size; if (buf_len < num_blocks * ctx->block_size) { @@ -1347,6 +1333,40 @@ spdk_dif_set_md_interleave_iovs(struct iovec *iovs, int iovcnt, return iovcnt - sgl.iovcnt; } +int +spdk_dif_set_md_interleave_iovs(struct iovec *iovs, int iovcnt, + struct iovec *buf_iovs, int buf_iovcnt, + uint32_t data_offset, uint32_t data_len, + uint32_t *_mapped_len, + const struct spdk_dif_ctx *ctx) +{ + uint32_t data_block_size; + + if (iovs == NULL || iovcnt == 0 || buf_iovs == NULL || buf_iovcnt == 0) { + return -EINVAL; + } + + data_block_size = ctx->block_size - ctx->md_size; + + if ((data_len % data_block_size) != 0) { + SPDK_ERRLOG("Data length must be a multiple of data block size\n"); + return -EINVAL; + } + + if (data_offset >= data_len) { + SPDK_ERRLOG("Data offset must be smaller than data length\n"); + return -ERANGE; + } + + if (buf_iovcnt == 1) { + return dif_set_md_interleave_iovs(iovs, iovcnt, + buf_iovs[0].iov_base, buf_iovs[0].iov_len, + data_offset, data_len, _mapped_len, ctx); + } else { + return -EINVAL; + } +} + int spdk_dif_generate_stream(uint8_t *buf, uint32_t buf_len, uint32_t offset, uint32_t read_len, diff --git a/test/unit/lib/util/dif.c/dif_ut.c b/test/unit/lib/util/dif.c/dif_ut.c index 42176facf..304460d9c 100644 --- a/test/unit/lib/util/dif.c/dif_ut.c +++ b/test/unit/lib/util/dif.c/dif_ut.c @@ -1410,7 +1410,7 @@ set_md_interleave_iovs_test(void) SPDK_CU_ASSERT_FATAL(buf1 != NULL); _iov_set_buf(&iov1, buf1, (4096 + 128) * 4); - rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, buf1, (4096 + 128) * 4, + rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, &iov1, 1, 0, 4096 * 4, &mapped_len, &ctx); CU_ASSERT(rc == 4); CU_ASSERT(mapped_len == 4096 * 4); @@ -1425,7 +1425,7 @@ set_md_interleave_iovs_test(void) rc = spdk_dif_generate_stream(buf1, (4096 + 128) * 4, 0, 1024, &ctx); CU_ASSERT(rc == 0); - rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, buf1, (4096 + 128) * 4, + rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, &iov1, 1, read_base, 4096 * 4, &mapped_len, &ctx); CU_ASSERT(rc == 4); CU_ASSERT(mapped_len == 3072 + 4096 * 3); @@ -1440,7 +1440,7 @@ set_md_interleave_iovs_test(void) rc = spdk_dif_generate_stream(buf1, (4096 + 128) * 4, 1024, 3071, &ctx); CU_ASSERT(rc == 0); - rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, buf1, (4096 + 128) * 4, + rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, &iov1, 1, read_base, 4096 * 4, &mapped_len, &ctx); CU_ASSERT(rc == 4); CU_ASSERT(mapped_len == 1 + 4096 * 3); @@ -1455,7 +1455,7 @@ set_md_interleave_iovs_test(void) rc = spdk_dif_generate_stream(buf1, (4096 + 128) * 4, 4095, 1 + 4096 * 2 + 512, &ctx); CU_ASSERT(rc == 0); - rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, buf1, (4096 + 128) * 4, + rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, &iov1, 1, read_base, 4096 * 4, &mapped_len, &ctx); CU_ASSERT(rc == 1); CU_ASSERT(mapped_len == 3584);