Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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.localdomain


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 2dd6d8a1
Loading
Loading
Loading
Loading
+6 −10
Original line number Diff line number Diff line
@@ -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(&params.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;
+32 −70
Original line number Diff line number Diff line
@@ -2734,40 +2734,39 @@ static int __del_trace_probe_event(int fd, struct str_node *ent)
	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 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)) {
	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)
				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;
}

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;
		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);
	ret = del_trace_probe_events(kfd, filter, namelist);
	if (ret < 0 && ret != -ENOENT)
		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)
	ret2 = del_trace_probe_events(ufd, filter, unamelist);
	if (ret2 < 0 && ret2 != -ENOENT)
		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:
@@ -2845,6 +2806,7 @@ int del_perf_probe_events(struct strlist *dellist)
		strlist__delete(unamelist);
		close(ufd);
	}
	free(str);

	return ret;
}
+1 −1
Original line number Diff line number Diff line
@@ -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);