Commit 307a464b authored by Masami Hiramatsu's avatar Masami Hiramatsu Committed by Arnaldo Carvalho de Melo

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: default avatarMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Tested-by: default avatarArnaldo 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.localdomainSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 2dd6d8a1
...@@ -55,12 +55,12 @@ static struct { ...@@ -55,12 +55,12 @@ static struct {
bool show_ext_vars; bool show_ext_vars;
bool show_funcs; bool show_funcs;
bool mod_events; bool mod_events;
bool del_events;
bool uprobes; bool uprobes;
bool quiet; bool quiet;
bool target_used; bool target_used;
int nevents; int nevents;
struct perf_probe_event events[MAX_PROBES]; struct perf_probe_event events[MAX_PROBES];
struct strlist *dellist;
struct line_range line_range; struct line_range line_range;
char *target; char *target;
int max_probe_points; int max_probe_points;
...@@ -195,10 +195,8 @@ static int opt_del_probe_event(const struct option *opt __maybe_unused, ...@@ -195,10 +195,8 @@ static int opt_del_probe_event(const struct option *opt __maybe_unused,
const char *str, int unset __maybe_unused) const char *str, int unset __maybe_unused)
{ {
if (str) { if (str) {
params.mod_events = true; params.del_events = true;
if (!params.dellist) return params_add_filter(str);
params.dellist = strlist__new(true, NULL);
strlist__add(params.dellist, str);
} }
return 0; return 0;
} }
...@@ -313,8 +311,6 @@ static void cleanup_params(void) ...@@ -313,8 +311,6 @@ static void cleanup_params(void)
for (i = 0; i < params.nevents; i++) for (i = 0; i < params.nevents; i++)
clear_perf_probe_event(params.events + i); clear_perf_probe_event(params.events + i);
if (params.dellist)
strlist__delete(params.dellist);
line_range__clear(&params.line_range); line_range__clear(&params.line_range);
free(params.target); free(params.target);
if (params.filter) if (params.filter)
...@@ -454,7 +450,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) ...@@ -454,7 +450,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
if (params.max_probe_points == 0) if (params.max_probe_points == 0)
params.max_probe_points = MAX_PROBES; 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)) !params.show_lines && !params.show_funcs))
usage_with_options(probe_usage, options); usage_with_options(probe_usage, options);
...@@ -514,8 +510,8 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) ...@@ -514,8 +510,8 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
} }
#endif #endif
if (params.dellist) { if (params.del_events) {
ret = del_perf_probe_events(params.dellist); ret = del_perf_probe_events(params.filter);
if (ret < 0) { if (ret < 0) {
pr_err_with_code(" Error: Failed to delete events.", ret); pr_err_with_code(" Error: Failed to delete events.", ret);
return ret; return ret;
......
...@@ -2734,40 +2734,39 @@ static int __del_trace_probe_event(int fd, struct str_node *ent) ...@@ -2734,40 +2734,39 @@ static int __del_trace_probe_event(int fd, struct str_node *ent)
return ret; return ret;
} }
static int del_trace_probe_event(int fd, const char *buf, static int del_trace_probe_events(int fd, struct strfilter *filter,
struct strlist *namelist) struct strlist *namelist)
{ {
struct str_node *ent, *n; struct str_node *ent;
const char *p;
int ret = -ENOENT; int ret = -ENOENT;
if (strpbrk(buf, "*?")) { /* Glob-exp */ if (!namelist)
strlist__for_each_safe(ent, n, namelist) return -ENOENT;
if (strglobmatch(ent->s, buf)) {
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); ret = __del_trace_probe_event(fd, ent);
if (ret < 0) if (ret < 0)
break; break;
strlist__remove(namelist, ent);
}
} else {
ent = strlist__find(namelist, buf);
if (ent) {
ret = __del_trace_probe_event(fd, ent);
if (ret >= 0)
strlist__remove(namelist, ent);
} }
} }
return ret; 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; int ret, ret2, ufd = -1, kfd = -1;
char buf[128];
const char *group, *event;
char *p, *str;
struct str_node *ent;
struct strlist *namelist = NULL, *unamelist = NULL; 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 */ /* Get current event names */
kfd = open_kprobe_events(true); kfd = open_kprobe_events(true);
...@@ -2780,59 +2779,21 @@ int del_perf_probe_events(struct strlist *dellist) ...@@ -2780,59 +2779,21 @@ int del_perf_probe_events(struct strlist *dellist)
if (kfd < 0 && ufd < 0) { if (kfd < 0 && ufd < 0) {
print_both_open_warning(kfd, ufd); print_both_open_warning(kfd, ufd);
ret = kfd;
goto error; goto error;
} }
if (namelist == NULL && unamelist == NULL) { ret = del_trace_probe_events(kfd, filter, namelist);
ret = -ENOENT; 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; goto error;
}
pr_debug("Group: %s, Event: %s\n", group, event); ret2 = del_trace_probe_events(ufd, filter, unamelist);
free(str); if (ret2 < 0 && ret2 != -ENOENT)
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; ret = ret2;
break; 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: error:
...@@ -2845,6 +2806,7 @@ int del_perf_probe_events(struct strlist *dellist) ...@@ -2845,6 +2806,7 @@ int del_perf_probe_events(struct strlist *dellist)
strlist__delete(unamelist); strlist__delete(unamelist);
close(ufd); close(ufd);
} }
free(str);
return ret; return ret;
} }
......
...@@ -126,7 +126,7 @@ extern const char *kernel_get_module_path(const char *module); ...@@ -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, extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
int max_probe_points, bool force_add); 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_perf_probe_events(struct strfilter *filter);
extern int show_line_range(struct line_range *lr, const char *module, extern int show_line_range(struct line_range *lr, const char *module,
bool user); bool user);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment