As a preparation to improve open zones accounting for devices with the
max_active_zones limit, get the limit from the devices. In same manner
as max_open_zones, call get_max_active_zones callback if the I/O engine
supports it. Add the new call back to the I/O engine API and bump up
FIO_IOOPS_VERSION. It is expected that io_uring and xnvme engines to
support the callback later. When the callback is not available, refer
max_active_zones sysfs attribute for block devices. When the limit value
is not available, use zero value which means no limit. Keep the obtained
limit value in the struct zoned_block_device_info.
Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
Reviewed-by: Niklas Cassel <niklas.cassel@wdc.com>
Link: https://lore.kernel.org/r/20230719105756.553146-2-shinichiro.kawasaki@wdc.com
Signed-off-by: Vincent Fu <vincent.fu@samsung.com>
#include "zbd_types.h"
#include "fdp.h"
-#define FIO_IOOPS_VERSION 32
+#define FIO_IOOPS_VERSION 33
#ifndef CONFIG_DYNAMIC_ENGINES
#define FIO_STATIC static
uint64_t, uint64_t);
int (*get_max_open_zones)(struct thread_data *, struct fio_file *,
unsigned int *);
+ int (*get_max_active_zones)(struct thread_data *, struct fio_file *,
+ unsigned int *);
int (*finish_zone)(struct thread_data *, struct fio_file *,
uint64_t, uint64_t);
int (*fdp_fetch_ruhs)(struct thread_data *, struct fio_file *,
uint64_t offset, uint64_t length);
extern int blkzoned_get_max_open_zones(struct thread_data *td, struct fio_file *f,
unsigned int *max_open_zones);
+extern int blkzoned_get_max_active_zones(struct thread_data *td,
+ struct fio_file *f,
+ unsigned int *max_active_zones);
extern int blkzoned_finish_zone(struct thread_data *td, struct fio_file *f,
uint64_t offset, uint64_t length);
#else
{
return -EIO;
}
+static inline int blkzoned_get_max_active_zones(struct thread_data *td,
+ struct fio_file *f,
+ unsigned int *max_open_zones)
+{
+ return -EIO;
+}
static inline int blkzoned_finish_zone(struct thread_data *td,
struct fio_file *f,
uint64_t offset, uint64_t length)
return 0;
}
+int blkzoned_get_max_active_zones(struct thread_data *td, struct fio_file *f,
+ unsigned int *max_active_zones)
+{
+ char *max_active_str;
+
+ if (f->filetype != FIO_TYPE_BLOCK)
+ return -EIO;
+
+ max_active_str = blkzoned_get_sysfs_attr(f->file_name, "queue/max_active_zones");
+ if (!max_active_str) {
+ *max_active_zones = 0;
+ return 0;
+ }
+
+ dprint(FD_ZBD, "%s: max active zones supported by device: %s\n",
+ f->file_name, max_active_str);
+ *max_active_zones = atoll(max_active_str);
+
+ free(max_active_str);
+
+ return 0;
+}
+
static uint64_t zone_capacity(struct blk_zone_report *hdr,
struct blk_zone *blkz)
{
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",
* are simultaneously written. A zero value means unlimited zones of
* simultaneous writes and that write target zones will not be tracked in
* the write_zones array.
+ * @max_active_zones: device side limit on the number of sequential write zones
+ * in open or closed conditions. A zero value means unlimited number of
+ * zones in the conditions.
* @mutex: Protects the modifiable members in this structure (refcount and
* num_open_zones).
* @zone_size: size of a single zone in bytes.
struct zoned_block_device_info {
enum zbd_zoned_model model;
uint32_t max_write_zones;
+ uint32_t max_active_zones;
pthread_mutex_t mutex;
uint64_t zone_size;
uint64_t wp_valid_data_bytes;