aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt (Red Hat) <rostedt@goodmis.org>2014-01-06 21:32:10 -0500
committerSteven Rostedt <rostedt@goodmis.org>2014-01-09 21:20:07 -0500
commit13a1e4aef53b2a7684ddee374e749999ba103b4a (patch)
tree74acb760b6d12d4faaae4c4c76a146855e8352a5
parente8dc637152d2921447b012f58c51e0342304af33 (diff)
tracing: Consolidate event trigger code
The event trigger code that checks for callback triggers before and after recording of an event has lots of flags checks. This code is duplicated throughout the ftrace events, kprobes and system calls. They all do the exact same checks against the event flags. Added helper functions ftrace_trigger_soft_disabled(), event_trigger_unlock_commit() and event_trigger_unlock_commit_regs() that consolidated the code and these are used instead. Link: http://lkml.kernel.org/r/20140106222703.5e7dbba2@gandalf.local.home Acked-by: Tom Zanussi <tom.zanussi@linux.intel.com> Tested-by: Tom Zanussi <tom.zanussi@linux.intel.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--include/linux/ftrace_event.h117
-rw-r--r--include/trace/ftrace.h23
-rw-r--r--kernel/trace/trace_kprobe.c48
-rw-r--r--kernel/trace/trace_syscalls.c48
4 files changed, 137 insertions, 99 deletions
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
index 03d2db22ad0d..4e4cc28623ad 100644
--- a/include/linux/ftrace_event.h
+++ b/include/linux/ftrace_event.h
@@ -370,6 +370,123 @@ extern enum event_trigger_type event_triggers_call(struct ftrace_event_file *fil
370extern void event_triggers_post_call(struct ftrace_event_file *file, 370extern void event_triggers_post_call(struct ftrace_event_file *file,
371 enum event_trigger_type tt); 371 enum event_trigger_type tt);
372 372
373/**
374 * ftrace_trigger_soft_disabled - do triggers and test if soft disabled
375 * @file: The file pointer of the event to test
376 *
377 * If any triggers without filters are attached to this event, they
378 * will be called here. If the event is soft disabled and has no
379 * triggers that require testing the fields, it will return true,
380 * otherwise false.
381 */
382static inline bool
383ftrace_trigger_soft_disabled(struct ftrace_event_file *file)
384{
385 unsigned long eflags = file->flags;
386
387 if (!(eflags & FTRACE_EVENT_FL_TRIGGER_COND)) {
388 if (eflags & FTRACE_EVENT_FL_TRIGGER_MODE)
389 event_triggers_call(file, NULL);
390 if (eflags & FTRACE_EVENT_FL_SOFT_DISABLED)
391 return true;
392 }
393 return false;
394}
395
396/*
397 * Helper function for event_trigger_unlock_commit{_regs}().
398 * If there are event triggers attached to this event that requires
399 * filtering against its fields, then they wil be called as the
400 * entry already holds the field information of the current event.
401 *
402 * It also checks if the event should be discarded or not.
403 * It is to be discarded if the event is soft disabled and the
404 * event was only recorded to process triggers, or if the event
405 * filter is active and this event did not match the filters.
406 *
407 * Returns true if the event is discarded, false otherwise.
408 */
409static inline bool
410__event_trigger_test_discard(struct ftrace_event_file *file,
411 struct ring_buffer *buffer,
412 struct ring_buffer_event *event,
413 void *entry,
414 enum event_trigger_type *tt)
415{
416 unsigned long eflags = file->flags;
417
418 if (eflags & FTRACE_EVENT_FL_TRIGGER_COND)
419 *tt = event_triggers_call(file, entry);
420
421 if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &file->flags))
422 ring_buffer_discard_commit(buffer, event);
423 else if (!filter_check_discard(file, entry, buffer, event))
424 return false;
425
426 return true;
427}
428
429/**
430 * event_trigger_unlock_commit - handle triggers and finish event commit
431 * @file: The file pointer assoctiated to the event
432 * @buffer: The ring buffer that the event is being written to
433 * @event: The event meta data in the ring buffer
434 * @entry: The event itself
435 * @irq_flags: The state of the interrupts at the start of the event
436 * @pc: The state of the preempt count at the start of the event.
437 *
438 * This is a helper function to handle triggers that require data
439 * from the event itself. It also tests the event against filters and
440 * if the event is soft disabled and should be discarded.
441 */
442static inline void
443event_trigger_unlock_commit(struct ftrace_event_file *file,
444 struct ring_buffer *buffer,
445 struct ring_buffer_event *event,
446 void *entry, unsigned long irq_flags, int pc)
447{
448 enum event_trigger_type tt = ETT_NONE;
449
450 if (!__event_trigger_test_discard(file, buffer, event, entry, &tt))
451 trace_buffer_unlock_commit(buffer, event, irq_flags, pc);
452
453 if (tt)
454 event_triggers_post_call(file, tt);
455}
456
457/**
458 * event_trigger_unlock_commit_regs - handle triggers and finish event commit
459 * @file: The file pointer assoctiated to the event
460 * @buffer: The ring buffer that the event is being written to
461 * @event: The event meta data in the ring buffer
462 * @entry: The event itself
463 * @irq_flags: The state of the interrupts at the start of the event
464 * @pc: The state of the preempt count at the start of the event.
465 *
466 * This is a helper function to handle triggers that require data
467 * from the event itself. It also tests the event against filters and
468 * if the event is soft disabled and should be discarded.
469 *
470 * Same as event_trigger_unlock_commit() but calls
471 * trace_buffer_unlock_commit_regs() instead of trace_buffer_unlock_commit().
472 */
473static inline void
474event_trigger_unlock_commit_regs(struct ftrace_event_file *file,
475 struct ring_buffer *buffer,
476 struct ring_buffer_event *event,
477 void *entry, unsigned long irq_flags, int pc,
478 struct pt_regs *regs)
479{
480 enum event_trigger_type tt = ETT_NONE;
481
482 if (!__event_trigger_test_discard(file, buffer, event, entry, &tt))
483 trace_buffer_unlock_commit_regs(buffer, event,
484 irq_flags, pc, regs);
485
486 if (tt)
487 event_triggers_post_call(file, tt);
488}
489
373enum { 490enum {
374 FILTER_OTHER = 0, 491 FILTER_OTHER = 0,
375 FILTER_STATIC_STRING, 492 FILTER_STATIC_STRING,
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h
index 0962968b8b37..1a8b28db3775 100644
--- a/include/trace/ftrace.h
+++ b/include/trace/ftrace.h
@@ -546,8 +546,6 @@ ftrace_raw_event_##call(void *__data, proto) \
546 struct ftrace_event_file *ftrace_file = __data; \ 546 struct ftrace_event_file *ftrace_file = __data; \
547 struct ftrace_event_call *event_call = ftrace_file->event_call; \ 547 struct ftrace_event_call *event_call = ftrace_file->event_call; \
548 struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\ 548 struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\
549 unsigned long eflags = ftrace_file->flags; \
550 enum event_trigger_type __tt = ETT_NONE; \
551 struct ring_buffer_event *event; \ 549 struct ring_buffer_event *event; \
552 struct ftrace_raw_##call *entry; \ 550 struct ftrace_raw_##call *entry; \
553 struct ring_buffer *buffer; \ 551 struct ring_buffer *buffer; \
@@ -555,12 +553,8 @@ ftrace_raw_event_##call(void *__data, proto) \
555 int __data_size; \ 553 int __data_size; \
556 int pc; \ 554 int pc; \
557 \ 555 \
558 if (!(eflags & FTRACE_EVENT_FL_TRIGGER_COND)) { \ 556 if (ftrace_trigger_soft_disabled(ftrace_file)) \
559 if (eflags & FTRACE_EVENT_FL_TRIGGER_MODE) \ 557 return; \
560 event_triggers_call(ftrace_file, NULL); \
561 if (eflags & FTRACE_EVENT_FL_SOFT_DISABLED) \
562 return; \
563 } \
564 \ 558 \
565 local_save_flags(irq_flags); \ 559 local_save_flags(irq_flags); \
566 pc = preempt_count(); \ 560 pc = preempt_count(); \
@@ -579,17 +573,8 @@ ftrace_raw_event_##call(void *__data, proto) \
579 \ 573 \
580 { assign; } \ 574 { assign; } \
581 \ 575 \
582 if (eflags & FTRACE_EVENT_FL_TRIGGER_COND) \ 576 event_trigger_unlock_commit(ftrace_file, buffer, event, entry, \
583 __tt = event_triggers_call(ftrace_file, entry); \ 577 irq_flags, pc); \
584 \
585 if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, \
586 &ftrace_file->flags)) \
587 ring_buffer_discard_commit(buffer, event); \
588 else if (!filter_check_discard(ftrace_file, entry, buffer, event)) \
589 trace_buffer_unlock_commit(buffer, event, irq_flags, pc); \
590 \
591 if (__tt) \
592 event_triggers_post_call(ftrace_file, __tt); \
593} 578}
594/* 579/*
595 * The ftrace_test_probe is compiled out, it is only here as a build time check 580 * The ftrace_test_probe is compiled out, it is only here as a build time check
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 3afa716d6268..bdbae450c13e 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -929,20 +929,12 @@ __kprobe_trace_func(struct trace_kprobe *tk, struct pt_regs *regs,
929 struct ring_buffer *buffer; 929 struct ring_buffer *buffer;
930 int size, dsize, pc; 930 int size, dsize, pc;
931 unsigned long irq_flags; 931 unsigned long irq_flags;
932 unsigned long eflags;
933 enum event_trigger_type tt = ETT_NONE;
934 struct ftrace_event_call *call = &tk->tp.call; 932 struct ftrace_event_call *call = &tk->tp.call;
935 933
936 WARN_ON(call != ftrace_file->event_call); 934 WARN_ON(call != ftrace_file->event_call);
937 935
938 eflags = ftrace_file->flags; 936 if (ftrace_trigger_soft_disabled(ftrace_file))
939 937 return;
940 if (!(eflags & FTRACE_EVENT_FL_TRIGGER_COND)) {
941 if (eflags & FTRACE_EVENT_FL_TRIGGER_MODE)
942 event_triggers_call(ftrace_file, NULL);
943 if (eflags & FTRACE_EVENT_FL_SOFT_DISABLED)
944 return;
945 }
946 938
947 local_save_flags(irq_flags); 939 local_save_flags(irq_flags);
948 pc = preempt_count(); 940 pc = preempt_count();
@@ -960,16 +952,8 @@ __kprobe_trace_func(struct trace_kprobe *tk, struct pt_regs *regs,
960 entry->ip = (unsigned long)tk->rp.kp.addr; 952 entry->ip = (unsigned long)tk->rp.kp.addr;
961 store_trace_args(sizeof(*entry), &tk->tp, regs, (u8 *)&entry[1], dsize); 953 store_trace_args(sizeof(*entry), &tk->tp, regs, (u8 *)&entry[1], dsize);
962 954
963 if (eflags & FTRACE_EVENT_FL_TRIGGER_COND) 955 event_trigger_unlock_commit_regs(ftrace_file, buffer, event,
964 tt = event_triggers_call(ftrace_file, entry); 956 entry, irq_flags, pc, regs);
965
966 if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &ftrace_file->flags))
967 ring_buffer_discard_commit(buffer, event);
968 else if (!filter_check_discard(ftrace_file, entry, buffer, event))
969 trace_buffer_unlock_commit_regs(buffer, event,
970 irq_flags, pc, regs);
971 if (tt)
972 event_triggers_post_call(ftrace_file, tt);
973} 957}
974 958
975static __kprobes void 959static __kprobes void
@@ -992,20 +976,12 @@ __kretprobe_trace_func(struct trace_kprobe *tk, struct kretprobe_instance *ri,
992 struct ring_buffer *buffer; 976 struct ring_buffer *buffer;
993 int size, pc, dsize; 977 int size, pc, dsize;
994 unsigned long irq_flags; 978 unsigned long irq_flags;
995 unsigned long eflags;
996 enum event_trigger_type tt = ETT_NONE;
997 struct ftrace_event_call *call = &tk->tp.call; 979 struct ftrace_event_call *call = &tk->tp.call;
998 980
999 WARN_ON(call != ftrace_file->event_call); 981 WARN_ON(call != ftrace_file->event_call);
1000 982
1001 eflags = ftrace_file->flags; 983 if (ftrace_trigger_soft_disabled(ftrace_file))
1002 984 return;
1003 if (!(eflags & FTRACE_EVENT_FL_TRIGGER_COND)) {
1004 if (eflags & FTRACE_EVENT_FL_TRIGGER_MODE)
1005 event_triggers_call(ftrace_file, NULL);
1006 if (eflags & FTRACE_EVENT_FL_SOFT_DISABLED)
1007 return;
1008 }
1009 985
1010 local_save_flags(irq_flags); 986 local_save_flags(irq_flags);
1011 pc = preempt_count(); 987 pc = preempt_count();
@@ -1024,16 +1000,8 @@ __kretprobe_trace_func(struct trace_kprobe *tk, struct kretprobe_instance *ri,
1024 entry->ret_ip = (unsigned long)ri->ret_addr; 1000 entry->ret_ip = (unsigned long)ri->ret_addr;
1025 store_trace_args(sizeof(*entry), &tk->tp, regs, (u8 *)&entry[1], dsize); 1001 store_trace_args(sizeof(*entry), &tk->tp, regs, (u8 *)&entry[1], dsize);
1026 1002
1027 if (eflags & FTRACE_EVENT_FL_TRIGGER_COND) 1003 event_trigger_unlock_commit_regs(ftrace_file, buffer, event,
1028 tt = event_triggers_call(ftrace_file, entry); 1004 entry, irq_flags, pc, regs);
1029
1030 if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &ftrace_file->flags))
1031 ring_buffer_discard_commit(buffer, event);
1032 else if (!filter_check_discard(ftrace_file, entry, buffer, event))
1033 trace_buffer_unlock_commit_regs(buffer, event,
1034 irq_flags, pc, regs);
1035 if (tt)
1036 event_triggers_post_call(ftrace_file, tt);
1037} 1005}
1038 1006
1039static __kprobes void 1007static __kprobes void
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
index a4acf9bbffa7..759d5e004517 100644
--- a/kernel/trace/trace_syscalls.c
+++ b/kernel/trace/trace_syscalls.c
@@ -306,10 +306,8 @@ static void ftrace_syscall_enter(void *data, struct pt_regs *regs, long id)
306 struct syscall_trace_enter *entry; 306 struct syscall_trace_enter *entry;
307 struct syscall_metadata *sys_data; 307 struct syscall_metadata *sys_data;
308 struct ring_buffer_event *event; 308 struct ring_buffer_event *event;
309 enum event_trigger_type tt = ETT_NONE;
310 struct ring_buffer *buffer; 309 struct ring_buffer *buffer;
311 unsigned long irq_flags; 310 unsigned long irq_flags;
312 unsigned long eflags;
313 int pc; 311 int pc;
314 int syscall_nr; 312 int syscall_nr;
315 int size; 313 int size;
@@ -323,14 +321,8 @@ static void ftrace_syscall_enter(void *data, struct pt_regs *regs, long id)
323 if (!ftrace_file) 321 if (!ftrace_file)
324 return; 322 return;
325 323
326 eflags = ftrace_file->flags; 324 if (ftrace_trigger_soft_disabled(ftrace_file))
327 325 return;
328 if (!(eflags & FTRACE_EVENT_FL_TRIGGER_COND)) {
329 if (eflags & FTRACE_EVENT_FL_TRIGGER_MODE)
330 event_triggers_call(ftrace_file, NULL);
331 if (eflags & FTRACE_EVENT_FL_SOFT_DISABLED)
332 return;
333 }
334 326
335 sys_data = syscall_nr_to_meta(syscall_nr); 327 sys_data = syscall_nr_to_meta(syscall_nr);
336 if (!sys_data) 328 if (!sys_data)
@@ -351,16 +343,8 @@ static void ftrace_syscall_enter(void *data, struct pt_regs *regs, long id)
351 entry->nr = syscall_nr; 343 entry->nr = syscall_nr;
352 syscall_get_arguments(current, regs, 0, sys_data->nb_args, entry->args); 344 syscall_get_arguments(current, regs, 0, sys_data->nb_args, entry->args);
353 345
354 if (eflags & FTRACE_EVENT_FL_TRIGGER_COND) 346 event_trigger_unlock_commit(ftrace_file, buffer, event, entry,
355 tt = event_triggers_call(ftrace_file, entry); 347 irq_flags, pc);
356
357 if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &ftrace_file->flags))
358 ring_buffer_discard_commit(buffer, event);
359 else if (!filter_check_discard(ftrace_file, entry, buffer, event))
360 trace_current_buffer_unlock_commit(buffer, event,
361 irq_flags, pc);
362 if (tt)
363 event_triggers_post_call(ftrace_file, tt);
364} 348}
365 349
366static void ftrace_syscall_exit(void *data, struct pt_regs *regs, long ret) 350static void ftrace_syscall_exit(void *data, struct pt_regs *regs, long ret)
@@ -370,10 +354,8 @@ static void ftrace_syscall_exit(void *data, struct pt_regs *regs, long ret)
370 struct syscall_trace_exit *entry; 354 struct syscall_trace_exit *entry;
371 struct syscall_metadata *sys_data; 355 struct syscall_metadata *sys_data;
372 struct ring_buffer_event *event; 356 struct ring_buffer_event *event;
373 enum event_trigger_type tt = ETT_NONE;
374 struct ring_buffer *buffer; 357 struct ring_buffer *buffer;
375 unsigned long irq_flags; 358 unsigned long irq_flags;
376 unsigned long eflags;
377 int pc; 359 int pc;
378 int syscall_nr; 360 int syscall_nr;
379 361
@@ -386,14 +368,8 @@ static void ftrace_syscall_exit(void *data, struct pt_regs *regs, long ret)
386 if (!ftrace_file) 368 if (!ftrace_file)
387 return; 369 return;
388 370
389 eflags = ftrace_file->flags; 371 if (ftrace_trigger_soft_disabled(ftrace_file))
390 372 return;
391 if (!(eflags & FTRACE_EVENT_FL_TRIGGER_COND)) {
392 if (eflags & FTRACE_EVENT_FL_TRIGGER_MODE)
393 event_triggers_call(ftrace_file, NULL);
394 if (eflags & FTRACE_EVENT_FL_SOFT_DISABLED)
395 return;
396 }
397 373
398 sys_data = syscall_nr_to_meta(syscall_nr); 374 sys_data = syscall_nr_to_meta(syscall_nr);
399 if (!sys_data) 375 if (!sys_data)
@@ -413,16 +389,8 @@ static void ftrace_syscall_exit(void *data, struct pt_regs *regs, long ret)
413 entry->nr = syscall_nr; 389 entry->nr = syscall_nr;
414 entry->ret = syscall_get_return_value(current, regs); 390 entry->ret = syscall_get_return_value(current, regs);
415 391
416 if (eflags & FTRACE_EVENT_FL_TRIGGER_COND) 392 event_trigger_unlock_commit(ftrace_file, buffer, event, entry,
417 tt = event_triggers_call(ftrace_file, entry); 393 irq_flags, pc);
418
419 if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &ftrace_file->flags))
420 ring_buffer_discard_commit(buffer, event);
421 else if (!filter_check_discard(ftrace_file, entry, buffer, event))
422 trace_current_buffer_unlock_commit(buffer, event,
423 irq_flags, pc);
424 if (tt)
425 event_triggers_post_call(ftrace_file, tt);
426} 394}
427 395
428static int reg_event_syscall_enter(struct ftrace_event_file *file, 396static int reg_event_syscall_enter(struct ftrace_event_file *file,