Skip to content

Commit

Permalink
tracing: Update event filters for multibuffer
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Steven Rostedt <[email protected]>
  • Loading branch information
tzanussi authored and rostedt committed Nov 5, 2013
1 parent f02b625 commit f306cc8
Show file tree
Hide file tree
Showing 15 changed files with 264 additions and 102 deletions.
25 changes: 20 additions & 5 deletions include/linux/ftrace_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ enum {
TRACE_EVENT_FL_NO_SET_FILTER_BIT,
TRACE_EVENT_FL_IGNORE_ENABLE_BIT,
TRACE_EVENT_FL_WAS_ENABLED_BIT,
TRACE_EVENT_FL_USE_CALL_FILTER_BIT,
};

/*
Expand All @@ -213,13 +214,15 @@ enum {
* WAS_ENABLED - Set and stays set when an event was ever enabled
* (used for module unloading, if a module event is enabled,
* it is best to clear the buffers that used it).
* USE_CALL_FILTER - For ftrace internal events, don't use file filter
*/
enum {
TRACE_EVENT_FL_FILTERED = (1 << TRACE_EVENT_FL_FILTERED_BIT),
TRACE_EVENT_FL_CAP_ANY = (1 << TRACE_EVENT_FL_CAP_ANY_BIT),
TRACE_EVENT_FL_NO_SET_FILTER = (1 << TRACE_EVENT_FL_NO_SET_FILTER_BIT),
TRACE_EVENT_FL_IGNORE_ENABLE = (1 << TRACE_EVENT_FL_IGNORE_ENABLE_BIT),
TRACE_EVENT_FL_WAS_ENABLED = (1 << TRACE_EVENT_FL_WAS_ENABLED_BIT),
TRACE_EVENT_FL_USE_CALL_FILTER = (1 << TRACE_EVENT_FL_USE_CALL_FILTER_BIT),
};

