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 <james.r.harris@intel.com>
Change-Id: I3c910198fbd83eae95e5c57d618284e64db46ff7

Reviewed-on: https://review.gerrithub.io/404414
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
This commit is contained in:
Jim Harris 2018-03-19 13:09:32 -07:00 committed by Changpeng Liu
parent 1b41df0558
commit a8d3ac0cf4
2 changed files with 27 additions and 4 deletions

View File

@ -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);
}

View File

@ -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();