From 5fd9561f54daa8eff7f3bcb56c789655bca846b1 Mon Sep 17 00:00:00 2001 From: Alexey Marchuk Date: Thu, 21 Apr 2022 17:37:50 +0300 Subject: [PATCH] dma: Add memzero function Add functions to set and call memzero callback to memory domains library. Signed-off-by: Alexey Marchuk Change-Id: Ia6ddc3c9e0ca6e9172189964d180444e5da71d30 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/12343 Community-CI: Mellanox Build Bot Community-CI: Broadcom CI Reviewed-by: Jim Harris Reviewed-by: Tomasz Zawadzki Reviewed-by: Shuhei Matsumoto Reviewed-by: Ben Walker Tested-by: SPDK CI Jenkins --- include/spdk/dma.h | 40 ++++++++++++++++++++++++- lib/dma/dma.c | 27 +++++++++++++++++ lib/dma/spdk_dma.map | 2 ++ test/unit/lib/dma/dma.c/dma_ut.c | 50 +++++++++++++++++++++++++++----- 4 files changed, 110 insertions(+), 9 deletions(-) diff --git a/include/spdk/dma.h b/include/spdk/dma.h index 1af9b4519..2456e96d2 100644 --- a/include/spdk/dma.h +++ b/include/spdk/dma.h @@ -71,7 +71,7 @@ enum spdk_dma_device_type { struct spdk_memory_domain; /** - * Definition of completion callback to be called by pull or push functions. + * Definition of completion callback to be called by pull, push or memzero functions. * * \param ctx User context passed to pull of push functions * \param rc Result of asynchronous data pull or push function @@ -117,6 +117,20 @@ typedef int (*spdk_memory_domain_push_data_cb)(struct spdk_memory_domain *dst_do struct iovec *dst_iov, uint32_t dst_iovcnt, struct iovec *src_iov, uint32_t src_iovcnt, spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg); +/** + * Definition of function which asynchronously fills memory in \b domain with zeroes + * + * \param domain Memory domain in which address space data buffer is located + * \param domain_ctx User defined context + * \param iov iov in \b domain memory space to be filled with zeroes + * \param iovcnt \b iov array size + * \param cpl_cb Completion callback + * \param cpl_cb_arg Completion callback argument + * \return 0 on success, negated errno on failure + */ +typedef int (*spdk_memory_domain_memzero_cb)(struct spdk_memory_domain *domain, void *domain_ctx, + struct iovec *iov, uint32_t iovcnt, spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg); + struct spdk_memory_domain_translation_result { /** size of this structure in bytes */ size_t size; @@ -228,6 +242,15 @@ void spdk_memory_domain_set_pull(struct spdk_memory_domain *domain, void spdk_memory_domain_set_push(struct spdk_memory_domain *domain, spdk_memory_domain_push_data_cb push_cb); +/** + * Set memzero function for memory domain. Overwrites existing memzero function. + * + * \param domain Memory domain + * \param memzero_cb memzero function + */ +void spdk_memory_domain_set_memzero(struct spdk_memory_domain *domain, + spdk_memory_domain_memzero_cb memzero_cb); + /** * Get the context passed by the user in \ref spdk_memory_domain_create * @@ -319,6 +342,21 @@ int spdk_memory_domain_translate_data(struct spdk_memory_domain *src_domain, voi struct spdk_memory_domain *dst_domain, struct spdk_memory_domain_translation_ctx *dst_domain_ctx, void *addr, size_t len, struct spdk_memory_domain_translation_result *result); +/** + * Fills memory in \b domain with zeroes + * + * \param domain Memory domain in which address space data buffer is located + * \param domain_ctx User defined context + * \param iov iov in \b domain memory space to be filled with zeroes + * \param iovcnt \b iov array size + * \param cpl_cb Completion callback + * \param cpl_cb_arg Completion callback argument + * \return 0 on success, negated errno on failure. memzero implementation must only call the callback when 0 + * is returned + */ +int spdk_memory_domain_memzero(struct spdk_memory_domain *domain, void *domain_ctx, + struct iovec *iov, uint32_t iovcnt, spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg); + /** * Get the first memory domain. * diff --git a/lib/dma/dma.c b/lib/dma/dma.c index 5994b8b7f..e8117ea4f 100644 --- a/lib/dma/dma.c +++ b/lib/dma/dma.c @@ -44,6 +44,7 @@ struct spdk_memory_domain { spdk_memory_domain_pull_data_cb pull_cb; spdk_memory_domain_push_data_cb push_cb; spdk_memory_domain_translate_memory_cb translate_cb; + spdk_memory_domain_memzero_cb memzero_cb; TAILQ_ENTRY(spdk_memory_domain) link; struct spdk_memory_domain_ctx *ctx; char *id; @@ -138,6 +139,17 @@ spdk_memory_domain_set_push(struct spdk_memory_domain *domain, domain->push_cb = push_cb; } +void +spdk_memory_domain_set_memzero(struct spdk_memory_domain *domain, + spdk_memory_domain_memzero_cb memzero_cb) +{ + if (!domain) { + return; + } + + domain->memzero_cb = memzero_cb; +} + struct spdk_memory_domain_ctx * spdk_memory_domain_get_context(struct spdk_memory_domain *domain) { @@ -228,6 +240,21 @@ spdk_memory_domain_translate_data(struct spdk_memory_domain *src_domain, void *s result); } +int +spdk_memory_domain_memzero(struct spdk_memory_domain *domain, void *domain_ctx, struct iovec *iov, + uint32_t iovcnt, spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg) +{ + assert(domain); + assert(iov); + assert(iovcnt); + + if (spdk_unlikely(!domain->memzero_cb)) { + return -ENOTSUP; + } + + return domain->memzero_cb(domain, domain_ctx, iov, iovcnt, cpl_cb, cpl_cb_arg); +} + struct spdk_memory_domain * spdk_memory_domain_get_first(const char *id) { diff --git a/lib/dma/spdk_dma.map b/lib/dma/spdk_dma.map index d286caf4f..f41851b9e 100644 --- a/lib/dma/spdk_dma.map +++ b/lib/dma/spdk_dma.map @@ -6,6 +6,7 @@ spdk_memory_domain_set_translation; spdk_memory_domain_set_pull; spdk_memory_domain_set_push; + spdk_memory_domain_set_memzero; spdk_memory_domain_get_context; spdk_memory_domain_get_dma_device_type; spdk_memory_domain_get_dma_device_id; @@ -13,6 +14,7 @@ spdk_memory_domain_pull_data; spdk_memory_domain_push_data; spdk_memory_domain_translate_data; + spdk_memory_domain_memzero; spdk_memory_domain_get_first; spdk_memory_domain_get_next; diff --git a/test/unit/lib/dma/dma.c/dma_ut.c b/test/unit/lib/dma/dma.c/dma_ut.c index 059982bee..acaf732ef 100644 --- a/test/unit/lib/dma/dma.c/dma_ut.c +++ b/test/unit/lib/dma/dma.c/dma_ut.c @@ -39,6 +39,7 @@ static bool g_memory_domain_pull_called; static bool g_memory_domain_push_called; static bool g_memory_domain_translate_called; +static bool g_memory_domain_memzero_called; static int g_memory_domain_cb_rc = 123; static void @@ -46,19 +47,21 @@ test_memory_domain_data_cpl_cb(void *ctx, int rc) { } -static int test_memory_domain_pull_data_cb(struct spdk_memory_domain *src_device, - void *src_device_ctx, struct iovec *src_iov, uint32_t src_iovcnt, struct iovec *dst_iov, - uint32_t dst_iovcnt, spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg) +static int +test_memory_domain_pull_data_cb(struct spdk_memory_domain *src_device, + void *src_device_ctx, struct iovec *src_iov, uint32_t src_iovcnt, struct iovec *dst_iov, + uint32_t dst_iovcnt, spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg) { g_memory_domain_pull_called = true; return g_memory_domain_cb_rc; } -static int test_memory_domain_push_data_cb(struct spdk_memory_domain *dst_domain, - void *dst_domain_ctx, - struct iovec *dst_iov, uint32_t dst_iovcnt, struct iovec *src_iov, uint32_t src_iovcnt, - spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg) +static int +test_memory_domain_push_data_cb(struct spdk_memory_domain *dst_domain, + void *dst_domain_ctx, + struct iovec *dst_iov, uint32_t dst_iovcnt, struct iovec *src_iov, uint32_t src_iovcnt, + spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg) { g_memory_domain_push_called = true; @@ -75,6 +78,15 @@ test_memory_domain_translate_memory_cb(struct spdk_memory_domain *src_device, vo return g_memory_domain_cb_rc; } +static int +test_memory_domain_memzero_cb(struct spdk_memory_domain *src_domain, void *src_domain_ctx, + struct iovec *iov, uint32_t iovcnt, spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg) +{ + g_memory_domain_memzero_called = true; + + return g_memory_domain_cb_rc; +} + static void test_dma(void) { @@ -166,6 +178,20 @@ test_dma(void) CU_ASSERT(rc == g_memory_domain_cb_rc); CU_ASSERT(g_memory_domain_translate_called == true); + /* memzero, callback is NULL. Expect fail */ + g_memory_domain_memzero_called = false; + rc = spdk_memory_domain_memzero(domain, NULL, &src_iov, 1, test_memory_domain_data_cpl_cb, NULL); + CU_ASSERT(rc == -ENOTSUP); + CU_ASSERT(g_memory_domain_memzero_called == false); + + /* Set memzero callback */ + spdk_memory_domain_set_memzero(domain, test_memory_domain_memzero_cb); + + /* memzero. Expect pass */ + rc = spdk_memory_domain_memzero(domain, NULL, &src_iov, 1, test_memory_domain_data_cpl_cb, NULL); + CU_ASSERT(rc == g_memory_domain_cb_rc); + CU_ASSERT(g_memory_domain_memzero_called == true); + /* Set translation callback to NULL. Expect pass */ spdk_memory_domain_set_translation(domain, NULL); CU_ASSERT(domain->translate_cb == NULL); @@ -178,10 +204,18 @@ test_dma(void) spdk_memory_domain_set_pull(domain, NULL); CU_ASSERT(domain->pull_cb == NULL); - /* Set translation_callback. Expect pass */ + /* Set pull callback. Expect pass */ spdk_memory_domain_set_pull(domain, test_memory_domain_pull_data_cb); CU_ASSERT(domain->pull_cb == test_memory_domain_pull_data_cb); + /* Set memzero to NULL. Expect pass */ + spdk_memory_domain_set_memzero(domain, NULL); + CU_ASSERT(domain->memzero_cb == NULL); + + /* Set memzero callback. Expect pass */ + spdk_memory_domain_set_memzero(domain, test_memory_domain_memzero_cb); + CU_ASSERT(domain->memzero_cb == test_memory_domain_memzero_cb); + /* Create 2nd and 3rd memory domains with equal id to test enumeration */ rc = spdk_memory_domain_create(&domain_2, SPDK_DMA_DEVICE_TYPE_RDMA, &memory_domain_ctx, "test_2"); CU_ASSERT(rc == 0);