t/btrace2fio: cap depth if we don't see completion traces
[fio.git] / t / btrace2fio.c
index 5666a560c0beca15941ad596a3469a4422264d36..bf67ed0a183ac5cbd08854087e068f37355d399b 100644 (file)
@@ -19,6 +19,7 @@ static unsigned int rt_threshold = 1000000;
 static unsigned int ios_threshold = 10;
 static unsigned int rate_threshold;
 static unsigned int set_rate;
+static unsigned int max_depth = 256;
 static int output_ascii = 1;
 static char *filename;
 
@@ -45,6 +46,9 @@ struct btrace_out {
 
        int inflight;
        unsigned int depth;
+       int depth_disabled;
+       int complete_seen;
+
        uint64_t first_ttime[DDIR_RWDIR_CNT];
        uint64_t last_ttime[DDIR_RWDIR_CNT];
        uint64_t kb[DDIR_RWDIR_CNT];
@@ -125,7 +129,13 @@ static void inflight_add(struct btrace_pid *p, uint64_t sector, uint32_t len)
        i = calloc(1, sizeof(*i));
        i->p = p;
        o->inflight++;
-       o->depth = max((int) o->depth, o->inflight);
+       if (!o->depth_disabled) {
+               o->depth = max((int) o->depth, o->inflight);
+               if (o->depth >= max_depth && !o->complete_seen) {
+                       o->depth_disabled = 1;
+                       o->depth = max_depth;
+               }
+       }
        i->end_sector = sector + (len >> 9);
        __inflight_add(i);
 }
@@ -383,6 +393,7 @@ static int handle_trace(struct blk_io_trace *t, struct btrace_pid *p)
                i = inflight_find(t->sector + (t->bytes >> 9));
                if (i) {
                        i->p->o.kb[t_to_rwdir(t)] += (t->bytes >> 10);
+                       i->p->o.complete_seen = 1;
                        inflight_remove(i);
                }
        }
@@ -450,7 +461,7 @@ static struct btrace_pid *pid_hash_get(pid_t pid)
  * Load a blktrace file by reading all the blk_io_trace entries, and storing
  * them as io_pieces like the fio text version would do.
  */
-static int load_blktrace(const char *filename, int need_swap)
+static int load_blktrace(const char *fname, int need_swap)
 {
        struct btrace_pid *p;
        unsigned long traces;
@@ -458,7 +469,7 @@ static int load_blktrace(const char *filename, int need_swap)
        struct fifo *fifo;
        int fd, ret = 0;
 
-       fd = open(filename, O_RDONLY);
+       fd = open(fname, O_RDONLY);
        if (fd < 0) {
                perror("open trace file\n");
                return 1;
@@ -468,8 +479,7 @@ static int load_blktrace(const char *filename, int need_swap)
 
        traces = 0;
        do {
-               int ret = trace_fifo_get(fifo, fd, &t, sizeof(t));
-
+               ret = trace_fifo_get(fifo, fd, &t, sizeof(t));
                if (ret < 0)
                        goto err;
                else if (!ret)
@@ -811,6 +821,7 @@ static int output_p(void)
 {
        unsigned long ios[DDIR_RWDIR_CNT];
        struct flist_head *e, *tmp;
+       int depth_disabled = 0;
        int ret = 0;
 
        flist_for_each_safe(e, tmp, &pid_list) {
@@ -822,8 +833,12 @@ static int output_p(void)
                        continue;
                }
                p->o.start_delay = (o_first_ttime(&p->o) / 1000ULL) - first_ttime;
+               depth_disabled += p->o.depth_disabled;
        }
 
+       if (depth_disabled)
+               log_err("fio: missing completion traces, depths capped at %u\n", max_depth);
+
        memset(ios, 0, sizeof(ios));
 
        flist_sort(NULL, &pid_list, entry_cmp);
@@ -852,6 +867,7 @@ static int usage(char *argv[])
        log_err("\t-d\tUse this file/device for replay\n");
        log_err("\t-r\tIgnore jobs with less than this KB/sec rate\n");
        log_err("\t-R\tSet rate in fio job\n");
+       log_err("\t-D\tCap queue depth at this value (def=%u)\n", max_depth);
        return 1;
 }
 
@@ -870,9 +886,11 @@ static int trace_needs_swap(const char *trace_file, int *swap)
 
        ret = read(fd, &t, sizeof(t));
        if (ret < 0) {
+               close(fd);
                perror("read");
                return 1;
        } else if (ret != sizeof(t)) {
+               close(fd);
                log_err("fio: short read on trace file\n");
                return 1;
        }
@@ -905,7 +923,7 @@ int main(int argc, char *argv[])
        if (argc < 2)
                return usage(argv);
 
-       while ((c = getopt(argc, argv, "t:n:fd:r:R")) != -1) {
+       while ((c = getopt(argc, argv, "t:n:fd:r:RD:")) != -1) {
                switch (c) {
                case 'R':
                        set_rate = 1;
@@ -925,6 +943,9 @@ int main(int argc, char *argv[])
                case 'd':
                        filename = strdup(optarg);
                        break;
+               case 'D':
+                       max_depth = atoi(optarg);
+                       break;
                case '?':
                default:
                        return usage(argv);