Initial support for explicit write barriers
authorJens Axboe <jaxboe@fusionio.com>
Fri, 8 Oct 2010 13:07:01 +0000 (15:07 +0200)
committerJens Axboe <jaxboe@fusionio.com>
Fri, 8 Oct 2010 13:07:01 +0000 (15:07 +0200)
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
engines/binject.c
fio.h
io_u.c
ioengine.h
options.c

index 65894c2ef7847462c36baeeb2baf7593672e4067..44a3796c6782f30e69a3dae9b081fdebccadc7a9 100644 (file)
@@ -191,7 +191,10 @@ static int fio_binject_prep(struct thread_data *td, struct io_u *io_u)
                buc->type = B_TYPE_READ;
        } else if (io_u->ddir == DDIR_WRITE) {
                binject_buc_init(bd, io_u);
-               buc->type = B_TYPE_WRITE;
+               if (io_u->flags & IO_U_F_BARRIER)
+                       buc->type = B_TYPE_WRITEBARRIER;
+               else
+                       buc->type = B_TYPE_WRITE;
        } else if (io_u->ddir == DDIR_TRIM) {
                binject_buc_init(bd, io_u);
                buc->type = B_TYPE_DISCARD;
@@ -407,7 +410,7 @@ static struct ioengine_ops ioengine = {
        .open_file      = fio_binject_open_file,
        .close_file     = fio_binject_close_file,
        .get_file_size  = generic_get_file_size,
-       .flags          = FIO_RAWIO,
+       .flags          = FIO_RAWIO | FIO_BARRIER,
 };
 
 #else /* FIO_HAVE_BINJECT */
diff --git a/fio.h b/fio.h
index c2a0d4d25efb20fc219cdc391a4b0e7ddf3d0453..4ed8cb1b0480c2e717848564fd2167a82dd29809 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -217,6 +217,7 @@ struct thread_options {
        unsigned int thinktime_blocks;
        unsigned int fsync_blocks;
        unsigned int fdatasync_blocks;
+       unsigned int barrier_blocks;
        unsigned long start_delay;
        unsigned long long timeout;
        unsigned long long ramp_time;
diff --git a/io_u.c b/io_u.c
index baa961b103cd954a8536a5e1f1a28777526b95ef..6d539a01fbdaec105144c2b93252683a4630af46 100644 (file)
--- a/io_u.c
+++ b/io_u.c
@@ -501,6 +501,17 @@ static enum fio_ddir get_rw_ddir(struct thread_data *td)
        return td->rwmix_ddir;
 }
 
+static void set_rw_ddir(struct thread_data *td, struct io_u *io_u)
+{
+       io_u->ddir = get_rw_ddir(td);
+
+       if (io_u->ddir == DDIR_WRITE && (td->io_ops->flags & FIO_BARRIER) &&
+           td->o.barrier_blocks &&
+          !(td->io_issues[DDIR_WRITE] % td->o.barrier_blocks) &&
+            td->io_issues[DDIR_WRITE])
+               io_u->flags |= IO_U_F_BARRIER;
+}
+
 void put_file_log(struct thread_data *td, struct fio_file *f)
 {
        int ret = put_file(td, f);
@@ -560,7 +571,7 @@ static int fill_io_u(struct thread_data *td, struct io_u *io_u)
        if (td->io_ops->flags & FIO_NOIO)
                goto out;
 
-       io_u->ddir = get_rw_ddir(td);
+       set_rw_ddir(td, io_u);
 
        /*
         * fsync() or fdatasync() or trim etc, we are done
@@ -963,7 +974,7 @@ again:
        if (io_u) {
                assert(io_u->flags & IO_U_F_FREE);
                io_u->flags &= ~(IO_U_F_FREE | IO_U_F_FREE_DEF);
-               io_u->flags &= ~IO_U_F_TRIMMED;
+               io_u->flags &= ~(IO_U_F_TRIMMED | IO_U_F_BARRIER);
 
                io_u->error = 0;
                flist_del(&io_u->list);
index 344cdbf939a3e55fed9c7274133355e058f2a0d8..7a3c08fd7891c48d600c333342d5ad6c5ec65892 100644 (file)
@@ -10,6 +10,7 @@ enum {
        IO_U_F_IN_CUR_DEPTH     = 1 << 3,
        IO_U_F_BUSY_OK          = 1 << 4,
        IO_U_F_TRIMMED          = 1 << 5,
+       IO_U_F_BARRIER          = 1 << 6,
 };
 
 /*
@@ -126,6 +127,7 @@ enum fio_ioengine_flags {
        FIO_NOIO        = 1 << 6,       /* thread does only pseudo IO */
        FIO_SIGQUIT     = 1 << 7,       /* needs SIGQUIT to exit */
        FIO_PIPEIO      = 1 << 8,       /* input/output no seekable */
+       FIO_BARRIER     = 1 << 9,       /* engine supports barriers */
 };
 
 /*
index bdf358204197b7ad1ed40bf6c2a749c2403c229c..d111018820603fe0e3a578524872343929411ce8 100644 (file)
--- a/options.c
+++ b/options.c
@@ -1185,6 +1185,13 @@ static struct fio_option options[FIO_MAX_OPTS] = {
                .help   = "Issue fdatasync for writes every given number of blocks",
                .def    = "0",
        },
+       {
+               .name   = "write_barrier",
+               .type   = FIO_OPT_INT,
+               .off1   = td_var_offset(barrier_blocks),
+               .help   = "Make every Nth write a barrier write",
+               .def    = "0",
+       },
 #ifdef FIO_HAVE_SYNC_FILE_RANGE
        {
                .name   = "sync_file_range",