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;