[PATCH] Missed the ->device in endianness conversions
[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>
d5396421 28#include <getopt.h>
412819ce
JA
29#include <errno.h>
30#include <signal.h>
d0ca268b 31
8fc0abbc
JA
32#include "blktrace.h"
33#include "rbtree.h"
d0ca268b 34
cfab07eb
AB
35#define SECONDS(x) ((unsigned long long)(x) / 1000000000)
36#define NANO_SECONDS(x) ((unsigned long long)(x) % 1000000000)
37
d5396421
JA
38static int backwards;
39static unsigned long long genesis_time, last_reported_time;
40
41struct per_cpu_info {
d0ca268b
JA
42 int cpu;
43 int nelems;
d0ca268b
JA
44
45 int fd;
87b72777 46 char fname[128];
d0ca268b 47
87b72777
JA
48 FILE *ofp;
49 char ofname[128];
8fc0abbc 50
5c017e4b 51 unsigned long qreads, qwrites, creads, cwrites, mreads, mwrites;
afd2d7ad 52 unsigned long ireads, iwrites;
5c017e4b 53 unsigned long long qread_kb, qwrite_kb, cread_kb, cwrite_kb;
afd2d7ad 54 unsigned long long iread_kb, iwrite_kb;
d0ca268b
JA
55};
56
d5396421
JA
57#define S_OPTS "i:o:"
58static struct option l_opts[] = {
59 {
60 .name = "input",
61 .has_arg = 1,
62 .flag = NULL,
63 .val = 'i'
64 },
65 {
66 .name = "output",
67 .has_arg = 1,
68 .flag = NULL,
69 .val = 'o'
70 },
71 {
72 .name = NULL,
73 .has_arg = 0,
74 .flag = NULL,
75 .val = 0
76 }
77};
78
8fc0abbc
JA
79static struct rb_root rb_root;
80
81struct trace {
82 struct blk_io_trace *bit;
83 struct rb_node rb_node;
84};
85
a718bd37
NS
86static int max_cpus;
87static struct per_cpu_info *per_cpu_info;
d0ca268b 88
87b72777
JA
89static unsigned long long events;
90
d5396421 91static char *dev, *output_name;
d0ca268b 92
412819ce
JA
93#define is_done() (*(volatile int *)(&done))
94static volatile int done;
95
a718bd37
NS
96static void resize_cpu_info(int cpuid)
97{
98 int new_space, new_max = cpuid + 1;
99 char *new_start;
100
101 per_cpu_info = realloc(per_cpu_info, new_max * sizeof(*per_cpu_info));
102 if (!per_cpu_info) {
103 fprintf(stderr, "Cannot allocate CPU info -- %d x %d bytes\n",
104 new_max, (int) sizeof(*per_cpu_info));
105 exit(1);
106 }
107
108 new_start = (char *)per_cpu_info + (max_cpus * sizeof(*per_cpu_info));
109 new_space = (new_max - max_cpus) * sizeof(*per_cpu_info);
110 memset(new_start, 0, new_space);
111 max_cpus = new_max;
112}
113
114static struct per_cpu_info *get_cpu_info(int cpu)
115{
c499bf38
JA
116 struct per_cpu_info *pci;
117
a718bd37
NS
118 if (cpu >= max_cpus)
119 resize_cpu_info(cpu);
120
c499bf38
JA
121 /*
122 * ->cpu might already be set, but just set it unconditionally
123 */
124 pci = &per_cpu_info[cpu];
125 pci->cpu = cpu;
126
127 return pci;
a718bd37
NS
128}
129
cfab07eb
AB
130static inline void check_time(struct blk_io_trace *bit)
131{
132 unsigned long long this = bit->time;
133 unsigned long long last = last_reported_time;
134
135 backwards = (this < last) ? 'B' : ' ';
136 last_reported_time = this;
137}
138
d5396421 139static inline void account_m(struct per_cpu_info *pci, int rw,
5c017e4b 140 unsigned int bytes)
d0ca268b
JA
141{
142 if (rw) {
d5396421
JA
143 pci->mwrites++;
144 pci->qwrite_kb += bytes >> 10;
d0ca268b 145 } else {
d5396421
JA
146 pci->mreads++;
147 pci->qread_kb += bytes >> 10;
d0ca268b
JA
148 }
149}
150
d5396421 151static inline void account_q(struct per_cpu_info *pci, int rw,
5c017e4b 152 unsigned int bytes)
d0ca268b
JA
153{
154 if (rw) {
d5396421
JA
155 pci->qwrites++;
156 pci->qwrite_kb += bytes >> 10;
d0ca268b 157 } else {
d5396421
JA
158 pci->qreads++;
159 pci->qread_kb += bytes >> 10;
d0ca268b
JA
160 }
161}
162
d5396421 163static inline void account_c(struct per_cpu_info *pci, int rw,
5c017e4b 164 unsigned int bytes)
d0ca268b
JA
165{
166 if (rw) {
d5396421
JA
167 pci->cwrites++;
168 pci->cwrite_kb += bytes >> 10;
d0ca268b 169 } else {
d5396421
JA
170 pci->creads++;
171 pci->cread_kb += bytes >> 10;
d0ca268b
JA
172 }
173}
174
d5396421 175static inline void account_i(struct per_cpu_info *pci, int rw,
afd2d7ad 176 unsigned int bytes)
177{
178 if (rw) {
d5396421
JA
179 pci->iwrites++;
180 pci->iwrite_kb += bytes >> 10;
afd2d7ad 181 } else {
d5396421
JA
182 pci->ireads++;
183 pci->iread_kb += bytes >> 10;
afd2d7ad 184 }
185}
186
d5396421 187static void output(struct per_cpu_info *pci, char *s)
d0ca268b
JA
188{
189 printf("%s", s);
d5396421
JA
190
191 if (pci->ofp)
33b56019 192 fprintf(pci->ofp, "%s", s);
d0ca268b
JA
193}
194
3aabcd89
JA
195static char hstring[256];
196static char tstring[256];
d0ca268b 197
d5396421
JA
198static inline char *setup_header(struct per_cpu_info *pci,
199 struct blk_io_trace *t, char act)
d0ca268b
JA
200{
201 int w = t->action & BLK_TC_ACT(BLK_TC_WRITE);
202 int b = t->action & BLK_TC_ACT(BLK_TC_BARRIER);
203 int s = t->action & BLK_TC_ACT(BLK_TC_SYNC);
204 char rwbs[4];
205 int i = 0;
206
207 if (w)
208 rwbs[i++] = 'W';
209 else
210 rwbs[i++] = 'R';
211 if (b)
212 rwbs[i++] = 'B';
213 if (s)
214 rwbs[i++] = 'S';
215
216 rwbs[i] = '\0';
217
cfab07eb 218 sprintf(hstring, "%c %3d %15ld %5Lu.%09Lu %5u %c %3s", backwards,
d5396421 219 pci->cpu,
cfab07eb
AB
220 (unsigned long)t->sequence, SECONDS(t->time),
221 NANO_SECONDS(t->time), t->pid, act, rwbs);
d0ca268b
JA
222
223 return hstring;
224}
225
d5396421
JA
226static void log_complete(struct per_cpu_info *pci, struct blk_io_trace *t,
227 char act)
d0ca268b 228{
d5396421 229 sprintf(tstring,"%s %Lu + %u [%d]\n", setup_header(pci, t, act),
d0ca268b 230 (unsigned long long)t->sector, t->bytes >> 9, t->error);
d5396421 231 output(pci, tstring);
d0ca268b
JA
232}
233
d5396421
JA
234static void log_queue(struct per_cpu_info *pci, struct blk_io_trace *t,
235 char act)
d0ca268b 236{
2955af9d
NS
237 sprintf(tstring,"%s %Lu + %u [%s]\n", setup_header(pci, t, act),
238 (unsigned long long)t->sector, t->bytes >> 9, t->comm);
d5396421 239 output(pci, tstring);
d0ca268b
JA
240}
241
d5396421
JA
242static void log_issue(struct per_cpu_info *pci, struct blk_io_trace *t,
243 char act)
d0ca268b 244{
2955af9d
NS
245 sprintf(tstring,"%s %Lu + %u [%s]\n", setup_header(pci, t, act),
246 (unsigned long long)t->sector, t->bytes >> 9, t->comm);
d5396421 247 output(pci, tstring);
d0ca268b
JA
248}
249
d5396421
JA
250static void log_merge(struct per_cpu_info *pci, struct blk_io_trace *t,
251 char act)
d0ca268b 252{
2955af9d
NS
253 sprintf(tstring,"%s %Lu + %u [%s]\n", setup_header(pci, t, act),
254 (unsigned long long)t->sector, t->bytes >> 9, t->comm);
d5396421 255 output(pci, tstring);
d0ca268b
JA
256}
257
d5396421
JA
258static void log_generic(struct per_cpu_info *pci, struct blk_io_trace *t,
259 char act)
d0ca268b 260{
2955af9d
NS
261 sprintf(tstring,"%s %Lu + %u [%s]\n", setup_header(pci, t, act),
262 (unsigned long long)t->sector, t->bytes >> 9, t->comm);
d5396421 263 output(pci, tstring);
d0ca268b
JA
264}
265
d5396421 266static int log_pc(struct per_cpu_info *pci, struct blk_io_trace *t, char act)
d0ca268b 267{
87b72777
JA
268 unsigned char *buf;
269 int i;
d0ca268b 270
d5396421
JA
271 sprintf(tstring,"%s ", setup_header(pci, t, act));
272 output(pci, tstring);
d0ca268b 273
87b72777 274 buf = (unsigned char *) t + sizeof(*t);
d0ca268b
JA
275 for (i = 0; i < t->pdu_len; i++) {
276 sprintf(tstring,"%02x ", buf[i]);
d5396421 277 output(pci, tstring);
d0ca268b
JA
278 }
279
280 if (act == 'C') {
2955af9d
NS
281 sprintf(tstring,"[%d]\n", t->error);
282 output(pci, tstring);
283 } else {
284 sprintf(tstring,"[%s]\n", t->comm);
d5396421 285 output(pci, tstring);
d0ca268b 286 }
87b72777 287 return 0;
d0ca268b
JA
288}
289
d5396421 290static int dump_trace_pc(struct blk_io_trace *t, struct per_cpu_info *pci)
d0ca268b 291{
87b72777
JA
292 int ret = 0;
293
d0ca268b
JA
294 switch (t->action & 0xffff) {
295 case __BLK_TA_QUEUE:
d5396421 296 log_generic(pci, t, 'Q');
d0ca268b
JA
297 break;
298 case __BLK_TA_GETRQ:
d5396421 299 log_generic(pci, t, 'G');
d0ca268b
JA
300 break;
301 case __BLK_TA_SLEEPRQ:
d5396421 302 log_generic(pci, t, 'S');
d0ca268b
JA
303 break;
304 case __BLK_TA_REQUEUE:
d5396421 305 log_generic(pci, t, 'R');
d0ca268b
JA
306 break;
307 case __BLK_TA_ISSUE:
d5396421 308 ret = log_pc(pci, t, 'D');
d0ca268b
JA
309 break;
310 case __BLK_TA_COMPLETE:
d5396421 311 log_pc(pci, t, 'C');
d0ca268b
JA
312 break;
313 default:
314 fprintf(stderr, "Bad pc action %x\n", t->action);
87b72777
JA
315 ret = 1;
316 break;
d0ca268b
JA
317 }
318
87b72777 319 return ret;
d0ca268b
JA
320}
321
d5396421 322static void dump_trace_fs(struct blk_io_trace *t, struct per_cpu_info *pci)
d0ca268b
JA
323{
324 int w = t->action & BLK_TC_ACT(BLK_TC_WRITE);
325
326 switch (t->action & 0xffff) {
327 case __BLK_TA_QUEUE:
d5396421
JA
328 account_q(pci, w, t->bytes);
329 log_queue(pci, t, 'Q');
d0ca268b
JA
330 break;
331 case __BLK_TA_BACKMERGE:
d5396421
JA
332 account_m(pci, w, t->bytes);
333 log_merge(pci, t, 'M');
d0ca268b
JA
334 break;
335 case __BLK_TA_FRONTMERGE:
d5396421
JA
336 account_m(pci, w, t->bytes);
337 log_merge(pci, t, 'F');
d0ca268b
JA
338 break;
339 case __BLK_TA_GETRQ:
d5396421 340 log_generic(pci, t, 'G');
d0ca268b
JA
341 break;
342 case __BLK_TA_SLEEPRQ:
d5396421 343 log_generic(pci, t, 'S');
d0ca268b
JA
344 break;
345 case __BLK_TA_REQUEUE:
d5396421
JA
346 account_c(pci, w, -t->bytes);
347 log_queue(pci, t, 'R');
d0ca268b
JA
348 break;
349 case __BLK_TA_ISSUE:
d5396421
JA
350 account_i(pci, w, t->bytes);
351 log_issue(pci, t, 'D');
d0ca268b
JA
352 break;
353 case __BLK_TA_COMPLETE:
d5396421
JA
354 account_c(pci, w, t->bytes);
355 log_complete(pci, t, 'C');
d0ca268b
JA
356 break;
357 default:
358 fprintf(stderr, "Bad fs action %x\n", t->action);
1f79c4a0 359 break;
d0ca268b 360 }
d0ca268b
JA
361}
362
d5396421 363static int dump_trace(struct blk_io_trace *t, struct per_cpu_info *pci)
d0ca268b 364{
87b72777
JA
365 int ret = 0;
366
33b56019
JA
367 if (output_name && !pci->ofp) {
368 snprintf(pci->ofname, sizeof(pci->ofname) - 1,
369 "%s_log.%d", output_name, pci->cpu);
370
371 pci->ofp = fopen(pci->ofname, "w");
372 if (pci->ofp == NULL) {
373 perror(pci->ofname);
374 return 1;
375 }
376 }
377
d0ca268b 378 if (t->action & BLK_TC_ACT(BLK_TC_PC))
d5396421 379 ret = dump_trace_pc(t, pci);
d0ca268b 380 else
d5396421 381 dump_trace_fs(t, pci);
87b72777
JA
382
383 events++;
384 return ret;
d0ca268b
JA
385}
386
d5396421 387static void dump_pci_stats(struct per_cpu_info *pci)
5c017e4b 388{
0a6b8fc4
NS
389 printf(" Reads Queued: %'8lu, %'8LuKiB\t", pci->qreads, pci->qread_kb);
390 printf(" Writes Queued: %'8lu, %'8LuKiB\n", pci->qwrites,pci->qwrite_kb);
391
392 printf(" Read Dispatches: %'8lu, %'8LuKiB\t", pci->ireads, pci->iread_kb);
393 printf(" Write Dispatches: %'8lu, %'8LuKiB\n", pci->iwrites,pci->iwrite_kb);
394 printf(" Reads Completed: %'8lu, %'8LuKiB\t", pci->creads, pci->cread_kb);
395 printf(" Writes Completed: %'8lu, %'8LuKiB\n", pci->cwrites,pci->cwrite_kb);
396 printf(" Read Merges: %'8lu%8c\t", pci->mreads, ' ');
397
398 printf(" Write Merges: %'8lu\n", pci->mwrites);
5c017e4b
JA
399}
400
d5396421 401static void show_stats(void)
d0ca268b 402{
d5396421 403 struct per_cpu_info foo, *pci;
412819ce 404 int i, pci_events = 0;
5c017e4b
JA
405
406 memset(&foo, 0, sizeof(foo));
d0ca268b 407
a718bd37 408 for (i = 0; i < max_cpus; i++) {
d5396421 409 pci = &per_cpu_info[i];
5c017e4b 410
d5396421 411 if (!pci->nelems)
afd2d7ad 412 continue;
413
d5396421
JA
414 foo.qreads += pci->qreads;
415 foo.qwrites += pci->qwrites;
416 foo.creads += pci->creads;
417 foo.cwrites += pci->cwrites;
418 foo.mreads += pci->mreads;
419 foo.mwrites += pci->mwrites;
420 foo.qread_kb += pci->qread_kb;
421 foo.qwrite_kb += pci->qwrite_kb;
422 foo.cread_kb += pci->cread_kb;
423 foo.cwrite_kb += pci->cwrite_kb;
5c017e4b
JA
424
425 printf("CPU%d:\n", i);
d5396421 426 dump_pci_stats(pci);
412819ce 427 pci_events++;
5c017e4b
JA
428 }
429
412819ce 430 if (pci_events > 1) {
5c017e4b 431 printf("Total:\n");
d5396421 432 dump_pci_stats(&foo);
5c017e4b 433 }
d0ca268b
JA
434
435 printf("Events: %'Lu\n", events);
d0ca268b
JA
436}
437
3aabcd89 438static inline int trace_rb_insert(struct trace *t)
8fc0abbc
JA
439{
440 struct rb_node **p = &rb_root.rb_node;
441 struct rb_node *parent = NULL;
442 struct trace *__t;
443
444 while (*p) {
445 parent = *p;
446 __t = rb_entry(parent, struct trace, rb_node);
447
448 if (t->bit->sequence < __t->bit->sequence)
449 p = &(*p)->rb_left;
450 else if (t->bit->sequence > __t->bit->sequence)
451 p = &(*p)->rb_right;
452 else {
87b72777 453 fprintf(stderr, "sequence alias!\n");
8fc0abbc
JA
454 return 1;
455 }
456 }
457
458 rb_link_node(&t->rb_node, parent, p);
459 rb_insert_color(&t->rb_node, &rb_root);
460 return 0;
461}
462
412819ce 463static int sort_entries(void *traces, unsigned long offset, int nr)
8fc0abbc 464{
412819ce 465 struct per_cpu_info *pci;
8fc0abbc
JA
466 struct blk_io_trace *bit;
467 struct trace *t;
468 void *start = traces;
469 int nelems = 0;
470
6fe4709e 471 while (traces - start <= offset - sizeof(*bit)) {
412819ce
JA
472 if (!nr)
473 break;
474
8fc0abbc 475 bit = traces;
6fe4709e 476
8fc0abbc
JA
477 t = malloc(sizeof(*t));
478 t->bit = bit;
479 memset(&t->rb_node, 0, sizeof(t->rb_node));
480
6fe4709e
JA
481 trace_to_cpu(bit);
482
66fa7233
JA
483 if (verify_trace(bit))
484 break;
485
a718bd37 486 pci = get_cpu_info(bit->cpu);
412819ce
JA
487 pci->nelems++;
488
8fc0abbc
JA
489 if (trace_rb_insert(t))
490 return -1;
491
492 traces += sizeof(*bit) + bit->pdu_len;
493 nelems++;
412819ce 494 nr--;
6fe4709e 495 }
8fc0abbc
JA
496
497 return nelems;
498}
499
412819ce
JA
500static void free_entries_rb(void)
501{
502 struct rb_node *n;
503
504 while ((n = rb_first(&rb_root)) != NULL) {
505 struct trace *t = rb_entry(n, struct trace, rb_node);
506
507 rb_erase(&t->rb_node, &rb_root);
508 free(t);
509 }
510}
511
d5396421 512static void show_entries_rb(void)
8fc0abbc 513{
8fc0abbc 514 struct blk_io_trace *bit;
3aabcd89 515 struct rb_node *n;
8fc0abbc
JA
516 struct trace *t;
517 int cpu;
518
3aabcd89
JA
519 n = rb_first(&rb_root);
520 if (!n)
521 return;
8fc0abbc 522
3aabcd89 523 do {
8fc0abbc
JA
524 t = rb_entry(n, struct trace, rb_node);
525 bit = t->bit;
526
d5396421 527 cpu = bit->cpu;
87b72777 528 if (cpu > max_cpus) {
8fc0abbc 529 fprintf(stderr, "CPU number too large (%d)\n", cpu);
87b72777 530 break;
8fc0abbc
JA
531 }
532
cfab07eb
AB
533 if (genesis_time == 0)
534 genesis_time = bit->time;
535 bit->time -= genesis_time;
8fc0abbc 536
cfab07eb 537 check_time(bit);
8fc0abbc 538
d5396421 539 if (dump_trace(bit, &per_cpu_info[cpu]))
87b72777
JA
540 break;
541
8fc0abbc
JA
542 } while ((n = rb_next(n)) != NULL);
543}
544
1f79c4a0
JA
545static int read_data(int fd, void *buffer, int bytes, int block)
546{
547 int ret, bytes_left, fl;
548 void *p;
549
550 fl = fcntl(fd, F_GETFL);
551
552 if (!block)
553 fcntl(fd, F_SETFL, fl | O_NONBLOCK);
554 else
555 fcntl(fd, F_SETFL, fl & ~O_NONBLOCK);
556
557 bytes_left = bytes;
558 p = buffer;
559 while (bytes_left > 0) {
560 ret = read(fd, p, bytes_left);
561 if (!ret)
562 return 1;
563 else if (ret < 0) {
564 if (errno != EAGAIN)
565 perror("read");
566 return -1;
567 } else {
568 p += ret;
569 bytes_left -= ret;
570 }
571 }
572
573 return 0;
574}
575
d5396421 576static int do_file(void)
d0ca268b 577{
a718bd37 578 int i, nfiles;
d0ca268b 579
a718bd37
NS
580 for (i = 0, nfiles = 0;; i++, nfiles++) {
581 struct per_cpu_info *pci;
87b72777
JA
582 struct stat st;
583 void *tb;
584
a718bd37 585 pci = get_cpu_info(i);
d5396421 586 pci->ofp = NULL;
d0ca268b 587
d5396421
JA
588 snprintf(pci->fname, sizeof(pci->fname)-1,"%s_out.%d", dev, i);
589 if (stat(pci->fname, &st) < 0)
d0ca268b 590 break;
afd2d7ad 591 if (!st.st_size)
592 continue;
d0ca268b 593
d5396421 594 printf("Processing %s\n", pci->fname);
8fc0abbc 595
87b72777 596 tb = malloc(st.st_size);
8fc0abbc 597
d5396421
JA
598 pci->fd = open(pci->fname, O_RDONLY);
599 if (pci->fd < 0) {
600 perror(pci->fname);
3aabcd89 601 break;
d0ca268b 602 }
afd2d7ad 603
1f79c4a0 604 if (read_data(pci->fd, tb, st.st_size, 1))
3aabcd89 605 break;
d0ca268b 606
a718bd37 607 if (sort_entries(tb, st.st_size, ~0U) == -1)
3aabcd89 608 break;
d0ca268b 609
d5396421 610 close(pci->fd);
d5396421
JA
611 printf("\t%2d %10s %15d\n", i, pci->fname, pci->nelems);
612
613 }
614
615 if (!nfiles) {
616 fprintf(stderr, "No files found\n");
617 return 1;
618 }
619
620 show_entries_rb();
d5396421
JA
621 return 0;
622}
623
412819ce 624static void resize_buffer(void **buffer, long *old_size)
d5396421 625{
412819ce 626 long cur_size = *old_size;
d5396421
JA
627 void *ptr;
628
412819ce
JA
629 *old_size *= 2;
630 ptr = malloc(*old_size);
631 memcpy(ptr, *buffer, cur_size);
632 free(*buffer);
633 *buffer = ptr;
634}
d5396421 635
412819ce
JA
636static int read_sort_events(int fd, void **buffer)
637{
638 long offset, max_offset;
639 int events;
d5396421 640
412819ce
JA
641 max_offset = 128 * sizeof(struct blk_io_trace);
642 *buffer = malloc(max_offset);
643 events = 0;
644 offset = 0;
d5396421 645
412819ce
JA
646 do {
647 struct blk_io_trace *t;
648 int pdu_len;
d5396421 649
412819ce
JA
650 if (max_offset - offset < sizeof(*t))
651 resize_buffer(buffer, &max_offset);
d5396421 652
412819ce
JA
653 if (read_data(fd, *buffer + offset, sizeof(*t), !events)) {
654 if (events)
d5396421 655 break;
412819ce
JA
656
657 usleep(1000);
658 continue;
d5396421
JA
659 }
660
412819ce
JA
661 t = *buffer + offset;
662 offset += sizeof(*t);
d5396421 663
412819ce 664 pdu_len = be16_to_cpu(t->pdu_len);
d5396421 665
412819ce
JA
666 if (max_offset - offset < pdu_len)
667 resize_buffer(buffer, &max_offset);
d5396421 668
412819ce
JA
669 if (read_data(fd, *buffer + offset, pdu_len, 1))
670 break;
d5396421 671
412819ce
JA
672 offset += pdu_len;
673 events++;
674 } while (!is_done());
d5396421 675
412819ce
JA
676 return events;
677}
d5396421 678
412819ce
JA
679static int do_stdin(void)
680{
681 int fd;
682 void *ptr;
d5396421 683
1f79c4a0 684 fd = dup(STDIN_FILENO);
412819ce
JA
685 do {
686 int events;
d5396421 687
412819ce
JA
688 events = read_sort_events(fd, &ptr);
689 if (!events)
690 break;
691
692 sort_entries(ptr, ~0UL, events);
693 show_entries_rb();
694 free_entries_rb();
d5396421
JA
695 } while (1);
696
697 close(fd);
698 free(ptr);
d5396421
JA
699 return 0;
700}
d0ca268b 701
1f79c4a0 702static void flush_output(void)
412819ce
JA
703{
704 int i;
705
a718bd37 706 for (i = 0; i < max_cpus; i++) {
412819ce
JA
707 struct per_cpu_info *pci = &per_cpu_info[i];
708
709 if (pci->ofp) {
710 fflush(pci->ofp);
711 fclose(pci->ofp);
712 pci->ofp = NULL;
713 }
714 }
715}
716
1f79c4a0 717static void handle_sigint(int sig)
412819ce
JA
718{
719 done = 1;
720 flush_output();
721}
722
1f79c4a0
JA
723static void usage(char *prog)
724{
725 fprintf(stderr, "Usage: %s -i <name> [-o <output>]\n", prog);
726}
727
d5396421
JA
728int main(int argc, char *argv[])
729{
412819ce 730 int c, ret;
d5396421
JA
731
732 while ((c = getopt_long(argc, argv, S_OPTS, l_opts, NULL)) != -1) {
733 switch (c) {
734 case 'i':
735 dev = strdup(optarg);
736 break;
737 case 'o':
738 output_name = strdup(optarg);
739 break;
740 default:
1f79c4a0 741 usage(argv[0]);
d5396421
JA
742 return 1;
743 }
d0ca268b
JA
744 }
745
d5396421 746 if (!dev) {
1f79c4a0 747 usage(argv[0]);
d5396421
JA
748 return 1;
749 }
750
412819ce
JA
751 memset(&rb_root, 0, sizeof(rb_root));
752
753 signal(SIGINT, handle_sigint);
754 signal(SIGHUP, handle_sigint);
755 signal(SIGTERM, handle_sigint);
d5396421
JA
756
757 if (!strcmp(dev, "-"))
758 ret = do_stdin();
759 else
760 ret = do_file();
761
412819ce
JA
762 show_stats();
763 flush_output();
d5396421 764 return ret;
d0ca268b 765}