diff --git a/include/spdk/dma.h b/include/spdk/dma.h index 35bc68842..77c66c4e1 100644 --- a/include/spdk/dma.h +++ b/include/spdk/dma.h @@ -63,12 +63,12 @@ enum spdk_dma_device_type { struct spdk_memory_domain; /** - * Definition of completion callback to be called by pull function. + * Definition of completion callback to be called by pull or push functions. * - * \param ctx User context passed to pull function - * \param rc Result of asynchronous pull function + * \param ctx User context passed to pull of push functions + * \param rc Result of asynchronous data pull or push function */ -typedef void (*spdk_memory_domain_pull_data_cpl_cb)(void *ctx, int rc); +typedef void (*spdk_memory_domain_data_cpl_cb)(void *ctx, int rc); /** * Definition of function which asynchronously pulles data from src_domain to local memory domain. @@ -88,7 +88,26 @@ typedef void (*spdk_memory_domain_pull_data_cpl_cb)(void *ctx, int rc); typedef int (*spdk_memory_domain_pull_data_cb)(struct spdk_memory_domain *src_domain, void *src_domain_ctx, struct iovec *src_iov, uint32_t src_iovcnt, struct iovec *dst_iov, uint32_t dst_iovcnt, - spdk_memory_domain_pull_data_cpl_cb cpl_cb, void *cpl_cb_arg); + spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg); + +/** + * Definition of function which asynchronously pushes data from local memory to destination memory domain. + * Implementation of this function must call \b cpl_cb only when it returns 0. All other return codes mean failure. + * + * \param dst_domain Memory domain to which the data should be pushed + * \param dst_domain_ctx Optional context passed by upper layer with IO request + * \param dst_iov Iov vector in dst_domain space + * \param dst_iovcnt dst_iov array size + * \param src_iov Iov vector in local memory + * \param src_iovcnt src_iov array size + * \param cpl_cb A callback to be called when push operation completes + * \param cpl_cb_arg Optional argument to be passed to \b cpl_cb + * \return 0 on success, negated errno on failure + */ +typedef int (*spdk_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); struct spdk_memory_domain_translation_result { /** size of this structure in bytes */ @@ -181,6 +200,15 @@ void spdk_memory_domain_set_translation(struct spdk_memory_domain *domain, void spdk_memory_domain_set_pull(struct spdk_memory_domain *domain, spdk_memory_domain_pull_data_cb pull_cb); +/** + * Set push function for memory domain. Overwrites existing push function. + * + * \param domain Memory domain + * \param push_cb push function + */ +void spdk_memory_domain_set_push(struct spdk_memory_domain *domain, + spdk_memory_domain_push_data_cb push_cb); + /** * Get the context passed by the user in \ref spdk_memory_domain_create * @@ -228,7 +256,25 @@ void spdk_memory_domain_destroy(struct spdk_memory_domain *domain); */ int spdk_memory_domain_pull_data(struct spdk_memory_domain *src_domain, void *src_domain_ctx, struct iovec *src_iov, uint32_t src_iov_cnt, struct iovec *dst_iov, uint32_t dst_iov_cnt, - spdk_memory_domain_pull_data_cpl_cb cpl_cb, void *cpl_cb_arg); + spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg); + +/** + * Asynchronously push data located in local memory to \b dst_domain + * + * \param dst_domain Memory domain to which the data should be pushed + * \param dst_domain_ctx Optional context passed by upper layer with IO request + * \param dst_iov Iov vector in dst_domain space + * \param dst_iovcnt dst_iov array size + * \param src_iov Iov vector in local memory + * \param src_iovcnt src_iov array size + * \param cpl_cb Completion callback + * \param cpl_cb_arg Completion callback argument + * \return 0 on success, negated errno on failure. push_cb implementation must only call the callback when 0 + * is returned + */ +int spdk_memory_domain_push_data(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); /** * Translate data located in \b src_domain space at address \b addr with size \b len into an equivalent diff --git a/lib/dma/dma.c b/lib/dma/dma.c index 02d3ac4d0..5994b8b7f 100644 --- a/lib/dma/dma.c +++ b/lib/dma/dma.c @@ -42,6 +42,7 @@ TAILQ_HEAD(, spdk_memory_domain) g_dma_memory_domains = TAILQ_HEAD_INITIALIZER( struct spdk_memory_domain { enum spdk_dma_device_type type; spdk_memory_domain_pull_data_cb pull_cb; + spdk_memory_domain_push_data_cb push_cb; spdk_memory_domain_translate_memory_cb translate_cb; TAILQ_ENTRY(spdk_memory_domain) link; struct spdk_memory_domain_ctx *ctx; @@ -126,6 +127,17 @@ spdk_memory_domain_set_pull(struct spdk_memory_domain *domain, domain->pull_cb = pull_cb; } +void +spdk_memory_domain_set_push(struct spdk_memory_domain *domain, + spdk_memory_domain_push_data_cb push_cb) +{ + if (!domain) { + return; + } + + domain->push_cb = push_cb; +} + struct spdk_memory_domain_ctx * spdk_memory_domain_get_context(struct spdk_memory_domain *domain) { @@ -168,7 +180,7 @@ spdk_memory_domain_destroy(struct spdk_memory_domain *domain) int spdk_memory_domain_pull_data(struct spdk_memory_domain *src_domain, void *src_domain_ctx, struct iovec *src_iov, uint32_t src_iov_cnt, struct iovec *dst_iov, uint32_t dst_iov_cnt, - spdk_memory_domain_pull_data_cpl_cb cpl_cb, void *cpl_cb_arg) + spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg) { assert(src_domain); assert(src_iov); @@ -182,6 +194,23 @@ spdk_memory_domain_pull_data(struct spdk_memory_domain *src_domain, void *src_do cpl_cb, cpl_cb_arg); } +int +spdk_memory_domain_push_data(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) +{ + assert(dst_domain); + assert(dst_iov); + assert(src_iov); + + if (spdk_unlikely(!dst_domain->push_cb)) { + return -ENOTSUP; + } + + return dst_domain->push_cb(dst_domain, dst_domain_ctx, dst_iov, dst_iovcnt, src_iov, src_iovcnt, + cpl_cb, cpl_cb_arg); +} + int spdk_memory_domain_translate_data(struct spdk_memory_domain *src_domain, void *src_domain_ctx, struct spdk_memory_domain *dst_domain, struct spdk_memory_domain_translation_ctx *dst_domain_ctx, diff --git a/lib/dma/spdk_dma.map b/lib/dma/spdk_dma.map index aeef0a32f..d286caf4f 100644 --- a/lib/dma/spdk_dma.map +++ b/lib/dma/spdk_dma.map @@ -5,11 +5,13 @@ spdk_memory_domain_create; spdk_memory_domain_set_translation; spdk_memory_domain_set_pull; + spdk_memory_domain_set_push; spdk_memory_domain_get_context; spdk_memory_domain_get_dma_device_type; spdk_memory_domain_get_dma_device_id; spdk_memory_domain_destroy; spdk_memory_domain_pull_data; + spdk_memory_domain_push_data; spdk_memory_domain_translate_data; 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 284cd4b69..fa93b0732 100644 --- a/test/unit/lib/dma/dma.c/dma_ut.c +++ b/test/unit/lib/dma/dma.c/dma_ut.c @@ -37,23 +37,34 @@ #include "dma/dma.c" static bool g_memory_domain_pull_called; +static bool g_memory_domain_push_called; static bool g_memory_domain_translate_called; static int g_memory_domain_cb_rc = 123; static void -test_memory_domain_pull_data_cpl_cb(void *ctx, int rc) +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_pull_data_cpl_cb cpl_cb, void *cpl_cb_arg) + 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) +{ + g_memory_domain_push_called = true; + + return g_memory_domain_cb_rc; +} + static int test_memory_domain_translate_memory_cb(struct spdk_memory_domain *src_device, void *src_device_ctx, struct spdk_memory_domain *dst_device, struct spdk_memory_domain_translation_ctx *dst_device_ctx, @@ -108,7 +119,7 @@ test_dma(void) /* pull data, callback is NULL. Expect fail */ g_memory_domain_pull_called = false; rc = spdk_memory_domain_pull_data(domain, NULL, &src_iov, 1, &dst_iov, 1, - test_memory_domain_pull_data_cpl_cb, NULL); + test_memory_domain_data_cpl_cb, NULL); CU_ASSERT(rc == -ENOTSUP); CU_ASSERT(g_memory_domain_pull_called == false); @@ -117,10 +128,26 @@ test_dma(void) /* pull data. Expect pass */ rc = spdk_memory_domain_pull_data(domain, NULL, &src_iov, 1, &dst_iov, 1, - test_memory_domain_pull_data_cpl_cb, NULL); + test_memory_domain_data_cpl_cb, NULL); CU_ASSERT(rc == g_memory_domain_cb_rc); CU_ASSERT(g_memory_domain_pull_called == true); + /* push data, callback is NULL. Expect fail */ + g_memory_domain_push_called = false; + rc = spdk_memory_domain_push_data(domain, NULL, &dst_iov, 1, &src_iov, 1, + test_memory_domain_data_cpl_cb, NULL); + CU_ASSERT(rc == -ENOTSUP); + CU_ASSERT(g_memory_domain_push_called == false); + + /* Set push callback */ + spdk_memory_domain_set_push(domain, test_memory_domain_push_data_cb); + + /* push data. Expect pass */ + rc = spdk_memory_domain_push_data(domain, NULL, &dst_iov, 1, &src_iov, 1, + test_memory_domain_data_cpl_cb, NULL); + CU_ASSERT(rc == g_memory_domain_cb_rc); + CU_ASSERT(g_memory_domain_push_called == true); + /* Translate data, callback is NULL. Expect fail */ g_memory_domain_translate_called = false; rc = spdk_memory_domain_translate_data(domain, NULL, domain, NULL, (void *)0xfeeddbeef, 0x1000, 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 22437b15e..5efcd9d46 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 @@ -69,7 +69,7 @@ DEFINE_STUB(spdk_memory_domain_get_dma_device_type, enum spdk_dma_device_type, DEFINE_STUB_V(spdk_memory_domain_destroy, (struct spdk_memory_domain *device)); DEFINE_STUB(spdk_memory_domain_pull_data, int, (struct spdk_memory_domain *src_domain, void *src_domain_ctx, struct iovec *src_iov, uint32_t src_iov_cnt, struct iovec *dst_iov, - uint32_t dst_iov_cnt, spdk_memory_domain_pull_data_cpl_cb cpl_cb, void *cpl_cb_arg), 0); + uint32_t dst_iov_cnt, spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg), 0); DEFINE_RETURN_MOCK(spdk_memory_domain_create, int); int