rand: cleanup rand_between() and helpers
[fio.git] / engines / sync.c
index 41612dfa8c31ba0f8fc81436d162fee1ece500da..b3e1c9db8ba3eeb9d87567dc53b69de5759be715 100644 (file)
 #include <unistd.h>
 #include <sys/uio.h>
 #include <errno.h>
-#include <assert.h>
 
 #include "../fio.h"
+#include "../optgroup.h"
+#include "../lib/rand.h"
 
 /*
  * Sync engine uses engine_data to store last offset
  */
-#define LAST_POS(f)    ((f)->engine_data)
+#define LAST_POS(f)    ((f)->engine_pos)
 
 struct syncio_data {
        struct iovec *iovecs;
@@ -29,8 +30,45 @@ struct syncio_data {
        unsigned long long last_offset;
        struct fio_file *last_file;
        enum fio_ddir last_ddir;
+
+       struct frand_state rand_state;
+};
+
+#ifdef FIO_HAVE_PWRITEV2
+struct psyncv2_options {
+       void *pad;
+       unsigned int hipri;
+       unsigned int hipri_percentage;
 };
 
+static struct fio_option options[] = {
+       {
+               .name   = "hipri",
+               .lname  = "RWF_HIPRI",
+               .type   = FIO_OPT_STR_SET,
+               .off1   = offsetof(struct psyncv2_options, hipri),
+               .help   = "Set RWF_HIPRI for pwritev2/preadv2",
+               .category = FIO_OPT_C_ENGINE,
+               .group  = FIO_OPT_G_INVALID,
+       },
+       {
+               .name   = "hipri_percentage",
+               .lname  = "RWF_HIPRI_PERCENTAGE",
+               .type   = FIO_OPT_INT,
+               .off1   = offsetof(struct psyncv2_options, hipri_percentage),
+               .minval = 0,
+               .maxval = 100,
+               .def    = "100",
+               .help   = "Probabilistically set RWF_HIPRI for pwritev2/preadv2",
+               .category = FIO_OPT_C_ENGINE,
+               .group  = FIO_OPT_G_INVALID,
+       },
+       {
+               .name   = NULL,
+       },
+};
+#endif
+
 static int fio_syncio_prep(struct thread_data *td, struct io_u *io_u)
 {
        struct fio_file *f = io_u->file;
@@ -63,16 +101,19 @@ static int fio_io_end(struct thread_data *td, struct io_u *io_u, int ret)
                        io_u->error = errno;
        }
 
-       if (io_u->error)
+       if (io_u->error) {
+               io_u_log_error(td, io_u);
                td_verror(td, io_u->error, "xfer");
+       }
 
        return FIO_Q_COMPLETED;
 }
 
 #ifdef CONFIG_PWRITEV
-static int fio_pvsyncio_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status fio_pvsyncio_queue(struct thread_data *td,
+                                           struct io_u *io_u)
 {
-       struct syncio_data *sd = td->io_ops->data;
+       struct syncio_data *sd = td->io_ops_data;
        struct iovec *iov = &sd->iovecs[0];
        struct fio_file *f = io_u->file;
        int ret;
@@ -96,7 +137,41 @@ static int fio_pvsyncio_queue(struct thread_data *td, struct io_u *io_u)
 }
 #endif
 
-static int fio_psyncio_queue(struct thread_data *td, struct io_u *io_u)
+#ifdef FIO_HAVE_PWRITEV2
+static enum fio_q_status fio_pvsyncio2_queue(struct thread_data *td,
+                                            struct io_u *io_u)
+{
+       struct syncio_data *sd = td->io_ops_data;
+       struct psyncv2_options *o = td->eo;
+       struct iovec *iov = &sd->iovecs[0];
+       struct fio_file *f = io_u->file;
+       int ret, flags = 0;
+
+       fio_ro_check(td, io_u);
+
+       if (o->hipri &&
+           (rand_between(&sd->rand_state, 1, 100) <= o->hipri_percentage))
+               flags |= RWF_HIPRI;
+
+       iov->iov_base = io_u->xfer_buf;
+       iov->iov_len = io_u->xfer_buflen;
+
+       if (io_u->ddir == DDIR_READ)
+               ret = preadv2(f->fd, iov, 1, io_u->offset, flags);
+       else if (io_u->ddir == DDIR_WRITE)
+               ret = pwritev2(f->fd, iov, 1, io_u->offset, flags);
+       else if (io_u->ddir == DDIR_TRIM) {
+               do_io_u_trim(td, io_u);
+               return FIO_Q_COMPLETED;
+       } else
+               ret = do_io_u_sync(td, io_u);
+
+       return fio_io_end(td, io_u, ret);
+}
+#endif
+
+static enum fio_q_status fio_psyncio_queue(struct thread_data *td,
+                                          struct io_u *io_u)
 {
        struct fio_file *f = io_u->file;
        int ret;
@@ -116,7 +191,8 @@ static int fio_psyncio_queue(struct thread_data *td, struct io_u *io_u)
        return fio_io_end(td, io_u, ret);
 }
 
