zbd: introduce zbd_zone_align_file_sizes() helper
[fio.git] / zbd.c
diff --git a/zbd.c b/zbd.c
index 44e7722799c729fef85853cff284ad9ac2f0d10b..11c15c622f2a268b361fdd1a060208a2b6ae75c0 100644 (file)
--- a/zbd.c
+++ b/zbd.c
 #include "pshared.h"
 #include "zbd.h"
 
+static bool is_valid_offset(const struct fio_file *f, uint64_t offset)
+{
+       return (uint64_t)(offset - f->file_offset) < f->io_size;
+}
+
+static inline unsigned int zbd_zone_nr(const struct fio_file *f,
+                                      struct fio_zone_info *zone)
+{
+       return zone - f->zbd_info->zone_info;
+}
+
+/**
+ * zbd_zone_idx - convert an offset into a zone number
+ * @f: file pointer.
+ * @offset: offset in bytes. If this offset is in the first zone_size bytes
+ *         past the disk size then the index of the sentinel is returned.
+ */
+static uint32_t zbd_zone_idx(const struct fio_file *f, uint64_t offset)
+{
+       uint32_t zone_idx;
+
+       if (f->zbd_info->zone_size_log2 > 0)
+               zone_idx = offset >> f->zbd_info->zone_size_log2;
+       else
+               zone_idx = offset / f->zbd_info->zone_size;
+
+       return min(zone_idx, f->zbd_info->nr_zones);
+}
+
+/**
+ * zbd_zone_end - Return zone end location
+ * @z: zone info pointer.
+ */
+static inline uint64_t zbd_zone_end(const struct fio_zone_info *z)
+{
+       return (z+1)->start;
+}
+
+/**
+ * zbd_zone_capacity_end - Return zone capacity limit end location
+ * @z: zone info pointer.
+ */
+static inline uint64_t zbd_zone_capacity_end(const struct fio_zone_info *z)
+{
+       return z->start + z->capacity;
+}
+
+/**
+ * zbd_zone_full - verify whether a minimum number of bytes remain in a zone
+ * @f: file pointer.
+ * @z: zone info pointer.
+ * @required: minimum number of bytes that must remain in a zone.
+ *
+ * The caller must hold z->mutex.
+ */
+static bool zbd_zone_full(const struct fio_file *f, struct fio_zone_info *z,
+                         uint64_t required)
+{
+       assert((required & 511) == 0);
+
+       return z->has_wp &&
+               z->wp + required > zbd_zone_capacity_end(z);
+}
+
+static void zone_lock(struct thread_data *td, const struct fio_file *f,
+                     struct fio_zone_info *z)
+{
+       struct zoned_block_device_info *zbd = f->zbd_info;
+       uint32_t nz = z - zbd->zone_info;
+
+       /* A thread should never lock zones outside its working area. */
+       assert(f->min_zone <= nz && nz < f->max_zone);
+
+       assert(z->has_wp);
+
+       /*
+        * Lock the io_u target zone. The zone will be unlocked if io_u offset
+        * is changed or when io_u completes and zbd_put_io() executed.
+        * To avoid multiple jobs doing asynchronous I/Os from deadlocking each
+        * other waiting for zone locks when building an io_u batch, first
+        * only trylock the zone. If the zone is already locked by another job,
+        * process the currently queued I/Os so that I/O progress is made and
+        * zones unlocked.
+        */
+       if (pthread_mutex_trylock(&z->mutex) != 0) {
+               if (!td_ioengine_flagged(td, FIO_SYNCIO))
+                       io_u_quiesce(td);
+               pthread_mutex_lock(&z->mutex);
+       }
+}
+
+static inline void zone_unlock(struct fio_zone_info *z)
+{
+       int ret;
+
+       assert(z->has_wp);
+       ret = pthread_mutex_unlock(&z->mutex);
+       assert(!ret);
+}
+
+static inline struct fio_zone_info *get_zone(const struct fio_file *f,
+                                            unsigned int zone_nr)
+{
+       return &f->zbd_info->zone_info[zone_nr];
+}
+
 /**
  * zbd_get_zoned_model - Get a device zoned model
  * @td: FIO thread data
@@ -124,131 +230,219 @@ static int zbd_reset_wp(struct thread_data *td, struct fio_file *f,
 }
 
 /**
- * zbd_get_max_open_zones - Get the maximum number of open zones
- * @td: FIO thread data
- * @f: FIO file for which to get max open zones
- * @max_open_zones: Upon success, result will be stored here.
- *
- * A @max_open_zones value set to zero means no limit.
+ * zbd_reset_zone - reset the write pointer of a single zone
+ * @td: FIO thread data.
+ * @f: FIO file associated with the disk for which to reset a write pointer.
+ * @z: Zone to reset.
  *
  * Returns 0 upon success and a negative error code upon failure.
+ *
+ * The caller must hold z->mutex.
  */
