blktrace: add 'reply_skip' option
authorJens Axboe <axboe@kernel.dk>
Thu, 26 Apr 2018 21:27:05 +0000 (15:27 -0600)
committerJens Axboe <axboe@kernel.dk>
Thu, 26 Apr 2018 21:27:05 +0000 (15:27 -0600)
Allows the user to skip certain IO types. Useful for replaying
workloads with trim on a device that doesn't support it, for
instance. Or just replaying parts of a workload (eg just writes,
or just reads).

Signed-off-by: Jens Axboe <axboe@kernel.dk>
blktrace.c
cconv.c
options.c
server.h
thread_options.h

index e256d633d929cd5f7b60936bdb39bb84cddc9b48..3c66c5afb971723518f95608f81bcb3083a70dcc 100644 (file)
@@ -273,6 +273,9 @@ static void handle_trace_discard(struct thread_data *td,
        unsigned int bs;
        int fileno;
 
        unsigned int bs;
        int fileno;
 
+       if (td->o.replay_skip & (1u << DDIR_TRIM))
+               return;
+
        ipo = calloc(1, sizeof(*ipo));
        init_ipo(ipo);
        fileno = trace_add_file(td, t->device, &bs);
        ipo = calloc(1, sizeof(*ipo));
        init_ipo(ipo);
        fileno = trace_add_file(td, t->device, &bs);
@@ -312,6 +315,14 @@ static void handle_trace_fs(struct thread_data *td, struct blk_io_trace *t,
 
        rw = (t->action & BLK_TC_ACT(BLK_TC_WRITE)) != 0;
 
 
        rw = (t->action & BLK_TC_ACT(BLK_TC_WRITE)) != 0;
 
+       if (rw) {
+               if (td->o.replay_skip & (1u << DDIR_WRITE))
+                       return;
+       } else {
+               if (td->o.replay_skip & (1u << DDIR_READ))
+                       return;
+       }
+
        assert(t->bytes);
 
        if (t->bytes > rw_bs[rw])
        assert(t->bytes);
 
        if (t->bytes > rw_bs[rw])
@@ -329,6 +340,9 @@ static void handle_trace_flush(struct thread_data *td, struct blk_io_trace *t,
        unsigned int bs;
        int fileno;
 
        unsigned int bs;
        int fileno;
 
+       if (td->o.replay_skip & (1u << DDIR_SYNC))
+               return;
+
        ipo = calloc(1, sizeof(*ipo));
        init_ipo(ipo);
        fileno = trace_add_file(td, t->device, &bs);
        ipo = calloc(1, sizeof(*ipo));
        init_ipo(ipo);
        fileno = trace_add_file(td, t->device, &bs);
diff --git a/cconv.c b/cconv.c
index 9e163b35fd68627e147f434adc0288e8cec926fd..bfd699dab7bff26087a29bc993210a84478e619a 100644 (file)
--- a/cconv.c
+++ b/cconv.c
@@ -290,6 +290,7 @@ void convert_thread_options_to_cpu(struct thread_options *o,
        o->replay_align = le32_to_cpu(top->replay_align);
        o->replay_scale = le32_to_cpu(top->replay_scale);
        o->replay_time_scale = le32_to_cpu(top->replay_time_scale);
        o->replay_align = le32_to_cpu(top->replay_align);
        o->replay_scale = le32_to_cpu(top->replay_scale);
        o->replay_time_scale = le32_to_cpu(top->replay_time_scale);
+       o->replay_skip = le32_to_cpu(top->replay_skip);
        o->per_job_logs = le32_to_cpu(top->per_job_logs);
        o->write_bw_log = le32_to_cpu(top->write_bw_log);
        o->write_lat_log = le32_to_cpu(top->write_lat_log);
        o->per_job_logs = le32_to_cpu(top->per_job_logs);
        o->write_bw_log = le32_to_cpu(top->write_bw_log);
        o->write_lat_log = le32_to_cpu(top->write_lat_log);
@@ -479,6 +480,7 @@ void convert_thread_options_to_net(struct thread_options_pack *top,
        top->replay_align = cpu_to_le32(o->replay_align);
        top->replay_scale = cpu_to_le32(o->replay_scale);
        top->replay_time_scale = cpu_to_le32(o->replay_time_scale);
        top->replay_align = cpu_to_le32(o->replay_align);
        top->replay_scale = cpu_to_le32(o->replay_scale);
        top->replay_time_scale = cpu_to_le32(o->replay_time_scale);
+       top->replay_skip = cpu_to_le32(o->replay_skip);
        top->per_job_logs = cpu_to_le32(o->per_job_logs);
        top->write_bw_log = cpu_to_le32(o->write_bw_log);
        top->write_lat_log = cpu_to_le32(o->write_lat_log);
        top->per_job_logs = cpu_to_le32(o->per_job_logs);
        top->write_bw_log = cpu_to_le32(o->write_bw_log);
        top->write_lat_log = cpu_to_le32(o->write_lat_log);
index 0b3a895d14d83ab00d5c495b9393e307bba1c4c2..047e493daec44dcaa787043959fcb86d81130b08 100644 (file)
--- a/options.c
+++ b/options.c
@@ -342,6 +342,43 @@ static int ignore_error_type(struct thread_data *td, enum error_type_bit etype,
 
 }
 
 
 }
 
+static int str_replay_skip_cb(void *data, const char *input)
+{
+       struct thread_data *td = cb_data_to_td(data);
+       char *str, *p, *n;
+       int ret = 0;
+
+       if (parse_dryrun())
+               return 0;
+
+       p = str = strdup(input);
+
+       strip_blank_front(&str);
+       strip_blank_end(str);
+
+       while (p) {
+               n = strchr(p, ',');
+               if (n)
+                       *n++ = '\0';
+               if (!strcmp(p, "read"))
+                       td->o.replay_skip |= 1u << DDIR_READ;
+               else if (!strcmp(p, "write"))
+                       td->o.replay_skip |= 1u << DDIR_WRITE;
+               else if (!strcmp(p, "trim"))
+                       td->o.replay_skip |= 1u << DDIR_TRIM;
+               else if (!strcmp(p, "sync"))
+                       td->o.replay_skip |= 1u << DDIR_SYNC;
+               else {
+                       log_err("Unknown skip type: %s\n", p);
+                       ret = 1;
+                       break;
+               }
+               p = n;
+       }
+       free(str);
+       return ret;
+}
+
 static int str_ignore_error_cb(void *data, const char *input)
 {
        struct thread_data *td = cb_data_to_td(data);
 static int str_ignore_error_cb(void *data, const char *input)
 {
        struct thread_data *td = cb_data_to_td(data);
@@ -3158,6 +3195,17 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .category = FIO_OPT_C_IO,
                .group  = FIO_OPT_G_IOLOG,
        },
                .category = FIO_OPT_C_IO,
                .group  = FIO_OPT_G_IOLOG,
        },
+       {
+               .name   = "replay_skip",
+               .lname  = "Replay Skip",
+               .type   = FIO_OPT_STR,
+               .cb     = str_replay_skip_cb,
+               .off1   = offsetof(struct thread_options, replay_skip),
+               .parent = "read_iolog",
+               .help   = "Skip certain IO types (read,write,trim,flush)",
+               .category = FIO_OPT_C_IO,
+               .group  = FIO_OPT_G_IOLOG,
+       },
        {
                .name   = "exec_prerun",
                .lname  = "Pre-execute runnable",
        {
                .name   = "exec_prerun",
                .lname  = "Pre-execute runnable",
index 48968603d732b8fb676ff46b70040a26803a4b2c..b48bbe16ba4254705b29ddb7b7a4202026ef5b12 100644 (file)
--- a/server.h
+++ b/server.h
@@ -48,7 +48,7 @@ struct fio_net_cmd_reply {
 };
 
 enum {
 };
 
 enum {
-       FIO_SERVER_VER                  = 72,
+       FIO_SERVER_VER                  = 73,
 
        FIO_SERVER_MAX_FRAGMENT_PDU     = 1024,
        FIO_SERVER_MAX_CMD_MB           = 2048,
 
        FIO_SERVER_MAX_FRAGMENT_PDU     = 1024,
        FIO_SERVER_MAX_CMD_MB           = 2048,
index 4ec570dc12c65a45dac90e531eec00cde222c013..52026e365ee9e10a9df2e318906a9a8ab47f9572 100644 (file)
@@ -316,6 +316,7 @@ struct thread_options {
        unsigned int replay_align;
        unsigned int replay_scale;
        unsigned int replay_time_scale;
        unsigned int replay_align;
        unsigned int replay_scale;
        unsigned int replay_time_scale;
+       unsigned int replay_skip;
 
        unsigned int per_job_logs;
 
 
        unsigned int per_job_logs;
 
@@ -590,6 +591,7 @@ struct thread_options_pack {
        uint32_t replay_align;
        uint32_t replay_scale;
        uint32_t replay_time_scale;
        uint32_t replay_align;
        uint32_t replay_scale;
        uint32_t replay_time_scale;
+       uint32_t replay_skip;
 
        uint32_t per_job_logs;
 
 
        uint32_t per_job_logs;