bdev: fix race condition between spdk_bdev_close and _remove_notify

When new bdev was created, the struct spdk_bdev_module::examine_disk()
may open and close bdev. On the other hand, if something goes wrong,
the creation procedure may unregister new created bdev, so race
condition appeared between _remove_notify() and spdk_bdev_close().

Add the new field "closed" and "remove_notified" in struct spdk_bdev_desc,
so _remove_notify() and spdk_bdev_close() knows how to deal with this
situation.

Change-Id: Ibfe915a4d76096796b039a13a4f49f26669eba2c
Signed-off-by: wuzhouhui <wuzhouhui@kingsoft.com>
Reviewed-on: https://review.gerrithub.io/423369
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
wuzhouhui 2018-08-24 15:46:11 +08:00 committed by Ben Walker
parent 898739fbac
commit f118de60af

View File

@ -263,6 +263,7 @@ struct spdk_bdev_desc {
spdk_bdev_remove_cb_t remove_cb;
void *remove_ctx;
bool remove_scheduled;
bool closed;
bool write;
TAILQ_ENTRY(spdk_bdev_desc) link;
};
@ -3174,7 +3175,13 @@ _remove_notify(void *arg)
{
struct spdk_bdev_desc *desc = arg;
desc->remove_scheduled = false;
if (desc->closed) {
free(desc);
} else {
desc->remove_cb(desc->remove_ctx);
}
}
void
@ -3289,7 +3296,12 @@ spdk_bdev_close(struct spdk_bdev_desc *desc)
pthread_mutex_lock(&bdev->internal.mutex);
TAILQ_REMOVE(&bdev->internal.open_descs, desc, link);
desc->closed = true;
if (!desc->remove_scheduled) {
free(desc);
}
/* If no more descriptors, kill QoS channel */
if (bdev->internal.qos && TAILQ_EMPTY(&bdev->internal.open_descs)) {