From 2696886c75f1c7a99ccd89f38da68b1f12aa4d6f Mon Sep 17 00:00:00 2001 From: Alexey Marchuk Date: Wed, 6 Oct 2021 18:24:07 +0300 Subject: [PATCH] dma: Update translation result to hold iovec pointer In some cases a single virtually contriguos memory buffer can be translated to several chunks of memory. To make such translation possible, update structure spdk_memory_domain_translation_result to use a pointer to iovec. Add a single iov structure or cases where translation is always 1:1, it will make easier translation callback implementation. For RDMA transport translation of address is always 1:1, so treat iovcnt other than 1 as an error. Change-Id: I65605575d43a490490eba72c1eb19f3a09d55ec6 Signed-off-by: Alexey Marchuk Signed-off-by: Max Gurtovoy Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9779 Community-CI: Broadcom CI Tested-by: SPDK CI Jenkins Reviewed-by: Ben Walker Reviewed-by: Jim Harris --- include/spdk/dma.h | 12 ++++++++---- lib/nvme/nvme_rdma.c | 8 ++++---- test/dma/test_dma/test_dma.c | 5 +++-- test/unit/lib/nvme/nvme_rdma.c/nvme_rdma_ut.c | 6 ++++++ 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/include/spdk/dma.h b/include/spdk/dma.h index 545837043..6fc23d5cf 100644 --- a/include/spdk/dma.h +++ b/include/spdk/dma.h @@ -120,10 +120,14 @@ typedef int (*spdk_memory_domain_push_data_cb)(struct spdk_memory_domain *dst_do struct spdk_memory_domain_translation_result { /** size of this structure in bytes */ size_t size; - /** Address of data buffer translated into destination memory domain space */ - void *addr; - /** Size of the data buffer */ - size_t len; + /** Number of elements in iov */ + uint32_t iov_count; + /** Translation results, holds single address, length pair. Should only be used if \b iov_count is 1 */ + struct iovec iov; + /** Translation results, array of addresses and lengths. Should only be used if \b iov_count is + * bigger than 1. The implementer of the translation callback is responsible for allocating and + * storing of this array until IO request completes */ + struct iovec *iovs; /** Destination domain passed to translation function */ struct spdk_memory_domain *dst_domain; union { diff --git a/lib/nvme/nvme_rdma.c b/lib/nvme/nvme_rdma.c index 904085ef7..902f7a0a0 100644 --- a/lib/nvme/nvme_rdma.c +++ b/lib/nvme/nvme_rdma.c @@ -1375,15 +1375,15 @@ nvme_rdma_get_memory_translation(struct nvme_request *req, struct nvme_rdma_qpai req->payload.opts->memory_domain_ctx, rqpair->memory_domain->domain, &ctx, _ctx->addr, _ctx->length, &dma_translation); - if (spdk_unlikely(rc)) { - SPDK_ERRLOG("DMA memory translation failed, rc %d\n", rc); + if (spdk_unlikely(rc) || dma_translation.iov_count != 1) { + SPDK_ERRLOG("DMA memory translation failed, rc %d, iov count %u\n", rc, dma_translation.iov_count); return rc; } _ctx->lkey = dma_translation.rdma.lkey; _ctx->rkey = dma_translation.rdma.rkey; - _ctx->addr = dma_translation.addr; - _ctx->length = dma_translation.len; + _ctx->addr = dma_translation.iov.iov_base; + _ctx->length = dma_translation.iov.iov_len; } else { rc = spdk_rdma_get_translation(rqpair->mr_map, _ctx->addr, _ctx->length, &rdma_translation); if (spdk_unlikely(rc)) { diff --git a/test/dma/test_dma/test_dma.c b/test/dma/test_dma/test_dma.c index 911de7e97..e9373dbf6 100644 --- a/test/dma/test_dma/test_dma.c +++ b/test/dma/test_dma/test_dma.c @@ -94,8 +94,9 @@ dma_test_translate_memory_cb(struct spdk_memory_domain *src_domain, void *src_do return -1; } - result->len = len; - result->addr = addr; + result->iov.iov_base = addr; + result->iov.iov_len = len; + result->iov_count = 1; result->rdma.lkey = ctx->mr->lkey; result->rdma.rkey = ctx->mr->rkey; result->dst_domain = dst_domain; diff --git a/test/unit/lib/nvme/nvme_rdma.c/nvme_rdma_ut.c b/test/unit/lib/nvme/nvme_rdma.c/nvme_rdma_ut.c index 5efcd9d46..6af2316f1 100644 --- a/test/unit/lib/nvme/nvme_rdma.c/nvme_rdma_ut.c +++ b/test/unit/lib/nvme/nvme_rdma.c/nvme_rdma_ut.c @@ -1274,12 +1274,18 @@ test_rdma_get_memory_translation(void) MOCK_CLEAR(spdk_memory_domain_translate_data); /* Test 2 - expect pass */ + g_memory_translation_translation.iov_count = 1; + g_memory_translation_translation.iov.iov_base = ctx.addr + 1; + g_memory_translation_translation.iov.iov_len = ctx.length; g_memory_translation_translation.rdma.lkey = 123; g_memory_translation_translation.rdma.rkey = 321; + rc = nvme_rdma_get_memory_translation(&req, &rqpair, &ctx); CU_ASSERT(rc == 0); CU_ASSERT(ctx.lkey == g_memory_translation_translation.rdma.lkey); CU_ASSERT(ctx.rkey == g_memory_translation_translation.rdma.rkey); + CU_ASSERT(ctx.addr == g_memory_translation_translation.iov.iov_base); + CU_ASSERT(ctx.length == g_memory_translation_translation.iov.iov_len); /* case 2, using rdma translation * Test 1 - spdk_rdma_get_translation error, expect fail */