-static int zbd_get_max_open_zones(struct thread_data *td, struct fio_file *f,
-                                 unsigned int *max_open_zones)
+static int zbd_reset_zone(struct thread_data *td, struct fio_file *f,
+                         struct fio_zone_info *z)
 {
-       int ret;
+       uint64_t offset = z->start;
+       uint64_t length = (z+1)->start - offset;
+       uint64_t data_in_zone = z->wp - z->start;
+       int ret = 0;
 
-       if (td->io_ops && td->io_ops->get_max_open_zones)
-               ret = td->io_ops->get_max_open_zones(td, f, max_open_zones);
-       else
-               ret = blkzoned_get_max_open_zones(td, f, max_open_zones);
-       if (ret < 0) {
-               td_verror(td, errno, "get max open zones failed");
-               log_err("%s: get max open zones failed (%d).\n",
-                       f->file_name, errno);
+       if (!data_in_zone)
+               return 0;
+
+       assert(is_valid_offset(f, offset + length - 1));
+
+       dprint(FD_ZBD, "%s: resetting wp of zone %u.\n", f->file_name,
+               zbd_zone_nr(f, z));
+       switch (f->zbd_info->model) {
+       case ZBD_HOST_AWARE:
+       case ZBD_HOST_MANAGED:
+               ret = zbd_reset_wp(td, f, offset, length);
+               if (ret < 0)
+                       return ret;
+               break;
+       default:
+               break;
        }
 
+       pthread_mutex_lock(&f->zbd_info->mutex);
+       f->zbd_info->sectors_with_data -= data_in_zone;
+       f->zbd_info->wp_sectors_with_data -= data_in_zone;
+       pthread_mutex_unlock(&f->zbd_info->mutex);
+       z->wp = z->start;
+       z->verify_block = 0;
+
+       td->ts.nr_zone_resets++;
+
        return ret;
 }
 
 /**
- * zbd_zone_idx - convert an offset into a zone number
- * @f: file pointer.
- * @offset: offset in bytes. If this offset is in the first zone_size bytes
- *         past the disk size then the index of the sentinel is returned.
+ * zbd_close_zone - Remove a zone from the open zones array.
+ * @td: FIO thread data.
+ * @f: FIO file associated with the disk for which to reset a write pointer.
+ * @zone_idx: Index of the zone to remove.
+ *
+ * The caller must hold f->zbd_info->mutex.
  */
-static uint32_t zbd_zone_idx(const struct fio_file *f, uint64_t offset)
+static void zbd_close_zone(struct thread_data *td, const struct fio_file *f,
+                          unsigned int zone_idx)
 {
-       uint32_t zone_idx;
+       uint32_t open_zone_idx = 0;
 
-       if (f->zbd_info->zone_size_log2 > 0)
-               zone_idx = offset >> f->zbd_info->zone_size_log2;
-       else
-               zone_idx = offset / f->zbd_info->zone_size;
+       for (; open_zone_idx < f->zbd_info->num_open_zones; open_zone_idx++) {
+               if (f->zbd_info->open_zones[open_zone_idx] == zone_idx)
+                       break;
+       }
+       if (open_zone_idx == f->zbd_info->num_open_zones)
+               return;
 
-       return min(zone_idx, f->zbd_info->nr_zones);
+       dprint(FD_ZBD, "%s: closing zone %d\n", f->file_name, zone_idx);
+       memmove(f->zbd_info->open_zones + open_zone_idx,
+               f->zbd_info->open_zones + open_zone_idx + 1,
+               (ZBD_MAX_OPEN_ZONES - (open_zone_idx + 1)) *
+               sizeof(f->zbd_info->open_zones[0]));
+       f->zbd_info->num_open_zones--;
+       td->num_open_zones--;
+       get_zone(f, zone_idx)->open = 0;
 }
 
 /**
- * zbd_zone_end - Return zone end location
- * @z: zone info pointer.
+ * zbd_reset_zones - Reset a range of zones.
+ * @td: fio thread data.
+ * @f: fio file for which to reset zones
+ * @zb: first zone to reset.
+ * @ze: first zone not to reset.
+ *
+ * Returns 0 upon success and 1 upon failure.
  */
-static inline uint64_t zbd_zone_end(const struct fio_zone_info *z)
+static int zbd_reset_zones(struct thread_data *td, struct fio_file *f,
+                          struct fio_zone_info *const zb,
+                          struct fio_zone_info *const ze)
 {
-       return (z+1)->start;
-}
+       struct fio_zone_info *z;
+       const uint64_t min_bs = td->o.min_bs[DDIR_WRITE];
+       int res = 0;
 
-/**
- * zbd_zone_capacity_end - Return zone capacity limit end location
- * @z: zone info pointer.
- */
-static inline uint64_t zbd_zone_capacity_end(const struct fio_zone_info *z)
-{
-       return z->start + z->capacity;
+       assert(min_bs);
+
+       dprint(FD_ZBD, "%s: examining zones %u .. %u\n", f->file_name,
+               zbd_zone_nr(f, zb), zbd_zone_nr(f, ze));
+       for (z = zb; z < ze; z++) {
+               uint32_t nz = zbd_zone_nr(f, z);
+
+               if (!z->has_wp)
+                       continue;
+               zone_lock(td, f, z);
+               pthread_mutex_lock(&f->zbd_info->mutex);
+               zbd_close_zone(td, f, nz);
+               pthread_mutex_unlock(&f->zbd_info->mutex);
+               if (z->wp != z->start) {
+                       dprint(FD_ZBD, "%s: resetting zone %u\n",
+                              f->file_name, zbd_zone_nr(f, z));
+                       if (zbd_reset_zone(td, f, z) < 0)
+                               res = 1;
+               }
+               zone_unlock(z);
+       }
+
+       return res;
 }
 
 /**
- * zbd_zone_full - verify whether a minimum number of bytes remain in a zone
- * @f: file pointer.
- * @z: zone info pointer.
- * @required: minimum number of bytes that must remain in a zone.
+ * zbd_get_max_open_zones - Get the maximum number of open zones
+ * @td: FIO thread data
+ * @f: FIO file for which to get max open zones
+ * @max_open_zones: Upon success, result will be stored here.
  *
- * The caller must hold z->mutex.
+ * A @max_open_zones value set to zero means no limit.
+ *
+ * Returns 0 upon success and a negative error code upon failure.
  */
-static bool zbd_zone_full(const struct fio_file *f, struct fio_zone_info *z,
-                         uint64_t required)
+static int zbd_get_max_open_zones(struct thread_data *td, struct fio_file *f,
+                                 unsigned int *max_open_zones)
 {
-       assert((required & 511) == 0);
+       int ret;
 
-       return z->has_wp &&
-               z->wp + required > zbd_zone_capacity_end(z);
+       if (td->io_ops && td->io_ops->get_max_open_zones)
+               ret = td->io_ops->get_max_open_zones(td, f, max_open_zones);
+       else
+               ret = blkzoned_get_max_open_zones(td, f, max_open_zones);
+       if (ret < 0) {
+               td_verror(td, errno, "get max open zones failed");
+               log_err("%s: get max open zones failed (%d).\n",
+                       f->file_name, errno);
+       }
+
+       return ret;
 }
 
-static void zone_lock(struct thread_data *td, const struct fio_file *f,
-                     struct fio_zone_info *z)
+/**
+ * zbd_open_zone - Add a zone to the array of open zones.
+ * @td: fio thread data.
+ * @f: fio file that has the open zones to add.
+ * @zone_idx: Index of the zone to add.
+ *
+ * Open a ZBD zone if it is not already open. Returns true if either the zone
+ * was already open or if the zone was successfully added to the array of open
+ * zones without exceeding the maximum number of open zones. Returns false if
+ * the zone was not already open and opening the zone would cause the zone limit
+ * to be exceeded.
+ */
+static bool zbd_open_zone(struct thread_data *td, const struct fio_file *f,
+                         uint32_t zone_idx)
 {
-       struct zoned_block_device_info *zbd = f->zbd_info;
-       uint32_t nz = z - zbd->zone_info;
-
-       /* A thread should never lock zones outside its working area. */
-       assert(f->min_zone <= nz && nz < f->max_zone);
+       const uint64_t min_bs = td->o.min_bs[DDIR_WRITE];
+       struct zoned_block_device_info *zbdi = f->zbd_info;
+       struct fio_zone_info *z = get_zone(f, zone_idx);
+       bool res = true;
 
-       assert(z->has_wp);
+       if (z->cond == ZBD_ZONE_COND_OFFLINE)
+               return false;
 
        /*
-        * Lock the io_u target zone. The zone will be unlocked if io_u offset
-        * is changed or when io_u completes and zbd_put_io() executed.
-        * To avoid multiple jobs doing asynchronous I/Os from deadlocking each
-        * other waiting for zone locks when building an io_u batch, first
-        * only trylock the zone. If the zone is already locked by another job,
-        * process the currently queued I/Os so that I/O progress is made and
-        * zones unlocked.
+        * Skip full zones with data verification enabled because resetting a
+        * zone causes data loss and hence causes verification to fail.
         */
-       if (pthread_mutex_trylock(&z->mutex) != 0) {
-               if (!td_ioengine_flagged(td, FIO_SYNCIO))
-                       io_u_quiesce(td);
-               pthread_mutex_lock(&z->mutex);
-       }
-}
+       if (td->o.verify != VERIFY_NONE && zbd_zone_full(f, z, min_bs))
+               return false;
 
-static inline void zone_unlock(struct fio_zone_info *z)
-{
-       int ret;
+       /*
+        * zbdi->max_open_zones == 0 means that there is no limit on the maximum
+        * number of open zones. In this case, do no track open zones in
+        * zbdi->open_zones array.
+        */
+       if (!zbdi->max_open_zones)
+               return true;
 
-       assert(z->has_wp);
-       ret = pthread_mutex_unlock(&z->mutex);
-       assert(!ret);
-}
+       pthread_mutex_lock(&zbdi->mutex);
 
-static bool is_valid_offset(const struct fio_file *f, uint64_t offset)
-{
-       return (uint64_t)(offset - f->file_offset) < f->io_size;
-}
+       if (z->open) {
+               /*
+                * If the zone is going to be completely filled by writes
+                * already in-flight, handle it as a full zone instead of an
+                * open zone.
+                */
+               if (z->wp >= zbd_zone_capacity_end(z))
+                       res = false;
+               goto out;
+       }
+       res = false;
+       /* Zero means no limit */
+       if (td->o.job_max_open_zones > 0 &&
+           td->num_open_zones >= td->o.job_max_open_zones)
+               goto out;
+       if (zbdi->num_open_zones >= zbdi->max_open_zones)
+               goto out;
+       dprint(FD_ZBD, "%s: opening zone %d\n", f->file_name, zone_idx);
+       zbdi->open_zones[zbdi->num_open_zones++] = zone_idx;
+       td->num_open_zones++;
+       z->open = 1;
+       res = true;
 
-static inline struct fio_zone_info *get_zone(const struct fio_file *f,
-                                            unsigned int zone_nr)
-{
-       return &f->zbd_info->zone_info[zone_nr];
+out:
+       pthread_mutex_unlock(&zbdi->mutex);
+       return res;
 }
 
 /* Verify whether direct I/O is used for all host-managed zoned drives. */
@@ -288,79 +482,95 @@ static bool zbd_is_seq_job(struct fio_file *f)
        return false;
 }
 
