Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1387248 > unrolled thread

[PATCH perf/core v4 00/19] perf-probe --cache and SDT support

Started byMasami Hiramatsu <mhiramat@kernel.org>
First post2016-04-26 11:10 +0200
Last post2016-04-27 17:40 +0200
Articles 20 on this page of 40 — 4 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH perf/core v4 00/19] perf-probe --cache and SDT support Masami Hiramatsu <mhiramat@kernel.org> - 2016-04-26 11:10 +0200
    [PATCH perf/core v4 11/19] perf/sdt: ELF support for SDT Masami Hiramatsu <mhiramat@kernel.org> - 2016-04-26 11:10 +0200
    [PATCH perf/core v4 03/19] perf buildid-cache: Fall back to the old style build-id cache Masami Hiramatsu <mhiramat@kernel.org> - 2016-04-26 11:10 +0200
      Re: [PATCH perf/core v4 03/19] perf buildid-cache: Fall back to the  old style build-id cache Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-04-26 15:50 +0200
        Re: [PATCH perf/core v4 03/19] perf buildid-cache: Fall back to the  old style build-id cache Masami Hiramatsu <mhiramat@kernel.org> - 2016-04-26 16:50 +0200
    [PATCH perf/core v4 16/19] perf-list: Show SDT and pre-cached events Masami Hiramatsu <mhiramat@kernel.org> - 2016-04-26 11:10 +0200
    [PATCH perf/core v4 01/19] perf probe: Use strbuf for making strings Masami Hiramatsu <mhiramat@kernel.org> - 2016-04-26 11:10 +0200
      Re: [PATCH perf/core v4 01/19] perf probe: Use strbuf for making  strings Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-04-26 15:40 +0200
        Re: [PATCH perf/core v4 01/19] perf probe: Use strbuf for making  strings Masami Hiramatsu <mhiramat@kernel.org> - 2016-04-26 16:50 +0200
          Re: [PATCH perf/core v4 01/19] perf probe: Use strbuf for making  strings Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-04-26 17:10 +0200
            Re: [PATCH perf/core v4 01/19] perf probe: Use strbuf for making  strings Masami Hiramatsu <mhiramat@kernel.org> - 2016-04-27 20:50 +0200
    [PATCH perf/core v4 04/19] perf: Add lsdir to read a directory Masami Hiramatsu <mhiramat@kernel.org> - 2016-04-26 11:10 +0200
      Re: [PATCH perf/core v4 04/19] perf: Add lsdir to read a directory Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-04-26 15:50 +0200
        Re: [PATCH perf/core v4 04/19] perf: Add lsdir to read a directory Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-04-26 16:10 +0200
          Re: [PATCH perf/core v4 04/19] perf: Add lsdir to read a directory Masami Hiramatsu <mhiramat@kernel.org> - 2016-04-26 17:00 +0200
            Re: [PATCH perf/core v4 04/19] perf: Add lsdir to read a directory Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-04-26 17:10 +0200
      [tip:perf/core] perf tools: Add lsdir() helper to read a directory tip-bot for Masami Hiramatsu <tipbot@zytor.com> - 2016-04-27 17:40 +0200
    [PATCH perf/core v4 15/19] perf probe: Accept %sdt and %cached event name Masami Hiramatsu <mhiramat@kernel.org> - 2016-04-26 11:10 +0200
    [PATCH perf/core v4 19/19] perf probe: Support @BUILDID or @FILE suffix for SDT events Masami Hiramatsu <mhiramat@kernel.org> - 2016-04-26 11:10 +0200
    [PATCH perf/core v4 18/19] perf probe: Allow wildcard for cached events Masami Hiramatsu <mhiramat@kernel.org> - 2016-04-26 11:10 +0200
      Re: [PATCH perf/core v4 18/19] perf probe: Allow wildcard for cached  events Hemant Kumar <hemant@linux.vnet.ibm.com> - 2016-04-27 17:40 +0200
        Re: [PATCH perf/core v4 18/19] perf probe: Allow wildcard for  cached events Masami Hiramatsu <mhiramat@kernel.org> - 2016-04-27 21:00 +0200
    [PATCH perf/core v4 05/19] perf-buildid-cache: Use lsdir for looking up buildid caches Masami Hiramatsu <mhiramat@kernel.org> - 2016-04-26 11:10 +0200
    [PATCH perf/core v4 07/19] perf probe: Add --cache option to cache the probe definitions Masami Hiramatsu <mhiramat@kernel.org> - 2016-04-26 11:10 +0200
    [PATCH perf/core v4 10/19] perf probe: Remove caches when --cache is given Masami Hiramatsu <mhiramat@kernel.org> - 2016-04-26 11:10 +0200
    [PATCH perf/core v4 14/19] perf buildid-cache: Scan and import user SDT events to probe cache Masami Hiramatsu <mhiramat@kernel.org> - 2016-04-26 11:10 +0200
      Re: [PATCH perf/core v4 14/19] perf buildid-cache: Scan and import  user SDT events to probe cache Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-04-27 17:30 +0200
        Re: [PATCH perf/core v4 14/19] perf buildid-cache: Scan and import  user SDT events to probe cache Masami Hiramatsu <mhiramat@kernel.org> - 2016-04-27 21:40 +0200
          Re: [PATCH perf/core v4 14/19] perf buildid-cache: Scan and import  user SDT events to probe cache Hemant Kumar <hemant@linux.vnet.ibm.com> - 2016-04-27 22:30 +0200
        Re: [PATCH perf/core v4 14/19] perf buildid-cache: Scan and import  user SDT events to probe cache Hemant Kumar <hemant@linux.vnet.ibm.com> - 2016-04-27 22:20 +0200
      Re: [PATCH perf/core v4 14/19] perf buildid-cache: Scan and import  user SDT events to probe cache Hemant Kumar <hemant@linux.vnet.ibm.com> - 2016-04-27 17:30 +0200
    [PATCH perf/core v4 02/19] perf-buildid-cache: Use path/to/bin/buildid/elf instead of path/to/bin/buildid Masami Hiramatsu <mhiramat@kernel.org> - 2016-04-26 11:10 +0200
      Re: [PATCH perf/core v4 02/19] perf-buildid-cache: Use  path/to/bin/buildid/elf instead of path/to/bin/buildid Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-04-26 15:50 +0200
        Re: [PATCH perf/core v4 02/19] perf-buildid-cache: Use  path/to/bin/buildid/elf instead of path/to/bin/buildid Masami Hiramatsu <mhiramat@kernel.org> - 2016-04-26 16:50 +0200
    [PATCH perf/core v4 06/19] perf-probe: Let probe_file__add_event return 0 if succeeded Masami Hiramatsu <mhiramat@kernel.org> - 2016-04-26 11:10 +0200
      Re: [PATCH perf/core v4 06/19] perf-probe: Let probe_file__add_event  return 0 if succeeded Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-04-26 15:50 +0200
      [tip:perf/core] perf probe: Let probe_file__add_event return 0 if  succeeded tip-bot for Masami Hiramatsu <tipbot@zytor.com> - 2016-04-27 17:40 +0200
    [PATCH perf/core v4 09/19] perf probe: Show all cached probes Masami Hiramatsu <mhiramat@kernel.org> - 2016-04-26 11:20 +0200
    [PATCH perf/core v4 08/19] perf probe: Use cache entry if possible Masami Hiramatsu <mhiramat@kernel.org> - 2016-04-26 11:30 +0200
    Re: [PATCH perf/core v4 00/19] perf-probe --cache and SDT support Hemant Kumar <hemant@linux.vnet.ibm.com> - 2016-04-27 17:40 +0200

Page 2 of 2 — ← Prev page 1 [2]


#1389243 — Re: [PATCH perf/core v4 18/19] perf probe: Allow wildcard for cached events

FromHemant Kumar <hemant@linux.vnet.ibm.com>
Date2016-04-27 17:40 +0200
SubjectRe: [PATCH perf/core v4 18/19] perf probe: Allow wildcard for cached events
Message-ID<rszJg-3tA-33@gated-at.bofh.it>
In reply to#1387259

On 04/26/2016 02:34 PM, Masami Hiramatsu wrote:
> Allo glob wildcard for reusing cached/SDT events. This also
> automatically find the target binaries, e.g.
>
>    # perf probe -a %sdt_libc:\*
>
> This example adds probes for all SDT in libc.
> Note that the SDTs must have been scanned by perf buildid-cache.

There is a segfault after applying this patch :

# perf probe -x /home/hemant/test %marker1
Segmentation fault (core dumped)

The problem is there is no group name with this marker and
strglobmatch tries to match entry->pev.group with pev->group (which is 
NULL).

> Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
> ---
>   tools/perf/util/probe-event.c |  153 ++++++++++++++++++++++++++++++++++++++++-
>   tools/perf/util/probe-event.h |    1
>   tools/perf/util/probe-file.c  |   33 ++++++++-
>   tools/perf/util/probe-file.h  |    5 +
>   4 files changed, 183 insertions(+), 9 deletions(-)
>
> diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
> index 1128631..3bd81f0 100644
> --- a/tools/perf/util/probe-event.c
> +++ b/tools/perf/util/probe-event.c
> @@ -236,7 +236,7 @@ static void clear_perf_probe_point(struct perf_probe_point *pp)
>   	free(pp->lazy_line);
>   }
>
> -static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
> +void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
>   {
>   	int i;
>
> @@ -1151,7 +1151,7 @@ static int parse_perf_probe_event_name(char **arg, struct perf_probe_event *pev)
>   	ptr = strchr(*arg, ':');
>   	if (ptr) {
>   		*ptr = '\0';
> -		if (!is_c_func_name(*arg))
> +		if (!pev->sdt && !is_c_func_name(*arg))
>   			goto ng_name;
>   		pev->group = strdup(*arg);
>   		if (!pev->group)
> @@ -1159,7 +1159,7 @@ static int parse_perf_probe_event_name(char **arg, struct perf_probe_event *pev)
>   		*arg = ptr + 1;
>   	} else
>   		pev->group = NULL;
> -	if (!is_c_func_name(*arg)) {
> +	if (!pev->sdt && !is_c_func_name(*arg)) {
>   ng_name:
>   		semantic_error("%s is bad for event name -it must "
>   			       "follow C symbol-naming rule.\n", *arg);
> @@ -1585,6 +1585,11 @@ int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev)
>   	p = strchr(argv[1], ':');
>   	if (p) {
>   		tp->module = strndup(argv[1], p - argv[1]);
> +		if (!tp->module) {
> +			ret = -ENOMEM;
> +			goto out;
> +		}
> +		tev->uprobes = (tp->module[0] == '/');
>   		p++;
>   	} else
>   		p = argv[1];
> @@ -2430,7 +2435,7 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev,
>   	int ret;
>
>   	/* If probe_event or trace_event already have the name, reuse it */
> -	if (pev->event)
> +	if (pev->event && !pev->sdt)
>   		event = pev->event;
>   	else if (tev->event)
>   		event = tev->event;
> @@ -2443,7 +2448,7 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev,
>   		else
>   			event = tev->point.realname;
>   	}
> -	if (pev->group)
> +	if (pev->group && !pev->sdt)
>   		group = pev->group;
>   	else if (tev->group)
>   		group = tev->group;
> @@ -2794,6 +2799,137 @@ errout:
>
>   bool __weak arch__prefers_symtab(void) { return false; }
>
> +/* Concatinate two arrays */
> +static void *memcat(void *a, size_t sz_a, void *b, size_t sz_b)
> +{
> +	void *ret;
> +
> +	ret = malloc(sz_a + sz_b);
> +	if (ret) {
> +		memcpy(ret, a, sz_a);
> +		memcpy(ret + sz_a, b, sz_b);
> +	}
> +	return ret;
> +}
> +
> +static int
> +concat_probe_trace_events(struct probe_trace_event **tevs, int *ntevs,
> +			  struct probe_trace_event **tevs2, int ntevs2)
> +{
> +	struct probe_trace_event *new_tevs;
> +	int ret = 0;
> +
> +	if (ntevs == 0) {
> +		*tevs = *tevs2;
> +		*ntevs = ntevs2;
> +		*tevs2 = NULL;
> +		return 0;
> +	}
> +
> +	if (*ntevs + ntevs2 > probe_conf.max_probes)
> +		ret = -E2BIG;
> +	else {
> +		/* Concatinate the array of probe_trace_event */
> +		new_tevs = memcat(*tevs, (*ntevs) * sizeof(**tevs),
> +				  *tevs2, ntevs2 * sizeof(**tevs2));
> +		if (!new_tevs)
> +			ret = -ENOMEM;
> +		else {
> +			free(*tevs);
> +			*tevs = new_tevs;
> +			*ntevs += ntevs2;
> +		}
> +	}
> +	if (ret < 0)
> +		clear_probe_trace_events(*tevs2, ntevs2);
> +	zfree(tevs2);
> +
> +	return ret;
> +}
> +
> +/* Try to find probe_trace_event from given probe caches */
> +static int find_cached_events(struct perf_probe_event *pev,
> +			      struct probe_trace_event **tevs,
> +			      const char *target)
> +{
> +	struct probe_cache *cache;
> +	struct probe_cache_entry *entry;
> +	struct probe_trace_event *tmp_tevs = NULL;
> +	int ntevs = 0;
> +	int ret = 0;
> +
> +	cache = probe_cache__new(target);
> +	if (!cache)
> +		return -ENOENT;
> +
> +	for_each_probe_cache_entry(entry, cache) {
> +		/* Skip the cache entry which has no name */
> +		if (!entry->pev.event || !entry->pev.group)
> +			continue;
> +		if (strglobmatch(entry->pev.group, pev->group) &&
> +		    strglobmatch(entry->pev.event, pev->event)) {

Due to the above issue, we can change the above condition to :
if (strglobmatch(entry->pev.event, pev->event) {
     if (!pev->group || (pev->group && strglobmatch(entry->pev.group, 
pev->group)))
         // Do stuff
}

> +			ret = probe_cache_entry__get_event(entry, &tmp_tevs);
> +			if (ret > 0)
> +				ret = concat_probe_trace_events(tevs, &ntevs,
> +								&tmp_tevs, ret);
> +			if (ret < 0)
> +				break;
> +		}
> +	}
> +	probe_cache__delete(cache);
> +	if (ret < 0) {
> +		clear_probe_trace_events(*tevs, ntevs);
> +		zfree(tevs);
> +	} else {
> +		ret = ntevs;
> +		if (target[0] == '/')
> +			pev->uprobes = true;
> +	}
> +
> +	return ret;
> +}
> +
> +/* Try to find probe_trace_event from all probe caches */
> +static int find_cached_events_all(struct perf_probe_event *pev,
> +				   struct probe_trace_event **tevs)
> +{
> +	struct probe_trace_event *tmp_tevs = NULL;
> +	struct strlist *bidlist;
> +	struct str_node *nd;
> +	char *pathname;
> +	int ntevs = 0;
> +	int ret;
> +
> +	/* Get the buildid list of all valid caches */
> +	ret = build_id_cache__list_all(&bidlist, true);
> +	if (ret < 0) {
> +		pr_debug("Failed to get buildids: %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = 0;
> +	strlist__for_each(nd, bidlist) {
> +		pathname = build_id_cache__origname(nd->s);
> +		ret = find_cached_events(pev, &tmp_tevs, pathname);
> +		if (ret > 0)
> +			ret = concat_probe_trace_events(tevs, &ntevs,
> +							&tmp_tevs, ret);
> +		/* In the case of cnt == 0, we just skip it */
> +		free(pathname);
> +		if (ret < 0)
> +			break;
> +	}
> +	strlist__delete(bidlist);
> +
> +	if (ret < 0) {
> +		clear_probe_trace_events(*tevs, ntevs);
> +		zfree(tevs);
> +	} else
> +		ret = ntevs;
> +
> +	return ret;
> +}
> +
>   static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,
>   					      struct probe_trace_event **tevs)
>   {
> @@ -2803,6 +2939,13 @@ static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,
>   	struct str_node *node;
>   	int ret, i;
>
> +	if (pev->sdt) {
> +		/* For SDT/cached events, we use special search functions */
> +		if (!pev->target)
> +			return find_cached_events_all(pev, tevs);
> +		else
> +			return find_cached_events(pev, tevs, pev->target);
> +	}
>   	cache = probe_cache__new(pev->target);
>   	if (!cache)
>   		return 0;
> diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
> index 2a23efe..39b5a35 100644
> --- a/tools/perf/util/probe-event.h
> +++ b/tools/perf/util/probe-event.h
> @@ -134,6 +134,7 @@ bool perf_probe_event_need_dwarf(struct perf_probe_event *pev);
>   /* Release event contents */
>   void clear_perf_probe_event(struct perf_probe_event *pev);
>   void clear_probe_trace_event(struct probe_trace_event *tev);
> +void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs);
>
>   /* Command string to line-range */
>   int parse_line_range_desc(const char *cmd, struct line_range *lr);
> diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
> index 2437b48..896d645 100644
> --- a/tools/perf/util/probe-file.c
> +++ b/tools/perf/util/probe-file.c
> @@ -360,6 +360,31 @@ probe_cache_entry__new(struct perf_probe_event *pev)
>   	return ret;
>   }
>
> +int probe_cache_entry__get_event(struct probe_cache_entry *entry,
> +				 struct probe_trace_event **tevs)
> +{
> +	struct probe_trace_event *tev;
> +	struct str_node *node;
> +	int ret, i;
> +
> +	ret = strlist__nr_entries(entry->tevlist);
> +	if (ret > probe_conf.max_probes)
> +		return -E2BIG;
> +
> +	*tevs = zalloc(ret * sizeof(*tev));
> +	if (!*tevs)
> +		return -ENOMEM;
> +
> +	i = 0;
> +	strlist__for_each(node, entry->tevlist) {
> +		tev = &(*tevs)[i++];
> +		ret = parse_probe_trace_command(node->s, tev);
> +		if (ret < 0)
> +			break;
> +	}
> +	return i;
> +}
> +
>   /* For the kernel probe caches, pass target = NULL */
>   static int probe_cache__open(struct probe_cache *pcache, const char *target)
>   {
> @@ -528,7 +553,7 @@ probe_cache__find(struct probe_cache *pcache, struct perf_probe_event *pev)
>   	if (!cmd)
>   		return NULL;
>
> -	list_for_each_entry(entry, &pcache->list, list) {
> +	for_each_probe_cache_entry(entry, pcache) {
>   		if (pev->sdt) {
>   			if (entry->pev.event &&
>   			    streql(entry->pev.event, pev->event) &&
> @@ -558,7 +583,7 @@ probe_cache__find_by_name(struct probe_cache *pcache,
>   {
>   	struct probe_cache_entry *entry = NULL;
>
> -	list_for_each_entry(entry, &pcache->list, list) {
> +	for_each_probe_cache_entry(entry, pcache) {
>   		/* Hit if same event name or same command-string */
>   		if (streql(entry->pev.group, group) &&
>   		    streql(entry->pev.event, event))
> @@ -711,7 +736,7 @@ int probe_cache__commit(struct probe_cache *pcache)
>   	if (ret < 0)
>   		goto out;
>
> -	list_for_each_entry(entry, &pcache->list, list) {
> +	for_each_probe_cache_entry(entry, pcache) {
>   		ret = probe_cache_entry__write(entry, pcache->fd);
>   		pr_debug("Cache committed: %d\n", ret);
>   		if (ret < 0)
> @@ -750,7 +775,7 @@ static int probe_cache__show_entries(struct probe_cache *pcache,
>   {
>   	struct probe_cache_entry *entry;
>
> -	list_for_each_entry(entry, &pcache->list, list) {
> +	for_each_probe_cache_entry(entry, pcache) {
>   		if (probe_cache_entry__compare(entry, filter))
>   			printf("%s\n", entry->spev);
>   	}
> diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
> index 55322f1..a02bbbd 100644
> --- a/tools/perf/util/probe-file.h
> +++ b/tools/perf/util/probe-file.h
> @@ -32,6 +32,11 @@ struct probe_cache {
>   	struct list_head list;
>   };
>
> +int probe_cache_entry__get_event(struct probe_cache_entry *entry,
> +				 struct probe_trace_event **tevs);
> +#define for_each_probe_cache_entry(entry, pcache) \
> +	list_for_each_entry(entry, &pcache->list, list)
> +
>   struct probe_cache *probe_cache__new(const char *target);
>   int probe_cache__add_entry(struct probe_cache *pcache,
>   			   struct perf_probe_event *pev,
>

-- 
Thanks,
Hemant Kumar

[toc] | [prev] | [next] | [standalone]


#1389496 — Re: [PATCH perf/core v4 18/19] perf probe: Allow wildcard for cached events

FromMasami Hiramatsu <mhiramat@kernel.org>
Date2016-04-27 21:00 +0200
SubjectRe: [PATCH perf/core v4 18/19] perf probe: Allow wildcard for cached events
Message-ID<rsCQP-66m-41@gated-at.bofh.it>
In reply to#1389243
On Wed, 27 Apr 2016 21:04:53 +0530
Hemant Kumar <hemant@linux.vnet.ibm.com> wrote:

> 
> 
> On 04/26/2016 02:34 PM, Masami Hiramatsu wrote:
> > Allo glob wildcard for reusing cached/SDT events. This also
> > automatically find the target binaries, e.g.
> >
> >    # perf probe -a %sdt_libc:\*
> >
> > This example adds probes for all SDT in libc.
> > Note that the SDTs must have been scanned by perf buildid-cache.
> 
> There is a segfault after applying this patch :
> 
> # perf probe -x /home/hemant/test %marker1
> Segmentation fault (core dumped)
> 
> The problem is there is no group name with this marker and
> strglobmatch tries to match entry->pev.group with pev->group (which is 
> NULL).

Thank you for testing!

[...]
> > +/* Try to find probe_trace_event from given probe caches */
> > +static int find_cached_events(struct perf_probe_event *pev,
> > +			      struct probe_trace_event **tevs,
> > +			      const char *target)
> > +{
> > +	struct probe_cache *cache;
> > +	struct probe_cache_entry *entry;
> > +	struct probe_trace_event *tmp_tevs = NULL;
> > +	int ntevs = 0;
> > +	int ret = 0;
> > +
> > +	cache = probe_cache__new(target);
> > +	if (!cache)
> > +		return -ENOENT;
> > +
> > +	for_each_probe_cache_entry(entry, cache) {
> > +		/* Skip the cache entry which has no name */
> > +		if (!entry->pev.event || !entry->pev.group)
> > +			continue;
> > +		if (strglobmatch(entry->pev.group, pev->group) &&
> > +		    strglobmatch(entry->pev.event, pev->event)) {
> 
> Due to the above issue, we can change the above condition to :
> if (strglobmatch(entry->pev.event, pev->event) {
>      if (!pev->group || (pev->group && strglobmatch(entry->pev.group, 
> pev->group)))
>          // Do stuff
> }

OK, I'll fix that.

thanks!!

-- 
Masami Hiramatsu <mhiramat@kernel.org>

[toc] | [prev] | [next] | [standalone]


#1387261 — [PATCH perf/core v4 05/19] perf-buildid-cache: Use lsdir for looking up buildid caches

FromMasami Hiramatsu <mhiramat@kernel.org>
Date2016-04-26 11:10 +0200
Subject[PATCH perf/core v4 05/19] perf-buildid-cache: Use lsdir for looking up buildid caches
Message-ID<rs7ak-4SP-47@gated-at.bofh.it>
In reply to#1387248
From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>

Use new lsdir() for looking up buildid caches. This changes
logic a bit to ignore all dot files, since the build-id
cache must not start with dot.

Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 tools/perf/util/build-id.c |   30 +++++-------------------------
 1 file changed, 5 insertions(+), 25 deletions(-)

diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index b035483..848e05f 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -400,38 +400,18 @@ int build_id_cache__list_build_ids(const char *pathname,
 {
 	struct strlist *list;
 	char *dir_name;
-	DIR *dir;
-	struct dirent *d;
 	int ret = 0;
 
-	list = strlist__new(NULL, NULL);
 	dir_name = build_id_cache__dirname_from_path(pathname, false, false,
 						     NULL);
-	if (!list || !dir_name) {
-		ret = -ENOMEM;
-		goto out;
-	}
+	if (!dir_name)
+		return -ENOMEM;
 
-	/* List up all dirents */
-	dir = opendir(dir_name);
-	if (!dir) {
+	list = lsdir(dir_name, lsdir_no_dot_filter);
+	if (!list)
 		ret = -errno;
-		goto out;
-	}
-
-	while ((d = readdir(dir)) != NULL) {
-		if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
-			continue;
-		strlist__add(list, d->d_name);
-	}
-	closedir(dir);
-
-out:
+	*result = list;
 	free(dir_name);
-	if (ret)
-		strlist__delete(list);
-	else
-		*result = list;
 
 	return ret;
 }

[toc] | [prev] | [next] | [standalone]


#1387262 — [PATCH perf/core v4 07/19] perf probe: Add --cache option to cache the probe definitions

FromMasami Hiramatsu <mhiramat@kernel.org>
Date2016-04-26 11:10 +0200
Subject[PATCH perf/core v4 07/19] perf probe: Add --cache option to cache the probe definitions
Message-ID<rs7ak-4SP-51@gated-at.bofh.it>
In reply to#1387248
From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>

Add --cache option to cache the probe definitions. This
just saves the result of the dwarf analysis to probe cache.

Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 Changes in v4:
  - Remove cache saving failure message.
---
 tools/perf/Documentation/perf-probe.txt |    4 
 tools/perf/builtin-probe.c              |    1 
 tools/perf/util/build-id.c              |   13 +
 tools/perf/util/build-id.h              |    2 
 tools/perf/util/probe-event.c           |  126 +++++++++++--
 tools/perf/util/probe-event.h           |    5 +
 tools/perf/util/probe-file.c            |  299 +++++++++++++++++++++++++++++++
 tools/perf/util/probe-file.h            |   19 ++
 8 files changed, 441 insertions(+), 28 deletions(-)

diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 3a8a9ba..947db6f 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -109,6 +109,10 @@ OPTIONS
 	Dry run. With this option, --add and --del doesn't execute actual
 	adding and removal operations.
 
+--cache::
+	Cache the probes (with --add option). Any events which successfully added
+	are also stored in the cache file.
+
 --max-probes=NUM::
 	Set the maximum number of probe points for an event. Default is 128.
 
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 9af859b..6d7ab431 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -512,6 +512,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
 		    "Enable symbol demangling"),
 	OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
 		    "Enable kernel symbol demangling"),
+	OPT_BOOLEAN(0, "cache", &probe_conf.cache, "Manipulate probe cache"),
 	OPT_END()
 	};
 	int ret;
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 848e05f..588ff01 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -371,9 +371,8 @@ void disable_buildid_cache(void)
 	no_buildid_cache = true;
 }
 
-static char *build_id_cache__dirname_from_path(const char *name,
-					       bool is_kallsyms, bool is_vdso,
-					       const char *sbuild_id)
+char *build_id_cache__dirname_from_path(const char *sbuild_id, const char *name,
+					bool is_kallsyms, bool is_vdso)
 {
 	char *realname = (char *)name, *filename;
 	bool slash = is_kallsyms || is_vdso;
@@ -402,8 +401,8 @@ int build_id_cache__list_build_ids(const char *pathname,
 	char *dir_name;
 	int ret = 0;
 
-	dir_name = build_id_cache__dirname_from_path(pathname, false, false,
-						     NULL);
+	dir_name = build_id_cache__dirname_from_path(NULL, pathname,
+						     false, false);
 	if (!dir_name)
 		return -ENOMEM;
 
@@ -430,8 +429,8 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
 			goto out_free;
 	}
 
-	dir_name = build_id_cache__dirname_from_path(name, is_kallsyms,
-						     is_vdso, sbuild_id);
+	dir_name = build_id_cache__dirname_from_path(sbuild_id, name,
+						     is_kallsyms, is_vdso);
 	if (!dir_name)
 		goto out_free;
 
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index 64af3e2..1841524 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -28,6 +28,8 @@ bool perf_session__read_build_ids(struct perf_session *session, bool with_hits);
 int perf_session__write_buildid_table(struct perf_session *session, int fd);
 int perf_session__cache_build_ids(struct perf_session *session);
 
+char *build_id_cache__dirname_from_path(const char *sbuild_id, const char *name,
+					bool is_kallsyms, bool is_vdso);
 int build_id_cache__list_build_ids(const char *pathname,
 				   struct strlist **result);
 bool build_id_cache__cached(const char *sbuild_id);
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 148af81..f6d194c 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -67,7 +67,6 @@ int e_snprintf(char *str, size_t size, const char *format, ...)
 	return ret;
 }
 
-static char *synthesize_perf_probe_point(struct perf_probe_point *pp);
 static struct machine *host_machine;
 
 /* Initialize symbol maps and path of vmlinux/modules */
@@ -1648,7 +1647,7 @@ char *synthesize_perf_probe_arg(struct perf_probe_arg *pa)
 }
 
 /* Compose only probe point (not argument) */
-static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
+char *synthesize_perf_probe_point(struct perf_probe_point *pp)
 {
 	struct strbuf buf;
 	char *tmp;
@@ -1679,30 +1678,36 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
 	return strbuf_detach(&buf, NULL);
 }
 
-#if 0
 char *synthesize_perf_probe_command(struct perf_probe_event *pev)
 {
-	char *buf;
-	int i, len, ret;
+	struct strbuf buf;
+	char *tmp;
+	int i;
 
-	buf = synthesize_perf_probe_point(&pev->point);
-	if (!buf)
-		return NULL;
+	strbuf_init(&buf, 64);
+	if (pev->event)
+		strbuf_addf(&buf, "%s:%s=", pev->group ?: PERFPROBE_GROUP,
+			    pev->event);
+
+	tmp = synthesize_perf_probe_point(&pev->point);
+	if (!tmp)
+		goto out;
+	strbuf_addstr(&buf, tmp);
+	free(tmp);
 
-	len = strlen(buf);
 	for (i = 0; i < pev->nargs; i++) {
-		ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s",
-				 pev->args[i].name);
-		if (ret <= 0) {
-			free(buf);
-			return NULL;
-		}
-		len += ret;
+		tmp = synthesize_perf_probe_arg(pev->args + i);
+		if (!tmp)
+			goto out;
+		strbuf_addf(&buf, " %s", tmp);
+		free(tmp);
 	}
 
-	return buf;
+	tmp = strbuf_detach(&buf, NULL);
+out:
+	strbuf_release(&buf);
+	return tmp;
 }
-#endif
 
 static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref,
 					    struct strbuf *buf, int depth)
@@ -1945,6 +1950,79 @@ void clear_perf_probe_event(struct perf_probe_event *pev)
 	memset(pev, 0, sizeof(*pev));
 }
 
+#define strdup_or_goto(str, label)	\
+({ char *__p = NULL; if (str && !(__p = strdup(str))) goto label; __p; })
+
+static int perf_probe_point__copy(struct perf_probe_point *dst,
+				  struct perf_probe_point *src)
+{
+	dst->file = strdup_or_goto(src->file, out_err);
+	dst->function = strdup_or_goto(src->function, out_err);
+	dst->lazy_line = strdup_or_goto(src->lazy_line, out_err);
+	dst->line = src->line;
+	dst->retprobe = src->retprobe;
+	dst->offset = src->offset;
+	return 0;
+
+out_err:
+	clear_perf_probe_point(dst);
+	return -ENOMEM;
+}
+
+static int perf_probe_arg__copy(struct perf_probe_arg *dst,
+				struct perf_probe_arg *src)
+{
+	struct perf_probe_arg_field *field, **ppfield;
+
+	dst->name = strdup_or_goto(src->name, out_err);
+	dst->var = strdup_or_goto(src->var, out_err);
+	dst->type = strdup_or_goto(src->type, out_err);
+
+	field = src->field;
+	ppfield = &(dst->field);
+	while (field) {
+		*ppfield = zalloc(sizeof(*field));
+		if (!*ppfield)
+			goto out_err;
+		(*ppfield)->name = strdup_or_goto(field->name, out_err);
+		(*ppfield)->index = field->index;
+		(*ppfield)->ref = field->ref;
+		field = field->next;
+		ppfield = &((*ppfield)->next);
+	}
+	return 0;
+out_err:
+	return -ENOMEM;
+}
+
+int perf_probe_event__copy(struct perf_probe_event *dst,
+			   struct perf_probe_event *src)
+{
+	int i;
+
+	dst->event = strdup_or_goto(src->event, out_err);
+	dst->group = strdup_or_goto(src->group, out_err);
+	dst->target = strdup_or_goto(src->target, out_err);
+	dst->uprobes = src->uprobes;
+
+	if (perf_probe_point__copy(&dst->point, &src->point) < 0)
+		goto out_err;
+
+	dst->args = zalloc(sizeof(struct perf_probe_arg) * src->nargs);
+	if (!dst->args)
+		goto out_err;
+	dst->nargs = src->nargs;
+
+	for (i = 0; i < src->nargs; i++)
+		if (perf_probe_arg__copy(&dst->args[i], &src->args[i]) < 0)
+			goto out_err;
+	return 0;
+
+out_err:
+	clear_perf_probe_event(dst);
+	return -ENOMEM;
+}
+
 void clear_probe_trace_event(struct probe_trace_event *tev)
 {
 	struct probe_trace_arg_ref *ref, *next;
@@ -2348,6 +2426,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
 {
 	int i, fd, ret;
 	struct probe_trace_event *tev = NULL;
+	struct probe_cache *cache = NULL;
 	struct strlist *namelist;
 
 	fd = probe_file__open(PF_FL_RW | (pev->uprobes ? PF_FL_UPROBE : 0));
@@ -2389,6 +2468,14 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
 	}
 	if (ret == -EINVAL && pev->uprobes)
 		warn_uprobe_event_compat(tev);
+	if (ret == 0 && probe_conf.cache) {
+		cache = probe_cache__new(pev->target);
+		if (cache) {
+			probe_cache__add_entry(cache, pev, tevs, ntevs);
+			probe_cache__commit(cache);
+			probe_cache__delete(cache);
+		}
+	}
 
 	strlist__delete(namelist);
 close_out:
@@ -2417,9 +2504,6 @@ static int find_probe_functions(struct map *map, char *name,
 	return found;
 }
 
-#define strdup_or_goto(str, label)	\
-	({ char *__p = strdup(str); if (!__p) goto label; __p; })
-
 void __weak arch__fix_tev_from_maps(struct perf_probe_event *pev __maybe_unused,
 				struct probe_trace_event *tev __maybe_unused,
 				struct map *map __maybe_unused) { }
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index e220962..c451223 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -12,6 +12,7 @@ struct probe_conf {
 	bool	show_location_range;
 	bool	force_add;
 	bool	no_inlines;
+	bool	cache;
 	int	max_probes;
 };
 extern struct probe_conf probe_conf;
@@ -121,6 +122,10 @@ int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev);
 char *synthesize_perf_probe_command(struct perf_probe_event *pev);
 char *synthesize_probe_trace_command(struct probe_trace_event *tev);
 char *synthesize_perf_probe_arg(struct perf_probe_arg *pa);
+char *synthesize_perf_probe_point(struct perf_probe_point *pp);
+
+int perf_probe_event__copy(struct perf_probe_event *dst,
+			   struct perf_probe_event *src);
 
 /* Check the perf_probe_event needs debuginfo */
 bool perf_probe_event_need_dwarf(struct perf_probe_event *pev);
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index 3fe6214..bb849c9 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -14,6 +14,7 @@
  * GNU General Public License for more details.
  *
  */
+#include <sys/uio.h>
 #include "util.h"
 #include "event.h"
 #include "strlist.h"
@@ -324,3 +325,301 @@ int probe_file__del_events(int fd, struct strfilter *filter)
 
 	return ret;
 }
+
+static void probe_cache_entry__delete(struct probe_cache_entry *node)
+{
+	if (!list_empty(&node->list))
+		list_del(&node->list);
+	if (node->tevlist)
+		strlist__delete(node->tevlist);
+	clear_perf_probe_event(&node->pev);
+	free(node->spev);
+	free(node);
+}
+
+static struct probe_cache_entry *
+probe_cache_entry__new(struct perf_probe_event *pev)
+{
+	struct probe_cache_entry *ret = zalloc(sizeof(*ret));
+
+	if (ret) {
+		INIT_LIST_HEAD(&ret->list);
+		ret->tevlist = strlist__new(NULL, NULL);
+		if (!ret->tevlist)
+			zfree(&ret);
+		if (ret && pev) {
+			ret->spev = synthesize_perf_probe_command(pev);
+			if (!ret->spev ||
+			    perf_probe_event__copy(&ret->pev, pev) < 0) {
+				probe_cache_entry__delete(ret);
+				return NULL;
+			}
+		}
+	}
+
+	return ret;
+}
+
+/* For the kernel probe caches, pass target = NULL */
+static int probe_cache__open(struct probe_cache *pcache, const char *target)
+{
+	char cpath[PATH_MAX];
+	char sbuildid[SBUILD_ID_SIZE];
+	char *dir_name;
+	bool is_kallsyms = !target;
+	int ret, fd;
+
+	if (target)
+		ret = filename__sprintf_build_id(target, sbuildid);
+	else {
+		target = "[kernel.kallsyms]";
+		ret = sysfs__sprintf_build_id("/", sbuildid);
+	}
+	if (ret < 0) {
+		pr_debug("Failed to get build-id from %s.\n", target ?: "kernel");
+		return ret;
+	}
+
+	/* If we have no buildid cache, make it */
+	if (!build_id_cache__cached(sbuildid)) {
+		ret = build_id_cache__add_s(sbuildid, target,
+					    is_kallsyms, NULL);
+		if (ret < 0) {
+			pr_debug("Failed to add build-id cache: %s\n", target);
+			return ret;
+		}
+	}
+
+	dir_name = build_id_cache__dirname_from_path(sbuildid, target,
+						     is_kallsyms, false);
+	if (!dir_name)
+		return -ENOMEM;
+
+	snprintf(cpath, PATH_MAX, "%s/probes", dir_name);
+	fd = open(cpath, O_CREAT | O_RDWR | O_APPEND, 0644);
+	if (fd < 0)
+		pr_debug("Failed to open cache(%d): %s\n", fd, cpath);
+	free(dir_name);
+	pcache->fd = fd;
+
+	return fd;
+}
+
+static int probe_cache__load(struct probe_cache *pcache)
+{
+	struct probe_cache_entry *entry = NULL;
+	char buf[MAX_CMDLEN], *p;
+	int ret = 0;
+	FILE *fp;
+
+	fp = fdopen(dup(pcache->fd), "r");
+	while (!feof(fp)) {
+		if (!fgets(buf, MAX_CMDLEN, fp))
+			break;
+		p = strchr(buf, '\n');
+		if (p)
+			*p = '\0';
+		if (buf[0] == '#') {	/* #perf_probe_event */
+			entry = probe_cache_entry__new(NULL);
+			entry->spev = strdup(buf + 1);
+			ret = parse_perf_probe_command(buf + 1, &entry->pev);
+			if (!entry->spev || ret < 0) {
+				probe_cache_entry__delete(entry);
+				goto out;
+			}
+			list_add_tail(&entry->list, &pcache->list);
+		} else {	/* trace_probe_event */
+			if (!entry) {
+				ret = -EINVAL;
+				goto out;
+			}
+			strlist__add(entry->tevlist, buf);
+		}
+	}
+out:
+	fclose(fp);
+	return ret;
+}
+
+static struct probe_cache *probe_cache__alloc(void)
+{
+	struct probe_cache *ret = zalloc(sizeof(*ret));
+
+	if (ret) {
+		INIT_LIST_HEAD(&ret->list);
+		ret->fd = -EINVAL;
+	}
+	return ret;
+}
+
+void probe_cache__delete(struct probe_cache *pcache)
+{
+	struct probe_cache_entry *entry;
+
+	if (!pcache)
+		return;
+
+	while (!list_empty(&pcache->list)) {
+		entry = list_first_entry(&pcache->list, typeof(*entry), list);
+		probe_cache_entry__delete(entry);
+	}
+	if (pcache->fd > 0)
+		close(pcache->fd);
+	free(pcache);
+}
+
+struct probe_cache *probe_cache__new(const char *target)
+{
+	struct probe_cache *pcache = probe_cache__alloc();
+	int ret;
+
+	if (!pcache)
+		return NULL;
+
+	ret = probe_cache__open(pcache, target);
+	if (ret < 0) {
+		pr_debug("Cache open error: %d\n", ret);
+		goto out_err;
+	}
+
+	ret = probe_cache__load(pcache);
+	if (ret < 0) {
+		pr_debug("Cache read error: %d\n", ret);
+		goto out_err;
+	}
+
+	return pcache;
+
+out_err:
+	probe_cache__delete(pcache);
+	return NULL;
+}
+
+static bool streql(const char *a, const char *b)
+{
+	if (a == b)
+		return true;
+
+	if (!a || !b)
+		return false;
+
+	return !strcmp(a, b);
+}
+
+static struct probe_cache_entry *
+probe_cache__find(struct probe_cache *pcache, struct perf_probe_event *pev)
+{
+	struct probe_cache_entry *entry = NULL;
+	char *cmd = NULL;
+
+	cmd = synthesize_perf_probe_command(pev);
+	if (!cmd)
+		return NULL;
+
+	list_for_each_entry(entry, &pcache->list, list) {
+		/* Hit if same event name or same command-string */
+		if ((pev->event &&
+		     (streql(entry->pev.group, pev->group) &&
+		      streql(entry->pev.event, pev->event))) ||
+		    (!strcmp(entry->spev, cmd)))
+			goto found;
+	}
+	entry = NULL;
+
+found:
+	free(cmd);
+	return entry;
+}
+
+int probe_cache__add_entry(struct probe_cache *pcache,
+			   struct perf_probe_event *pev,
+			   struct probe_trace_event *tevs, int ntevs)
+{
+	struct probe_cache_entry *entry = NULL;
+	char *command;
+	int i, ret = 0;
+
+	if (!pcache || !pev || !tevs || ntevs <= 0) {
+		ret = -EINVAL;
+		goto out_err;
+	}
+
+	/* Remove old cache entry */
+	entry = probe_cache__find(pcache, pev);
+	if (entry)
+		probe_cache_entry__delete(entry);
+
+	ret = -ENOMEM;
+	entry = probe_cache_entry__new(pev);
+	if (!entry)
+		goto out_err;
+
+	for (i = 0; i < ntevs; i++) {
+		if (!tevs[i].point.symbol)
+			continue;
+
+		command = synthesize_probe_trace_command(&tevs[i]);
+		if (!command)
+			goto out_err;
+		strlist__add(entry->tevlist, command);
+		free(command);
+	}
+	list_add_tail(&entry->list, &pcache->list);
+	pr_debug("Added probe cache: %d\n", ntevs);
+	return 0;
+
+out_err:
+	pr_debug("Failed to add probe caches\n");
+	if (entry)
+		probe_cache_entry__delete(entry);
+	return ret;
+}
+
+static int probe_cache_entry__write(struct probe_cache_entry *entry, int fd)
+{
+	struct str_node *snode;
+	struct iovec iov[3];
+	int ret;
+
+	pr_debug("Writing cache: #%s\n", entry->spev);
+	iov[0].iov_base = (void *)"#"; iov[0].iov_len = 1;
+	iov[1].iov_base = entry->spev; iov[1].iov_len = strlen(entry->spev);
+	iov[2].iov_base = (void *)"\n"; iov[2].iov_len = 1;
+	ret = writev(fd, iov, 3);
+	if (ret < 0)
+		return ret;
+
+	strlist__for_each(snode, entry->tevlist) {
+		iov[0].iov_base = (void *)snode->s;
+		iov[0].iov_len = strlen(snode->s);
+		iov[1].iov_base = (void *)"\n"; iov[1].iov_len = 1;
+		ret = writev(fd, iov, 2);
+		if (ret < 0)
+			return ret;
+	}
+	return 0;
+}
+
+int probe_cache__commit(struct probe_cache *pcache)
+{
+	struct probe_cache_entry *entry;
+	int ret = 0;
+
+	/* TBD: if we do not update existing entries, skip it */
+	ret = lseek(pcache->fd, 0, SEEK_SET);
+	if (ret < 0)
+		goto out;
+
+	ret = ftruncate(pcache->fd, 0);
+	if (ret < 0)
+		goto out;
+
+	list_for_each_entry(entry, &pcache->list, list) {
+		ret = probe_cache_entry__write(entry, pcache->fd);
+		pr_debug("Cache committed: %d\n", ret);
+		if (ret < 0)
+			break;
+	}
+out:
+	return ret;
+}
diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
index 18ac9cf..ded9e0a 100644
--- a/tools/perf/util/probe-file.h
+++ b/tools/perf/util/probe-file.h
@@ -18,5 +18,24 @@ int probe_file__get_events(int fd, struct strfilter *filter,
 				  struct strlist *plist);
 int probe_file__del_strlist(int fd, struct strlist *namelist);
 
+/* Cache of probe definitions */
+struct probe_cache_entry {
+	struct list_head	list;
+	struct perf_probe_event pev;
+	char			*spev;
+	struct strlist		*tevlist;
+};
+
+struct probe_cache {
+	int	fd;
+	struct list_head list;
+};
+
+struct probe_cache *probe_cache__new(const char *target);
+int probe_cache__add_entry(struct probe_cache *pcache,
+			   struct perf_probe_event *pev,
+			   struct probe_trace_event *tevs, int ntevs);
+int probe_cache__commit(struct probe_cache *pcache);
+void probe_cache__delete(struct probe_cache *pcache);
 
 #endif

[toc] | [prev] | [next] | [standalone]


#1387263 — [PATCH perf/core v4 10/19] perf probe: Remove caches when --cache is given

FromMasami Hiramatsu <mhiramat@kernel.org>
Date2016-04-26 11:10 +0200
Subject[PATCH perf/core v4 10/19] perf probe: Remove caches when --cache is given
Message-ID<rs7ak-4SP-49@gated-at.bofh.it>
In reply to#1387248
From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>

perf-probe --del removes caches when --cache is given.
Note that the delete pattern is not same as normal events.

If you cached probes with event name, --del "eventname"
works as expected. However, if you skipped it, the cached
probes doesn't have actual event name. In that case
 --del "probe-desc" is required (wildcard is acceptable).
For example a cache entry has the probe-desc "vfs_read $params",
you can remove it with --del 'vfs_read*'.

  -----
  # perf probe --cache --list
  /[kernel.kallsyms] (1466a0a250b5d0070c6d0f03c5fed30b237970a1):
  vfs_read $params
  /usr/lib64/libc-2.17.so (c31ffe7942bfd77b2fca8f9bd5709d387a86d3bc):
  getaddrinfo $params

  # perf probe --cache --del vfs_read\*
  Removed event: probe:vfs_read

  # perf probe --cache --list
  /[kernel.kallsyms] (1466a0a250b5d0070c6d0f03c5fed30b237970a1):
  /usr/lib64/libc-2.17.so (c31ffe7942bfd77b2fca8f9bd5709d387a86d3bc):
  getaddrinfo $params
  -----

Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 Changes in v4:
  - move del_perf_probe_caches() into builtin-probe.c since
    command-line related delete procedure is there now.
---
 tools/perf/Documentation/perf-probe.txt |    1 +
 tools/perf/builtin-probe.c              |   27 +++++++++++++++++++++++++
 tools/perf/util/probe-file.c            |   33 +++++++++++++++++++++++--------
 tools/perf/util/probe-file.h            |    2 ++
 4 files changed, 55 insertions(+), 8 deletions(-)

diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 5a70d45..8d09173 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -116,6 +116,7 @@ OPTIONS
 	(With --add) Cache the probes. Any events which successfully added
 	are also stored in the cache file.
 	(With --list) Show cached probes.
+	(With --del) Remove cached probes.
 
 --max-probes=NUM::
 	Set the maximum number of probe points for an event. Default is 128.
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 53e380c0e..8f61525 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -363,6 +363,30 @@ out_cleanup:
 	return ret;
 }
 
+static int del_perf_probe_caches(struct strfilter *filter)
+{
+	struct probe_cache *cache;
+	struct strlist *bidlist;
+	struct str_node *nd;
+	int ret;
+
+	ret = build_id_cache__list_all(&bidlist);
+	if (ret < 0) {
+		pr_debug("Failed to get buildids: %d\n", ret);
+		return ret;
+	}
+
+	strlist__for_each(nd, bidlist) {
+		cache = probe_cache__new(nd->s);
+		if (!cache)
+			continue;
+		probe_cache__remove_entries(cache, filter);
+		probe_cache__commit(cache);
+		probe_cache__delete(cache);
+	}
+	return 0;
+}
+
 static int perf_del_probe_events(struct strfilter *filter)
 {
 	int ret, ret2, ufd = -1, kfd = -1;
@@ -375,6 +399,9 @@ static int perf_del_probe_events(struct strfilter *filter)
 
 	pr_debug("Delete filter: \'%s\'\n", str);
 
+	if (probe_conf.cache)
+		return del_perf_probe_caches(filter);
+
 	/* Get current event names */
 	ret = probe_file__open_both(&kfd, &ufd, PF_FL_RW);
 	if (ret < 0)
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index 72d58e7..46f006e 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -396,7 +396,6 @@ static int probe_cache__open(struct probe_cache *pcache, const char *target)
 			return ret;
 		}
 	}
-
 	dir_name = build_id_cache__dirname_from_path(sbuildid, target,
 						     is_kallsyms, false);
 found:
@@ -652,19 +651,37 @@ out:
 	return ret;
 }
 
+static bool probe_cache_entry__compare(struct probe_cache_entry *entry,
+				       struct strfilter *filter)
+{
+	char buf[128], *ptr = entry->spev;
+
+	if (entry->pev.event) {
+		snprintf(buf, 128, "%s:%s", entry->pev.group, entry->pev.event);
+		ptr = buf;
+	}
+	return strfilter__compare(filter, ptr);
+}
+
+int probe_cache__remove_entries(struct probe_cache *pcache,
+				struct strfilter *filter)
+{
+	struct probe_cache_entry *entry, *tmp;
+
+	list_for_each_entry_safe(entry, tmp, &pcache->list, list) {
+		if (probe_cache_entry__compare(entry, filter))
+			probe_cache_entry__delete(entry);
+	}
+	return 0;
+}
+
 static int probe_cache__show_entries(struct probe_cache *pcache,
 				     struct strfilter *filter)
 {
 	struct probe_cache_entry *entry;
-	char buf[128], *ptr;
 
 	list_for_each_entry(entry, &pcache->list, list) {
-		if (entry->pev.event) {
-			ptr = buf;
-			snprintf(buf, 128, "%s:%s", entry->pev.group, entry->pev.event);
-		} else
-			ptr = entry->spev;
-		if (strfilter__compare(filter, ptr))
+		if (probe_cache_entry__compare(entry, filter))
 			printf("%s\n", entry->spev);
 	}
 	return 0;
diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
index ab6911d..ba7b6d3 100644
--- a/tools/perf/util/probe-file.h
+++ b/tools/perf/util/probe-file.h
@@ -37,6 +37,8 @@ int probe_cache__add_entry(struct probe_cache *pcache,
 			   struct probe_trace_event *tevs, int ntevs);
 int probe_cache__commit(struct probe_cache *pcache);
 void probe_cache__delete(struct probe_cache *pcache);
+int probe_cache__remove_entries(struct probe_cache *pcache,
+				struct strfilter *filter);
 struct probe_cache_entry *probe_cache__find(struct probe_cache *pcache,
 					    struct perf_probe_event *pev);
 struct probe_cache_entry *probe_cache__find_by_name(struct probe_cache *pcache,

[toc] | [prev] | [next] | [standalone]


#1387264 — [PATCH perf/core v4 14/19] perf buildid-cache: Scan and import user SDT events to probe cache

FromMasami Hiramatsu <mhiramat@kernel.org>
Date2016-04-26 11:10 +0200
Subject[PATCH perf/core v4 14/19] perf buildid-cache: Scan and import user SDT events to probe cache
Message-ID<rs7ak-4SP-55@gated-at.bofh.it>
In reply to#1387248
From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>

perf buildid-cache --add <binary> scans given binary and add
the SDT events to probe cache. "sdt_" prefix is appended for
all SDT providers to avoid event-name clash with other pre-defined
events. It is possible to use the cached SDT events as other cached
events, via perf probe --add "sdt_<provider>:<event>=<event>".

e.g.
  ----
  # perf buildid-cache --add /lib/libc-2.17.so
  # perf probe --cache --list | head -n 5
  /usr/lib/libc-2.17.so (a6fb821bdf53660eb2c29f778757aef294d3d392):
  sdt_libc:setjmp=setjmp
  sdt_libc:longjmp=longjmp
  sdt_libc:longjmp_target=longjmp_target
  sdt_libc:memory_heap_new=memory_heap_new
  # perf probe -x /usr/lib/libc-2.17.so \
    -a sdt_libc:memory_heap_new=memory_heap_new
  Added new event:
    sdt_libc:memory_heap_new (on memory_heap_new
   in /usr/lib/libc-2.17.so)

  You can now use it in all perf tools, such as:

          perf record -e sdt_libc:memory_heap_new -aR sleep 1

  # perf probe -l
    sdt_libc:memory_heap_new (on new_heap+183 in /usr/lib/libc-2.17.so)
  ----

Note that SDT event entries in probe-cache file is somewhat different
from normal cached events. Normal one starts with "#", but SDTs are
starting with "%".

Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 Changes in v4:
  - Fix a bug to copy correct group name to entries.
  - Fix to consolidate same-name entries.
---
 tools/perf/util/build-id.c   |   27 +++++++++++++++--
 tools/perf/util/probe-file.c |   67 ++++++++++++++++++++++++++++++++++++++++--
 tools/perf/util/probe-file.h |    2 +
 3 files changed, 90 insertions(+), 6 deletions(-)

diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index a7da315..49a467b9 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -17,6 +17,7 @@
 #include "tool.h"
 #include "header.h"
 #include "vdso.h"
+#include "probe-file.h"
 
 
 static bool no_buildid_cache;
@@ -490,6 +491,23 @@ int build_id_cache__list_build_ids(const char *pathname,
 	return ret;
 }
 
+#ifdef HAVE_LIBELF_SUPPORT
+static void build_id_cache__add_sdt_cache(const char *sbuild_id,
+					  const char *realname)
+{
+	struct probe_cache *cache;
+
+	cache = probe_cache__new(sbuild_id);
+	if (!cache)
+		return;
+	if (probe_cache__scan_sdt(cache, realname) >= 0)
+		probe_cache__commit(cache);
+	probe_cache__delete(cache);
+}
+#else
+#define build_id_cache__add_sdt_cache(sbuild_id, realname) do { } while (0)
+#endif
+
 int build_id_cache__add_s(const char *sbuild_id, const char *name,
 			  bool is_kallsyms, bool is_vdso)
 {
@@ -533,20 +551,23 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
 			goto out_free;
 	}
 
+	/* Make a symbolic link */
 	if (!build_id_cache__linkname(sbuild_id, linkname, size))
 		goto out_free;
+
 	tmp = strrchr(linkname, '/');
 	*tmp = '\0';
-
 	if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
 		goto out_free;
-
 	*tmp = '/';
 	tmp = dir_name + strlen(buildid_dir) - 5;
 	memcpy(tmp, "../..", 5);
-
 	if (symlink(tmp, linkname) == 0)
 		err = 0;
+
+	/* Update SDT cache */
+	build_id_cache__add_sdt_cache(sbuild_id, realname);
+
 out_free:
 	if (!is_kallsyms)
 		free(realname);
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index 46f006e..c10a647 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -428,9 +428,12 @@ static int probe_cache__load(struct probe_cache *pcache)
 		p = strchr(buf, '\n');
 		if (p)
 			*p = '\0';
-		if (buf[0] == '#') {	/* #perf_probe_event */
+		/* #perf_probe_event or %sdt_event */
+		if (buf[0] == '#' || buf[0] == '%') {
 			entry = probe_cache_entry__new(NULL);
 			entry->spev = strdup(buf + 1);
+			if (buf[0] == '%')
+				entry->sdt = true;
 			ret = parse_perf_probe_command(buf + 1, &entry->pev);
 			if (!entry->spev || ret < 0) {
 				probe_cache_entry__delete(entry);
@@ -602,14 +605,72 @@ out_err:
 	return ret;
 }
 
+static unsigned long long sdt_note__get_addr(struct sdt_note *note)
+{
+	return note->bit32 ? (unsigned long long)note->addr.a32[0]
+		 : (unsigned long long)note->addr.a64[0];
+}
+
+int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
+{
+	struct probe_cache_entry *entry = NULL;
+	struct list_head sdtlist;
+	struct sdt_note *note;
+	char *buf;
+	char sdtgrp[64];
+	int ret;
+
+	INIT_LIST_HEAD(&sdtlist);
+	ret = get_sdt_note_list(&sdtlist, pathname);
+	if (ret < 0) {
+		pr_debug("Failed to get sdt note: %d\n", ret);
+		return ret;
+	}
+	list_for_each_entry(note, &sdtlist, note_list) {
+		ret = snprintf(sdtgrp, 64, "sdt_%s", note->provider);
+		if (ret < 0)
+			break;
+		/* Try to find same-name entry */
+		entry = probe_cache__find_by_name(pcache, sdtgrp, note->name);
+		if (!entry) {
+			entry = probe_cache_entry__new(NULL);
+			if (!entry) {
+				ret = -ENOMEM;
+				break;
+			}
+			entry->sdt = true;
+			ret = asprintf(&entry->spev, "%s:%s=%s", sdtgrp,
+					note->name, note->name);
+			if (ret < 0)
+				break;
+			entry->pev.event = strdup(note->name);
+			entry->pev.group = strdup(sdtgrp);
+			list_add_tail(&entry->list, &pcache->list);
+		}
+		ret = asprintf(&buf, "p:%s/%s %s:0x%llx",
+				sdtgrp, note->name, pathname,
+				sdt_note__get_addr(note));
+		if (ret < 0)
+			break;
+		strlist__add(entry->tevlist, buf);
+		free(buf);
+		entry = NULL;
+	}
+	if (entry)
+		probe_cache_entry__delete(entry);
+	cleanup_sdt_note_list(&sdtlist);
+	return ret;
+}
+
 static int probe_cache_entry__write(struct probe_cache_entry *entry, int fd)
 {
 	struct str_node *snode;
 	struct iovec iov[3];
+	const char *prefix = entry->sdt ? "%" : "#";
 	int ret;
 
-	pr_debug("Writing cache: #%s\n", entry->spev);
-	iov[0].iov_base = (void *)"#"; iov[0].iov_len = 1;
+	pr_debug("Writing cache: %s%s\n", prefix, entry->spev);
+	iov[0].iov_base = (void *)prefix; iov[0].iov_len = 1;
 	iov[1].iov_base = entry->spev; iov[1].iov_len = strlen(entry->spev);
 	iov[2].iov_base = (void *)"\n"; iov[2].iov_len = 1;
 	ret = writev(fd, iov, 3);
diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
index ba7b6d3..55322f1 100644
--- a/tools/perf/util/probe-file.h
+++ b/tools/perf/util/probe-file.h
@@ -21,6 +21,7 @@ int probe_file__del_strlist(int fd, struct strlist *namelist);
 /* Cache of probe definitions */
 struct probe_cache_entry {
 	struct list_head	list;
+	bool			sdt;
 	struct perf_probe_event pev;
 	char			*spev;
 	struct strlist		*tevlist;
@@ -35,6 +36,7 @@ struct probe_cache *probe_cache__new(const char *target);
 int probe_cache__add_entry(struct probe_cache *pcache,
 			   struct perf_probe_event *pev,
 			   struct probe_trace_event *tevs, int ntevs);
+int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname);
 int probe_cache__commit(struct probe_cache *pcache);
 void probe_cache__delete(struct probe_cache *pcache);
 int probe_cache__remove_entries(struct probe_cache *pcache,

[toc] | [prev] | [next] | [standalone]


#1389225 — Re: [PATCH perf/core v4 14/19] perf buildid-cache: Scan and import user SDT events to probe cache

FromArnaldo Carvalho de Melo <acme@kernel.org>
Date2016-04-27 17:30 +0200
SubjectRe: [PATCH perf/core v4 14/19] perf buildid-cache: Scan and import user SDT events to probe cache
Message-ID<rszzB-3p7-17@gated-at.bofh.it>
In reply to#1387264
Em Wed, Apr 27, 2016 at 08:49:08PM +0530, Hemant Kumar escreveu:
> 
> 
> On 04/26/2016 02:34 PM, Masami Hiramatsu wrote:
> >From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
> >
> >perf buildid-cache --add <binary> scans given binary and add
> >the SDT events to probe cache. "sdt_" prefix is appended for
> >all SDT providers to avoid event-name clash with other pre-defined
> >events. It is possible to use the cached SDT events as other cached
> >events, via perf probe --add "sdt_<provider>:<event>=<event>".
> >
> >e.g.
> >   ----
> >   # perf buildid-cache --add /lib/libc-2.17.so
> >   # perf probe --cache --list | head -n 5
> >   /usr/lib/libc-2.17.so (a6fb821bdf53660eb2c29f778757aef294d3d392):
> >   sdt_libc:setjmp=setjmp
> >   sdt_libc:longjmp=longjmp
> >   sdt_libc:longjmp_target=longjmp_target
> >   sdt_libc:memory_heap_new=memory_heap_new
> >   # perf probe -x /usr/lib/libc-2.17.so \
> >     -a sdt_libc:memory_heap_new=memory_heap_new
> >   Added new event:
> >     sdt_libc:memory_heap_new (on memory_heap_new
> >    in /usr/lib/libc-2.17.so)
> >
> >   You can now use it in all perf tools, such as:
> >
> >           perf record -e sdt_libc:memory_heap_new -aR sleep 1
> >
> >   # perf probe -l
> >     sdt_libc:memory_heap_new (on new_heap+183 in /usr/lib/libc-2.17.so)
> >   ----
> 
> Patch looks good to me. Have a few questions below :
> 
> What about the same binary path having different build-ids. For e.g
> a binary say, "test" has some markers, we add it to the cache. And,
> then the file gets rebuilt again with different build-id now. And we try
> to add to the cache again. It shows multiple entries in the cache :
> # perf probe --cache --list
> /home/hemant/test (157380727e2b3854395aa915dfc91dbccc02058b):
> sdt_user_test:marker1=marker1
> /home/hemant/test (64c0a018636e6d5145b09fc65839c1a4a7899f18):
> sdt_user_test:marker1=marker1
> /home/hemant/test (c9e34759ae95b68fa385831041c5d9e0dd1697fb):
> sdt_user_test:marker1=marker1
> ...
> 
> But, perf list sdt shows only one entry (which it should) :
> # perf list sdt
> 
> List of pre-defined events (to be used in -e):
> 
>   sdt_user_test:marker1                                [SDT event]
> 
> perf probe also works as expected :
> # perf probe -x /home/hemant/test %sdt_user_test:marker1
> Added new event:
>   sdt_user_test:marker1  (on %marker1 in /home/hemant/test)
> 
> You can now use it in all perf tools, such as:
> 
>     perf record -e sdt_user_test:marker1 -aR sleep 1
> 
> So, the question is, do we delete the previous entries for "test" from
> the cache once we get a newer version of "test"?

No, we shouldn't, since those entries may be used for other tasks that
involves using the exact DSO used for a particular perf.data session.

Humm, but you are talking about what cache? The "probe cache" or the
"build-id cache"? My previous statement was about the build-id cache.

For the probe cache, humm, probably we want to keep it as well, we may
have moved that 'test' file to some other place, renamed it, etc, but it
continues being accessible by its content-based identifier (the
build-id) and could be used in ways we don't envision right now.

I.e. the same principle used for the build-id cache should be used for
this probe cache, where we store things by build-id.

We need to prune this from time to time and for this we have:

  perf buildid-cache purge

But that right now is unflexible, we should have a way to ask to control
how much is purged :-\

- Arnaldo

- Arnaldo
 
> >Note that SDT event entries in probe-cache file is somewhat different
> >from normal cached events. Normal one starts with "#", but SDTs are
> >starting with "%".
> >
> >Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
> >Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
> >---
> [SNIP]
> >+	list_for_each_entry(note, &sdtlist, note_list) {
> >+		ret = snprintf(sdtgrp, 64, "sdt_%s", note->provider);
> >+		if (ret < 0)
> >+			break;
> >+		/* Try to find same-name entry */
> >+		entry = probe_cache__find_by_name(pcache, sdtgrp, note->name);
> 
> Wouldn't it be better to compare the build-id rather than the event
> name? So, if there is a new sdt event added to a binary, its build-id will
> change. And, if there is no change, the build-id remains the same.
> 
> Only if there is a change in the build-id, we can go for searching the
> event name. This two level check can help optimizing the search.
> 
> >+		if (!entry) {
> >+			entry = probe_cache_entry__new(NULL);
> >+			if (!entry) {
> >+				ret = -ENOMEM;
> >+				break;
> >+			}
> >+			entry->sdt = true;
> >+			ret = asprintf(&entry->spev, "%s:%s=%s", sdtgrp,
> >+					note->name, note->name);
> >+			if (ret < 0)
> >+				break;
> >+			entry->pev.event = strdup(note->name);
> >+			entry->pev.group = strdup(sdtgrp);
> >+			list_add_tail(&entry->list, &pcache->list);
> >+		}
> >+		ret = asprintf(&buf, "p:%s/%s %s:0x%llx",
> >+				sdtgrp, note->name, pathname,
> >+				sdt_note__get_addr(note));
> >+		if (ret < 0)
> >+			break;
> >+		strlist__add(entry->tevlist, buf);
> >+		free(buf);
> >+		entry = NULL;
> >+	}
> >+	if (entry)
> >+		probe_cache_entry__delete(entry);
> >+	cleanup_sdt_note_list(&sdtlist);
> >+	return ret;
> >+}
> >+
> >  static int probe_cache_entry__write(struct probe_cache_entry *entry, int fd)
> >  {
> >  	struct str_node *snode;
> >  	struct iovec iov[3];
> >+	const char *prefix = entry->sdt ? "%" : "#";
> >  	int ret;
> >
> >-	pr_debug("Writing cache: #%s\n", entry->spev);
> >-	iov[0].iov_base = (void *)"#"; iov[0].iov_len = 1;
> >+	pr_debug("Writing cache: %s%s\n", prefix, entry->spev);
> >+	iov[0].iov_base = (void *)prefix; iov[0].iov_len = 1;
> >  	iov[1].iov_base = entry->spev; iov[1].iov_len = strlen(entry->spev);
> >  	iov[2].iov_base = (void *)"\n"; iov[2].iov_len = 1;
> >  	ret = writev(fd, iov, 3);
> >diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
> >index ba7b6d3..55322f1 100644
> >--- a/tools/perf/util/probe-file.h
> >+++ b/tools/perf/util/probe-file.h
> >@@ -21,6 +21,7 @@ int probe_file__del_strlist(int fd, struct strlist *namelist);
> >  /* Cache of probe definitions */
> >  struct probe_cache_entry {
> >  	struct list_head	list;
> >+	bool			sdt;
> >  	struct perf_probe_event pev;
> >  	char			*spev;
> >  	struct strlist		*tevlist;
> >@@ -35,6 +36,7 @@ struct probe_cache *probe_cache__new(const char *target);
> >  int probe_cache__add_entry(struct probe_cache *pcache,
> >  			   struct perf_probe_event *pev,
> >  			   struct probe_trace_event *tevs, int ntevs);
> >+int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname);
> >  int probe_cache__commit(struct probe_cache *pcache);
> >  void probe_cache__delete(struct probe_cache *pcache);
> >  int probe_cache__remove_entries(struct probe_cache *pcache,
> >
> 
> -- 
> Thanks,
> Hemant Kumar

[toc] | [prev] | [next] | [standalone]


#1389526 — Re: [PATCH perf/core v4 14/19] perf buildid-cache: Scan and import user SDT events to probe cache

FromMasami Hiramatsu <mhiramat@kernel.org>
Date2016-04-27 21:40 +0200
SubjectRe: [PATCH perf/core v4 14/19] perf buildid-cache: Scan and import user SDT events to probe cache
Message-ID<rsDtw-6Pk-3@gated-at.bofh.it>
In reply to#1389225
On Wed, 27 Apr 2016 12:28:16 -0300
Arnaldo Carvalho de Melo <acme@kernel.org> wrote:

> Em Wed, Apr 27, 2016 at 08:49:08PM +0530, Hemant Kumar escreveu:
> > 
> > 
> > On 04/26/2016 02:34 PM, Masami Hiramatsu wrote:
> > >From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
> > >
> > >perf buildid-cache --add <binary> scans given binary and add
> > >the SDT events to probe cache. "sdt_" prefix is appended for
> > >all SDT providers to avoid event-name clash with other pre-defined
> > >events. It is possible to use the cached SDT events as other cached
> > >events, via perf probe --add "sdt_<provider>:<event>=<event>".
> > >
> > >e.g.
> > >   ----
> > >   # perf buildid-cache --add /lib/libc-2.17.so
> > >   # perf probe --cache --list | head -n 5
> > >   /usr/lib/libc-2.17.so (a6fb821bdf53660eb2c29f778757aef294d3d392):
> > >   sdt_libc:setjmp=setjmp
> > >   sdt_libc:longjmp=longjmp
> > >   sdt_libc:longjmp_target=longjmp_target
> > >   sdt_libc:memory_heap_new=memory_heap_new
> > >   # perf probe -x /usr/lib/libc-2.17.so \
> > >     -a sdt_libc:memory_heap_new=memory_heap_new
> > >   Added new event:
> > >     sdt_libc:memory_heap_new (on memory_heap_new
> > >    in /usr/lib/libc-2.17.so)
> > >
> > >   You can now use it in all perf tools, such as:
> > >
> > >           perf record -e sdt_libc:memory_heap_new -aR sleep 1
> > >
> > >   # perf probe -l
> > >     sdt_libc:memory_heap_new (on new_heap+183 in /usr/lib/libc-2.17.so)
> > >   ----
> > 
> > Patch looks good to me. Have a few questions below :
> > 
> > What about the same binary path having different build-ids. For e.g
> > a binary say, "test" has some markers, we add it to the cache. And,
> > then the file gets rebuilt again with different build-id now. And we try
> > to add to the cache again. It shows multiple entries in the cache :
> > # perf probe --cache --list
> > /home/hemant/test (157380727e2b3854395aa915dfc91dbccc02058b):
> > sdt_user_test:marker1=marker1
> > /home/hemant/test (64c0a018636e6d5145b09fc65839c1a4a7899f18):
> > sdt_user_test:marker1=marker1
> > /home/hemant/test (c9e34759ae95b68fa385831041c5d9e0dd1697fb):
> > sdt_user_test:marker1=marker1
> > ...
> > 
> > But, perf list sdt shows only one entry (which it should) :
> > # perf list sdt
> > 
> > List of pre-defined events (to be used in -e):
> > 
> >   sdt_user_test:marker1                                [SDT event]
> > 
> > perf probe also works as expected :
> > # perf probe -x /home/hemant/test %sdt_user_test:marker1
> > Added new event:
> >   sdt_user_test:marker1  (on %marker1 in /home/hemant/test)
> > 
> > You can now use it in all perf tools, such as:
> > 
> >     perf record -e sdt_user_test:marker1 -aR sleep 1
> > 
> > So, the question is, do we delete the previous entries for "test" from
> > the cache once we get a newer version of "test"?
> 
> No, we shouldn't, since those entries may be used for other tasks that
> involves using the exact DSO used for a particular perf.data session.

Agreed. And you can do it by using perf buildid-cache as below;

# perf buildid-cache --purge /home/hemant/test
# perf buildid-cache --add /home/hemant/test

This actually removes all old binary caches, and it maybe not
what you want. Or, you can try removing cached events too.

# perf probe --cache -d %sdt_user_test:\*
# perf buildid-cache --add /home/hemant/test

> Humm, but you are talking about what cache? The "probe cache" or the
> "build-id cache"? My previous statement was about the build-id cache.
> 
> For the probe cache, humm, probably we want to keep it as well, we may
> have moved that 'test' file to some other place, renamed it, etc, but it
> continues being accessible by its content-based identifier (the
> build-id) and could be used in ways we don't envision right now.
> 
> I.e. the same principle used for the build-id cache should be used for
> this probe cache, where we store things by build-id.
> 
> We need to prune this from time to time and for this we have:
> 
>   perf buildid-cache purge
> 
> But that right now is unflexible, we should have a way to ask to control
> how much is purged :-\

Agreed, current buildid-cache --update does just rescan current
binary, but maybe it should also remove old caches.

> > [SNIP]
> > >+	list_for_each_entry(note, &sdtlist, note_list) {
> > >+		ret = snprintf(sdtgrp, 64, "sdt_%s", note->provider);
> > >+		if (ret < 0)
> > >+			break;
> > >+		/* Try to find same-name entry */
> > >+		entry = probe_cache__find_by_name(pcache, sdtgrp, note->name);
> > 
> > Wouldn't it be better to compare the build-id rather than the event
> > name? So, if there is a new sdt event added to a binary, its build-id will
> > change. And, if there is no change, the build-id remains the same.

This is not such purpose, but just for folding same name SDTs(but different
addresses) on same binary.

> > 
> > Only if there is a change in the build-id, we can go for searching the
> > event name. This two level check can help optimizing the search.

That have been done in build-id.c :)

Thank you,

-- 
Masami Hiramatsu <mhiramat@kernel.org>

[toc] | [prev] | [next] | [standalone]


#1389568 — Re: [PATCH perf/core v4 14/19] perf buildid-cache: Scan and import user SDT events to probe cache

FromHemant Kumar <hemant@linux.vnet.ibm.com>
Date2016-04-27 22:30 +0200
SubjectRe: [PATCH perf/core v4 14/19] perf buildid-cache: Scan and import user SDT events to probe cache
Message-ID<rsEfU-7xd-11@gated-at.bofh.it>
In reply to#1389526

On 04/28/2016 01:06 AM, Masami Hiramatsu wrote:
> On Wed, 27 Apr 2016 12:28:16 -0300
> Arnaldo Carvalho de Melo <acme@kernel.org> wrote:
>
>> Em Wed, Apr 27, 2016 at 08:49:08PM +0530, Hemant Kumar escreveu:
>>>
>>> On 04/26/2016 02:34 PM, Masami Hiramatsu wrote:
>>>> From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
>>>>
>>>> perf buildid-cache --add <binary> scans given binary and add
>>>> the SDT events to probe cache. "sdt_" prefix is appended for
>>>> all SDT providers to avoid event-name clash with other pre-defined
>>>> events. It is possible to use the cached SDT events as other cached
>>>> events, via perf probe --add "sdt_<provider>:<event>=<event>".
>>>>
>>>> e.g.
>>>>    ----
>>>>    # perf buildid-cache --add /lib/libc-2.17.so
>>>>    # perf probe --cache --list | head -n 5
>>>>    /usr/lib/libc-2.17.so (a6fb821bdf53660eb2c29f778757aef294d3d392):
>>>>    sdt_libc:setjmp=setjmp
>>>>    sdt_libc:longjmp=longjmp
>>>>    sdt_libc:longjmp_target=longjmp_target
>>>>    sdt_libc:memory_heap_new=memory_heap_new
>>>>    # perf probe -x /usr/lib/libc-2.17.so \
>>>>      -a sdt_libc:memory_heap_new=memory_heap_new
>>>>    Added new event:
>>>>      sdt_libc:memory_heap_new (on memory_heap_new
>>>>     in /usr/lib/libc-2.17.so)
>>>>
>>>>    You can now use it in all perf tools, such as:
>>>>
>>>>            perf record -e sdt_libc:memory_heap_new -aR sleep 1
>>>>
>>>>    # perf probe -l
>>>>      sdt_libc:memory_heap_new (on new_heap+183 in /usr/lib/libc-2.17.so)
>>>>    ----
>>> Patch looks good to me. Have a few questions below :
>>>
>>> What about the same binary path having different build-ids. For e.g
>>> a binary say, "test" has some markers, we add it to the cache. And,
>>> then the file gets rebuilt again with different build-id now. And we try
>>> to add to the cache again. It shows multiple entries in the cache :
>>> # perf probe --cache --list
>>> /home/hemant/test (157380727e2b3854395aa915dfc91dbccc02058b):
>>> sdt_user_test:marker1=marker1
>>> /home/hemant/test (64c0a018636e6d5145b09fc65839c1a4a7899f18):
>>> sdt_user_test:marker1=marker1
>>> /home/hemant/test (c9e34759ae95b68fa385831041c5d9e0dd1697fb):
>>> sdt_user_test:marker1=marker1
>>> ...
>>>
>>> But, perf list sdt shows only one entry (which it should) :
>>> # perf list sdt
>>>
>>> List of pre-defined events (to be used in -e):
>>>
>>>    sdt_user_test:marker1                                [SDT event]
>>>
>>> perf probe also works as expected :
>>> # perf probe -x /home/hemant/test %sdt_user_test:marker1
>>> Added new event:
>>>    sdt_user_test:marker1  (on %marker1 in /home/hemant/test)
>>>
>>> You can now use it in all perf tools, such as:
>>>
>>>      perf record -e sdt_user_test:marker1 -aR sleep 1
>>>
>>> So, the question is, do we delete the previous entries for "test" from
>>> the cache once we get a newer version of "test"?
>> No, we shouldn't, since those entries may be used for other tasks that
>> involves using the exact DSO used for a particular perf.data session.
> Agreed. And you can do it by using perf buildid-cache as below;
>
> # perf buildid-cache --purge /home/hemant/test
> # perf buildid-cache --add /home/hemant/test
>
> This actually removes all old binary caches, and it maybe not
> what you want. Or, you can try removing cached events too.
>
> # perf probe --cache -d %sdt_user_test:\*

Yeah, it does work for me, but without the '%'.

> # perf buildid-cache --add /home/hemant/test
>
>> Humm, but you are talking about what cache? The "probe cache" or the
>> "build-id cache"? My previous statement was about the build-id cache.
>>
>> For the probe cache, humm, probably we want to keep it as well, we may
>> have moved that 'test' file to some other place, renamed it, etc, but it
>> continues being accessible by its content-based identifier (the
>> build-id) and could be used in ways we don't envision right now.
>>
>> I.e. the same principle used for the build-id cache should be used for
>> this probe cache, where we store things by build-id.
>>
>> We need to prune this from time to time and for this we have:
>>
>>    perf buildid-cache purge
>>
>> But that right now is unflexible, we should have a way to ask to control
>> how much is purged :-\
> Agreed, current buildid-cache --update does just rescan current
> binary, but maybe it should also remove old caches.

Ok.

>>> [SNIP]
>>>> +	list_for_each_entry(note, &sdtlist, note_list) {
>>>> +		ret = snprintf(sdtgrp, 64, "sdt_%s", note->provider);
>>>> +		if (ret < 0)
>>>> +			break;
>>>> +		/* Try to find same-name entry */
>>>> +		entry = probe_cache__find_by_name(pcache, sdtgrp, note->name);
>>> Wouldn't it be better to compare the build-id rather than the event
>>> name? So, if there is a new sdt event added to a binary, its build-id will
>>> change. And, if there is no change, the build-id remains the same.
> This is not such purpose, but just for folding same name SDTs(but different
> addresses) on same binary.

I get it. But, I was wondering whether that can be used for comparison 
as well.

>>> Only if there is a change in the build-id, we can go for searching the
>>> event name. This two level check can help optimizing the search.
> That have been done in build-id.c :)

Ok, probably missed it.

> Thank you,
>

Thanks for the explanation.

-- 
Thanks,
Hemant Kumar

[toc] | [prev] | [next] | [standalone]


#1389565 — Re: [PATCH perf/core v4 14/19] perf buildid-cache: Scan and import user SDT events to probe cache

FromHemant Kumar <hemant@linux.vnet.ibm.com>
Date2016-04-27 22:20 +0200
SubjectRe: [PATCH perf/core v4 14/19] perf buildid-cache: Scan and import user SDT events to probe cache
Message-ID<rsE6e-7r0-7@gated-at.bofh.it>
In reply to#1389225

On 04/27/2016 08:58 PM, Arnaldo Carvalho de Melo wrote:
> Em Wed, Apr 27, 2016 at 08:49:08PM +0530, Hemant Kumar escreveu:
>>
>> On 04/26/2016 02:34 PM, Masami Hiramatsu wrote:
>>> From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
>>>
>>> perf buildid-cache --add <binary> scans given binary and add
>>> the SDT events to probe cache. "sdt_" prefix is appended for
>>> all SDT providers to avoid event-name clash with other pre-defined
>>> events. It is possible to use the cached SDT events as other cached
>>> events, via perf probe --add "sdt_<provider>:<event>=<event>".
>>>
>>> e.g.
>>>    ----
>>>    # perf buildid-cache --add /lib/libc-2.17.so
>>>    # perf probe --cache --list | head -n 5
>>>    /usr/lib/libc-2.17.so (a6fb821bdf53660eb2c29f778757aef294d3d392):
>>>    sdt_libc:setjmp=setjmp
>>>    sdt_libc:longjmp=longjmp
>>>    sdt_libc:longjmp_target=longjmp_target
>>>    sdt_libc:memory_heap_new=memory_heap_new
>>>    # perf probe -x /usr/lib/libc-2.17.so \
>>>      -a sdt_libc:memory_heap_new=memory_heap_new
>>>    Added new event:
>>>      sdt_libc:memory_heap_new (on memory_heap_new
>>>     in /usr/lib/libc-2.17.so)
>>>
>>>    You can now use it in all perf tools, such as:
>>>
>>>            perf record -e sdt_libc:memory_heap_new -aR sleep 1
>>>
>>>    # perf probe -l
>>>      sdt_libc:memory_heap_new (on new_heap+183 in /usr/lib/libc-2.17.so)
>>>    ----
>> Patch looks good to me. Have a few questions below :
>>
>> What about the same binary path having different build-ids. For e.g
>> a binary say, "test" has some markers, we add it to the cache. And,
>> then the file gets rebuilt again with different build-id now. And we try
>> to add to the cache again. It shows multiple entries in the cache :
>> # perf probe --cache --list
>> /home/hemant/test (157380727e2b3854395aa915dfc91dbccc02058b):
>> sdt_user_test:marker1=marker1
>> /home/hemant/test (64c0a018636e6d5145b09fc65839c1a4a7899f18):
>> sdt_user_test:marker1=marker1
>> /home/hemant/test (c9e34759ae95b68fa385831041c5d9e0dd1697fb):
>> sdt_user_test:marker1=marker1
>> ...
>>
>> But, perf list sdt shows only one entry (which it should) :
>> # perf list sdt
>>
>> List of pre-defined events (to be used in -e):
>>
>>    sdt_user_test:marker1                                [SDT event]
>>
>> perf probe also works as expected :
>> # perf probe -x /home/hemant/test %sdt_user_test:marker1
>> Added new event:
>>    sdt_user_test:marker1  (on %marker1 in /home/hemant/test)
>>
>> You can now use it in all perf tools, such as:
>>
>>      perf record -e sdt_user_test:marker1 -aR sleep 1
>>
>> So, the question is, do we delete the previous entries for "test" from
>> the cache once we get a newer version of "test"?
> No, we shouldn't, since those entries may be used for other tasks that
> involves using the exact DSO used for a particular perf.data session.
>
> Humm, but you are talking about what cache? The "probe cache" or the
> "build-id cache"? My previous statement was about the build-id cache.

I was talking about the "probe cache".

> For the probe cache, humm, probably we want to keep it as well, we may
> have moved that 'test' file to some other place, renamed it, etc, but it
> continues being accessible by its content-based identifier (the
> build-id) and could be used in ways we don't envision right now.

Agreed. Makes sense.

> I.e. the same principle used for the build-id cache should be used for
> this probe cache, where we store things by build-id.
>
> We need to prune this from time to time and for this we have:
>
>    perf buildid-cache purge
>
> But that right now is unflexible, we should have a way to ask to control
> how much is purged :-\

Right.

-- 
Thanks,
Hemant Kumar

[toc] | [prev] | [next] | [standalone]


#1389228 — Re: [PATCH perf/core v4 14/19] perf buildid-cache: Scan and import user SDT events to probe cache

FromHemant Kumar <hemant@linux.vnet.ibm.com>
Date2016-04-27 17:30 +0200
SubjectRe: [PATCH perf/core v4 14/19] perf buildid-cache: Scan and import user SDT events to probe cache
Message-ID<rszzB-3p7-19@gated-at.bofh.it>
In reply to#1387264

On 04/26/2016 02:34 PM, Masami Hiramatsu wrote:
> From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
>
> perf buildid-cache --add <binary> scans given binary and add
> the SDT events to probe cache. "sdt_" prefix is appended for
> all SDT providers to avoid event-name clash with other pre-defined
> events. It is possible to use the cached SDT events as other cached
> events, via perf probe --add "sdt_<provider>:<event>=<event>".
>
> e.g.
>    ----
>    # perf buildid-cache --add /lib/libc-2.17.so
>    # perf probe --cache --list | head -n 5
>    /usr/lib/libc-2.17.so (a6fb821bdf53660eb2c29f778757aef294d3d392):
>    sdt_libc:setjmp=setjmp
>    sdt_libc:longjmp=longjmp
>    sdt_libc:longjmp_target=longjmp_target
>    sdt_libc:memory_heap_new=memory_heap_new
>    # perf probe -x /usr/lib/libc-2.17.so \
>      -a sdt_libc:memory_heap_new=memory_heap_new
>    Added new event:
>      sdt_libc:memory_heap_new (on memory_heap_new
>     in /usr/lib/libc-2.17.so)
>
>    You can now use it in all perf tools, such as:
>
>            perf record -e sdt_libc:memory_heap_new -aR sleep 1
>
>    # perf probe -l
>      sdt_libc:memory_heap_new (on new_heap+183 in /usr/lib/libc-2.17.so)
>    ----

Patch looks good to me. Have a few questions below :

What about the same binary path having different build-ids. For e.g
a binary say, "test" has some markers, we add it to the cache. And,
then the file gets rebuilt again with different build-id now. And we try
to add to the cache again. It shows multiple entries in the cache :
# perf probe --cache --list
/home/hemant/test (157380727e2b3854395aa915dfc91dbccc02058b):
sdt_user_test:marker1=marker1
/home/hemant/test (64c0a018636e6d5145b09fc65839c1a4a7899f18):
sdt_user_test:marker1=marker1
/home/hemant/test (c9e34759ae95b68fa385831041c5d9e0dd1697fb):
sdt_user_test:marker1=marker1
...

But, perf list sdt shows only one entry (which it should) :
# perf list sdt

List of pre-defined events (to be used in -e):

   sdt_user_test:marker1                                [SDT event]

perf probe also works as expected :
# perf probe -x /home/hemant/test %sdt_user_test:marker1
Added new event:
   sdt_user_test:marker1  (on %marker1 in /home/hemant/test)

You can now use it in all perf tools, such as:

     perf record -e sdt_user_test:marker1 -aR sleep 1

So, the question is, do we delete the previous entries for "test" from
the cache once we get a newer version of "test"?

> Note that SDT event entries in probe-cache file is somewhat different
> from normal cached events. Normal one starts with "#", but SDTs are
> starting with "%".
>
> Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
> Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
> ---
[SNIP]
> +	list_for_each_entry(note, &sdtlist, note_list) {
> +		ret = snprintf(sdtgrp, 64, "sdt_%s", note->provider);
> +		if (ret < 0)
> +			break;
> +		/* Try to find same-name entry */
> +		entry = probe_cache__find_by_name(pcache, sdtgrp, note->name);

Wouldn't it be better to compare the build-id rather than the event
name? So, if there is a new sdt event added to a binary, its build-id will
change. And, if there is no change, the build-id remains the same.

Only if there is a change in the build-id, we can go for searching the
event name. This two level check can help optimizing the search.

> +		if (!entry) {
> +			entry = probe_cache_entry__new(NULL);
> +			if (!entry) {
> +				ret = -ENOMEM;
> +				break;
> +			}
> +			entry->sdt = true;
> +			ret = asprintf(&entry->spev, "%s:%s=%s", sdtgrp,
> +					note->name, note->name);
> +			if (ret < 0)
> +				break;
> +			entry->pev.event = strdup(note->name);
> +			entry->pev.group = strdup(sdtgrp);
> +			list_add_tail(&entry->list, &pcache->list);
> +		}
> +		ret = asprintf(&buf, "p:%s/%s %s:0x%llx",
> +				sdtgrp, note->name, pathname,
> +				sdt_note__get_addr(note));
> +		if (ret < 0)
> +			break;
> +		strlist__add(entry->tevlist, buf);
> +		free(buf);
> +		entry = NULL;
> +	}
> +	if (entry)
> +		probe_cache_entry__delete(entry);
> +	cleanup_sdt_note_list(&sdtlist);
> +	return ret;
> +}
> +
>   static int probe_cache_entry__write(struct probe_cache_entry *entry, int fd)
>   {
>   	struct str_node *snode;
>   	struct iovec iov[3];
> +	const char *prefix = entry->sdt ? "%" : "#";
>   	int ret;
>
> -	pr_debug("Writing cache: #%s\n", entry->spev);
> -	iov[0].iov_base = (void *)"#"; iov[0].iov_len = 1;
> +	pr_debug("Writing cache: %s%s\n", prefix, entry->spev);
> +	iov[0].iov_base = (void *)prefix; iov[0].iov_len = 1;
>   	iov[1].iov_base = entry->spev; iov[1].iov_len = strlen(entry->spev);
>   	iov[2].iov_base = (void *)"\n"; iov[2].iov_len = 1;
>   	ret = writev(fd, iov, 3);
> diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
> index ba7b6d3..55322f1 100644
> --- a/tools/perf/util/probe-file.h
> +++ b/tools/perf/util/probe-file.h
> @@ -21,6 +21,7 @@ int probe_file__del_strlist(int fd, struct strlist *namelist);
>   /* Cache of probe definitions */
>   struct probe_cache_entry {
>   	struct list_head	list;
> +	bool			sdt;
>   	struct perf_probe_event pev;
>   	char			*spev;
>   	struct strlist		*tevlist;
> @@ -35,6 +36,7 @@ struct probe_cache *probe_cache__new(const char *target);
>   int probe_cache__add_entry(struct probe_cache *pcache,
>   			   struct perf_probe_event *pev,
>   			   struct probe_trace_event *tevs, int ntevs);
> +int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname);
>   int probe_cache__commit(struct probe_cache *pcache);
>   void probe_cache__delete(struct probe_cache *pcache);
>   int probe_cache__remove_entries(struct probe_cache *pcache,
>

-- 
Thanks,
Hemant Kumar

[toc] | [prev] | [next] | [standalone]


#1387265 — [PATCH perf/core v4 02/19] perf-buildid-cache: Use path/to/bin/buildid/elf instead of path/to/bin/buildid

FromMasami Hiramatsu <mhiramat@kernel.org>
Date2016-04-26 11:10 +0200
Subject[PATCH perf/core v4 02/19] perf-buildid-cache: Use path/to/bin/buildid/elf instead of path/to/bin/buildid
Message-ID<rs7ak-4SP-57@gated-at.bofh.it>
In reply to#1387248
From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>

Use path/to/bin/buildid/elf instead of path/to/bin/buildid
to store corresponding elf binary.
This also stores vdso in buildid/vdso, kallsyms in buildid/kallsyms.
Note that the build-id based symlink changes to point to the
path/to/bin/buildid, not path/to/bin/buildid/elf.

Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 tools/perf/util/build-id.c |   65 +++++++++++++++++++++++++++++++-------------
 tools/perf/util/dso.h      |    5 +++
 tools/perf/util/symbol.c   |    2 +
 3 files changed, 52 insertions(+), 20 deletions(-)

diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index b6ecf87..46a8bcc 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -144,7 +144,8 @@ static int asnprintf(char **strp, size_t size, const char *fmt, ...)
 	return ret;
 }
 
-static char *build_id__filename(const char *sbuild_id, char *bf, size_t size)
+static char *build_id_cache__linkname(const char *sbuild_id, char *bf,
+				      size_t size)
 {
 	char *tmp = bf;
 	int ret = asnprintf(&bf, size, "%s/.build-id/%.2s/%s", buildid_dir,
@@ -154,15 +155,35 @@ static char *build_id__filename(const char *sbuild_id, char *bf, size_t size)
 	return bf;
 }
 
+static const char *build_id_cache__basename(bool is_kallsyms, bool is_vdso)
+{
+	return is_kallsyms ? "kallsyms" : (is_vdso ? "vdso" : "elf");
+}
+
 char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
 {
-	char build_id_hex[SBUILD_ID_SIZE];
+	bool is_kallsyms = dso__is_kallsyms((struct dso *)dso);
+	bool is_vdso = dso__is_vdso((struct dso *)dso);
+	char sbuild_id[SBUILD_ID_SIZE];
+	char *linkname;
+	bool alloc = (bf == NULL);
+	int ret;
 
 	if (!dso->has_build_id)
 		return NULL;
 
-	build_id__sprintf(dso->build_id, sizeof(dso->build_id), build_id_hex);
-	return build_id__filename(build_id_hex, bf, size);
+	build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
+	linkname = build_id_cache__linkname(sbuild_id, NULL, 0);
+	if (!linkname)
+		return NULL;
+
+	ret = asnprintf(&bf, size, "%s/%s", linkname,
+			 build_id_cache__basename(is_kallsyms, is_vdso));
+	if (ret < 0 || (!alloc && size < (unsigned int)ret))
+		bf = NULL;
+	free(linkname);
+
+	return bf;
 }
 
 bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size)
@@ -341,7 +362,8 @@ void disable_buildid_cache(void)
 }
 
 static char *build_id_cache__dirname_from_path(const char *name,
-					       bool is_kallsyms, bool is_vdso)
+					       bool is_kallsyms, bool is_vdso,
+					       const char *sbuild_id)
 {
 	char *realname = (char *)name, *filename;
 	bool slash = is_kallsyms || is_vdso;
@@ -352,8 +374,9 @@ static char *build_id_cache__dirname_from_path(const char *name,
 			return NULL;
 	}
 
-	if (asprintf(&filename, "%s%s%s", buildid_dir, slash ? "/" : "",
-		     is_vdso ? DSO__NAME_VDSO : realname) < 0)
+	if (asprintf(&filename, "%s%s%s%s%s", buildid_dir, slash ? "/" : "",
+		     is_vdso ? DSO__NAME_VDSO : realname,
+		     sbuild_id ? "/" : "", sbuild_id ?: "") < 0)
 		filename = NULL;
 
 	if (!slash)
@@ -372,7 +395,8 @@ int build_id_cache__list_build_ids(const char *pathname,
 	int ret = 0;
 
 	list = strlist__new(NULL, NULL);
-	dir_name = build_id_cache__dirname_from_path(pathname, false, false);
+	dir_name = build_id_cache__dirname_from_path(pathname, false, false,
+						     NULL);
 	if (!list || !dir_name) {
 		ret = -ENOMEM;
 		goto out;
@@ -407,7 +431,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
 {
 	const size_t size = PATH_MAX;
 	char *realname = NULL, *filename = NULL, *dir_name = NULL,
-	     *linkname = zalloc(size), *targetname, *tmp;
+	     *linkname = zalloc(size), *tmp;
 	int err = -1;
 
 	if (!is_kallsyms) {
@@ -416,14 +440,17 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
 			goto out_free;
 	}
 
-	dir_name = build_id_cache__dirname_from_path(name, is_kallsyms, is_vdso);
+	dir_name = build_id_cache__dirname_from_path(name, is_kallsyms,
+						     is_vdso, sbuild_id);
 	if (!dir_name)
 		goto out_free;
 
 	if (mkdir_p(dir_name, 0755))
 		goto out_free;
 
-	if (asprintf(&filename, "%s/%s", dir_name, sbuild_id) < 0) {
+	/* Save the allocated buildid dirname */
+	if (asprintf(&filename, "%s/%s", dir_name,
+		     build_id_cache__basename(is_kallsyms, is_vdso)) < 0) {
 		filename = NULL;
 		goto out_free;
 	}
@@ -437,7 +464,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
 			goto out_free;
 	}
 
-	if (!build_id__filename(sbuild_id, linkname, size))
+	if (!build_id_cache__linkname(sbuild_id, linkname, size))
 		goto out_free;
 	tmp = strrchr(linkname, '/');
 	*tmp = '\0';
@@ -446,10 +473,10 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
 		goto out_free;
 
 	*tmp = '/';
-	targetname = filename + strlen(buildid_dir) - 5;
-	memcpy(targetname, "../..", 5);
+	tmp = dir_name + strlen(buildid_dir) - 5;
+	memcpy(tmp, "../..", 5);
 
-	if (symlink(targetname, linkname) == 0)
+	if (symlink(tmp, linkname) == 0)
 		err = 0;
 out_free:
 	if (!is_kallsyms)
@@ -474,7 +501,7 @@ static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
 bool build_id_cache__cached(const char *sbuild_id)
 {
 	bool ret = false;
-	char *filename = build_id__filename(sbuild_id, NULL, 0);
+	char *filename = build_id_cache__linkname(sbuild_id, NULL, 0);
 
 	if (filename && !access(filename, F_OK))
 		ret = true;
@@ -493,7 +520,7 @@ int build_id_cache__remove_s(const char *sbuild_id)
 	if (filename == NULL || linkname == NULL)
 		goto out_free;
 
-	if (!build_id__filename(sbuild_id, linkname, size))
+	if (!build_id_cache__linkname(sbuild_id, linkname, size))
 		goto out_free;
 
 	if (access(linkname, F_OK))
@@ -511,7 +538,7 @@ int build_id_cache__remove_s(const char *sbuild_id)
 	tmp = strrchr(linkname, '/') + 1;
 	snprintf(tmp, size - (tmp - linkname), "%s", filename);
 
-	if (unlink(linkname))
+	if (rm_rf(linkname))
 		goto out_free;
 
 	err = 0;
@@ -523,7 +550,7 @@ out_free:
 
 static int dso__cache_build_id(struct dso *dso, struct machine *machine)
 {
-	bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
+	bool is_kallsyms = dso__is_kallsyms(dso);
 	bool is_vdso = dso__is_vdso(dso);
 	const char *name = dso->long_name;
 	char nm[PATH_MAX];
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 0953280..76d79d0 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -349,6 +349,11 @@ static inline bool dso__is_kcore(struct dso *dso)
 	       dso->binary_type == DSO_BINARY_TYPE__GUEST_KCORE;
 }
 
+static inline bool dso__is_kallsyms(struct dso *dso)
+{
+	return dso->kernel && dso->long_name[0] != '/';
+}
+
 void dso__free_a2l(struct dso *dso);
 
 enum dso_type dso__type(struct dso *dso, struct machine *machine);
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 415c4f6..c57cb47 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1685,7 +1685,7 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
 	if (!find_matching_kcore(map, path, sizeof(path)))
 		return strdup(path);
 
-	scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s",
+	scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s/kallsyms",
 		  buildid_dir, sbuild_id);
 
 	if (access(path, F_OK)) {

[toc] | [prev] | [next] | [standalone]


#1387485 — Re: [PATCH perf/core v4 02/19] perf-buildid-cache: Use path/to/bin/buildid/elf instead of path/to/bin/buildid

FromArnaldo Carvalho de Melo <acme@kernel.org>
Date2016-04-26 15:50 +0200
SubjectRe: [PATCH perf/core v4 02/19] perf-buildid-cache: Use path/to/bin/buildid/elf instead of path/to/bin/buildid
Message-ID<rsbxf-eJ-1@gated-at.bofh.it>
In reply to#1387265
Em Tue, Apr 26, 2016 at 06:02:22PM +0900, Masami Hiramatsu escreveu:
> From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
> 
> Use path/to/bin/buildid/elf instead of path/to/bin/buildid
> to store corresponding elf binary.
> This also stores vdso in buildid/vdso, kallsyms in buildid/kallsyms.
> Note that the build-id based symlink changes to point to the
> path/to/bin/buildid, not path/to/bin/buildid/elf.

Ok, but what happens to existing caches? Not a problem? I.e. the lookups
are made from ~/.debug/.build-id/, so it will just follow that symlink
and if the file was inserted in the cache before this change, it will
find it there, ok.

If inserted later, ditto.

Now what do you mean by "Note that the build-id based symlink changes to
point to the path/to/bin/buildid, not path/to/bin/buildid/elf."?

Probably the 'perf buildid-cache --purge" will just follow the symlink,
so it'll work.

- Arnaldo

 
> Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
> Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
> ---
>  tools/perf/util/build-id.c |   65 +++++++++++++++++++++++++++++++-------------
>  tools/perf/util/dso.h      |    5 +++
>  tools/perf/util/symbol.c   |    2 +
>  3 files changed, 52 insertions(+), 20 deletions(-)
> 
> diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
> index b6ecf87..46a8bcc 100644
> --- a/tools/perf/util/build-id.c
> +++ b/tools/perf/util/build-id.c
> @@ -144,7 +144,8 @@ static int asnprintf(char **strp, size_t size, const char *fmt, ...)
>  	return ret;
>  }
>  
> -static char *build_id__filename(const char *sbuild_id, char *bf, size_t size)
> +static char *build_id_cache__linkname(const char *sbuild_id, char *bf,
> +				      size_t size)
>  {
>  	char *tmp = bf;
>  	int ret = asnprintf(&bf, size, "%s/.build-id/%.2s/%s", buildid_dir,
> @@ -154,15 +155,35 @@ static char *build_id__filename(const char *sbuild_id, char *bf, size_t size)
>  	return bf;
>  }
>  
> +static const char *build_id_cache__basename(bool is_kallsyms, bool is_vdso)
> +{
> +	return is_kallsyms ? "kallsyms" : (is_vdso ? "vdso" : "elf");
> +}
> +
>  char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
>  {
> -	char build_id_hex[SBUILD_ID_SIZE];
> +	bool is_kallsyms = dso__is_kallsyms((struct dso *)dso);
> +	bool is_vdso = dso__is_vdso((struct dso *)dso);
> +	char sbuild_id[SBUILD_ID_SIZE];
> +	char *linkname;
> +	bool alloc = (bf == NULL);
> +	int ret;
>  
>  	if (!dso->has_build_id)
>  		return NULL;
>  
> -	build_id__sprintf(dso->build_id, sizeof(dso->build_id), build_id_hex);
> -	return build_id__filename(build_id_hex, bf, size);
> +	build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
> +	linkname = build_id_cache__linkname(sbuild_id, NULL, 0);
> +	if (!linkname)
> +		return NULL;
> +
> +	ret = asnprintf(&bf, size, "%s/%s", linkname,
> +			 build_id_cache__basename(is_kallsyms, is_vdso));
> +	if (ret < 0 || (!alloc && size < (unsigned int)ret))
> +		bf = NULL;
> +	free(linkname);
> +
> +	return bf;
>  }
>  
>  bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size)
> @@ -341,7 +362,8 @@ void disable_buildid_cache(void)
>  }
>  
>  static char *build_id_cache__dirname_from_path(const char *name,
> -					       bool is_kallsyms, bool is_vdso)
> +					       bool is_kallsyms, bool is_vdso,
> +					       const char *sbuild_id)
>  {
>  	char *realname = (char *)name, *filename;
>  	bool slash = is_kallsyms || is_vdso;
> @@ -352,8 +374,9 @@ static char *build_id_cache__dirname_from_path(const char *name,
>  			return NULL;
>  	}
>  
> -	if (asprintf(&filename, "%s%s%s", buildid_dir, slash ? "/" : "",
> -		     is_vdso ? DSO__NAME_VDSO : realname) < 0)
> +	if (asprintf(&filename, "%s%s%s%s%s", buildid_dir, slash ? "/" : "",
> +		     is_vdso ? DSO__NAME_VDSO : realname,
> +		     sbuild_id ? "/" : "", sbuild_id ?: "") < 0)
>  		filename = NULL;
>  
>  	if (!slash)
> @@ -372,7 +395,8 @@ int build_id_cache__list_build_ids(const char *pathname,
>  	int ret = 0;
>  
>  	list = strlist__new(NULL, NULL);
> -	dir_name = build_id_cache__dirname_from_path(pathname, false, false);
> +	dir_name = build_id_cache__dirname_from_path(pathname, false, false,
> +						     NULL);
>  	if (!list || !dir_name) {
>  		ret = -ENOMEM;
>  		goto out;
> @@ -407,7 +431,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
>  {
>  	const size_t size = PATH_MAX;
>  	char *realname = NULL, *filename = NULL, *dir_name = NULL,
> -	     *linkname = zalloc(size), *targetname, *tmp;
> +	     *linkname = zalloc(size), *tmp;
>  	int err = -1;
>  
>  	if (!is_kallsyms) {
> @@ -416,14 +440,17 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
>  			goto out_free;
>  	}
>  
> -	dir_name = build_id_cache__dirname_from_path(name, is_kallsyms, is_vdso);
> +	dir_name = build_id_cache__dirname_from_path(name, is_kallsyms,
> +						     is_vdso, sbuild_id);
>  	if (!dir_name)
>  		goto out_free;
>  
>  	if (mkdir_p(dir_name, 0755))
>  		goto out_free;
>  
> -	if (asprintf(&filename, "%s/%s", dir_name, sbuild_id) < 0) {
> +	/* Save the allocated buildid dirname */
> +	if (asprintf(&filename, "%s/%s", dir_name,
> +		     build_id_cache__basename(is_kallsyms, is_vdso)) < 0) {
>  		filename = NULL;
>  		goto out_free;
>  	}
> @@ -437,7 +464,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
>  			goto out_free;
>  	}
>  
> -	if (!build_id__filename(sbuild_id, linkname, size))
> +	if (!build_id_cache__linkname(sbuild_id, linkname, size))
>  		goto out_free;
>  	tmp = strrchr(linkname, '/');
>  	*tmp = '\0';
> @@ -446,10 +473,10 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
>  		goto out_free;
>  
>  	*tmp = '/';
> -	targetname = filename + strlen(buildid_dir) - 5;
> -	memcpy(targetname, "../..", 5);
> +	tmp = dir_name + strlen(buildid_dir) - 5;
> +	memcpy(tmp, "../..", 5);
>  
> -	if (symlink(targetname, linkname) == 0)
> +	if (symlink(tmp, linkname) == 0)
>  		err = 0;
>  out_free:
>  	if (!is_kallsyms)
> @@ -474,7 +501,7 @@ static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
>  bool build_id_cache__cached(const char *sbuild_id)
>  {
>  	bool ret = false;
> -	char *filename = build_id__filename(sbuild_id, NULL, 0);
> +	char *filename = build_id_cache__linkname(sbuild_id, NULL, 0);
>  
>  	if (filename && !access(filename, F_OK))
>  		ret = true;
> @@ -493,7 +520,7 @@ int build_id_cache__remove_s(const char *sbuild_id)
>  	if (filename == NULL || linkname == NULL)
>  		goto out_free;
>  
> -	if (!build_id__filename(sbuild_id, linkname, size))
> +	if (!build_id_cache__linkname(sbuild_id, linkname, size))
>  		goto out_free;
>  
>  	if (access(linkname, F_OK))
> @@ -511,7 +538,7 @@ int build_id_cache__remove_s(const char *sbuild_id)
>  	tmp = strrchr(linkname, '/') + 1;
>  	snprintf(tmp, size - (tmp - linkname), "%s", filename);
>  
> -	if (unlink(linkname))
> +	if (rm_rf(linkname))
>  		goto out_free;
>  
>  	err = 0;
> @@ -523,7 +550,7 @@ out_free:
>  
>  static int dso__cache_build_id(struct dso *dso, struct machine *machine)
>  {
> -	bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
> +	bool is_kallsyms = dso__is_kallsyms(dso);
>  	bool is_vdso = dso__is_vdso(dso);
>  	const char *name = dso->long_name;
>  	char nm[PATH_MAX];
> diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
> index 0953280..76d79d0 100644
> --- a/tools/perf/util/dso.h
> +++ b/tools/perf/util/dso.h
> @@ -349,6 +349,11 @@ static inline bool dso__is_kcore(struct dso *dso)
>  	       dso->binary_type == DSO_BINARY_TYPE__GUEST_KCORE;
>  }
>  
> +static inline bool dso__is_kallsyms(struct dso *dso)
> +{
> +	return dso->kernel && dso->long_name[0] != '/';
> +}
> +
>  void dso__free_a2l(struct dso *dso);
>  
>  enum dso_type dso__type(struct dso *dso, struct machine *machine);
> diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
> index 415c4f6..c57cb47 100644
> --- a/tools/perf/util/symbol.c
> +++ b/tools/perf/util/symbol.c
> @@ -1685,7 +1685,7 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
>  	if (!find_matching_kcore(map, path, sizeof(path)))
>  		return strdup(path);
>  
> -	scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s",
> +	scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s/kallsyms",
>  		  buildid_dir, sbuild_id);
>  
>  	if (access(path, F_OK)) {

[toc] | [prev] | [next] | [standalone]


#1387567 — Re: [PATCH perf/core v4 02/19] perf-buildid-cache: Use path/to/bin/buildid/elf instead of path/to/bin/buildid

FromMasami Hiramatsu <mhiramat@kernel.org>
Date2016-04-26 16:50 +0200
SubjectRe: [PATCH perf/core v4 02/19] perf-buildid-cache: Use path/to/bin/buildid/elf instead of path/to/bin/buildid
Message-ID<rsctl-Xx-39@gated-at.bofh.it>
In reply to#1387485
On Tue, 26 Apr 2016 10:45:38 -0300
Arnaldo Carvalho de Melo <acme@kernel.org> wrote:

> Em Tue, Apr 26, 2016 at 06:02:22PM +0900, Masami Hiramatsu escreveu:
> > From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
> > 
> > Use path/to/bin/buildid/elf instead of path/to/bin/buildid
> > to store corresponding elf binary.
> > This also stores vdso in buildid/vdso, kallsyms in buildid/kallsyms.
> > Note that the build-id based symlink changes to point to the
> > path/to/bin/buildid, not path/to/bin/buildid/elf.
> 
> Ok, but what happens to existing caches? Not a problem? I.e. the lookups
> are made from ~/.debug/.build-id/, so it will just follow that symlink
> and if the file was inserted in the cache before this change, it will
> find it there, ok.

Right, that the next patch does. And I agree with you that it should be
merged to this patch.

> 
> If inserted later, ditto.
> 
> Now what do you mean by "Note that the build-id based symlink changes to
> point to the path/to/bin/buildid, not path/to/bin/buildid/elf."?

Ah, this is just a note that someone directly accessing the cache.
But anyway, it is just a design note.

Thank you,

> 
> Probably the 'perf buildid-cache --purge" will just follow the symlink,
> so it'll work.
> 
> - Arnaldo
> 
>  
> > Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
> > Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
> > ---
> >  tools/perf/util/build-id.c |   65 +++++++++++++++++++++++++++++++-------------
> >  tools/perf/util/dso.h      |    5 +++
> >  tools/perf/util/symbol.c   |    2 +
> >  3 files changed, 52 insertions(+), 20 deletions(-)
> > 
> > diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
> > index b6ecf87..46a8bcc 100644
> > --- a/tools/perf/util/build-id.c
> > +++ b/tools/perf/util/build-id.c
> > @@ -144,7 +144,8 @@ static int asnprintf(char **strp, size_t size, const char *fmt, ...)
> >  	return ret;
> >  }
> >  
> > -static char *build_id__filename(const char *sbuild_id, char *bf, size_t size)
> > +static char *build_id_cache__linkname(const char *sbuild_id, char *bf,
> > +				      size_t size)
> >  {
> >  	char *tmp = bf;
> >  	int ret = asnprintf(&bf, size, "%s/.build-id/%.2s/%s", buildid_dir,
> > @@ -154,15 +155,35 @@ static char *build_id__filename(const char *sbuild_id, char *bf, size_t size)
> >  	return bf;
> >  }
> >  
> > +static const char *build_id_cache__basename(bool is_kallsyms, bool is_vdso)
> > +{
> > +	return is_kallsyms ? "kallsyms" : (is_vdso ? "vdso" : "elf");
> > +}
> > +
> >  char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
> >  {
> > -	char build_id_hex[SBUILD_ID_SIZE];
> > +	bool is_kallsyms = dso__is_kallsyms((struct dso *)dso);
> > +	bool is_vdso = dso__is_vdso((struct dso *)dso);
> > +	char sbuild_id[SBUILD_ID_SIZE];
> > +	char *linkname;
> > +	bool alloc = (bf == NULL);
> > +	int ret;
> >  
> >  	if (!dso->has_build_id)
> >  		return NULL;
> >  
> > -	build_id__sprintf(dso->build_id, sizeof(dso->build_id), build_id_hex);
> > -	return build_id__filename(build_id_hex, bf, size);
> > +	build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
> > +	linkname = build_id_cache__linkname(sbuild_id, NULL, 0);
> > +	if (!linkname)
> > +		return NULL;
> > +
> > +	ret = asnprintf(&bf, size, "%s/%s", linkname,
> > +			 build_id_cache__basename(is_kallsyms, is_vdso));
> > +	if (ret < 0 || (!alloc && size < (unsigned int)ret))
> > +		bf = NULL;
> > +	free(linkname);
> > +
> > +	return bf;
> >  }
> >  
> >  bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size)
> > @@ -341,7 +362,8 @@ void disable_buildid_cache(void)
> >  }
> >  
> >  static char *build_id_cache__dirname_from_path(const char *name,
> > -					       bool is_kallsyms, bool is_vdso)
> > +					       bool is_kallsyms, bool is_vdso,
> > +					       const char *sbuild_id)
> >  {
> >  	char *realname = (char *)name, *filename;
> >  	bool slash = is_kallsyms || is_vdso;
> > @@ -352,8 +374,9 @@ static char *build_id_cache__dirname_from_path(const char *name,
> >  			return NULL;
> >  	}
> >  
> > -	if (asprintf(&filename, "%s%s%s", buildid_dir, slash ? "/" : "",
> > -		     is_vdso ? DSO__NAME_VDSO : realname) < 0)
> > +	if (asprintf(&filename, "%s%s%s%s%s", buildid_dir, slash ? "/" : "",
> > +		     is_vdso ? DSO__NAME_VDSO : realname,
> > +		     sbuild_id ? "/" : "", sbuild_id ?: "") < 0)
> >  		filename = NULL;
> >  
> >  	if (!slash)
> > @@ -372,7 +395,8 @@ int build_id_cache__list_build_ids(const char *pathname,
> >  	int ret = 0;
> >  
> >  	list = strlist__new(NULL, NULL);
> > -	dir_name = build_id_cache__dirname_from_path(pathname, false, false);
> > +	dir_name = build_id_cache__dirname_from_path(pathname, false, false,
> > +						     NULL);
> >  	if (!list || !dir_name) {
> >  		ret = -ENOMEM;
> >  		goto out;
> > @@ -407,7 +431,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
> >  {
> >  	const size_t size = PATH_MAX;
> >  	char *realname = NULL, *filename = NULL, *dir_name = NULL,
> > -	     *linkname = zalloc(size), *targetname, *tmp;
> > +	     *linkname = zalloc(size), *tmp;
> >  	int err = -1;
> >  
> >  	if (!is_kallsyms) {
> > @@ -416,14 +440,17 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
> >  			goto out_free;
> >  	}
> >  
> > -	dir_name = build_id_cache__dirname_from_path(name, is_kallsyms, is_vdso);
> > +	dir_name = build_id_cache__dirname_from_path(name, is_kallsyms,
> > +						     is_vdso, sbuild_id);
> >  	if (!dir_name)
> >  		goto out_free;
> >  
> >  	if (mkdir_p(dir_name, 0755))
> >  		goto out_free;
> >  
> > -	if (asprintf(&filename, "%s/%s", dir_name, sbuild_id) < 0) {
> > +	/* Save the allocated buildid dirname */
> > +	if (asprintf(&filename, "%s/%s", dir_name,
> > +		     build_id_cache__basename(is_kallsyms, is_vdso)) < 0) {
> >  		filename = NULL;
> >  		goto out_free;
> >  	}
> > @@ -437,7 +464,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
> >  			goto out_free;
> >  	}
> >  
> > -	if (!build_id__filename(sbuild_id, linkname, size))
> > +	if (!build_id_cache__linkname(sbuild_id, linkname, size))
> >  		goto out_free;
> >  	tmp = strrchr(linkname, '/');
> >  	*tmp = '\0';
> > @@ -446,10 +473,10 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
> >  		goto out_free;
> >  
> >  	*tmp = '/';
> > -	targetname = filename + strlen(buildid_dir) - 5;
> > -	memcpy(targetname, "../..", 5);
> > +	tmp = dir_name + strlen(buildid_dir) - 5;
> > +	memcpy(tmp, "../..", 5);
> >  
> > -	if (symlink(targetname, linkname) == 0)
> > +	if (symlink(tmp, linkname) == 0)
> >  		err = 0;
> >  out_free:
> >  	if (!is_kallsyms)
> > @@ -474,7 +501,7 @@ static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
> >  bool build_id_cache__cached(const char *sbuild_id)
> >  {
> >  	bool ret = false;
> > -	char *filename = build_id__filename(sbuild_id, NULL, 0);
> > +	char *filename = build_id_cache__linkname(sbuild_id, NULL, 0);
> >  
> >  	if (filename && !access(filename, F_OK))
> >  		ret = true;
> > @@ -493,7 +520,7 @@ int build_id_cache__remove_s(const char *sbuild_id)
> >  	if (filename == NULL || linkname == NULL)
> >  		goto out_free;
> >  
> > -	if (!build_id__filename(sbuild_id, linkname, size))
> > +	if (!build_id_cache__linkname(sbuild_id, linkname, size))
> >  		goto out_free;
> >  
> >  	if (access(linkname, F_OK))
> > @@ -511,7 +538,7 @@ int build_id_cache__remove_s(const char *sbuild_id)
> >  	tmp = strrchr(linkname, '/') + 1;
> >  	snprintf(tmp, size - (tmp - linkname), "%s", filename);
> >  
> > -	if (unlink(linkname))
> > +	if (rm_rf(linkname))
> >  		goto out_free;
> >  
> >  	err = 0;
> > @@ -523,7 +550,7 @@ out_free:
> >  
> >  static int dso__cache_build_id(struct dso *dso, struct machine *machine)
> >  {
> > -	bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
> > +	bool is_kallsyms = dso__is_kallsyms(dso);
> >  	bool is_vdso = dso__is_vdso(dso);
> >  	const char *name = dso->long_name;
> >  	char nm[PATH_MAX];
> > diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
> > index 0953280..76d79d0 100644
> > --- a/tools/perf/util/dso.h
> > +++ b/tools/perf/util/dso.h
> > @@ -349,6 +349,11 @@ static inline bool dso__is_kcore(struct dso *dso)
> >  	       dso->binary_type == DSO_BINARY_TYPE__GUEST_KCORE;
> >  }
> >  
> > +static inline bool dso__is_kallsyms(struct dso *dso)
> > +{
> > +	return dso->kernel && dso->long_name[0] != '/';
> > +}
> > +
> >  void dso__free_a2l(struct dso *dso);
> >  
> >  enum dso_type dso__type(struct dso *dso, struct machine *machine);
> > diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
> > index 415c4f6..c57cb47 100644
> > --- a/tools/perf/util/symbol.c
> > +++ b/tools/perf/util/symbol.c
> > @@ -1685,7 +1685,7 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
> >  	if (!find_matching_kcore(map, path, sizeof(path)))
> >  		return strdup(path);
> >  
> > -	scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s",
> > +	scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s/kallsyms",
> >  		  buildid_dir, sbuild_id);
> >  
> >  	if (access(path, F_OK)) {


-- 
Masami Hiramatsu <mhiramat@kernel.org>

[toc] | [prev] | [next] | [standalone]


#1387267 — [PATCH perf/core v4 06/19] perf-probe: Let probe_file__add_event return 0 if succeeded

FromMasami Hiramatsu <mhiramat@kernel.org>
Date2016-04-26 11:10 +0200
Subject[PATCH perf/core v4 06/19] perf-probe: Let probe_file__add_event return 0 if succeeded
Message-ID<rs7ak-4SP-53@gated-at.bofh.it>
In reply to#1387248
Since other methods return 0 if succeeded (or filedesc),
let probe_file__add_event() return 0 instead of the length
of written bytes.

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 tools/perf/util/probe-file.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index e3b3b92..3fe6214 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -220,8 +220,7 @@ int probe_file__add_event(int fd, struct probe_trace_event *tev)
 
 	pr_debug("Writing event: %s\n", buf);
 	if (!probe_event_dry_run) {
-		ret = write(fd, buf, strlen(buf));
-		if (ret <= 0) {
+		if (write(fd, buf, strlen(buf)) < (int)strlen(buf)) {
 			ret = -errno;
 			pr_warning("Failed to write event: %s\n",
 				   strerror_r(errno, sbuf, sizeof(sbuf)));

[toc] | [prev] | [next] | [standalone]


#1387486 — Re: [PATCH perf/core v4 06/19] perf-probe: Let probe_file__add_event return 0 if succeeded

FromArnaldo Carvalho de Melo <acme@kernel.org>
Date2016-04-26 15:50 +0200
SubjectRe: [PATCH perf/core v4 06/19] perf-probe: Let probe_file__add_event return 0 if succeeded
Message-ID<rsbxg-eJ-5@gated-at.bofh.it>
In reply to#1387267
Em Tue, Apr 26, 2016 at 06:03:04PM +0900, Masami Hiramatsu escreveu:
> Since other methods return 0 if succeeded (or filedesc),
> let probe_file__add_event() return 0 instead of the length
> of written bytes.

Thanks, applied.

- Arnaldo
 
> Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
> ---
>  tools/perf/util/probe-file.c |    3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
> index e3b3b92..3fe6214 100644
> --- a/tools/perf/util/probe-file.c
> +++ b/tools/perf/util/probe-file.c
> @@ -220,8 +220,7 @@ int probe_file__add_event(int fd, struct probe_trace_event *tev)
>  
>  	pr_debug("Writing event: %s\n", buf);
>  	if (!probe_event_dry_run) {
> -		ret = write(fd, buf, strlen(buf));
> -		if (ret <= 0) {
> +		if (write(fd, buf, strlen(buf)) < (int)strlen(buf)) {
>  			ret = -errno;
>  			pr_warning("Failed to write event: %s\n",
>  				   strerror_r(errno, sbuf, sizeof(sbuf)));

[toc] | [prev] | [next] | [standalone]


#1389257 — [tip:perf/core] perf probe: Let probe_file__add_event return 0 if succeeded

Fromtip-bot for Masami Hiramatsu <tipbot@zytor.com>
Date2016-04-27 17:40 +0200
Subject[tip:perf/core] perf probe: Let probe_file__add_event return 0 if succeeded
Message-ID<rszJi-3tA-69@gated-at.bofh.it>
In reply to#1387267
Commit-ID:  6ed0720a74d90eea51284c07592369d45d56f1f7
Gitweb:     http://git.kernel.org/tip/6ed0720a74d90eea51284c07592369d45d56f1f7
Author:     Masami Hiramatsu <mhiramat@kernel.org>
AuthorDate: Tue, 26 Apr 2016 18:03:04 +0900
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Tue, 26 Apr 2016 13:14:58 -0300

perf probe: Let probe_file__add_event return 0 if succeeded

Since other methods return 0 if succeeded (or filedesc), let
probe_file__add_event() return 0 instead of the length of written bytes.

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Ananth N Mavinakayanahalli <ananth@linux.vnet.ibm.com>
Cc: Hemant Kumar <hemant@linux.vnet.ibm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20160426090303.11891.18232.stgit@devbox
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/probe-file.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index e3b3b92..3fe6214 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -220,8 +220,7 @@ int probe_file__add_event(int fd, struct probe_trace_event *tev)
 
 	pr_debug("Writing event: %s\n", buf);
 	if (!probe_event_dry_run) {
-		ret = write(fd, buf, strlen(buf));
-		if (ret <= 0) {
+		if (write(fd, buf, strlen(buf)) < (int)strlen(buf)) {
 			ret = -errno;
 			pr_warning("Failed to write event: %s\n",
 				   strerror_r(errno, sbuf, sizeof(sbuf)));

[toc] | [prev] | [next] | [standalone]


#1387273 — [PATCH perf/core v4 09/19] perf probe: Show all cached probes

FromMasami Hiramatsu <mhiramat@kernel.org>
Date2016-04-26 11:20 +0200
Subject[PATCH perf/core v4 09/19] perf probe: Show all cached probes
Message-ID<rs7jY-4Yn-9@gated-at.bofh.it>
In reply to#1387248
From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>

perf probe --list shows all cached probes when --cache
is given. Each caches are shown with on which binary that
probed. e.g.
  -----
  # perf probe --cache vfs_read \$params
  # perf probe --cache -x /lib64/libc-2.17.so getaddrinfo \$params
  # perf probe --cache --list
  /[kernel.kallsyms] (1466a0a250b5d0070c6d0f03c5fed30b237970a1):
  vfs_read $params
  /usr/lib64/libc-2.17.so (c31ffe7942bfd77b2fca8f9bd5709d387a86d3bc):
  getaddrinfo $params
  -----
Note that $params requires debuginfo.

Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 tools/perf/Documentation/perf-probe.txt |    8 ++-
 tools/perf/builtin-probe.c              |    2 -
 tools/perf/util/build-id.c              |   79 ++++++++++++++++++++++++++++++-
 tools/perf/util/build-id.h              |    3 +
 tools/perf/util/probe-event.c           |    3 +
 tools/perf/util/probe-file.c            |   67 ++++++++++++++++++++++++++
 tools/perf/util/probe-file.h            |    1 
 7 files changed, 156 insertions(+), 7 deletions(-)

diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 947db6f..5a70d45 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -67,7 +67,10 @@ OPTIONS
 
 -l::
 --list[=[GROUP:]EVENT]::
-	List up current probe events. This can also accept filtering patterns of event names.
+	List up current probe events. This can also accept filtering patterns of
+	event names.
+	When this is used with --cache, perf shows all cached probes instead of
+	the live probes.
 
 -L::
 --line=::
@@ -110,8 +113,9 @@ OPTIONS
 	adding and removal operations.
 
 --cache::
-	Cache the probes (with --add option). Any events which successfully added
+	(With --add) Cache the probes. Any events which successfully added
 	are also stored in the cache file.
+	(With --list) Show cached probes.
 
 --max-probes=NUM::
 	Set the maximum number of probe points for an event. Default is 128.
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 6d7ab431..53e380c0e 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -44,7 +44,7 @@
 
 #define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*"
 #define DEFAULT_FUNC_FILTER "!_*"
-#define DEFAULT_LIST_FILTER "*:*"
+#define DEFAULT_LIST_FILTER "*"
 
 /* Session management structure */
 static struct {
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 588ff01..a7da315 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -144,8 +144,7 @@ static int asnprintf(char **strp, size_t size, const char *fmt, ...)
 	return ret;
 }
 
-static char *build_id_cache__linkname(const char *sbuild_id, char *bf,
-				      size_t size)
+char *build_id_cache__linkname(const char *sbuild_id, char *bf, size_t size)
 {
 	char *tmp = bf;
 	int ret = asnprintf(&bf, size, "%s/.build-id/%.2s/%s", buildid_dir,
@@ -161,6 +160,29 @@ static bool __is_regular_file(const char *pathname)
 	return stat(pathname, &sb) == 0 && S_ISREG(sb.st_mode);
 }
 
+char *build_id_cache__origname(const char *sbuild_id)
+{
+	char *linkname;
+	char buf[PATH_MAX];
+	char *ret = NULL, *p;
+
+	linkname = build_id_cache__linkname(sbuild_id, NULL, 0);
+	if (!linkname)
+		return NULL;
+
+	if (readlink(linkname, buf, PATH_MAX) < 0)
+		goto out;
+	/* The link should be "../..<origpath>/<sbuild_id>" */
+	p = strrchr(buf, '/');	/* Cut off the "/<sbuild_id>" */
+	if (p) {
+		*p = '\0';
+		ret = strdup(buf + 5);	/* Skip "../.." */
+	}
+out:
+	free(linkname);
+	return ret;
+}
+
 static const char *build_id_cache__basename(bool is_kallsyms, bool is_vdso)
 {
 	return is_kallsyms ? "kallsyms" : (is_vdso ? "vdso" : "elf");
@@ -371,6 +393,59 @@ void disable_buildid_cache(void)
 	no_buildid_cache = true;
 }
 
+int build_id_cache__list_all(struct strlist **result)
+{
+	struct strlist *toplist, *list, *bidlist;
+	struct str_node *nd, *nd2;
+	char *topdir, *linkdir;
+	char sbuild_id[SBUILD_ID_SIZE];
+	int ret = 0;
+
+	/* Open the top-level directory */
+	if (asprintf(&topdir, "%s/.build-id/", buildid_dir) < 0)
+		return -errno;
+	toplist = lsdir(topdir, lsdir_no_dot_filter);
+	if (!toplist) {
+		pr_debug("Failed to opendir %s\n", topdir);
+		ret = -errno;
+		goto out;
+	}
+	bidlist = strlist__new(NULL, NULL);
+	strlist__for_each(nd, toplist) {
+		if (asprintf(&linkdir, "%s/%s", topdir, nd->s) < 0) {
+			ret = -errno;
+			goto out;
+		}
+		/* Open the lower-level directory */
+		list = lsdir(linkdir, lsdir_no_dot_filter);
+		if (!list) {
+			pr_debug("Failed to open %s: %d\n", linkdir, -errno);
+			goto next;
+		}
+		strlist__for_each(nd2, list) {
+			ret = snprintf(sbuild_id, SBUILD_ID_SIZE, "%s%s",
+					nd->s, nd2->s);
+			if (ret != SBUILD_ID_SIZE - 1) {
+				pr_debug("%s/%s is not buildid cache\n",
+					nd->s, nd2->s);
+				continue;
+			}
+			strlist__add(bidlist, sbuild_id);
+		}
+		strlist__delete(list);
+next:
+		free(linkdir);
+	}
+
+	*result = bidlist;
+out:
+	if (toplist)
+		strlist__delete(toplist);
+	free(topdir);
+
+	return ret;
+}
+
 char *build_id_cache__dirname_from_path(const char *sbuild_id, const char *name,
 					bool is_kallsyms, bool is_vdso)
 {
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index 1841524..2c98a39 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -28,8 +28,11 @@ bool perf_session__read_build_ids(struct perf_session *session, bool with_hits);
 int perf_session__write_buildid_table(struct perf_session *session, int fd);
 int perf_session__cache_build_ids(struct perf_session *session);
 
+char *build_id_cache__origname(const char *sbuild_id);
+char *build_id_cache__linkname(const char *sbuild_id, char *bf, size_t size);
 char *build_id_cache__dirname_from_path(const char *sbuild_id, const char *name,
 					bool is_kallsyms, bool is_vdso);
+int build_id_cache__list_all(struct strlist **result);
 int build_id_cache__list_build_ids(const char *pathname,
 				   struct strlist **result);
 bool build_id_cache__cached(const char *sbuild_id);
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 2ec0206..de5460d 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -2280,6 +2280,9 @@ int show_perf_probe_events(struct strfilter *filter)
 
 	setup_pager();
 
+	if (probe_conf.cache)
+		return probe_cache__show_all_caches(filter);
+
 	ret = init_probe_symbol_maps(false);
 	if (ret < 0)
 		return ret;
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index 0d1298f..72d58e7 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -365,10 +365,17 @@ static int probe_cache__open(struct probe_cache *pcache, const char *target)
 {
 	char cpath[PATH_MAX];
 	char sbuildid[SBUILD_ID_SIZE];
-	char *dir_name;
+	char *dir_name = NULL;
 	bool is_kallsyms = !target;
 	int ret, fd;
 
+	if (target && build_id_cache__cached(target)) {
+		/* This is a cached buildid */
+		strncpy(sbuildid, target, SBUILD_ID_SIZE);
+		dir_name = build_id_cache__linkname(sbuildid, NULL, 0);
+		goto found;
+	}
+
 	if (target)
 		ret = filename__sprintf_build_id(target, sbuildid);
 	else {
@@ -392,8 +399,11 @@ static int probe_cache__open(struct probe_cache *pcache, const char *target)
 
 	dir_name = build_id_cache__dirname_from_path(sbuildid, target,
 						     is_kallsyms, false);
-	if (!dir_name)
+found:
+	if (!dir_name) {
+		pr_debug("Failed to get cache from %s\n", target);
 		return -ENOMEM;
+	}
 
 	snprintf(cpath, PATH_MAX, "%s/probes", dir_name);
 	fd = open(cpath, O_CREAT | O_RDWR | O_APPEND, 0644);
@@ -641,3 +651,56 @@ int probe_cache__commit(struct probe_cache *pcache)
 out:
 	return ret;
 }
+
+static int probe_cache__show_entries(struct probe_cache *pcache,
+				     struct strfilter *filter)
+{
+	struct probe_cache_entry *entry;
+	char buf[128], *ptr;
+
+	list_for_each_entry(entry, &pcache->list, list) {
+		if (entry->pev.event) {
+			ptr = buf;
+			snprintf(buf, 128, "%s:%s", entry->pev.group, entry->pev.event);
+		} else
+			ptr = entry->spev;
+		if (strfilter__compare(filter, ptr))
+			printf("%s\n", entry->spev);
+	}
+	return 0;
+}
+
+/* Show all cached probes */
+int probe_cache__show_all_caches(struct strfilter *filter)
+{
+	struct probe_cache *pcache;
+	struct strlist *bidlist;
+	struct str_node *nd;
+	char *buf;
+	int ret;
+
+	buf = strfilter__string(filter);
+	pr_debug("list cache with filter: %s\n", buf);
+	free(buf);
+
+	ret = build_id_cache__list_all(&bidlist);
+	if (ret < 0) {
+		pr_debug("Failed to get buildids: %d\n", ret);
+		return ret == -ENOENT ? 0 : ret;
+	}
+	strlist__for_each(nd, bidlist) {
+		pcache = probe_cache__new(nd->s);
+		if (!pcache)
+			continue;
+		if (!list_empty(&pcache->list)) {
+			buf = build_id_cache__origname(nd->s);
+			printf("%s (%s):\n", buf, nd->s);
+			free(buf);
+			probe_cache__show_entries(pcache, filter);
+		}
+		probe_cache__delete(pcache);
+	}
+	strlist__delete(bidlist);
+
+	return 0;
+}
diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
index a094824..ab6911d 100644
--- a/tools/perf/util/probe-file.h
+++ b/tools/perf/util/probe-file.h
@@ -41,4 +41,5 @@ struct probe_cache_entry *probe_cache__find(struct probe_cache *pcache,
 					    struct perf_probe_event *pev);
 struct probe_cache_entry *probe_cache__find_by_name(struct probe_cache *pcache,
 					const char *group, const char *event);
+int probe_cache__show_all_caches(struct strfilter *filter);
 #endif

[toc] | [prev] | [next] | [standalone]


#1387301 — [PATCH perf/core v4 08/19] perf probe: Use cache entry if possible

FromMasami Hiramatsu <mhiramat@kernel.org>
Date2016-04-26 11:30 +0200
Subject[PATCH perf/core v4 08/19] perf probe: Use cache entry if possible
Message-ID<rs7tF-57R-11@gated-at.bofh.it>
In reply to#1387248
From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>

Before analyzing debuginfo, try to find a corresponding entry
from probe cache always. This does not depend on --cache,
the --cache enables to store/update cache, but looking up
the cache is always enabled.

Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 tools/perf/util/probe-event.c |   72 ++++++++++++++++++++++++++++++++++++++++-
 tools/perf/util/probe-file.c  |   20 +++++++++++
 tools/perf/util/probe-file.h  |    5 ++-
 3 files changed, 93 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index f6d194c..2ec0206 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -2388,17 +2388,24 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev,
 	char buf[64];
 	int ret;
 
+	/* If probe_event or trace_event already have the name, reuse it */
 	if (pev->event)
 		event = pev->event;
-	else
+	else if (tev->event)
+		event = tev->event;
+	else {
+		/* Or generate new one from probe point */
 		if (pev->point.function &&
 			(strncmp(pev->point.function, "0x", 2) != 0) &&
 			!strisglob(pev->point.function))
 			event = pev->point.function;
 		else
 			event = tev->point.realname;
+	}
 	if (pev->group)
 		group = pev->group;
+	else if (tev->group)
+		group = tev->group;
 	else
 		group = PERFPROBE_GROUP;
 
@@ -2445,7 +2452,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
 	for (i = 0; i < ntevs; i++) {
 		tev = &tevs[i];
 		/* Skip if the symbol is out of .text or blacklisted */
-		if (!tev->point.symbol)
+		if (!tev->point.symbol && !pev->uprobes)
 			continue;
 
 		/* Set new name for tev (and update namelist) */
@@ -2746,6 +2753,62 @@ errout:
 
 bool __weak arch__prefers_symtab(void) { return false; }
 
+static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,
+					      struct probe_trace_event **tevs)
+{
+	struct probe_cache *cache;
+	struct probe_cache_entry *entry;
+	struct probe_trace_event *tev;
+	struct str_node *node;
+	int ret, i;
+
+	cache = probe_cache__new(pev->target);
+	if (!cache)
+		return 0;
+
+	entry = probe_cache__find(cache, pev);
+
+	if (!entry && !pev->event &&
+	    (!pev->point.file && pev->point.function && !pev->point.retprobe &&
+	     !pev->point.line && !pev->point.offset && !pev->point.lazy_line)) {
+		entry = probe_cache__find_by_name(cache, pev->group,
+						  pev->point.function);
+	}
+	if (!entry) {
+		ret = 0;
+		goto out;
+	}
+
+	ret = strlist__nr_entries(entry->tevlist);
+	if (ret > probe_conf.max_probes) {
+		pr_debug("Too many entries matched in the cache of %s\n",
+			 pev->target ? : "kernel");
+		ret = -E2BIG;
+		goto out;
+	}
+
+	*tevs = zalloc(ret * sizeof(*tev));
+	if (!*tevs) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	i = 0;
+	strlist__for_each(node, entry->tevlist) {
+		tev = &(*tevs)[i++];
+		ret = parse_probe_trace_command(node->s, tev);
+		if (ret < 0)
+			goto out;
+		/* Set the uprobes attribute as same as original */
+		tev->uprobes = pev->uprobes;
+	}
+	ret = i;
+
+out:
+	probe_cache__delete(cache);
+	return ret;
+}
+
 static int convert_to_probe_trace_events(struct perf_probe_event *pev,
 					 struct probe_trace_event **tevs)
 {
@@ -2764,6 +2827,11 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
 	if (ret > 0)
 		return ret;
 
+	/* At first, we need to lookup cache entry */
+	ret = find_probe_trace_events_from_cache(pev, tevs);
+	if (ret > 0)
+		return ret;	/* Found in probe cache */
+
 	if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) {
 		ret = find_probe_trace_events_from_map(pev, tevs);
 		if (ret > 0)
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index bb849c9..0d1298f 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -506,7 +506,7 @@ static bool streql(const char *a, const char *b)
 	return !strcmp(a, b);
 }
 
-static struct probe_cache_entry *
+struct probe_cache_entry *
 probe_cache__find(struct probe_cache *pcache, struct perf_probe_event *pev)
 {
 	struct probe_cache_entry *entry = NULL;
@@ -531,6 +531,24 @@ found:
 	return entry;
 }
 
+struct probe_cache_entry *
+probe_cache__find_by_name(struct probe_cache *pcache,
+			  const char *group, const char *event)
+{
+	struct probe_cache_entry *entry = NULL;
+
+	list_for_each_entry(entry, &pcache->list, list) {
+		/* Hit if same event name or same command-string */
+		if (streql(entry->pev.group, group) &&
+		    streql(entry->pev.event, event))
+			goto found;
+	}
+	entry = NULL;
+
+found:
+	return entry;
+}
+
 int probe_cache__add_entry(struct probe_cache *pcache,
 			   struct perf_probe_event *pev,
 			   struct probe_trace_event *tevs, int ntevs)
diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
index ded9e0a..a094824 100644
--- a/tools/perf/util/probe-file.h
+++ b/tools/perf/util/probe-file.h
@@ -37,5 +37,8 @@ int probe_cache__add_entry(struct probe_cache *pcache,
 			   struct probe_trace_event *tevs, int ntevs);
 int probe_cache__commit(struct probe_cache *pcache);
 void probe_cache__delete(struct probe_cache *pcache);
-
+struct probe_cache_entry *probe_cache__find(struct probe_cache *pcache,
+					    struct perf_probe_event *pev);
+struct probe_cache_entry *probe_cache__find_by_name(struct probe_cache *pcache,
+					const char *group, const char *event);
 #endif

[toc] | [prev] | [next] | [standalone]


#1389251

FromHemant Kumar <hemant@linux.vnet.ibm.com>
Date2016-04-27 17:40 +0200
Message-ID<rszJh-3tA-51@gated-at.bofh.it>
In reply to#1387248
Hi Masami,

On 04/26/2016 02:32 PM, Masami Hiramatsu wrote:
> Hi,
>
> Here is the 4th version of the patchset for probe-cache and
> initial SDT support which are going to be perf-cache finally.

Applied your patches and tested them. I have a few questions/
suggestions on some of the patches.

> The previous version is here; https://lkml.org/lkml/2015/8/15/52
>
> This version fixes some bugs and improve wildcard support (
> including automatic target binary selection, we don't need
> -x option for SDT/pre-cached events any more :) ),
> and drops perf-record support currently because it seems more
> work on cleanup side.
>
> BTW, since I couldn't find list_dir function in Arnaldo's mail,
> so this series still have a patch to add lsdir().
>
> Note that all SDT events have "sdt_" prefix on the provider name,
> because of easier to distinguish between other named caches.
>
> TODOs:
>   - (perf record) Support SDT event recording directly
>   - (perf record) Support @FILE/@BUILDID suffix to record specific SDTs.
>   - (perf record) Try to unregister SDT events after record.
>   - (ftrace) Support multiple SDTs on single event.
>
> Done:
>   - (perf probe) Allow glob matching for pre-cached events.
>   - (perf probe) Removes -x option when using pre-cached events.
>   - (perf probe) Support @FILE/@BUILDID suffix for pre-cached events.
>   - (perf buildid-cache) Fallback to old style buildid-cache.
>
> Thank you,
>
>
> ---
>
> Hemant Kumar (1):
>        perf/sdt: ELF support for SDT
>
> Masami Hiramatsu (18):
>        perf probe: Use strbuf for making strings
>        perf-buildid-cache: Use path/to/bin/buildid/elf instead of path/to/bin/buildid
>        perf buildid-cache: Fall back to the old style build-id cache
>        perf: Add lsdir to read a directory
>        perf-buildid-cache: Use lsdir for looking up buildid caches
>        perf-probe: Let probe_file__add_event return 0 if succeeded
>        perf probe: Add --cache option to cache the probe definitions
>        perf probe: Use cache entry if possible
>        perf probe: Show all cached probes
>        perf probe: Remove caches when --cache is given
>        perf probe: Add group name support
>        perf-probe: Set default kprobe group name if it is not given
>        perf buildid-cache: Scan and import user SDT events to probe cache
>        perf probe: Accept %sdt and %cached event name
>        perf-list: Show SDT and pre-cached events
>        perf-list: Skip SDTs placed in invalid binaries
>        perf probe: Allow wildcard for cached events
>        perf probe: Support @BUILDID or @FILE suffix for SDT events
>
>
>   tools/perf/Documentation/perf-probe.txt |   24 +
>   tools/perf/builtin-list.c               |    4
>   tools/perf/builtin-probe.c              |   30 +
>   tools/perf/util/build-id.c              |  278 ++++++++++--
>   tools/perf/util/build-id.h              |    6
>   tools/perf/util/dso.h                   |    5
>   tools/perf/util/parse-events.c          |   83 ++++
>   tools/perf/util/parse-events.h          |    2
>   tools/perf/util/probe-event.c           |  692 ++++++++++++++++++++++---------
>   tools/perf/util/probe-event.h           |    9
>   tools/perf/util/probe-file.c            |  495 ++++++++++++++++++++++
>   tools/perf/util/probe-file.h            |   32 +
>   tools/perf/util/probe-finder.c          |   14 -
>   tools/perf/util/symbol-elf.c            |  252 +++++++++++
>   tools/perf/util/symbol.c                |   15 -
>   tools/perf/util/symbol.h                |   22 +
>   tools/perf/util/util.c                  |   34 ++
>   tools/perf/util/util.h                  |    4
>   18 files changed, 1725 insertions(+), 276 deletions(-)
>
> --
> Masami Hiramatsu
>

-- 
Thanks,
Hemant Kumar

[toc] | [prev] | [standalone]


Page 2 of 2 — ← Prev page 1 [2]

Back to top | Article view | linux.kernel


csiph-web