nvme/tcp: Support unaligned extended LBA payload in nvme_tcp_pdu_set_data_buf
When DIF is inserted or stripped, nvme_tcp_pdu_set_data_buf must shift the range of the buffer from LBA based to extended LBA based because the extended LBA based range must be passed to create a special temporary iovec array to leave a space of metadata for each block then. This patch do the following: - Add a pointer to the current DIF context to struct nvme_tcp_pdu. This pointer is set when DIF is inserted or stripped to the current NVMf request. - When the pointer to the current DIF context in the PDU is set, get the extended LBA based offset and length by calling spdk_dif_get_range_with_md() and use them in nvme_tcp_pdu_set_data_buf(). - Original data length is set in the PDU and original data offset is set in the current DIF context in nvme_tcp_pdu_set_data_buf(). - Add UT code. Change-Id: Ic1f4fd326b5b3e3d4c74677592bda34d6949a11e Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/458920 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com> Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
This commit is contained in:
parent
457afd77b1
commit
a7a32ea052
@ -35,6 +35,7 @@
|
||||
#define SPDK_INTERNAL_NVME_TCP_H
|
||||
|
||||
#include "spdk/sock.h"
|
||||
#include "spdk/dif.h"
|
||||
|
||||
#define SPDK_CRC32C_XOR 0xffffffffUL
|
||||
#define SPDK_NVME_TCP_DIGEST_LEN 4
|
||||
@ -118,6 +119,8 @@ struct nvme_tcp_pdu {
|
||||
uint32_t padding_len;
|
||||
struct _nvme_tcp_sgl sgl;
|
||||
|
||||
struct spdk_dif_ctx *dif_ctx;
|
||||
|
||||
void *ctx; /* data tied to a tcp request */
|
||||
};
|
||||
|
||||
@ -446,32 +449,50 @@ nvme_tcp_read_payload_data(struct spdk_sock *sock, struct nvme_tcp_pdu *pdu)
|
||||
}
|
||||
|
||||
static void
|
||||
nvme_tcp_pdu_set_data(struct nvme_tcp_pdu *pdu, void *data, uint32_t data_len)
|
||||
_nvme_tcp_pdu_set_data(struct nvme_tcp_pdu *pdu, void *data, uint32_t data_len)
|
||||
{
|
||||
pdu->data_iov[0].iov_base = data;
|
||||
pdu->data_iov[0].iov_len = pdu->data_len = data_len;
|
||||
pdu->data_iov[0].iov_len = data_len;
|
||||
pdu->data_iovcnt = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
nvme_tcp_pdu_set_data(struct nvme_tcp_pdu *pdu, void *data, uint32_t data_len)
|
||||
{
|
||||
_nvme_tcp_pdu_set_data(pdu, data, data_len);
|
||||
pdu->data_len = data_len;
|
||||
}
|
||||
|
||||
static void
|
||||
nvme_tcp_pdu_set_data_buf(struct nvme_tcp_pdu *pdu,
|
||||
struct iovec *iov, int iovcnt,
|
||||
uint32_t data_offset, uint32_t data_len)
|
||||
{
|
||||
uint32_t remain_len, len;
|
||||
uint32_t buf_offset, buf_len, remain_len, len;
|
||||
uint8_t *buf;
|
||||
struct _nvme_tcp_sgl *pdu_sgl, buf_sgl;
|
||||
|
||||
pdu->data_len = data_len;
|
||||
|
||||
if (spdk_likely(!pdu->dif_ctx)) {
|
||||
buf_offset = data_offset;
|
||||
buf_len = data_len;
|
||||
} else {
|
||||
spdk_dif_ctx_set_data_offset(pdu->dif_ctx, data_offset);
|
||||
spdk_dif_get_range_with_md(data_offset, data_len,
|
||||
&buf_offset, &buf_len, pdu->dif_ctx);
|
||||
}
|
||||
|
||||
if (iovcnt == 1) {
|
||||
nvme_tcp_pdu_set_data(pdu, (void *)((uint64_t)iov[0].iov_base + data_offset), data_len);
|
||||
_nvme_tcp_pdu_set_data(pdu, (void *)((uint64_t)iov[0].iov_base + buf_offset), buf_len);
|
||||
} else {
|
||||
pdu_sgl = &pdu->sgl;
|
||||
|
||||
_nvme_tcp_sgl_init(pdu_sgl, pdu->data_iov, NVME_TCP_MAX_SGL_DESCRIPTORS, 0);
|
||||
_nvme_tcp_sgl_init(&buf_sgl, iov, iovcnt, 0);
|
||||
|
||||
_nvme_tcp_sgl_advance(&buf_sgl, data_offset);
|
||||
remain_len = data_len;
|
||||
_nvme_tcp_sgl_advance(&buf_sgl, buf_offset);
|
||||
remain_len = buf_len;
|
||||
|
||||
while (remain_len > 0) {
|
||||
_nvme_tcp_sgl_get_buf(&buf_sgl, (void *)&buf, &len);
|
||||
@ -486,10 +507,9 @@ nvme_tcp_pdu_set_data_buf(struct nvme_tcp_pdu *pdu,
|
||||
}
|
||||
|
||||
assert(remain_len == 0);
|
||||
assert(pdu_sgl->total_size == data_len);
|
||||
assert(pdu_sgl->total_size == buf_len);
|
||||
|
||||
pdu->data_iovcnt = NVME_TCP_MAX_SGL_DESCRIPTORS - pdu_sgl->iovcnt;
|
||||
pdu->data_len = data_len;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -291,6 +291,101 @@ test_nvme_tcp_build_sgl_request(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_nvme_tcp_pdu_set_data_buf_with_md(void)
|
||||
{
|
||||
struct nvme_tcp_pdu pdu = {};
|
||||
struct iovec iovs[7] = {};
|
||||
struct spdk_dif_ctx dif_ctx = {};
|
||||
int rc;
|
||||
|
||||
pdu.dif_ctx = &dif_ctx;
|
||||
|
||||
rc = spdk_dif_ctx_init(&dif_ctx, 520, 8, true, false, SPDK_DIF_DISABLE, 0,
|
||||
0, 0, 0, 0, 0);
|
||||
CU_ASSERT(rc == 0);
|
||||
|
||||
/* Single iovec case */
|
||||
iovs[0].iov_base = (void *)0xDEADBEEF;
|
||||
iovs[0].iov_len = 2080;
|
||||
|
||||
nvme_tcp_pdu_set_data_buf(&pdu, iovs, 1, 0, 500);
|
||||
|
||||
CU_ASSERT(dif_ctx.data_offset == 0);
|
||||
CU_ASSERT(pdu.data_len == 500);
|
||||
CU_ASSERT(pdu.data_iovcnt == 1);
|
||||
CU_ASSERT(pdu.data_iov[0].iov_base == (void *)0xDEADBEEF);
|
||||
CU_ASSERT(pdu.data_iov[0].iov_len == 500);
|
||||
|
||||
nvme_tcp_pdu_set_data_buf(&pdu, iovs, 1, 500, 1000);
|
||||
|
||||
CU_ASSERT(dif_ctx.data_offset == 500);
|
||||
CU_ASSERT(pdu.data_len == 1000);
|
||||
CU_ASSERT(pdu.data_iovcnt == 1);
|
||||
CU_ASSERT(pdu.data_iov[0].iov_base == (void *)(0xDEADBEEF + 500));
|
||||
CU_ASSERT(pdu.data_iov[0].iov_len == 1016);
|
||||
|
||||
nvme_tcp_pdu_set_data_buf(&pdu, iovs, 1, 1500, 548);
|
||||
|
||||
CU_ASSERT(dif_ctx.data_offset == 1500);
|
||||
CU_ASSERT(pdu.data_len == 548);
|
||||
CU_ASSERT(pdu.data_iovcnt == 1);
|
||||
CU_ASSERT(pdu.data_iov[0].iov_base == (void *)(0xDEADBEEF + 1516));
|
||||
CU_ASSERT(pdu.data_iov[0].iov_len == 564);
|
||||
|
||||
/* Multiple iovecs case */
|
||||
iovs[0].iov_base = (void *)0xDEADBEEF;
|
||||
iovs[0].iov_len = 256;
|
||||
iovs[1].iov_base = (void *)((uint8_t *)(0xDEADBEEF + 0x1000));
|
||||
iovs[1].iov_len = 256 + 1;
|
||||
iovs[2].iov_base = (void *)((uint8_t *)(0xDEADBEEF + 0x2000));
|
||||
iovs[2].iov_len = 4;
|
||||
iovs[3].iov_base = (void *)((uint8_t *)(0xDEADBEEF + 0x3000));
|
||||
iovs[3].iov_len = 3 + 123;
|
||||
iovs[4].iov_base = (void *)((uint8_t *)(0xDEADBEEF + 0x4000));
|
||||
iovs[4].iov_len = 389 + 6;
|
||||
iovs[5].iov_base = (void *)((uint8_t *)(0xDEADBEEF + 0x5000));
|
||||
iovs[5].iov_len = 2 + 512 + 8 + 432;
|
||||
iovs[6].iov_base = (void *)((uint8_t *)(0xDEADBEEF + 0x6000));
|
||||
iovs[6].iov_len = 80 + 8;
|
||||
|
||||
nvme_tcp_pdu_set_data_buf(&pdu, iovs, 7, 0, 500);
|
||||
|
||||
CU_ASSERT(dif_ctx.data_offset == 0);
|
||||
CU_ASSERT(pdu.data_len == 500);
|
||||
CU_ASSERT(pdu.data_iovcnt == 2);
|
||||
CU_ASSERT(pdu.data_iov[0].iov_base == (void *)0xDEADBEEF);
|
||||
CU_ASSERT(pdu.data_iov[0].iov_len == 256);
|
||||
CU_ASSERT(pdu.data_iov[1].iov_base == (void *)(0xDEADBEEF + 0x1000));
|
||||
CU_ASSERT(pdu.data_iov[1].iov_len == 244);
|
||||
|
||||
nvme_tcp_pdu_set_data_buf(&pdu, iovs, 7, 500, 1000);
|
||||
|
||||
CU_ASSERT(dif_ctx.data_offset == 500);
|
||||
CU_ASSERT(pdu.data_len == 1000);
|
||||
CU_ASSERT(pdu.data_iovcnt == 5);
|
||||
CU_ASSERT(pdu.data_iov[0].iov_base == (void *)(0xDEADBEEF + 0x1000 + 244));
|
||||
CU_ASSERT(pdu.data_iov[0].iov_len == 13);
|
||||
CU_ASSERT(pdu.data_iov[1].iov_base == (void *)(0xDEADBEEF + 0x2000));
|
||||
CU_ASSERT(pdu.data_iov[1].iov_len == 4);
|
||||
CU_ASSERT(pdu.data_iov[2].iov_base == (void *)(0xDEADBEEF + 0x3000));
|
||||
CU_ASSERT(pdu.data_iov[2].iov_len == 3 + 123);
|
||||
CU_ASSERT(pdu.data_iov[3].iov_base == (void *)(0xDEADBEEF + 0x4000));
|
||||
CU_ASSERT(pdu.data_iov[3].iov_len == 395);
|
||||
CU_ASSERT(pdu.data_iov[4].iov_base == (void *)(0xDEADBEEF + 0x5000));
|
||||
CU_ASSERT(pdu.data_iov[4].iov_len == 478);
|
||||
|
||||
nvme_tcp_pdu_set_data_buf(&pdu, iovs, 7, 1500, 548);
|
||||
|
||||
CU_ASSERT(dif_ctx.data_offset == 1500);
|
||||
CU_ASSERT(pdu.data_len == 548);
|
||||
CU_ASSERT(pdu.data_iovcnt == 2);
|
||||
CU_ASSERT(pdu.data_iov[0].iov_base == (void *)(0xDEADBEEF + 0x5000 + 478));
|
||||
CU_ASSERT(pdu.data_iov[0].iov_len == 476);
|
||||
CU_ASSERT(pdu.data_iov[1].iov_base == (void *)(0xDEADBEEF + 0x6000));
|
||||
CU_ASSERT(pdu.data_iov[1].iov_len == 88);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CU_pSuite suite = NULL;
|
||||
@ -311,7 +406,9 @@ int main(int argc, char **argv)
|
||||
CU_add_test(suite, "nvme_tcp_build_iovs",
|
||||
test_nvme_tcp_build_iovs) == NULL ||
|
||||
CU_add_test(suite, "build_sgl_request",
|
||||
test_nvme_tcp_build_sgl_request) == NULL
|
||||
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
|
||||
) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
|
Loading…
Reference in New Issue
Block a user