trace_output.c 21.5 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
 * trace_output.c
 *
 * Copyright (C) 2008 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
 *
 */

#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/ftrace.h>

#include "trace_output.h"

/* must be a power of 2 */
#define EVENT_HASHSIZE	128

static DEFINE_MUTEX(trace_event_mutex);
static struct hlist_head event_hash[EVENT_HASHSIZE] __read_mostly;

static int next_event_type = __TRACE_LAST_TYPE + 1;

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
enum print_line_t trace_print_bprintk_msg_only(struct trace_iterator *iter)
{
	struct trace_seq *s = &iter->seq;
	struct trace_entry *entry = iter->ent;
	struct bprint_entry *field;
	int ret;

	trace_assign_type(field, entry);

	ret = trace_seq_bprintf(s, field->fmt, field->buf);
	if (!ret)
		return TRACE_TYPE_PARTIAL_LINE;

	return TRACE_TYPE_HANDLED;
}

enum print_line_t trace_print_printk_msg_only(struct trace_iterator *iter)
{
	struct trace_seq *s = &iter->seq;
	struct trace_entry *entry = iter->ent;
	struct print_entry *field;
	int ret;

	trace_assign_type(field, entry);

	ret = trace_seq_printf(s, "%s", field->buf);
	if (!ret)
		return TRACE_TYPE_PARTIAL_LINE;

	return TRACE_TYPE_HANDLED;
}

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/**
 * trace_seq_printf - sequence printing of trace information
 * @s: trace sequence descriptor
 * @fmt: printf format string
 *
 * The tracer may use either sequence operations or its own
 * copy to user routines. To simplify formating of a trace
 * trace_seq_printf is used to store strings into a special
 * buffer (@s). Then the output may be either used by
 * the sequencer or pulled into another buffer.
 */
int
trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
{
	int len = (PAGE_SIZE - 1) - s->len;
	va_list ap;
	int ret;

	if (!len)
		return 0;

	va_start(ap, fmt);
	ret = vsnprintf(s->buffer + s->len, len, fmt, ap);
	va_end(ap);

	/* If we can't write it all, don't bother writing anything */
	if (ret >= len)
		return 0;

	s->len += ret;

	return len;
}

88
int trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary)
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
{
	int len = (PAGE_SIZE - 1) - s->len;
	int ret;

	if (!len)
		return 0;

	ret = bstr_printf(s->buffer + s->len, len, fmt, binary);

	/* If we can't write it all, don't bother writing anything */
	if (ret >= len)
		return 0;

	s->len += ret;

	return len;
}

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
/**
 * trace_seq_puts - trace sequence printing of simple string
 * @s: trace sequence descriptor
 * @str: simple string to record
 *
 * The tracer may use either the sequence operations or its own
 * copy to user routines. This function records a simple string
 * into a special buffer (@s) for later retrieval by a sequencer
 * or other mechanism.
 */
int trace_seq_puts(struct trace_seq *s, const char *str)
{
	int len = strlen(str);

	if (len > ((PAGE_SIZE - 1) - s->len))
		return 0;

	memcpy(s->buffer + s->len, str, len);
	s->len += len;

	return len;
}

int trace_seq_putc(struct trace_seq *s, unsigned char c)
{
	if (s->len >= (PAGE_SIZE - 1))
		return 0;

	s->buffer[s->len++] = c;

	return 1;
}

int trace_seq_putmem(struct trace_seq *s, void *mem, size_t len)
{
	if (len > ((PAGE_SIZE - 1) - s->len))
		return 0;

	memcpy(s->buffer + s->len, mem, len);
	s->len += len;

	return len;
}

