blktrace: add support for scaling and aligning replays
authorJens Axboe <axboe@fb.com>
Wed, 6 May 2015 20:19:20 +0000 (14:19 -0600)
committerJens Axboe <axboe@fb.com>
Wed, 6 May 2015 20:19:20 +0000 (14:19 -0600)
Signed-off-by: Jens Axboe <axboe@fb.com>
HOWTO
blktrace.c
cconv.c
fio.1
options.c
thread_options.h

diff --git a/HOWTO b/HOWTO
index bb29826428574a77f0352e279155c4b6adb2cea0..0808cc3a07e0f53a62c3476b6789f47426917829 100644 (file)
--- a/HOWTO
+++ b/HOWTO
@@ -1433,6 +1433,12 @@ replay_redirect=str While replaying I/O patterns using read_iolog the
                independent fio invocations.  Unfortuantely this also breaks
                the strict time ordering between multiple device accesses.
 
+replay_align=int       Force alignment of IO offsets and lengths in a trace
+               to this power of 2 value.
+
+replay_scale=int       Scale sector offsets down by this factor when
+               replaying traces.
+
 write_bw_log=str If given, write a bandwidth log of the jobs in this job
                file. Can be used to store data of the bandwidth of the
                jobs in their lifetime. The included fio_generate_plots
index 2d4dc1b9fbca3724e47c7285e7fcdab277b82bc3..562e126b428389af6db707b5fffde18cc922efb9 100644 (file)
@@ -208,6 +208,23 @@ out:
        return last_fileno;
 }
 
+static void t_bytes_align(struct thread_options *o, struct blk_io_trace *t)
+{
+       if (!o->replay_align)
+               return;
+
+       t->bytes = (t->bytes + o->replay_align - 1) & ~(o->replay_align - 1);
+}
+
+static void ipo_bytes_align(struct thread_options *o, struct io_piece *ipo)
+{
+       if (!o->replay_align)
+               return;
+
+       ipo->offset &= ~(o->replay_align - 1);
+}
+
+
 /*
  * Store blk_io_trace data in an ipo for later retrieval.
  */
