12 #define MAX_CPUS (512)
14 struct per_file_info {
28 unsigned long long start_time;
31 static struct rb_root rb_root;
34 struct blk_io_trace *bit;
35 struct rb_node rb_node;
38 struct per_file_info per_file_info[MAX_CPUS];
39 struct per_file_info *cur_file;
41 static unsigned long qreads, qwrites, creads, cwrites, mreads, mwrites;
42 static unsigned long long qread_kb, qwrite_kb, cread_kb, cwrite_kb;
43 static unsigned long long events, missed_events;
45 static inline void account_m(int rw, unsigned int bytes)
49 qwrite_kb += bytes >> 10;
52 qread_kb += bytes >> 10;
56 static inline void account_q(int rw, unsigned int bytes)
60 qwrite_kb += bytes >> 10;
63 qread_kb += bytes >> 10;
67 static inline void account_c(int rw, unsigned int bytes)
71 cwrite_kb += bytes >> 10;
74 cread_kb += bytes >> 10;
78 static void output(char *s)
81 fprintf(cur_file->ofp,"%s",s);
84 static char hstring[256];
85 static char tstring[256];
87 static inline char *setup_header(struct blk_io_trace *t, char act)
89 int w = t->action & BLK_TC_ACT(BLK_TC_WRITE);
90 int b = t->action & BLK_TC_ACT(BLK_TC_BARRIER);
91 int s = t->action & BLK_TC_ACT(BLK_TC_SYNC);
106 sprintf(hstring, "%3d %15ld %12Lu %5u %c %3s", cur_file->cpu,
107 (unsigned long)t->sequence, (unsigned long long)t->time, t->pid,
113 static void log_complete(struct blk_io_trace *t, char act)
115 sprintf(tstring,"%s %Lu + %u [%d]\n", setup_header(t, act),
116 (unsigned long long)t->sector, t->bytes >> 9, t->error);
120 static void log_queue(struct blk_io_trace *t, char act)
122 sprintf(tstring,"%s %Lu + %u\n", setup_header(t, act),
123 (unsigned long long)t->sector, t->bytes >> 9);
127 static void log_issue(struct blk_io_trace *t, char act)
129 sprintf(tstring,"%s %Lu + %u\n", setup_header(t, act),
130 (unsigned long long)t->sector, t->bytes >> 9);
134 static void log_merge(struct blk_io_trace *t, char act)
136 sprintf(tstring,"%s %Lu + %u\n", setup_header(t, act),
137 (unsigned long long)t->sector, t->bytes >> 9);
141 static void log_generic(struct blk_io_trace *t, char act)
143 sprintf(tstring,"%s %Lu + %u\n", setup_header(t, act),
144 (unsigned long long)t->sector, t->bytes >> 9);
148 static void log_pc(struct blk_io_trace *t, char act)
151 unsigned char buf[64];
153 sprintf(tstring,"%s\n", setup_header(t, act));
156 if (t->pdu_len > sizeof(buf)) {
157 fprintf(stderr, "Payload too large %d\n", t->pdu_len);
161 ret = read(cur_file->dfd, buf, t->pdu_len);
162 if (ret != t->pdu_len) {
163 fprintf(stderr,"read(%d) failed on %s - %d\n", t->pdu_len,
164 cur_file->dname, ret);
168 for (i = 0; i < t->pdu_len; i++) {
169 sprintf(tstring,"%02x ", buf[i]);
174 sprintf(tstring,"[%d]", t->error);
181 static void dump_trace_pc(struct blk_io_trace *t)
183 switch (t->action & 0xffff) {
190 case __BLK_TA_SLEEPRQ:
193 case __BLK_TA_REQUEUE:
199 case __BLK_TA_COMPLETE:
203 fprintf(stderr, "Bad pc action %x\n", t->action);
210 static void dump_trace_fs(struct blk_io_trace *t)
212 int w = t->action & BLK_TC_ACT(BLK_TC_WRITE);
214 switch (t->action & 0xffff) {
216 account_q(w, t->bytes);
219 case __BLK_TA_BACKMERGE:
220 account_m(w, t->bytes);
223 case __BLK_TA_FRONTMERGE:
224 account_m(w, t->bytes);
230 case __BLK_TA_SLEEPRQ:
233 case __BLK_TA_REQUEUE:
239 case __BLK_TA_COMPLETE:
240 account_c(w, t->bytes);
241 log_complete(t, 'C');
244 fprintf(stderr, "Bad fs action %x\n", t->action);
251 static void dump_trace(struct blk_io_trace *t)
253 if (t->action & BLK_TC_ACT(BLK_TC_PC))
259 static void show_stats(void)
262 printf("\tQueued: %'8lu, %'8LuKiB\n", qreads, qread_kb);
263 printf("\tCompleted: %'8lu, %'8LuKiB\n", creads, cread_kb);
264 printf("\tMerges: %'8lu\n", mreads);
267 printf("\tQueued: %'8lu, %'8LuKiB\n", qwrites, qwrite_kb);
268 printf("\tCompleted: %'8lu, %'8LuKiB\n", cwrites, cwrite_kb);
269 printf("\tMerges: %'8lu\n", mwrites);
271 printf("Events: %'Lu\n", events);
272 printf("Missed events: %'Lu\n", missed_events);
275 static inline int trace_rb_insert(struct trace *t)
277 struct rb_node **p = &rb_root.rb_node;
278 struct rb_node *parent = NULL;
283 __t = rb_entry(parent, struct trace, rb_node);
285 if (t->bit->sequence < __t->bit->sequence)
287 else if (t->bit->sequence > __t->bit->sequence)
290 fprintf(stderr, "sequence alias %u!\n", t->bit->sequence);
295 rb_link_node(&t->rb_node, parent, p);
296 rb_insert_color(&t->rb_node, &rb_root);
300 static int sort_entries(void *traces, unsigned long offset)
302 struct blk_io_trace *bit;
304 void *start = traces;
307 memset(&rb_root, 0, sizeof(rb_root));
311 t = malloc(sizeof(*t));
313 memset(&t->rb_node, 0, sizeof(t->rb_node));
315 if (trace_rb_insert(t))
318 traces += sizeof(*bit) + bit->pdu_len;
320 } while (traces < start + offset);
325 static void show_entries(void)
327 struct blk_io_trace *bit;
332 n = rb_first(&rb_root);
337 t = rb_entry(n, struct trace, rb_node);
341 if (cpu >= MAX_CPUS) {
342 fprintf(stderr, "CPU number too large (%d)\n", cpu);
346 cur_file = &per_file_info[cpu];
349 * offset time by first trace event.
351 * NOTE: This is *cpu* relative, thus you can not
352 * compare times ACROSS cpus.
354 if (cur_file->start_time == 0)
355 cur_file->start_time = bit->time;
357 bit->time -= cur_file->start_time;
360 } while ((n = rb_next(n)) != NULL);
363 int main(int argc, char *argv[])
365 struct per_file_info *pfi;
370 fprintf(stderr, "Usage %s <dev>\n", argv[0]);
377 for (i = 0, pfi = &per_file_info[0]; i < MAX_CPUS; i++, pfi++) {
381 pfi->fname = malloc(128);
382 sprintf(pfi->fname, "%s_out.%d", dev, i);
383 if (stat(pfi->fname, &pfi->stat) < 0)
386 pfi->dname = malloc(128);
387 snprintf(pfi->dname, 127, "%s_dat.%d", dev, i);
388 pfi->dfd = open(pfi->dname, O_RDONLY);
394 pfi->ofname = malloc(128);
395 snprintf(pfi->ofname, 127, "%s_log.%d", dev, i);
396 pfi->ofp = fopen(pfi->ofname, "w");
397 if (pfi->ofp == NULL) {
402 printf("Processing %s\n", pfi->fname);
404 pfi->trace_buf = malloc(pfi->stat.st_size);
406 pfi->fd = open(pfi->fname, O_RDONLY);
411 if (read(pfi->fd, pfi->trace_buf, pfi->stat.st_size) != pfi->stat.st_size) {
412 fprintf(stderr, "error reading\n");
416 ret = sort_entries(pfi->trace_buf, pfi->stat.st_size);
423 printf("\t%2d %10s %15d\n", i, pfi->fname, pfi->nelems);
433 fprintf(stderr, "No files found\n");