+/*
+ * Verify whether the file offset and size parameters are aligned with zone
+ * boundaries. If the file offset is not aligned, align it down to the start of
+ * the zone containing the start offset and align up the file io_size parameter.
+ */
+static bool zbd_zone_align_file_sizes(struct thread_data *td,
+                                     struct fio_file *f)
+{
+       const struct fio_zone_info *z;
+       uint64_t new_offset, new_end;
+       uint32_t zone_idx;
+
+       if (!f->zbd_info)
+               return true;
+       if (f->file_offset >= f->real_file_size)
+               return true;
+       if (!zbd_is_seq_job(f))
+               return true;
+
+       if (!td->o.zone_size) {
+               td->o.zone_size = f->zbd_info->zone_size;
+               if (!td->o.zone_size) {
+                       log_err("%s: invalid 0 zone size\n",
+                               f->file_name);
+                       return false;
+               }
+       } else if (td->o.zone_size != f->zbd_info->zone_size) {
+               log_err("%s: zonesize %llu does not match the device zone size %"PRIu64".\n",
+                       f->file_name, td->o.zone_size,
+                       f->zbd_info->zone_size);
+               return false;
+       }
+
+       if (td->o.zone_skip % td->o.zone_size) {
+               log_err("%s: zoneskip %llu is not a multiple of the device zone size %llu.\n",
+                       f->file_name, td->o.zone_skip,
+                       td->o.zone_size);
+               return false;
+       }
+
+       zone_idx = zbd_zone_idx(f, f->file_offset);
+       z = get_zone(f, zone_idx);
+       if ((f->file_offset != z->start) &&
+           (td->o.td_ddir != TD_DDIR_READ)) {
+               new_offset = zbd_zone_end(z);
+               if (new_offset >= f->file_offset + f->io_size) {
+                       log_info("%s: io_size must be at least one zone\n",
+                                f->file_name);
+                       return false;
+               }
+               log_info("%s: rounded up offset from %"PRIu64" to %"PRIu64"\n",
+                        f->file_name, f->file_offset,
+                        new_offset);
+               f->io_size -= (new_offset - f->file_offset);
+               f->file_offset = new_offset;
+       }
+
+       zone_idx = zbd_zone_idx(f, f->file_offset + f->io_size);
+       z = get_zone(f, zone_idx);
+       new_end = z->start;
+       if ((td->o.td_ddir != TD_DDIR_READ) &&
+           (f->file_offset + f->io_size != new_end)) {
+               if (new_end <= f->file_offset) {
+                       log_info("%s: io_size must be at least one zone\n",
+                                f->file_name);
+                       return false;
+               }
+               log_info("%s: rounded down io_size from %"PRIu64" to %"PRIu64"\n",
+                        f->file_name, f->io_size,
+                        new_end - f->file_offset);
+               f->io_size = new_end - f->file_offset;
+       }
+
+       return true;
+}
+
 /*
  * Verify whether offset and size parameters are aligned with zone boundaries.
  */
 static bool zbd_verify_sizes(void)
 {
-       const struct fio_zone_info *z;
        struct thread_data *td;
        struct fio_file *f;
-       uint64_t new_offset, new_end;
-       uint32_t zone_idx;
        int i, j;
 
        for_each_td(td, i) {
                for_each_file(td, f, j) {
-                       if (!f->zbd_info)
-                               continue;
-                       if (f->file_offset >= f->real_file_size)
-                               continue;
-                       if (!zbd_is_seq_job(f))
-                               continue;
-
-                       if (!td->o.zone_size) {
-                               td->o.zone_size = f->zbd_info->zone_size;
-                               if (!td->o.zone_size) {
-                                       log_err("%s: invalid 0 zone size\n",
-                                               f->file_name);
-                                       return false;
-                               }
-                       } else if (td->o.zone_size != f->zbd_info->zone_size) {
-                               log_err("%s: job parameter zonesize %llu does not match disk zone size %"PRIu64".\n",
-                                       f->file_name, td->o.zone_size,
-                                       f->zbd_info->zone_size);
-                               return false;
-                       }
-
-                       if (td->o.zone_skip % td->o.zone_size) {
-                               log_err("%s: zoneskip %llu is not a multiple of the device zone size %llu.\n",
-                                       f->file_name, td->o.zone_skip,
-                                       td->o.zone_size);
+                       if (!zbd_zone_align_file_sizes(td, f))
                                return false;
-                       }
-
-                       zone_idx = zbd_zone_idx(f, f->file_offset);
-                       z = get_zone(f, zone_idx);
-                       if ((f->file_offset != z->start) &&
-                           (td->o.td_ddir != TD_DDIR_READ)) {
-                               new_offset = zbd_zone_end(z);
-                               if (new_offset >= f->file_offset + f->io_size) {
-                                       log_info("%s: io_size must be at least one zone\n",
-                                                f->file_name);
-                                       return false;
-                               }
-                               log_info("%s: rounded up offset from %"PRIu64" to %"PRIu64"\n",
-                                        f->file_name, f->file_offset,
-                                        new_offset);
-                               f->io_size -= (new_offset - f->file_offset);
-                               f->file_offset = new_offset;
-                       }
-                       zone_idx = zbd_zone_idx(f, f->file_offset + f->io_size);
-                       z = get_zone(f, zone_idx);
-                       new_end = z->start;
-                       if ((td->o.td_ddir != TD_DDIR_READ) &&
-                           (f->file_offset + f->io_size != new_end)) {
-                               if (new_end <= f->file_offset) {
-                                       log_info("%s: io_size must be at least one zone\n",
-                                                f->file_name);
-                                       return false;
-                               }
-                               log_info("%s: rounded down io_size from %"PRIu64" to %"PRIu64"\n",
-                                        f->file_name, f->io_size,
-                                        new_end - f->file_offset);
-                               f->io_size = new_end - f->file_offset;
-                       }
                }
        }
 
@@ -751,11 +961,6 @@ static int zbd_init_zone_info(struct thread_data *td, struct fio_file *file)
        return ret;
 }
 
