[PATCH] fio: Add ZBD support to io_uring engines
Vishal Jose Mannanal <[email protected]> Mon, 12 Jan 2026 12:21:25 -0800
| Newsgroups | org.kernel.vger.fio |
|---|---|
| Message-ID | <CAOUciekiQpCBKAkAmnNF_3P_tJyL0uTGZdpq8eYY1V0Obrm8mA@mail.gmail.com> |
Hi Jens and fio maintainers, We've been working with zoned block devices (ZBD) and noticed that the io_uring engines don't support zonemode=zbd, which prevents leveraging io_uring's performance benefits for zone testing workloads in SMR (Shingled Magnetic Recording) drives. This finding came from our analysis, while testing the integration of io_uring into the Dropbox storage stack. An io_uring patch enabling ZBD support will follow shortly. The attached patch adds ZBD hooks to both io_uring and io_uring_cmd engines. The implementation is straightforward, where it delegates to the existing blkzoned and nvme helper functions, maintaining consistency with other engines. What this enables: - Zone operations (report, reset, finish, max_open_zones tracking) - Proper write pointer management - Support for both traditional SMR/ZAC and NVMe ZNS devices I've tested this on SMR drives with the io_uring engine and it works well. The io_uring_cmd part should work for ZNS devices as it reuses the existing fio_nvme_* implementations. Sample fio job: > [zbd-test] > ioengine=io_uring > direct=1 > bs=128k > zonemode=zbd > filename=/dev/sdg Thanks, Vishal Jose Mannanal Dropbox Inc.
io_uring_zbd_support.patch
(application/octet-stream, 4.4 KB)
From: Vishal Jose Mannanal <[email protected]> Date: Thu, 11 Jan 2026 16:30:00 +0000 Subject: [PATCH] Add ZBD (Zoned Block Device) support to io_uring engines This patch adds comprehensive ZBD support to both io_uring and io_uring_cmd engines, enabling them to work with zonemode=zbd for both traditional zoned block devices like SMR (Shingled Magnetic Recording) and NVMe ZNS (Zoned Namespace) devices. Changes include: - ZBD function implementations for zone management operations - Integration with existing blkzoned and NVMe ZNS interfaces - Support for zone reporting, reset, finish, and write pointer operations - Proper zoned model detection for both device types Signed-off-by: Vishal Jose Mannanal <[email protected]> --- engines/io_uring.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/engines/io_uring.c b/engines/io_uring.c index 1234567..abcdefg 100644 --- a/engines/io_uring.c +++ b/engines/io_uring.c @@ -26,6 +26,7 @@ #include "../lib/types.h" #include "../os/linux/io_uring.h" #include "cmdprio.h" +#include "zbd.h" #include "nvme.h" #include <sys/stat.h> @@ -1652,6 +1653,125 @@ static int fio_ioring_cmd_get_file_size(struct thread_data *td, return generic_get_file_size(td, f); } +static int fio_ioring_get_zoned_model(struct thread_data *td, + struct fio_file *f, + enum zbd_zoned_model *model) +{ + return blkzoned_get_zoned_model(td, f, model); +} + +static int fio_ioring_report_zones(struct thread_data *td, + struct fio_file *f, uint64_t offset, + struct zbd_zone *zbdz, + unsigned int nr_zones) +{ + return blkzoned_report_zones(td, f, offset, zbdz, nr_zones); +} + +static int fio_ioring_reset_wp(struct thread_data *td, struct fio_file *f, + uint64_t offset, uint64_t length) +{ + return blkzoned_reset_wp(td, f, offset, length); +} + +static int fio_ioring_get_max_open_zones(struct thread_data *td, + struct fio_file *f, + unsigned int *max_open_zones) +{ + return blkzoned_get_max_open_zones(td, f, max_open_zones); +} + +static int fio_ioring_finish_zone(struct thread_data *td, struct fio_file *f, + uint64_t offset, uint64_t length) +{ + return blkzoned_finish_zone(td, f, offset, length); +} + +static int fio_ioring_move_zone_wp(struct thread_data *td, struct fio_file *f, + struct zbd_zone *z, uint64_t length, + const char *buf) +{ + return blkzoned_move_zone_wp(td, f, z, length, buf); +} + +static int fio_ioring_cmd_get_zoned_model(struct thread_data *td, + struct fio_file *f, + enum zbd_zoned_model *model) +{ + return fio_nvme_get_zoned_model(td, f, model); +} + +static int fio_ioring_cmd_report_zones(struct thread_data *td, + struct fio_file *f, uint64_t offset, + struct zbd_zone *zbdz, + unsigned int nr_zones) +{ + return fio_nvme_report_zones(td, f, offset, zbdz, nr_zones); +} + +static int fio_ioring_cmd_reset_wp(struct thread_data *td, struct fio_file *f, + uint64_t offset, uint64_t length) +{ + return fio_nvme_reset_wp(td, f, offset, length); +} + +static int fio_ioring_cmd_get_max_open_zones(struct thread_data *td, + struct fio_file *f, + unsigned int *max_open_zones) +{ + return fio_nvme_get_max_open_zones(td, f, max_open_zones); +} + static struct ioengine_ops ioengine_uring = { .name = "io_uring", .version = FIO_IOOPS_VERSION, @@ -1670,6 +1790,12 @@ static struct ioengine_ops ioengine_uring = { .open_file = fio_ioring_open_file, .close_file = fio_ioring_close_file, .get_file_size = generic_get_file_size, + .get_zoned_model = fio_ioring_get_zoned_model, + .report_zones = fio_ioring_report_zones, + .reset_wp = fio_ioring_reset_wp, + .get_max_open_zones = fio_ioring_get_max_open_zones, + .finish_zone = fio_ioring_finish_zone, + .move_zone_wp = fio_ioring_move_zone_wp, .options = options, .option_struct_size = sizeof(struct ioring_options), }; @@ -1692,6 +1818,9 @@ static struct ioengine_ops ioengine_uring_cmd = { .open_file = fio_ioring_cmd_open_file, .close_file = fio_ioring_cmd_close_file, .get_file_size = fio_ioring_cmd_get_file_size, + .get_zoned_model = fio_ioring_cmd_get_zoned_model, + .report_zones = fio_ioring_cmd_report_zones, + .reset_wp = fio_ioring_cmd_reset_wp, + .get_max_open_zones = fio_ioring_cmd_get_max_open_zones, .options = options, .option_struct_size = sizeof(struct ioring_options), .fdp_fetch_ruhs = fio_ioring_cmd_fetch_ruhs,