summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--HOWTO6
-rw-r--r--blktrace.c27
-rw-r--r--cconv.c4
-rw-r--r--fio.16
-rw-r--r--options.c22
-rw-r--r--thread_options.h6
6 files changed, 70 insertions, 1 deletions
diff --git a/HOWTO b/HOWTO
index bb298264..0808cc3a 100644
--- 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
diff --git a/blktrace.c b/blktrace.c
index 2d4dc1b9..562e126b 100644
--- a/blktrace.c
+++ b/blktrace.c
@@ -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 976059cd..9c7e7185 100644
--- 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 a77c71c3..e54e419b 100644
--- 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
diff --git a/options.c b/options.c
index 3de1248c..40b69ed9 100644
--- a/options.c
+++ b/options.c
@@ -2662,6 +2662,28 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
.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",
.type = FIO_OPT_STR_STORE,
diff --git a/thread_options.h b/thread_options.h
index aa7f3f26..1c48bd83 100644
--- a/thread_options.h
+++ b/thread_options.h
@@ -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);