bdev/rbd: make destruct path asynchronous
When a bdev is being unregistered, after all channels have been closed, the bdev layer calls the module's destruct callback for the bdev before calling the bdev unregister callback. For the rbd module, the destruct callback is bdev_rbd_destruct. This callback unregisters the rbd io_device which is an asynchronous operation. We need to return >0 from bdev_rbd_destruct to inform the bdev layer that this is an asynchronous operation, so that it does not immediately call the bdev unregister callback. Once the rbd io_device is unregistered, we can call spdk_bdev_destruct_done() which will trigger the bdev layer to finally call the bdev unregister callback. Without this fix, deleting an rbd bdev would complete before the backing cluster reference had been released. This meant that even if you had deleted all rbd bdevs, there might still be cluster references in place for a short period of time. It's better to wait to complete the delete operation until the cluster reference has been released to avoid this issue (which this patch now does). Fixes issue #2069. Signed-off-by: Jim Harris <james.r.harris@intel.com> Change-Id: I8ac156c89d3e235a95ef196308cc349e6078bfd7 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9115 Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com> Community-CI: Mellanox Build Bot Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com> Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Ziye Yang <ziye.yang@intel.com>
This commit is contained in:
parent
a70aae4610
commit
abb4baef2d
@ -74,6 +74,7 @@ struct bdev_rbd {
|
||||
rbd_image_info_t info;
|
||||
pthread_mutex_t mutex;
|
||||
struct spdk_thread *main_td;
|
||||
struct spdk_thread *destruct_td;
|
||||
uint32_t ch_count;
|
||||
struct bdev_rbd_group_channel *group_ch;
|
||||
|
||||
@ -496,16 +497,30 @@ bdev_rbd_reset(struct bdev_rbd *disk, struct spdk_bdev_io *bdev_io)
|
||||
}
|
||||
|
||||
static void
|
||||
bdev_rbd_free_cb(void *io_device)
|
||||
_bdev_rbd_destruct_done(void *io_device)
|
||||
{
|
||||
struct bdev_rbd *rbd = io_device;
|
||||
|
||||
assert(rbd != NULL);
|
||||
assert(rbd->ch_count == 0);
|
||||
|
||||
spdk_bdev_destruct_done(&rbd->disk, 0);
|
||||
bdev_rbd_free(rbd);
|
||||
}
|
||||
|
||||
static void
|
||||
bdev_rbd_free_cb(void *io_device)
|
||||
{
|
||||
struct bdev_rbd *rbd = io_device;
|
||||
|
||||
/* The io device has been unregistered. Send a message back to the
|
||||
* original thread that started the destruct operation, so that the
|
||||
* bdev unregister callback is invoked on the same thread that started
|
||||
* this whole process.
|
||||
*/
|
||||
spdk_thread_send_msg(rbd->destruct_td, _bdev_rbd_destruct_done, rbd);
|
||||
}
|
||||
|
||||
static void
|
||||
_bdev_rbd_destruct(void *ctx)
|
||||
{
|
||||
@ -534,9 +549,12 @@ bdev_rbd_destruct(void *ctx)
|
||||
* from the main thread, in case there are pending
|
||||
* channel delete messages in flight to this thread.
|
||||
*/
|
||||
assert(rbd->destruct_td == NULL);
|
||||
rbd->destruct_td = td;
|
||||
spdk_thread_send_msg(td, _bdev_rbd_destruct, rbd);
|
||||
|
||||
return 0;
|
||||
/* Return 1 to indicate the destruct path is asynchronous. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
|
Loading…
Reference in New Issue
Block a user