zbd: get max_active_zones limit value from zoned devices
authorShin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
Wed, 19 Jul 2023 10:57:44 +0000 (19:57 +0900)
committerVincent Fu <vincent.fu@samsung.com>
Thu, 20 Jul 2023 13:52:37 +0000 (09:52 -0400)
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>
ioengines.h
oslib/blkzoned.h
oslib/linux-blkzoned.c
zbd.c
zbd.h

index 9484265e6f0fcb817f9766d185c8f865a0c4f87a..4391b31e3ca2a30900aa85d38bc0275f13ee68f5 100644 (file)
@@ -9,7 +9,7 @@
 #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
@@ -62,6 +62,8 @@ struct ioengine_ops {
                        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 *,
index 29fb034f585402b3798609b32a18c0519c9a03f5..e598bd4f8026f74ad6e61771858710589b409e2b 100644 (file)
@@ -18,6 +18,9 @@ extern int blkzoned_reset_wp(struct thread_data *td, struct fio_file *f,
                                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
@@ -53,6 +56,12 @@ static inline int blkzoned_get_max_open_zones(struct thread_data *td, struct fio
 {
        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)
index 722e09925b3d22e6b6ec654ea6104c8143c9b9bd..2c3ecf33b4cc31a2e6555bc64afec09d861c37d4 100644 (file)
@@ -186,6 +186,29 @@ int blkzoned_get_max_open_zones(struct thread_data *td, struct fio_file *f,
        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)
 {
diff --git a/zbd.c b/zbd.c
index d45652157c021f17d043872d2265ad829b6152cd..a5cb34d228eed3b40db189f5f4d8bf862a81c317 100644 (file)
--- a/zbd.c
+++ b/zbd.c
@@ -471,6 +471,34 @@ static int zbd_get_max_open_zones(struct thread_data *td, struct fio_file *f,
        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.
@@ -927,6 +955,7 @@ 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;
+       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",
diff --git a/zbd.h b/zbd.h
index f0ac98763ca71f38b36174a74ce41dfdd7d40dff..a5cf59d1391aac6f267d21deb30afd9694d4b70a 100644 (file)
--- a/zbd.h
+++ b/zbd.h
@@ -52,6 +52,9 @@ struct fio_zone_info {
  *      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.
@@ -75,6 +78,7 @@ struct fio_zone_info {
 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;