t/fiotestlib: use dictionaries for filenames and paths
[fio.git] / zbd.c
diff --git a/zbd.c b/zbd.c
index b6cf2a93be86e7b630ea20b63df2475eb2304b71..5f1a7d7f3edb46ecdd3179918995b412979335ad 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
@@ -208,8 +213,8 @@ static int zbd_report_zones(struct thread_data *td, struct fio_file *f,
                ret = blkzoned_report_zones(td, f, offset, zones, nr_zones);
        if (ret < 0) {
                td_verror(td, errno, "report zones failed");
-               log_err("%s: report zones from sector %"PRIu64" failed (%d).\n",
-                       f->file_name, offset >> 9, errno);
+               log_err("%s: report zones from sector %"PRIu64" failed (nr_zones=%d; errno=%d).\n",
+                       f->file_name, offset >> 9, nr_zones, errno);
        } else if (ret == 0) {
                td_verror(td, errno, "Empty zone report");
                log_err("%s: report zones from sector %"PRIu64" is empty.\n",
@@ -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;
 
@@ -517,11 +524,10 @@ out:
 /* Verify whether direct I/O is used for all host-managed zoned block drives. */
 static bool zbd_using_direct_io(void)
 {
-       struct thread_data *td;
        struct fio_file *f;
-       int i, j;
+       int j;
 
-       for_each_td(td, i) {
+       for_each_td(td) {
                if (td->o.odirect || !(td->o.td_ddir & TD_DDIR_WRITE))
                        continue;
                for_each_file(td, f, j) {
@@ -529,13 +535,13 @@ static bool zbd_using_direct_io(void)
                            f->zbd_info->model == ZBD_HOST_MANAGED)
                                return false;
                }
-       }
+       } end_for_each();
 
        return true;
 }
 
 /* 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;
 
@@ -632,27 +638,25 @@ static bool zbd_zone_align_file_sizes(struct thread_data *td,
  */
 static bool zbd_verify_sizes(void)
 {
-       struct thread_data *td;
        struct fio_file *f;
-       int i, j;
+       int j;
 
-       for_each_td(td, i) {
+       for_each_td(td) {
                for_each_file(td, f, j) {
                        if (!zbd_zone_align_file_sizes(td, f))
                                return false;
                }
-       }
+       } end_for_each();
 
        return true;
 }
 
 static bool zbd_verify_bs(void)
 {
-       struct thread_data *td;
        struct fio_file *f;
-       int i, j;
+       int j;
 
-       for_each_td(td, i) {
+       for_each_td(td) {
                if (td_trim(td) &&
                    (td->o.min_bs[DDIR_TRIM] != td->o.max_bs[DDIR_TRIM] ||
                     td->o.bssplit_nr[DDIR_TRIM])) {
@@ -673,7 +677,7 @@ static bool zbd_verify_bs(void)
                                return false;
                        }
                }
-       }
+       } end_for_each();
        return true;
 }
 
@@ -772,7 +776,8 @@ static int parse_zone_info(struct thread_data *td, struct fio_file *f)
        int nr_zones, nrz;
        struct zbd_zone *zones, *z;
        struct fio_zone_info *p;
-       uint64_t zone_size, offset;
+       uint64_t zone_size, offset, capacity;
+       bool same_zone_cap = true;
        struct zoned_block_device_info *zbd_info = NULL;
        int i, j, ret = -ENOMEM;
 
@@ -789,6 +794,7 @@ static int parse_zone_info(struct thread_data *td, struct fio_file *f)
        }
 
        zone_size = zones[0].len;
+       capacity = zones[0].capacity;
        nr_zones = (f->real_file_size + zone_size - 1) / zone_size;
 
        if (td->o.zone_size == 0) {
@@ -817,6 +823,8 @@ static int parse_zone_info(struct thread_data *td, struct fio_file *f)
                                                     PTHREAD_MUTEX_RECURSIVE);
                        p->start = z->start;
                        p->capacity = z->capacity;
+                       if (capacity != z->capacity)
+                               same_zone_cap = false;
 
                        switch (z->cond) {
                        case ZBD_ZONE_COND_NOT_WP:
@@ -841,8 +849,9 @@ static int parse_zone_info(struct thread_data *td, struct fio_file *f)
                        p->cond = z->cond;
 
                        if (j > 0 && p->start != p[-1].start + zone_size) {
-                               log_info("%s: invalid zone data\n",
-                                        f->file_name);
+                               log_info("%s: invalid zone data [%d:%d]: %"PRIu64" + %"PRIu64" != %"PRIu64"\n",
+                                        f->file_name, j, i,
+                                        p[-1].start, zone_size, p->start);
                                ret = -EINVAL;
                                goto out;
                        }
@@ -871,6 +880,11 @@ static int parse_zone_info(struct thread_data *td, struct fio_file *f)
        f->zbd_info->zone_size_log2 = is_power_of_2(zone_size) ?
                ilog2(zone_size) : 0;
        f->zbd_info->nr_zones = nr_zones;
+
+       if (same_zone_cap)
+               dprint(FD_ZBD, "Zone capacity = %"PRIu64" KB\n",
+                      capacity / 1024);
+
        zbd_info = NULL;
        ret = 0;
 
@@ -1002,11 +1016,10 @@ void zbd_free_zone_info(struct fio_file *f)
  */
 static int zbd_init_zone_info(struct thread_data *td, struct fio_file *file)
 {
-       struct thread_data *td2;
        struct fio_file *f2;
-       int i, j, ret;
+       int j, ret;
 
-       for_each_td(td2, i) {
+       for_each_td(td2) {
                for_each_file(td2, f2, j) {
                        if (td2 == td && f2 == file)
                                continue;
@@ -1017,7 +1030,7 @@ static int zbd_init_zone_info(struct thread_data *td, struct fio_file *file)
                        file->zbd_info->refcount++;
                        return 0;
                }
-       }
+       } end_for_each();
 
        ret = zbd_create_zone_info(td, file);
        if (ret < 0)
@@ -1067,6 +1080,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 +1151,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 +1159,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,35 +1255,9 @@ static bool zbd_dec_and_reset_write_cnt(const struct thread_data *td,
        return write_cnt == 0;
 }
 
-static uint64_t zbd_set_swd(struct thread_data *td, const struct fio_file *f)
-{
-       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);
-       f->zbd_info->wp_sectors_with_data = wp_swd;
-       pthread_mutex_unlock(&f->zbd_info->mutex);
-
-       for (z = zb; z < ze; z++)
-               if (z->has_wp)
-                       zone_unlock(z);
-
-       return wp_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))
@@ -1226,10 +1265,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_set_swd(td, f);
-
-       dprint(FD_ZBD, "%s(%s): swd = %" PRIu64 "\n",
-              __func__, f->file_name, swd);
 
        /*
         * If data verification is enabled reset the affected zones before
@@ -1259,13 +1294,10 @@ static uint32_t pick_random_zone_idx(const struct fio_file *f,
 
 static bool any_io_in_flight(void)
 {
-       struct thread_data *td;
-       int i;
-
-       for_each_td(td, i) {
+       for_each_td(td) {
                if (td->io_u_in_flight)
                        return true;
-       }
+       } end_for_each();
 
        return false;
 }
@@ -1605,10 +1637,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:
@@ -1960,7 +1993,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;
                }