zbd: fix write zone accounting of trim workload
authorShin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
Thu, 8 Jun 2023 07:06:05 +0000 (16:06 +0900)
committerVincent Fu <vincent.fu@samsung.com>
Thu, 8 Jun 2023 18:39:07 +0000 (14:39 -0400)
The commit e3be810bf0fd ("zbd: Support zone reset by trim") supported
trim for zonemode=zbd by introducing the function zbd_do_io_u_trim(),
which calls zbd_reset_zone(). However, it did not call
zbd_write_zone_put() to the trim target zone, then trim operation
resulted in wrong accounting of write zones.

To fix the issue, call zbd_write_zone_put() from zbd_reset_zone(). To
cover the case to reset zones without a zbd_write_zone_put() call,
prepare another function __zbd_reset_zone(). While at it, simplify
zbd_reset_zones() by calling the modified zbd_reset_zone().

Of note is that the constifier of the argument td of do_io_u_trim() is
removed since zbd_write_zone_put() requires changes in that argument.

Fixes: e3be810bf0fd ("zbd: Support zone reset by trim")
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>
engines/io_uring.c
io_u.c
io_u.h
zbd.c
zbd.h

index ff64fc9fbfa9b9980a58e35e0aa3dd9bde3a56b0..73e4a27abf3cf1d026e1ab12b3935c90a77feba8 100644 (file)
@@ -561,7 +561,7 @@ static inline void fio_ioring_cmdprio_prep(struct thread_data *td,
                ld->sqes[io_u->index].ioprio = io_u->ioprio;
 }
 
-static int fio_ioring_cmd_io_u_trim(const struct thread_data *td,
+static int fio_ioring_cmd_io_u_trim(struct thread_data *td,
                                    struct io_u *io_u)
 {
        struct fio_file *f = io_u->file;
diff --git a/io_u.c b/io_u.c
index 6f5fc94d9a3e87bf68e3a5cdd2149579ac855720..faf512e53a39e6704764777e80f3f8da6a88517c 100644 (file)
--- a/io_u.c
+++ b/io_u.c
@@ -2379,7 +2379,7 @@ int do_io_u_sync(const struct thread_data *td, struct io_u *io_u)
        return ret;
 }
 
-int do_io_u_trim(const struct thread_data *td, struct io_u *io_u)
+int do_io_u_trim(struct thread_data *td, struct io_u *io_u)
 {
 #ifndef FIO_HAVE_TRIM
        io_u->error = EINVAL;
diff --git a/io_u.h b/io_u.h
index 55b4d08312b2d3fff93f341ff194f22a426d09e6..b432a54010ebc5f154e1ff7e220c9719c001a33d 100644 (file)
--- a/io_u.h
+++ b/io_u.h
@@ -162,7 +162,7 @@ void io_u_mark_submit(struct thread_data *, unsigned int);
 bool queue_full(const struct thread_data *);
 
 int do_io_u_sync(const struct thread_data *, struct io_u *);
-int do_io_u_trim(const struct thread_data *, struct io_u *);
+int do_io_u_trim(struct thread_data *, struct io_u *);
 
 #ifdef FIO_INC_DEBUG
 static inline void dprint_io_u(struct io_u *io_u, const char *p)
diff --git a/zbd.c b/zbd.c
index 36b68d62597eee1be6e3b7c577d2ccac5d500a15..9455140ac89fd16f0279ad1b24bb530ad4809cfe 100644 (file)
--- a/zbd.c
+++ b/zbd.c
@@ -254,7 +254,7 @@ static int zbd_reset_wp(struct thread_data *td, struct fio_file *f,
 }
 
 /**
- * zbd_reset_zone - reset the write pointer of a single zone
+ * __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.
@@ -263,8 +263,8 @@ static int zbd_reset_wp(struct thread_data *td, struct fio_file *f,
  *
  * The caller must hold z->mutex.
  */
-static int zbd_reset_zone(struct thread_data *td, struct fio_file *f,
-                         struct fio_zone_info *z)
+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;
@@ -339,6 +339,32 @@ static void zbd_write_zone_put(struct thread_data *td, const struct fio_file *f,
        z->write = 0;
 }
 
+/**
+ * zbd_reset_zone - reset the write pointer of a single zone and remove the zone
+ *                  from the array of write zones.
+ * @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)
+{
+       int ret;
+
+       ret = __zbd_reset_zone(td, f, z);
+       if (ret)
+               return ret;
+
+       pthread_mutex_lock(&f->zbd_info->mutex);
+       zbd_write_zone_put(td, f, z);
+       pthread_mutex_unlock(&f->zbd_info->mutex);
+       return 0;
+}
+
 /**
  * zbd_finish_zone - finish the specified zone
  * @td: FIO thread data.
@@ -404,9 +430,6 @@ static int zbd_reset_zones(struct thread_data *td, struct fio_file *f,
                        continue;
 
                zone_lock(td, f, z);
-               pthread_mutex_lock(&f->zbd_info->mutex);
-               zbd_write_zone_put(td, f, z);
-               pthread_mutex_unlock(&f->zbd_info->mutex);
 
                if (z->wp != z->start) {
                        dprint(FD_ZBD, "%s: resetting zone %u\n",
@@ -2048,7 +2071,7 @@ retry:
                         */
                        io_u_quiesce(td);
                        zb->reset_zone = 0;
-                       if (zbd_reset_zone(td, f, zb) < 0)
+                       if (__zbd_reset_zone(td, f, zb) < 0)
                                goto eof;
 
                        if (zb->capacity < min_bs) {
@@ -2167,7 +2190,7 @@ char *zbd_write_status(const struct thread_stat *ts)
  * Return io_u_completed when reset zone succeeds. Return 0 when the target zone
  * does not have write pointer. On error, return negative errno.
  */
-int zbd_do_io_u_trim(const struct thread_data *td, struct io_u *io_u)
+int zbd_do_io_u_trim(struct thread_data *td, struct io_u *io_u)
 {
        struct fio_file *f = io_u->file;
        struct fio_zone_info *z;
diff --git a/zbd.h b/zbd.h
index 25a3e0f1f9c802f3a6e51c1eaf38088806b8a2c6..f0ac98763ca71f38b36174a74ce41dfdd7d40dff 100644 (file)
--- a/zbd.h
+++ b/zbd.h
@@ -100,7 +100,7 @@ enum fio_ddir zbd_adjust_ddir(struct thread_data *td, struct io_u *io_u,
                              enum fio_ddir ddir);
 enum io_u_action zbd_adjust_block(struct thread_data *td, struct io_u *io_u);
 char *zbd_write_status(const struct thread_stat *ts);
-int zbd_do_io_u_trim(const struct thread_data *td, struct io_u *io_u);
+int zbd_do_io_u_trim(struct thread_data *td, struct io_u *io_u);
 
 static inline void zbd_close_file(struct fio_file *f)
 {