zbd: move zone finish operation to zbd_convert_to_write_zone()
authorShin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
Mon, 14 Apr 2025 06:27:18 +0000 (15:27 +0900)
committerJens Axboe <axboe@kernel.dk>
Mon, 14 Apr 2025 14:27:31 +0000 (08:27 -0600)
Currently, when a write target zone has fewer remainder sectors than
the block size, fio finishes the zone to make the zone inactive (not
open), so that another zone can be open and used as a write target zone.
This zone finish operation is implemented in zbd_adjust_block().
However, this placement is less ideal because zbd_adjust_block() manages
not just write requests but also read and trim requests.

Since the zone finish operation is exclusively necessary for write
requests, implement it into zbd_convert_to_write_zone(). While at it,
improve the function comment.

Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Link: https://lore.kernel.org/r/20250414062721.87641-2-shinichiro.kawasaki@wdc.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
zbd.c

diff --git a/zbd.c b/zbd.c
index ee095b1dd5f827bf5cfc94147c01606dd8c0f584..ac65640b06813cffce5ba4cec9609a0420e25bc3 100644 (file)
--- a/zbd.c
+++ b/zbd.c
@@ -1396,16 +1396,23 @@ static bool any_io_in_flight(void)
        return false;
 }
 
-/*
+/**
+ * zbd_convert_to_write_zone - Convert the target zone of an io_u to a writable zone
+ * @td: The fio thread data
+ * @io_u: The I/O unit that targets the zone to convert
+ * @zb: The zone selected at the beginning of the function call. The caller must
+ *      hold zb->mutex.
+ *
  * Modify the offset of an I/O unit that does not refer to a zone such that
- * in write target zones array. Add a zone to or remove a zone from the lsit if
+ * in write target zones array. Add a zone to or remove a zone from the array if
  * necessary. The write target zone is searched across sequential zones.
  * This algorithm can only work correctly if all write pointers are
- * a multiple of the fio block size. The caller must neither hold z->mutex
- * nor f->zbd_info->mutex. Returns with z->mutex held upon success.
+ * a multiple of the fio block size. The caller must not hold
+ * f->zbd_info->mutex. Returns with z->mutex held upon success.
  */
 static struct fio_zone_info *zbd_convert_to_write_zone(struct thread_data *td,
-                                                      struct io_u *io_u)
+                                                      struct io_u *io_u,
+                                                      struct fio_zone_info *zb)
 {
        const uint64_t min_bs = td->o.min_bs[io_u->ddir];
        struct fio_file *f = io_u->file;
@@ -1420,6 +1427,34 @@ static struct fio_zone_info *zbd_convert_to_write_zone(struct thread_data *td,
 
        assert(is_valid_offset(f, io_u->offset));
 
+       if (zbd_zone_remainder(zb) > 0 && zbd_zone_remainder(zb) < min_bs) {
+               pthread_mutex_lock(&f->zbd_info->mutex);
+               zbd_write_zone_put(td, f, zb);
+               pthread_mutex_unlock(&f->zbd_info->mutex);
+               dprint(FD_ZBD, "%s: finish zone %d\n",
+                      f->file_name, zbd_zone_idx(f, zb));
+               io_u_quiesce(td);
+               zbd_finish_zone(td, f, zb);
+               zone_unlock(zb);
+
+               if (zbd_zone_idx(f, zb) + 1 >= f->max_zone && !td_random(td))
+                       return NULL;
+
+               /* Find the next write pointer zone */
+               do {
+                       zb++;
+                       if (zbd_zone_idx(f, zb) >= f->max_zone)
+                               zb = zbd_get_zone(f, f->min_zone);
+               } while (!zb->has_wp);
+
+               zone_lock(td, f, zb);
+       }
+
+       if (zbd_write_zone_get(td, f, zb))
+               return zb;
+
+       zone_unlock(zb);
+
        if (zbdi->max_write_zones || td->o.job_max_open_zones) {
                /*
                 * This statement accesses zbdi->write_zones[] on purpose
@@ -2047,40 +2082,11 @@ enum io_u_action zbd_adjust_block(struct thread_data *td, struct io_u *io_u)
                }
 
 retry:
-               if (zbd_zone_remainder(zb) > 0 &&
-                   zbd_zone_remainder(zb) < min_bs) {
-                       pthread_mutex_lock(&f->zbd_info->mutex);
-                       zbd_write_zone_put(td, f, zb);
-                       pthread_mutex_unlock(&f->zbd_info->mutex);
-                       dprint(FD_ZBD,
-                              "%s: finish zone %d\n",
-                              f->file_name, zbd_zone_idx(f, zb));
-                       io_u_quiesce(td);
-                       zbd_finish_zone(td, f, zb);
-                       if (zbd_zone_idx(f, zb) + 1 >= f->max_zone) {
-                               if (!td_random(td))
-                                       goto eof;
-                       }
-                       zone_unlock(zb);
-
-                       /* Find the next write pointer zone */
-                       do {
-                               zb++;
-                               if (zbd_zone_idx(f, zb) >= f->max_zone)
-                                       zb = zbd_get_zone(f, f->min_zone);
-                       } while (!zb->has_wp);
-
-                       zone_lock(td, f, zb);
-               }
-
-               if (!zbd_write_zone_get(td, f, zb)) {
-                       zone_unlock(zb);
-                       zb = zbd_convert_to_write_zone(td, io_u);
-                       if (!zb) {
-                               dprint(FD_IO, "%s: can't convert to write target zone",
-                                      f->file_name);
-                               goto eof;
-                       }
+               zb = zbd_convert_to_write_zone(td, io_u, zb);
+               if (!zb) {
+                       dprint(FD_IO, "%s: can't convert to write target zone",
+                              f->file_name);
+                       goto eof;
                }
 
                if (zbd_zone_remainder(zb) > 0 &&