diff options
Diffstat (limited to 'kernel/trace/trace_events.c')
| -rw-r--r-- | kernel/trace/trace_events.c | 81 |
1 files changed, 42 insertions, 39 deletions
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 189b09baf4fb..3f972ad98d04 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c | |||
| @@ -60,10 +60,8 @@ int trace_define_field(struct ftrace_event_call *call, const char *type, | |||
| 60 | return 0; | 60 | return 0; |
| 61 | 61 | ||
| 62 | err: | 62 | err: |
| 63 | if (field) { | 63 | if (field) |
| 64 | kfree(field->name); | 64 | kfree(field->name); |
| 65 | kfree(field->type); | ||
| 66 | } | ||
| 67 | kfree(field); | 65 | kfree(field); |
| 68 | 66 | ||
| 69 | return -ENOMEM; | 67 | return -ENOMEM; |
| @@ -520,41 +518,16 @@ out: | |||
| 520 | return ret; | 518 | return ret; |
| 521 | } | 519 | } |
| 522 | 520 | ||
| 523 | extern char *__bad_type_size(void); | ||
| 524 | |||
| 525 | #undef FIELD | ||
| 526 | #define FIELD(type, name) \ | ||
| 527 | sizeof(type) != sizeof(field.name) ? __bad_type_size() : \ | ||
| 528 | #type, "common_" #name, offsetof(typeof(field), name), \ | ||
| 529 | sizeof(field.name), is_signed_type(type) | ||
| 530 | |||
| 531 | static int trace_write_header(struct trace_seq *s) | ||
| 532 | { | ||
| 533 | struct trace_entry field; | ||
| 534 | |||
| 535 | /* struct trace_entry */ | ||
| 536 | return trace_seq_printf(s, | ||
| 537 | "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\tsigned:%u;\n" | ||
| 538 | "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\tsigned:%u;\n" | ||
| 539 | "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\tsigned:%u;\n" | ||
| 540 | "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\tsigned:%u;\n" | ||
| 541 | "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\tsigned:%u;\n" | ||
| 542 | "\n", | ||
| 543 | FIELD(unsigned short, type), | ||
| 544 | FIELD(unsigned char, flags), | ||
| 545 | FIELD(unsigned char, preempt_count), | ||
| 546 | FIELD(int, pid), | ||
| 547 | FIELD(int, lock_depth)); | ||
| 548 | } | ||
| 549 | |||
| 550 | static ssize_t | 521 | static ssize_t |
| 551 | event_format_read(struct file *filp, char __user *ubuf, size_t cnt, | 522 | event_format_read(struct file *filp, char __user *ubuf, size_t cnt, |
| 552 | loff_t *ppos) | 523 | loff_t *ppos) |
| 553 | { | 524 | { |
| 554 | struct ftrace_event_call *call = filp->private_data; | 525 | struct ftrace_event_call *call = filp->private_data; |
| 526 | struct ftrace_event_field *field; | ||
| 555 | struct trace_seq *s; | 527 | struct trace_seq *s; |
| 528 | int common_field_count = 5; | ||
| 556 | char *buf; | 529 | char *buf; |
| 557 | int r; | 530 | int r = 0; |
| 558 | 531 | ||
| 559 | if (*ppos) | 532 | if (*ppos) |
| 560 | return 0; | 533 | return 0; |
| @@ -565,14 +538,48 @@ event_format_read(struct file *filp, char __user *ubuf, size_t cnt, | |||
| 565 | 538 | ||
| 566 | trace_seq_init(s); | 539 | trace_seq_init(s); |
| 567 | 540 | ||
| 568 | /* If any of the first writes fail, so will the show_format. */ | ||
| 569 | |||
| 570 | trace_seq_printf(s, "name: %s\n", call->name); | 541 | trace_seq_printf(s, "name: %s\n", call->name); |
| 571 | trace_seq_printf(s, "ID: %d\n", call->id); | 542 | trace_seq_printf(s, "ID: %d\n", call->id); |
| 572 | trace_seq_printf(s, "format:\n"); | 543 | trace_seq_printf(s, "format:\n"); |
| 573 | trace_write_header(s); | ||
| 574 | 544 | ||
| 575 | r = call->show_format(call, s); | 545 | list_for_each_entry_reverse(field, &call->fields, link) { |
| 546 | /* | ||
| 547 | * Smartly shows the array type(except dynamic array). | ||
| 548 | * Normal: | ||
| 549 | * field:TYPE VAR | ||
| 550 | * If TYPE := TYPE[LEN], it is shown: | ||
| 551 | * field:TYPE VAR[LEN] | ||
| 552 | */ | ||
| 553 | const char *array_descriptor = strchr(field->type, '['); | ||
| 554 | |||
| 555 | if (!strncmp(field->type, "__data_loc", 10)) | ||
| 556 | array_descriptor = NULL; | ||
| 557 | |||
| 558 | if (!array_descriptor) { | ||
| 559 | r = trace_seq_printf(s, "\tfield:%s %s;\toffset:%u;" | ||
| 560 | "\tsize:%u;\tsigned:%d;\n", | ||
| 561 | field->type, field->name, field->offset, | ||
| 562 | field->size, !!field->is_signed); | ||
| 563 | } else { | ||
| 564 | r = trace_seq_printf(s, "\tfield:%.*s %s%s;\toffset:%u;" | ||
| 565 | "\tsize:%u;\tsigned:%d;\n", | ||
| 566 | (int)(array_descriptor - field->type), | ||
| 567 | field->type, field->name, | ||
| 568 | array_descriptor, field->offset, | ||
| 569 | field->size, !!field->is_signed); | ||
| 570 | } | ||
| 571 | |||
| 572 | if (--common_field_count == 0) | ||
| 573 | r = trace_seq_printf(s, "\n"); | ||
| 574 | |||
| 575 | if (!r) | ||
| 576 | break; | ||
| 577 | } | ||
| 578 | |||
| 579 | if (r) | ||
| 580 | r = trace_seq_printf(s, "\nprint fmt: %s\n", | ||
| 581 | call->print_fmt); | ||
| 582 | |||
| 576 | if (!r) { | 583 | if (!r) { |
| 577 | /* | 584 | /* |
| 578 | * ug! The format output is bigger than a PAGE!! | 585 | * ug! The format output is bigger than a PAGE!! |
| @@ -948,10 +955,6 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events, | |||
| 948 | filter); | 955 | filter); |
| 949 | } | 956 | } |
| 950 | 957 | ||
| 951 | /* A trace may not want to export its format */ | ||
| 952 | if (!call->show_format) | ||
| 953 | return 0; | ||
| 954 | |||
| 955 | trace_create_file("format", 0444, call->dir, call, | 958 | trace_create_file("format", 0444, call->dir, call, |
| 956 | format); | 959 | format); |
| 957 | 960 | ||
