From 45b5808eba402d6618d5f6a85e60b282bad1c942 Mon Sep 17 00:00:00 2001 From: Wojciech Malikowski Date: Fri, 12 Jul 2019 10:55:57 -0400 Subject: [PATCH] lib/bdev: Added spdk_bdev_zone_append() spdk_bdev_zone_append() allows writing to open zone from multiple threads or from single thread with queue depth greater than one. Zone first logical address and number of blocks to be written are provided by user. Logical block address of written data is returned in completion callback. Change-Id: I4da994d72b7e0fe6621962e3b0f2380940ec3b45 Signed-off-by: Wojciech Malikowski Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/461614 Tested-by: SPDK CI Jenkins Reviewed-by: Jim Harris Reviewed-by: Ben Walker --- include/spdk/bdev.h | 1 + include/spdk/bdev_zone.h | 50 ++++++++++++++++++++++++++++++++++++++++ lib/bdev/bdev_zone.c | 48 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+) diff --git a/include/spdk/bdev.h b/include/spdk/bdev.h index 6e3a8a11a..6abcc91c5 100644 --- a/include/spdk/bdev.h +++ b/include/spdk/bdev.h @@ -128,6 +128,7 @@ enum spdk_bdev_io_type { SPDK_BDEV_IO_TYPE_ZCOPY, SPDK_BDEV_IO_TYPE_GET_ZONE_INFO, SPDK_BDEV_IO_TYPE_ZONE_MANAGEMENT, + SPDK_BDEV_IO_TYPE_ZONE_APPEND, SPDK_BDEV_NUM_IO_TYPES /* Keep last */ }; diff --git a/include/spdk/bdev_zone.h b/include/spdk/bdev_zone.h index dde3daaf2..867bd2495 100644 --- a/include/spdk/bdev_zone.h +++ b/include/spdk/bdev_zone.h @@ -142,6 +142,56 @@ int spdk_bdev_zone_management(struct spdk_bdev_desc *desc, struct spdk_io_channe uint64_t zone_id, enum spdk_bdev_zone_action action, spdk_bdev_io_completion_cb cb, void *cb_arg); +/** + * Submit a zone_append 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 buf Data buffer to written from. + * \param zone_id First logical block of a zone. + * \param num_blocks The number of blocks to write. buf must be greater than or equal to this size. + * \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). + * Appended logical block address can be obtained with spdk_bdev_io_get_append_location(). + * 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_zone_append(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, + void *buf, uint64_t zone_id, uint64_t num_blocks, + spdk_bdev_io_completion_cb cb, void *cb_arg); + +/** + * Submit a zone_append request with metadata to the bdev. + * + * This function uses separate buffer for metadata transfer (valid only if bdev supports this + * mode). + * + * \ingroup bdev_io_submit_functions + * + * \param desc Block device descriptor. + * \param ch I/O channel. Obtained by calling spdk_bdev_get_io_channel(). + * \param buf Data buffer to written from. + * \param md Metadata buffer. + * \param zone_id First logical block of a zone. + * \param num_blocks The number of blocks to write. buf must be greater than or equal to this size. + * \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). + * Appended logical block address can be obtained with spdk_bdev_io_get_append_location(). + * 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_zone_append_with_md(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, + void *buf, void *md, uint64_t zone_id, uint64_t num_blocks, + spdk_bdev_io_completion_cb cb, void *cb_arg); + /** * Get append location (offset in blocks of the bdev) for this I/O. * diff --git a/lib/bdev/bdev_zone.c b/lib/bdev/bdev_zone.c index 0505c33af..625b9ec87 100644 --- a/lib/bdev/bdev_zone.c +++ b/lib/bdev/bdev_zone.c @@ -108,6 +108,54 @@ spdk_bdev_zone_management(struct spdk_bdev_desc *desc, struct spdk_io_channel *c return 0; } +static int +_spdk_bdev_append_with_md(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, + void *buf, void *md_buf, uint64_t zone_id, uint64_t num_blocks, + 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_ZONE_APPEND; + bdev_io->u.bdev.iovs = &bdev_io->iov; + bdev_io->u.bdev.iovs[0].iov_base = buf; + bdev_io->u.bdev.iovs[0].iov_len = num_blocks * bdev->blocklen; + bdev_io->u.bdev.iovcnt = 1; + bdev_io->u.bdev.md_buf = md_buf; + bdev_io->u.bdev.num_blocks = num_blocks; + bdev_io->u.bdev.offset_blocks = zone_id; + spdk_bdev_io_init(bdev_io, bdev, cb_arg, cb); + + spdk_bdev_io_submit(bdev_io); + return 0; +} + +int +spdk_bdev_zone_append(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, + void *buf, uint64_t start_lba, uint64_t num_blocks, + spdk_bdev_io_completion_cb cb, void *cb_arg) +{ + return _spdk_bdev_append_with_md(desc, ch, buf, NULL, start_lba, num_blocks, + cb, cb_arg); +} + +int +spdk_bdev_zone_append_with_md(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, + void *buf, void *md, uint64_t start_lba, uint64_t num_blocks, + spdk_bdev_io_completion_cb cb, void *cb_arg) +{ + return _spdk_bdev_append_with_md(desc, ch, buf, md, start_lba, num_blocks, + cb, cb_arg); +} + uint64_t spdk_bdev_io_get_append_location(struct spdk_bdev_io *bdev_io) {