From f0494649e3019937526c8f4dac507b1350cb80d7 Mon Sep 17 00:00:00 2001 From: GangCao Date: Wed, 21 Sep 2022 21:32:37 -0400 Subject: [PATCH] Lib/Bdev: add the new API spdk_bdev_for_each_channel And also related function pointers and APIs: spdk_bdev_for_each_channel_msg; spdk_bdev_for_each_channel_done; spdk_bdev_for_each_channel_continue; Change-Id: I52f0f6f27717d53c238faf2f998810c9c5ee45d4 Signed-off-by: GangCao Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/14614 Tested-by: SPDK CI Jenkins Reviewed-by: Shuhei Matsumoto Reviewed-by: Jim Harris Community-CI: Mellanox Build Bot --- CHANGELOG.md | 5 ++++ include/spdk/bdev.h | 54 ++++++++++++++++++++++++++++++++++ lib/bdev/Makefile | 2 +- lib/bdev/bdev.c | 67 ++++++++++++++++++++++++++++++++++++++++++ lib/bdev/spdk_bdev.map | 2 ++ 5 files changed, 129 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f62f71e58..c19304307 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,11 @@ Protection information is now supported by the malloc bdev module. Changing scheduler from dynamic back to static is no longer possible, as there is no way of saving original SPDK thread distribution on reactors. +### bdev + +New APIs `spdk_bdev_for_each_channel` and `spdk_bdev_for_each_channel_continue` and +associated function pointers were added to iterate each channel of the required bdev. + ## v22.09 ### accel diff --git a/include/spdk/bdev.h b/include/spdk/bdev.h index b9bd88d84..f8087626c 100644 --- a/include/spdk/bdev.h +++ b/include/spdk/bdev.h @@ -1934,6 +1934,60 @@ size_t spdk_bdev_get_media_events(struct spdk_bdev_desc *bdev_desc, int spdk_bdev_get_memory_domains(struct spdk_bdev *bdev, struct spdk_memory_domain **domains, int array_size); +/** + * \brief SPDK bdev channel iterator. + * + * This is a virtual representation of a bdev channel iterator. + */ +struct spdk_bdev_channel_iter; + +/** + * Called on the appropriate thread for each channel associated with the given bdev. + * + * \param i bdev channel iterator. + * \param bdev Block device. + * \param ch I/O channel. + * \param ctx context of the bdev channel iterator. + */ +typedef void (*spdk_bdev_for_each_channel_msg)(struct spdk_bdev_channel_iter *i, + struct spdk_bdev *bdev, struct spdk_io_channel *ch, void *ctx); + +/** + * spdk_bdev_for_each_channel() function's final callback with the given bdev. + * + * \param bdev Block device. + * \param ctx context of the bdev channel iterator. + * \param status 0 if it completed successfully, or negative errno if it failed. + */ +typedef void (*spdk_bdev_for_each_channel_done)(struct spdk_bdev *bdev, void *ctx, int status); + +/** + * Helper function to iterate the next channel for spdk_bdev_for_each_channel(). + * + * \param i bdev channel iterator. + * \param status Status for the bdev channel iterator; + * for non 0 status remaining iterations are terminated. + */ +void spdk_bdev_for_each_channel_continue(struct spdk_bdev_channel_iter *i, int status); + +/** + * Call 'fn' on each channel associated with the given bdev. + * + * This happens asynchronously, so fn may be called after spdk_bdev_for_each_channel + * returns. 'fn' will be called for each channel serially, such that two calls + * to 'fn' will not overlap in time. After 'fn' has been called, call + * spdk_bdev_for_each_channel_continue() to continue iterating. Note that the + * spdk_bdev_for_each_channel_continue() function can be called asynchronously. + * + * \param bdev 'fn' will be called on each channel associated with this given bdev. + * \param fn Called on the appropriate thread for each channel associated with the given bdev. + * \param ctx Context for the caller. + * \param cpl Called on the thread that spdk_bdev_for_each_channel was initially called + * from when 'fn' has been called on each channel. + */ +void spdk_bdev_for_each_channel(struct spdk_bdev *bdev, spdk_bdev_for_each_channel_msg fn, + void *ctx, spdk_bdev_for_each_channel_done cpl); + #ifdef __cplusplus } #endif diff --git a/lib/bdev/Makefile b/lib/bdev/Makefile index b9399d692..c7c12e3b2 100644 --- a/lib/bdev/Makefile +++ b/lib/bdev/Makefile @@ -7,7 +7,7 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..) include $(SPDK_ROOT_DIR)/mk/spdk.common.mk SO_VER := 10 -SO_MINOR := 0 +SO_MINOR := 1 ifeq ($(CONFIG_VTUNE),y) CFLAGS += -I$(CONFIG_VTUNE_DIR)/include -I$(CONFIG_VTUNE_DIR)/sdk/src/ittnotify diff --git a/lib/bdev/bdev.c b/lib/bdev/bdev.c index 8f1dd51e6..fc8a8d542 100644 --- a/lib/bdev/bdev.c +++ b/lib/bdev/bdev.c @@ -321,6 +321,13 @@ struct set_qos_limit_ctx { struct spdk_bdev *bdev; }; +struct spdk_bdev_channel_iter { + spdk_bdev_for_each_channel_msg fn; + spdk_bdev_for_each_channel_done cpl; + struct spdk_io_channel_iter *i; + void *ctx; +}; + #define __bdev_to_io_dev(bdev) (((char *)bdev) + 1) #define __bdev_from_io_dev(io_dev) ((struct spdk_bdev *)(((char *)io_dev) - 1)) @@ -8033,6 +8040,66 @@ spdk_bdev_for_each_bdev_io(struct spdk_bdev *bdev, void *_ctx, spdk_bdev_io_fn f bdev_for_each_io_done); } +void +spdk_bdev_for_each_channel_continue(struct spdk_bdev_channel_iter *iter, int status) +{ + spdk_for_each_channel_continue(iter->i, status); +} + +static struct spdk_bdev * +io_channel_iter_get_bdev(struct spdk_io_channel_iter *i) +{ + void *io_device = spdk_io_channel_iter_get_io_device(i); + + return __bdev_from_io_dev(io_device); +} + +static void +bdev_each_channel_msg(struct spdk_io_channel_iter *i) +{ + struct spdk_bdev_channel_iter *iter = spdk_io_channel_iter_get_ctx(i); + struct spdk_bdev *bdev = io_channel_iter_get_bdev(i); + struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i); + + iter->i = i; + iter->fn(iter, bdev, ch, iter->ctx); +} + +static void +bdev_each_channel_cpl(struct spdk_io_channel_iter *i, int status) +{ + struct spdk_bdev_channel_iter *iter = spdk_io_channel_iter_get_ctx(i); + struct spdk_bdev *bdev = io_channel_iter_get_bdev(i); + + iter->i = i; + iter->cpl(bdev, iter->ctx, status); + + free(iter); +} + +void +spdk_bdev_for_each_channel(struct spdk_bdev *bdev, spdk_bdev_for_each_channel_msg fn, + void *ctx, spdk_bdev_for_each_channel_done cpl) +{ + struct spdk_bdev_channel_iter *iter; + + assert(bdev != NULL && fn != NULL && ctx != NULL); + + iter = calloc(1, sizeof(struct spdk_bdev_channel_iter)); + if (iter == NULL) { + SPDK_ERRLOG("Unable to allocate iterator\n"); + assert(false); + return; + } + + iter->fn = fn; + iter->cpl = cpl; + iter->ctx = ctx; + + spdk_for_each_channel(__bdev_to_io_dev(bdev), bdev_each_channel_msg, + iter, bdev_each_channel_cpl); +} + SPDK_LOG_REGISTER_COMPONENT(bdev) SPDK_TRACE_REGISTER_FN(bdev_trace, "bdev", TRACE_GROUP_BDEV) diff --git a/lib/bdev/spdk_bdev.map b/lib/bdev/spdk_bdev.map index 1808a9899..8078528b4 100644 --- a/lib/bdev/spdk_bdev.map +++ b/lib/bdev/spdk_bdev.map @@ -103,6 +103,8 @@ spdk_bdev_get_memory_domains; spdk_bdev_readv_blocks_ext; spdk_bdev_writev_blocks_ext; + spdk_bdev_for_each_channel; + spdk_bdev_for_each_channel_continue; # Public functions in bdev_module.h spdk_bdev_register;