All of lore.kernel.org
 help / color / mirror / Atom feed
From: Arnaldo Carvalho de Melo <acme@kernel.org>
To: Jiri Olsa <jolsa@kernel.org>
Cc: lkml <linux-kernel@vger.kernel.org>,
	"David Ahern" <dsahern@gmail.com>,
	"Ingo Molnar" <mingo@kernel.org>,
	"Namhyung Kim" <namhyung@kernel.org>,
	"Peter Zijlstra" <a.p.zijlstra@chello.nl>,
	"Matt Fleming" <matt@codeblueprint.co.uk>,
	"Raphaël Beamonte" <raphael.beamonte@gmail.com>
Subject: Re: [PATCH 4/5] perf tools: Propagate error info from tp_format
Date: Wed, 9 Sep 2015 17:58:13 -0300	[thread overview]
Message-ID: <20150909205813.GV3475@kernel.org> (raw)
In-Reply-To: <1441615087-13886-5-git-send-email-jolsa@kernel.org>

Em Mon, Sep 07, 2015 at 10:38:06AM +0200, Jiri Olsa escreveu:
> Propagate error info from tp_format via ERR_PTR to get
> it all the way down to the parse-event.c tracepoint adding
> routines. Following functions now return pointer with
> encoded error:
>   - tp_format
>   - trace_event__tp_format
>   - perf_evsel__newtp_idx
>   - perf_evsel__newtp
> 
> This affects several other places in perf, that cannot use
> pointer check anymore, but must utilize the err.h interface,
> when getting error information from above functions list.

Right, so this is tricky and we must be careful, see below...
 
> Link: http://lkml.kernel.org/n/tip-bzdckgv1zfp2y8up9l7ojt7y@git.kernel.org
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> ---
>  tools/perf/builtin-trace.c                  | 19 +++++++++++--------
>  tools/perf/tests/evsel-tp-sched.c           | 10 ++++++++--
>  tools/perf/tests/openat-syscall-all-cpus.c  |  3 ++-
>  tools/perf/tests/openat-syscall-tp-fields.c |  3 ++-
>  tools/perf/tests/openat-syscall.c           |  3 ++-
>  tools/perf/util/evlist.c                    |  3 ++-
>  tools/perf/util/evsel.c                     | 11 +++++++++--
>  tools/perf/util/evsel.h                     |  3 +++
>  tools/perf/util/parse-events.c              |  6 +++---
>  tools/perf/util/trace-event.c               | 13 +++++++++++--
>  10 files changed, 53 insertions(+), 21 deletions(-)
> 
> diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
> index 215653274102..93b80f12f35e 100644
> --- a/tools/perf/builtin-trace.c
> +++ b/tools/perf/builtin-trace.c
> @@ -38,6 +38,7 @@
>  #include <stdlib.h>
>  #include <sys/mman.h>
>  #include <linux/futex.h>
> +#include <linux/err.h>
>  
>  /* For older distros: */
>  #ifndef MAP_STACK
> @@ -245,13 +246,14 @@ static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void
>  	struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction);
>  
>  	/* older kernel (e.g., RHEL6) use syscalls:{enter,exit} */
> -	if (evsel == NULL)
> +	if (IS_ERR(evsel))
>  		evsel = perf_evsel__newtp("syscalls", direction);
>  
> -	if (evsel) {
> -		if (perf_evsel__init_syscall_tp(evsel, handler))
> -			goto out_delete;
> -	}
> +	if (IS_ERR(evsel))
> +		return NULL;
> +
> +	if (perf_evsel__init_syscall_tp(evsel, handler))
> +		goto out_delete;

This kind of stuff is ok, as evsel is a local variable and you kept the
interface for perf_evsel__syscall_newtp(), i.e. it returns NULL if a new
evsel can't be instantiated.

Ok, but that is a different interface than the one used by
perf_evsel__newtp(), that also instantiates a new evsel.

So when one thinks about "foo__new()" we now need to check which one of
the two interfaces it uses, if err.h or if the old NULL based failure
reporting one.

Double tricky if it is foo__new() and foo__new_variant(), as
perf_evsel__syscall_newtp() and perf_evsel__newtp(), i.e. both will
return a "struct perf_evsel" instance, but one using err.h, the other
use NULL.

