Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+137 -99
+117
include/linux/ftrace_event.h
··· 370 370 extern void event_triggers_post_call(struct ftrace_event_file *file, 371 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 + */ 382 + static inline bool 383 + ftrace_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 + */ 409 + static 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 + */ 442 + static inline void 443 + event_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 + */ 473 + static inline void 474 + event_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 + 373 490 enum { 374 491 FILTER_OTHER = 0, 375 492 FILTER_STATIC_STRING,
+4 -19
include/trace/ftrace.h
··· 546 546 struct ftrace_event_file *ftrace_file = __data; \ 547 547 struct ftrace_event_call *event_call = ftrace_file->event_call; \ 548 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 549 struct ring_buffer_event *event; \ 552 550 struct ftrace_raw_##call *entry; \ 553 551 struct ring_buffer *buffer; \ ··· 553 555 int __data_size; \ 554 556 int pc; \ 555 557 \ 556 - if (!(eflags & FTRACE_EVENT_FL_TRIGGER_COND)) { \ 557 - if (eflags & FTRACE_EVENT_FL_TRIGGER_MODE) \ 558 - event_triggers_call(ftrace_file, NULL); \ 559 - if (eflags & FTRACE_EVENT_FL_SOFT_DISABLED) \ 560 - return; \ 561 - } \ 558 + if (ftrace_trigger_soft_disabled(ftrace_file)) \ 559 + return; \ 562 560 \ 563 561 local_save_flags(irq_flags); \ 564 562 pc = preempt_count(); \ ··· 573 579 \ 574 580 { assign; } \ 575 581 \ 576 - if (eflags & FTRACE_EVENT_FL_TRIGGER_COND) \ 577 - __tt = event_triggers_call(ftrace_file, entry); \ 578 - \ 579 - if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, \ 580 - &ftrace_file->flags)) \ 581 - ring_buffer_discard_commit(buffer, event); \ 582 - else if (!filter_check_discard(ftrace_file, entry, buffer, event)) \ 583 - trace_buffer_unlock_commit(buffer, event, irq_flags, pc); \ 584 - \ 585 - if (__tt) \ 586 - event_triggers_post_call(ftrace_file, __tt); \ 582 + event_trigger_unlock_commit(ftrace_file, buffer, event, entry, \ 583 + irq_flags, pc); \ 587 584 } 588 585 /* 589 586 * The ftrace_test_probe is compiled out, it is only here as a build time check
+8 -40
kernel/trace/trace_kprobe.c
··· 929 929 struct ring_buffer *buffer; 930 930 int size, dsize, pc; 931 931 unsigned long irq_flags; 932 - unsigned long eflags; 933 - enum event_trigger_type tt = ETT_NONE; 934 932 struct ftrace_event_call *call = &tk->tp.call; 935 933 936 934 WARN_ON(call != ftrace_file->event_call); 937 935 938 - eflags = ftrace_file->flags; 939 - 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 - } 936 + if (ftrace_trigger_soft_disabled(ftrace_file)) 937 + return; 946 938 947 939 local_save_flags(irq_flags); 948 940 pc = preempt_count(); ··· 952 960 entry->ip = (unsigned long)tk->rp.kp.addr; 953 961 store_trace_args(sizeof(*entry), &tk->tp, regs, (u8 *)&entry[1], dsize); 954 962 955 - if (eflags & FTRACE_EVENT_FL_TRIGGER_COND) 956 - tt = event_triggers_call(ftrace_file, entry); 957 - 958 - if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &ftrace_file->flags)) 959 - ring_buffer_discard_commit(buffer, event); 960 - else if (!filter_check_discard(ftrace_file, entry, buffer, event)) 961 - trace_buffer_unlock_commit_regs(buffer, event, 962 - irq_flags, pc, regs); 963 - if (tt) 964 - event_triggers_post_call(ftrace_file, tt); 963 + event_trigger_unlock_commit_regs(ftrace_file, buffer, event, 964 + entry, irq_flags, pc, regs); 965 965 } 966 966 967 967 static __kprobes void ··· 976 992 struct ring_buffer *buffer; 977 993 int size, pc, dsize; 978 994 unsigned long irq_flags; 979 - unsigned long eflags; 980 - enum event_trigger_type tt = ETT_NONE; 981 995 struct ftrace_event_call *call = &tk->tp.call; 982 996 983 997 WARN_ON(call != ftrace_file->event_call); 984 998 985 - eflags = ftrace_file->flags; 986 - 987 - if (!(eflags & FTRACE_EVENT_FL_TRIGGER_COND)) { 988 - if (eflags & FTRACE_EVENT_FL_TRIGGER_MODE) 989 - event_triggers_call(ftrace_file, NULL); 990 - if (eflags & FTRACE_EVENT_FL_SOFT_DISABLED) 991 - return; 992 - } 999 + if (ftrace_trigger_soft_disabled(ftrace_file)) 1000 + return; 993 1001 994 1002 local_save_flags(irq_flags); 995 1003 pc = preempt_count(); ··· 1000 1024 entry->ret_ip = (unsigned long)ri->ret_addr; 1001 1025 store_trace_args(sizeof(*entry), &tk->tp, regs, (u8 *)&entry[1], dsize); 1002 1026 1003 - if (eflags & FTRACE_EVENT_FL_TRIGGER_COND) 1004 - tt = event_triggers_call(ftrace_file, entry); 1005 - 1006 - if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &ftrace_file->flags)) 1007 - ring_buffer_discard_commit(buffer, event); 1008 - else if (!filter_check_discard(ftrace_file, entry, buffer, event)) 1009 - trace_buffer_unlock_commit_regs(buffer, event, 1010 - irq_flags, pc, regs); 1011 - if (tt) 1012 - event_triggers_post_call(ftrace_file, tt); 1027 + event_trigger_unlock_commit_regs(ftrace_file, buffer, event, 1028 + entry, irq_flags, pc, regs); 1013 1029 } 1014 1030 1015 1031 static __kprobes void
+8 -40
kernel/trace/trace_syscalls.c
··· 306 306 struct syscall_trace_enter *entry; 307 307 struct syscall_metadata *sys_data; 308 308 struct ring_buffer_event *event; 309 - enum event_trigger_type tt = ETT_NONE; 310 309 struct ring_buffer *buffer; 311 310 unsigned long irq_flags; 312 - unsigned long eflags; 313 311 int pc; 314 312 int syscall_nr; 315 313 int size; ··· 321 323 if (!ftrace_file) 322 324 return; 323 325 324 - eflags = ftrace_file->flags; 325 - 326 - if (!(eflags & FTRACE_EVENT_FL_TRIGGER_COND)) { 327 - if (eflags & FTRACE_EVENT_FL_TRIGGER_MODE) 328 - event_triggers_call(ftrace_file, NULL); 329 - if (eflags & FTRACE_EVENT_FL_SOFT_DISABLED) 330 - return; 331 - } 326 + if (ftrace_trigger_soft_disabled(ftrace_file)) 327 + return; 332 328 333 329 sys_data = syscall_nr_to_meta(syscall_nr); 334 330 if (!sys_data) ··· 343 351 entry->nr = syscall_nr; 344 352 syscall_get_arguments(current, regs, 0, sys_data->nb_args, entry->args); 345 353 346 - if (eflags & FTRACE_EVENT_FL_TRIGGER_COND) 347 - tt = event_triggers_call(ftrace_file, entry); 348 - 349 - if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &ftrace_file->flags)) 350 - ring_buffer_discard_commit(buffer, event); 351 - else if (!filter_check_discard(ftrace_file, entry, buffer, event)) 352 - trace_current_buffer_unlock_commit(buffer, event, 353 - irq_flags, pc); 354 - if (tt) 355 - event_triggers_post_call(ftrace_file, tt); 354 + event_trigger_unlock_commit(ftrace_file, buffer, event, entry, 355 + irq_flags, pc); 356 356 } 357 357 358 358 static void ftrace_syscall_exit(void *data, struct pt_regs *regs, long ret) ··· 354 370 struct syscall_trace_exit *entry; 355 371 struct syscall_metadata *sys_data; 356 372 struct ring_buffer_event *event; 357 - enum event_trigger_type tt = ETT_NONE; 358 373 struct ring_buffer *buffer; 359 374 unsigned long irq_flags; 360 - unsigned long eflags; 361 375 int pc; 362 376 int syscall_nr; 363 377 ··· 368 386 if (!ftrace_file) 369 387 return; 370 388 371 - eflags = ftrace_file->flags; 372 - 373 - if (!(eflags & FTRACE_EVENT_FL_TRIGGER_COND)) { 374 - if (eflags & FTRACE_EVENT_FL_TRIGGER_MODE) 375 - event_triggers_call(ftrace_file, NULL); 376 - if (eflags & FTRACE_EVENT_FL_SOFT_DISABLED) 377 - return; 378 - } 389 + if (ftrace_trigger_soft_disabled(ftrace_file)) 390 + return; 379 391 380 392 sys_data = syscall_nr_to_meta(syscall_nr); 381 393 if (!sys_data) ··· 389 413 entry->nr = syscall_nr; 390 414 entry->ret = syscall_get_return_value(current, regs); 391 415 392 - if (eflags & FTRACE_EVENT_FL_TRIGGER_COND) 393 - tt = event_triggers_call(ftrace_file, entry); 394 - 395 - if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &ftrace_file->flags)) 396 - ring_buffer_discard_commit(buffer, event); 397 - else if (!filter_check_discard(ftrace_file, entry, buffer, event)) 398 - trace_current_buffer_unlock_commit(buffer, event, 399 - irq_flags, pc); 400 - if (tt) 401 - event_triggers_post_call(ftrace_file, tt); 416 + event_trigger_unlock_commit(ftrace_file, buffer, event, entry, 417 + irq_flags, pc); 402 418 } 403 419 404 420 static int reg_event_syscall_enter(struct ftrace_event_file *file,