aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2010-08-16 11:17:30 -0400
committerSteven Rostedt <rostedt@goodmis.org>2010-08-16 11:17:30 -0400
commitd244b6bd41e09ecbb09c738cc2c108be227398c8 (patch)
tree848c6a8a0d6f83929daf43d63e241dc8072066ac /kernel/trace
parentda5cabf80e2433131bf0ed8993abc0f7ea618c73 (diff)
parent1aa54bca6ee0d07ebcafb8ca8074b624d80724aa (diff)
Merge branch 'tip/perf/urgent-3' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-2.6-trace into trace/tip/perf/urgent-4
Conflicts: kernel/trace/trace_events.c Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace')
-rw-r--r--kernel/trace/ring_buffer.c3
-rw-r--r--kernel/trace/trace.c11
-rw-r--r--kernel/trace/trace_events.c207
-rw-r--r--kernel/trace/trace_functions_graph.c10
4 files changed, 163 insertions, 68 deletions
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 3632ce87674f..19cccc3c3028 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -3846,6 +3846,9 @@ int ring_buffer_read_page(struct ring_buffer *buffer,
3846 rpos = reader->read; 3846 rpos = reader->read;
3847 pos += size; 3847 pos += size;
3848 3848
3849 if (rpos >= commit)
3850 break;
3851
3849 event = rb_reader_event(cpu_buffer); 3852 event = rb_reader_event(cpu_buffer);
3850 size = rb_event_length(event); 3853 size = rb_event_length(event);
3851 } while (len > size); 3854 } while (len > size);
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index ba14a22be4cc..9ec59f541156 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -3463,6 +3463,7 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
3463 size_t cnt, loff_t *fpos) 3463 size_t cnt, loff_t *fpos)
3464{ 3464{
3465 char *buf; 3465 char *buf;
3466 size_t written;
3466 3467
3467 if (tracing_disabled) 3468 if (tracing_disabled)
3468 return -EINVAL; 3469 return -EINVAL;
@@ -3484,11 +3485,15 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
3484 } else 3485 } else
3485 buf[cnt] = '\0'; 3486 buf[cnt] = '\0';
3486 3487
3487 cnt = mark_printk("%s", buf); 3488 written = mark_printk("%s", buf);
3488 kfree(buf); 3489 kfree(buf);
3489 *fpos += cnt; 3490 *fpos += written;
3490 3491
3491 return cnt; 3492 /* don't tell userspace we wrote more - it might confuse them */
3493 if (written > cnt)
3494 written = cnt;
3495
3496 return written;
3492} 3497}
3493 3498
3494static int tracing_clock_show(struct seq_file *m, void *v) 3499static int tracing_clock_show(struct seq_file *m, void *v)
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 09b4fa6e4d3b..4c758f146328 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -598,88 +598,165 @@ out:
598 return ret; 598 return ret;
599} 599}
600 600
601static void print_event_fields(struct trace_seq *s, struct list_head *head) 601enum {
602 FORMAT_HEADER = 1,
603 FORMAT_PRINTFMT = 2,
604};
605
606static void *f_next(struct seq_file *m, void *v, loff_t *pos)
602{ 607{
608 struct ftrace_event_call *call = m->private;
603 struct ftrace_event_field *field; 609 struct ftrace_event_field *field;
610 struct list_head *head;
604 611
605 list_for_each_entry_reverse(field, head, link) { 612 (*pos)++;
606 /*
607 * Smartly shows the array type(except dynamic array).
608 * Normal:
609 * field:TYPE VAR
610 * If TYPE := TYPE[LEN], it is shown:
611 * field:TYPE VAR[LEN]
612 */
613 const char *array_descriptor = strchr(field->type, '[');
614 613
615 if (!strncmp(field->type, "__data_loc", 10)) 614 switch ((unsigned long)v) {
616 array_descriptor = NULL; 615 case FORMAT_HEADER:
616 head = &ftrace_common_fields;
617 617
618 if (!array_descriptor) { 618 if (unlikely(list_empty(head)))
619 trace_seq_printf(s, "\tfield:%s %s;\toffset:%u;" 619 return NULL;
620 "\tsize:%u;\tsigned:%d;\n", 620
621 field->type, field->name, field->offset, 621 field = list_entry(head->prev, struct ftrace_event_field, link);
622 field->size, !!field->is_signed); 622 return field;
623 } else { 623
624 trace_seq_printf(s, "\tfield:%.*s %s%s;\toffset:%u;" 624 case FORMAT_PRINTFMT:
625 "\tsize:%u;\tsigned:%d;\n", 625 /* all done */
626 (int)(array_descriptor - field->type), 626 return NULL;
627 field->type, field->name, 627 }
628 array_descriptor, field->offset, 628
629 field->size, !!field->is_signed); 629 head = trace_get_fields(call);
630 } 630
631 /*
632 * To separate common fields from event fields, the
633 * LSB is set on the first event field. Clear it in case.
634 */
635 v = (void *)((unsigned long)v & ~1L);
636
637 field = v;
638 /*
639 * If this is a common field, and at the end of the list, then
640 * continue with main list.
641 */
642 if (field->link.prev == &ftrace_common_fields) {
643 if (unlikely(list_empty(head)))
644 return NULL;
645 field = list_entry(head->prev, struct ftrace_event_field, link);
646 /* Set the LSB to notify f_show to print an extra newline */
647 field = (struct ftrace_event_field *)
648 ((unsigned long)field | 1);
649 return field;
631 } 650 }
651
652 /* If we are done tell f_show to print the format */
653 if (field->link.prev == head)
654 return (void *)FORMAT_PRINTFMT;
655
656 field = list_entry(field->link.prev, struct ftrace_event_field, link);
657
658 return field;
632} 659}
633 660
634static ssize_t 661static void *f_start(struct seq_file *m, loff_t *pos)
635event_format_read(struct file *filp, char __user *ubuf, size_t cnt,
636 loff_t *ppos)
637{ 662{
638 struct ftrace_event_call *call = filp->private_data; 663 loff_t l = 0;
639 struct list_head *head; 664 void *p;
640 struct trace_seq *s;
641 char *buf;
642 int r;
643 665
644 if (*ppos) 666 /* Start by showing the header */
667 if (!*pos)
668 return (void *)FORMAT_HEADER;
669
670 p = (void *)FORMAT_HEADER;
671 do {
672 p = f_next(m, p, &l);
673 } while (p && l < *pos);
674
675 return p;
676}
677
678static int f_show(struct seq_file *m, void *v)
679{
680 struct ftrace_event_call *call = m->private;
681 struct ftrace_event_field *field;
682 const char *array_descriptor;
683
684 switch ((unsigned long)v) {
685 case FORMAT_HEADER:
686 seq_printf(m, "name: %s\n", call->name);
687 seq_printf(m, "ID: %d\n", call->event.type);
688 seq_printf(m, "format:\n");
645 return 0; 689 return 0;
646 690
647 s = kmalloc(sizeof(*s), GFP_KERNEL); 691 case FORMAT_PRINTFMT:
648 if (!s) 692 seq_printf(m, "\nprint fmt: %s\n",
649 return -ENOMEM; 693 call->print_fmt);
694 return 0;
695 }
650 696
651 trace_seq_init(s); 697 /*
698 * To separate common fields from event fields, the
699 * LSB is set on the first event field. Clear it and
700 * print a newline if it is set.
701 */
702 if ((unsigned long)v & 1) {
703 seq_putc(m, '\n');
704 v = (void *)((unsigned long)v & ~1L);
705 }
652 706
653 trace_seq_printf(s, "name: %s\n", call->name); 707 field = v;
654 trace_seq_printf(s, "ID: %d\n", call->event.type);
655 trace_seq_printf(s, "format:\n");
656 708
657 /* print common fields */ 709 /*
658 print_event_fields(s, &ftrace_common_fields); 710 * Smartly shows the array type(except dynamic array).
711 * Normal:
712 * field:TYPE VAR
713 * If TYPE := TYPE[LEN], it is shown:
714 * field:TYPE VAR[LEN]
715 */
716 array_descriptor = strchr(field->type, '[');
659 717
660 trace_seq_putc(s, '\n'); 718 if (!strncmp(field->type, "__data_loc", 10))
719 array_descriptor = NULL;
661 720
662 /* print event specific fields */ 721 if (!array_descriptor)
663 head = trace_get_fields(call); 722 seq_printf(m, "\tfield:%s %s;\toffset:%u;\tsize:%u;\tsigned:%d;\n",
664 print_event_fields(s, head); 723 field->type, field->name, field->offset,
724 field->size, !!field->is_signed);
725 else
726 seq_printf(m, "\tfield:%.*s %s%s;\toffset:%u;\tsize:%u;\tsigned:%d;\n",
727 (int)(array_descriptor - field->type),
728 field->type, field->name,
729 array_descriptor, field->offset,
730 field->size, !!field->is_signed);
665 731
666 r = trace_seq_printf(s, "\nprint fmt: %s\n", call->print_fmt); 732 return 0;
733}
667 734
668 if (!r) { 735static void f_stop(struct seq_file *m, void *p)
669 /* 736{
670 * ug! The format output is bigger than a PAGE!! 737}
671 */
672 buf = "FORMAT TOO BIG\n";
673 r = simple_read_from_buffer(ubuf, cnt, ppos,
674 buf, strlen(buf));
675 goto out;
676 }
677 738
678 r = simple_read_from_buffer(ubuf, cnt, ppos, 739static const struct seq_operations trace_format_seq_ops = {
679 s->buffer, s->len); 740 .start = f_start,
680 out: 741 .next = f_next,
681 kfree(s); 742 .stop = f_stop,
682 return r; 743 .show = f_show,
744};
745
746static int trace_format_open(struct inode *inode, struct file *file)
747{
748 struct ftrace_event_call *call = inode->i_private;
749 struct seq_file *m;
750 int ret;
751
752 ret = seq_open(file, &trace_format_seq_ops);
753 if (ret < 0)
754 return ret;
755
756 m = file->private_data;
757 m->private = call;
758
759 return 0;
683} 760}
684 761
685static ssize_t 762static ssize_t
@@ -877,8 +954,10 @@ static const struct file_operations ftrace_enable_fops = {
877}; 954};
878 955
879static const struct file_operations ftrace_event_format_fops = { 956static const struct file_operations ftrace_event_format_fops = {
880 .open = tracing_open_generic, 957 .open = trace_format_open,
881 .read = event_format_read, 958 .read = seq_read,
959 .llseek = seq_lseek,
960 .release = seq_release,
882}; 961};
883 962
884static const struct file_operations ftrace_event_id_fops = { 963static const struct file_operations ftrace_event_id_fops = {
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
index 6bff23625781..6f233698518e 100644
--- a/kernel/trace/trace_functions_graph.c
+++ b/kernel/trace/trace_functions_graph.c
@@ -507,7 +507,15 @@ get_return_for_leaf(struct trace_iterator *iter,
507 * if the output fails. 507 * if the output fails.
508 */ 508 */
509 data->ent = *curr; 509 data->ent = *curr;
510 data->ret = *next; 510 /*
511 * If the next event is not a return type, then
512 * we only care about what type it is. Otherwise we can
513 * safely copy the entire event.
514 */
515 if (next->ent.type == TRACE_GRAPH_RET)
516 data->ret = *next;
517 else
518 data->ret.ent.type = next->ent.type;
511 } 519 }
512 } 520 }
513 521