+/*
+ * Reset zbd_info.write_cnt, the counter that counts down towards the next
+ * zone reset.
+ */
+static void zbd_reset_write_cnt(const struct thread_data *td,
+ const struct fio_file *f)
+{
+ assert(0 <= td->o.zrf.u.f && td->o.zrf.u.f <= 1);
+
+ pthread_mutex_lock(&f->zbd_info->mutex);
+ f->zbd_info->write_cnt = td->o.zrf.u.f ?
+ min(1.0 / td->o.zrf.u.f, 0.0 + UINT_MAX) : UINT_MAX;
+ pthread_mutex_unlock(&f->zbd_info->mutex);
+}
+
+static bool zbd_dec_and_reset_write_cnt(const struct thread_data *td,
+ const struct fio_file *f)
+{
+ uint32_t write_cnt = 0;
+
+ pthread_mutex_lock(&f->zbd_info->mutex);
+ assert(f->zbd_info->write_cnt);
+ if (f->zbd_info->write_cnt)
+ write_cnt = --f->zbd_info->write_cnt;
+ if (write_cnt == 0)
+ zbd_reset_write_cnt(td, f);
+ pthread_mutex_unlock(&f->zbd_info->mutex);
+
+ 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(const struct fio_file *f, enum swd_action a)
+{
+ struct fio_zone_info *zb, *ze, *z;
+ uint64_t swd = 0;
+
+ zb = &f->zbd_info->zone_info[zbd_zone_idx(f, f->file_offset)];
+ ze = &f->zbd_info->zone_info[zbd_zone_idx(f, f->file_offset +
+ f->io_size)];
+ for (z = zb; z < ze; z++) {
+ pthread_mutex_lock(&z->mutex);
+ swd += z->wp - z->start;
+ }
+ pthread_mutex_lock(&f->zbd_info->mutex);
+ switch (a) {
+ case CHECK_SWD:
+ assert(f->zbd_info->sectors_with_data == swd);
+ break;
+ case SET_SWD:
+ f->zbd_info->sectors_with_data = swd;
+ break;
+ }
+ pthread_mutex_unlock(&f->zbd_info->mutex);
+ for (z = zb; z < ze; z++)
+ pthread_mutex_unlock(&z->mutex);
+
+ return 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 value of zbd_info.sectors_with_data is correct. */
+static void zbd_check_swd(const struct fio_file *f)
+{
+ if (!enable_check_swd)
+ return;
+
+ zbd_process_swd(f, CHECK_SWD);
+}
+
+static void zbd_init_swd(struct fio_file *f)
+{
+ uint64_t swd;
+
+ swd = zbd_process_swd(f, SET_SWD);
+ dprint(FD_ZBD, "%s(%s): swd = %" PRIu64 "\n", __func__, f->file_name,
+ swd);
+}
+