From 72cb529751882fc4c022da7429ad61d248542639 Mon Sep 17 00:00:00 2001 From: Shuhei Matsumoto Date: Wed, 10 Aug 2022 07:27:21 +0900 Subject: [PATCH] bdev/rbd: Reset returns completion after all inflight I/Os complete Previously, reset just set a long timer to wait until all inflight I/Os complete. As already noted as a TODO item, check if any I/O is still inflight before completing the reset by using a new API spdk_bdev_get_current_qd(). The RBD bdev module can count outstanding I/Os itself but is not efficient. Signed-off-by: liu-darong Signed-off-by: Shuhei Matsumoto Change-Id: Iecaf90b06cae8e21198ec3822b978b54f5404d2b Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/13945 Tested-by: SPDK CI Jenkins Reviewed-by: Jim Harris Reviewed-by: Aleksey Marchuk Reviewed-by: Dong Yi Reviewed-by: Xiaodong Liu Reviewed-by: GangCao --- module/bdev/rbd/bdev_rbd.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/module/bdev/rbd/bdev_rbd.c b/module/bdev/rbd/bdev_rbd.c index 01d23dffd..39d4ca304 100644 --- a/module/bdev/rbd/bdev_rbd.c +++ b/module/bdev/rbd/bdev_rbd.c @@ -458,18 +458,38 @@ static struct spdk_bdev_module rbd_if = { }; SPDK_BDEV_MODULE_REGISTER(rbd, &rbd_if) +static int bdev_rbd_reset_timer(void *arg); + +static void +bdev_rbd_check_outstanding_ios(struct spdk_bdev *bdev, uint64_t current_qd, + void *cb_arg, int rc) +{ + struct bdev_rbd *disk = cb_arg; + enum spdk_bdev_io_status bio_status; + + if (rc == 0 && current_qd > 0) { + disk->reset_timer = SPDK_POLLER_REGISTER(bdev_rbd_reset_timer, disk, 1000); + return; + } + + if (rc != 0) { + bio_status = SPDK_BDEV_IO_STATUS_FAILED; + } else { + bio_status = SPDK_BDEV_IO_STATUS_SUCCESS; + } + + bdev_rbd_io_complete(disk->reset_bdev_io, bio_status); + disk->reset_bdev_io = NULL; +} + static int bdev_rbd_reset_timer(void *arg) { struct bdev_rbd *disk = arg; - /* - * TODO: This should check if any I/O is still in flight before completing the reset. - * For now, just complete after the timer expires. - */ - bdev_rbd_io_complete(disk->reset_bdev_io, SPDK_BDEV_IO_STATUS_SUCCESS); spdk_poller_unregister(&disk->reset_timer); - disk->reset_bdev_io = NULL; + + spdk_bdev_get_current_qd(&disk->disk, bdev_rbd_check_outstanding_ios, disk); return SPDK_POLLER_BUSY; } @@ -479,11 +499,12 @@ bdev_rbd_reset(struct bdev_rbd *disk, struct spdk_bdev_io *bdev_io) { /* * HACK: Since librbd doesn't provide any way to cancel outstanding aio, just kick off a - * timer to wait for in-flight I/O to complete. + * poller to wait for in-flight I/O to complete. */ assert(disk->reset_bdev_io == NULL); disk->reset_bdev_io = bdev_io; - disk->reset_timer = SPDK_POLLER_REGISTER(bdev_rbd_reset_timer, disk, 1 * 1000 * 1000); + + bdev_rbd_reset_timer(disk); } static void