All of lore.kernel.org
 help / color / mirror / Atom feed
From: Arnaldo Carvalho de Melo <acme@kernel.org>
To: Wang Nan <wangnan0@huawei.com>
Cc: namhyung@kernel.org, linux-kernel@vger.kernel.org,
	pi3orama@163.com, mingo@kernel.org, lizefan@huawei.com,
	Alexei Starovoitov <ast@kernel.org>,
	Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Subject: Re: [PATCH v4 13/16] perf tools: Always give options even it not compiled
Date: Fri, 11 Dec 2015 09:39:32 -0300	[thread overview]
Message-ID: <20151211123932.GA6843@kernel.org> (raw)
In-Reply-To: <1449541544-67621-14-git-send-email-wangnan0@huawei.com>

Em Tue, Dec 08, 2015 at 02:25:41AM +0000, Wang Nan escreveu:
> This patch keeps options of perf builtins same in all conditions. If
> one option is disabled because of compiling options, users should be
> notified.
> 
> Masami suggested another implementation in [1] that, by adding a
> OPTION_NEXT_DEPENDS option before those options in the 'struct option'
> array, options parser knows an option is disabled. However, in some
> cases this array is reordered (options__order()). In addition, in
> parse-option.c that array is const, so we can't simply merge
> information in decorator option into the affacted option.
> 
> This patch chooses a simpler implementation that, introducing a
> set_option_nobuild() function and two option parsing flags. Builtins
> with such options should call set_option_nobuild() before option
> parsing. The complexity of this patch is because we want some of options
> can be skipped safely. In this case their arguments should also be
> consumed.
> 
> Options in 'perf record' and 'perf probe' are fixed in this patch.
> 
> [1] http://lkml.kernel.org/g/50399556C9727B4D88A595C8584AAB3752627CD4@GSjpTKYDCembx32.service.hitachi.net
> 
> Test result:
> 
> Normal case:
> 
> # ./perf probe --vmlinux /tmp/vmlinux sys_write
> Added new event:
>   probe:sys_write      (on sys_write)
> 
> You can now use it in all perf tools, such as:
> 
> 	perf record -e probe:sys_write -aR sleep 1
> 
> 
> Build with NO_DWARF=1:
> 
> # ./perf probe -L sys_write
>   Error: switch `L' is not built because NO_DWARF=1

This should be:

  Error: switch `L' is not built-in because NO_DWARF=1

