Merge branch 'td-eo-double-free-fix' of https://github.com/dpronin/fio
[fio.git] / oslib / linux-blkzoned.c
index 84a64ed3014e04bd7eb188df5d491ad45b78a71f..2c3ecf33b4cc31a2e6555bc64afec09d861c37d4 100644 (file)
@@ -22,6 +22,9 @@
 #include "zbd_types.h"
 
 #include <linux/blkzoned.h>
+#ifndef BLKFINISHZONE
+#define BLKFINISHZONE _IOW(0x12, 136, struct blk_zone_range)
+#endif
 
 /*
  * If the uapi headers installed on the system lacks zone capacity support,
@@ -140,10 +143,8 @@ int blkzoned_get_zoned_model(struct thread_data *td, struct fio_file *f,
 {
        char *model_str = NULL;
 
-       if (f->filetype != FIO_TYPE_BLOCK) {
-               *model = ZBD_IGNORE;
-               return 0;
-       }
+       if (f->filetype != FIO_TYPE_BLOCK)
+               return -EINVAL;
 
        *model = ZBD_NONE;
 
@@ -162,6 +163,52 @@ int blkzoned_get_zoned_model(struct thread_data *td, struct fio_file *f,
        return 0;
 }
 
+int blkzoned_get_max_open_zones(struct thread_data *td, struct fio_file *f,
+                               unsigned int *max_open_zones)
+{
+       char *max_open_str;
+
+       if (f->filetype != FIO_TYPE_BLOCK)
+               return -EIO;
+
+       max_open_str = blkzoned_get_sysfs_attr(f->file_name, "queue/max_open_zones");
+       if (!max_open_str) {
+               *max_open_zones = 0;
+               return 0;
+       }
+
+       dprint(FD_ZBD, "%s: max open zones supported by device: %s\n",
+              f->file_name, max_open_str);
+       *max_open_zones = atoll(max_open_str);
+
+       free(max_open_str);
+
+       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)
 {
@@ -287,3 +334,37 @@ int blkzoned_reset_wp(struct thread_data *td, struct fio_file *f,
 
        return ret;
 }
+
+int blkzoned_finish_zone(struct thread_data *td, struct fio_file *f,
+                        uint64_t offset, uint64_t length)
+{
+       struct blk_zone_range zr = {
+               .sector         = offset >> 9,
+               .nr_sectors     = length >> 9,
+       };
+       int fd, ret = 0;
+
+       /* If the file is not yet opened, open it for this function. */
+       fd = f->fd;
+       if (fd < 0) {
+               fd = open(f->file_name, O_RDWR | O_LARGEFILE);
+               if (fd < 0)
+                       return -errno;
+       }
+
+       if (ioctl(fd, BLKFINISHZONE, &zr) < 0) {
+               ret = -errno;
+               /*
+                * Kernel versions older than 5.5 do not support BLKFINISHZONE
+                * and return the ENOTTY error code. These old kernels only
+                * support block devices that close zones automatically.
+                */
+               if (ret == ENOTTY)
+                       ret = 0;
+       }
+
+       if (f->fd < 0)
+               close(fd);
+
+       return ret;
+}