bdev: Add spdk_bdev_for_each_bdev_io() to execute function for each bdev_io

Some use cases want to abort every bdev_io submitted to the bdev by
traversing the bdev channels.

However, struct spdk_bdev_channel is private in lib/bdev/bdev.c.

Hence, add a helper function spdk_bdev_for_each_bdev_io() to execute
the function on the appropriate thread for every bdev_io submitted
to the bdev.

This function should be used only from the bdev module and it should
be ensured that the bdev is not unregistered during execution.

We keep this function as generic as possible because we may have
other use cases in future.

Signed-off-by: Shuhei Matsumoto <smatsumoto@nvidia.com>
Change-Id: Ic0209361bd1228ea8d4cb3241d0df07106be58d9
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/12751
Community-CI: Mellanox Build Bot
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com>
This commit is contained in:
Shuhei Matsumoto 2022-05-20 11:46:49 +09:00 committed by Tomasz Zawadzki
parent 3851a64f9f
commit 1212b53fb8
4 changed files with 84 additions and 0 deletions

View File

@ -17,6 +17,9 @@ an object with an array named "subsystems".
New RPCs `bdev_xnvme_create` and `bdev_xnvme_delete` were added to support the xNVMe bdev.
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.
### sock
Added new `ssl` based socket implementation, the code is located in module/sock/posix.

View File

@ -1293,6 +1293,26 @@ int spdk_bdev_push_media_events(struct spdk_bdev *bdev, const struct spdk_bdev_m
*/
void spdk_bdev_notify_media_management(struct spdk_bdev *bdev);
typedef int (*spdk_bdev_io_fn)(void *ctx, struct spdk_bdev_io *bdev_io);
typedef void (*spdk_bdev_for_each_io_cb)(void *ctx, int rc);
/**
* Call the provided function on the appropriate thread for each bdev_io submitted
* to the provided bdev.
*
* Note: This function should be used only in the bdev module and it should be
* ensured that the bdev is not unregistered while executing the function.
* Both fn and cb are required to specify.
*
* \param bdev Block device to query.
* \param ctx Context passed to the function for each bdev_io and the completion
* callback function.
* \param fn Called on the appropriate thread for each bdev_io submitted to the bdev.
* \param cb Called when this operation completes.
*/
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);
/*
* Macro used to register module for later initialization.
*/

View File

@ -7739,6 +7739,66 @@ spdk_bdev_get_memory_domains(struct spdk_bdev *bdev, struct spdk_memory_domain *
return 0;
}
struct spdk_bdev_for_each_io_ctx {
void *ctx;
spdk_bdev_io_fn fn;
spdk_bdev_for_each_io_cb cb;
};
static void
bdev_channel_for_each_io(struct spdk_io_channel_iter *i)
{
struct spdk_bdev_for_each_io_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);
struct spdk_bdev_io *bdev_io;
int rc = 0;
TAILQ_FOREACH(bdev_io, &bdev_ch->io_submitted, internal.ch_link) {
rc = ctx->fn(ctx->ctx, bdev_io);
if (rc != 0) {
break;
}
}
spdk_for_each_channel_continue(i, rc);
}
static void
bdev_for_each_io_done(struct spdk_io_channel_iter *i, int status)
{
struct spdk_bdev_for_each_io_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
ctx->cb(ctx->ctx, status);
free(ctx);
}
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)
{
struct spdk_bdev_for_each_io_ctx *ctx;
assert(fn != NULL && cb != NULL);
ctx = calloc(1, sizeof(*ctx));
if (ctx == NULL) {
SPDK_ERRLOG("Failed to allocate context.\n");
cb(_ctx, -ENOMEM);
return;
}
ctx->ctx = _ctx;
ctx->fn = fn;
ctx->cb = cb;
spdk_for_each_channel(__bdev_to_io_dev(bdev),
bdev_channel_for_each_io,
ctx,
bdev_for_each_io_done);
}
SPDK_LOG_REGISTER_COMPONENT(bdev)
SPDK_TRACE_REGISTER_FN(bdev_trace, "bdev", TRACE_GROUP_BDEV)

View File

@ -147,6 +147,7 @@
spdk_bdev_part_get_offset_blocks;
spdk_bdev_push_media_events;
spdk_bdev_notify_media_management;
spdk_bdev_for_each_bdev_io;
# Public functions in bdev_zone.h
spdk_bdev_get_zone_size;