lkml.org 
[lkml]   [2011]   [Jul]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[RFC 2/4] perf, ftrace: Add filter support for ftrace:function tracepoint
Date
Add support to specify perf filter for function trace.

Standard perf filter could be now used for ftrace:function tracepoint like:

# ./perf stat -e ftrace:function --filter "ip == sys_open || ip == sys_close" sleep 1

Performance counter stats for 'sleep 1':

9 ftrace:function

1.003097430 seconds time elapsed

Details:
- the value for ip and parent_ip fields gets translated to the
function value (mcount return IP). The ip and parent_ip are then
processed as integer values.

---
include/linux/ftrace.h | 2 ++
kernel/trace/ftrace.c | 23 +++++++++++++++++++++++
kernel/trace/trace_events_filter.c | 32 ++++++++++++++++++++++++++------
3 files changed, 51 insertions(+), 6 deletions(-)

diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index ed0eb52..f858e97 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -157,6 +157,8 @@ extern void
unregister_ftrace_function_probe_func(char *glob, struct ftrace_probe_ops *ops);
extern void unregister_ftrace_function_probe_all(char *glob);

+extern int ftrace_function_rec_ip(char *func, unsigned long long *ip);
+
extern int ftrace_text_reserved(void *start, void *end);

enum {
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 6d6e0d0..7325ae4 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -2599,6 +2599,29 @@ register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
return count;
}

+int ftrace_function_rec_ip(char *func, unsigned long long *ip)
+{
+ struct ftrace_page *pg;
+ struct dyn_ftrace *rec;
+ int len = strlen(func);
+ int found = 0;
+
+ mutex_lock(&ftrace_lock);
+
+ do_for_each_ftrace_rec(pg, rec) {
+ if (!ftrace_match_record(rec, NULL, func, len, MATCH_FULL))
+ continue;
+
+ *ip = rec->ip;
+ found = 1;
+ break;
+ } while_for_each_ftrace_rec();
+
+ mutex_unlock(&ftrace_lock);
+
+ return found ? 0 : -EINVAL;
+}
+
enum {
PROBE_TEST_FUNC = 1,
PROBE_TEST_DATA = 2
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index 256764e..dd5c648 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -883,8 +883,12 @@ static bool is_string_field(struct ftrace_event_field *field)
field->filter_type == FILTER_PTR_STRING;
}

-static int is_legal_op(struct ftrace_event_field *field, int op)
+static int is_legal_op(struct ftrace_event_call *call,
+ struct ftrace_event_field *field, int op)
{
+ if ((call->event.type == TRACE_FN) &&
+ (op != OP_EQ && op != OP_NE))
+ return 0;
if (is_string_field(field) &&
(op != OP_EQ && op != OP_NE && op != OP_GLOB))
return 0;
@@ -937,6 +941,24 @@ static filter_pred_fn_t select_comparison_fn(int op, int field_size,
return fn;
}

+static int pred_get_val(struct ftrace_event_call *call,
+ struct filter_pred *pred,
+ struct ftrace_event_field *field,
+ unsigned long long *val)
+{
+ int ret;
+
+ if (call->event.type == TRACE_FN)
+ return ftrace_function_rec_ip(pred->regex.pattern, val);
+
+ if (field->is_signed)
+ ret = strict_strtoll(pred->regex.pattern, 0, val);
+ else
+ ret = strict_strtoull(pred->regex.pattern, 0, val);
+
+ return ret;
+}
+
static int filter_add_pred(struct filter_parse_state *ps,
struct ftrace_event_call *call,
struct event_filter *filter,
@@ -964,7 +986,7 @@ static int filter_add_pred(struct filter_parse_state *ps,

pred->offset = field->offset;

- if (!is_legal_op(field, pred->op)) {
+ if (!is_legal_op(call, field, pred->op)) {
parse_error(ps, FILT_ERR_ILLEGAL_FIELD_OP, 0);
return -EINVAL;
}
@@ -980,14 +1002,12 @@ static int filter_add_pred(struct filter_parse_state *ps,
else
fn = filter_pred_pchar;
} else {
- if (field->is_signed)
- ret = strict_strtoll(pred->regex.pattern, 0, &val);
- else
- ret = strict_strtoull(pred->regex.pattern, 0, &val);
+ ret = pred_get_val(call, pred, field, &val);
if (ret) {
parse_error(ps, FILT_ERR_ILLEGAL_INTVAL, 0);
return -EINVAL;
}
+
pred->val = val;

fn = select_comparison_fn(pred->op, field->size,
--
1.7.1


\
 
 \ /
  Last update: 2011-07-11 15:25    [W:0.082 / U:0.260 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site