From cad6f55e33eb5d47548825ee78341c28ee2a781b Mon Sep 17 00:00:00 2001 From: Shuhei Matsumoto Date: Tue, 24 May 2022 06:43:18 +0900 Subject: [PATCH] bdev: Add spdk_bdev_get_current_qd to measure and return current value The generic bdev layer has a public API spdk_bdev_get_qd() but its value is the most recently measured value and it requires qd sampling to be enabled. We will have bdev modules to want to wait until all bdev_ios are aborted by a reset. Unfortunately, spdk_bdev_get_qd() is not suitable for the custom bdev module. Furthermore, spdk_bdev_channel::io_outstanding is not accessible from bdev modules. Hence, add a new public API spdk_bdev_get_current_qd(). This function should be used only from the bdev module and it should be ensured that the bdev is not unregistered during execution. Signed-off-by: Shuhei Matsumoto Change-Id: Ica30a8d8fe3264e28f0772a39bdf5f9ba72933e1 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/12791 Community-CI: Mellanox Build Bot Tested-by: SPDK CI Jenkins Reviewed-by: Jim Harris Reviewed-by: Aleksey Marchuk --- CHANGELOG.md | 3 +++ include/spdk/bdev_module.h | 21 +++++++++++++++ lib/bdev/bdev.c | 52 ++++++++++++++++++++++++++++++++++++++ lib/bdev/spdk_bdev.map | 1 + 4 files changed, 77 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 02da05b5f..98b7ece56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,9 @@ New RPCs `bdev_xnvme_create` and `bdev_xnvme_delete` were added to support the x A new API `spdk_bdev_for_each_bdev_io` was added to execute the function on the appropriate thread for each bdev_io submitted to the bdev. +A new API `spdk_bdev_get_current_qd` was added to measure and return the queue depth from a +bdev. This API is available even when queue depth sampling is disabled. + ### sock Added new `ssl` based socket implementation, the code is located in module/sock/posix. diff --git a/include/spdk/bdev_module.h b/include/spdk/bdev_module.h index 40e59420c..e1a0bfa00 100644 --- a/include/spdk/bdev_module.h +++ b/include/spdk/bdev_module.h @@ -1313,6 +1313,27 @@ typedef void (*spdk_bdev_for_each_io_cb)(void *ctx, int rc); void spdk_bdev_for_each_bdev_io(struct spdk_bdev *bdev, void *ctx, spdk_bdev_io_fn fn, spdk_bdev_for_each_io_cb cb); +typedef void (*spdk_bdev_get_current_qd_cb)(struct spdk_bdev *bdev, uint64_t current_qd, + void *cb_arg, int rc); + +/** + * Measure and return the queue depth from a bdev. + * + * Note: spdk_bdev_get_qd() works only when the user enables queue depth sampling, + * while this new function works even when queue depth sampling is disabled. + * The returned queue depth may not be exact, for example, some additional I/Os may + * have been submitted or completed during the for_each_channel operation. + * This function should be used only in the bdev module and it should be ensured + * that the dev is not unregistered while executing the function. + * cb_fn is required to specify. + * + * \param bdev Block device to query. + * \param cb_fn Callback function to be called with queue depth measured for a bdev. + * \param cb_arg Argument to pass to callback function. + */ +void spdk_bdev_get_current_qd(struct spdk_bdev *bdev, + spdk_bdev_get_current_qd_cb cb_fn, void *cb_arg); + /* * Macro used to register module for later initialization. */ diff --git a/lib/bdev/bdev.c b/lib/bdev/bdev.c index f29db216c..d3b598ed1 100644 --- a/lib/bdev/bdev.c +++ b/lib/bdev/bdev.c @@ -4052,6 +4052,58 @@ spdk_bdev_set_qd_sampling_period(struct spdk_bdev *bdev, uint64_t period) bdev, period); } +struct bdev_get_current_qd_ctx { + uint64_t current_qd; + spdk_bdev_get_current_qd_cb cb_fn; + void *cb_arg; +}; + +static void +bdev_get_current_qd_done(struct spdk_io_channel_iter *i, int status) +{ + struct bdev_get_current_qd_ctx *ctx = spdk_io_channel_iter_get_ctx(i); + void *io_dev = spdk_io_channel_iter_get_io_device(i); + + ctx->cb_fn(__bdev_from_io_dev(io_dev), ctx->current_qd, ctx->cb_arg, 0); + + free(ctx); +} + +static void +bdev_get_current_qd(struct spdk_io_channel_iter *i) +{ + struct bdev_get_current_qd_ctx *ctx = spdk_io_channel_iter_get_ctx(i); + struct spdk_io_channel *io_ch = spdk_io_channel_iter_get_channel(i); + struct spdk_bdev_channel *bdev_ch = spdk_io_channel_get_ctx(io_ch); + + ctx->current_qd += bdev_ch->io_outstanding; + + spdk_for_each_channel_continue(i, 0); +} + +void +spdk_bdev_get_current_qd(struct spdk_bdev *bdev, spdk_bdev_get_current_qd_cb cb_fn, + void *cb_arg) +{ + struct bdev_get_current_qd_ctx *ctx; + + assert(cb_fn != NULL); + + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) { + cb_fn(bdev, 0, cb_arg, -ENOMEM); + return; + } + + ctx->cb_fn = cb_fn; + ctx->cb_arg = cb_arg; + + spdk_for_each_channel(__bdev_to_io_dev(bdev), + bdev_get_current_qd, + ctx, + bdev_get_current_qd_done); +} + static void _resize_notify(void *arg) { diff --git a/lib/bdev/spdk_bdev.map b/lib/bdev/spdk_bdev.map index 11f3709d7..e1934c8ce 100644 --- a/lib/bdev/spdk_bdev.map +++ b/lib/bdev/spdk_bdev.map @@ -45,6 +45,7 @@ spdk_bdev_get_dif_type; spdk_bdev_is_dif_head_of_md; spdk_bdev_is_dif_check_enabled; + spdk_bdev_get_current_qd; spdk_bdev_get_qd; spdk_bdev_get_qd_sampling_period; spdk_bdev_set_qd_sampling_period;