diff options
Diffstat (limited to 'kernel/trace/trace_output.c')
-rw-r--r-- | kernel/trace/trace_output.c | 82 |
1 files changed, 73 insertions, 9 deletions
diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c index 64b54a59c55b..8bd9a2c1a46a 100644 --- a/kernel/trace/trace_output.c +++ b/kernel/trace/trace_output.c | |||
@@ -19,6 +19,16 @@ static struct hlist_head event_hash[EVENT_HASHSIZE] __read_mostly; | |||
19 | 19 | ||
20 | static int next_event_type = __TRACE_LAST_TYPE + 1; | 20 | static int next_event_type = __TRACE_LAST_TYPE + 1; |
21 | 21 | ||
22 | void trace_print_seq(struct seq_file *m, struct trace_seq *s) | ||
23 | { | ||
24 | int len = s->len >= PAGE_SIZE ? PAGE_SIZE - 1 : s->len; | ||
25 | |||
26 | s->buffer[len] = 0; | ||
27 | seq_puts(m, s->buffer); | ||
28 | |||
29 | trace_seq_init(s); | ||
30 | } | ||
31 | |||
22 | enum print_line_t trace_print_bprintk_msg_only(struct trace_iterator *iter) | 32 | enum print_line_t trace_print_bprintk_msg_only(struct trace_iterator *iter) |
23 | { | 33 | { |
24 | struct trace_seq *s = &iter->seq; | 34 | struct trace_seq *s = &iter->seq; |
@@ -84,6 +94,7 @@ trace_seq_printf(struct trace_seq *s, const char *fmt, ...) | |||
84 | 94 | ||
85 | return len; | 95 | return len; |
86 | } | 96 | } |
97 | EXPORT_SYMBOL_GPL(trace_seq_printf); | ||
87 | 98 | ||
88 | int trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary) | 99 | int trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary) |
89 | { | 100 | { |
@@ -472,6 +483,36 @@ struct trace_event *ftrace_find_event(int type) | |||
472 | return NULL; | 483 | return NULL; |
473 | } | 484 | } |
474 | 485 | ||
486 | static LIST_HEAD(ftrace_event_list); | ||
487 | |||
488 | static int trace_search_list(struct list_head **list) | ||
489 | { | ||
490 | struct trace_event *e; | ||
491 | int last = __TRACE_LAST_TYPE; | ||
492 | |||
493 | if (list_empty(&ftrace_event_list)) { | ||
494 | *list = &ftrace_event_list; | ||
495 | return last + 1; | ||
496 | } | ||
497 | |||
498 | /* | ||
499 | * We used up all possible max events, | ||
500 | * lets see if somebody freed one. | ||
501 | */ | ||
502 | list_for_each_entry(e, &ftrace_event_list, list) { | ||
503 | if (e->type != last + 1) | ||
504 | break; | ||
505 | last++; | ||
506 | } | ||
507 | |||
508 | /* Did we used up all 65 thousand events??? */ | ||
509 | if ((last + 1) > FTRACE_MAX_EVENT) | ||
510 | return 0; | ||
511 | |||
512 | *list = &e->list; | ||
513 | return last + 1; | ||
514 | } | ||
515 | |||
475 | /** | 516 | /** |
476 | * register_ftrace_event - register output for an event type | 517 | * register_ftrace_event - register output for an event type |
477 | * @event: the event type to register | 518 | * @event: the event type to register |
@@ -494,20 +535,40 @@ int register_ftrace_event(struct trace_event *event) | |||
494 | 535 | ||
495 | mutex_lock(&trace_event_mutex); | 536 | mutex_lock(&trace_event_mutex); |
496 | 537 | ||
497 | if (!event) { | 538 | if (WARN_ON(!event)) |
498 | ret = next_event_type++; | ||
499 | goto out; | 539 | goto out; |
500 | } | ||
501 | 540 | ||
502 | if (!event->type) | 541 | INIT_LIST_HEAD(&event->list); |
503 | event->type = next_event_type++; | 542 | |
504 | else if (event->type > __TRACE_LAST_TYPE) { | 543 | if (!event->type) { |
544 | struct list_head *list = NULL; | ||
545 | |||
546 | if (next_event_type > FTRACE_MAX_EVENT) { | ||
547 | |||
548 | event->type = trace_search_list(&list); | ||
549 | if (!event->type) | ||
550 | goto out; | ||
551 | |||
552 | } else { | ||
553 | |||
554 | event->type = next_event_type++; | ||
555 | list = &ftrace_event_list; | ||
556 | } | ||
557 | |||
558 | if (WARN_ON(ftrace_find_event(event->type))) | ||
559 | goto out; | ||
560 | |||
561 | list_add_tail(&event->list, list); | ||
562 | |||
563 | } else if (event->type > __TRACE_LAST_TYPE) { | ||
505 | printk(KERN_WARNING "Need to add type to trace.h\n"); | 564 | printk(KERN_WARNING "Need to add type to trace.h\n"); |
506 | WARN_ON(1); | 565 | WARN_ON(1); |
507 | } | ||
508 | |||
509 | if (ftrace_find_event(event->type)) | ||
510 | goto out; | 566 | goto out; |
567 | } else { | ||
568 | /* Is this event already used */ | ||
569 | if (ftrace_find_event(event->type)) | ||
570 | goto out; | ||
571 | } | ||
511 | 572 | ||
512 | if (event->trace == NULL) | 573 | if (event->trace == NULL) |
513 | event->trace = trace_nop_print; | 574 | event->trace = trace_nop_print; |
@@ -528,6 +589,7 @@ int register_ftrace_event(struct trace_event *event) | |||
528 | 589 | ||
529 | return ret; | 590 | return ret; |
530 | } | 591 | } |
592 | EXPORT_SYMBOL_GPL(register_ftrace_event); | ||
531 | 593 | ||
532 | /** | 594 | /** |
533 | * unregister_ftrace_event - remove a no longer used event | 595 | * unregister_ftrace_event - remove a no longer used event |
@@ -537,10 +599,12 @@ int unregister_ftrace_event(struct trace_event *event) | |||
537 | { | 599 | { |
538 | mutex_lock(&trace_event_mutex); | 600 | mutex_lock(&trace_event_mutex); |
539 | hlist_del(&event->node); | 601 | hlist_del(&event->node); |
602 | list_del(&event->list); | ||
540 | mutex_unlock(&trace_event_mutex); | 603 | mutex_unlock(&trace_event_mutex); |
541 | 604 | ||
542 | return 0; | 605 | return 0; |
543 | } | 606 | } |
607 | EXPORT_SYMBOL_GPL(unregister_ftrace_event); | ||
544 | 608 | ||
545 | /* | 609 | /* |
546 | * Standard events | 610 | * Standard events |