diff options
author | Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> | 2015-05-05 11:29:48 +0900 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2015-05-05 18:13:02 -0300 |
commit | 307a464b2342a502da492f0ada8cefd6ab7f63a7 (patch) | |
tree | 318a2eda0b78732cf4219c3a5bead24a3eee940a | |
parent | 2dd6d8a10a942c5fd8950d1046e172237d009c8e (diff) |
perf probe: Allow to use filter on --del command
This makes perf-probe --del option to accept filter rules
not only simple glob pattern. This simplifies the code and
improve the flexibility.
E.g. if we remove 2 different pattern events, we need 2
-d options.
----
# ./perf probe -d vfs\* -d malloc
Removed event: probe_libc:malloc
Removed event: probe:vfs_read
----
This allows you to joint the 2 patterns with '|'.
----
# ./perf probe -d 'vfs*|malloc'
Removed event: probe:vfs_read
Removed event: probe_libc:malloc
----
Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20150505022948.23399.4197.stgit@localhost.localdomain
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r-- | tools/perf/builtin-probe.c | 16 | ||||
-rw-r--r-- | tools/perf/util/probe-event.c | 102 | ||||
-rw-r--r-- | tools/perf/util/probe-event.h | 2 |
3 files changed, 39 insertions, 81 deletions
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index feca3165f957..1f41b4eb0c5a 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c @@ -55,12 +55,12 @@ static struct { bool show_ext_vars; bool show_funcs; bool mod_events; + bool del_events; bool uprobes; bool quiet; bool target_used; int nevents; struct perf_probe_event events[MAX_PROBES]; - struct strlist *dellist; struct line_range line_range; char *target; int max_probe_points; @@ -195,10 +195,8 @@ static int opt_del_probe_event(const struct option *opt __maybe_unused, const char *str, int unset __maybe_unused) { if (str) { - params.mod_events = true; - if (!params.dellist) - params.dellist = strlist__new(true, NULL); - strlist__add(params.dellist, str); + params.del_events = true; + return params_add_filter(str); } return 0; } @@ -313,8 +311,6 @@ static void cleanup_params(void) for (i = 0; i < params.nevents; i++) clear_perf_probe_event(params.events + i); - if (params.dellist) - strlist__delete(params.dellist); line_range__clear(¶ms.line_range); free(params.target); if (params.filter) @@ -454,7 +450,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) if (params.max_probe_points == 0) params.max_probe_points = MAX_PROBES; - if ((!params.nevents && !params.dellist && !params.list_events && + if ((!params.nevents && !params.del_events && !params.list_events && !params.show_lines && !params.show_funcs)) usage_with_options(probe_usage, options); @@ -514,8 +510,8 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) } #endif - if (params.dellist) { - ret = del_perf_probe_events(params.dellist); + if (params.del_events) { + ret = del_perf_probe_events(params.filter); if (ret < 0) { pr_err_with_code(" Error: Failed to delete events.", ret); return ret; diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 5995d81d2bad..abf5845a2acc 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -2734,40 +2734,39 @@ error: return ret; } -static int del_trace_probe_event(int fd, const char *buf, - struct strlist *namelist) +static int del_trace_probe_events(int fd, struct strfilter *filter, + struct strlist *namelist) { - struct str_node *ent, *n; + struct str_node *ent; + const char *p; int ret = -ENOENT; - if (strpbrk(buf, "*?")) { /* Glob-exp */ - strlist__for_each_safe(ent, n, namelist) - if (strglobmatch(ent->s, buf)) { - ret = __del_trace_probe_event(fd, ent); - if (ret < 0) - break; - strlist__remove(namelist, ent); - } - } else { - ent = strlist__find(namelist, buf); - if (ent) { + if (!namelist) + return -ENOENT; + + strlist__for_each(ent, namelist) { + p = strchr(ent->s, ':'); + if ((p && strfilter__compare(filter, p + 1)) || + strfilter__compare(filter, ent->s)) { ret = __del_trace_probe_event(fd, ent); - if (ret >= 0) - strlist__remove(namelist, ent); + if (ret < 0) + break; } } return ret; } -int del_perf_probe_events(struct strlist *dellist) +int del_perf_probe_events(struct strfilter *filter) { - int ret = -1, ret2, ufd = -1, kfd = -1; - char buf[128]; - const char *group, *event; - char *p, *str; - struct str_node *ent; + int ret, ret2, ufd = -1, kfd = -1; struct strlist *namelist = NULL, *unamelist = NULL; + char *str = strfilter__string(filter); + + if (!str) + return -EINVAL; + + pr_debug("Delete filter: \'%s\'\n", str); /* Get current event names */ kfd = open_kprobe_events(true); @@ -2780,59 +2779,21 @@ int del_perf_probe_events(struct strlist *dellist) if (kfd < 0 && ufd < 0) { print_both_open_warning(kfd, ufd); + ret = kfd; goto error; } - if (namelist == NULL && unamelist == NULL) { - ret = -ENOENT; + ret = del_trace_probe_events(kfd, filter, namelist); + if (ret < 0 && ret != -ENOENT) goto error; - } - - strlist__for_each(ent, dellist) { - str = strdup(ent->s); - if (str == NULL) { - ret = -ENOMEM; - goto error; - } - pr_debug("Parsing: %s\n", str); - p = strchr(str, ':'); - if (p) { - group = str; - *p = '\0'; - event = p + 1; - } else { - group = "*"; - event = str; - } - if (event && *event == '.') - event++; - - ret = e_snprintf(buf, 128, "%s:%s", group, event); - if (ret < 0) { - pr_err("Failed to copy event."); - free(str); - goto error; - } - - pr_debug("Group: %s, Event: %s\n", group, event); - free(str); - - ret = ret2 = -ENOENT; - if (namelist) - ret = del_trace_probe_event(kfd, buf, namelist); - - if ((ret >= 0 || ret == -ENOENT) && unamelist) - ret2 = del_trace_probe_event(ufd, buf, unamelist); - - /* Since we can remove probes which already removed, don't check it */ - if (ret == -ENOENT && ret2 == -ENOENT) - pr_debug("Event \"%s\" does not exist.\n", buf); - else if (ret < 0 || ret2 < 0) { - if (ret >= 0) - ret = ret2; - break; - } + ret2 = del_trace_probe_events(ufd, filter, unamelist); + if (ret2 < 0 && ret2 != -ENOENT) + ret = ret2; + else if (ret == -ENOENT && ret2 == -ENOENT) { + pr_debug("\"%s\" does not hit any event.\n", str); + /* Note that this is silently ignored */ + ret = 0; } error: @@ -2845,6 +2806,7 @@ error: strlist__delete(unamelist); close(ufd); } + free(str); return ret; } diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index ec13362d882f..e10aedc34570 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h @@ -126,7 +126,7 @@ extern const char *kernel_get_module_path(const char *module); extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs, int max_probe_points, bool force_add); -extern int del_perf_probe_events(struct strlist *dellist); +extern int del_perf_probe_events(struct strfilter *filter); extern int show_perf_probe_events(struct strfilter *filter); extern int show_line_range(struct line_range *lr, const char *module, bool user); |