-static bool zbd_open_zone(struct thread_data *td, const struct fio_file *f,
-                         uint32_t zone_idx);
-static int zbd_reset_zone(struct thread_data *td, struct fio_file *f,
-                         struct fio_zone_info *z);
-
 int zbd_init_files(struct thread_data *td)
 {
        struct fio_file *f;
@@ -879,123 +1084,6 @@ int zbd_setup_files(struct thread_data *td)
        return 0;
 }
 
-static inline unsigned int zbd_zone_nr(const struct fio_file *f,
-                                      struct fio_zone_info *zone)
-{
-       return zone - f->zbd_info->zone_info;
-}
-
-/**
- * zbd_reset_zone - reset the write pointer of a single zone
- * @td: FIO thread data.
- * @f: FIO file associated with the disk for which to reset a write pointer.
- * @z: Zone to reset.
- *
- * Returns 0 upon success and a negative error code upon failure.
- *
- * The caller must hold z->mutex.
- */
-static int zbd_reset_zone(struct thread_data *td, struct fio_file *f,
-                         struct fio_zone_info *z)
-{
-       uint64_t offset = z->start;
-       uint64_t length = (z+1)->start - offset;
-       uint64_t data_in_zone = z->wp - z->start;
-       int ret = 0;
-
-       if (!data_in_zone)
-               return 0;
-
-       assert(is_valid_offset(f, offset + length - 1));
-
-       dprint(FD_ZBD, "%s: resetting wp of zone %u.\n", f->file_name,
-               zbd_zone_nr(f, z));
-       switch (f->zbd_info->model) {
-       case ZBD_HOST_AWARE:
-       case ZBD_HOST_MANAGED:
-               ret = zbd_reset_wp(td, f, offset, length);
-               if (ret < 0)
-                       return ret;
-               break;
-       default:
-               break;
-       }
-
-       pthread_mutex_lock(&f->zbd_info->mutex);
-       f->zbd_info->sectors_with_data -= data_in_zone;
-       f->zbd_info->wp_sectors_with_data -= data_in_zone;
-       pthread_mutex_unlock(&f->zbd_info->mutex);
-       z->wp = z->start;
-       z->verify_block = 0;
-
-       td->ts.nr_zone_resets++;
-
-       return ret;
-}
-
-/* The caller must hold f->zbd_info->mutex */
-static void zbd_close_zone(struct thread_data *td, const struct fio_file *f,
-                          unsigned int zone_idx)
-{
-       uint32_t open_zone_idx = 0;
-
-       for (; open_zone_idx < f->zbd_info->num_open_zones; open_zone_idx++) {
-               if (f->zbd_info->open_zones[open_zone_idx] == zone_idx)
-                       break;
-       }
-       if (open_zone_idx == f->zbd_info->num_open_zones)
-               return;
-
-       dprint(FD_ZBD, "%s: closing zone %d\n", f->file_name, zone_idx);
-       memmove(f->zbd_info->open_zones + open_zone_idx,
-               f->zbd_info->open_zones + open_zone_idx + 1,
-               (ZBD_MAX_OPEN_ZONES - (open_zone_idx + 1)) *
-               sizeof(f->zbd_info->open_zones[0]));
-       f->zbd_info->num_open_zones--;
-       td->num_open_zones--;
-       get_zone(f, zone_idx)->open = 0;
-}
-
-/*
- * Reset a range of zones. Returns 0 upon success and 1 upon failure.
- * @td: fio thread data.
- * @f: fio file for which to reset zones
- * @zb: first zone to reset.
- * @ze: first zone not to reset.
- */
-static int zbd_reset_zones(struct thread_data *td, struct fio_file *f,
-                          struct fio_zone_info *const zb,
-                          struct fio_zone_info *const ze)
-{
-       struct fio_zone_info *z;
-       const uint64_t min_bs = td->o.min_bs[DDIR_WRITE];
-       int res = 0;
-
-       assert(min_bs);
-
-       dprint(FD_ZBD, "%s: examining zones %u .. %u\n", f->file_name,
-               zbd_zone_nr(f, zb), zbd_zone_nr(f, ze));
-       for (z = zb; z < ze; z++) {
-               uint32_t nz = zbd_zone_nr(f, z);
-
-               if (!z->has_wp)
-                       continue;
-               zone_lock(td, f, z);
-               pthread_mutex_lock(&f->zbd_info->mutex);
-               zbd_close_zone(td, f, nz);
-               pthread_mutex_unlock(&f->zbd_info->mutex);
-               if (z->wp != z->start) {
-                       dprint(FD_ZBD, "%s: resetting zone %u\n",
-                              f->file_name, zbd_zone_nr(f, z));
-                       if (zbd_reset_zone(td, f, z) < 0)
-                               res = 1;
-               }
-               zone_unlock(z);
-       }
-
-       return res;
-}
-
 /*
  * Reset zbd_info.write_cnt, the counter that counts down towards the next
  * zone reset.
@@ -1112,86 +1200,6 @@ void zbd_file_reset(struct thread_data *td, struct fio_file *f)
        zbd_reset_write_cnt(td, f);
 }
 
-/* The caller must hold f->zbd_info->mutex. */
-static bool is_zone_open(const struct thread_data *td, const struct fio_file *f,
-                        unsigned int zone_idx)
-{
-       struct zoned_block_device_info *zbdi = f->zbd_info;
-       int i;
-
-       /* This function should never be called when zbdi->max_open_zones == 0 */
-       assert(zbdi->max_open_zones);
-       assert(td->o.job_max_open_zones == 0 || td->num_open_zones <= td->o.job_max_open_zones);
-       assert(td->o.job_max_open_zones <= zbdi->max_open_zones);
-       assert(zbdi->num_open_zones <= zbdi->max_open_zones);
-
-       for (i = 0; i < zbdi->num_open_zones; i++)
-               if (zbdi->open_zones[i] == zone_idx)
-                       return true;
-
-       return false;
-}
-
-/*
- * Open a ZBD zone if it was not yet open. Returns true if either the zone was
- * already open or if opening a new zone is allowed. Returns false if the zone
- * was not yet open and opening a new zone would cause the zone limit to be
- * exceeded.
- */
-static bool zbd_open_zone(struct thread_data *td, const struct fio_file *f,
-                         uint32_t zone_idx)
-{
-       const uint64_t min_bs = td->o.min_bs[DDIR_WRITE];
-       struct zoned_block_device_info *zbdi = f->zbd_info;
-       struct fio_zone_info *z = get_zone(f, zone_idx);
-       bool res = true;
-
-       if (z->cond == ZBD_ZONE_COND_OFFLINE)
-               return false;
-
-       /*
-        * Skip full zones with data verification enabled because resetting a
-        * zone causes data loss and hence causes verification to fail.
-        */
-       if (td->o.verify != VERIFY_NONE && zbd_zone_full(f, z, min_bs))
-               return false;
-
-       /*
-        * zbdi->max_open_zones == 0 means that there is no limit on the maximum
-        * number of open zones. In this case, do no track open zones in
-        * zbdi->open_zones array.
-        */
-       if (!zbdi->max_open_zones)
-               return true;
-
-       pthread_mutex_lock(&zbdi->mutex);
-       if (is_zone_open(td, f, zone_idx)) {
-               /*
-                * If the zone is already open and going to be full by writes
-                * in-flight, handle it as a full zone instead of an open zone.
-                */
-               if (z->wp >= zbd_zone_capacity_end(z))
-                       res = false;
-               goto out;
-       }
-       res = false;
-       /* Zero means no limit */
-       if (td->o.job_max_open_zones > 0 &&
-           td->num_open_zones >= td->o.job_max_open_zones)
-               goto out;
-       if (zbdi->num_open_zones >= zbdi->max_open_zones)
-               goto out;
-       dprint(FD_ZBD, "%s: opening zone %d\n", f->file_name, zone_idx);
-       zbdi->open_zones[zbdi->num_open_zones++] = zone_idx;
-       td->num_open_zones++;
-       z->open = 1;
-       res = true;
-
-out:
-       pthread_mutex_unlock(&zbdi->mutex);
-       return res;
-}
-
 /* Return random zone index for one of the open zones. */
 static uint32_t pick_random_zone_idx(const struct fio_file *f,
                                     const struct io_u *io_u)