zbd: fix write zone accounting of almost full zones
authorShin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
Thu, 8 Jun 2023 07:06:04 +0000 (16:06 +0900)
committerVincent Fu <vincent.fu@samsung.com>
Thu, 8 Jun 2023 18:39:07 +0000 (14:39 -0400)
For zonemode=zbd, fio checks condition of each zone and account it as
write target zone if it has open condition. However, when such a zone in
open condition is almost full and its remainder area for write is
smaller than the block size, fio does not handle it as a write target
zone. This causes difference between open zones accounting on the device
and write target zones accounting by fio. It results in unexpected
max_open_zones limit failure.

Avoid the zone accounting difference by handling the almost full zones
as write target zones at fio start. Introduce the helper function
__zbd_write_zone_get() which does same operation as zbd_write_zone_get()
except the check for the almost full zones. At fio start, call
__zbd_write_zone_get() so that almost full zones are added to write
target zones. During fio workload run, call zbd_write_zone_get() so that
the almost full zones are not chosen for write target.

Suggested-by: Niklas Cassel <niklas.cassel@wdc.com>
Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
Reviewed-by: Niklas Cassel <niklas.cassel@wdc.com>
Signed-off-by: Vincent Fu <vincent.fu@samsung.com>
zbd.c

diff --git a/zbd.c b/zbd.c
index 832868cb45fcf425b56aaf9cea1be2c9273ed772..36b68d62597eee1be6e3b7c577d2ccac5d500a15 100644 (file)
--- a/zbd.c
+++ b/zbd.c
@@ -450,21 +450,19 @@ static int zbd_get_max_open_zones(struct thread_data *td, struct fio_file *f,
 }
 
 /**
- * zbd_write_zone_get - Add a zone to the array of write zones.
+ * __zbd_write_zone_get - Add a zone to the array of write zones.
  * @td: fio thread data.
  * @f: fio file that has the write zones array to add.
  * @zone_idx: Index of the zone to add.
  *
- * Add a ZBD zone to write target zones array, if it is not yet added. Returns
- * true if either the zone was already added or if the zone was successfully
- * added to the array without exceeding the maximum number of write zones.
- * Returns false if the zone was not already added and addition of the zone
- * would cause the zone limit to be exceeded.
+ * Do same operation as @zbd_write_zone_get, except it adds the zone at
+ * @zone_idx to write target zones array even when it does not have remainder
+ * space to write one block.
  */
-static bool zbd_write_zone_get(struct thread_data *td, const struct fio_file *f,
-                              struct fio_zone_info *z)
+static bool __zbd_write_zone_get(struct thread_data *td,
+                                const struct fio_file *f,
+                                struct fio_zone_info *z)
 {
-       const uint64_t min_bs = td->o.min_bs[DDIR_WRITE];
        struct zoned_block_device_info *zbdi = f->zbd_info;
        uint32_t zone_idx = zbd_zone_idx(f, z);
        bool res = true;
@@ -476,7 +474,7 @@ static bool zbd_write_zone_get(struct thread_data *td, const struct fio_file *f,
         * 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))
+       if (td->o.verify != VERIFY_NONE && zbd_zone_remainder(z) == 0)
                return false;
 
        /*
@@ -521,6 +519,33 @@ out:
        return res;
 }
 
+/**
+ * zbd_write_zone_get - Add a zone to the array of write zones.
+ * @td: fio thread data.
+ * @f: fio file that has the open zones to add.
+ * @zone_idx: Index of the zone to add.
+ *
+ * Add a ZBD zone to write target zones array, if it is not yet added. Returns
+ * true if either the zone was already added or if the zone was successfully
+ * added to the array without exceeding the maximum number of write zones.
+ * Returns false if the zone was not already added and addition of the zone
+ * would cause the zone limit to be exceeded.
+ */
+static bool zbd_write_zone_get(struct thread_data *td, const struct fio_file *f,
+                              struct fio_zone_info *z)
+{
+       const uint64_t min_bs = td->o.min_bs[DDIR_WRITE];
+
+       /*
+        * 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;
+
+       return __zbd_write_zone_get(td, f, z);
+}
+
 /* Verify whether direct I/O is used for all host-managed zoned block drives. */
 static bool zbd_using_direct_io(void)
 {
@@ -1202,7 +1227,7 @@ int zbd_setup_files(struct thread_data *td)
                        if (z->cond != ZBD_ZONE_COND_IMP_OPEN &&
                            z->cond != ZBD_ZONE_COND_EXP_OPEN)
                                continue;
-                       if (zbd_write_zone_get(td, f, z))
+                       if (__zbd_write_zone_get(td, f, z))
                                continue;
                        /*
                         * If the number of open zones exceeds specified limits,