nvme/tcp: Support extended LBA payload in nvme_tcp_build_iovs
When pdu->dif_ctx is not NULL, call spdk_dif_set_md_interleave_iovs in nvme_tcp_build_iovs and nvme_tcp_build_payload_iovs to create special SGL for the data segment to leave a space of metadata for each block. Add UT to verify if the update works correctly. This update is very similar with the use case of spdk_dif_set_md_interleave_iovs in iSCSI target. Change-Id: Ie802cb4b7c541089579ecc2a630fc1e34004da55 Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/458923 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
This commit is contained in:
parent
2c4d313367
commit
ced3e20709
@ -278,6 +278,51 @@ _nvme_tcp_sgl_append_multi(struct _nvme_tcp_sgl *s, struct iovec *iov, int iovcn
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
_get_iov_array_size(struct iovec *iov, int iovcnt)
|
||||
{
|
||||
int i;
|
||||
uint32_t size = 0;
|
||||
|
||||
for (i = 0; i < iovcnt; i++) {
|
||||
size += iov[i].iov_len;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
_nvme_tcp_sgl_append_multi_with_md(struct _nvme_tcp_sgl *s, struct iovec *iov, int iovcnt,
|
||||
uint32_t data_len, const struct spdk_dif_ctx *dif_ctx)
|
||||
{
|
||||
int rc;
|
||||
uint32_t mapped_len = 0;
|
||||
|
||||
if (s->iov_offset >= data_len) {
|
||||
s->iov_offset -= _get_iov_array_size(iov, iovcnt);
|
||||
} else {
|
||||
rc = spdk_dif_set_md_interleave_iovs(s->iov, s->iovcnt, iov, iovcnt,
|
||||
s->iov_offset, data_len - s->iov_offset,
|
||||
&mapped_len, dif_ctx);
|
||||
if (rc < 0) {
|
||||
SPDK_ERRLOG("Failed to setup iovs for DIF insert/strip.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
s->total_size += mapped_len;
|
||||
s->iov_offset = 0;
|
||||
assert(s->iovcnt >= rc);
|
||||
s->iovcnt -= rc;
|
||||
s->iov += rc;
|
||||
|
||||
if (s->iovcnt == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
nvme_tcp_build_iovs(struct iovec *iov, int iovcnt, struct nvme_tcp_pdu *pdu,
|
||||
bool hdgst_enable, bool ddgst_enable, uint32_t *_mapped_length)
|
||||
@ -326,8 +371,15 @@ nvme_tcp_build_iovs(struct iovec *iov, int iovcnt, struct nvme_tcp_pdu *pdu,
|
||||
|
||||
/* Data Segment */
|
||||
plen += pdu->data_len;
|
||||
if (!_nvme_tcp_sgl_append_multi(sgl, pdu->data_iov, pdu->data_iovcnt)) {
|
||||
goto end;
|
||||
if (spdk_likely(!pdu->dif_ctx)) {
|
||||
if (!_nvme_tcp_sgl_append_multi(sgl, pdu->data_iov, pdu->data_iovcnt)) {
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
if (!_nvme_tcp_sgl_append_multi_with_md(sgl, pdu->data_iov, pdu->data_iovcnt,
|
||||
pdu->data_len, pdu->dif_ctx)) {
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
/* Data Digest */
|
||||
@ -362,8 +414,15 @@ nvme_tcp_build_payload_iovs(struct iovec *iov, int iovcnt, struct nvme_tcp_pdu *
|
||||
sgl = &pdu->sgl;
|
||||
_nvme_tcp_sgl_init(sgl, iov, iovcnt, pdu->readv_offset);
|
||||
|
||||
if (!_nvme_tcp_sgl_append_multi(sgl, pdu->data_iov, pdu->data_iovcnt)) {
|
||||
goto end;
|
||||
if (spdk_likely(!pdu->dif_ctx)) {
|
||||
if (!_nvme_tcp_sgl_append_multi(sgl, pdu->data_iov, pdu->data_iovcnt)) {
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
if (!_nvme_tcp_sgl_append_multi_with_md(sgl, pdu->data_iov, pdu->data_iovcnt,
|
||||
pdu->data_len, pdu->dif_ctx)) {
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
/* Data Digest */
|
||||
|
@ -386,6 +386,73 @@ test_nvme_tcp_pdu_set_data_buf_with_md(void)
|
||||
CU_ASSERT(pdu.data_iov[1].iov_len == 88);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nvme_tcp_build_iovs_with_md(void)
|
||||
{
|
||||
struct nvme_tcp_pdu pdu = {};
|
||||
struct iovec iovs[11] = {};
|
||||
struct spdk_dif_ctx dif_ctx = {};
|
||||
uint32_t mapped_length = 0;
|
||||
int rc;
|
||||
|
||||
rc = spdk_dif_ctx_init(&dif_ctx, 520, 8, true, false, SPDK_DIF_DISABLE, 0,
|
||||
0, 0, 0, 0, 0);
|
||||
CU_ASSERT(rc == 0);
|
||||
|
||||
pdu.dif_ctx = &dif_ctx;
|
||||
|
||||
pdu.hdr.common.pdu_type = SPDK_NVME_TCP_PDU_TYPE_CAPSULE_CMD;
|
||||
pdu.hdr.common.hlen = sizeof(struct spdk_nvme_tcp_cmd);
|
||||
pdu.hdr.common.plen = pdu.hdr.common.hlen + SPDK_NVME_TCP_DIGEST_LEN + 512 * 8 +
|
||||
SPDK_NVME_TCP_DIGEST_LEN;
|
||||
pdu.data_len = 512 * 8;
|
||||
pdu.padding_len = 0;
|
||||
|
||||
pdu.data_iov[0].iov_base = (void *)0xDEADBEEF;
|
||||
pdu.data_iov[0].iov_len = (512 + 8) * 8;
|
||||
pdu.data_iovcnt = 1;
|
||||
|
||||
pdu.writev_offset = 0;
|
||||
|
||||
rc = nvme_tcp_build_iovs(iovs, 11, &pdu, true, true, &mapped_length);
|
||||
CU_ASSERT(rc == 10);
|
||||
CU_ASSERT(iovs[0].iov_base == (void *)&pdu.hdr.raw);
|
||||
CU_ASSERT(iovs[0].iov_len == sizeof(struct spdk_nvme_tcp_cmd) + SPDK_NVME_TCP_DIGEST_LEN);
|
||||
CU_ASSERT(iovs[1].iov_base == (void *)0xDEADBEEF);
|
||||
CU_ASSERT(iovs[1].iov_len == 512);
|
||||
CU_ASSERT(iovs[2].iov_base == (void *)(0xDEADBEEF + 520));
|
||||
CU_ASSERT(iovs[2].iov_len == 512);
|
||||
CU_ASSERT(iovs[3].iov_base == (void *)(0xDEADBEEF + 520 * 2));
|
||||
CU_ASSERT(iovs[3].iov_len == 512);
|
||||
CU_ASSERT(iovs[4].iov_base == (void *)(0xDEADBEEF + 520 * 3));
|
||||
CU_ASSERT(iovs[4].iov_len == 512);
|
||||
CU_ASSERT(iovs[5].iov_base == (void *)(0xDEADBEEF + 520 * 4));
|
||||
CU_ASSERT(iovs[5].iov_len == 512);
|
||||
CU_ASSERT(iovs[6].iov_base == (void *)(0xDEADBEEF + 520 * 5));
|
||||
CU_ASSERT(iovs[6].iov_len == 512);
|
||||
CU_ASSERT(iovs[7].iov_base == (void *)(0xDEADBEEF + 520 * 6));
|
||||
CU_ASSERT(iovs[7].iov_len == 512);
|
||||
CU_ASSERT(iovs[8].iov_base == (void *)(0xDEADBEEF + 520 * 7));
|
||||
CU_ASSERT(iovs[8].iov_len == 512);
|
||||
CU_ASSERT(iovs[9].iov_base == (void *)pdu.data_digest);
|
||||
CU_ASSERT(iovs[9].iov_len == SPDK_NVME_TCP_DIGEST_LEN);
|
||||
CU_ASSERT(mapped_length == sizeof(struct spdk_nvme_tcp_cmd) + SPDK_NVME_TCP_DIGEST_LEN +
|
||||
512 * 8 + SPDK_NVME_TCP_DIGEST_LEN);
|
||||
|
||||
pdu.writev_offset += sizeof(struct spdk_nvme_tcp_cmd) + SPDK_NVME_TCP_DIGEST_LEN +
|
||||
512 * 6 + 256;
|
||||
|
||||
rc = nvme_tcp_build_iovs(iovs, 11, &pdu, true, true, &mapped_length);
|
||||
CU_ASSERT(rc == 3);
|
||||
CU_ASSERT(iovs[0].iov_base == (void *)(0xDEADBEEF + (520 * 6) + 256));
|
||||
CU_ASSERT(iovs[0].iov_len == 256);
|
||||
CU_ASSERT(iovs[1].iov_base == (void *)(0xDEADBEEF + 520 * 7));
|
||||
CU_ASSERT(iovs[1].iov_len == 512);
|
||||
CU_ASSERT(iovs[2].iov_base == (void *)pdu.data_digest);
|
||||
CU_ASSERT(iovs[2].iov_len == SPDK_NVME_TCP_DIGEST_LEN);
|
||||
CU_ASSERT(mapped_length == 256 + 512 + SPDK_NVME_TCP_DIGEST_LEN);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CU_pSuite suite = NULL;
|
||||
@ -408,7 +475,9 @@ int main(int argc, char **argv)
|
||||
CU_add_test(suite, "build_sgl_request",
|
||||
test_nvme_tcp_build_sgl_request) == NULL ||
|
||||
CU_add_test(suite, "nvme_tcp_pdu_set_data_buf_with_md",
|
||||
test_nvme_tcp_pdu_set_data_buf_with_md) == NULL
|
||||
test_nvme_tcp_pdu_set_data_buf_with_md) == NULL ||
|
||||
CU_add_test(suite, "nvme_tcp_build_iovs_with_md",
|
||||
test_nvme_tcp_build_iovs_with_md) == NULL
|
||||
) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
|
Loading…
Reference in New Issue
Block a user