engines/xnvme: user space vfio based backend
[fio.git] / engines / libzbc.c
index 7f2bc431b4352f7f3472fd00b63c268b823dbe64..2b63ef1acaa0b4624b80206893f3c6f6c74fb618 100644 (file)
@@ -14,6 +14,7 @@
 #include "fio.h"
 #include "err.h"
 #include "zbd_types.h"
+#include "zbd.h"
 
 struct libzbc_data {
        struct zbc_device       *zdev;
@@ -63,7 +64,7 @@ static int libzbc_open_dev(struct thread_data *td, struct fio_file *f,
                return -EINVAL;
        }
 
-       if (td_write(td)) {
+       if (td_write(td) || td_trim(td)) {
                if (!read_only)
                        flags |= O_RDWR;
        } else if (td_read(td)) {
@@ -71,10 +72,6 @@ static int libzbc_open_dev(struct thread_data *td, struct fio_file *f,
                        flags |= O_RDWR;
                else
                        flags |= O_RDONLY;
-       } else if (td_trim(td)) {
-               td_verror(td, EINVAL, "libzbc does not support trim");
-               log_err("%s: libzbc does not support trim\n", f->file_name);
-               return -EINVAL;
        }
 
        if (td->o.oatomic) {
@@ -88,7 +85,7 @@ static int libzbc_open_dev(struct thread_data *td, struct fio_file *f,
                return -ENOMEM;
 
        ret = zbc_open(f->file_name,
-                      flags | ZBC_O_DRV_BLOCK | ZBC_O_DRV_SCSI | ZBC_O_DRV_ATA,
+                      flags | ZBC_O_DRV_SCSI | ZBC_O_DRV_ATA,
                       &ld->zdev);
        if (ret) {
                log_err("%s: zbc_open() failed, err=%d\n",
@@ -335,6 +332,39 @@ err:
        return -ret;
 }
 
+static int libzbc_finish_zone(struct thread_data *td, struct fio_file *f,
+                             uint64_t offset, uint64_t length)
+{
+       struct libzbc_data *ld = td->io_ops_data;
+       uint64_t sector = offset >> 9;
+       unsigned int nr_zones;
+       struct zbc_errno err;
+       int i, ret;
+
+       assert(ld);
+       assert(ld->zdev);
+
+       nr_zones = (length + td->o.zone_size - 1) / td->o.zone_size;
+       assert(nr_zones > 0);
+
+       for (i = 0; i < nr_zones; i++, sector += td->o.zone_size >> 9) {
+               ret = zbc_finish_zone(ld->zdev, sector, 0);
+               if (ret)
+                       goto err;
+       }
+
+       return 0;
+
+err:
+       zbc_errno(ld->zdev, &err);
+       td_verror(td, errno, "zbc_finish_zone failed");
+       if (err.sk)
+               log_err("%s: finish zone failed %s:%s\n",
+                       f->file_name,
+                       zbc_sk_str(err.sk), zbc_asc_ascq_str(err.asc_ascq));
+       return -ret;
+}
+
 static int libzbc_get_max_open_zones(struct thread_data *td, struct fio_file *f,
                                     unsigned int *max_open_zones)
 {
@@ -411,7 +441,11 @@ static enum fio_q_status libzbc_queue(struct thread_data *td, struct io_u *io_u)
                ret = zbc_flush(ld->zdev);
                if (ret)
                        log_err("zbc_flush error %zd\n", ret);
-       } else if (io_u->ddir != DDIR_TRIM) {
+       } else if (io_u->ddir == DDIR_TRIM) {
+               ret = zbd_do_io_u_trim(td, io_u);
+               if (!ret)
+                       ret = EINVAL;
+       } else {
                log_err("Unsupported operation %u\n", io_u->ddir);
                ret = -EINVAL;
        }
@@ -433,6 +467,7 @@ FIO_STATIC struct ioengine_ops ioengine = {
        .report_zones           = libzbc_report_zones,
        .reset_wp               = libzbc_reset_wp,
        .get_max_open_zones     = libzbc_get_max_open_zones,
+       .finish_zone            = libzbc_finish_zone,
        .queue                  = libzbc_queue,
        .flags                  = FIO_SYNCIO | FIO_NOEXTEND | FIO_RAWIO,
 };