@@ -220,6 +237,9 @@ static void store_ipo(struct thread_data *td, unsigned long long offset,
        init_ipo(ipo);
 
        ipo->offset = offset * bs;
+       if (td->o.replay_scale)
+               ipo->offset = ipo->offset / td->o.replay_scale;
+       ipo_bytes_align(&td->o, ipo);
        ipo->len = bytes;
        ipo->delay = ttime / 1000;
        if (rw)
@@ -275,6 +295,9 @@ static void handle_trace_discard(struct thread_data *td,
        INIT_FLIST_HEAD(&ipo->list);
 
        ipo->offset = t->sector * bs;
+       if (td->o.replay_scale)
+               ipo->offset = ipo->offset / td->o.replay_scale;
+       ipo_bytes_align(&td->o, ipo);
        ipo->len = t->bytes;
        ipo->delay = ttime / 1000;
        ipo->ddir = DDIR_TRIM;
@@ -314,7 +337,7 @@ static void handle_trace(struct thread_data *td, struct blk_io_trace *t,
                         unsigned long *ios, unsigned int *bs)
 {
        static unsigned long long last_ttime;
-       unsigned long long delay;
+       unsigned long long delay = 0;
 
        if ((t->action & 0xffff) != __BLK_TA_QUEUE)
                return;
@@ -329,6 +352,8 @@ static void handle_trace(struct thread_data *td, struct blk_io_trace *t,
                }
        }
 
+       t_bytes_align(&td->o, t);
+
        if (t->action & BLK_TC_ACT(BLK_TC_NOTIFY))
                handle_trace_notify(t);
        else if (t->action & BLK_TC_ACT(BLK_TC_DISCARD))
diff --git a/cconv.c b/cconv.c
index 976059cde61ab1c298f6ca41949b054c686c2d5f..9c7e718593046068244fcc1917cc016b99a92ddc 100644 (file)
--- a/cconv.c
+++ b/cconv.c
@@ -244,6 +244,8 @@ void convert_thread_options_to_cpu(struct thread_options *o,
        o->compress_percentage = le32_to_cpu(top->compress_percentage);
        o->compress_chunk = le32_to_cpu(top->compress_chunk);
        o->dedupe_percentage = le32_to_cpu(top->dedupe_percentage);
+       o->replay_align = le32_to_cpu(top->replay_align);
+       o->replay_scale = le32_to_cpu(top->replay_scale);
 
        o->trim_backlog = le64_to_cpu(top->trim_backlog);
 
@@ -407,6 +409,8 @@ void convert_thread_options_to_net(struct thread_options_pack *top,
        top->compress_percentage = cpu_to_le32(o->compress_percentage);
        top->compress_chunk = cpu_to_le32(o->compress_chunk);
        top->dedupe_percentage = cpu_to_le32(o->dedupe_percentage);
+       top->replay_align = cpu_to_le32(o->replay_align);
+       top->replay_scale = cpu_to_le32(o->replay_scale);
 
        for (i = 0; i < DDIR_RWDIR_CNT; i++) {
                top->bs[i] = cpu_to_le32(o->bs[i]);
diff --git a/fio.1 b/fio.1
index a77c71c3f3adaf9a306e0ac12ac2ce46ffcba058..e54e419b2f5852733c7312a44defcf0345be7591 100644 (file)
--- a/fio.1
+++ b/fio.1
@@ -1265,6 +1265,12 @@ is to replay the IOPS onto the major/minor device that each IOP was recorded
 from.  Setting \fBreplay_redirect\fR causes all IOPS to be replayed onto the
 single specified device regardless of the device it was recorded from.
 .TP
+.BI replay_align \fR=\fPint
+Force alignment of IO offsets and lengths in a trace to this power of 2 value.
+.TP
+.BI replay_scale \fR=\fPint
+Scale sector offsets down by this factor when replaying traces.
+.TP
 .BI write_bw_log \fR=\fPstr
 If given, write a bandwidth log of the jobs in this job file. Can be used to
 store data of the bandwidth of the jobs in their lifetime. The included
index 3de1248cce9ef44da252ec41b4578a09b6e39da8..40b69ed9877af50e979eb24683a61d5a7710b118 100644 (file)
--- a/options.c
+++ b/options.c
@@ -2661,6 +2661,28 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .category = FIO_OPT_C_IO,
                .group  = FIO_OPT_G_IOLOG,
        },
+       {
+               .name   = "replay_scale",
+               .lname  = "Replace offset scale factor",
+               .type   = FIO_OPT_INT,
+               .off1   = td_var_offset(replay_scale),
+               .parent = "read_iolog",
+               .def    = "1",
+               .help   = "Align offsets to this blocksize",
+               .category = FIO_OPT_C_IO,
+               .group  = FIO_OPT_G_IOLOG,
+       },
+       {
+               .name   = "replay_align",
+               .lname  = "Replace alignment",
+               .type   = FIO_OPT_INT,
+               .off1   = td_var_offset(replay_align),
+               .parent = "read_iolog",
+               .help   = "Scale offset down by this factor",
+               .category = FIO_OPT_C_IO,
+               .group  = FIO_OPT_G_IOLOG,
+               .pow2   = 1,
+       },
        {
                .name   = "exec_prerun",
                .lname  = "Pre-execute runnable",
index aa7f3f2657c8c985e94ec1449e01a34b5fed1ce5..1c48bd83d394577b463ecb9ec5b4572b05123747 100644 (file)
@@ -265,6 +265,9 @@ struct thread_options {
 
        unsigned block_error_hist;
        unsigned int skip_bad;
+
+       unsigned int replay_align;
+       unsigned int replay_scale;
 };
 
 #define FIO_TOP_STR_MAX                256
@@ -495,6 +498,9 @@ struct thread_options_pack {
 
        uint32_t block_error_hist;
        uint32_t skip_bad;
+
+       uint32_t replay_align;
+       uint32_t replay_scale;
 } __attribute__((packed));
 
 extern void convert_thread_options_to_cpu(struct thread_options *o, struct thread_options_pack *top);