-static int fio_syncio_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status fio_syncio_queue(struct thread_data *td,
+                                         struct io_u *io_u)
 {
        struct fio_file *f = io_u->file;
        int ret;
@@ -140,7 +216,7 @@ static int fio_vsyncio_getevents(struct thread_data *td, unsigned int min,
                                 unsigned int max,
                                 const struct timespec fio_unused *t)
 {
-       struct syncio_data *sd = td->io_ops->data;
+       struct syncio_data *sd = td->io_ops_data;
        int ret;
 
        if (min) {
@@ -155,14 +231,14 @@ static int fio_vsyncio_getevents(struct thread_data *td, unsigned int min,
 
 static struct io_u *fio_vsyncio_event(struct thread_data *td, int event)
 {
-       struct syncio_data *sd = td->io_ops->data;
+       struct syncio_data *sd = td->io_ops_data;
 
        return sd->io_us[event];
 }
 
 static int fio_vsyncio_append(struct thread_data *td, struct io_u *io_u)
 {
-       struct syncio_data *sd = td->io_ops->data;
+       struct syncio_data *sd = td->io_ops_data;
 
        if (ddir_sync(io_u->ddir))
                return 0;
@@ -187,9 +263,10 @@ static void fio_vsyncio_set_iov(struct syncio_data *sd, struct io_u *io_u,
        sd->queued++;
 }
 
-static int fio_vsyncio_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status fio_vsyncio_queue(struct thread_data *td,
+                                          struct io_u *io_u)
 {
-       struct syncio_data *sd = td->io_ops->data;
+       struct syncio_data *sd = td->io_ops_data;
 
        fio_ro_check(td, io_u);
 
@@ -229,7 +306,7 @@ static int fio_vsyncio_queue(struct thread_data *td, struct io_u *io_u)
  */
 static int fio_vsyncio_end(struct thread_data *td, ssize_t bytes)
 {
-       struct syncio_data *sd = td->io_ops->data;
+       struct syncio_data *sd = td->io_ops_data;
        struct io_u *io_u;
        unsigned int i;
        int err;
@@ -269,7 +346,7 @@ static int fio_vsyncio_end(struct thread_data *td, ssize_t bytes)
 
 static int fio_vsyncio_commit(struct thread_data *td)
 {
-       struct syncio_data *sd = td->io_ops->data;
+       struct syncio_data *sd = td->io_ops_data;
        struct fio_file *f;
        ssize_t ret;
 
@@ -306,18 +383,21 @@ static int fio_vsyncio_init(struct thread_data *td)
        sd->last_offset = -1ULL;
        sd->iovecs = malloc(td->o.iodepth * sizeof(struct iovec));
        sd->io_us = malloc(td->o.iodepth * sizeof(struct io_u *));
+       init_rand(&sd->rand_state, 0);
 
-       td->io_ops->data = sd;
+       td->io_ops_data = sd;
        return 0;
 }
 
 static void fio_vsyncio_cleanup(struct thread_data *td)
 {
-       struct syncio_data *sd = td->io_ops->data;
+       struct syncio_data *sd = td->io_ops_data;
 
-       free(sd->iovecs);
-       free(sd->io_us);
-       free(sd);
+       if (sd) {
+               free(sd->iovecs);
+               free(sd->io_us);
+               free(sd);
+       }
 }
 
 static struct ioengine_ops ioengine_rw = {
@@ -370,6 +450,22 @@ static struct ioengine_ops ioengine_pvrw = {
 };
 #endif
 
+#ifdef FIO_HAVE_PWRITEV2
+static struct ioengine_ops ioengine_pvrw2 = {
+       .name           = "pvsync2",
+       .version        = FIO_IOOPS_VERSION,
+       .init           = fio_vsyncio_init,
+       .cleanup        = fio_vsyncio_cleanup,
+       .queue          = fio_pvsyncio2_queue,
+       .open_file      = generic_open_file,
+       .close_file     = generic_close_file,
+       .get_file_size  = generic_get_file_size,
+       .flags          = FIO_SYNCIO,
+       .options        = options,
+       .option_struct_size     = sizeof(struct psyncv2_options),
+};
+#endif
+
 static void fio_init fio_syncio_register(void)
 {
        register_ioengine(&ioengine_rw);
@@ -378,6 +474,9 @@ static void fio_init fio_syncio_register(void)
 #ifdef CONFIG_PWRITEV
        register_ioengine(&ioengine_pvrw);
 #endif
+#ifdef FIO_HAVE_PWRITEV2
+       register_ioengine(&ioengine_pvrw2);
+#endif
 }
 
 static void fio_exit fio_syncio_unregister(void)
@@ -388,4 +487,7 @@ static void fio_exit fio_syncio_unregister(void)
 #ifdef CONFIG_PWRITEV
        unregister_ioengine(&ioengine_pvrw);
 #endif
+#ifdef FIO_HAVE_PWRITEV2
+       unregister_ioengine(&ioengine_pvrw2);
+#endif
 }