Ok, you marked the ones using a comment, wonder if we couldn't use
'sparse' somehow here, is it used to check IS_ERR() usage in the kernel?

Ah, but what about this in trace__event_handler() in builtin-trace.c?
 
        if (evsel->tp_format) {
                event_format__fprintf(evsel->tp_format, sample->cpu,
                                      sample->raw_data, sample->raw_size,
                                      trace->output);
        }


Don't we have to use IS_ERR() here? Ok, no, because if setting up
evsel->tp_format fails, then that evsel will be destroyed and
perf_evsel__newtp() will return ERR_PTR(), so it is ok not no use
ERR_PTR(evsel->tp_format) because it will only be != NULL when it was
successfully set up.

But then, in perf_evsel__newtp_idx if zalloc() fails we will not return
ERR_PTR(), but instead NULL, a-ha, this one seems to be a real bug, no?

/*
 * Returns pointer with encoded error via <linux/err.h> interface.
 */
struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx)
{
	struct perf_evsel *evsel = zalloc(perf_evsel__object.size);
	int err = -ENOMEM;

	if (evsel != NULL) {
		struct perf_event_attr attr = {
			.type	       = PERF_TYPE_TRACEPOINT,
			.sample_type   = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
					  PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD),
		};

		if (asprintf(&evsel->name, "%s:%s", sys, name) < 0)
			goto out_free;

		evsel->tp_format = trace_event__tp_format(sys, name);
		if (IS_ERR(evsel->tp_format)) {
			err = PTR_ERR(evsel->tp_format);
			goto out_free;
		}

		event_attr_init(&attr);
		attr.config = evsel->tp_format->id;
		attr.sample_period = 1;
		perf_evsel__init(evsel, &attr, idx);
	}

	return evsel;

out_free:
	zfree(&evsel->name);
	free(evsel);
	return ERR_PTR(err);
}

