Root/kernel/trace/trace_output.c

1/*
2 * trace_output.c
3 *
4 * Copyright (C) 2008 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
5 *
6 */
7
8#include <linux/module.h>
9#include <linux/mutex.h>
10#include <linux/ftrace.h>
11
12#include "trace_output.h"
13
14/* must be a power of 2 */
15#define EVENT_HASHSIZE 128
16
17DECLARE_RWSEM(trace_event_mutex);
18
19static struct hlist_head event_hash[EVENT_HASHSIZE] __read_mostly;
20
21static int next_event_type = __TRACE_LAST_TYPE + 1;
22
23int trace_print_seq(struct seq_file *m, struct trace_seq *s)
24{
25    int len = s->len >= PAGE_SIZE ? PAGE_SIZE - 1 : s->len;
26    int ret;
27
28    ret = seq_write(m, s->buffer, len);
29
30    /*
31     * Only reset this buffer if we successfully wrote to the
32     * seq_file buffer.
33     */
34    if (!ret)
35        trace_seq_init(s);
36
37    return ret;
38}
39
40enum print_line_t trace_print_bprintk_msg_only(struct trace_iterator *iter)
41{
42    struct trace_seq *s = &iter->seq;
43    struct trace_entry *entry = iter->ent;
44    struct bprint_entry *field;
45    int ret;
46
47    trace_assign_type(field, entry);
48
49    ret = trace_seq_bprintf(s, field->fmt, field->buf);
50    if (!ret)
51        return TRACE_TYPE_PARTIAL_LINE;
52
53    return TRACE_TYPE_HANDLED;
54}
55
56enum print_line_t trace_print_printk_msg_only(struct trace_iterator *iter)
57{
58    struct trace_seq *s = &iter->seq;
59    struct trace_entry *entry = iter->ent;
60    struct print_entry *field;
61    int ret;
62
63    trace_assign_type(field, entry);
64
65    ret = trace_seq_printf(s, "%s", field->buf);
66    if (!ret)
67        return TRACE_TYPE_PARTIAL_LINE;
68
69    return TRACE_TYPE_HANDLED;
70}
71
72/**
73 * trace_seq_printf - sequence printing of trace information
74 * @s: trace sequence descriptor
75 * @fmt: printf format string
76 *
77 * It returns 0 if the trace oversizes the buffer's free
78 * space, 1 otherwise.
79 *
80 * The tracer may use either sequence operations or its own
81 * copy to user routines. To simplify formating of a trace
82 * trace_seq_printf is used to store strings into a special
83 * buffer (@s). Then the output may be either used by
84 * the sequencer or pulled into another buffer.
85 */
86int
87trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
88{
89    int len = (PAGE_SIZE - 1) - s->len;
90    va_list ap;
91    int ret;
92
93    if (s->full || !len)
94        return 0;
95
96    va_start(ap, fmt);
97    ret = vsnprintf(s->buffer + s->len, len, fmt, ap);
98    va_end(ap);
99
100    /* If we can't write it all, don't bother writing anything */
101    if (ret >= len) {
102        s->full = 1;
103        return 0;
104    }
105
106    s->len += ret;
107
108    return 1;
109}
110EXPORT_SYMBOL_GPL(trace_seq_printf);
111
112/**
113 * trace_seq_vprintf - sequence printing of trace information
114 * @s: trace sequence descriptor
115 * @fmt: printf format string
116 *
117 * The tracer may use either sequence operations or its own
118 * copy to user routines. To simplify formating of a trace
119 * trace_seq_printf is used to store strings into a special
120 * buffer (@s). Then the output may be either used by
121 * the sequencer or pulled into another buffer.
122 */
123int
124trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args)
125{
126    int len = (PAGE_SIZE - 1) - s->len;
127    int ret;
128
129    if (s->full || !len)
130        return 0;
131
132    ret = vsnprintf(s->buffer + s->len, len, fmt, args);
133
134    /* If we can't write it all, don't bother writing anything */
135    if (ret >= len) {
136        s->full = 1;
137        return 0;
138    }
139
140    s->len += ret;
141
142    return len;
143}
144EXPORT_SYMBOL_GPL(trace_seq_vprintf);
145
146int trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary)
147{
148    int len = (PAGE_SIZE - 1) - s->len;
149    int ret;
150
151    if (s->full || !len)
152        return 0;
153
154    ret = bstr_printf(s->buffer + s->len, len, fmt, binary);
155
156    /* If we can't write it all, don't bother writing anything */
157    if (ret >= len) {
158        s->full = 1;
159        return 0;
160    }
161
162    s->len += ret;
163
164    return len;
165}
166
167/**
168 * trace_seq_puts - trace sequence printing of simple string
169 * @s: trace sequence descriptor
170 * @str: simple string to record
171 *
172 * The tracer may use either the sequence operations or its own
173 * copy to user routines. This function records a simple string
174 * into a special buffer (@s) for later retrieval by a sequencer
175 * or other mechanism.
176 */
177int trace_seq_puts(struct trace_seq *s, const char *str)
178{
179    int len = strlen(str);
180
181    if (s->full)
182        return 0;
183
184    if (len > ((PAGE_SIZE - 1) - s->len)) {
185        s->full = 1;
186        return 0;
187    }
188
189    memcpy(s->buffer + s->len, str, len);
190    s->len += len;
191
192    return len;
193}
194
195int trace_seq_putc(struct trace_seq *s, unsigned char c)
196{
197    if (s->full)
198        return 0;
199
200    if (s->len >= (PAGE_SIZE - 1)) {
201        s->full = 1;
202        return 0;
203    }
204
205    s->buffer[s->len++] = c;
206
207    return 1;
208}
209EXPORT_SYMBOL(trace_seq_putc);
210
211int trace_seq_putmem(struct trace_seq *s, const void *mem, size_t len)
212{
213    if (s->full)
214        return 0;
215
216    if (len > ((PAGE_SIZE - 1) - s->len)) {
217        s->full = 1;
218        return 0;
219    }
220
221    memcpy(s->buffer + s->len, mem, len);
222    s->len += len;
223
224    return len;
225}
226
227int trace_seq_putmem_hex(struct trace_seq *s, const void *mem, size_t len)
228{
229    unsigned char hex[HEX_CHARS];
230    const unsigned char *data = mem;
231    int i, j;
232
233    if (s->full)
234        return 0;
235
236#ifdef __BIG_ENDIAN
237    for (i = 0, j = 0; i < len; i++) {
238#else
239    for (i = len-1, j = 0; i >= 0; i--) {
240#endif
241        hex[j++] = hex_asc_hi(data[i]);
242        hex[j++] = hex_asc_lo(data[i]);
243    }
244    hex[j++] = ' ';
245
246    return trace_seq_putmem(s, hex, j);
247}
248
249void *trace_seq_reserve(struct trace_seq *s, size_t len)
250{
251    void *ret;
252
253    if (s->full)
254        return NULL;
255
256    if (len > ((PAGE_SIZE - 1) - s->len)) {
257        s->full = 1;
258        return NULL;
259    }
260
261    ret = s->buffer + s->len;
262    s->len += len;
263
264    return ret;
265}
266
267int trace_seq_path(struct trace_seq *s, struct path *path)
268{
269    unsigned char *p;
270
271    if (s->full)
272        return 0;
273
274    if (s->len >= (PAGE_SIZE - 1)) {
275        s->full = 1;
276        return 0;
277    }
278
279    p = d_path(path, s->buffer + s->len, PAGE_SIZE - s->len);
280    if (!IS_ERR(p)) {
281        p = mangle_path(s->buffer + s->len, p, "\n");
282        if (p) {
283            s->len = p - s->buffer;
284            return 1;
285        }
286    } else {
287        s->buffer[s->len++] = '?';
288        return 1;
289    }
290
291    s->full = 1;
292    return 0;
293}
294
295const char *
296ftrace_print_flags_seq(struct trace_seq *p, const char *delim,
297               unsigned long flags,
298               const struct trace_print_flags *flag_array)
299{
300    unsigned long mask;
301    const char *str;
302    const char *ret = p->buffer + p->len;
303    int i;
304
305    for (i = 0; flag_array[i].name && flags; i++) {
306
307        mask = flag_array[i].mask;
308        if ((flags & mask) != mask)
309            continue;
310
311        str = flag_array[i].name;
312        flags &= ~mask;
313        if (p->len && delim)
314            trace_seq_puts(p, delim);
315        trace_seq_puts(p, str);
316    }
317
318    /* check for left over flags */
319    if (flags) {
320        if (p->len && delim)
321            trace_seq_puts(p, delim);
322        trace_seq_printf(p, "0x%lx", flags);
323    }
324
325    trace_seq_putc(p, 0);
326
327    return ret;
328}
329EXPORT_SYMBOL(ftrace_print_flags_seq);
330
331const char *
332ftrace_print_symbols_seq(struct trace_seq *p, unsigned long val,
333             const struct trace_print_flags *symbol_array)
334{
335    int i;
336    const char *ret = p->buffer + p->len;
337
338    for (i = 0; symbol_array[i].name; i++) {
339
340        if (val != symbol_array[i].mask)
341            continue;
342
343        trace_seq_puts(p, symbol_array[i].name);
344        break;
345    }
346
347    if (!p->len)
348        trace_seq_printf(p, "0x%lx", val);
349        
350    trace_seq_putc(p, 0);
351
352    return ret;
353}
354EXPORT_SYMBOL(ftrace_print_symbols_seq);
355
356#if BITS_PER_LONG == 32
357const char *
358ftrace_print_symbols_seq_u64(struct trace_seq *p, unsigned long long val,
359             const struct trace_print_flags_u64 *symbol_array)
360{
361    int i;
362    const char *ret = p->buffer + p->len;
363
364    for (i = 0; symbol_array[i].name; i++) {
365
366        if (val != symbol_array[i].mask)
367            continue;
368
369        trace_seq_puts(p, symbol_array[i].name);
370        break;
371    }
372
373    if (!p->len)
374        trace_seq_printf(p, "0x%llx", val);
375
376    trace_seq_putc(p, 0);
377
378    return ret;
379}
380EXPORT_SYMBOL(ftrace_print_symbols_seq_u64);
381#endif
382
383const char *
384ftrace_print_hex_seq(struct trace_seq *p, const unsigned char *buf, int buf_len)
385{
386    int i;
387    const char *ret = p->buffer + p->len;
388
389    for (i = 0; i < buf_len; i++)
390        trace_seq_printf(p, "%s%2.2x", i == 0 ? "" : " ", buf[i]);
391
392    trace_seq_putc(p, 0);
393
394    return ret;
395}
396EXPORT_SYMBOL(ftrace_print_hex_seq);
397
398#ifdef CONFIG_KRETPROBES
399static inline const char *kretprobed(const char *name)
400{
401    static const char tramp_name[] = "kretprobe_trampoline";
402    int size = sizeof(tramp_name);
403
404    if (strncmp(tramp_name, name, size) == 0)
405        return "[unknown/kretprobe'd]";
406    return name;
407}
408#else
409static inline const char *kretprobed(const char *name)
410{
411    return name;
412}
413#endif /* CONFIG_KRETPROBES */
414
415static int
416seq_print_sym_short(struct trace_seq *s, const char *fmt, unsigned long address)
417{
418#ifdef CONFIG_KALLSYMS
419    char str[KSYM_SYMBOL_LEN];
420    const char *name;
421
422    kallsyms_lookup(address, NULL, NULL, NULL, str);
423
424    name = kretprobed(str);
425
426    return trace_seq_printf(s, fmt, name);
427#endif
428    return 1;
429}
430
431static int
432seq_print_sym_offset(struct trace_seq *s, const char *fmt,
433             unsigned long address)
434{
435#ifdef CONFIG_KALLSYMS
436    char str[KSYM_SYMBOL_LEN];
437    const char *name;
438
439    sprint_symbol(str, address);
440    name = kretprobed(str);
441
442    return trace_seq_printf(s, fmt, name);
443#endif
444    return 1;
445}
446
447#ifndef CONFIG_64BIT
448# define IP_FMT "%08lx"
449#else
450# define IP_FMT "%016lx"
451#endif
452
453int seq_print_user_ip(struct trace_seq *s, struct mm_struct *mm,
454              unsigned long ip, unsigned long sym_flags)
455{
456    struct file *file = NULL;
457    unsigned long vmstart = 0;
458    int ret = 1;
459
460    if (s->full)
461        return 0;
462
463    if (mm) {
464        const struct vm_area_struct *vma;
465
466        down_read(&mm->mmap_sem);
467        vma = find_vma(mm, ip);
468        if (vma) {
469            file = vma->vm_file;
470            vmstart = vma->vm_start;
471        }
472        if (file) {
473            ret = trace_seq_path(s, &file->f_path);
474            if (ret)
475                ret = trace_seq_printf(s, "[+0x%lx]",
476                               ip - vmstart);
477        }
478        up_read(&mm->mmap_sem);
479    }
480    if (ret && ((sym_flags & TRACE_ITER_SYM_ADDR) || !file))
481        ret = trace_seq_printf(s, " <" IP_FMT ">", ip);
482    return ret;
483}
484
485int
486seq_print_userip_objs(const struct userstack_entry *entry, struct trace_seq *s,
487              unsigned long sym_flags)
488{
489    struct mm_struct *mm = NULL;
490    int ret = 1;
491    unsigned int i;
492
493    if (trace_flags & TRACE_ITER_SYM_USEROBJ) {
494        struct task_struct *task;
495        /*
496         * we do the lookup on the thread group leader,
497         * since individual threads might have already quit!
498         */
499        rcu_read_lock();
500        task = find_task_by_vpid(entry->tgid);
501        if (task)
502            mm = get_task_mm(task);
503        rcu_read_unlock();
504    }
505
506    for (i = 0; i < FTRACE_STACK_ENTRIES; i++) {
507        unsigned long ip = entry->caller[i];
508
509        if (ip == ULONG_MAX || !ret)
510            break;
511        if (ret)
512            ret = trace_seq_puts(s, " => ");
513        if (!ip) {
514            if (ret)
515                ret = trace_seq_puts(s, "??");
516            if (ret)
517                ret = trace_seq_puts(s, "\n");
518            continue;
519        }
520        if (!ret)
521            break;
522        if (ret)
523            ret = seq_print_user_ip(s, mm, ip, sym_flags);
524        ret = trace_seq_puts(s, "\n");
525    }
526
527    if (mm)
528        mmput(mm);
529    return ret;
530}
531
532int
533seq_print_ip_sym(struct trace_seq *s, unsigned long ip, unsigned long sym_flags)
534{
535    int ret;
536
537    if (!ip)
538        return trace_seq_printf(s, "0");
539
540    if (sym_flags & TRACE_ITER_SYM_OFFSET)
541        ret = seq_print_sym_offset(s, "%s", ip);
542    else
543        ret = seq_print_sym_short(s, "%s", ip);
544
545    if (!ret)
546        return 0;
547
548    if (sym_flags & TRACE_ITER_SYM_ADDR)
549        ret = trace_seq_printf(s, " <" IP_FMT ">", ip);
550    return ret;
551}
552
553/**
554 * trace_print_lat_fmt - print the irq, preempt and lockdep fields
555 * @s: trace seq struct to write to
556 * @entry: The trace entry field from the ring buffer
557 *
558 * Prints the generic fields of irqs off, in hard or softirq, preempt
559 * count.
560 */
561int trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry)
562{
563    char hardsoft_irq;
564    char need_resched;
565    char irqs_off;
566    int hardirq;
567    int softirq;
568    int ret;
569
570    hardirq = entry->flags & TRACE_FLAG_HARDIRQ;
571    softirq = entry->flags & TRACE_FLAG_SOFTIRQ;
572
573    irqs_off =
574        (entry->flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
575        (entry->flags & TRACE_FLAG_IRQS_NOSUPPORT) ? 'X' :
576        '.';
577    need_resched =
578        (entry->flags & TRACE_FLAG_NEED_RESCHED) ? 'N' : '.';
579    hardsoft_irq =
580        (hardirq && softirq) ? 'H' :
581        hardirq ? 'h' :
582        softirq ? 's' :
583        '.';
584
585    if (!trace_seq_printf(s, "%c%c%c",
586                  irqs_off, need_resched, hardsoft_irq))
587        return 0;
588
589    if (entry->preempt_count)
590        ret = trace_seq_printf(s, "%x", entry->preempt_count);
591    else
592        ret = trace_seq_putc(s, '.');
593
594    return ret;
595}
596
597static int
598lat_print_generic(struct trace_seq *s, struct trace_entry *entry, int cpu)
599{
600    char comm[TASK_COMM_LEN];
601
602    trace_find_cmdline(entry->pid, comm);
603
604    if (!trace_seq_printf(s, "%8.8s-%-5d %3d",
605                  comm, entry->pid, cpu))
606        return 0;
607
608    return trace_print_lat_fmt(s, entry);
609}
610
611static unsigned long preempt_mark_thresh = 100;
612
613static int
614lat_print_timestamp(struct trace_seq *s, u64 abs_usecs,
615            unsigned long rel_usecs)
616{
617    return trace_seq_printf(s, " %4lldus%c: ", abs_usecs,
618                rel_usecs > preempt_mark_thresh ? '!' :
619                  rel_usecs > 1 ? '+' : ' ');
620}
621
622int trace_print_context(struct trace_iterator *iter)
623{
624    struct trace_seq *s = &iter->seq;
625    struct trace_entry *entry = iter->ent;
626    unsigned long long t = ns2usecs(iter->ts);
627    unsigned long usec_rem = do_div(t, USEC_PER_SEC);
628    unsigned long secs = (unsigned long)t;
629    char comm[TASK_COMM_LEN];
630
631    trace_find_cmdline(entry->pid, comm);
632
633    return trace_seq_printf(s, "%16s-%-5d [%03d] %5lu.%06lu: ",
634                comm, entry->pid, iter->cpu, secs, usec_rem);
635}
636
637int trace_print_lat_context(struct trace_iterator *iter)
638{
639    u64 next_ts;
640    int ret;
641    struct trace_seq *s = &iter->seq;
642    struct trace_entry *entry = iter->ent,
643               *next_entry = trace_find_next_entry(iter, NULL,
644                                   &next_ts);
645    unsigned long verbose = (trace_flags & TRACE_ITER_VERBOSE);
646    unsigned long abs_usecs = ns2usecs(iter->ts - iter->tr->time_start);
647    unsigned long rel_usecs;
648
649    if (!next_entry)
650        next_ts = iter->ts;
651    rel_usecs = ns2usecs(next_ts - iter->ts);
652
653    if (verbose) {
654        char comm[TASK_COMM_LEN];
655
656        trace_find_cmdline(entry->pid, comm);
657
658        ret = trace_seq_printf(s, "%16s %5d %3d %d %08x %08lx [%08llx]"
659                       " %ld.%03ldms (+%ld.%03ldms): ", comm,
660                       entry->pid, iter->cpu, entry->flags,
661                       entry->preempt_count, iter->idx,
662                       ns2usecs(iter->ts),
663                       abs_usecs / USEC_PER_MSEC,
664                       abs_usecs % USEC_PER_MSEC,
665                       rel_usecs / USEC_PER_MSEC,
666                       rel_usecs % USEC_PER_MSEC);
667    } else {
668        ret = lat_print_generic(s, entry, iter->cpu);
669        if (ret)
670            ret = lat_print_timestamp(s, abs_usecs, rel_usecs);
671    }
672
673    return ret;
674}
675
676static const char state_to_char[] = TASK_STATE_TO_CHAR_STR;
677
678static int task_state_char(unsigned long state)
679{
680    int bit = state ? __ffs(state) + 1 : 0;
681
682    return bit < sizeof(state_to_char) - 1 ? state_to_char[bit] : '?';
683}
684
685/**
686 * ftrace_find_event - find a registered event
687 * @type: the type of event to look for
688 *
689 * Returns an event of type @type otherwise NULL
690 * Called with trace_event_read_lock() held.
691 */
692struct trace_event *ftrace_find_event(int type)
693{
694    struct trace_event *event;
695    struct hlist_node *n;
696    unsigned key;
697
698    key = type & (EVENT_HASHSIZE - 1);
699
700    hlist_for_each_entry(event, n, &event_hash[key], node) {
701        if (event->type == type)
702            return event;
703    }
704
705    return NULL;
706}
707
708static LIST_HEAD(ftrace_event_list);
709
710static int trace_search_list(struct list_head **list)
711{
712    struct trace_event *e;
713    int last = __TRACE_LAST_TYPE;
714
715    if (list_empty(&ftrace_event_list)) {
716        *list = &ftrace_event_list;
717        return last + 1;
718    }
719
720    /*
721     * We used up all possible max events,
722     * lets see if somebody freed one.
723     */
724    list_for_each_entry(e, &ftrace_event_list, list) {
725        if (e->type != last + 1)
726            break;
727        last++;
728    }
729
730    /* Did we used up all 65 thousand events??? */
731    if ((last + 1) > FTRACE_MAX_EVENT)
732        return 0;
733
734    *list = &e->list;
735    return last + 1;
736}
737
738void trace_event_read_lock(void)
739{
740    down_read(&trace_event_mutex);
741}
742
743void trace_event_read_unlock(void)
744{
745    up_read(&trace_event_mutex);
746}
747
748/**
749 * register_ftrace_event - register output for an event type
750 * @event: the event type to register
751 *
752 * Event types are stored in a hash and this hash is used to
753 * find a way to print an event. If the @event->type is set
754 * then it will use that type, otherwise it will assign a
755 * type to use.
756 *
757 * If you assign your own type, please make sure it is added
758 * to the trace_type enum in trace.h, to avoid collisions
759 * with the dynamic types.
760 *
761 * Returns the event type number or zero on error.
762 */
763int register_ftrace_event(struct trace_event *event)
764{
765    unsigned key;
766    int ret = 0;
767
768    down_write(&trace_event_mutex);
769
770    if (WARN_ON(!event))
771        goto out;
772
773    if (WARN_ON(!event->funcs))
774        goto out;
775
776    INIT_LIST_HEAD(&event->list);
777
778    if (!event->type) {
779        struct list_head *list = NULL;
780
781        if (next_event_type > FTRACE_MAX_EVENT) {
782
783            event->type = trace_search_list(&list);
784            if (!event->type)
785                goto out;
786
787        } else {
788            
789            event->type = next_event_type++;
790            list = &ftrace_event_list;
791        }
792
793        if (WARN_ON(ftrace_find_event(event->type)))
794            goto out;
795
796        list_add_tail(&event->list, list);
797
798    } else if (event->type > __TRACE_LAST_TYPE) {
799        printk(KERN_WARNING "Need to add type to trace.h\n");
800        WARN_ON(1);
801        goto out;
802    } else {
803        /* Is this event already used */
804        if (ftrace_find_event(event->type))
805            goto out;
806    }
807
808    if (event->funcs->trace == NULL)
809        event->funcs->trace = trace_nop_print;
810    if (event->funcs->raw == NULL)
811        event->funcs->raw = trace_nop_print;
812    if (event->funcs->hex == NULL)
813        event->funcs->hex = trace_nop_print;
814    if (event->funcs->binary == NULL)
815        event->funcs->binary = trace_nop_print;
816
817    key = event->type & (EVENT_HASHSIZE - 1);
818
819    hlist_add_head(&event->node, &event_hash[key]);
820
821    ret = event->type;
822 out:
823    up_write(&trace_event_mutex);
824
825    return ret;
826}
827EXPORT_SYMBOL_GPL(register_ftrace_event);
828
829/*
830 * Used by module code with the trace_event_mutex held for write.
831 */
832int __unregister_ftrace_event(struct trace_event *event)
833{
834    hlist_del(&event->node);
835    list_del(&event->list);
836    return 0;
837}
838
839/**
840 * unregister_ftrace_event - remove a no longer used event
841 * @event: the event to remove
842 */
843int unregister_ftrace_event(struct trace_event *event)
844{
845    down_write(&trace_event_mutex);
846    __unregister_ftrace_event(event);
847    up_write(&trace_event_mutex);
848
849    return 0;
850}
851EXPORT_SYMBOL_GPL(unregister_ftrace_event);
852
853/*
854 * Standard events
855 */
856
857enum print_line_t trace_nop_print(struct trace_iterator *iter, int flags,
858                  struct trace_event *event)
859{
860    if (!trace_seq_printf(&iter->seq, "type: %d\n", iter->ent->type))
861        return TRACE_TYPE_PARTIAL_LINE;
862
863    return TRACE_TYPE_HANDLED;
864}
865
866/* TRACE_FN */
867static enum print_line_t trace_fn_trace(struct trace_iterator *iter, int flags,
868                    struct trace_event *event)
869{
870    struct ftrace_entry *field;
871    struct trace_seq *s = &iter->seq;
872
873    trace_assign_type(field, iter->ent);
874
875    if (!seq_print_ip_sym(s, field->ip, flags))
876        goto partial;
877
878    if ((flags & TRACE_ITER_PRINT_PARENT) && field->parent_ip) {
879        if (!trace_seq_printf(s, " <-"))
880            goto partial;
881        if (!seq_print_ip_sym(s,
882                      field->parent_ip,
883                      flags))
884            goto partial;
885    }
886    if (!trace_seq_printf(s, "\n"))
887        goto partial;
888
889    return TRACE_TYPE_HANDLED;
890
891 partial:
892    return TRACE_TYPE_PARTIAL_LINE;
893}
894
895static enum print_line_t trace_fn_raw(struct trace_iterator *iter, int flags,
896                      struct trace_event *event)
897{
898    struct ftrace_entry *field;
899
900    trace_assign_type(field, iter->ent);
901
902    if (!trace_seq_printf(&iter->seq, "%lx %lx\n",
903                  field->ip,
904                  field->parent_ip))
905        return TRACE_TYPE_PARTIAL_LINE;
906
907    return TRACE_TYPE_HANDLED;
908}
909
910static enum print_line_t trace_fn_hex(struct trace_iterator *iter, int flags,
911                      struct trace_event *event)
912{
913    struct ftrace_entry *field;
914    struct trace_seq *s = &iter->seq;
915
916    trace_assign_type(field, iter->ent);
917
918    SEQ_PUT_HEX_FIELD_RET(s, field->ip);
919    SEQ_PUT_HEX_FIELD_RET(s, field->parent_ip);
920
921    return TRACE_TYPE_HANDLED;
922}
923
924static enum print_line_t trace_fn_bin(struct trace_iterator *iter, int flags,
925                      struct trace_event *event)
926{
927    struct ftrace_entry *field;
928    struct trace_seq *s = &iter->seq;
929
930    trace_assign_type(field, iter->ent);
931
932    SEQ_PUT_FIELD_RET(s, field->ip);
933    SEQ_PUT_FIELD_RET(s, field->parent_ip);
934
935    return TRACE_TYPE_HANDLED;
936}
937
938static struct trace_event_functions trace_fn_funcs = {
939    .trace = trace_fn_trace,
940    .raw = trace_fn_raw,
941    .hex = trace_fn_hex,
942    .binary = trace_fn_bin,
943};
944
945static struct trace_event trace_fn_event = {
946    .type = TRACE_FN,
947    .funcs = &trace_fn_funcs,
948};
949
950/* TRACE_CTX an TRACE_WAKE */
951static enum print_line_t trace_ctxwake_print(struct trace_iterator *iter,
952                         char *delim)
953{
954    struct ctx_switch_entry *field;
955    char comm[TASK_COMM_LEN];
956    int S, T;
957
958
959    trace_assign_type(field, iter->ent);
960
961    T = task_state_char(field->next_state);
962    S = task_state_char(field->prev_state);
963    trace_find_cmdline(field->next_pid, comm);
964    if (!trace_seq_printf(&iter->seq,
965                  " %5d:%3d:%c %s [%03d] %5d:%3d:%c %s\n",
966                  field->prev_pid,
967                  field->prev_prio,
968                  S, delim,
969                  field->next_cpu,
970                  field->next_pid,
971                  field->next_prio,
972                  T, comm))
973        return TRACE_TYPE_PARTIAL_LINE;
974
975    return TRACE_TYPE_HANDLED;
976}
977
978static enum print_line_t trace_ctx_print(struct trace_iterator *iter, int flags,
979                     struct trace_event *event)
980{
981    return trace_ctxwake_print(iter, "==>");
982}
983
984static enum print_line_t trace_wake_print(struct trace_iterator *iter,
985                      int flags, struct trace_event *event)
986{
987    return trace_ctxwake_print(iter, " +");
988}
989
990static int trace_ctxwake_raw(struct trace_iterator *iter, char S)
991{
992    struct ctx_switch_entry *field;
993    int T;
994
995    trace_assign_type(field, iter->ent);
996
997    if (!S)
998        S = task_state_char(field->prev_state);
999    T = task_state_char(field->next_state);
1000    if (!trace_seq_printf(&iter->seq, "%d %d %c %d %d %d %c\n",
1001                  field->prev_pid,
1002                  field->prev_prio,
1003                  S,
1004                  field->next_cpu,
1005                  field->next_pid,
1006                  field->next_prio,
1007                  T))
1008        return TRACE_TYPE_PARTIAL_LINE;
1009
1010    return TRACE_TYPE_HANDLED;
1011}
1012
1013static enum print_line_t trace_ctx_raw(struct trace_iterator *iter, int flags,
1014                       struct trace_event *event)
1015{
1016    return trace_ctxwake_raw(iter, 0);
1017}
1018
1019static enum print_line_t trace_wake_raw(struct trace_iterator *iter, int flags,
1020                    struct trace_event *event)
1021{
1022    return trace_ctxwake_raw(iter, '+');
1023}
1024
1025
1026static int trace_ctxwake_hex(struct trace_iterator *iter, char S)
1027{
1028    struct ctx_switch_entry *field;
1029    struct trace_seq *s = &iter->seq;
1030    int T;
1031
1032    trace_assign_type(field, iter->ent);
1033
1034    if (!S)
1035        S = task_state_char(field->prev_state);
1036    T = task_state_char(field->next_state);
1037
1038    SEQ_PUT_HEX_FIELD_RET(s, field->prev_pid);
1039    SEQ_PUT_HEX_FIELD_RET(s, field->prev_prio);
1040    SEQ_PUT_HEX_FIELD_RET(s, S);
1041    SEQ_PUT_HEX_FIELD_RET(s, field->next_cpu);
1042    SEQ_PUT_HEX_FIELD_RET(s, field->next_pid);
1043    SEQ_PUT_HEX_FIELD_RET(s, field->next_prio);
1044    SEQ_PUT_HEX_FIELD_RET(s, T);
1045
1046    return TRACE_TYPE_HANDLED;
1047}
1048
1049static enum print_line_t trace_ctx_hex(struct trace_iterator *iter, int flags,
1050                       struct trace_event *event)
1051{
1052    return trace_ctxwake_hex(iter, 0);
1053}
1054
1055static enum print_line_t trace_wake_hex(struct trace_iterator *iter, int flags,
1056                    struct trace_event *event)
1057{
1058    return trace_ctxwake_hex(iter, '+');
1059}
1060
1061static enum print_line_t trace_ctxwake_bin(struct trace_iterator *iter,
1062                       int flags, struct trace_event *event)
1063{
1064    struct ctx_switch_entry *field;
1065    struct trace_seq *s = &iter->seq;
1066
1067    trace_assign_type(field, iter->ent);
1068
1069    SEQ_PUT_FIELD_RET(s, field->prev_pid);
1070    SEQ_PUT_FIELD_RET(s, field->prev_prio);
1071    SEQ_PUT_FIELD_RET(s, field->prev_state);
1072    SEQ_PUT_FIELD_RET(s, field->next_pid);
1073    SEQ_PUT_FIELD_RET(s, field->next_prio);
1074    SEQ_PUT_FIELD_RET(s, field->next_state);
1075
1076    return TRACE_TYPE_HANDLED;
1077}
1078
1079static struct trace_event_functions trace_ctx_funcs = {
1080    .trace = trace_ctx_print,
1081    .raw = trace_ctx_raw,
1082    .hex = trace_ctx_hex,
1083    .binary = trace_ctxwake_bin,
1084};
1085
1086static struct trace_event trace_ctx_event = {
1087    .type = TRACE_CTX,
1088    .funcs = &trace_ctx_funcs,
1089};
1090
1091static struct trace_event_functions trace_wake_funcs = {
1092    .trace = trace_wake_print,
1093    .raw = trace_wake_raw,
1094    .hex = trace_wake_hex,
1095    .binary = trace_ctxwake_bin,
1096};
1097
1098static struct trace_event trace_wake_event = {
1099    .type = TRACE_WAKE,
1100    .funcs = &trace_wake_funcs,
1101};
1102
1103/* TRACE_STACK */
1104
1105static enum print_line_t trace_stack_print(struct trace_iterator *iter,
1106                       int flags, struct trace_event *event)
1107{
1108    struct stack_entry *field;
1109    struct trace_seq *s = &iter->seq;
1110    int i;
1111
1112    trace_assign_type(field, iter->ent);
1113
1114    if (!trace_seq_puts(s, "<stack trace>\n"))
1115        goto partial;
1116    for (i = 0; i < FTRACE_STACK_ENTRIES; i++) {
1117        if (!field->caller[i] || (field->caller[i] == ULONG_MAX))
1118            break;
1119        if (!trace_seq_puts(s, " => "))
1120            goto partial;
1121
1122        if (!seq_print_ip_sym(s, field->caller[i], flags))
1123            goto partial;
1124        if (!trace_seq_puts(s, "\n"))
1125            goto partial;
1126    }
1127
1128    return TRACE_TYPE_HANDLED;
1129
1130 partial:
1131    return TRACE_TYPE_PARTIAL_LINE;
1132}
1133
1134static struct trace_event_functions trace_stack_funcs = {
1135    .trace = trace_stack_print,
1136};
1137
1138static struct trace_event trace_stack_event = {
1139    .type = TRACE_STACK,
1140    .funcs = &trace_stack_funcs,
1141};
1142
1143/* TRACE_USER_STACK */
1144static enum print_line_t trace_user_stack_print(struct trace_iterator *iter,
1145                        int flags, struct trace_event *event)
1146{
1147    struct userstack_entry *field;
1148    struct trace_seq *s = &iter->seq;
1149
1150    trace_assign_type(field, iter->ent);
1151
1152    if (!trace_seq_puts(s, "<user stack trace>\n"))
1153        goto partial;
1154
1155    if (!seq_print_userip_objs(field, s, flags))
1156        goto partial;
1157
1158    return TRACE_TYPE_HANDLED;
1159
1160 partial:
1161    return TRACE_TYPE_PARTIAL_LINE;
1162}
1163
1164static struct trace_event_functions trace_user_stack_funcs = {
1165    .trace = trace_user_stack_print,
1166};
1167
1168static struct trace_event trace_user_stack_event = {
1169    .type = TRACE_USER_STACK,
1170    .funcs = &trace_user_stack_funcs,
1171};
1172
1173/* TRACE_BPRINT */
1174static enum print_line_t
1175trace_bprint_print(struct trace_iterator *iter, int flags,
1176           struct trace_event *event)
1177{
1178    struct trace_entry *entry = iter->ent;
1179    struct trace_seq *s = &iter->seq;
1180    struct bprint_entry *field;
1181
1182    trace_assign_type(field, entry);
1183
1184    if (!seq_print_ip_sym(s, field->ip, flags))
1185        goto partial;
1186
1187    if (!trace_seq_puts(s, ": "))
1188        goto partial;
1189
1190    if (!trace_seq_bprintf(s, field->fmt, field->buf))
1191        goto partial;
1192
1193    return TRACE_TYPE_HANDLED;
1194
1195 partial:
1196    return TRACE_TYPE_PARTIAL_LINE;
1197}
1198
1199
1200static enum print_line_t
1201trace_bprint_raw(struct trace_iterator *iter, int flags,
1202         struct trace_event *event)
1203{
1204    struct bprint_entry *field;
1205    struct trace_seq *s = &iter->seq;
1206
1207    trace_assign_type(field, iter->ent);
1208
1209    if (!trace_seq_printf(s, ": %lx : ", field->ip))
1210        goto partial;
1211
1212    if (!trace_seq_bprintf(s, field->fmt, field->buf))
1213        goto partial;
1214
1215    return TRACE_TYPE_HANDLED;
1216
1217 partial:
1218    return TRACE_TYPE_PARTIAL_LINE;
1219}
1220
1221static struct trace_event_functions trace_bprint_funcs = {
1222    .trace = trace_bprint_print,
1223    .raw = trace_bprint_raw,
1224};
1225
1226static struct trace_event trace_bprint_event = {
1227    .type = TRACE_BPRINT,
1228    .funcs = &trace_bprint_funcs,
1229};
1230
1231/* TRACE_PRINT */
1232static enum print_line_t trace_print_print(struct trace_iterator *iter,
1233                       int flags, struct trace_event *event)
1234{
1235    struct print_entry *field;
1236    struct trace_seq *s = &iter->seq;
1237
1238    trace_assign_type(field, iter->ent);
1239
1240    if (!seq_print_ip_sym(s, field->ip, flags))
1241        goto partial;
1242
1243    if (!trace_seq_printf(s, ": %s", field->buf))
1244        goto partial;
1245
1246    return TRACE_TYPE_HANDLED;
1247
1248 partial:
1249    return TRACE_TYPE_PARTIAL_LINE;
1250}
1251
1252static enum print_line_t trace_print_raw(struct trace_iterator *iter, int flags,
1253                     struct trace_event *event)
1254{
1255    struct print_entry *field;
1256
1257    trace_assign_type(field, iter->ent);
1258
1259    if (!trace_seq_printf(&iter->seq, "# %lx %s", field->ip, field->buf))
1260        goto partial;
1261
1262    return TRACE_TYPE_HANDLED;
1263
1264 partial:
1265    return TRACE_TYPE_PARTIAL_LINE;
1266}
1267
1268static struct trace_event_functions trace_print_funcs = {
1269    .trace = trace_print_print,
1270    .raw = trace_print_raw,
1271};
1272
1273static struct trace_event trace_print_event = {
1274    .type = TRACE_PRINT,
1275    .funcs = &trace_print_funcs,
1276};
1277
1278
1279static struct trace_event *events[] __initdata = {
1280    &trace_fn_event,
1281    &trace_ctx_event,
1282    &trace_wake_event,
1283    &trace_stack_event,
1284    &trace_user_stack_event,
1285    &trace_bprint_event,
1286    &trace_print_event,
1287    NULL
1288};
1289
1290__init static int init_events(void)
1291{
1292    struct trace_event *event;
1293    int i, ret;
1294
1295    for (i = 0; events[i]; i++) {
1296        event = events[i];
1297
1298        ret = register_ftrace_event(event);
1299        if (!ret) {
1300            printk(KERN_WARNING "event %d failed to register\n",
1301                   event->type);
1302            WARN_ON_ONCE(1);
1303        }
1304    }
1305
1306    return 0;
1307}
1308device_initcall(init_events);
1309

Archive Download this file



interactive