struct ftrace_event_call {
Expand All @@ -238,6 +241,7 @@ struct ftrace_event_call {
* bit 2: failed to apply filter
* bit 3: ftrace internal event (do not enable)
* bit 4: Event was enabled by module
* bit 5: use call filter rather than file filter
*/
int flags; /* static flags of different events */

Expand All @@ -253,6 +257,8 @@ struct ftrace_subsystem_dir;
enum {
FTRACE_EVENT_FL_ENABLED_BIT,
FTRACE_EVENT_FL_RECORDED_CMD_BIT,
FTRACE_EVENT_FL_FILTERED_BIT,
FTRACE_EVENT_FL_NO_SET_FILTER_BIT,
FTRACE_EVENT_FL_SOFT_MODE_BIT,
FTRACE_EVENT_FL_SOFT_DISABLED_BIT,
};
Expand All @@ -261,20 +267,25 @@ enum {
* Ftrace event file flags:
* ENABLED - The event is enabled
* RECORDED_CMD - The comms should be recorded at sched_switch
* FILTERED - The event has a filter attached
* NO_SET_FILTER - Set when filter has error and is to be ignored
* SOFT_MODE - The event is enabled/disabled by SOFT_DISABLED
* SOFT_DISABLED - When set, do not trace the event (even though its
* tracepoint may be enabled)
*/
enum {
FTRACE_EVENT_FL_ENABLED = (1 << FTRACE_EVENT_FL_ENABLED_BIT),
FTRACE_EVENT_FL_RECORDED_CMD = (1 << FTRACE_EVENT_FL_RECORDED_CMD_BIT),
FTRACE_EVENT_FL_FILTERED = (1 << FTRACE_EVENT_FL_FILTERED_BIT),
FTRACE_EVENT_FL_NO_SET_FILTER = (1 << FTRACE_EVENT_FL_NO_SET_FILTER_BIT),
FTRACE_EVENT_FL_SOFT_MODE = (1 << FTRACE_EVENT_FL_SOFT_MODE_BIT),
FTRACE_EVENT_FL_SOFT_DISABLED = (1 << FTRACE_EVENT_FL_SOFT_DISABLED_BIT),
};

struct ftrace_event_file {
struct list_head list;
struct ftrace_event_call *event_call;
struct event_filter *filter;
struct dentry *dir;
struct trace_array *tr;
struct ftrace_subsystem_dir *system;
Expand Down Expand Up @@ -310,12 +321,16 @@ struct ftrace_event_file {

#define MAX_FILTER_STR_VAL 256 /* Should handle KSYM_SYMBOL_LEN */

extern void destroy_preds(struct ftrace_event_call *call);
extern void destroy_preds(struct ftrace_event_file *file);
extern void destroy_call_preds(struct ftrace_event_call *call);
extern int filter_match_preds(struct event_filter *filter, void *rec);
extern int filter_current_check_discard(struct ring_buffer *buffer,
struct ftrace_event_call *call,
void *rec,
struct ring_buffer_event *event);

extern int filter_check_discard(struct ftrace_event_file *file, void *rec,
struct ring_buffer *buffer,
struct ring_buffer_event *event);
extern int call_filter_check_discard(struct ftrace_event_call *call, void *rec,
struct ring_buffer *buffer,
struct ring_buffer_event *event);

enum {
FILTER_OTHER = 0,
Expand Down
4 changes: 2 additions & 2 deletions include/linux/syscalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ extern struct trace_event_functions exit_syscall_print_funcs;
.class = &event_class_syscall_enter, \
.event.funcs = &enter_syscall_print_funcs, \
.data = (void *)&__syscall_meta_##sname,\
.flags = TRACE_EVENT_FL_CAP_ANY, \
.flags = TRACE_EVENT_FL_CAP_ANY | TRACE_EVENT_FL_USE_CALL_FILTER,\
}; \
static struct ftrace_event_call __used \
__attribute__((section("_ftrace_events"))) \
Expand All @@ -134,7 +134,7 @@ extern struct trace_event_functions exit_syscall_print_funcs;
.class = &event_class_syscall_exit, \
.event.funcs = &exit_syscall_print_funcs, \
.data = (void *)&__syscall_meta_##sname,\
.flags = TRACE_EVENT_FL_CAP_ANY, \
.flags = TRACE_EVENT_FL_CAP_ANY | TRACE_EVENT_FL_USE_CALL_FILTER,\
}; \
static struct ftrace_event_call __used \
__attribute__((section("_ftrace_events"))) \
Expand Down
7 changes: 3 additions & 4 deletions include/trace/ftrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -437,9 +437,8 @@ static inline notrace int ftrace_get_offsets_##call( \
* { <assign>; } <-- Here we assign the entries by the __field and
* __array macros.
*
* if (!filter_current_check_discard(buffer, event_call, entry, event))
* trace_nowake_buffer_unlock_commit(buffer,
* event, irq_flags, pc);
* if (!filter_check_discard(ftrace_file, entry, buffer, event))
* trace_buffer_unlock_commit(buffer, event, irq_flags, pc);
* }
*
* static struct trace_event ftrace_event_type_<call> = {
Expand Down Expand Up @@ -553,7 +552,7 @@ ftrace_raw_event_##call(void *__data, proto) \
\
{ assign; } \
\
if (!filter_current_check_discard(buffer, event_call, entry, event)) \
if (!filter_check_discard(ftrace_file, entry, buffer, event)) \
trace_buffer_unlock_commit(buffer, event, irq_flags, pc); \
}
/*
Expand Down
40 changes: 30 additions & 10 deletions kernel/trace/trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -235,13 +235,33 @@ void trace_array_put(struct trace_array *this_tr)
mutex_unlock(&trace_types_lock);
}

int filter_current_check_discard(struct ring_buffer *buffer,
struct ftrace_event_call *call, void *rec,
struct ring_buffer_event *event)
int filter_check_discard(struct ftrace_event_file *file, void *rec,
struct ring_buffer *buffer,
struct ring_buffer_event *event)
{
return filter_check_discard(call, rec, buffer, event);
if (unlikely(file->flags & FTRACE_EVENT_FL_FILTERED) &&
!filter_match_preds(file->filter, rec)) {
ring_buffer_discard_commit(buffer, event);
return 1;
}

return 0;
}
EXPORT_SYMBOL_GPL(filter_check_discard);

int call_filter_check_discard(struct ftrace_event_call *call, void *rec,
struct ring_buffer *buffer,
struct ring_buffer_event *event)
{
if (unlikely(call->flags & TRACE_EVENT_FL_FILTERED) &&
!filter_match_preds(call->filter, rec)) {
ring_buffer_discard_commit(buffer, event);
return 1;
}

return 0;
}
EXPORT_SYMBOL_GPL(filter_current_check_discard);
EXPORT_SYMBOL_GPL(call_filter_check_discard);

cycle_t buffer_ftrace_now(struct trace_buffer *buf, int cpu)
{
Expand Down Expand Up @@ -1633,7 +1653,7 @@ trace_function(struct trace_array *tr,
entry->ip = ip;
entry->parent_ip = parent_ip;

if (!filter_check_discard(call, entry, buffer, event))
if (!call_filter_check_discard(call, entry, buffer, event))
__buffer_unlock_commit(buffer, event);
}

Expand Down Expand Up @@ -1717,7 +1737,7 @@ static void __ftrace_trace_stack(struct ring_buffer *buffer,

entry->size = trace.nr_entries;

if (!filter_check_discard(call, entry, buffer, event))
if (!call_filter_check_discard(call, entry, buffer, event))
__buffer_unlock_commit(buffer, event);

out:
Expand Down Expand Up @@ -1819,7 +1839,7 @@ ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags, int pc)
trace.entries = entry->caller;

save_stack_trace_user(&trace);
if (!filter_check_discard(call, entry, buffer, event))
if (!call_filter_check_discard(call, entry, buffer, event))
__buffer_unlock_commit(buffer, event);

out_drop_count:
Expand Down Expand Up @@ -2011,7 +2031,7 @@ int trace_vbprintk(unsigned long ip, const char *fmt, va_list args)
entry->fmt = fmt;

memcpy(entry->buf, tbuffer, sizeof(u32) * len);
if (!filter_check_discard(call, entry, buffer, event)) {
if (!call_filter_check_discard(call, entry, buffer, event)) {
__buffer_unlock_commit(buffer, event);
ftrace_trace_stack(buffer, flags, 6, pc);
}
Expand Down Expand Up @@ -2066,7 +2086,7 @@ __trace_array_vprintk(struct ring_buffer *buffer,

memcpy(&entry->buf, tbuffer, len);
entry->buf[len] = '\0';
if (!filter_check_discard(call, entry, buffer, event)) {
if (!call_filter_check_discard(call, entry, buffer, event)) {
__buffer_unlock_commit(buffer, event);
ftrace_trace_stack(buffer, flags, 6, pc);
}
Expand Down
18 changes: 2 additions & 16 deletions kernel/trace/trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -1007,9 +1007,9 @@ struct filter_pred {

extern enum regex_type
filter_parse_regex(char *buff, int len, char **search, int *not);
extern void print_event_filter(struct ftrace_event_call *call,
extern void print_event_filter(struct ftrace_event_file *file,
struct trace_seq *s);
extern int apply_event_filter(struct ftrace_event_call *call,
extern int apply_event_filter(struct ftrace_event_file *file,
char *filter_string);
extern int apply_subsystem_event_filter(struct ftrace_subsystem_dir *dir,
char *filter_string);
Expand All @@ -1020,20 +1020,6 @@ extern int filter_assign_type(const char *type);
struct ftrace_event_field *
trace_find_event_field(struct ftrace_event_call *call, char *name);

static inline int
filter_check_discard(struct ftrace_event_call *call, void *rec,
struct ring_buffer *buffer,
struct ring_buffer_event *event)
{
if (unlikely(call->flags & TRACE_EVENT_FL_FILTERED) &&
!filter_match_preds(call->filter, rec)) {
ring_buffer_discard_commit(buffer, event);
return 1;
}

return 0;
}

extern void trace_event_enable_cmd_record(bool enable);
extern int event_trace_add_tracer(struct dentry *parent, struct trace_array *tr);
extern int event_trace_del_tracer(struct trace_array *tr);
Expand Down
2 changes: 1 addition & 1 deletion kernel/trace/trace_branch.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ probe_likely_condition(struct ftrace_branch_data *f, int val, int expect)
entry->line = f->line;
entry->correct = val == expect;

if (!filter_check_discard(call, entry, buffer, event))
if (!call_filter_check_discard(call, entry, buffer, event))
__buffer_unlock_commit(buffer, event);

out:
Expand Down
23 changes: 12 additions & 11 deletions kernel/trace/trace_events.c
Original file line number Diff line number Diff line change
Expand Up @@ -989,7 +989,7 @@ static ssize_t
event_filter_read(struct file *filp, char __user *ubuf, size_t cnt,
loff_t *ppos)
{
struct ftrace_event_call *call;
struct ftrace_event_file *file;
struct trace_seq *s;
int r = -ENODEV;

Expand All @@ -1004,12 +1004,12 @@ event_filter_read(struct file *filp, char __user *ubuf, size_t cnt,
trace_seq_init(s);

mutex_lock(&event_mutex);
call = event_file_data(filp);
if (call)
print_event_filter(call, s);
file = event_file_data(filp);
if (file)
print_event_filter(file, s);
mutex_unlock(&event_mutex);

if (call)
if (file)
r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len);

kfree(s);
Expand All @@ -1021,7 +1021,7 @@ static ssize_t
event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt,
loff_t *ppos)
{
struct ftrace_event_call *call;
struct ftrace_event_file *file;
char *buf;
int err = -ENODEV;

Expand All @@ -1039,9 +1039,9 @@ event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt,
buf[cnt] = '\0';

mutex_lock(&event_mutex);
call = event_file_data(filp);
if (call)
err = apply_event_filter(call, buf);
file = event_file_data(filp);
if (file)
err = apply_event_filter(file, buf);
mutex_unlock(&event_mutex);

free_page((unsigned long) buf);
Expand Down Expand Up @@ -1539,7 +1539,7 @@ event_create_dir(struct dentry *parent, struct ftrace_event_file *file)
return -1;
}
}
trace_create_file("filter", 0644, file->dir, call,
trace_create_file("filter", 0644, file->dir, file,
&ftrace_event_filter_fops);

trace_create_file("format", 0444, file->dir, call,
Expand Down Expand Up @@ -1577,6 +1577,7 @@ static void event_remove(struct ftrace_event_call *call)
if (file->event_call != call)
continue;
ftrace_event_enable_disable(file, 0);
destroy_preds(file);
/*
* The do_for_each_event_file() is
* a double loop. After finding the call for this
Expand Down Expand Up @@ -1700,7 +1701,7 @@ static void __trace_remove_event_call(struct ftrace_event_call *call)
{
event_remove(call);
trace_destroy_fields(call);
destroy_preds(call);
destroy_call_preds(call);
}

static int probe_remove_event_call(struct ftrace_event_call *call)
Expand Down
Loading

0 comments on commit f306cc8

Please sign in to comment.