Messages in this thread Patch in this message |  | | | From | Frederic Weisbecker <> | | Subject | [RFC][PATCH 5/5] tracing/filters: Provide support for char * pointers | | Date | Sat, 1 Aug 2009 09:23:28 +0200 |
| |
Provide support for char * pointers in the filtering framework. Usually, char * entries are dangerous in traces because the string can be released whereas a pointer to it can still wait to be read from the ring buffer. But sometimes we can assume it's safe, like in case of RO data (eg: __file__ or __line__, used in bkl trace event). If these RO data are in a module and so is the call to the trace event, then it's safe, because the ring buffer will be flushed once this module get unloaded.
Now the bkl events becomes more useful. Say that you want to trace only the bkl use in reiserfs:
cd /debug/tracing/events/bkl/lock_kernel echo "file == fs/reiserfs*" > filter_regex cat /debug/tracing/trace syslogd-3658 [001] 1874.661878: lock_kernel: depth: 1, fs/reiserfs/super.c:563 reiserfs_dirty_inode() syslogd-3658 [001] 1874.662266: lock_kernel: depth: 0, fs/reiserfs/inode.c:2695 reiserfs_write_end() syslogd-3658 [001] 1874.662268: lock_kernel: depth: 1, fs/reiserfs/super.c:563 reiserfs_dirty_inode() syslogd-3658 [001] 1874.662291: lock_kernel: depth: 0, fs/reiserfs/inode.c:2695 reiserfs_write_end()
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Tom Zanussi <tzanussi@gmail.com> Cc: Steven Rostedt <rostedt@goodmis.org> --- kernel/trace/trace_events_filter.c | 34 +++++++++++++++++++++++++++++----- 1 files changed, 29 insertions(+), 5 deletions(-) diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index 51b4e24..071c93e 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c @@ -160,6 +160,20 @@ static int filter_pred_string(struct filter_pred *pred, void *event, return match; } +/* Filter predicate for char * pointers */ +static int filter_pred_pchar(struct filter_pred *pred, void *event, + int val1, int val2) +{ + char **addr = (char **)(event + pred->offset); + int cmp, match; + + cmp = pred->regex.match(*addr, &pred->regex); + + match = (!!cmp) ^ pred->not; + + return match; +} + /* * Filter predicate for dynamic sized arrays of characters. * These are implemented through a list of strings at the end @@ -547,6 +561,7 @@ static int filter_add_pred_fn(struct filter_parse_state *ps, enum { FILTER_STATIC_STRING = 1, FILTER_DYN_STRING, + FILTER_PTR_STRING }; static int is_string_field(const char *type) @@ -557,6 +572,9 @@ static int is_string_field(const char *type) if (strchr(type, '[') && strstr(type, "char")) return FILTER_STATIC_STRING; + if (strstr(type, "char *")) + return FILTER_PTR_STRING; + return 0; } @@ -646,12 +664,18 @@ static int filter_add_pred(struct filter_parse_state *ps, string_type = is_string_field(field->type); if (string_type) { - if (string_type == FILTER_DYN_STRING) - fn = filter_pred_strloc; - else - fn = filter_pred_string; + if (string_type == FILTER_PTR_STRING) { + fn = filter_pred_pchar; + pred->regex.len = strlen(pred->regex.pattern); + } else { + pred->regex.len = field->size; + + if (string_type == FILTER_DYN_STRING) + fn = filter_pred_strloc; + else + fn = filter_pred_string; + } - pred->regex.len = field->size; if (pred->op == OP_NE) pred->not = 1; -- 1.6.2.3
|  |