oslib: blkzoned: add blkzoned_finish_zone() helper function
[fio.git] / oslib / linux-blkzoned.c
index 6f89ec6f414e63c6a9bf6691a10dfc6723a29451..c3130d0e2a1b2d9d98a1914e80cb591969364e4b 100644 (file)
@@ -140,10 +140,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;
 
@@ -171,8 +169,10 @@ int blkzoned_get_max_open_zones(struct thread_data *td, struct fio_file *f,
                return -EIO;
 
        max_open_str = blkzoned_get_sysfs_attr(f->file_name, "queue/max_open_zones");
-       if (!max_open_str)
+       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);
@@ -308,3 +308,40 @@ 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)
+{
+#ifdef BLKFINISHZONE
+       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;
+
+       if (f->fd < 0)
+               close(fd);
+
+       return ret;
+#else
+       /*
+        * Kernel versions older than 5.5 does not support BLKFINISHZONE. These
+        * old kernels assumed zones are closed automatically at max_open_zones
+        * limit. Also they did not support max_active_zones limit. Then there
+        * was no need to finish zones to avoid errors caused by max_open_zones
+        * or max_active_zones. For those old versions, just do nothing.
+        */
+       return 0;
+#endif
+}