>  
>  	return evsel;
>  
> @@ -1705,12 +1707,12 @@ static int trace__read_syscall_info(struct trace *trace, int id)
>  	snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
>  	sc->tp_format = trace_event__tp_format("syscalls", tp_name);
>  
> -	if (sc->tp_format == NULL && sc->fmt && sc->fmt->alias) {
> +	if (IS_ERR(sc->tp_format) && sc->fmt && sc->fmt->alias) {
>  		snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
>  		sc->tp_format = trace_event__tp_format("syscalls", tp_name);
>  	}
>  
> -	if (sc->tp_format == NULL)
> +	if (IS_ERR(sc->tp_format))
>  		return -1;
>  
>  	sc->args = sc->tp_format->format.fields;
> @@ -2390,7 +2392,8 @@ static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
>  static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
>  {
>  	struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
> -	if (evsel == NULL)
> +
> +	if (IS_ERR(evsel))
>  		return false;
>  
>  	if (perf_evsel__field(evsel, "pathname") == NULL) {
> diff --git a/tools/perf/tests/evsel-tp-sched.c b/tools/perf/tests/evsel-tp-sched.c
> index 52162425c969..790e413d9a1f 100644
> --- a/tools/perf/tests/evsel-tp-sched.c
> +++ b/tools/perf/tests/evsel-tp-sched.c
> @@ -1,3 +1,4 @@
> +#include <linux/err.h>
>  #include <traceevent/event-parse.h>
>  #include "evsel.h"
>  #include "tests.h"
> @@ -36,8 +37,8 @@ int test__perf_evsel__tp_sched_test(void)
>  	struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch");
>  	int ret = 0;
>  
> -	if (evsel == NULL) {
> -		pr_debug("perf_evsel__new\n");
> +	if (IS_ERR(evsel)) {
> +		pr_debug("perf_evsel__newtp failed with %ld\n", PTR_ERR(evsel));
>  		return -1;
>  	}
>  
> @@ -66,6 +67,11 @@ int test__perf_evsel__tp_sched_test(void)
>  
>  	evsel = perf_evsel__newtp("sched", "sched_wakeup");
>  
> +	if (IS_ERR(evsel)) {
> +		pr_debug("perf_evsel__newtp failed with %ld\n", PTR_ERR(evsel));
> +		return -1;
> +	}
> +
>  	if (perf_evsel__test_field(evsel, "comm", 16, true))
>  		ret = -1;
>  
> diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c
> index 495d8126b722..9e104a2e973d 100644
> --- a/tools/perf/tests/openat-syscall-all-cpus.c
> +++ b/tools/perf/tests/openat-syscall-all-cpus.c
> @@ -1,4 +1,5 @@
>  #include <api/fs/fs.h>
> +#include <linux/err.h>
>  #include "evsel.h"
>  #include "tests.h"
>  #include "thread_map.h"
> @@ -31,7 +32,7 @@ int test__openat_syscall_event_on_all_cpus(void)
>  	CPU_ZERO(&cpu_set);
>  
>  	evsel = perf_evsel__newtp("syscalls", "sys_enter_openat");
> -	if (evsel == NULL) {
> +	if (IS_ERR(evsel)) {
>  		tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "syscalls", "sys_enter_openat");
>  		pr_err("%s\n", errbuf);
>  		goto out_thread_map_delete;
> diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c
> index 01a19626c846..473d3869727e 100644
> --- a/tools/perf/tests/openat-syscall-tp-fields.c
> +++ b/tools/perf/tests/openat-syscall-tp-fields.c
> @@ -1,3 +1,4 @@
> +#include <linux/err.h>
>  #include "perf.h"
>  #include "evlist.h"
>  #include "evsel.h"
> @@ -30,7 +31,7 @@ int test__syscall_openat_tp_fields(void)
>  	}
>  
>  	evsel = perf_evsel__newtp("syscalls", "sys_enter_openat");
> -	if (evsel == NULL) {
> +	if (IS_ERR(evsel)) {
>  		pr_debug("%s: perf_evsel__newtp\n", __func__);
>  		goto out_delete_evlist;
>  	}
> diff --git a/tools/perf/tests/openat-syscall.c b/tools/perf/tests/openat-syscall.c
> index 08ac9d94a050..7b1db8306098 100644
> --- a/tools/perf/tests/openat-syscall.c
> +++ b/tools/perf/tests/openat-syscall.c
> @@ -1,4 +1,5 @@
>  #include <api/fs/tracing_path.h>
> +#include <linux/err.h>
>  #include "thread_map.h"
>  #include "evsel.h"
>  #include "debug.h"
> @@ -19,7 +20,7 @@ int test__openat_syscall_event(void)
>  	}
>  
>  	evsel = perf_evsel__newtp("syscalls", "sys_enter_openat");
> -	if (evsel == NULL) {
> +	if (IS_ERR(evsel)) {
>  		tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "syscalls", "sys_enter_openat");
>  		pr_err("%s\n", errbuf);
>  		goto out_thread_map_delete;
> diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
> index d51a5200c8af..3cb2bf9bd4bd 100644
> --- a/tools/perf/util/evlist.c
> +++ b/tools/perf/util/evlist.c
> @@ -25,6 +25,7 @@
>  #include <linux/bitops.h>
>  #include <linux/hash.h>
>  #include <linux/log2.h>
> +#include <linux/err.h>
>  
>  static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx);
>  static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx);
> @@ -265,7 +266,7 @@ int perf_evlist__add_newtp(struct perf_evlist *evlist,
>  {
>  	struct perf_evsel *evsel = perf_evsel__newtp(sys, name);
>  
> -	if (evsel == NULL)
> +	if (IS_ERR(evsel))
>  		return -1;
>  
>  	evsel->handler = handler;
> diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
> index 771ade4d5966..08c20ee4e27d 100644
> --- a/tools/perf/util/evsel.c
> +++ b/tools/perf/util/evsel.c
> @@ -13,6 +13,7 @@
>  #include <traceevent/event-parse.h>
>  #include <linux/hw_breakpoint.h>
>  #include <linux/perf_event.h>
> +#include <linux/err.h>
>  #include <sys/resource.h>
>  #include "asm/bug.h"
>  #include "callchain.h"
> @@ -225,9 +226,13 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
>  	return evsel;
>  }
>  
> +/*
> + * Returns pointer with encoded error via <linux/err.h> interface.
> + */
>  struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx)
>  {
>  	struct perf_evsel *evsel = zalloc(perf_evsel__object.size);
> +	int err = -ENOMEM;
>  
>  	if (evsel != NULL) {
>  		struct perf_event_attr attr = {
> @@ -240,8 +245,10 @@ struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int
>  			goto out_free;
>  
>  		evsel->tp_format = trace_event__tp_format(sys, name);
> -		if (evsel->tp_format == NULL)
> +		if (IS_ERR(evsel->tp_format)) {
> +			err = PTR_ERR(evsel->tp_format);
>  			goto out_free;
> +		}
>  
>  		event_attr_init(&attr);
>  		attr.config = evsel->tp_format->id;
> @@ -254,7 +261,7 @@ struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int
>  out_free:
>  	zfree(&evsel->name);
>  	free(evsel);
> -	return NULL;
> +	return ERR_PTR(err);
>  }
>  
>  const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = {
> diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
> index 298e6bbca200..b6e8ff876f17 100644
> --- a/tools/perf/util/evsel.h
> +++ b/tools/perf/util/evsel.h
> @@ -161,6 +161,9 @@ static inline struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr)
>  
>  struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx);
>  
> +/*
> + * Returns pointer with encoded error via <linux/err.h> interface.
> + */
>  static inline struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name)
>  {
>  	return perf_evsel__newtp_idx(sys, name, 0);
> diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
> index 1b284b8ad243..c47831c47220 100644
> --- a/tools/perf/util/parse-events.c
> +++ b/tools/perf/util/parse-events.c
> @@ -1,4 +1,5 @@
>  #include <linux/hw_breakpoint.h>
> +#include <linux/err.h>
>  #include "util.h"
>  #include "../perf.h"
>  #include "evlist.h"
> @@ -393,11 +394,10 @@ static int add_tracepoint(struct list_head *list, int *idx,
>  	struct perf_evsel *evsel;
>  
>  	evsel = perf_evsel__newtp_idx(sys_name, evt_name, (*idx)++);
> -	if (!evsel)
> -		return -ENOMEM;
> +	if (IS_ERR(evsel))
> +		return PTR_ERR(evsel);
>  
>  	list_add_tail(&evsel->node, list);
> -
>  	return 0;
>  }
>  
> diff --git a/tools/perf/util/trace-event.c b/tools/perf/util/trace-event.c
> index 2f4996ab313d..8e3a60e3e15f 100644
> --- a/tools/perf/util/trace-event.c
> +++ b/tools/perf/util/trace-event.c
> @@ -7,6 +7,7 @@
>  #include <sys/stat.h>
>  #include <fcntl.h>
>  #include <linux/kernel.h>
> +#include <linux/err.h>
>  #include <traceevent/event-parse.h>
>  #include <api/fs/tracing_path.h>
>  #include "trace-event.h"
> @@ -66,6 +67,9 @@ void trace_event__cleanup(struct trace_event *t)
>  	pevent_free(t->pevent);
>  }
>  
> +/*
> + * Returns pointer with encoded error via <linux/err.h> interface.
> + */
>  static struct event_format*
>  tp_format(const char *sys, const char *name)
>  {
> @@ -74,12 +78,14 @@ tp_format(const char *sys, const char *name)
>  	char path[PATH_MAX];
>  	size_t size;
>  	char *data;
> +	int err;
>  
>  	scnprintf(path, PATH_MAX, "%s/%s/%s/format",
>  		  tracing_events_path, sys, name);
>  
> -	if (filename__read_str(path, &data, &size))
> -		return NULL;
> +	err = filename__read_str(path, &data, &size);
> +	if (err)
> +		return ERR_PTR(err);
>  
>  	pevent_parse_format(pevent, &event, data, size, sys);
>  
> @@ -87,6 +93,9 @@ tp_format(const char *sys, const char *name)
>  	return event;
>  }
>  
> +/*
> + * Returns pointer with encoded error via <linux/err.h> interface.
> + */
>  struct event_format*
>  trace_event__tp_format(const char *sys, const char *name)
>  {
> -- 
> 2.4.3

  reply	other threads:[~2015-09-09 20:58 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-09-07  8:38 [PATCHv2 0/5] perf tools: Enhance parsing events tracepoint error output Jiri Olsa
2015-09-07  8:38 ` [PATCH 1/5] tools: Add err.h with ERR_PTR PTR_ERR interface Jiri Olsa
2015-09-08 20:22   ` Raphaël Beamonte
2015-09-08 20:24     ` Raphaël Beamonte
2015-09-08 21:06     ` Arnaldo Carvalho de Melo
2015-09-08 21:28       ` Raphaël Beamonte
2015-09-08 21:29   ` Raphaël Beamonte
2015-09-16  7:28   ` [tip:perf/core] " tip-bot for Jiri Olsa
2015-09-21 23:41     ` Vinson Lee
2015-09-29  6:35       ` Vinson Lee
2015-09-29  7:14         ` Jiri Olsa
2015-09-29  7:20           ` Jiri Olsa
2015-09-29  7:52             ` He Kuang
2015-09-29  7:57               ` Jiri Olsa
2015-09-29  8:15                 ` He Kuang
2015-09-29 10:41                   ` Jiri Olsa
2015-09-29 14:52                     ` Arnaldo Carvalho de Melo
2015-09-29 15:05                       ` [PATCH] perf tool: Fix shadowed declaration in parse-events.c Jiri Olsa
2015-10-01  7:10                         ` [tip:perf/core] perf tools: " tip-bot for Jiri Olsa
2015-09-07  8:38 ` [PATCH 2/5] perf tools: Add tools/include into tags directories Jiri Olsa
2015-09-15  7:02   ` [tip:perf/core] perf tools: Add tools/ include " tip-bot for Jiri Olsa
2015-09-07  8:38 ` [PATCH 3/5] perf tools: Propagate error info for the tracepoint parsing Jiri Olsa
2015-09-08 21:42   ` Raphaël Beamonte
2015-09-09  7:50     ` Jiri Olsa
2015-09-12 10:54   ` Matt Fleming
2015-09-16  7:29   ` [tip:perf/core] " tip-bot for Jiri Olsa
2015-09-07  8:38 ` [PATCH 4/5] perf tools: Propagate error info from tp_format Jiri Olsa
2015-09-09 20:58   ` Arnaldo Carvalho de Melo [this message]
2015-09-10  8:24     ` Jiri Olsa
2015-09-10 14:16       ` Arnaldo Carvalho de Melo
2015-09-14 20:53       ` Arnaldo Carvalho de Melo
2015-09-14 20:59         ` Raphaël Beamonte
2015-09-14 21:36           ` Arnaldo Carvalho de Melo
2015-09-14 22:05             ` Raphaël Beamonte
2015-09-15  2:35               ` Arnaldo Carvalho de Melo
2015-09-14 21:02         ` Arnaldo Carvalho de Melo
2015-09-16  7:29   ` [tip:perf/core] perf evsel: " tip-bot for Jiri Olsa
2015-09-07  8:38 ` [PATCH 5/5] perf tools: Enhance parsing events tracepoint error output Jiri Olsa
2015-09-10  7:00   ` Namhyung Kim
2015-09-10  8:05     ` Jiri Olsa
2015-09-11 16:09       ` Namhyung Kim
2015-09-11 16:16         ` Jiri Olsa
2015-09-11 17:50           ` Raphaël Beamonte
2015-09-11 18:55             ` Arnaldo Carvalho de Melo
2015-09-11 19:56               ` Raphaël Beamonte
2015-09-11 20:22                 ` Arnaldo Carvalho de Melo
2015-09-11 22:01                   ` Raphaël Beamonte
2015-09-14 20:59       ` Arnaldo Carvalho de Melo
2015-09-16  7:29   ` [tip:perf/core] " tip-bot for Jiri Olsa

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20150909205813.GV3475@kernel.org \
    --to=acme@kernel.org \
    --cc=a.p.zijlstra@chello.nl \
    --cc=dsahern@gmail.com \
    --cc=jolsa@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=matt@codeblueprint.co.uk \
    --cc=mingo@kernel.org \
    --cc=namhyung@kernel.org \
    --cc=raphael.beamonte@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.