[PATCH] Style fixups
[blktrace.git] / blkparse.c
CommitLineData
d956a2cd
JA
1/*
2 * block queue tracing parse application
3 *
4 * Copyright (C) 2005 Jens Axboe <axboe@suse.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
d0ca268b
JA
21#include <sys/types.h>
22#include <sys/stat.h>
23#include <unistd.h>
24#include <stdio.h>
25#include <fcntl.h>
26#include <stdlib.h>
8fc0abbc 27#include <string.h>
d0ca268b 28
8fc0abbc
JA
29#include "blktrace.h"
30#include "rbtree.h"
d0ca268b 31
fd92da24 32#define MAX_CPUS (512)
d0ca268b 33
cfab07eb
AB
34#define SECONDS(x) ((unsigned long long)(x) / 1000000000)
35#define NANO_SECONDS(x) ((unsigned long long)(x) % 1000000000)
36
37int backwards;
38unsigned long long genesis_time, last_reported_time;
d0ca268b
JA
39struct per_file_info {
40 int cpu;
41 int nelems;
d0ca268b
JA
42
43 int fd;
87b72777 44 char fname[128];
d0ca268b 45
87b72777
JA
46 FILE *ofp;
47 char ofname[128];
8fc0abbc 48
5c017e4b 49 unsigned long qreads, qwrites, creads, cwrites, mreads, mwrites;
afd2d7ad 50 unsigned long ireads, iwrites;
5c017e4b 51 unsigned long long qread_kb, qwrite_kb, cread_kb, cwrite_kb;
afd2d7ad 52 unsigned long long iread_kb, iwrite_kb;
d0ca268b
JA
53};
54
8fc0abbc
JA
55static struct rb_root rb_root;
56
57struct trace {
58 struct blk_io_trace *bit;
66fa7233 59 unsigned int cpu;
8fc0abbc
JA
60 struct rb_node rb_node;
61};
62
87b72777
JA
63static struct per_file_info per_file_info[MAX_CPUS];
64static struct per_file_info *cur_file;
d0ca268b 65
87b72777
JA
66static unsigned long long events;
67
68static int max_cpus;
d0ca268b 69
cfab07eb
AB
70static inline void check_time(struct blk_io_trace *bit)
71{
72 unsigned long long this = bit->time;
73 unsigned long long last = last_reported_time;
74
75 backwards = (this < last) ? 'B' : ' ';
76 last_reported_time = this;
77}
78
5c017e4b
JA
79static inline void account_m(struct per_file_info *pfi, int rw,
80 unsigned int bytes)
d0ca268b
JA
81{
82 if (rw) {
5c017e4b
JA
83 pfi->mwrites++;
84 pfi->qwrite_kb += bytes >> 10;
d0ca268b 85 } else {
5c017e4b
JA
86 pfi->mreads++;
87 pfi->qread_kb += bytes >> 10;
d0ca268b
JA
88 }
89}
90
5c017e4b
JA
91static inline void account_q(struct per_file_info *pfi, int rw,
92 unsigned int bytes)
d0ca268b
JA
93{
94 if (rw) {
5c017e4b
JA
95 pfi->qwrites++;
96 pfi->qwrite_kb += bytes >> 10;
d0ca268b 97 } else {
5c017e4b
JA
98 pfi->qreads++;
99 pfi->qread_kb += bytes >> 10;
d0ca268b
JA
100 }
101}
102
5c017e4b
JA
103static inline void account_c(struct per_file_info *pfi, int rw,
104 unsigned int bytes)
d0ca268b
JA
105{
106 if (rw) {
5c017e4b
JA
107 pfi->cwrites++;
108 pfi->cwrite_kb += bytes >> 10;
d0ca268b 109 } else {
5c017e4b
JA
110 pfi->creads++;
111 pfi->cread_kb += bytes >> 10;
d0ca268b
JA
112 }
113}
114
afd2d7ad 115static inline void account_i(struct per_file_info *pfi, int rw,
116 unsigned int bytes)
117{
118 if (rw) {
119 pfi->iwrites++;
120 pfi->iwrite_kb += bytes >> 10;
121 } else {
122 pfi->ireads++;
123 pfi->iread_kb += bytes >> 10;
124 }
125}
126
3aabcd89 127static void output(char *s)
d0ca268b
JA
128{
129 printf("%s", s);
3aabcd89 130 fprintf(cur_file->ofp,"%s",s);
d0ca268b
JA
131}
132
3aabcd89
JA
133static char hstring[256];
134static char tstring[256];
d0ca268b 135
3aabcd89 136static inline char *setup_header(struct blk_io_trace *t, char act)
d0ca268b
JA
137{
138 int w = t->action & BLK_TC_ACT(BLK_TC_WRITE);
139 int b = t->action & BLK_TC_ACT(BLK_TC_BARRIER);
140 int s = t->action & BLK_TC_ACT(BLK_TC_SYNC);
141 char rwbs[4];
142 int i = 0;
143
144 if (w)
145 rwbs[i++] = 'W';
146 else
147 rwbs[i++] = 'R';
148 if (b)
149 rwbs[i++] = 'B';
150 if (s)
151 rwbs[i++] = 'S';
152
153 rwbs[i] = '\0';
154
cfab07eb
AB
155 sprintf(hstring, "%c %3d %15ld %5Lu.%09Lu %5u %c %3s", backwards,
156 cur_file->cpu,
157 (unsigned long)t->sequence, SECONDS(t->time),
158 NANO_SECONDS(t->time), t->pid, act, rwbs);
d0ca268b
JA
159
160 return hstring;
161}
162
3aabcd89 163static void log_complete(struct blk_io_trace *t, char act)
d0ca268b
JA
164{
165 sprintf(tstring,"%s %Lu + %u [%d]\n", setup_header(t, act),
166 (unsigned long long)t->sector, t->bytes >> 9, t->error);
167 output(tstring);
168}
169
3aabcd89 170static void log_queue(struct blk_io_trace *t, char act)
d0ca268b
JA
171{
172 sprintf(tstring,"%s %Lu + %u\n", setup_header(t, act),
173 (unsigned long long)t->sector, t->bytes >> 9);
174 output(tstring);
175}
176
3aabcd89 177static void log_issue(struct blk_io_trace *t, char act)
d0ca268b
JA
178{
179 sprintf(tstring,"%s %Lu + %u\n", setup_header(t, act),
180 (unsigned long long)t->sector, t->bytes >> 9);
181 output(tstring);
182}
183
3aabcd89 184static void log_merge(struct blk_io_trace *t, char act)
d0ca268b
JA
185{
186 sprintf(tstring,"%s %Lu + %u\n", setup_header(t, act),
187 (unsigned long long)t->sector, t->bytes >> 9);
188 output(tstring);
189}
190
3aabcd89 191static void log_generic(struct blk_io_trace *t, char act)
d0ca268b
JA
192{
193 sprintf(tstring,"%s %Lu + %u\n", setup_header(t, act),
194 (unsigned long long)t->sector, t->bytes >> 9);
195 output(tstring);
196}
197
87b72777 198static int log_pc(struct blk_io_trace *t, char act)
d0ca268b 199{
87b72777
JA
200 unsigned char *buf;
201 int i;
d0ca268b 202
87b72777 203 sprintf(tstring,"%s ", setup_header(t, act));
d0ca268b
JA
204 output(tstring);
205
87b72777 206 buf = (unsigned char *) t + sizeof(*t);
d0ca268b
JA
207 for (i = 0; i < t->pdu_len; i++) {
208 sprintf(tstring,"%02x ", buf[i]);
209 output(tstring);
210 }
211
212 if (act == 'C') {
213 sprintf(tstring,"[%d]", t->error);
214 output(tstring);
215 }
216
217 printf("\n");
87b72777 218 return 0;
d0ca268b
JA
219}
220
5c017e4b 221static int dump_trace_pc(struct blk_io_trace *t, struct per_file_info *pfi)
d0ca268b 222{
87b72777
JA
223 int ret = 0;
224
d0ca268b
JA
225 switch (t->action & 0xffff) {
226 case __BLK_TA_QUEUE:
227 log_generic(t, 'Q');
228 break;
229 case __BLK_TA_GETRQ:
230 log_generic(t, 'G');
231 break;
232 case __BLK_TA_SLEEPRQ:
233 log_generic(t, 'S');
234 break;
235 case __BLK_TA_REQUEUE:
236 log_generic(t, 'R');
237 break;
238 case __BLK_TA_ISSUE:
87b72777 239 ret = log_pc(t, 'D');
d0ca268b
JA
240 break;
241 case __BLK_TA_COMPLETE:
242 log_pc(t, 'C');
243 break;
244 default:
245 fprintf(stderr, "Bad pc action %x\n", t->action);
87b72777
JA
246 ret = 1;
247 break;
d0ca268b
JA
248 }
249
87b72777 250 return ret;
d0ca268b
JA
251}
252
5c017e4b 253static void dump_trace_fs(struct blk_io_trace *t, struct per_file_info *pfi)
d0ca268b
JA
254{
255 int w = t->action & BLK_TC_ACT(BLK_TC_WRITE);
256
257 switch (t->action & 0xffff) {
258 case __BLK_TA_QUEUE:
5c017e4b 259 account_q(pfi, w, t->bytes);
d0ca268b
JA
260 log_queue(t, 'Q');
261 break;
262 case __BLK_TA_BACKMERGE:
5c017e4b 263 account_m(pfi, w, t->bytes);
d0ca268b
JA
264 log_merge(t, 'M');
265 break;
266 case __BLK_TA_FRONTMERGE:
5c017e4b 267 account_m(pfi, w, t->bytes);
d0ca268b
JA
268 log_merge(t, 'F');
269 break;
270 case __BLK_TA_GETRQ:
271 log_generic(t, 'G');
272 break;
273 case __BLK_TA_SLEEPRQ:
274 log_generic(t, 'S');
275 break;
276 case __BLK_TA_REQUEUE:
5c017e4b 277 account_c(pfi, w, -t->bytes);
d0ca268b
JA
278 log_queue(t, 'R');
279 break;
280 case __BLK_TA_ISSUE:
afd2d7ad 281 account_i(pfi, w, t->bytes);
d0ca268b
JA
282 log_issue(t, 'D');
283 break;
284 case __BLK_TA_COMPLETE:
5c017e4b 285 account_c(pfi, w, t->bytes);
d0ca268b
JA
286 log_complete(t, 'C');
287 break;
288 default:
289 fprintf(stderr, "Bad fs action %x\n", t->action);
290 return;
291 }
d0ca268b
JA
292}
293
5c017e4b 294static int dump_trace(struct blk_io_trace *t, struct per_file_info *pfi)
d0ca268b 295{
87b72777
JA
296 int ret = 0;
297
d0ca268b 298 if (t->action & BLK_TC_ACT(BLK_TC_PC))
5c017e4b 299 ret = dump_trace_pc(t, pfi);
d0ca268b 300 else
5c017e4b 301 dump_trace_fs(t, pfi);
87b72777
JA
302
303 events++;
304 return ret;
d0ca268b
JA
305}
306
5c017e4b
JA
307static void dump_pfi_stats(struct per_file_info *pfi)
308{
309 printf("\tReads:\n");
310 printf("\t\tQueued: %'8lu, %'8LuKiB\n", pfi->qreads, pfi->qread_kb);
afd2d7ad 311 printf("\t\tDispatched %'8lu, %'8LuKiB\n", pfi->ireads, pfi->iread_kb);
5c017e4b
JA
312 printf("\t\tCompleted: %'8lu, %'8LuKiB\n", pfi->creads, pfi->cread_kb);
313 printf("\t\tMerges: %'8lu\n", pfi->mreads);
314
315 printf("\tWrites:\n");
316 printf("\t\tQueued: %'8lu, %'8LuKiB\n", pfi->qwrites,pfi->qwrite_kb);
afd2d7ad 317 printf("\t\tDispatched %'8lu, %'8LuKiB\n", pfi->iwrites,pfi->iwrite_kb);
5c017e4b
JA
318 printf("\t\tCompleted: %'8lu, %'8LuKiB\n", pfi->cwrites,pfi->cwrite_kb);
319 printf("\t\tMerges: %'8lu\n", pfi->mwrites);
320}
321
322static void show_stats(int nfiles)
d0ca268b 323{
5c017e4b
JA
324 struct per_file_info foo, *pfi;
325 int i;
326
327 memset(&foo, 0, sizeof(foo));
d0ca268b 328
5c017e4b
JA
329 for (i = 0; i < nfiles; i++) {
330 pfi = &per_file_info[i];
331
afd2d7ad 332 if (!pfi->nelems)
333 continue;
334
5c017e4b
JA
335 foo.qreads += pfi->qreads;
336 foo.qwrites += pfi->qwrites;
337 foo.creads += pfi->creads;
338 foo.cwrites += pfi->cwrites;
339 foo.mreads += pfi->mreads;
340 foo.mwrites += pfi->mwrites;
341 foo.qread_kb += pfi->qread_kb;
342 foo.qwrite_kb += pfi->qwrite_kb;
343 foo.cread_kb += pfi->cread_kb;
344 foo.cwrite_kb += pfi->cwrite_kb;
345
346 printf("CPU%d:\n", i);
347 dump_pfi_stats(pfi);
348 }
349
350 if (nfiles > 1) {
351 printf("Total:\n");
352 dump_pfi_stats(&foo);
353 }
d0ca268b
JA
354
355 printf("Events: %'Lu\n", events);
d0ca268b
JA
356}
357
3aabcd89 358static inline int trace_rb_insert(struct trace *t)
8fc0abbc
JA
359{
360 struct rb_node **p = &rb_root.rb_node;
361 struct rb_node *parent = NULL;
362 struct trace *__t;
363
364 while (*p) {
365 parent = *p;
366 __t = rb_entry(parent, struct trace, rb_node);
367
368 if (t->bit->sequence < __t->bit->sequence)
369 p = &(*p)->rb_left;
370 else if (t->bit->sequence > __t->bit->sequence)
371 p = &(*p)->rb_right;
372 else {
87b72777 373 fprintf(stderr, "sequence alias!\n");
8fc0abbc
JA
374 return 1;
375 }
376 }
377
378 rb_link_node(&t->rb_node, parent, p);
379 rb_insert_color(&t->rb_node, &rb_root);
380 return 0;
381}
382
66fa7233 383static int sort_entries(void *traces, unsigned long offset, int cpu)
8fc0abbc
JA
384{
385 struct blk_io_trace *bit;
386 struct trace *t;
387 void *start = traces;
388 int nelems = 0;
389
6fe4709e 390 while (traces - start <= offset - sizeof(*bit)) {
8fc0abbc 391 bit = traces;
6fe4709e 392
8fc0abbc
JA
393 t = malloc(sizeof(*t));
394 t->bit = bit;
66fa7233 395 t->cpu = cpu;
8fc0abbc
JA
396 memset(&t->rb_node, 0, sizeof(t->rb_node));
397
6fe4709e
JA
398 trace_to_cpu(bit);
399
66fa7233
JA
400 if (verify_trace(bit))
401 break;
402
8fc0abbc
JA
403 if (trace_rb_insert(t))
404 return -1;
405
406 traces += sizeof(*bit) + bit->pdu_len;
407 nelems++;
6fe4709e 408 }
8fc0abbc
JA
409
410 return nelems;
411}
412
3aabcd89 413static void show_entries(void)
8fc0abbc 414{
8fc0abbc 415 struct blk_io_trace *bit;
3aabcd89 416 struct rb_node *n;
8fc0abbc
JA
417 struct trace *t;
418 int cpu;
419
3aabcd89
JA
420 n = rb_first(&rb_root);
421 if (!n)
422 return;
8fc0abbc 423
3aabcd89 424 do {
8fc0abbc
JA
425 t = rb_entry(n, struct trace, rb_node);
426 bit = t->bit;
427
66fa7233 428 cpu = t->cpu;
87b72777 429 if (cpu > max_cpus) {
8fc0abbc 430 fprintf(stderr, "CPU number too large (%d)\n", cpu);
87b72777 431 break;
8fc0abbc
JA
432 }
433
3aabcd89 434 cur_file = &per_file_info[cpu];
8fc0abbc 435
cfab07eb
AB
436 if (genesis_time == 0)
437 genesis_time = bit->time;
438 bit->time -= genesis_time;
8fc0abbc 439
cfab07eb 440 check_time(bit);
8fc0abbc 441
5c017e4b 442 if (dump_trace(bit, cur_file))
87b72777
JA
443 break;
444
8fc0abbc
JA
445 } while ((n = rb_next(n)) != NULL);
446}
447
d0ca268b
JA
448int main(int argc, char *argv[])
449{
3aabcd89
JA
450 int i, nfiles, ret;
451 char *dev;
d0ca268b
JA
452
453 if (argc != 2) {
87b72777 454 fprintf(stderr, "Usage: %s <dev>\n", argv[0]);
d0ca268b
JA
455 return 1;
456 }
457
458 dev = argv[1];
459
df0fae6d 460 memset(&rb_root, 0, sizeof(rb_root));
5c017e4b 461 memset(per_file_info, 0, sizeof(per_file_info));
df0fae6d 462
afd2d7ad 463 for (max_cpus = 0, i = 0, nfiles = 0; i < MAX_CPUS; i++, nfiles++, max_cpus++) {
87b72777
JA
464 struct per_file_info *pfi = &per_file_info[i];
465 struct stat st;
466 void *tb;
467
d0ca268b 468 pfi->cpu = i;
d0ca268b 469
87b72777
JA
470 snprintf(pfi->fname, sizeof(pfi->fname)-1,"%s_out.%d", dev, i);
471 if (stat(pfi->fname, &st) < 0)
d0ca268b 472 break;
afd2d7ad 473 if (!st.st_size)
474 continue;
d0ca268b 475
87b72777 476 snprintf(pfi->ofname, sizeof(pfi->ofname)-1, "%s_log.%d", dev, i);
d0ca268b
JA
477 pfi->ofp = fopen(pfi->ofname, "w");
478 if (pfi->ofp == NULL) {
479 perror(pfi->ofname);
3aabcd89 480 break;
d0ca268b
JA
481 }
482
8fc0abbc
JA
483 printf("Processing %s\n", pfi->fname);
484
87b72777 485 tb = malloc(st.st_size);
8fc0abbc
JA
486
487 pfi->fd = open(pfi->fname, O_RDONLY);
488 if (pfi->fd < 0) {
d0ca268b 489 perror(pfi->fname);
3aabcd89 490 break;
d0ca268b 491 }
afd2d7ad 492
87b72777 493 if (read(pfi->fd, tb, st.st_size) != st.st_size) {
8fc0abbc 494 fprintf(stderr, "error reading\n");
3aabcd89 495 break;
fd92da24 496 }
d0ca268b 497
66fa7233 498 ret = sort_entries(tb, st.st_size, i);
8fc0abbc 499 if (ret == -1)
3aabcd89 500 break;
d0ca268b 501
8fc0abbc 502 close(pfi->fd);
8fc0abbc 503 pfi->nelems = ret;
8fc0abbc 504 printf("\t%2d %10s %15d\n", i, pfi->fname, pfi->nelems);
d0ca268b 505
d0ca268b
JA
506 }
507
3aabcd89
JA
508 if (nfiles) {
509 show_entries();
5c017e4b 510 show_stats(nfiles);
3aabcd89
JA
511 return 0;
512 }
8fc0abbc 513
3aabcd89
JA
514 fprintf(stderr, "No files found\n");
515 return 1;
d0ca268b 516}