zbd: Report the zone capacity
[fio.git] / zbd.c
diff --git a/zbd.c b/zbd.c
index f5e76c405697b0642802ec2f2c524bfbf883fca0..1d96bf178aac56de93b520aa894ca32a8cab3b5c 100644 (file)
--- a/zbd.c
+++ b/zbd.c
@@ -147,6 +147,11 @@ zbd_offset_to_zone(const struct fio_file *f,  uint64_t offset)
        return zbd_get_zone(f, zbd_offset_to_zone_idx(f, offset));
 }
 
+static bool accounting_vdb(struct thread_data *td, const struct fio_file *f)
+{
+       return td->o.zrt.u.f && td_write(td);
+}
+
 /**
  * zbd_get_zoned_model - Get a device zoned model
  * @td: FIO thread data
@@ -285,9 +290,11 @@ static int zbd_reset_zone(struct thread_data *td, struct fio_file *f,
                break;
        }
 
-       pthread_mutex_lock(&f->zbd_info->mutex);
-       f->zbd_info->wp_sectors_with_data -= data_in_zone;
-       pthread_mutex_unlock(&f->zbd_info->mutex);
+       if (accounting_vdb(td, f)) {
+               pthread_mutex_lock(&f->zbd_info->mutex);
+               f->zbd_info->wp_valid_data_bytes -= data_in_zone;
+               pthread_mutex_unlock(&f->zbd_info->mutex);
+       }
 
        z->wp = z->start;
 
@@ -535,7 +542,7 @@ static bool zbd_using_direct_io(void)
 }
 
 /* Whether or not the I/O range for f includes one or more sequential zones */
-static bool zbd_is_seq_job(struct fio_file *f)
+static bool zbd_is_seq_job(const struct fio_file *f)
 {
        uint32_t zone_idx, zone_idx_b, zone_idx_e;
 
@@ -800,8 +807,8 @@ static int parse_zone_info(struct thread_data *td, struct fio_file *f)
                goto out;
        }
 
-       dprint(FD_ZBD, "Device %s has %d zones of size %"PRIu64" KB\n",
-              f->file_name, nr_zones, zone_size / 1024);
+       dprint(FD_ZBD, "Device %s has %d zones of size %"PRIu64" KB and capacity %"PRIu64" KB\n",
+              f->file_name, nr_zones, zone_size / 1024, zones[0].capacity / 1024);
 
        zbd_info = scalloc(1, sizeof(*zbd_info) +
                           (nr_zones + 1) * sizeof(zbd_info->zone_info[0]));
@@ -1067,6 +1074,52 @@ void zbd_recalc_options_with_zone_granularity(struct thread_data *td)
        }
 }
 
