From f118de60af0369553a58599dbfd36d154df7b8af Mon Sep 17 00:00:00 2001 From: wuzhouhui Date: Fri, 24 Aug 2018 15:46:11 +0800 Subject: [PATCH] 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 Reviewed-on: https://review.gerrithub.io/423369 Tested-by: SPDK CI Jenkins Reviewed-by: Ben Walker Reviewed-by: Jim Harris --- lib/bdev/bdev.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/bdev/bdev.c b/lib/bdev/bdev.c index fe62e36e0..7ce64bd4d 100644 --- a/lib/bdev/bdev.c +++ b/lib/bdev/bdev.c @@ -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_cb(desc->remove_ctx); + 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); - free(desc); + + 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)) {