util: add 'unique' parameter to spdk_get_io_channel

Some subsystems may wish to create unique I/O channels
which are not shared across all users of the same I/O
device on the same thread.

Signed-off-by: Jim Harris <james.r.harris@intel.com>
Change-Id: I3ade3675d57338cf85b6a301285e6f392bd6cd2e
This commit is contained in:
Jim Harris 2016-09-27 13:10:05 -07:00
parent ff38547d80
commit c1e3a87bf7
7 changed files with 40 additions and 21 deletions

View File

@ -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 * 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 * I/O device with varying priorities. Currently this value must be set to
* SPDK_IO_PRIORITY_DEFAULT. * 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. * \brief Releases a reference to an I/O channel.

View File

@ -336,7 +336,7 @@ blockdev_aio_destroy_cb(void *io_device, void *ctx_buf)
static struct spdk_io_channel * static struct spdk_io_channel *
blockdev_aio_get_io_channel(struct spdk_bdev *bdev, uint32_t priority) 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 = { static const struct spdk_bdev_fn_table aio_fn_table = {

View File

@ -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; 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 = { static const struct spdk_bdev_fn_table nvmelib_fn_table = {

View File

@ -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) 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 static int
@ -208,7 +208,7 @@ copy_destroy_cb(void *io_device, void *ctx_buf)
struct spdk_io_channel * struct spdk_io_channel *
spdk_copy_engine_get_io_channel(uint32_t priority) 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 static int

View File

@ -236,7 +236,7 @@ ioat_destroy_cb(void *io_device, void *ctx_buf)
static struct spdk_io_channel * static struct spdk_io_channel *
ioat_get_io_channel(uint32_t priority) 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 { struct ioat_probe_ctx {

View File

@ -130,7 +130,7 @@ spdk_io_device_unregister(void *io_device)
} }
struct spdk_io_channel * 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 spdk_io_channel *ch;
struct io_device *dev; struct io_device *dev;
@ -154,14 +154,16 @@ spdk_get_io_channel(void *io_device, uint32_t priority)
} }
pthread_mutex_unlock(&g_devlist_mutex); pthread_mutex_unlock(&g_devlist_mutex);
TAILQ_FOREACH(ch, &g_io_channels, tailq) { if (unique == false) {
if (ch->io_device == io_device && ch->priority == priority) { TAILQ_FOREACH(ch, &g_io_channels, tailq) {
ch->ref++; 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. * An I/O channel already exists for this device on this
*/ * thread, so return it.
return ch; */
return ch;
}
} }
} }

View File

@ -101,7 +101,7 @@ create_cb_null(void *io_device, uint32_t priority, void *ctx_buf)
static void static void
channel(void) channel(void)
{ {
struct spdk_io_channel *ch1, *ch2; struct spdk_io_channel *ch1, *ch2, *ch3;
void *ctx; void *ctx;
spdk_allocate_thread(); spdk_allocate_thread();
@ -110,12 +110,12 @@ channel(void)
spdk_io_device_register(&device3, create_cb_null, NULL, 0); spdk_io_device_register(&device3, create_cb_null, NULL, 0);
g_create_cb_calls = 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); CU_ASSERT(g_create_cb_calls == 1);
SPDK_CU_ASSERT_FATAL(ch1 != NULL); SPDK_CU_ASSERT_FATAL(ch1 != NULL);
g_create_cb_calls = 0; 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(g_create_cb_calls == 0);
CU_ASSERT(ch1 == ch2); CU_ASSERT(ch1 == ch2);
SPDK_CU_ASSERT_FATAL(ch2 != NULL); SPDK_CU_ASSERT_FATAL(ch2 != NULL);
@ -125,7 +125,7 @@ channel(void)
CU_ASSERT(g_destroy_cb_calls == 0); CU_ASSERT(g_destroy_cb_calls == 0);
g_create_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(g_create_cb_calls == 1);
CU_ASSERT(ch1 != ch2); CU_ASSERT(ch1 != ch2);
SPDK_CU_ASSERT_FATAL(ch2 != NULL); SPDK_CU_ASSERT_FATAL(ch2 != NULL);
@ -133,6 +133,16 @@ channel(void)
ctx = spdk_io_channel_get_ctx(ch2); ctx = spdk_io_channel_get_ctx(ch2);
CU_ASSERT(*(uint64_t *)ctx == ctx2); 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; g_destroy_cb_calls = 0;
spdk_put_io_channel(ch1); spdk_put_io_channel(ch1);
CU_ASSERT(g_destroy_cb_calls == 1); CU_ASSERT(g_destroy_cb_calls == 1);
@ -141,11 +151,15 @@ channel(void)
spdk_put_io_channel(ch2); spdk_put_io_channel(ch2);
CU_ASSERT(g_destroy_cb_calls == 1); 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); CU_ASSERT(ch1 == NULL);
/* Confirm failure if user specifies an invalid I/O priority. */ /* 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); CU_ASSERT(ch1 == NULL);
spdk_io_device_unregister(&device1); spdk_io_device_unregister(&device1);