diff --git a/include/spdk/io_channel.h b/include/spdk/io_channel.h index ae2d4bdd8..59735ec02 100644 --- a/include/spdk/io_channel.h +++ b/include/spdk/io_channel.h @@ -96,8 +96,11 @@ void spdk_io_device_unregister(void *io_device); * The priority parameter allows callers to create different I/O channels to the same * I/O device with varying priorities. Currently this value must be set to * SPDK_IO_PRIORITY_DEFAULT. + * + * The unique parameter allows callers to specify that an existing channel should not + * be used to satisfy this request, even if the io_device and priority fields match. */ -struct spdk_io_channel *spdk_get_io_channel(void *io_device, uint32_t priority); +struct spdk_io_channel *spdk_get_io_channel(void *io_device, uint32_t priority, bool unique); /** * \brief Releases a reference to an I/O channel. diff --git a/lib/bdev/aio/blockdev_aio.c b/lib/bdev/aio/blockdev_aio.c index f5b6d6ae4..b9a197d1c 100644 --- a/lib/bdev/aio/blockdev_aio.c +++ b/lib/bdev/aio/blockdev_aio.c @@ -336,7 +336,7 @@ blockdev_aio_destroy_cb(void *io_device, void *ctx_buf) static struct spdk_io_channel * blockdev_aio_get_io_channel(struct spdk_bdev *bdev, uint32_t priority) { - return spdk_get_io_channel(bdev, priority); + return spdk_get_io_channel(bdev, priority, false); } static const struct spdk_bdev_fn_table aio_fn_table = { diff --git a/lib/bdev/nvme/blockdev_nvme.c b/lib/bdev/nvme/blockdev_nvme.c index af5213c26..d9883ed6c 100644 --- a/lib/bdev/nvme/blockdev_nvme.c +++ b/lib/bdev/nvme/blockdev_nvme.c @@ -336,7 +336,7 @@ blockdev_nvme_get_io_channel(struct spdk_bdev *bdev, uint32_t priority) { struct nvme_blockdev *nvme_bdev = (struct nvme_blockdev *)bdev; - return spdk_get_io_channel(nvme_bdev->ctrlr, priority); + return spdk_get_io_channel(nvme_bdev->ctrlr, priority, false); } static const struct spdk_bdev_fn_table nvmelib_fn_table = { diff --git a/lib/copy/copy_engine.c b/lib/copy/copy_engine.c index c05ab0e11..d89324662 100644 --- a/lib/copy/copy_engine.c +++ b/lib/copy/copy_engine.c @@ -151,7 +151,7 @@ memcpy_destroy_cb(void *io_device, void *ctx_buf) static struct spdk_io_channel *mem_get_io_channel(uint32_t priority) { - return spdk_get_io_channel(&memcpy_copy_engine, priority); + return spdk_get_io_channel(&memcpy_copy_engine, priority, false); } static int @@ -208,7 +208,7 @@ copy_destroy_cb(void *io_device, void *ctx_buf) struct spdk_io_channel * spdk_copy_engine_get_io_channel(uint32_t priority) { - return spdk_get_io_channel(&spdk_copy_module_list, priority); + return spdk_get_io_channel(&spdk_copy_module_list, priority, false); } static int diff --git a/lib/copy/ioat/copy_engine_ioat.c b/lib/copy/ioat/copy_engine_ioat.c index 8af3f17cf..794400161 100644 --- a/lib/copy/ioat/copy_engine_ioat.c +++ b/lib/copy/ioat/copy_engine_ioat.c @@ -236,7 +236,7 @@ ioat_destroy_cb(void *io_device, void *ctx_buf) static struct spdk_io_channel * ioat_get_io_channel(uint32_t priority) { - return spdk_get_io_channel(&ioat_copy_engine, priority); + return spdk_get_io_channel(&ioat_copy_engine, priority, false); } struct ioat_probe_ctx { diff --git a/lib/util/io_channel.c b/lib/util/io_channel.c index cc36b437c..ce2ab16da 100644 --- a/lib/util/io_channel.c +++ b/lib/util/io_channel.c @@ -130,7 +130,7 @@ spdk_io_device_unregister(void *io_device) } struct spdk_io_channel * -spdk_get_io_channel(void *io_device, uint32_t priority) +spdk_get_io_channel(void *io_device, uint32_t priority, bool unique) { struct spdk_io_channel *ch; struct io_device *dev; @@ -154,14 +154,16 @@ spdk_get_io_channel(void *io_device, uint32_t priority) } pthread_mutex_unlock(&g_devlist_mutex); - TAILQ_FOREACH(ch, &g_io_channels, tailq) { - if (ch->io_device == io_device && ch->priority == priority) { - ch->ref++; - /* - * An I/O channel already exists for this device on this - * thread, so return it. - */ - return ch; + if (unique == false) { + TAILQ_FOREACH(ch, &g_io_channels, tailq) { + if (ch->io_device == io_device && ch->priority == priority) { + ch->ref++; + /* + * An I/O channel already exists for this device on this + * thread, so return it. + */ + return ch; + } } } diff --git a/test/lib/util/io_channel/io_channel_ut.c b/test/lib/util/io_channel/io_channel_ut.c index 07d867c76..0ddf56099 100644 --- a/test/lib/util/io_channel/io_channel_ut.c +++ b/test/lib/util/io_channel/io_channel_ut.c @@ -101,7 +101,7 @@ create_cb_null(void *io_device, uint32_t priority, void *ctx_buf) static void channel(void) { - struct spdk_io_channel *ch1, *ch2; + struct spdk_io_channel *ch1, *ch2, *ch3; void *ctx; spdk_allocate_thread(); @@ -110,12 +110,12 @@ channel(void) spdk_io_device_register(&device3, create_cb_null, NULL, 0); g_create_cb_calls = 0; - ch1 = spdk_get_io_channel(&device1, SPDK_IO_PRIORITY_DEFAULT); + ch1 = spdk_get_io_channel(&device1, SPDK_IO_PRIORITY_DEFAULT, false); CU_ASSERT(g_create_cb_calls == 1); SPDK_CU_ASSERT_FATAL(ch1 != NULL); g_create_cb_calls = 0; - ch2 = spdk_get_io_channel(&device1, SPDK_IO_PRIORITY_DEFAULT); + ch2 = spdk_get_io_channel(&device1, SPDK_IO_PRIORITY_DEFAULT, false); CU_ASSERT(g_create_cb_calls == 0); CU_ASSERT(ch1 == ch2); SPDK_CU_ASSERT_FATAL(ch2 != NULL); @@ -125,7 +125,7 @@ channel(void) CU_ASSERT(g_destroy_cb_calls == 0); g_create_cb_calls = 0; - ch2 = spdk_get_io_channel(&device2, SPDK_IO_PRIORITY_DEFAULT); + ch2 = spdk_get_io_channel(&device2, SPDK_IO_PRIORITY_DEFAULT, false); CU_ASSERT(g_create_cb_calls == 1); CU_ASSERT(ch1 != ch2); SPDK_CU_ASSERT_FATAL(ch2 != NULL); @@ -133,6 +133,16 @@ channel(void) ctx = spdk_io_channel_get_ctx(ch2); CU_ASSERT(*(uint64_t *)ctx == ctx2); + /* + * Confirm that specifying unique==true will generate a new I/O channel, + * and reuse ch2. + */ + g_create_cb_calls = 0; + ch3 = spdk_get_io_channel(&device2, SPDK_IO_PRIORITY_DEFAULT, true); + CU_ASSERT(g_create_cb_calls == 1); + CU_ASSERT(ch2 != ch3); + CU_ASSERT(ch3 != NULL); + g_destroy_cb_calls = 0; spdk_put_io_channel(ch1); CU_ASSERT(g_destroy_cb_calls == 1); @@ -141,11 +151,15 @@ channel(void) spdk_put_io_channel(ch2); CU_ASSERT(g_destroy_cb_calls == 1); - ch1 = spdk_get_io_channel(&device3, SPDK_IO_PRIORITY_DEFAULT); + g_destroy_cb_calls = 0; + spdk_put_io_channel(ch3); + CU_ASSERT(g_destroy_cb_calls == 1); + + ch1 = spdk_get_io_channel(&device3, SPDK_IO_PRIORITY_DEFAULT, false); CU_ASSERT(ch1 == NULL); /* Confirm failure if user specifies an invalid I/O priority. */ - ch1 = spdk_get_io_channel(&device1, SPDK_IO_PRIORITY_DEFAULT + 1); + ch1 = spdk_get_io_channel(&device1, SPDK_IO_PRIORITY_DEFAULT + 1, false); CU_ASSERT(ch1 == NULL); spdk_io_device_unregister(&device1);