+static uint64_t zbd_verify_and_set_vdb(struct thread_data *td,
+                                      const struct fio_file *f)
+{
+       struct fio_zone_info *zb, *ze, *z;
+       uint64_t wp_vdb = 0;
+       struct zoned_block_device_info *zbdi = f->zbd_info;
+
+       assert(td->runstate < TD_RUNNING);
+       assert(zbdi);
+
+       if (!accounting_vdb(td, f))
+               return 0;
+
+       /*
+        * Ensure that the I/O range includes one or more sequential zones so
+        * that f->min_zone and f->max_zone have different values.
+        */
+       if (!zbd_is_seq_job(f))
+               return 0;
+
+       if (zbdi->write_min_zone != zbdi->write_max_zone) {
+               if (zbdi->write_min_zone != f->min_zone ||
+                   zbdi->write_max_zone != f->max_zone) {
+                       td_verror(td, EINVAL,
+                                 "multi-jobs with different write ranges are "
+                                 "not supported with zone_reset_threshold");
+                       log_err("multi-jobs with different write ranges are "
+                               "not supported with zone_reset_threshold\n");
+               }
+               return 0;
+       }
+
+       zbdi->write_min_zone = f->min_zone;
+       zbdi->write_max_zone = f->max_zone;
+
+       zb = zbd_get_zone(f, f->min_zone);
+       ze = zbd_get_zone(f, f->max_zone);
+       for (z = zb; z < ze; z++)
+               if (z->has_wp)
+                       wp_vdb += z->wp - z->start;
+
+       zbdi->wp_valid_data_bytes = wp_vdb;
+
+       return wp_vdb;
+}
+
 int zbd_setup_files(struct thread_data *td)
 {
        struct fio_file *f;
@@ -1092,6 +1145,7 @@ int zbd_setup_files(struct thread_data *td)
                struct zoned_block_device_info *zbd = f->zbd_info;
                struct fio_zone_info *z;
                int zi;
+               uint64_t vdb;
 
                assert(zbd);
 
@@ -1099,6 +1153,11 @@ int zbd_setup_files(struct thread_data *td)
                f->max_zone =
                        zbd_offset_to_zone_idx(f, f->file_offset + f->io_size);
 
+               vdb = zbd_verify_and_set_vdb(td, f);
+
+               dprint(FD_ZBD, "%s(%s): valid data bytes = %" PRIu64 "\n",
+                      __func__, f->file_name, vdb);
+
                /*
                 * When all zones in the I/O range are conventional, io_size
                 * can be smaller than zone size, making min_zone the same
@@ -1190,64 +1249,9 @@ static bool zbd_dec_and_reset_write_cnt(const struct thread_data *td,
        return write_cnt == 0;
 }
 
-enum swd_action {
-       CHECK_SWD,
-       SET_SWD,
-};
-
-/* Calculate the number of sectors with data (swd) and perform action 'a' */
-static uint64_t zbd_process_swd(struct thread_data *td,
-                               const struct fio_file *f, enum swd_action a)
-{
-       struct fio_zone_info *zb, *ze, *z;
-       uint64_t wp_swd = 0;
-
-       zb = zbd_get_zone(f, f->min_zone);
-       ze = zbd_get_zone(f, f->max_zone);
-       for (z = zb; z < ze; z++) {
-               if (z->has_wp) {
-                       zone_lock(td, f, z);
-                       wp_swd += z->wp - z->start;
-               }
-       }
-
-       pthread_mutex_lock(&f->zbd_info->mutex);
-       switch (a) {
-       case CHECK_SWD:
-               assert(f->zbd_info->wp_sectors_with_data == wp_swd);
-               break;
-       case SET_SWD:
-               f->zbd_info->wp_sectors_with_data = wp_swd;
-               break;
-       }
-       pthread_mutex_unlock(&f->zbd_info->mutex);
-
-       for (z = zb; z < ze; z++)
-               if (z->has_wp)
-                       zone_unlock(z);
-
-       return wp_swd;
-}
-
-/*
- * The swd check is useful for debugging but takes too much time to leave
- * it enabled all the time. Hence it is disabled by default.
- */
-static const bool enable_check_swd = false;
-
-/* Check whether the values of zbd_info.*sectors_with_data are correct. */
-static void zbd_check_swd(struct thread_data *td, const struct fio_file *f)
-{
-       if (!enable_check_swd)
-               return;
-
-       zbd_process_swd(td, f, CHECK_SWD);
-}
-
 void zbd_file_reset(struct thread_data *td, struct fio_file *f)
 {
        struct fio_zone_info *zb, *ze;
-       uint64_t swd;
        bool verify_data_left = false;
 
        if (!f->zbd_info || !td_write(td))
@@ -1255,10 +1259,6 @@ void zbd_file_reset(struct thread_data *td, struct fio_file *f)
 
        zb = zbd_get_zone(f, f->min_zone);
        ze = zbd_get_zone(f, f->max_zone);
-       swd = zbd_process_swd(td, f, SET_SWD);
-
-       dprint(FD_ZBD, "%s(%s): swd = %" PRIu64 "\n",
-              __func__, f->file_name, swd);
 
        /*
         * If data verification is enabled reset the affected zones before
@@ -1634,10 +1634,11 @@ static void zbd_queue_io(struct thread_data *td, struct io_u *io_u, int q,
                 * z->wp > zone_end means that one or more I/O errors
                 * have occurred.
                 */
-               pthread_mutex_lock(&zbd_info->mutex);
-               if (z->wp <= zone_end)
-                       zbd_info->wp_sectors_with_data += zone_end - z->wp;
-               pthread_mutex_unlock(&zbd_info->mutex);
+               if (accounting_vdb(td, f) && z->wp <= zone_end) {
+                       pthread_mutex_lock(&zbd_info->mutex);
+                       zbd_info->wp_valid_data_bytes += zone_end - z->wp;
+                       pthread_mutex_unlock(&zbd_info->mutex);
+               }
                z->wp = zone_end;
                break;
        default:
@@ -1677,7 +1678,6 @@ static void zbd_put_io(struct thread_data *td, const struct io_u *io_u)
        zbd_end_zone_io(td, io_u, z);
 
        zone_unlock(z);
-       zbd_check_swd(td, f);
 }
 
 /*
@@ -1866,8 +1866,6 @@ enum io_u_action zbd_adjust_block(struct thread_data *td, struct io_u *io_u)
            io_u->ddir == DDIR_READ && td->o.read_beyond_wp)
                return io_u_accept;
 
-       zbd_check_swd(td, f);
-
        zone_lock(td, f, zb);
 
        switch (io_u->ddir) {
@@ -1992,7 +1990,8 @@ retry:
 
                /* Check whether the zone reset threshold has been exceeded */
                if (td->o.zrf.u.f) {
-                       if (zbdi->wp_sectors_with_data >= f->io_size * td->o.zrt.u.f &&
+                       if (zbdi->wp_valid_data_bytes >=
+                           f->io_size * td->o.zrt.u.f &&
                            zbd_dec_and_reset_write_cnt(td, f))
                                zb->reset_zone = 1;
                }