channel: Correctly defer unregisters if channels exist
Unregistering a device should be deferred if I/O channels still exist. Those I/O channels are likely undergoing a deferred unregister themselves. Change-Id: I67186232a58f212b867f6ef894c3d37aae2a4d53 Signed-off-by: Ben Walker <benjamin.walker@intel.com> Reviewed-on: https://review.gerrithub.io/370351 Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com> Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
This commit is contained in:
parent
59d6f04758
commit
afe860aeb1
@ -39,18 +39,20 @@
|
|||||||
static pthread_mutex_t g_devlist_mutex = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_mutex_t g_devlist_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
struct io_device {
|
struct io_device {
|
||||||
void *io_device_ctx;
|
void *io_device;
|
||||||
spdk_io_channel_create_cb create_cb;
|
spdk_io_channel_create_cb create_cb;
|
||||||
spdk_io_channel_destroy_cb destroy_cb;
|
spdk_io_channel_destroy_cb destroy_cb;
|
||||||
uint32_t ctx_size;
|
uint32_t ctx_size;
|
||||||
TAILQ_ENTRY(io_device) tailq;
|
TAILQ_ENTRY(io_device) tailq;
|
||||||
|
|
||||||
|
bool unregistered;
|
||||||
};
|
};
|
||||||
|
|
||||||
static TAILQ_HEAD(, io_device) g_io_devices = TAILQ_HEAD_INITIALIZER(g_io_devices);
|
static TAILQ_HEAD(, io_device) g_io_devices = TAILQ_HEAD_INITIALIZER(g_io_devices);
|
||||||
|
|
||||||
struct spdk_io_channel {
|
struct spdk_io_channel {
|
||||||
struct spdk_thread *thread;
|
struct spdk_thread *thread;
|
||||||
void *io_device;
|
struct io_device *dev;
|
||||||
uint32_t ref;
|
uint32_t ref;
|
||||||
TAILQ_ENTRY(spdk_io_channel) tailq;
|
TAILQ_ENTRY(spdk_io_channel) tailq;
|
||||||
spdk_io_channel_destroy_cb destroy_cb;
|
spdk_io_channel_destroy_cb destroy_cb;
|
||||||
@ -178,14 +180,15 @@ spdk_io_device_register(void *io_device, spdk_io_channel_create_cb create_cb,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->io_device_ctx = io_device;
|
dev->io_device = io_device;
|
||||||
dev->create_cb = create_cb;
|
dev->create_cb = create_cb;
|
||||||
dev->destroy_cb = destroy_cb;
|
dev->destroy_cb = destroy_cb;
|
||||||
dev->ctx_size = ctx_size;
|
dev->ctx_size = ctx_size;
|
||||||
|
dev->unregistered = false;
|
||||||
|
|
||||||
pthread_mutex_lock(&g_devlist_mutex);
|
pthread_mutex_lock(&g_devlist_mutex);
|
||||||
TAILQ_FOREACH(tmp, &g_io_devices, tailq) {
|
TAILQ_FOREACH(tmp, &g_io_devices, tailq) {
|
||||||
if (tmp->io_device_ctx == io_device) {
|
if (tmp->io_device == io_device) {
|
||||||
SPDK_ERRLOG("io_device %p already registered\n", io_device);
|
SPDK_ERRLOG("io_device %p already registered\n", io_device);
|
||||||
free(dev);
|
free(dev);
|
||||||
pthread_mutex_unlock(&g_devlist_mutex);
|
pthread_mutex_unlock(&g_devlist_mutex);
|
||||||
@ -196,6 +199,27 @@ spdk_io_device_register(void *io_device, spdk_io_channel_create_cb create_cb,
|
|||||||
pthread_mutex_unlock(&g_devlist_mutex);
|
pthread_mutex_unlock(&g_devlist_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_spdk_io_device_attempt_free(struct io_device *dev)
|
||||||
|
{
|
||||||
|
struct spdk_thread *thread;
|
||||||
|
struct spdk_io_channel *ch;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(thread, &g_threads, tailq) {
|
||||||
|
TAILQ_FOREACH(ch, &thread->io_channels, tailq) {
|
||||||
|
if (ch->dev == dev) {
|
||||||
|
/* A channel that references this I/O
|
||||||
|
* device still exists. Defer deletion
|
||||||
|
* until it is removed.
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(dev);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
spdk_io_device_unregister(void *io_device)
|
spdk_io_device_unregister(void *io_device)
|
||||||
{
|
{
|
||||||
@ -203,14 +227,21 @@ spdk_io_device_unregister(void *io_device)
|
|||||||
|
|
||||||
pthread_mutex_lock(&g_devlist_mutex);
|
pthread_mutex_lock(&g_devlist_mutex);
|
||||||
TAILQ_FOREACH(dev, &g_io_devices, tailq) {
|
TAILQ_FOREACH(dev, &g_io_devices, tailq) {
|
||||||
if (dev->io_device_ctx == io_device) {
|
if (dev->io_device == io_device) {
|
||||||
TAILQ_REMOVE(&g_io_devices, dev, tailq);
|
break;
|
||||||
free(dev);
|
|
||||||
pthread_mutex_unlock(&g_devlist_mutex);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SPDK_ERRLOG("io_device %p not found\n", io_device);
|
|
||||||
|
if (!dev) {
|
||||||
|
SPDK_ERRLOG("io_device %p not found\n", io_device);
|
||||||
|
pthread_mutex_unlock(&g_devlist_mutex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->unregistered = true;
|
||||||
|
TAILQ_REMOVE(&g_io_devices, dev, tailq);
|
||||||
|
_spdk_io_device_attempt_free(dev);
|
||||||
|
|
||||||
pthread_mutex_unlock(&g_devlist_mutex);
|
pthread_mutex_unlock(&g_devlist_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,7 +255,7 @@ spdk_get_io_channel(void *io_device)
|
|||||||
|
|
||||||
pthread_mutex_lock(&g_devlist_mutex);
|
pthread_mutex_lock(&g_devlist_mutex);
|
||||||
TAILQ_FOREACH(dev, &g_io_devices, tailq) {
|
TAILQ_FOREACH(dev, &g_io_devices, tailq) {
|
||||||
if (dev->io_device_ctx == io_device) {
|
if (dev->io_device == io_device) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -241,15 +272,14 @@ spdk_get_io_channel(void *io_device)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_unlock(&g_devlist_mutex);
|
|
||||||
|
|
||||||
TAILQ_FOREACH(ch, &thread->io_channels, tailq) {
|
TAILQ_FOREACH(ch, &thread->io_channels, tailq) {
|
||||||
if (ch->io_device == io_device) {
|
if (ch->dev == dev) {
|
||||||
ch->ref++;
|
ch->ref++;
|
||||||
/*
|
/*
|
||||||
* An I/O channel already exists for this device on this
|
* An I/O channel already exists for this device on this
|
||||||
* thread, so return it.
|
* thread, so return it.
|
||||||
*/
|
*/
|
||||||
|
pthread_mutex_unlock(&g_devlist_mutex);
|
||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -257,19 +287,27 @@ spdk_get_io_channel(void *io_device)
|
|||||||
ch = calloc(1, sizeof(*ch) + dev->ctx_size);
|
ch = calloc(1, sizeof(*ch) + dev->ctx_size);
|
||||||
if (ch == NULL) {
|
if (ch == NULL) {
|
||||||
SPDK_ERRLOG("could not calloc spdk_io_channel\n");
|
SPDK_ERRLOG("could not calloc spdk_io_channel\n");
|
||||||
return NULL;
|
pthread_mutex_unlock(&g_devlist_mutex);
|
||||||
}
|
|
||||||
rc = dev->create_cb(io_device, (uint8_t *)ch + sizeof(*ch));
|
|
||||||
if (rc == -1) {
|
|
||||||
free(ch);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ch->io_device = io_device;
|
ch->dev = dev;
|
||||||
ch->destroy_cb = dev->destroy_cb;
|
ch->destroy_cb = dev->destroy_cb;
|
||||||
ch->thread = thread;
|
ch->thread = thread;
|
||||||
ch->ref = 1;
|
ch->ref = 1;
|
||||||
TAILQ_INSERT_TAIL(&thread->io_channels, ch, tailq);
|
TAILQ_INSERT_TAIL(&thread->io_channels, ch, tailq);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&g_devlist_mutex);
|
||||||
|
|
||||||
|
rc = dev->create_cb(io_device, (uint8_t *)ch + sizeof(*ch));
|
||||||
|
if (rc == -1) {
|
||||||
|
pthread_mutex_lock(&g_devlist_mutex);
|
||||||
|
TAILQ_REMOVE(&ch->thread->io_channels, ch, tailq);
|
||||||
|
free(ch);
|
||||||
|
pthread_mutex_unlock(&g_devlist_mutex);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,11 +323,22 @@ _spdk_put_io_channel(void *arg)
|
|||||||
|
|
||||||
ch->ref--;
|
ch->ref--;
|
||||||
|
|
||||||
if (ch->ref == 0) {
|
if (ch->ref > 0) {
|
||||||
TAILQ_REMOVE(&ch->thread->io_channels, ch, tailq);
|
return;
|
||||||
ch->destroy_cb(ch->io_device, (uint8_t *)ch + sizeof(*ch));
|
|
||||||
free(ch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ch->destroy_cb(ch->dev->io_device, spdk_io_channel_get_ctx(ch));
|
||||||
|
|
||||||
|
pthread_mutex_lock(&g_devlist_mutex);
|
||||||
|
|
||||||
|
TAILQ_REMOVE(&ch->thread->io_channels, ch, tailq);
|
||||||
|
|
||||||
|
if (ch->dev->unregistered) {
|
||||||
|
_spdk_io_device_attempt_free(ch->dev);
|
||||||
|
}
|
||||||
|
free(ch);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&g_devlist_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -347,7 +396,7 @@ _call_channel(void *ctx)
|
|||||||
thread = TAILQ_NEXT(thread, tailq);
|
thread = TAILQ_NEXT(thread, tailq);
|
||||||
while (thread) {
|
while (thread) {
|
||||||
TAILQ_FOREACH(ch, &thread->io_channels, tailq) {
|
TAILQ_FOREACH(ch, &thread->io_channels, tailq) {
|
||||||
if (ch->io_device == ch_ctx->io_device) {
|
if (ch->dev->io_device == ch_ctx->io_device) {
|
||||||
ch_ctx->cur_thread = thread;
|
ch_ctx->cur_thread = thread;
|
||||||
ch_ctx->cur_ch = ch;
|
ch_ctx->cur_ch = ch;
|
||||||
pthread_mutex_unlock(&g_devlist_mutex);
|
pthread_mutex_unlock(&g_devlist_mutex);
|
||||||
@ -387,7 +436,7 @@ spdk_for_each_channel(void *io_device, spdk_channel_msg fn, void *ctx,
|
|||||||
|
|
||||||
TAILQ_FOREACH(thread, &g_threads, tailq) {
|
TAILQ_FOREACH(thread, &g_threads, tailq) {
|
||||||
TAILQ_FOREACH(ch, &thread->io_channels, tailq) {
|
TAILQ_FOREACH(ch, &thread->io_channels, tailq) {
|
||||||
if (ch->io_device == io_device) {
|
if (ch->dev->io_device == io_device) {
|
||||||
ch_ctx->cur_thread = thread;
|
ch_ctx->cur_thread = thread;
|
||||||
ch_ctx->cur_ch = ch;
|
ch_ctx->cur_ch = ch;
|
||||||
pthread_mutex_unlock(&g_devlist_mutex);
|
pthread_mutex_unlock(&g_devlist_mutex);
|
||||||
|
Loading…
Reference in New Issue
Block a user