diff options
| author | Steven Rostedt <srostedt@redhat.com> | 2009-11-20 23:00:00 -0500 |
|---|---|---|
| committer | Steven Rostedt <rostedt@goodmis.org> | 2009-11-20 23:00:00 -0500 |
| commit | 157dbbfa9aaad08ead9075930d4e5adcc574df53 (patch) | |
| tree | b8d69f5525dc5400ec562e11e3fb2ca862dd985f | |
| parent | 0ad6fbb6cb5e6c91adad4a977e1fae786c0ebe02 (diff) | |
Handle old format
Update to read the old file format for 2.6.30. It is very limited,
but can process a little.
Unfortunately, the printk_formats file is broken for 2.6.30.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
| -rw-r--r-- | parse-events.c | 13 | ||||
| -rw-r--r-- | parse-events.h | 2 | ||||
| -rw-r--r-- | trace-cmd.c | 64 | ||||
| -rw-r--r-- | trace-read.c | 95 |
4 files changed, 169 insertions, 5 deletions
diff --git a/parse-events.c b/parse-events.c index cbd9773..4e48faa 100644 --- a/parse-events.c +++ b/parse-events.c | |||
| @@ -40,6 +40,8 @@ int header_page_data_size; | |||
| 40 | 40 | ||
| 41 | int latency_format; | 41 | int latency_format; |
| 42 | 42 | ||
| 43 | int old_format; | ||
| 44 | |||
| 43 | static char *input_buf; | 45 | static char *input_buf; |
| 44 | static unsigned long long input_buf_ptr; | 46 | static unsigned long long input_buf_ptr; |
| 45 | static unsigned long long input_buf_siz; | 47 | static unsigned long long input_buf_siz; |
| @@ -3140,6 +3142,17 @@ static void parse_header_field(const char *field, | |||
| 3140 | 3142 | ||
| 3141 | int parse_header_page(char *buf, unsigned long size) | 3143 | int parse_header_page(char *buf, unsigned long size) |
| 3142 | { | 3144 | { |
| 3145 | if (!size) { | ||
| 3146 | /* | ||
| 3147 | * Old kernels did not have header page info. | ||
| 3148 | * Sorry but we just use what we find here in user space. | ||
| 3149 | */ | ||
| 3150 | header_page_ts_size = sizeof(long long); | ||
| 3151 | header_page_size_size = sizeof(long); | ||
| 3152 | header_page_data_offset = sizeof(long long) + sizeof(long); | ||
| 3153 | old_format = 1; | ||
| 3154 | return 0; | ||
| 3155 | } | ||
| 3143 | init_input_buf(buf, size); | 3156 | init_input_buf(buf, size); |
| 3144 | 3157 | ||
| 3145 | parse_header_field("timestamp", &header_page_ts_offset, | 3158 | parse_header_field("timestamp", &header_page_ts_offset, |
diff --git a/parse-events.h b/parse-events.h index 740da6c..4858a52 100644 --- a/parse-events.h +++ b/parse-events.h | |||
| @@ -163,6 +163,8 @@ struct record { | |||
| 163 | struct record *trace_peek_data(int cpu); | 163 | struct record *trace_peek_data(int cpu); |
| 164 | struct record *trace_read_data(int cpu); | 164 | struct record *trace_read_data(int cpu); |
| 165 | 165 | ||
| 166 | extern int old_format; | ||
| 167 | |||
| 166 | void parse_set_info(int nr_cpus, int long_sz); | 168 | void parse_set_info(int nr_cpus, int long_sz); |
| 167 | 169 | ||
| 168 | void trace_report(int argc, char **argv); | 170 | void trace_report(int argc, char **argv); |
diff --git a/trace-cmd.c b/trace-cmd.c index 9e69aee..2a531bb 100644 --- a/trace-cmd.c +++ b/trace-cmd.c | |||
| @@ -421,6 +421,7 @@ static void set_option(const char *option) | |||
| 421 | 421 | ||
| 422 | static void enable_event(const char *name) | 422 | static void enable_event(const char *name) |
| 423 | { | 423 | { |
| 424 | struct stat st; | ||
| 424 | FILE *fp; | 425 | FILE *fp; |
| 425 | char *path; | 426 | char *path; |
| 426 | int ret; | 427 | int ret; |
| @@ -428,6 +429,21 @@ static void enable_event(const char *name) | |||
| 428 | fprintf(stderr, "enable %s\n", name); | 429 | fprintf(stderr, "enable %s\n", name); |
| 429 | if (strcmp(name, "all") == 0) { | 430 | if (strcmp(name, "all") == 0) { |
| 430 | path = get_tracing_file("events/enable"); | 431 | path = get_tracing_file("events/enable"); |
| 432 | |||
| 433 | ret = stat(path, &st); | ||
| 434 | if (ret < 0) { | ||
| 435 | put_tracing_file(path); | ||
| 436 | /* need to use old way */ | ||
| 437 | path = get_tracing_file("set_event"); | ||
| 438 | fp = fopen(path, "w"); | ||
| 439 | if (!fp) | ||
| 440 | die("writing to '%s'", path); | ||
| 441 | put_tracing_file(path); | ||
| 442 | fwrite("*:*\n", 4, 1, fp); | ||
| 443 | fclose(fp); | ||
| 444 | return; | ||
| 445 | } | ||
| 446 | |||
| 431 | fp = fopen(path, "w"); | 447 | fp = fopen(path, "w"); |
| 432 | if (!fp) | 448 | if (!fp) |
| 433 | die("writing to '%s'", path); | 449 | die("writing to '%s'", path); |
| @@ -455,11 +471,28 @@ static void enable_event(const char *name) | |||
| 455 | 471 | ||
| 456 | static void disable_event(const char *name) | 472 | static void disable_event(const char *name) |
| 457 | { | 473 | { |
| 474 | struct stat st; | ||
| 458 | FILE *fp; | 475 | FILE *fp; |
| 459 | char *path; | 476 | char *path; |
| 477 | int ret; | ||
| 460 | 478 | ||
| 461 | if (strcmp(name, "all") == 0) { | 479 | if (strcmp(name, "all") == 0) { |
| 462 | path = get_tracing_file("events/enable"); | 480 | path = get_tracing_file("events/enable"); |
| 481 | |||
| 482 | ret = stat(path, &st); | ||
| 483 | if (ret < 0) { | ||
| 484 | put_tracing_file(path); | ||
| 485 | /* need to use old way */ | ||
| 486 | path = get_tracing_file("set_event"); | ||
| 487 | fp = fopen(path, "w"); | ||
| 488 | if (!fp) | ||
| 489 | die("writing to '%s'", path); | ||
| 490 | put_tracing_file(path); | ||
| 491 | fwrite("\n", 1, 1, fp); | ||
| 492 | fclose(fp); | ||
| 493 | return; | ||
| 494 | } | ||
| 495 | |||
| 463 | fp = fopen(path, "w"); | 496 | fp = fopen(path, "w"); |
| 464 | if (!fp) | 497 | if (!fp) |
| 465 | die("writing to '%s'", path); | 498 | die("writing to '%s'", path); |
| @@ -750,10 +783,25 @@ static unsigned long get_size(const char *file) | |||
| 750 | static void read_header_files(void) | 783 | static void read_header_files(void) |
| 751 | { | 784 | { |
| 752 | unsigned long long size, check_size; | 785 | unsigned long long size, check_size; |
| 786 | struct stat st; | ||
| 753 | char *path; | 787 | char *path; |
| 754 | int fd; | 788 | int fd; |
| 789 | int ret; | ||
| 755 | 790 | ||
| 756 | path = get_tracing_file("events/header_page"); | 791 | path = get_tracing_file("events/header_page"); |
| 792 | |||
| 793 | ret = stat(path, &st); | ||
| 794 | if (ret < 0) { | ||
| 795 | /* old style did not show this info, just add zero */ | ||
| 796 | put_tracing_file(path); | ||
| 797 | write_or_die("header_page", 12); | ||
| 798 | size = 0; | ||
| 799 | write_or_die(&size, 8); | ||
| 800 | write_or_die("header_event", 13); | ||
| 801 | write_or_die(&size, 8); | ||
| 802 | return; | ||
| 803 | } | ||
| 804 | |||
| 757 | fd = open(path, O_RDONLY); | 805 | fd = open(path, O_RDONLY); |
| 758 | if (fd < 0) | 806 | if (fd < 0) |
| 759 | die("can't read '%s'", path); | 807 | die("can't read '%s'", path); |
| @@ -1029,11 +1077,17 @@ static void read_thread_data(void) | |||
| 1029 | * Save the command lines; | 1077 | * Save the command lines; |
| 1030 | */ | 1078 | */ |
| 1031 | file = get_tracing_file("saved_cmdlines"); | 1079 | file = get_tracing_file("saved_cmdlines"); |
| 1032 | size = get_size(file); | 1080 | ret = stat(file, &st); |
| 1033 | write_or_die(&size, 8); | 1081 | if (ret >= 0) { |
| 1034 | check_size = copy_file(file); | 1082 | size = get_size(file); |
| 1035 | if (size != check_size) | 1083 | write_or_die(&size, 8); |
| 1036 | die("error in size of file '%s'", file); | 1084 | check_size = copy_file(file); |
| 1085 | if (size != check_size) | ||
| 1086 | die("error in size of file '%s'", file); | ||
| 1087 | } else { | ||
| 1088 | size = 0; | ||
| 1089 | write_or_die(&size, 8); | ||
| 1090 | } | ||
| 1037 | put_tracing_file(file); | 1091 | put_tracing_file(file); |
| 1038 | 1092 | ||
| 1039 | write_or_die(&cpu_count, 4); | 1093 | write_or_die(&cpu_count, 4); |
diff --git a/trace-read.c b/trace-read.c index 79530bc..4b6d522 100644 --- a/trace-read.c +++ b/trace-read.c | |||
| @@ -369,6 +369,22 @@ static void get_next_page(int cpu) | |||
| 369 | cpu, cpu_data[cpu].offset); | 369 | cpu, cpu_data[cpu].offset); |
| 370 | } | 370 | } |
| 371 | 371 | ||
| 372 | static unsigned int type4host(unsigned int type_len_ts) | ||
| 373 | { | ||
| 374 | if (file_bigendian) | ||
| 375 | return (type_len_ts >> 29) & 3; | ||
| 376 | else | ||
| 377 | return type_len_ts & 3; | ||
| 378 | } | ||
| 379 | |||
| 380 | static unsigned int len4host(unsigned int type_len_ts) | ||
| 381 | { | ||
| 382 | if (file_bigendian) | ||
| 383 | return (type_len_ts >> 27) & 7; | ||
| 384 | else | ||
| 385 | return (type_len_ts >> 2) & 7; | ||
| 386 | } | ||
| 387 | |||
| 372 | static unsigned int type_len4host(unsigned int type_len_ts) | 388 | static unsigned int type_len4host(unsigned int type_len_ts) |
| 373 | { | 389 | { |
| 374 | if (file_bigendian) | 390 | if (file_bigendian) |
| @@ -389,6 +405,74 @@ static int calc_index(void *ptr, int cpu) | |||
| 389 | { | 405 | { |
| 390 | return (unsigned long)ptr - (unsigned long)cpu_data[cpu].page; | 406 | return (unsigned long)ptr - (unsigned long)cpu_data[cpu].page; |
| 391 | } | 407 | } |
| 408 | enum old_ring_buffer_type { | ||
| 409 | OLD_RINGBUF_TYPE_PADDING, | ||
| 410 | OLD_RINGBUF_TYPE_TIME_EXTEND, | ||
| 411 | OLD_RINGBUF_TYPE_TIME_STAMP, | ||
| 412 | OLD_RINGBUF_TYPE_DATA, | ||
| 413 | }; | ||
| 414 | |||
| 415 | static struct record *read_old_format(void **ptr, int cpu) | ||
| 416 | { | ||
| 417 | struct record *data; | ||
| 418 | unsigned long long extend; | ||
| 419 | unsigned int type_len_ts; | ||
| 420 | unsigned int type; | ||
| 421 | unsigned int len; | ||
| 422 | unsigned int delta; | ||
| 423 | unsigned int length; | ||
| 424 | |||
| 425 | type_len_ts = data2host4(*ptr); | ||
| 426 | *ptr += 4; | ||
| 427 | |||
| 428 | type = type4host(type_len_ts); | ||
| 429 | len = len4host(type_len_ts); | ||
| 430 | delta = ts4host(type_len_ts); | ||
| 431 | |||
| 432 | switch (type) { | ||
| 433 | case OLD_RINGBUF_TYPE_PADDING: | ||
| 434 | *ptr = (void *)(((unsigned long)*ptr + (page_size - 1)) & | ||
| 435 | ~(page_size - 1)); | ||
| 436 | return NULL; | ||
| 437 | |||
| 438 | case OLD_RINGBUF_TYPE_TIME_EXTEND: | ||
| 439 | extend = data2host4(ptr); | ||
| 440 | extend <<= TS_SHIFT; | ||
| 441 | extend += delta; | ||
| 442 | cpu_data[cpu].timestamp += extend; | ||
| 443 | *ptr += 4; | ||
| 444 | return NULL; | ||
| 445 | |||
| 446 | case OLD_RINGBUF_TYPE_TIME_STAMP: | ||
| 447 | die("should not be here"); | ||
| 448 | break; | ||
| 449 | default: | ||
| 450 | if (len) | ||
| 451 | length = len * 4; | ||
| 452 | else { | ||
| 453 | length = data2host4(*ptr); | ||
| 454 | length -= 4; | ||
| 455 | *ptr += 4; | ||
| 456 | } | ||
| 457 | break; | ||
| 458 | } | ||
| 459 | |||
| 460 | cpu_data[cpu].timestamp += delta; | ||
| 461 | |||
| 462 | data = malloc_or_die(sizeof(*data)); | ||
| 463 | memset(data, 0, sizeof(*data)); | ||
| 464 | |||
| 465 | data->ts = cpu_data[cpu].timestamp; | ||
| 466 | data->size = length; | ||
| 467 | data->data = *ptr; | ||
| 468 | |||
| 469 | *ptr += ((length+3)/4) * 4; | ||
| 470 | |||
| 471 | cpu_data[cpu].index = calc_index(*ptr, cpu); | ||
| 472 | cpu_data[cpu].next = data; | ||
| 473 | |||
| 474 | return data; | ||
| 475 | } | ||
| 392 | 476 | ||
| 393 | struct record *trace_peek_data(int cpu) | 477 | struct record *trace_peek_data(int cpu) |
| 394 | { | 478 | { |
| @@ -437,6 +521,17 @@ read_again: | |||
| 437 | return trace_peek_data(cpu); | 521 | return trace_peek_data(cpu); |
| 438 | } | 522 | } |
| 439 | 523 | ||
| 524 | if (old_format) { | ||
| 525 | data = read_old_format(&ptr, cpu); | ||
| 526 | if (!data) { | ||
| 527 | if (!ptr) | ||
| 528 | return NULL; | ||
| 529 | goto read_again; | ||
| 530 | } | ||
| 531 | |||
| 532 | return data; | ||
| 533 | } | ||
| 534 | |||
| 440 | type_len_ts = data2host4(ptr); | 535 | type_len_ts = data2host4(ptr); |
| 441 | ptr += 4; | 536 | ptr += 4; |
| 442 | 537 | ||