int trace_seq_putmem_hex(struct trace_seq *s, void *mem, size_t len)
{
	unsigned char hex[HEX_CHARS];
	unsigned char *data = mem;
	int i, j;

#ifdef __BIG_ENDIAN
	for (i = 0, j = 0; i < len; i++) {
#else
	for (i = len-1, j = 0; i >= 0; i--) {
#endif
		hex[j++] = hex_asc_hi(data[i]);
		hex[j++] = hex_asc_lo(data[i]);
	}
	hex[j++] = ' ';

	return trace_seq_putmem(s, hex, j);
}

int trace_seq_path(struct trace_seq *s, struct path *path)
{
	unsigned char *p;

	if (s->len >= (PAGE_SIZE - 1))
		return 0;
	p = d_path(path, s->buffer + s->len, PAGE_SIZE - s->len);
	if (!IS_ERR(p)) {
		p = mangle_path(s->buffer + s->len, p, "\n");
		if (p) {
			s->len = p - s->buffer;
			return 1;
		}
	} else {
		s->buffer[s->len++] = '?';
		return 1;
	}

	return 0;
}

#ifdef CONFIG_KRETPROBES
static inline const char *kretprobed(const char *name)
{
	static const char tramp_name[] = "kretprobe_trampoline";
	int size = sizeof(tramp_name);

	if (strncmp(tramp_name, name, size) == 0)
		return "[unknown/kretprobe'd]";
	return name;
}
#else
static inline const char *kretprobed(const char *name)
{
	return name;
}
#endif /* CONFIG_KRETPROBES */

static int
seq_print_sym_short(struct trace_seq *s, const char *fmt, unsigned long address)
{
#ifdef CONFIG_KALLSYMS
	char str[KSYM_SYMBOL_LEN];
	const char *name;

	kallsyms_lookup(address, NULL, NULL, NULL, str);

	name = kretprobed(str);

	return trace_seq_printf(s, fmt, name);
#endif
	return 1;
}

static int
seq_print_sym_offset(struct trace_seq *s, const char *fmt,
		     unsigned long address)
{
#ifdef CONFIG_KALLSYMS
	char str[KSYM_SYMBOL_LEN];
	const char *name;

	sprint_symbol(str, address);
	name = kretprobed(str);

	return trace_seq_printf(s, fmt, name);
#endif
	return 1;
}

#ifndef CONFIG_64BIT
# define IP_FMT "%08lx"
#else
# define IP_FMT "%016lx"
#endif

int seq_print_user_ip(struct trace_seq *s, struct mm_struct *mm,
		      unsigned long ip, unsigned long sym_flags)
{
	struct file *file = NULL;
	unsigned long vmstart = 0;
	int ret = 1;

	if (mm) {
		const struct vm_area_struct *vma;

		down_read(&mm->mmap_sem);
		vma = find_vma(mm, ip);
		if (vma) {
			file = vma->vm_file;
			vmstart = vma->vm_start;
		}
		if (file) {
			ret = trace_seq_path(s, &file->f_path);
			if (ret)
				ret = trace_seq_printf(s, "[+0x%lx]",
						       ip - vmstart);
		}
		up_read(&mm->mmap_sem);
	}
	if (ret && ((sym_flags & TRACE_ITER_SYM_ADDR) || !file))
		ret = trace_seq_printf(s, " <" IP_FMT ">", ip);
	return ret;
}

int
seq_print_userip_objs(const struct userstack_entry *entry, struct trace_seq *s,
		      unsigned long sym_flags)
{
	struct mm_struct *mm = NULL;
	int ret = 1;
	unsigned int i;

	if (trace_flags & TRACE_ITER_SYM_USEROBJ) {
		struct task_struct *task;
		/*
		 * we do the lookup on the thread group leader,
		 * since individual threads might have already quit!
		 */
		rcu_read_lock();
		task = find_task_by_vpid(entry->ent.tgid);
		if (task)
			mm = get_task_mm(task);
		rcu_read_unlock();
	}

	for (i = 0; i < FTRACE_STACK_ENTRIES; i++) {
		unsigned long ip = entry->caller[i];

		if (ip == ULONG_MAX || !ret)
			break;
		if (i && ret)
			ret = trace_seq_puts(s, " <- ");
		if (!ip) {
			if (ret)
				ret = trace_seq_puts(s, "??");
			continue;
		}
		if (!ret)
			break;
		if (ret)
			ret = seq_print_user_ip(s, mm, ip, sym_flags);
	}

	if (mm)
		mmput(mm);
	return ret;
}

int
seq_print_ip_sym(struct trace_seq *s, unsigned long ip, unsigned long sym_flags)
{
	int ret;

	if (!ip)
		return trace_seq_printf(s, "0");

	if (sym_flags & TRACE_ITER_SYM_OFFSET)
		ret = seq_print_sym_offset(s, "%s", ip);
	else
		ret = seq_print_sym_short(s, "%s", ip);

	if (!ret)
		return 0;

	if (sym_flags & TRACE_ITER_SYM_ADDR)
		ret = trace_seq_printf(s, " <" IP_FMT ">", ip);
	return ret;
}

340
static int
341
342
343
lat_print_generic(struct trace_seq *s, struct trace_entry *entry, int cpu)
{
	int hardirq, softirq;
344
	char comm[TASK_COMM_LEN];
345

346
	trace_find_cmdline(entry->pid, comm);
347
348
	hardirq = entry->flags & TRACE_FLAG_HARDIRQ;
	softirq = entry->flags & TRACE_FLAG_SOFTIRQ;
349
350
351
352
353
354
355
356
357
358
359

	if (!trace_seq_printf(s, "%8.8s-%-5d %3d%c%c%c",
			      comm, entry->pid, cpu,
			      (entry->flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
				(entry->flags & TRACE_FLAG_IRQS_NOSUPPORT) ?
				  'X' : '.',
			      (entry->flags & TRACE_FLAG_NEED_RESCHED) ?
				'N' : '.',
			      (hardirq && softirq) ? 'H' :
				hardirq ? 'h' : softirq ? 's' : '.'))
		return 0;
360
361

	if (entry->preempt_count)
362
363
		return trace_seq_printf(s, "%x", entry->preempt_count);
	return trace_seq_puts(s, ".");
364
365
366
367
}

static unsigned long preempt_mark_thresh = 100;

368
static int
369
370
371
lat_print_timestamp(struct trace_seq *s, u64 abs_usecs,
		    unsigned long rel_usecs)
{
372
373
374
	return trace_seq_printf(s, " %4lldus%c: ", abs_usecs,
				rel_usecs > preempt_mark_thresh ? '!' :
				  rel_usecs > 1 ? '+' : ' ');
375
376
377
378
379
380
381
382
383
}

int trace_print_context(struct trace_iterator *iter)
{
	struct trace_seq *s = &iter->seq;
	struct trace_entry *entry = iter->ent;
	unsigned long long t = ns2usecs(iter->ts);
	unsigned long usec_rem = do_div(t, USEC_PER_SEC);
	unsigned long secs = (unsigned long)t;
384
385
386
	char comm[TASK_COMM_LEN];

	trace_find_cmdline(entry->pid, comm);
387

388
	return trace_seq_printf(s, "%16s-%-5d [%03d] %5lu.%06lu: ",
389
				comm, entry->pid, iter->cpu, secs, usec_rem);
390
391
392
393
394
}

int trace_print_lat_context(struct trace_iterator *iter)
{
	u64 next_ts;
395
	int ret;
396
397
398
399
400
401
402
403
404
405
406
407
408
	struct trace_seq *s = &iter->seq;
	struct trace_entry *entry = iter->ent,
			   *next_entry = trace_find_next_entry(iter, NULL,
							       &next_ts);
	unsigned long verbose = (trace_flags & TRACE_ITER_VERBOSE);
	unsigned long abs_usecs = ns2usecs(iter->ts - iter->tr->time_start);
	unsigned long rel_usecs;

	if (!next_entry)
		next_ts = iter->ts;
	rel_usecs = ns2usecs(next_ts - iter->ts);

	if (verbose) {
409
410
411
412
		char comm[TASK_COMM_LEN];

		trace_find_cmdline(entry->pid, comm);

413
414
		ret = trace_seq_printf(s, "%16s %5d %3d %d %08x %08lx [%08lx]"
				       " %ld.%03ldms (+%ld.%03ldms): ", comm,
415
				       entry->pid, iter->cpu, entry->flags,
416
417
418
419
420
421
				       entry->preempt_count, iter->idx,
				       ns2usecs(iter->ts),
				       abs_usecs / USEC_PER_MSEC,
				       abs_usecs % USEC_PER_MSEC,
				       rel_usecs / USEC_PER_MSEC,
				       rel_usecs % USEC_PER_MSEC);
422
	} else {
423
		ret = lat_print_generic(s, entry, iter->cpu);
424
425
		if (ret)
			ret = lat_print_timestamp(s, abs_usecs, rel_usecs);
426
427
	}

428
	return ret;
429
430
}

431
432
433
434
435
436
437
438
439
static const char state_to_char[] = TASK_STATE_TO_CHAR_STR;

static int task_state_char(unsigned long state)
{
	int bit = state ? __ffs(state) + 1 : 0;

	return bit < sizeof(state_to_char) - 1 ? state_to_char[bit] : '?';
}

440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
/**
 * ftrace_find_event - find a registered event
 * @type: the type of event to look for
 *
 * Returns an event of type @type otherwise NULL
 */
struct trace_event *ftrace_find_event(int type)
{
	struct trace_event *event;
	struct hlist_node *n;
	unsigned key;

	key = type & (EVENT_HASHSIZE - 1);

	hlist_for_each_entry_rcu(event, n, &event_hash[key], node) {
		if (event->type == type)
			return event;
	}

	return NULL;
}

/**
 * register_ftrace_event - register output for an event type
 * @event: the event type to register
 *
 * Event types are stored in a hash and this hash is used to
 * find a way to print an event. If the @event->type is set
 * then it will use that type, otherwise it will assign a
 * type to use.
 *
 * If you assign your own type, please make sure it is added
 * to the trace_type enum in trace.h, to avoid collisions
 * with the dynamic types.
 *
 * Returns the event type number or zero on error.
 */
int register_ftrace_event(struct trace_event *event)
{
	unsigned key;
	int ret = 0;

	mutex_lock(&trace_event_mutex);

484
485
486
487
488
	if (!event) {
		ret = next_event_type++;
		goto out;
	}

489
490
491
492
493
494
495
496
497
498
	if (!event->type)
		event->type = next_event_type++;
	else if (event->type > __TRACE_LAST_TYPE) {
		printk(KERN_WARNING "Need to add type to trace.h\n");
		WARN_ON(1);
	}

	if (ftrace_find_event(event->type))
		goto out;

499
500
501
502
503
504
505
506
507
	if (event->trace == NULL)
		event->trace = trace_nop_print;
	if (event->raw == NULL)
		event->raw = trace_nop_print;
	if (event->hex == NULL)
		event->hex = trace_nop_print;
	if (event->binary == NULL)
		event->binary = trace_nop_print;

508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
	key = event->type & (EVENT_HASHSIZE - 1);

	hlist_add_head_rcu(&event->node, &event_hash[key]);

	ret = event->type;
 out:
	mutex_unlock(&trace_event_mutex);

	return ret;
}

/**
 * unregister_ftrace_event - remove a no longer used event
 * @event: the event to remove
 */
int unregister_ftrace_event(struct trace_event *event)
{
	mutex_lock(&trace_event_mutex);
	hlist_del(&event->node);
	mutex_unlock(&trace_event_mutex);

	return 0;
}
531
532
533
534
535

/*
 * Standard events
 */

536
enum print_line_t trace_nop_print(struct trace_iterator *iter, int flags)
537
{
538
	return TRACE_TYPE_HANDLED;
539
540
541
}

/* TRACE_FN */
542
static enum print_line_t trace_fn_trace(struct trace_iterator *iter, int flags)
543
544
{
	struct ftrace_entry *field;
545
	struct trace_seq *s = &iter->seq;
546

547
	trace_assign_type(field, iter->ent);
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562

	if (!seq_print_ip_sym(s, field->ip, flags))
		goto partial;

	if ((flags & TRACE_ITER_PRINT_PARENT) && field->parent_ip) {
		if (!trace_seq_printf(s, " <-"))
			goto partial;
		if (!seq_print_ip_sym(s,
				      field->parent_ip,
				      flags))
			goto partial;
	}
	if (!trace_seq_printf(s, "\n"))
		goto partial;

563
	return TRACE_TYPE_HANDLED;
564
565
566
567
568

 partial:
	return TRACE_TYPE_PARTIAL_LINE;
}

569
static enum print_line_t trace_fn_raw(struct trace_iterator *iter, int flags)
570
571
572
{
	struct ftrace_entry *field;

573
	trace_assign_type(field, iter->ent);
574

575
	if (!trace_seq_printf(&iter->seq, "%lx %lx\n",
Lai Jiangshan's avatar
Lai Jiangshan committed
576
577
			      field->ip,
			      field->parent_ip))
578
579
		return TRACE_TYPE_PARTIAL_LINE;

580
	return TRACE_TYPE_HANDLED;
581
582
}

583
static enum print_line_t trace_fn_hex(struct trace_iterator *iter, int flags)
584
585
{
	struct ftrace_entry *field;
586
	struct trace_seq *s = &iter->seq;
587

588
	trace_assign_type(field, iter->ent);
589
590
591
592

	SEQ_PUT_HEX_FIELD_RET(s, field->ip);
	SEQ_PUT_HEX_FIELD_RET(s, field->parent_ip);

593
	return TRACE_TYPE_HANDLED;
594
595
}

596
static enum print_line_t trace_fn_bin(struct trace_iterator *iter, int flags)
597
598
{
	struct ftrace_entry *field;
599
	struct trace_seq *s = &iter->seq;
600

601
	trace_assign_type(field, iter->ent);
602
603
604
605

	SEQ_PUT_FIELD_RET(s, field->ip);
	SEQ_PUT_FIELD_RET(s, field->parent_ip);

606
	return TRACE_TYPE_HANDLED;
607
608
609
}

static struct trace_event trace_fn_event = {
610
	.type		= TRACE_FN,
611
612
613
614
615
616
617
	.trace		= trace_fn_trace,
	.raw		= trace_fn_raw,
	.hex		= trace_fn_hex,
	.binary		= trace_fn_bin,
};

/* TRACE_CTX an TRACE_WAKE */
618
619
static enum print_line_t trace_ctxwake_print(struct trace_iterator *iter,
					     char *delim)
620
621
{
	struct ctx_switch_entry *field;
622
	char comm[TASK_COMM_LEN];
623
624
	int S, T;

625

626
	trace_assign_type(field, iter->ent);
627
628
629

	T = task_state_char(field->next_state);
	S = task_state_char(field->prev_state);
630
	trace_find_cmdline(field->next_pid, comm);
631
632
	if (!trace_seq_printf(&iter->seq,
			      " %5d:%3d:%c %s [%03d] %5d:%3d:%c %s\n",
Lai Jiangshan's avatar
Lai Jiangshan committed
633
634
635
636
637
638
639
			      field->prev_pid,
			      field->prev_prio,
			      S, delim,
			      field->next_cpu,
			      field->next_pid,
			      field->next_prio,
			      T, comm))
640
641
		return TRACE_TYPE_PARTIAL_LINE;

642
	return TRACE_TYPE_HANDLED;
643
644
}

645
static enum print_line_t trace_ctx_print(struct trace_iterator *iter, int flags)
646
{
647
	return trace_ctxwake_print(iter, "==>");
648
649
}

650
651
static enum print_line_t trace_wake_print(struct trace_iterator *iter,
					  int flags)
652
{
653
	return trace_ctxwake_print(iter, "  +");
654
655
}

656
static int trace_ctxwake_raw(struct trace_iterator *iter, char S)
657
658
659
660
{
	struct ctx_switch_entry *field;
	int T;

661
	trace_assign_type(field, iter->ent);
662
663
664
665

	if (!S)
		task_state_char(field->prev_state);
	T = task_state_char(field->next_state);
666
	if (!trace_seq_printf(&iter->seq, "%d %d %c %d %d %d %c\n",
Lai Jiangshan's avatar
Lai Jiangshan committed
667
668
669
670
671
672
673
			      field->prev_pid,
			      field->prev_prio,
			      S,
			      field->next_cpu,
			      field->next_pid,
			      field->next_prio,
			      T))
674
675
		return TRACE_TYPE_PARTIAL_LINE;

676
	return TRACE_TYPE_HANDLED;
677
678
}

679
static enum print_line_t trace_ctx_raw(struct trace_iterator *iter, int flags)
680
{
681
	return trace_ctxwake_raw(iter, 0);
682
683
}

684
static enum print_line_t trace_wake_raw(struct trace_iterator *iter, int flags)
685
{
686
	return trace_ctxwake_raw(iter, '+');
687
688
689
}


690
static int trace_ctxwake_hex(struct trace_iterator *iter, char S)
691
692
{
	struct ctx_switch_entry *field;
693
	struct trace_seq *s = &iter->seq;
694
695
	int T;

696
	trace_assign_type(field, iter->ent);
697
698
699
700
701
702
703
704
705
706
707
708
709

	if (!S)
		task_state_char(field->prev_state);
	T = task_state_char(field->next_state);

	SEQ_PUT_HEX_FIELD_RET(s, field->prev_pid);
	SEQ_PUT_HEX_FIELD_RET(s, field->prev_prio);
	SEQ_PUT_HEX_FIELD_RET(s, S);
	SEQ_PUT_HEX_FIELD_RET(s, field->next_cpu);
	SEQ_PUT_HEX_FIELD_RET(s, field->next_pid);
	SEQ_PUT_HEX_FIELD_RET(s, field->next_prio);
	SEQ_PUT_HEX_FIELD_RET(s, T);

710
	return TRACE_TYPE_HANDLED;
711
712
}

713
static enum print_line_t trace_ctx_hex(struct trace_iterator *iter, int flags)
714
{
715
	return trace_ctxwake_hex(iter, 0);
716
717
}

718
static enum print_line_t trace_wake_hex(struct trace_iterator *iter, int flags)
719
{
720
	return trace_ctxwake_hex(iter, '+');
721
722
}

723
724
static enum print_line_t trace_ctxwake_bin(struct trace_iterator *iter,
					   int flags)
725
726
{
	struct ctx_switch_entry *field;
727
	struct trace_seq *s = &iter->seq;
728

729
	trace_assign_type(field, iter->ent);
730
731
732
733
734
735
736
737

	SEQ_PUT_FIELD_RET(s, field->prev_pid);
	SEQ_PUT_FIELD_RET(s, field->prev_prio);
	SEQ_PUT_FIELD_RET(s, field->prev_state);
	SEQ_PUT_FIELD_RET(s, field->next_pid);
	SEQ_PUT_FIELD_RET(s, field->next_prio);
	SEQ_PUT_FIELD_RET(s, field->next_state);

738
	return TRACE_TYPE_HANDLED;
739
740
741
}

static struct trace_event trace_ctx_event = {
742
	.type		= TRACE_CTX,
743
744
745
746
747
748
749
	.trace		= trace_ctx_print,
	.raw		= trace_ctx_raw,
	.hex		= trace_ctx_hex,
	.binary		= trace_ctxwake_bin,
};

static struct trace_event trace_wake_event = {
750
	.type		= TRACE_WAKE,
751
752
753
754
755
756
757
	.trace		= trace_wake_print,
	.raw		= trace_wake_raw,
	.hex		= trace_wake_hex,
	.binary		= trace_ctxwake_bin,
};

/* TRACE_SPECIAL */
758
759
static enum print_line_t trace_special_print(struct trace_iterator *iter,
					     int flags)
760
761
762
{
	struct special_entry *field;

763
	trace_assign_type(field, iter->ent);
764

765
	if (!trace_seq_printf(&iter->seq, "# %ld %ld %ld\n",
Lai Jiangshan's avatar
Lai Jiangshan committed
766
767
768
			      field->arg1,
			      field->arg2,
			      field->arg3))
769
770
		return TRACE_TYPE_PARTIAL_LINE;

771
	return TRACE_TYPE_HANDLED;
772
773
}

774
775
static enum print_line_t trace_special_hex(struct trace_iterator *iter,
					   int flags)
776
777
{
	struct special_entry *field;
778
	struct trace_seq *s = &iter->seq;
779

780
	trace_assign_type(field, iter->ent);
781
782
783
784
785

	SEQ_PUT_HEX_FIELD_RET(s, field->arg1);
	SEQ_PUT_HEX_FIELD_RET(s, field->arg2);
	SEQ_PUT_HEX_FIELD_RET(s, field->arg3);

786
	return TRACE_TYPE_HANDLED;
787
788
}

789
790
static enum print_line_t trace_special_bin(struct trace_iterator *iter,
					   int flags)
791
792
{
	struct special_entry *field;
793
	struct trace_seq *s = &iter->seq;
794

795
	trace_assign_type(field, iter->ent);
796
797
798
799
800

	SEQ_PUT_FIELD_RET(s, field->arg1);
	SEQ_PUT_FIELD_RET(s, field->arg2);
	SEQ_PUT_FIELD_RET(s, field->arg3);

801
	return TRACE_TYPE_HANDLED;
802
803
804
}

static struct trace_event trace_special_event = {
805
	.type		= TRACE_SPECIAL,
806
807
808
809
810
811
812
813
	.trace		= trace_special_print,
	.raw		= trace_special_print,
	.hex		= trace_special_hex,
	.binary		= trace_special_bin,
};

/* TRACE_STACK */

814
815
static enum print_line_t trace_stack_print(struct trace_iterator *iter,
					   int flags)
816
817
{
	struct stack_entry *field;
818
	struct trace_seq *s = &iter->seq;
819
820
	int i;

821
	trace_assign_type(field, iter->ent);
822
823
824

	for (i = 0; i < FTRACE_STACK_ENTRIES; i++) {
		if (i) {
Lai Jiangshan's avatar
Lai Jiangshan committed
825
			if (!trace_seq_puts(s, " <= "))
826
827
				goto partial;

Lai Jiangshan's avatar
Lai Jiangshan committed
828
			if (!seq_print_ip_sym(s, field->caller[i], flags))
829
830
				goto partial;
		}
Lai Jiangshan's avatar
Lai Jiangshan committed
831
		if (!trace_seq_puts(s, "\n"))
832
833
834
			goto partial;
	}

835
	return TRACE_TYPE_HANDLED;
836
837
838
839
840
841

 partial:
	return TRACE_TYPE_PARTIAL_LINE;
}

static struct trace_event trace_stack_event = {
842
	.type		= TRACE_STACK,
843
844
845
846
847
848
849
	.trace		= trace_stack_print,
	.raw		= trace_special_print,
	.hex		= trace_special_hex,
	.binary		= trace_special_bin,
};

/* TRACE_USER_STACK */
850
851
static enum print_line_t trace_user_stack_print(struct trace_iterator *iter,
						int flags)
852
853
{
	struct userstack_entry *field;
854
	struct trace_seq *s = &iter->seq;
855

856
	trace_assign_type(field, iter->ent);
857

Lai Jiangshan's avatar
Lai Jiangshan committed
858
	if (!seq_print_userip_objs(field, s, flags))
859
860
		goto partial;

Lai Jiangshan's avatar
Lai Jiangshan committed
861
	if (!trace_seq_putc(s, '\n'))
862
863
		goto partial;

864
	return TRACE_TYPE_HANDLED;
865
866
867
868
869
870

 partial:
	return TRACE_TYPE_PARTIAL_LINE;
}

static struct trace_event trace_user_stack_event = {
871
	.type		= TRACE_USER_STACK,
872
873
874
875
876
877
	.trace		= trace_user_stack_print,
	.raw		= trace_special_print,
	.hex		= trace_special_hex,
	.binary		= trace_special_bin,
};

878
/* TRACE_BPRINT */
879
static enum print_line_t
880
trace_bprint_print(struct trace_iterator *iter, int flags)
881
882
883
{
	struct trace_entry *entry = iter->ent;
	struct trace_seq *s = &iter->seq;
884
	struct bprint_entry *field;
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902

	trace_assign_type(field, entry);

	if (!seq_print_ip_sym(s, field->ip, flags))
		goto partial;

	if (!trace_seq_puts(s, ": "))
		goto partial;

	if (!trace_seq_bprintf(s, field->fmt, field->buf))
		goto partial;

	return TRACE_TYPE_HANDLED;

 partial:
	return TRACE_TYPE_PARTIAL_LINE;
}

903

904
905
static enum print_line_t
trace_bprint_raw(struct trace_iterator *iter, int flags)
906
{
907
	struct bprint_entry *field;
908
909
	struct trace_seq *s = &iter->seq;

910
	trace_assign_type(field, iter->ent);
911
912
913
914
915
916
917
918
919
920
921
922
923

	if (!trace_seq_printf(s, ": %lx : ", field->ip))
		goto partial;

	if (!trace_seq_bprintf(s, field->fmt, field->buf))
		goto partial;

	return TRACE_TYPE_HANDLED;

 partial:
	return TRACE_TYPE_PARTIAL_LINE;
}

924

925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
static struct trace_event trace_bprint_event = {
	.type		= TRACE_BPRINT,
	.trace		= trace_bprint_print,
	.raw		= trace_bprint_raw,
};

/* TRACE_PRINT */
static enum print_line_t trace_print_print(struct trace_iterator *iter,
					   int flags)
{
	struct print_entry *field;
	struct trace_seq *s = &iter->seq;

	trace_assign_type(field, iter->ent);

	if (!seq_print_ip_sym(s, field->ip, flags))
		goto partial;

	if (!trace_seq_printf(s, ": %s", field->buf))
		goto partial;

	return TRACE_TYPE_HANDLED;

 partial:
	return TRACE_TYPE_PARTIAL_LINE;
}

static enum print_line_t trace_print_raw(struct trace_iterator *iter, int flags)
{
	struct print_entry *field;

	trace_assign_type(field, iter->ent);

	if (!trace_seq_printf(&iter->seq, "# %lx %s", field->ip, field->buf))
		goto partial;

	return TRACE_TYPE_HANDLED;

 partial:
	return TRACE_TYPE_PARTIAL_LINE;
}

967
static struct trace_event trace_print_event = {
968
	.type	 	= TRACE_PRINT,
969
970
	.trace		= trace_print_print,
	.raw		= trace_print_raw,
971
972
};

973

974
975
976
977
978
979
980
static struct trace_event *events[] __initdata = {
	&trace_fn_event,
	&trace_ctx_event,
	&trace_wake_event,
	&trace_special_event,
	&trace_stack_event,
	&trace_user_stack_event,
981
	&trace_bprint_event,
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
	&trace_print_event,
	NULL
};

__init static int init_events(void)
{
	struct trace_event *event;
	int i, ret;

	for (i = 0; events[i]; i++) {
		event = events[i];

		ret = register_ftrace_event(event);
		if (!ret) {
			printk(KERN_WARNING "event %d failed to register\n",
			       event->type);
			WARN_ON_ONCE(1);
		}
	}