Commit a8d3ac0c authored by Jim Harris's avatar Jim Harris Committed by Changpeng Liu
Browse files

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

Reviewed-on: https://review.gerrithub.io/404414


Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
parent 1b41df05
Loading
Loading
Loading
Loading
+16 −4
Original line number Diff line number Diff line
@@ -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);
	}
}

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

+11 −0
Original line number Diff line number Diff line
@@ -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();