From 8c6b5f15af0410b98d7a19be301adce96983eb96 Mon Sep 17 00:00:00 2001 From: Konrad Sztyber Date: Thu, 16 Dec 2021 10:45:10 +0100 Subject: [PATCH] bdev/malloc: completion poller This poller is registered on each IO channel and can be used to schedule asynchronous completion of a request. This can be especially useful for requests that can be completed immediately. For now, nothing enqueues the requests to be completed through this poller - this will be changed in the following patch. Signed-off-by: Konrad Sztyber Change-Id: If6b26541907bb46402fc0904216bff74dad57b88 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/10803 Community-CI: Broadcom CI Tested-by: SPDK CI Jenkins Reviewed-by: Aleksey Marchuk Reviewed-by: Ben Walker Reviewed-by: Jim Harris --- module/bdev/malloc/bdev_malloc.c | 36 ++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/module/bdev/malloc/bdev_malloc.c b/module/bdev/malloc/bdev_malloc.c index 49a4bc663..3cd47254b 100644 --- a/module/bdev/malloc/bdev_malloc.c +++ b/module/bdev/malloc/bdev_malloc.c @@ -56,10 +56,13 @@ struct malloc_disk { struct malloc_task { int num_outstanding; enum spdk_bdev_io_status status; + TAILQ_ENTRY(malloc_task) tailq; }; struct malloc_channel { struct spdk_io_channel *accel_channel; + struct spdk_poller *completion_poller; + TAILQ_HEAD(, malloc_task) completed_tasks; }; static void @@ -475,6 +478,27 @@ delete_malloc_disk(struct spdk_bdev *bdev, spdk_delete_malloc_complete cb_fn, vo spdk_bdev_unregister(bdev, cb_fn, cb_arg); } +static int +malloc_completion_poller(void *ctx) +{ + struct malloc_channel *ch = ctx; + struct malloc_task *task; + TAILQ_HEAD(, malloc_task) completed_tasks; + uint32_t num_completions = 0; + + TAILQ_INIT(&completed_tasks); + TAILQ_SWAP(&completed_tasks, &ch->completed_tasks, malloc_task, tailq); + + while (!TAILQ_EMPTY(&completed_tasks)) { + task = TAILQ_FIRST(&completed_tasks); + TAILQ_REMOVE(&completed_tasks, task, tailq); + spdk_bdev_io_complete(spdk_bdev_io_from_ctx(task), task->status); + num_completions++; + } + + return num_completions > 0 ? SPDK_POLLER_BUSY : SPDK_POLLER_IDLE; +} + static int malloc_create_channel_cb(void *io_device, void *ctx) { @@ -486,6 +510,15 @@ malloc_create_channel_cb(void *io_device, void *ctx) return -ENOMEM; } + ch->completion_poller = SPDK_POLLER_REGISTER(malloc_completion_poller, ch, 0); + if (!ch->completion_poller) { + SPDK_ERRLOG("Failed to register malloc completion poller\n"); + spdk_put_io_channel(ch->accel_channel); + return -ENOMEM; + } + + TAILQ_INIT(&ch->completed_tasks); + return 0; } @@ -494,7 +527,10 @@ malloc_destroy_channel_cb(void *io_device, void *ctx) { struct malloc_channel *ch = ctx; + assert(TAILQ_EMPTY(&ch->completed_tasks)); + spdk_put_io_channel(ch->accel_channel); + spdk_poller_unregister(&ch->completion_poller); } static int bdev_malloc_initialize(void)