ftrace: Support full glob matching
authorMasami Hiramatsu <mhiramat@kernel.org>
Wed, 5 Oct 2016 11:58:15 +0000 (20:58 +0900)
committerSteven Rostedt <rostedt@goodmis.org>
Mon, 14 Nov 2016 21:42:58 +0000 (16:42 -0500)
Use glob_match() to support flexible glob wildcards (*,?)
and character classes ([) for ftrace.
Since the full glob matching is slower than the current
partial matching routines(*pat, pat*, *pat*), this leaves
those routines and just add MATCH_GLOB for complex glob
expression.

e.g.
----
[root@localhost tracing]# echo 'sched*group' > set_ftrace_filter
[root@localhost tracing]# cat set_ftrace_filter
sched_free_group
sched_change_group
sched_create_group
sched_online_group
sched_destroy_group
sched_offline_group
[root@localhost tracing]# echo '[Ss]y[Ss]_*' > set_ftrace_filter
[root@localhost tracing]# head set_ftrace_filter
sys_arch_prctl
sys_rt_sigreturn
sys_ioperm
SyS_iopl
sys_modify_ldt
SyS_mmap
SyS_set_thread_area
SyS_get_thread_area
SyS_set_tid_address
sys_fork
----

Link: http://lkml.kernel.org/r/147566869501.29136.6462645009894738056.stgit@devbox
Acked-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Documentation/trace/events.txt
Documentation/trace/ftrace.txt
kernel/trace/Kconfig
kernel/trace/ftrace.c
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_events_filter.c

index 08d74d75150ddb40564c8da0187034412277b964..2cc08d4a326e120cab3c87b60f8cf67934604fd9 100644 (file)
@@ -189,16 +189,13 @@ And for string fields they are:
 
 ==, !=, ~
 
-The glob (~) only accepts a wild card character (*) at the start and or
-end of the string. For example:
+The glob (~) accepts a wild card character (*,?) and character classes
+([). For example:
 
   prev_comm ~ "*sh"
   prev_comm ~ "sh*"
   prev_comm ~ "*sh*"
-
-But does not allow for it to be within the string:
-
-  prev_comm ~ "ba*sh"   <-- is invalid
+  prev_comm ~ "ba*sh"
 
 5.2 Setting filters
 -------------------
index 185c39fea2a022b6c6a7910e07a925d9688f542f..1bc66c1db0cbd9c302ab82f975061407edaec4db 100644 (file)
@@ -2218,16 +2218,13 @@ hrtimer_interrupt
 sys_nanosleep
 
 
-Perhaps this is not enough. The filters also allow simple wild
-cards. Only the following are currently available
+Perhaps this is not enough. The filters also allow glob(7) matching.
 
   <match>*  - will match functions that begin with <match>
   *<match>  - will match functions that end with <match>
   *<match>* - will match functions that have <match> in it
-
-These are the only wild cards which are supported.
-
-  <match>*<match> will not work.
+  <match1>*<match2> - will match functions that begin with
+                      <match1> and end with <match2>
 
 Note: It is better to use quotes to enclose the wild cards,
       otherwise the shell may expand the parameters into names
index 2a96b063d6590f326410feaa55fbb7f817241c0c..d5038005eb5dc06dd8432cc17e5be3c2c1de7e81 100644 (file)
@@ -70,6 +70,7 @@ config FTRACE_NMI_ENTER
 
 config EVENT_TRACING
        select CONTEXT_SWITCH_TRACER
+        select GLOB
        bool
 
 config CONTEXT_SWITCH_TRACER
@@ -133,6 +134,7 @@ config FUNCTION_TRACER
        select KALLSYMS
        select GENERIC_TRACER
        select CONTEXT_SWITCH_TRACER
+        select GLOB
        help
          Enable the kernel to trace every kernel function. This is done
          by using a compiler feature to insert a small, 5-byte No-Operation
index da87b3cba5b39aabb264dcf046b500c12259b0a0..356bb70d071e0001d2690c1b191dc8b282dd35d0 100644 (file)
@@ -3511,6 +3511,10 @@ static int ftrace_match(char *str, struct ftrace_glob *g)
                    memcmp(str + slen - g->len, g->search, g->len) == 0)
                        matched = 1;
                break;
+       case MATCH_GLOB:
+               if (glob_match(g->search, str))
+                       matched = 1;
+               break;
        }
 
        return matched;
index 8696ce6bf2f68838caefb8025ae3a6b133a2de64..d904516dfdab4de5010647222f9a6c6ee312fd07 100644 (file)
@@ -4065,7 +4065,7 @@ static const char readme_msg[] =
        "\n  available_filter_functions - list of functions that can be filtered on\n"
        "  set_ftrace_filter\t- echo function name in here to only trace these\n"
        "\t\t\t  functions\n"
-       "\t     accepts: func_full_name, *func_end, func_begin*, *func_middle*\n"
+       "\t     accepts: func_full_name or glob-matching-pattern\n"
        "\t     modules: Can select a group via module\n"
        "\t      Format: :mod:<module-name>\n"
        "\t     example: echo :mod:ext3 > set_ftrace_filter\n"
index fd24b1f9ac439730ac95815204084141e1b79966..4b7918902ab8b5cc64424415de6b4b47044ffd87 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/trace_events.h>
 #include <linux/compiler.h>
 #include <linux/trace_seq.h>
+#include <linux/glob.h>
 
 #ifdef CONFIG_FTRACE_SYSCALLS
 #include <asm/unistd.h>                /* For NR_SYSCALLS           */
@@ -1257,6 +1258,7 @@ enum regex_type {
        MATCH_FRONT_ONLY,
        MATCH_MIDDLE_ONLY,
        MATCH_END_ONLY,
+       MATCH_GLOB,
 };
 
 struct regex {
index 9daa9b3bc6d9133eaffd29723d68c4d3bcd8878a..e1c7e2cdc2407f960dc969efa735bce308e0c04a 100644 (file)
@@ -344,6 +344,12 @@ static int regex_match_end(char *str, struct regex *r, int len)
        return 0;
 }
 
+static int regex_match_glob(char *str, struct regex *r, int len __maybe_unused)
+{
+       if (glob_match(r->pattern, str))
+               return 1;
+       return 0;
+}
 /**
  * filter_parse_regex - parse a basic regex
  * @buff:   the raw regex
@@ -380,14 +386,20 @@ enum regex_type filter_parse_regex(char *buff, int len, char **search, int *not)
                        if (!i) {
                                *search = buff + 1;
                                type = MATCH_END_ONLY;
-                       } else {
+                       } else if (i == len - 1) {
                                if (type == MATCH_END_ONLY)
                                        type = MATCH_MIDDLE_ONLY;
                                else
                                        type = MATCH_FRONT_ONLY;
                                buff[i] = 0;
                                break;
+                       } else {        /* pattern continues, use full glob */
+                               type = MATCH_GLOB;
+                               break;
                        }
+               } else if (strchr("[?\\", buff[i])) {
+                       type = MATCH_GLOB;
+                       break;
                }
        }
 
@@ -420,6 +432,9 @@ static void filter_build_regex(struct filter_pred *pred)
        case MATCH_END_ONLY:
                r->match = regex_match_end;
                break;
+       case MATCH_GLOB:
+               r->match = regex_match_glob;
+               break;
        }
 
        pred->not ^= not;