From 02cabd9eb8fa86525cbf46521ba83e1e48c70d3b Mon Sep 17 00:00:00 2001 From: Wojciech Malikowski Date: Thu, 4 Jul 2019 09:28:13 -0400 Subject: [PATCH] lib/bdev: Added spdk_bdev_get_zone_info() command spdk_bdev_get_zone_info() is used for retriving information about zones inside zoned namespace. Change-Id: I8f931505245e984c0b1ee35ed6592c978ee47544 Signed-off-by: Wojciech Malikowski Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/460643 Tested-by: SPDK CI Jenkins Reviewed-by: Ben Walker Reviewed-by: Jim Harris --- include/spdk/bdev.h | 1 + include/spdk/bdev_module.h | 11 +++++++++++ include/spdk/bdev_zone.h | 39 ++++++++++++++++++++++++++++++++++++++ lib/bdev/bdev_zone.c | 28 +++++++++++++++++++++++++++ 4 files changed, 79 insertions(+) diff --git a/include/spdk/bdev.h b/include/spdk/bdev.h index 59e4e4d00..3ea6b4158 100644 --- a/include/spdk/bdev.h +++ b/include/spdk/bdev.h @@ -126,6 +126,7 @@ enum spdk_bdev_io_type { SPDK_BDEV_IO_TYPE_NVME_IO_MD, SPDK_BDEV_IO_TYPE_WRITE_ZEROES, SPDK_BDEV_IO_TYPE_ZCOPY, + SPDK_BDEV_IO_TYPE_GET_ZONE_INFO, SPDK_BDEV_NUM_IO_TYPES /* Keep last */ }; diff --git a/include/spdk/bdev_module.h b/include/spdk/bdev_module.h index 4a3df0480..7d27cba41 100644 --- a/include/spdk/bdev_module.h +++ b/include/spdk/bdev_module.h @@ -43,6 +43,7 @@ #include "spdk/stdinc.h" #include "spdk/bdev.h" +#include "spdk/bdev_zone.h" #include "spdk/queue.h" #include "spdk/scsi_spec.h" #include "spdk/thread.h" @@ -512,6 +513,16 @@ struct spdk_bdev_io { /* meta data buffer size to transfer */ size_t md_len; } nvme_passthru; + struct { + /* First logical block of a zone */ + uint64_t zone_id; + + /* Number of zones */ + uint32_t num_zones; + + /* The data buffer */ + void *buf; + } zone_mgmt; } u; /** It may be used by modules to put the bdev_io into its own list. */ diff --git a/include/spdk/bdev_zone.h b/include/spdk/bdev_zone.h index 5f5fb687c..c992d076d 100644 --- a/include/spdk/bdev_zone.h +++ b/include/spdk/bdev_zone.h @@ -39,6 +39,7 @@ #define SPDK_BDEV_ZONE_H #include "spdk/stdinc.h" +#include "spdk/bdev.h" /** * \brief SPDK block device. @@ -48,6 +49,22 @@ struct spdk_bdev; +enum spdk_bdev_zone_state { + SPDK_BDEV_ZONE_STATE_EMPTY, + SPDK_BDEV_ZONE_STATE_OPEN, + SPDK_BDEV_ZONE_STATE_FULL, + SPDK_BDEV_ZONE_STATE_CLOSED, + SPDK_BDEV_ZONE_STATE_READ_ONLY, + SPDK_BDEV_ZONE_STATE_OFFLINE +}; + +struct spdk_bdev_zone_info { + uint64_t zone_id; + uint64_t write_pointer; + uint64_t capacity; + enum spdk_bdev_zone_state state; +}; + /** * Get device zone size in logical blocks. * @@ -74,4 +91,26 @@ uint32_t spdk_bdev_get_max_open_zones(const struct spdk_bdev *bdev); */ uint32_t spdk_bdev_get_optimal_open_zones(const struct spdk_bdev *bdev); +/** + * Submit a get_zone_info request to the bdev. + * + * \ingroup bdev_io_submit_functions + * + * \param desc Block device descriptor. + * \param ch I/O channel. Obtained by calling spdk_bdev_get_io_channel(). + * \param zone_id First logical block of a zone. + * \param num_zones Number of consecutive zones info to retrieve. + * \param info Pointer to array capable of storing num_zones elements. + * \param cb Called when the request is complete. + * \param cb_arg Argument passed to cb. + * + * \return 0 on success. On success, the callback will always + * be called (even if the request ultimately failed). Return + * negated errno on failure, in which case the callback will not be called. + * * -ENOMEM - spdk_bdev_io buffer cannot be allocated + */ +int spdk_bdev_get_zone_info(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, + uint64_t zone_id, size_t num_zones, struct spdk_bdev_zone_info *info, + spdk_bdev_io_completion_cb cb, void *cb_arg); + #endif /* SPDK_BDEV_ZONE_H */ diff --git a/lib/bdev/bdev_zone.c b/lib/bdev/bdev_zone.c index a96cf9bb7..ce4bfeb6f 100644 --- a/lib/bdev/bdev_zone.c +++ b/lib/bdev/bdev_zone.c @@ -36,6 +36,8 @@ #include "spdk/bdev_zone.h" #include "spdk/bdev_module.h" +#include "bdev_internal.h" + uint64_t spdk_bdev_get_zone_size(const struct spdk_bdev *bdev) { @@ -53,3 +55,29 @@ spdk_bdev_get_optimal_open_zones(const struct spdk_bdev *bdev) { return bdev->optimal_open_zones; } + +int +spdk_bdev_get_zone_info(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, + uint64_t zone_id, size_t num_zones, struct spdk_bdev_zone_info *info, + spdk_bdev_io_completion_cb cb, void *cb_arg) +{ + struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(desc); + struct spdk_bdev_io *bdev_io; + struct spdk_bdev_channel *channel = spdk_io_channel_get_ctx(ch); + + bdev_io = spdk_bdev_get_io(channel); + if (!bdev_io) { + return -ENOMEM; + } + + bdev_io->internal.ch = channel; + bdev_io->internal.desc = desc; + bdev_io->type = SPDK_BDEV_IO_TYPE_GET_ZONE_INFO; + bdev_io->u.zone_mgmt.zone_id = zone_id; + bdev_io->u.zone_mgmt.num_zones = num_zones; + bdev_io->u.zone_mgmt.buf = info; + spdk_bdev_io_init(bdev_io, bdev, cb_arg, cb); + + spdk_bdev_io_submit(bdev_io); + return 0; +}