blktrace: handle flush/sync replay
[fio.git] / blktrace.c
index 65b600f5cfed020c2008e3c77511829fcd4cf02b..b37a54e9e1cd36ec75dffb7e9a03bfbec8e3f886 100644 (file)
@@ -3,10 +3,8 @@
  */
 #include <stdio.h>
 #include <stdlib.h>
-#include <sys/stat.h>
 #include <sys/ioctl.h>
 #include <linux/fs.h>
-#include <dirent.h>
 
 #include "flist.h"
 #include "fio.h"
@@ -224,8 +222,9 @@ static void store_ipo(struct thread_data *td, unsigned long long offset,
                      unsigned int bytes, int rw, unsigned long long ttime,
                      int fileno, unsigned int bs)
 {
-       struct io_piece *ipo = malloc(sizeof(*ipo));
+       struct io_piece *ipo;
 
+       ipo = calloc(1, sizeof(*ipo));
        init_ipo(ipo);
 
        ipo->offset = offset * bs;
@@ -270,10 +269,11 @@ static void handle_trace_discard(struct thread_data *td,
                                 unsigned long long ttime,
                                 unsigned long *ios, unsigned int *rw_bs)
 {
-       struct io_piece *ipo = malloc(sizeof(*ipo));
+       struct io_piece *ipo;
        unsigned int bs;
        int fileno;
 
+       ipo = calloc(1, sizeof(*ipo));
        init_ipo(ipo);
        fileno = trace_add_file(td, t->device, &bs);
 
@@ -283,7 +283,6 @@ static void handle_trace_discard(struct thread_data *td,
 
        td->o.size += t->bytes;
 
-       memset(ipo, 0, sizeof(*ipo));
        INIT_FLIST_HEAD(&ipo->list);
 
        ipo->offset = t->sector * bs;
@@ -313,7 +312,13 @@ static void handle_trace_fs(struct thread_data *td, struct blk_io_trace *t,
 
        rw = (t->action & BLK_TC_ACT(BLK_TC_WRITE)) != 0;
 
-       if (t->bytes > rw_bs[rw])
+       /*
+        * Need to figure out why 0 byte writes end up here sometimes, for
+        * now just ignore them.
+        */
+       if (!t->bytes)
+               return;
+       else if (t->bytes > rw_bs[rw])
                rw_bs[rw] = t->bytes;
 
        ios[rw]++;
@@ -321,6 +326,25 @@ static void handle_trace_fs(struct thread_data *td, struct blk_io_trace *t,
        store_ipo(td, t->sector, t->bytes, rw, ttime, fileno, bs);
 }
 
+static void handle_trace_flush(struct thread_data *td, struct blk_io_trace *t,
+                              unsigned long long ttime)
+{
+       struct io_piece *ipo;
+       unsigned int bs;
+       int fileno;
+
+       ipo = calloc(1, sizeof(*ipo));
+       init_ipo(ipo);
+       fileno = trace_add_file(td, t->device, &bs);
+
+       ipo->delay = ttime / 1000;
+       ipo->ddir = DDIR_SYNC;
+       ipo->fileno = fileno;
+
+       dprint(FD_BLKTRACE, "store flush delay=%lu\n", ipo->delay);
+       queue_io_piece(td, ipo);
+}
+
 /*
  * We only care for queue traces, most of the others are side effects
  * due to internal workings of the block layer.
@@ -335,13 +359,19 @@ static void handle_trace(struct thread_data *td, struct blk_io_trace *t,
                return;
 
        if (!(t->action & BLK_TC_ACT(BLK_TC_NOTIFY))) {
-               if (!last_ttime || td->o.no_stall) {
-                       last_ttime = t->time;
+               if (!last_ttime || td->o.no_stall)
                        delay = 0;
-               } else {
+               else if (td->o.replay_time_scale == 100)
                        delay = t->time - last_ttime;
-                       last_ttime = t->time;
+               else {
+                       double tmp = t->time - last_ttime;
+                       double scale;
+
+                       scale = (double) 100.0 / (double) td->o.replay_time_scale;
+                       tmp *= scale;
+                       delay = tmp;
                }
+               last_ttime = t->time;
        }
 
        t_bytes_align(&td->o, t);
@@ -350,6 +380,8 @@ static void handle_trace(struct thread_data *td, struct blk_io_trace *t,
                handle_trace_notify(t);
        else if (t->action & BLK_TC_ACT(BLK_TC_DISCARD))
                handle_trace_discard(td, t, delay, ios, bs);
+       else if (t->action & BLK_TC_ACT(BLK_TC_FLUSH))
+               handle_trace_flush(td, t, delay);
        else
                handle_trace_fs(td, t, delay, ios, bs);
 }
@@ -500,10 +532,8 @@ int load_blktrace(struct thread_data *td, const char *filename, int need_swap)
                handle_trace(td, &t, ios, rw_bs);
        } while (1);
 
-       for (i = 0; i < td->files_index; i++) {
-               f = td->files[i];
+       for_each_file(td, f, i)
                trace_add_open_close_event(td, f->fileno, FIO_LOG_CLOSE_FILE);
-       }
 
        fifo_free(fifo);
        close(fd);