static struct flist_head pid_hash[PID_HASH_SIZE];
static FLIST_HEAD(pid_list);
-static FLIST_HEAD(inflight_list);
+#define INFLIGHT_HASH_BITS 8
+#define INFLIGHT_HASH_SIZE (1U << INFLIGHT_HASH_BITS)
+static struct flist_head inflight_hash[INFLIGHT_HASH_SIZE];
static uint64_t first_ttime = -1ULL;
static struct inflight *inflight_find(uint64_t sector)
{
+ struct flist_head *inflight_list;
struct flist_head *e;
- flist_for_each(e, &inflight_list) {
+ inflight_list = &inflight_hash[hash_long(sector, INFLIGHT_HASH_BITS)];
+
+ flist_for_each(e, inflight_list) {
struct inflight *i = flist_entry(e, struct inflight, list);
if (i->end_sector == sector)
free(i);
}
-static void inflight_merge(struct inflight *i, int rw, unsigned int size)
+static void __inflight_add(struct inflight *i)
{
- i->p->o.merges[rw]++;
- if (size)
- i->end_sector += (size >> 9);
+ struct flist_head *list;
+
+ list = &inflight_hash[hash_long(i->end_sector, INFLIGHT_HASH_BITS)];
+ flist_add_tail(&i->list, list);
}
static void inflight_add(struct btrace_pid *p, uint64_t sector, uint32_t len)
o->inflight++;
o->depth = max((int) o->depth, o->inflight);
i->end_sector = sector + (len >> 9);
- flist_add_tail(&i->list, &inflight_list);
+ __inflight_add(i);
+}
+
+static void inflight_merge(struct inflight *i, int rw, unsigned int size)
+{
+ i->p->o.merges[rw]++;
+ if (size) {
+ i->end_sector += (size >> 9);
+ flist_del(&i->list);
+ __inflight_add(i);
+ }
}
/*
case BLK_TN_MESSAGE:
break;
default:
- fprintf(stderr, "unknown trace act %x\n", t->action);
+ log_err("unknown trace act %x\n", t->action);
break;
}
}
else if (!ret)
break;
else if (ret < (int) sizeof(t)) {
- fprintf(stderr, "fio: short fifo get\n");
+ log_err("fio: short fifo get\n");
break;
}
byteswap_trace(&t);
if ((t.magic & 0xffffff00) != BLK_IO_TRACE_MAGIC) {
- fprintf(stderr, "fio: bad magic in blktrace data: %x\n",
- t.magic);
+ log_err("fio: bad magic in blktrace data: %x\n", t.magic);
goto err;
}
if ((t.magic & 0xff) != BLK_IO_TRACE_VERSION) {
- fprintf(stderr, "fio: bad blktrace version %d\n",
- t.magic & 0xff);
+ log_err("fio: bad blktrace version %d\n", t.magic & 0xff);
goto err;
}
ret = discard_pdu(fifo, fd, &t);
if (ret < 0) {
- fprintf(stderr, "blktrace lseek\n");
+ log_err("blktrace lseek\n");
goto err;
} else if (t.pdu_len != ret) {
- fprintf(stderr, "fio: discarded %d of %d\n", ret, t.pdu_len);
+ log_err("fio: discarded %d of %d\n", ret, t.pdu_len);
goto err;
}
return ddir_rw_sum(pb->o.ios) - ddir_rw_sum(pa->o.ios);
}
+static void free_p(struct btrace_pid *p)
+{
+ struct btrace_out *o = &p->o;
+ int i;
+
+ for (i = 0; i < o->nr_files; i++) {
+ if (o->files[i].name && o->files[i].name != filename)
+ free(o->files[i].name);
+ }
+
+ for (i = 0; i < DDIR_RWDIR_CNT; i++)
+ free(o->bs[i]);
+
+ free(o->files);
+ flist_del(&p->pid_list);
+ flist_del(&p->hash_list);
+ free(p);
+}
+
static int output_p(void)
{
unsigned long ios[DDIR_RWDIR_CNT];
p = flist_entry(e, struct btrace_pid, pid_list);
if (prune_entry(&p->o)) {
- flist_del(&p->pid_list);
- flist_del(&p->hash_list);
- free(p);
+ free_p(p);
continue;
}
p->o.start_delay = (p->o.first_ttime / 1000ULL) - first_ttime;
static int usage(char *argv[])
{
- fprintf(stderr, "%s: <blktrace bin file>\n", argv[0]);
- fprintf(stderr, "\t-t\tUsec threshold to ignore task\n");
- fprintf(stderr, "\t-n\tNumber IOS threshold to ignore task\n");
- fprintf(stderr, "\t-f\tFio job file output\n");
- fprintf(stderr, "\t-d\tUse this file/device for replay\n");
+ log_err("%s: <blktrace bin file>\n", argv[0]);
+ log_err("\t-t\tUsec threshold to ignore task\n");
+ log_err("\t-n\tNumber IOS threshold to ignore task\n");
+ log_err("\t-f\tFio job file output\n");
+ log_err("\t-d\tUse this file/device for replay\n");
return 1;
}
-int main(int argc, char *argv[])
+static int trace_needs_swap(const char *trace_file, int *swap)
{
- int fd, ret, need_swap = -1;
struct blk_io_trace t;
- int i, c;
+ int fd, ret;
+
+ *swap = -1;
+
+ fd = open(trace_file, O_RDONLY);
+ if (fd < 0) {
+ perror("open");
+ return 1;
+ }
+
+ ret = read(fd, &t, sizeof(t));
+ if (ret < 0) {
+ perror("read");
+ return 1;
+ } else if (ret != sizeof(t)) {
+ log_err("fio: short read on trace file\n");
+ return 1;
+ }
+
+ close(fd);
+
+ if ((t.magic & 0xffffff00) == BLK_IO_TRACE_MAGIC)
+ *swap = 0;
+ else {
+ /*
+ * Maybe it needs to be endian swapped...
+ */
+ t.magic = fio_swap32(t.magic);
+ if ((t.magic & 0xffffff00) == BLK_IO_TRACE_MAGIC)
+ *swap = 1;
+ }
+
+ if (*swap == -1) {
+ log_err("fio: blktrace appears corrupt\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int need_swap, i, c;
if (argc < 2)
return usage(argv);
if (argc == optind)
return usage(argv);
- fd = open(argv[optind], O_RDONLY);
- if (fd < 0) {
- perror("open");
- return 1;
- }
-
- ret = read(fd, &t, sizeof(t));
- if (ret < 0) {
- perror("read");
- return 1;
- } else if (ret != sizeof(t)) {
- fprintf(stderr, "fio: short read on trace file\n");
- return 1;
- }
-
- close(fd);
-
- if ((t.magic & 0xffffff00) == BLK_IO_TRACE_MAGIC)
- need_swap = 0;
- else {
- /*
- * Maybe it needs to be endian swapped...
- */
- t.magic = fio_swap32(t.magic);
- if ((t.magic & 0xffffff00) == BLK_IO_TRACE_MAGIC)
- need_swap = 1;
- }
-
- if (need_swap == -1) {
- fprintf(stderr, "fio: blktrace appears corrupt\n");
+ if (trace_needs_swap(argv[optind], &need_swap))
return 1;
- }
for (i = 0; i < PID_HASH_SIZE; i++)
INIT_FLIST_HEAD(&pid_hash[i]);
+ for (i = 0; i < INFLIGHT_HASH_SIZE; i++)
+ INIT_FLIST_HEAD(&inflight_hash[i]);
load_blktrace(argv[optind], need_swap);
first_ttime /= 1000ULL;