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) {