#include <sys/stat.h>
#include <unistd.h>
+#include "compiler/compiler.h"
#include "os/os.h"
#include "file.h"
#include "fio.h"
static void zone_lock(struct thread_data *td, const struct fio_file *f,
struct fio_zone_info *z)
{
+#ifndef NDEBUG
struct zoned_block_device_info *zbd = f->zbd_info;
- uint32_t nz = z - zbd->zone_info;
-
+ uint32_t const nz = z - zbd->zone_info;
/* A thread should never lock zones outside its working area. */
assert(f->min_zone <= nz && nz < f->max_zone);
-
assert(z->has_wp);
+#endif
/*
* Lock the io_u target zone. The zone will be unlocked if io_u offset
static inline void zone_unlock(struct fio_zone_info *z)
{
- int ret;
-
assert(z->has_wp);
- ret = pthread_mutex_unlock(&z->mutex);
- assert(!ret);
+ pthread_mutex_unlock(&z->mutex);
}
static inline struct fio_zone_info *zbd_get_zone(const struct fio_file *f,
const uint64_t min_bs = td->o.min_bs[DDIR_WRITE];
int res = 0;
- assert(min_bs);
+ if (fio_unlikely(0 == min_bs))
+ return 1;
dprint(FD_ZBD, "%s: examining zones %u .. %u\n",
f->file_name, zbd_zone_idx(f, zb), zbd_zone_idx(f, ze));
return ret;
}
+/**
+ * zbd_get_max_active_zones - Get the maximum number of active zones
+ * @td: FIO thread data
+ * @f: FIO file for which to get max active zones
+ *
+ * Returns max_active_zones limit value of the target file if it is available.
+ * Otherwise return zero, which means no limit.
+ */
+static unsigned int zbd_get_max_active_zones(struct thread_data *td,
+ struct fio_file *f)
+{
+ unsigned int max_active_zones;
+ int ret;
+
+ if (td->io_ops && td->io_ops->get_max_active_zones)
+ ret = td->io_ops->get_max_active_zones(td, f,
+ &max_active_zones);
+ else
+ ret = blkzoned_get_max_active_zones(td, f, &max_active_zones);
+ if (ret < 0) {
+ dprint(FD_ZBD, "%s: max_active_zones is not available\n",
+ f->file_name);
+ return 0;
+ }
+
+ return max_active_zones;
+}
+
/**
* __zbd_write_zone_get - Add a zone to the array of write zones.
* @td: fio thread data.
f->zbd_info->zone_size_log2 = is_power_of_2(zone_size) ?
ilog2(zone_size) : 0;
f->zbd_info->nr_zones = nr_zones;
+ f->zbd_info->max_active_zones = zbd_get_max_active_zones(td, f);
if (same_zone_cap)
dprint(FD_ZBD, "Zone capacity = %"PRIu64" KB\n",
for (zi = f->min_zone; zi < f->max_zone; zi++) {
z = &zbd->zone_info[zi];
if (z->cond != ZBD_ZONE_COND_IMP_OPEN &&
- z->cond != ZBD_ZONE_COND_EXP_OPEN)
+ z->cond != ZBD_ZONE_COND_EXP_OPEN &&
+ z->cond != ZBD_ZONE_COND_CLOSED)
+ continue;
+ if (!zbd->max_active_zones &&
+ z->cond == ZBD_ZONE_COND_CLOSED)
continue;
if (__zbd_write_zone_get(td, f, z))
continue;
static void zbd_put_io(struct thread_data *td, const struct io_u *io_u)
{
const struct fio_file *f = io_u->file;
- struct zoned_block_device_info *zbd_info = f->zbd_info;
struct fio_zone_info *z;
- assert(zbd_info);
+ assert(f->zbd_info);
z = zbd_offset_to_zone(f, io_u->offset);
assert(z->has_wp);
case DDIR_WAIT:
case DDIR_LAST:
case DDIR_INVAL:
+ case DDIR_TIMEOUT:
goto accept;
}
return io_u_completed;
}
+
+void zbd_log_err(const struct thread_data *td, const struct io_u *io_u)
+{
+ const struct fio_file *f = io_u->file;
+
+ if (td->o.zone_mode != ZONE_MODE_ZBD)
+ return;
+
+ if (io_u->error == EOVERFLOW)
+ log_err("%s: Exceeded max_active_zones limit. Check conditions of zones out of I/O ranges.\n",
+ f->file_name);
+}