From a8d3ac0cf4b812d7cda5d0abb4dfe1cdc999fb56 Mon Sep 17 00:00:00 2001 From: Jim Harris Date: Mon, 19 Mar 2018 13:09:32 -0700 Subject: [PATCH] io_channel: invoke unregister_cb on same thread unregister was called The unregister callback is only invoked after all I/O channels related to the I/O device have been freed. The last I/O channel to be freed might be on a thread different than the thread where spdk_io_device_unregister was called. If this is the case, send an event to the latter thread so that the callback gets called on the same thread as spdk_io_device_unregister. Signed-off-by: Jim Harris Change-Id: I3c910198fbd83eae95e5c57d618284e64db46ff7 Reviewed-on: https://review.gerrithub.io/404414 Tested-by: SPDK Automated Test System Reviewed-by: Daniel Verkamp Reviewed-by: Changpeng Liu --- lib/util/io_channel.c | 20 ++++++++++++++++---- test/unit/lib/bdev/pmem/bdev_pmem_ut.c | 11 +++++++++++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/lib/util/io_channel.c b/lib/util/io_channel.c index 7d651d1ca..efb9c6692 100644 --- a/lib/util/io_channel.c +++ b/lib/util/io_channel.c @@ -51,6 +51,7 @@ struct io_device { spdk_io_channel_create_cb create_cb; spdk_io_channel_destroy_cb destroy_cb; spdk_io_device_unregister_cb unregister_cb; + struct spdk_thread *unregister_thread; uint32_t ctx_size; uint32_t for_each_count; TAILQ_ENTRY(io_device) tailq; @@ -327,6 +328,15 @@ spdk_io_device_register(void *io_device, spdk_io_channel_create_cb create_cb, pthread_mutex_unlock(&g_devlist_mutex); } +static void +_finish_unregister(void *arg) +{ + struct io_device *dev = arg; + + dev->unregister_cb(dev->io_device); + free(dev); +} + static void _spdk_io_device_attempt_free(struct io_device *dev, struct spdk_io_channel *ch) { @@ -358,11 +368,12 @@ _spdk_io_device_attempt_free(struct io_device *dev, struct spdk_io_channel *ch) } pthread_mutex_unlock(&g_devlist_mutex); - if (dev->unregister_cb) { - dev->unregister_cb(dev->io_device); + if (dev->unregister_cb == NULL) { + free(dev); + } else { + assert(dev->unregister_thread != NULL); + spdk_thread_send_msg(dev->unregister_thread, _finish_unregister, dev); } - - free(dev); } void @@ -393,6 +404,7 @@ spdk_io_device_unregister(void *io_device, spdk_io_device_unregister_cb unregist dev->unregistered = true; TAILQ_REMOVE(&g_io_devices, dev, tailq); pthread_mutex_unlock(&g_devlist_mutex); + dev->unregister_thread = spdk_get_thread(); _spdk_io_device_attempt_free(dev, NULL); } diff --git a/test/unit/lib/bdev/pmem/bdev_pmem_ut.c b/test/unit/lib/bdev/pmem/bdev_pmem_ut.c index c68099ae3..d08bf3f51 100644 --- a/test/unit/lib/bdev/pmem/bdev_pmem_ut.c +++ b/test/unit/lib/bdev/pmem/bdev_pmem_ut.c @@ -90,6 +90,12 @@ static struct spdk_bdev *g_bdev; static const char *g_check_version_msg; static bool g_pmemblk_open_allow_open = true; +static void +_pmem_send_msg(spdk_thread_fn fn, void *ctx, void *thread_ctx) +{ + fn(ctx); +} + DEFINE_STUB(spdk_json_write_object_begin, int, (struct spdk_json_write_ctx *w), 0); DEFINE_STUB(spdk_json_write_object_end, int, (struct spdk_json_write_ctx *w), 0); DEFINE_STUB(spdk_json_write_string, int, (struct spdk_json_write_ctx *w, const char *val), 0); @@ -359,6 +365,9 @@ ut_pmem_blk_clean(void) /* Unload module to free IO channel */ g_bdev_pmem_module->module_fini(); + + spdk_free_thread(); + return 0; } @@ -367,6 +376,8 @@ ut_pmem_blk_init(void) { errno = 0; + spdk_allocate_thread(_pmem_send_msg, NULL, NULL, NULL, NULL); + g_pool_ok.buffer = calloc(g_pool_ok.nblock, g_pool_ok.bsize); if (g_pool_ok.buffer == NULL) { ut_pmem_blk_clean();