forked from Minki/linux
f306cc82a9
The trace event filters are still tied to event calls rather than event files, which means you don't get what you'd expect when using filters in the multibuffer case: Before: # echo 'bytes_alloc > 8192' > /sys/kernel/debug/tracing/events/kmem/kmalloc/filter # cat /sys/kernel/debug/tracing/events/kmem/kmalloc/filter bytes_alloc > 8192 # mkdir /sys/kernel/debug/tracing/instances/test1 # echo 'bytes_alloc > 2048' > /sys/kernel/debug/tracing/instances/test1/events/kmem/kmalloc/filter # cat /sys/kernel/debug/tracing/events/kmem/kmalloc/filter bytes_alloc > 2048 # cat /sys/kernel/debug/tracing/instances/test1/events/kmem/kmalloc/filter bytes_alloc > 2048 Setting the filter in tracing/instances/test1/events shouldn't affect the same event in tracing/events as it does above. After: # echo 'bytes_alloc > 8192' > /sys/kernel/debug/tracing/events/kmem/kmalloc/filter # cat /sys/kernel/debug/tracing/events/kmem/kmalloc/filter bytes_alloc > 8192 # mkdir /sys/kernel/debug/tracing/instances/test1 # echo 'bytes_alloc > 2048' > /sys/kernel/debug/tracing/instances/test1/events/kmem/kmalloc/filter # cat /sys/kernel/debug/tracing/events/kmem/kmalloc/filter bytes_alloc > 8192 # cat /sys/kernel/debug/tracing/instances/test1/events/kmem/kmalloc/filter bytes_alloc > 2048 We'd like to just move the filter directly from ftrace_event_call to ftrace_event_file, but there are a couple cases that don't yet have multibuffer support and therefore have to continue using the current event_call-based filters. For those cases, a new USE_CALL_FILTER bit is added to the event_call flags, whose main purpose is to keep the old behavior for those cases until they can be updated with multibuffer support; at that point, the USE_CALL_FILTER flag (and the new associated call_filter_check_discard() function) can go away. The multibuffer support also made filter_current_check_discard() redundant, so this change removes that function as well and replaces it with filter_check_discard() (or call_filter_check_discard() as appropriate). Link: http://lkml.kernel.org/r/f16e9ce4270c62f46b2e966119225e1c3cca7e60.1382620672.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi <tom.zanussi@linux.intel.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
199 lines
5.3 KiB
C
199 lines
5.3 KiB
C
/*
|
|
* trace_export.c - export basic ftrace utilities to user space
|
|
*
|
|
* Copyright (C) 2009 Steven Rostedt <srostedt@redhat.com>
|
|
*/
|
|
#include <linux/stringify.h>
|
|
#include <linux/kallsyms.h>
|
|
#include <linux/seq_file.h>
|
|
#include <linux/debugfs.h>
|
|
#include <linux/uaccess.h>
|
|
#include <linux/ftrace.h>
|
|
#include <linux/module.h>
|
|
#include <linux/init.h>
|
|
#include <linux/fs.h>
|
|
|
|
#include "trace_output.h"
|
|
|
|
#undef TRACE_SYSTEM
|
|
#define TRACE_SYSTEM ftrace
|
|
|
|
/*
|
|
* The FTRACE_ENTRY_REG macro allows ftrace entry to define register
|
|
* function and thus become accesible via perf.
|
|
*/
|
|
#undef FTRACE_ENTRY_REG
|
|
#define FTRACE_ENTRY_REG(name, struct_name, id, tstruct, print, \
|
|
filter, regfn) \
|
|
FTRACE_ENTRY(name, struct_name, id, PARAMS(tstruct), PARAMS(print), \
|
|
filter)
|
|
|
|
/* not needed for this file */
|
|
#undef __field_struct
|
|
#define __field_struct(type, item)
|
|
|
|
#undef __field
|
|
#define __field(type, item) type item;
|
|
|
|
#undef __field_desc
|
|
#define __field_desc(type, container, item) type item;
|
|
|
|
#undef __array
|
|
#define __array(type, item, size) type item[size];
|
|
|
|
#undef __array_desc
|
|
#define __array_desc(type, container, item, size) type item[size];
|
|
|
|
#undef __dynamic_array
|
|
#define __dynamic_array(type, item) type item[];
|
|
|
|
#undef F_STRUCT
|
|
#define F_STRUCT(args...) args
|
|
|
|
#undef F_printk
|
|
#define F_printk(fmt, args...) fmt, args
|
|
|
|
#undef FTRACE_ENTRY
|
|
#define FTRACE_ENTRY(name, struct_name, id, tstruct, print, filter) \
|
|
struct ____ftrace_##name { \
|
|
tstruct \
|
|
}; \
|
|
static void __always_unused ____ftrace_check_##name(void) \
|
|
{ \
|
|
struct ____ftrace_##name *__entry = NULL; \
|
|
\
|
|
/* force compile-time check on F_printk() */ \
|
|
printk(print); \
|
|
}
|
|
|
|
#undef FTRACE_ENTRY_DUP
|
|
#define FTRACE_ENTRY_DUP(name, struct_name, id, tstruct, print, filter) \
|
|
FTRACE_ENTRY(name, struct_name, id, PARAMS(tstruct), PARAMS(print), \
|
|
filter)
|
|
|
|
#include "trace_entries.h"
|
|
|
|
#undef __field
|
|
#define __field(type, item) \
|
|
ret = trace_define_field(event_call, #type, #item, \
|
|
offsetof(typeof(field), item), \
|
|
sizeof(field.item), \
|
|
is_signed_type(type), filter_type); \
|
|
if (ret) \
|
|
return ret;
|
|
|
|
#undef __field_desc
|
|
#define __field_desc(type, container, item) \
|
|
ret = trace_define_field(event_call, #type, #item, \
|
|
offsetof(typeof(field), \
|
|
container.item), \
|
|
sizeof(field.container.item), \
|
|
is_signed_type(type), filter_type); \
|
|
if (ret) \
|
|
return ret;
|
|
|
|
#undef __array
|
|
#define __array(type, item, len) \
|
|
do { \
|
|
BUILD_BUG_ON(len > MAX_FILTER_STR_VAL); \
|
|
mutex_lock(&event_storage_mutex); \
|
|
snprintf(event_storage, sizeof(event_storage), \
|
|
"%s[%d]", #type, len); \
|
|
ret = trace_define_field(event_call, event_storage, #item, \
|
|
offsetof(typeof(field), item), \
|
|
sizeof(field.item), \
|
|
is_signed_type(type), filter_type); \
|
|
mutex_unlock(&event_storage_mutex); \
|
|
if (ret) \
|
|
return ret; \
|
|
} while (0);
|
|
|
|
#undef __array_desc
|
|
#define __array_desc(type, container, item, len) \
|
|
BUILD_BUG_ON(len > MAX_FILTER_STR_VAL); \
|
|
ret = trace_define_field(event_call, #type "[" #len "]", #item, \
|
|
offsetof(typeof(field), \
|
|
container.item), \
|
|
sizeof(field.container.item), \
|
|
is_signed_type(type), filter_type); \
|
|
if (ret) \
|
|
return ret;
|
|
|
|
#undef __dynamic_array
|
|
#define __dynamic_array(type, item) \
|
|
ret = trace_define_field(event_call, #type, #item, \
|
|
offsetof(typeof(field), item), \
|
|
0, is_signed_type(type), filter_type);\
|
|
if (ret) \
|
|
return ret;
|
|
|
|
#undef FTRACE_ENTRY
|
|
#define FTRACE_ENTRY(name, struct_name, id, tstruct, print, filter) \
|
|
static int __init \
|
|
ftrace_define_fields_##name(struct ftrace_event_call *event_call) \
|
|
{ \
|
|
struct struct_name field; \
|
|
int ret; \
|
|
int filter_type = filter; \
|
|
\
|
|
tstruct; \
|
|
\
|
|
return ret; \
|
|
}
|
|
|
|
#include "trace_entries.h"
|
|
|
|
#undef __entry
|
|
#define __entry REC
|
|
|
|
#undef __field
|
|
#define __field(type, item)
|
|
|
|
#undef __field_desc
|
|
#define __field_desc(type, container, item)
|
|
|
|
#undef __array
|
|
#define __array(type, item, len)
|
|
|
|
#undef __array_desc
|
|
#define __array_desc(type, container, item, len)
|
|
|
|
#undef __dynamic_array
|
|
#define __dynamic_array(type, item)
|
|
|
|
#undef F_printk
|
|
#define F_printk(fmt, args...) __stringify(fmt) ", " __stringify(args)
|
|
|
|
#undef FTRACE_ENTRY_REG
|
|
#define FTRACE_ENTRY_REG(call, struct_name, etype, tstruct, print, filter,\
|
|
regfn) \
|
|
\
|
|
struct ftrace_event_class __refdata event_class_ftrace_##call = { \
|
|
.system = __stringify(TRACE_SYSTEM), \
|
|
.define_fields = ftrace_define_fields_##call, \
|
|
.fields = LIST_HEAD_INIT(event_class_ftrace_##call.fields),\
|
|
.reg = regfn, \
|
|
}; \
|
|
\
|
|
struct ftrace_event_call __used event_##call = { \
|
|
.name = #call, \
|
|
.event.type = etype, \
|
|
.class = &event_class_ftrace_##call, \
|
|
.print_fmt = print, \
|
|
.flags = TRACE_EVENT_FL_IGNORE_ENABLE | TRACE_EVENT_FL_USE_CALL_FILTER, \
|
|
}; \
|
|
struct ftrace_event_call __used \
|
|
__attribute__((section("_ftrace_events"))) *__event_##call = &event_##call;
|
|
|
|
#undef FTRACE_ENTRY
|
|
#define FTRACE_ENTRY(call, struct_name, etype, tstruct, print, filter) \
|
|
FTRACE_ENTRY_REG(call, struct_name, etype, \
|
|
PARAMS(tstruct), PARAMS(print), filter, NULL)
|
|
|
|
int ftrace_event_is_function(struct ftrace_event_call *call)
|
|
{
|
|
return call == &event_function;
|
|
}
|
|
|
|
#include "trace_entries.h"
|