But it would be better as:

  Error: switch `L' is not available because NO_DWARF=1

What makes this an error is the fact that this option doesn't have that
CAN_SKIP flag, right? I.e. this SKIP flag determines the error/warning
message, for errors this should be "... is not available ..." for
warnings it should instead be "... is being ignored ...".

>  Usage: perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]
>     or: perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]
>     or: perf probe [<options>] --del '[GROUP:]EVENT' ...
>     or: perf probe --list [GROUP:]EVENT ...
>     or: perf probe [<options>] --funcs
> 
>     -L, --line <FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]>
>                           Show source code lines.
>                           (not build because NO_DWARF=1)
> 
> # ./perf probe -k /tmp/vmlinux sys_write
>   Warning: switch `k' is not built because NO_DWARF=1
> Added new event:
>   probe:sys_write      (on sys_write)
> 
> You can now use it in all perf tools, such as:
> 
> 	perf record -e probe:sys_write -aR sleep 1
> 
> # ./perf probe --vmlinux /tmp/vmlinux sys_write
>   Warning: option `vmlinux' is not built because NO_DWARF=1
> Added new event:
> [SNIP]
> 
> # ./perf probe -l
>  Usage: perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]
>     or: perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]
> ...
>     -k, --vmlinux <file>  vmlinux pathname
>                           (not build because NO_DWARF=1)
>     -L, --line <FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]>
>                           Show source code lines.
>                           (not build because NO_DWARF=1)
> ...
>     -V, --vars <FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT>
>                           Show accessible variables on PROBEDEF
>                           (not build because NO_DWARF=1)
>         --externs         Show external variables too (with --vars only)
>                           (not build because NO_DWARF=1)
>         --no-inlines      Don't search inlined functions
>                           (not build because NO_DWARF=1)
>         --range           Show variables location range in scope (with --vars only)
>                           (not build because NO_DWARF=1)
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> Cc: Alexei Starovoitov <ast@kernel.org>
> Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
> Cc: Namhyung Kim <namhyung@kernel.org>
> Cc: Zefan Li <lizefan@huawei.com>
> Cc: pi3orama@163.com
> ---
>  tools/perf/builtin-probe.c      |  15 +++++-
>  tools/perf/builtin-record.c     |   9 +++-
>  tools/perf/util/parse-options.c | 113 ++++++++++++++++++++++++++++++++++++----
>  tools/perf/util/parse-options.h |   5 ++
>  4 files changed, 129 insertions(+), 13 deletions(-)
> 
> diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
> index 132afc9..dbe2ea5 100644
> --- a/tools/perf/builtin-probe.c
> +++ b/tools/perf/builtin-probe.c
> @@ -249,6 +249,9 @@ static int opt_show_vars(const struct option *opt,
>  
>  	return ret;
>  }
> +#else
> +# define opt_show_lines NULL
> +# define opt_show_vars NULL
>  #endif
>  static int opt_add_probe_event(const struct option *opt,
>  			      const char *str, int unset __maybe_unused)
> @@ -473,7 +476,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
>  		opt_add_probe_event),
>  	OPT_BOOLEAN('f', "force", &probe_conf.force_add, "forcibly add events"
>  		    " with existing name"),
> -#ifdef HAVE_DWARF_SUPPORT
>  	OPT_CALLBACK('L', "line", NULL,
>  		     "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]",
>  		     "Show source code lines.", opt_show_lines),
> @@ -490,7 +492,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
>  		   "directory", "path to kernel source"),
>  	OPT_BOOLEAN('\0', "no-inlines", &probe_conf.no_inlines,
>  		"Don't search inlined functions"),
> -#endif
>  	OPT__DRY_RUN(&probe_event_dry_run),
>  	OPT_INTEGER('\0', "max-probes", &probe_conf.max_probes,
>  		 "Set how many probe points can be found for a probe."),
> @@ -521,6 +522,16 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
>  #ifdef HAVE_DWARF_SUPPORT
>  	set_option_flag(options, 'L', "line", PARSE_OPT_EXCLUSIVE);
>  	set_option_flag(options, 'V', "vars", PARSE_OPT_EXCLUSIVE);
> +#else
> +# define set_nobuild(s, l, c) set_option_nobuild(options, s, l, "NO_DWARF=1", c)
> +	set_nobuild('L', "line", false);
> +	set_nobuild('V', "vars", false);
> +	set_nobuild('\0', "externs", false);
> +	set_nobuild('\0', "range", false);
> +	set_nobuild('k', "vmlinux", true);
> +	set_nobuild('s', "source", true);
> +	set_nobuild('\0', "no-inlines", true);
> +# undef set_nobuild
>  #endif
>  	set_option_flag(options, 'F', "funcs", PARSE_OPT_EXCLUSIVE);
>  
> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
> index 8479821..11bf32d 100644
> --- a/tools/perf/builtin-record.c
> +++ b/tools/perf/builtin-record.c
> @@ -1124,12 +1124,10 @@ struct option __record_options[] = {
>  			"per thread proc mmap processing timeout in ms"),
>  	OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
>  		    "Record context switch events"),
> -#ifdef HAVE_LIBBPF_SUPPORT
>  	OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path",
>  		   "clang binary to use for compiling BPF scriptlets"),
>  	OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
>  		   "options passed to clang when compiling BPF scriptlets"),
> -#endif
>  	OPT_END()
>  };
>  
> @@ -1141,6 +1139,13 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
>  	struct record *rec = &record;
>  	char errbuf[BUFSIZ];
>  
> +#ifndef HAVE_LIBBPF_SUPPORT
> +# define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c)
> +	set_nobuild('\0', "clang-path", true);
> +	set_nobuild('\0', "clang-opt", true);
> +# undef set_nobuild
> +#endif
> +
>  	rec->evlist = perf_evlist__new();
>  	if (rec->evlist == NULL)
>  		return -ENOMEM;
> diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
> index 9fca092..105e357 100644
> --- a/tools/perf/util/parse-options.c
> +++ b/tools/perf/util/parse-options.c
> @@ -18,20 +18,34 @@ static int opterror(const struct option *opt, const char *reason, int flags)
>  	return error("option `%s' %s", opt->long_name, reason);
>  }
>  
> +static void optwarning(const struct option *opt, const char *reason, int flags)
> +{
> +	if (flags & OPT_SHORT)
> +		warning("switch `%c' %s", opt->short_name, reason);
> +	else if (flags & OPT_UNSET)
> +		warning("option `no-%s' %s", opt->long_name, reason);
> +	else
> +		warning("option `%s' %s", opt->long_name, reason);
> +}
> +
>  static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,
>  		   int flags, const char **arg)
>  {
> +	const char *res;
> +
>  	if (p->opt) {
> -		*arg = p->opt;
> +		res = p->opt;
>  		p->opt = NULL;
>  	} else if ((opt->flags & PARSE_OPT_LASTARG_DEFAULT) && (p->argc == 1 ||
>  		    **(p->argv + 1) == '-')) {
> -		*arg = (const char *)opt->defval;
> +		res = (const char *)opt->defval;
>  	} else if (p->argc > 1) {
>  		p->argc--;
> -		*arg = *++p->argv;
> +		res = *++p->argv;
>  	} else
>  		return opterror(opt, "requires a value", flags);
> +	if (arg)
> +		*arg = res;
>  	return 0;
>  }
>  
> @@ -91,6 +105,59 @@ static int get_value(struct parse_opt_ctx_t *p,
>  		}
>  	}
>  
> +	if (opt->flags & PARSE_OPT_NOBUILD) {
> +		char reason[128];
> +		bool noarg = false;
> +
> +		err = snprintf(reason, sizeof(reason),
> +				"is not built because %s",
> +				opt->build_opt);
> +		reason[sizeof(reason) - 1] = '\0';
> +
> +		if (err < 0)
> +			strncpy(reason, "is not built", sizeof(reason));
> +
> +		if (!(opt->flags & PARSE_OPT_CANSKIP))
> +			return opterror(opt, reason, flags);
> +
> +		err = 0;
> +		if (unset)
> +			noarg = true;
> +		if (opt->flags & PARSE_OPT_NOARG)
> +			noarg = true;
> +		if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
> +			noarg = true;
> +
> +		switch (opt->type) {
> +		case OPTION_BOOLEAN:
> +		case OPTION_INCR:
> +		case OPTION_BIT:
> +		case OPTION_SET_UINT:
> +		case OPTION_SET_PTR:
> +		case OPTION_END:
> +		case OPTION_ARGUMENT:
> +		case OPTION_GROUP:
> +			noarg = true;
> +			break;
> +		case OPTION_CALLBACK:
> +		case OPTION_STRING:
> +		case OPTION_INTEGER:
> +		case OPTION_UINTEGER:
> +		case OPTION_LONG:
> +		case OPTION_U64:
> +		default:
> +			break;
> +		}
> +
> +		if (!noarg)
> +			err = get_arg(p, opt, flags, NULL);
> +		if (err)
> +			return err;
> +
> +		optwarning(opt, reason, flags);
> +		return 0;
> +	}
> +
>  	switch (opt->type) {
>  	case OPTION_BIT:
>  		if (unset)
> @@ -647,6 +714,10 @@ static void print_option_help(const struct option *opts, int full)
>  		pad = USAGE_OPTS_WIDTH;
>  	}
>  	fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help);
> +	if (opts->flags & PARSE_OPT_NOBUILD)
> +		fprintf(stderr, "%*s(not build because %s)\n",
> +			USAGE_OPTS_WIDTH + USAGE_GAP, "",
> +			opts->build_opt);
>  }
>  
>  static int option__cmp(const void *va, const void *vb)
> @@ -853,15 +924,39 @@ int parse_opt_verbosity_cb(const struct option *opt,
>  	return 0;
>  }
>  
> -void set_option_flag(struct option *opts, int shortopt, const char *longopt,
> -		     int flag)
> +static struct option *
> +find_option(struct option *opts, int shortopt, const char *longopt)
>  {
>  	for (; opts->type != OPTION_END; opts++) {
>  		if ((shortopt && opts->short_name == shortopt) ||
>  		    (opts->long_name && longopt &&
> -		     !strcmp(opts->long_name, longopt))) {
> -			opts->flags |= flag;
> -			break;
> -		}
> +		     !strcmp(opts->long_name, longopt)))
> +			return opts;
>  	}
> +	return NULL;
> +}
> +
> +void set_option_flag(struct option *opts, int shortopt, const char *longopt,
> +		     int flag)
> +{
> +	struct option *opt = find_option(opts, shortopt, longopt);
> +
> +	if (opt)
> +		opt->flags |= flag;
> +	return;
> +}
> +
> +void set_option_nobuild(struct option *opts, int shortopt,
> +			const char *longopt,
> +			const char *build_opt,
> +			bool can_skip)
> +{
> +	struct option *opt = find_option(opts, shortopt, longopt);
> +
> +	if (!opt)
> +		return;
> +
> +	opt->flags |= PARSE_OPT_NOBUILD;
> +	opt->flags |= can_skip ? PARSE_OPT_CANSKIP : 0;
> +	opt->build_opt = build_opt;
>  }
> diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
> index a8e407b..2cac2aa 100644
> --- a/tools/perf/util/parse-options.h
> +++ b/tools/perf/util/parse-options.h
> @@ -41,6 +41,8 @@ enum parse_opt_option_flags {
>  	PARSE_OPT_DISABLED = 32,
>  	PARSE_OPT_EXCLUSIVE = 64,
>  	PARSE_OPT_NOEMPTY  = 128,
> +	PARSE_OPT_NOBUILD  = 256,
> +	PARSE_OPT_CANSKIP  = 512,
>  };
>  
>  struct option;
> @@ -96,6 +98,7 @@ struct option {
>  	void *value;
>  	const char *argh;
>  	const char *help;
> +	const char *build_opt;
>  
>  	int flags;
>  	parse_opt_cb *callback;
> @@ -226,4 +229,6 @@ extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
>  extern const char *parse_options_fix_filename(const char *prefix, const char *file);
>  
>  void set_option_flag(struct option *opts, int sopt, const char *lopt, int flag);
> +void set_option_nobuild(struct option *opts, int shortopt, const char *longopt,
> +			const char *build_opt, bool can_skip);
>  #endif /* __PERF_PARSE_OPTIONS_H */
> -- 
> 1.8.3.4

  reply	other threads:[~2015-12-11 12:40 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-12-08  2:25 [PATCH v4 00/16] perf tools: BPF related update and other improvements Wang Nan
2015-12-08  2:25 ` [PATCH v4 01/16] tools lib bpf: Check return value of strdup when reading map names Wang Nan
2015-12-14  8:37   ` [tip:perf/core] " tip-bot for Wang Nan
2015-12-08  2:25 ` [PATCH v4 02/16] tools lib bpf: Fetch map names from correct strtab Wang Nan
2015-12-14  8:38   ` [tip:perf/core] " tip-bot for Wang Nan
2015-12-08  2:25 ` [PATCH v4 03/16] perf tools: Add API to config maps in bpf object Wang Nan
2015-12-08  2:25 ` [PATCH v4 04/16] perf tools: Enable BPF object configure syntax Wang Nan
2015-12-08  2:25 ` [PATCH v4 05/16] perf record: Apply config to BPF objects before recording Wang Nan
2015-12-08  2:25 ` [PATCH v4 06/16] perf tools: Support perf event alias name Wang Nan
2015-12-11 12:03   ` Arnaldo Carvalho de Melo
2015-12-11 12:12     ` pi3orama
2015-12-08  2:25 ` [PATCH v4 07/16] perf tools: Enable passing event to BPF object Wang Nan
2015-12-08  2:25 ` [PATCH v4 08/16] perf tools: Support setting different slots in a BPF map separately Wang Nan
2015-12-08  2:25 ` [PATCH v4 09/16] perf tools: Enable indices setting syntax for BPF maps Wang Nan
2015-12-11 12:11   ` Arnaldo Carvalho de Melo
2015-12-11 12:15     ` Arnaldo Carvalho de Melo
2015-12-11 12:39       ` pi3orama
2015-12-11 12:47         ` Arnaldo Carvalho de Melo
2015-12-11 12:57           ` pi3orama
2015-12-11 18:21         ` Alexei Starovoitov
2015-12-14  3:27           ` Wangnan (F)
2015-12-14  4:28             ` Alexei Starovoitov
2015-12-14  4:39               ` Wangnan (F)
2015-12-14  5:51                 ` Alexei Starovoitov
2015-12-08  2:25 ` [PATCH v4 10/16] perf tools: Introduce bpf-output event Wang Nan
2015-12-08  2:25 ` [PATCH v4 11/16] perf data: Add u32_hex data type Wang Nan
2015-12-14  8:38   ` [tip:perf/core] " tip-bot for Wang Nan
2015-12-08  2:25 ` [PATCH v4 12/16] perf data: Support converting data from bpf_perf_event_output() Wang Nan
2015-12-08  2:25 ` [PATCH v4 13/16] perf tools: Always give options even it not compiled Wang Nan
2015-12-11 12:39   ` Arnaldo Carvalho de Melo [this message]
2015-12-08  2:25 ` [PATCH v4 14/16] perf record: Support custom vmlinux path Wang Nan
2015-12-08  2:25 ` [PATCH v4 15/16] perf script: Add support for PERF_TYPE_BREAKPOINT Wang Nan
2015-12-14  8:38   ` [tip:perf/core] " tip-bot for Wang Nan
2015-12-08  2:25 ` [PATCH v4 16/16] perf tools: Clear struct machine during machine__init() Wang Nan
2015-12-14  8:39   ` [tip:perf/core] " tip-bot for Wang Nan

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=20151211123932.GA6843@kernel.org \
    --to=acme@kernel.org \
    --cc=ast@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lizefan@huawei.com \
    --cc=masami.hiramatsu.pt@hitachi.com \
    --cc=mingo@kernel.org \
    --cc=namhyung@kernel.org \
    --cc=pi3orama@163.com \
    --cc=wangnan0@huawei.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.