* [PATCH v15 1/9] perf config: Add '--system' and '--user' options to select which config file is used
2016-02-10 17:51 [PATCHSET v15 0/9] perf config: Add several options into perf-config Taeung Song
@ 2016-02-10 17:51 ` Taeung Song
2016-02-16 7:51 ` [tip:perf/core] " tip-bot for Taeung Song
2016-02-10 17:51 ` [PATCH v15 2/9] perf config: Collect configs to handle config variables Taeung Song
` (7 subsequent siblings)
8 siblings, 1 reply; 11+ messages in thread
From: Taeung Song @ 2016-02-10 17:51 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: linux-kernel, Jiri Olsa, Namhyung Kim, Ingo Molnar, Taeung Song
The file-options '--system' means $(sysconfdir)/perfconfig and
'--user' means $HOME/.perfconfig. If file-option isn't used,
both system and user config file is read.
The syntax examples are like below.
perf config [<file-option>] [options]
a specific config file.
# perf config --user | --system
or
both user and system config file.
# perf config
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
---
tools/perf/Documentation/perf-config.txt | 14 +++++++++++++-
tools/perf/builtin-config.c | 27 ++++++++++++++++++++++++---
tools/perf/util/cache.h | 3 +++
tools/perf/util/config.c | 4 ++--
4 files changed, 42 insertions(+), 6 deletions(-)
diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt
index 74589c6..41b9081 100644
--- a/tools/perf/Documentation/perf-config.txt
+++ b/tools/perf/Documentation/perf-config.txt
@@ -8,7 +8,7 @@ perf-config - Get and set variables in a configuration file.
SYNOPSIS
--------
[verse]
-'perf config' -l | --list
+'perf config' [<file-option>] -l | --list
DESCRIPTION
-----------
@@ -21,6 +21,14 @@ OPTIONS
--list::
Show current config variables, name and value, for all sections.
+--user::
+ For writing and reading options: write to user
+ '$HOME/.perfconfig' file or read it.
+
+--system::
+ For writing and reading options: write to system-wide
+ '$(sysconfdir)/perfconfig' or read it.
+
CONFIGURATION FILE
------------------
@@ -30,6 +38,10 @@ The '$HOME/.perfconfig' file is used to store a per-user configuration.
The file '$(sysconfdir)/perfconfig' can be used to
store a system-wide default configuration.
+When reading or writing, the values are read from the system and user
+configuration files by default, and options '--system' and '--user'
+can be used to tell the command to read from or write to only that location.
+
Syntax
~~~~~~
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
index f04e804..c42448e 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -13,8 +13,10 @@
#include "util/util.h"
#include "util/debug.h"
+static bool use_system_config, use_user_config;
+
static const char * const config_usage[] = {
- "perf config [options]",
+ "perf config [<file-option>] [options]",
NULL
};
@@ -25,6 +27,8 @@ enum actions {
static struct option config_options[] = {
OPT_SET_UINT('l', "list", &actions,
"show current config variables", ACTION_LIST),
+ OPT_BOOLEAN(0, "system", &use_system_config, "use system config file"),
+ OPT_BOOLEAN(0, "user", &use_user_config, "use user config file"),
OPT_END()
};
@@ -42,10 +46,23 @@ static int show_config(const char *key, const char *value,
int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
{
int ret = 0;
+ char *user_config = mkpath("%s/.perfconfig", getenv("HOME"));
argc = parse_options(argc, argv, config_options, config_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
+ if (use_system_config && use_user_config) {
+ pr_err("Error: only one config file at a time\n");
+ parse_options_usage(config_usage, config_options, "user", 0);
+ parse_options_usage(NULL, config_options, "system", 0);
+ return -1;
+ }
+
+ if (use_system_config)
+ config_exclusive_filename = perf_etc_perfconfig();
+ else if (use_user_config)
+ config_exclusive_filename = user_config;
+
switch (actions) {
case ACTION_LIST:
if (argc) {
@@ -53,9 +70,13 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
parse_options_usage(config_usage, config_options, "l", 1);
} else {
ret = perf_config(show_config, NULL);
- if (ret < 0)
+ if (ret < 0) {
+ const char * config_filename = config_exclusive_filename;
+ if (!config_exclusive_filename)
+ config_filename = user_config;
pr_err("Nothing configured, "
- "please check your ~/.perfconfig file\n");
+ "please check your %s \n", config_filename);
+ }
}
break;
default:
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 07b5d63..3ca453f 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -23,6 +23,8 @@
#define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR"
#define PERF_PAGER_ENVIRONMENT "PERF_PAGER"
+extern const char *config_exclusive_filename;
+
typedef int (*config_fn_t)(const char *, const char *, void *);
extern int perf_default_config(const char *, const char *, void *);
extern int perf_config(config_fn_t fn, void *);
@@ -31,6 +33,7 @@ extern u64 perf_config_u64(const char *, const char *);
extern int perf_config_bool(const char *, const char *);
extern int config_error_nonbool(const char *);
extern const char *perf_config_dirname(const char *, const char *);
+extern const char *perf_etc_perfconfig(void);
char *alias_lookup(const char *alias);
int split_cmdline(char *cmdline, const char ***argv);
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index d3e12e3..4e72763 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -26,7 +26,7 @@ static const char *config_file_name;
static int config_linenr;
static int config_file_eof;
-static const char *config_exclusive_filename;
+const char *config_exclusive_filename;
static int get_next_char(void)
{
@@ -434,7 +434,7 @@ static int perf_config_from_file(config_fn_t fn, const char *filename, void *dat
return ret;
}
-static const char *perf_etc_perfconfig(void)
+const char *perf_etc_perfconfig(void)
{
static const char *system_wide;
if (!system_wide)
--
2.5.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [tip:perf/core] perf config: Add '--system' and '--user' options to select which config file is used
2016-02-10 17:51 ` [PATCH v15 1/9] perf config: Add '--system' and '--user' options to select which config file is used Taeung Song
@ 2016-02-16 7:51 ` tip-bot for Taeung Song
0 siblings, 0 replies; 11+ messages in thread
From: tip-bot for Taeung Song @ 2016-02-16 7:51 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, treeze.taeung, namhyung, acme, jolsa, hpa, mingo,
tglx
Commit-ID: c7ac24178c50a01f14eebcddf5c7b7a2e54676cc
Gitweb: http://git.kernel.org/tip/c7ac24178c50a01f14eebcddf5c7b7a2e54676cc
Author: Taeung Song <treeze.taeung@gmail.com>
AuthorDate: Thu, 11 Feb 2016 02:51:17 +0900
Committer: Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Fri, 12 Feb 2016 10:54:46 -0300
perf config: Add '--system' and '--user' options to select which config file is used
The '--system' option means $(sysconfdir)/perfconfig and '--user' means
$HOME/.perfconfig. If none is used, both system and user config file are
read. E.g.:
# perf config [<file-option>] [options]
With an specific config file:
# perf config --user | --system
or both user and system config file:
# perf config
Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: http://lkml.kernel.org/r/1455126685-32367-2-git-send-email-treeze.taeung@gmail.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/Documentation/perf-config.txt | 14 +++++++++++++-
tools/perf/builtin-config.c | 27 ++++++++++++++++++++++++---
tools/perf/util/cache.h | 3 +++
tools/perf/util/config.c | 4 ++--
4 files changed, 42 insertions(+), 6 deletions(-)
diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt
index c7158bf..15949e2 100644
--- a/tools/perf/Documentation/perf-config.txt
+++ b/tools/perf/Documentation/perf-config.txt
@@ -8,7 +8,7 @@ perf-config - Get and set variables in a configuration file.
SYNOPSIS
--------
[verse]
-'perf config' -l | --list
+'perf config' [<file-option>] -l | --list
DESCRIPTION
-----------
@@ -21,6 +21,14 @@ OPTIONS
--list::
Show current config variables, name and value, for all sections.
+--user::
+ For writing and reading options: write to user
+ '$HOME/.perfconfig' file or read it.
+
+--system::
+ For writing and reading options: write to system-wide
+ '$(sysconfdir)/perfconfig' or read it.
+
CONFIGURATION FILE
------------------
@@ -30,6 +38,10 @@ The '$HOME/.perfconfig' file is used to store a per-user configuration.
The file '$(sysconfdir)/perfconfig' can be used to
store a system-wide default configuration.
+When reading or writing, the values are read from the system and user
+configuration files by default, and options '--system' and '--user'
+can be used to tell the command to read from or write to only that location.
+
Syntax
~~~~~~
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
index f04e804..c42448e 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -13,8 +13,10 @@
#include "util/util.h"
#include "util/debug.h"
+static bool use_system_config, use_user_config;
+
static const char * const config_usage[] = {
- "perf config [options]",
+ "perf config [<file-option>] [options]",
NULL
};
@@ -25,6 +27,8 @@ enum actions {
static struct option config_options[] = {
OPT_SET_UINT('l', "list", &actions,
"show current config variables", ACTION_LIST),
+ OPT_BOOLEAN(0, "system", &use_system_config, "use system config file"),
+ OPT_BOOLEAN(0, "user", &use_user_config, "use user config file"),
OPT_END()
};
@@ -42,10 +46,23 @@ static int show_config(const char *key, const char *value,
int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
{
int ret = 0;
+ char *user_config = mkpath("%s/.perfconfig", getenv("HOME"));
argc = parse_options(argc, argv, config_options, config_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
+ if (use_system_config && use_user_config) {
+ pr_err("Error: only one config file at a time\n");
+ parse_options_usage(config_usage, config_options, "user", 0);
+ parse_options_usage(NULL, config_options, "system", 0);
+ return -1;
+ }
+
+ if (use_system_config)
+ config_exclusive_filename = perf_etc_perfconfig();
+ else if (use_user_config)
+ config_exclusive_filename = user_config;
+
switch (actions) {
case ACTION_LIST:
if (argc) {
@@ -53,9 +70,13 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
parse_options_usage(config_usage, config_options, "l", 1);
} else {
ret = perf_config(show_config, NULL);
- if (ret < 0)
+ if (ret < 0) {
+ const char * config_filename = config_exclusive_filename;
+ if (!config_exclusive_filename)
+ config_filename = user_config;
pr_err("Nothing configured, "
- "please check your ~/.perfconfig file\n");
+ "please check your %s \n", config_filename);
+ }
}
break;
default:
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 07b5d63..3ca453f 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -23,6 +23,8 @@
#define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR"
#define PERF_PAGER_ENVIRONMENT "PERF_PAGER"
+extern const char *config_exclusive_filename;
+
typedef int (*config_fn_t)(const char *, const char *, void *);
extern int perf_default_config(const char *, const char *, void *);
extern int perf_config(config_fn_t fn, void *);
@@ -31,6 +33,7 @@ extern u64 perf_config_u64(const char *, const char *);
extern int perf_config_bool(const char *, const char *);
extern int config_error_nonbool(const char *);
extern const char *perf_config_dirname(const char *, const char *);
+extern const char *perf_etc_perfconfig(void);
char *alias_lookup(const char *alias);
int split_cmdline(char *cmdline, const char ***argv);
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index d3e12e3..4e72763 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -26,7 +26,7 @@ static const char *config_file_name;
static int config_linenr;
static int config_file_eof;
-static const char *config_exclusive_filename;
+const char *config_exclusive_filename;
static int get_next_char(void)
{
@@ -434,7 +434,7 @@ static int perf_config_from_file(config_fn_t fn, const char *filename, void *dat
return ret;
}
-static const char *perf_etc_perfconfig(void)
+const char *perf_etc_perfconfig(void)
{
static const char *system_wide;
if (!system_wide)
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v15 2/9] perf config: Collect configs to handle config variables
2016-02-10 17:51 [PATCHSET v15 0/9] perf config: Add several options into perf-config Taeung Song
2016-02-10 17:51 ` [PATCH v15 1/9] perf config: Add '--system' and '--user' options to select which config file is used Taeung Song
@ 2016-02-10 17:51 ` Taeung Song
2016-02-10 17:51 ` [PATCH v15 3/9] perf config: Add 'list-all' option to perf-config Taeung Song
` (6 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Taeung Song @ 2016-02-10 17:51 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: linux-kernel, Jiri Olsa, Namhyung Kim, Ingo Molnar, Taeung Song
Collecting configs into list because of two reason.
First of all, if there are same variables both user
and system config file, they all will be printed
when 'list' command work. But if config variables are
duplicated, user config variables should only be printed
because it has priority.
Lastly, list into which configs is collected
will be required to keep and handle config variables
and values in the near furture. For example,
getting or setting functionality.
And change show_config() function.
Old show_config() worked depending on perf_config().
New show_config() work using collected configs list.
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
---
tools/perf/builtin-config.c | 150 ++++++++++++++++++++++++++++++++++++++++++--
tools/perf/util/cache.h | 13 ++++
2 files changed, 158 insertions(+), 5 deletions(-)
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
index c42448e..c43234e 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -32,13 +32,148 @@ static struct option config_options[] = {
OPT_END()
};
-static int show_config(const char *key, const char *value,
- void *cb __maybe_unused)
+static struct config_section *find_section(struct list_head *sections,
+ const char *section_name)
{
+ struct config_section *section;
+
+ list_for_each_entry(section, sections, list)
+ if (!strcmp(section->name, section_name))
+ return section;
+
+ return NULL;
+}
+
+static struct config_element *find_element(const char *name,
+ struct config_section *section)
+{
+ struct config_element *element;
+
+ list_for_each_entry(element, §ion->element_head, list)
+ if (!strcmp(element->name, name))
+ return element;
+
+ return NULL;
+}
+
+static void find_config(struct list_head *sections,
+ struct config_section **section,
+ struct config_element **element,
+ const char *section_name, const char *name)
+{
+ *section = find_section(sections, section_name);
+
+ if (*section != NULL)
+ *element = find_element(name, *section);
+ else
+ *element = NULL;
+}
+
+static struct config_section *init_section(const char *section_name)
+{
+ struct config_section *section;
+
+ section = zalloc(sizeof(*section));
+ if (!section)
+ return NULL;
+
+ INIT_LIST_HEAD(§ion->element_head);
+ section->name = strdup(section_name);
+ if (!section->name) {
+ pr_err("%s: strdup failed\n", __func__);
+ free(section);
+ return NULL;
+ }
+
+ return section;
+}
+
+static int add_element(struct list_head *head,
+ const char *name, const char *value)
+{
+ struct config_element *element;
+
+ element = zalloc(sizeof(*element));
+ if (!element)
+ return -1;
+
+ element->name = strdup(name);
+ if (!element->name) {
+ pr_err("%s: strdup failed\n", __func__);
+ free(element);
+ return -1;
+ }
if (value)
- printf("%s=%s\n", key, value);
+ element->value = (char *)value;
else
- printf("%s\n", key);
+ element->value = NULL;
+
+ list_add_tail(&element->list, head);
+ return 0;
+}
+
+static int collect_current_config(const char *var, const char *value,
+ void *spec_sections)
+{
+ int ret = -1;
+ char *ptr, *key;
+ char *section_name, *name;
+ struct config_section *section = NULL;
+ struct config_element *element = NULL;
+ struct list_head *sections = (struct list_head *)spec_sections;
+
+ key = ptr = strdup(var);
+ if (!key) {
+ pr_err("%s: strdup failed\n", __func__);
+ return -1;
+ }
+
+ section_name = strsep(&ptr, ".");
+ name = ptr;
+ if (name == NULL || value == NULL)
+ goto out_err;
+
+ find_config(sections, §ion, &element, section_name, name);
+
+ if (!section) {
+ section = init_section(section_name);
+ if (!section)
+ goto out_err;
+ list_add_tail(§ion->list, sections);
+ }
+
+ value = strdup(value);
+ if (!value) {
+ pr_err("%s: strdup failed\n", __func__);
+ goto out_err;
+ }
+
+ if (!element)
+ add_element(§ion->element_head, name, value);
+ else {
+ free(element->value);
+ element->value = (char *)value;
+ }
+
+ ret = 0;
+out_err:
+ free(key);
+ return ret;
+}
+
+static int show_config(struct list_head *sections)
+{
+ struct config_section *section;
+ struct config_element *element;
+
+ if (list_empty(sections))
+ return -1;
+ list_for_each_entry(section, sections, list) {
+ list_for_each_entry(element, §ion->element_head, list) {
+ printf("%s.%s=%s\n", section->name,
+ element->name, element->value);
+ }
+ }
return 0;
}
@@ -46,6 +181,7 @@ static int show_config(const char *key, const char *value,
int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
{
int ret = 0;
+ struct list_head sections;
char *user_config = mkpath("%s/.perfconfig", getenv("HOME"));
argc = parse_options(argc, argv, config_options, config_usage,
@@ -58,18 +194,22 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
return -1;
}
+ INIT_LIST_HEAD(§ions);
+
if (use_system_config)
config_exclusive_filename = perf_etc_perfconfig();
else if (use_user_config)
config_exclusive_filename = user_config;
+ perf_config(collect_current_config, §ions);
+
switch (actions) {
case ACTION_LIST:
if (argc) {
pr_err("Error: takes no arguments\n");
parse_options_usage(config_usage, config_options, "l", 1);
} else {
- ret = perf_config(show_config, NULL);
+ ret = show_config(§ions);
if (ret < 0) {
const char * config_filename = config_exclusive_filename;
if (!config_exclusive_filename)
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 3ca453f..92cd739 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -1,6 +1,7 @@
#ifndef __PERF_CACHE_H
#define __PERF_CACHE_H
+#include <linux/list.h>
#include <stdbool.h>
#include "util.h"
#include "strbuf.h"
@@ -23,6 +24,18 @@
#define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR"
#define PERF_PAGER_ENVIRONMENT "PERF_PAGER"
+struct config_element {
+ char *name;
+ char *value;
+ struct list_head list;
+};
+
+struct config_section {
+ char *name;
+ struct list_head element_head;
+ struct list_head list;
+};
+
extern const char *config_exclusive_filename;
typedef int (*config_fn_t)(const char *, const char *, void *);
--
2.5.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH v15 3/9] perf config: Add 'list-all' option to perf-config
2016-02-10 17:51 [PATCHSET v15 0/9] perf config: Add several options into perf-config Taeung Song
2016-02-10 17:51 ` [PATCH v15 1/9] perf config: Add '--system' and '--user' options to select which config file is used Taeung Song
2016-02-10 17:51 ` [PATCH v15 2/9] perf config: Collect configs to handle config variables Taeung Song
@ 2016-02-10 17:51 ` Taeung Song
2016-02-10 17:51 ` [PATCH v15 4/9] perf config: Add a option 'skel' " Taeung Song
` (5 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Taeung Song @ 2016-02-10 17:51 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: linux-kernel, Jiri Olsa, Namhyung Kim, Ingo Molnar, Taeung Song
'list-all' option is to display both current config variables
and all possible config variables with default values.
The syntax examples are like below
perf config [<file-option>] [options]
display all perf config with default values.
# perf config -a | --list-all
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
---
tools/perf/Documentation/perf-config.txt | 6 +
tools/perf/builtin-config.c | 231 ++++++++++++++++++++++++++++++-
2 files changed, 235 insertions(+), 2 deletions(-)
diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt
index 41b9081..955b342 100644
--- a/tools/perf/Documentation/perf-config.txt
+++ b/tools/perf/Documentation/perf-config.txt
@@ -9,6 +9,8 @@ SYNOPSIS
--------
[verse]
'perf config' [<file-option>] -l | --list
+or
+'perf config' [<file-option>] -a | --list-all
DESCRIPTION
-----------
@@ -29,6 +31,10 @@ OPTIONS
For writing and reading options: write to system-wide
'$(sysconfdir)/perfconfig' or read it.
+-a::
+--list-all::
+ Show current and all possible config variables with default values.
+
CONFIGURATION FILE
------------------
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
index c43234e..8a63119 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -21,17 +21,160 @@ static const char * const config_usage[] = {
};
enum actions {
- ACTION_LIST = 1
+ ACTION_LIST = 1,
+ ACTION_LIST_ALL
} actions;
static struct option config_options[] = {
OPT_SET_UINT('l', "list", &actions,
"show current config variables", ACTION_LIST),
+ OPT_SET_UINT('a', "list-all", &actions,
+ "show current and all possible config"
+ " variables with default values", ACTION_LIST_ALL),
OPT_BOOLEAN(0, "system", &use_system_config, "use system config file"),
OPT_BOOLEAN(0, "user", &use_user_config, "use user config file"),
OPT_END()
};
+enum config_idx {
+ CONFIG_COLORS_TOP,
+ CONFIG_COLORS_MEDIUM,
+ CONFIG_COLORS_NORMAL,
+ CONFIG_COLORS_SELECTED,
+ CONFIG_COLORS_JUMP_ARROWS,
+ CONFIG_COLORS_ADDR,
+ CONFIG_COLORS_ROOT,
+ CONFIG_TUI_REPORT,
+ CONFIG_TUI_ANNOTATE,
+ CONFIG_TUI_TOP,
+ CONFIG_BUILDID_DIR,
+ CONFIG_ANNOTATE_HIDE_SRC_CODE,
+ CONFIG_ANNOTATE_USE_OFFSET,
+ CONFIG_ANNOTATE_JUMP_ARROWS,
+ CONFIG_ANNOTATE_SHOW_NR_JUMPS,
+ CONFIG_ANNOTATE_SHOW_LINENR,
+ CONFIG_ANNOTATE_SHOW_TOTAL_PERIOD,
+ CONFIG_GTK_ANNOTATE,
+ CONFIG_GTK_REPORT,
+ CONFIG_GTK_TOP,
+ CONFIG_PAGER_CMD,
+ CONFIG_PAGER_REPORT,
+ CONFIG_PAGER_ANNOTATE,
+ CONFIG_PAGER_TOP,
+ CONFIG_PAGER_DIFF,
+ CONFIG_HELP_FORMAT,
+ CONFIG_HELP_AUTOCORRECT,
+ CONFIG_HIST_PERCENTAGE,
+ CONFIG_UI_SHOW_HEADERS,
+ CONFIG_CALL_GRAPH_RECORD_MODE,
+ CONFIG_CALL_GRAPH_DUMP_SIZE,
+ CONFIG_CALL_GRAPH_PRINT_TYPE,
+ CONFIG_CALL_GRAPH_ORDER,
+ CONFIG_CALL_GRAPH_SORT_KEY,
+ CONFIG_CALL_GRAPH_THRESHOLD,
+ CONFIG_CALL_GRAPH_PRINT_LIMIT,
+ CONFIG_REPORT_GROUP,
+ CONFIG_REPORT_CHILDREN,
+ CONFIG_REPORT_PERCENT_LIMIT,
+ CONFIG_REPORT_QUEUE_SIZE,
+ CONFIG_TOP_CHILDREN,
+ CONFIG_MAN_VIEWER,
+ CONFIG_KMEM_DEFAULT,
+};
+
+enum config_type {
+ CONFIG_TYPE_BOOL,
+ CONFIG_TYPE_INT,
+ CONFIG_TYPE_LONG,
+ CONFIG_TYPE_U64,
+ CONFIG_TYPE_FLOAT,
+ CONFIG_TYPE_DOUBLE,
+ CONFIG_TYPE_STRING,
+ /* special type */
+ CONFIG_END
+};
+
+struct config_item {
+ const char *section;
+ const char *name;
+ union {
+ bool b;
+ int i;
+ u32 l;
+ u64 ll;
+ float f;
+ double d;
+ const char *s;
+ } value;
+ enum config_type type;
+};
+
+#define CONF_VAR(_sec, _name, _field, _val, _type) \
+ { .section = _sec, .name = _name, .value._field = _val, .type = _type }
+
+#define CONF_BOOL_VAR(_idx, _sec, _name, _val) \
+ [CONFIG_##_idx] = CONF_VAR(_sec, _name, b, _val, CONFIG_TYPE_BOOL)
+#define CONF_INT_VAR(_idx, _sec, _name, _val) \
+ [CONFIG_##_idx] = CONF_VAR(_sec, _name, i, _val, CONFIG_TYPE_INT)
+#define CONF_LONG_VAR(_idx, _sec, _name, _val) \
+ [CONFIG_##_idx] = CONF_VAR(_sec, _name, l, _val, CONFIG_TYPE_LONG)
+#define CONF_U64_VAR(_idx, _sec, _name, _val) \
+ [CONFIG_##_idx] = CONF_VAR(_sec, _name, ll, _val, CONFIG_TYPE_U64)
+#define CONF_FLOAT_VAR(_idx, _sec, _name, _val) \
+ [CONFIG_##_idx] = CONF_VAR(_sec, _name, f, _val, CONFIG_TYPE_FLOAT)
+#define CONF_DOUBLE_VAR(_idx, _sec, _name, _val) \
+ [CONFIG_##_idx] = CONF_VAR(_sec, _name, d, _val, CONFIG_TYPE_DOUBLE)
+#define CONF_STR_VAR(_idx, _sec, _name, _val) \
+ [CONFIG_##_idx] = CONF_VAR(_sec, _name, s, _val, CONFIG_TYPE_STRING)
+#define CONF_END() { .type = CONFIG_END }
+
+struct config_item default_configs[] = {
+ CONF_STR_VAR(COLORS_TOP, "colors", "top", "red, default"),
+ CONF_STR_VAR(COLORS_MEDIUM, "colors", "medium", "green, default"),
+ CONF_STR_VAR(COLORS_NORMAL, "colors", "normal", "lightgray, default"),
+ CONF_STR_VAR(COLORS_SELECTED, "colors", "selected", "white, lightgray"),
+ CONF_STR_VAR(COLORS_JUMP_ARROWS, "colors", "jump_arrows", "blue, default"),
+ CONF_STR_VAR(COLORS_ADDR, "colors", "addr", "magenta, default"),
+ CONF_STR_VAR(COLORS_ROOT, "colors", "root", "white, blue"),
+ CONF_BOOL_VAR(TUI_REPORT, "tui", "report", true),
+ CONF_BOOL_VAR(TUI_ANNOTATE, "tui", "annotate", true),
+ CONF_BOOL_VAR(TUI_TOP, "tui", "top", true),
+ CONF_STR_VAR(BUILDID_DIR, "buildid", "dir", "~/.debug"),
+ CONF_BOOL_VAR(ANNOTATE_HIDE_SRC_CODE, "annotate", "hide_src_code", false),
+ CONF_BOOL_VAR(ANNOTATE_USE_OFFSET, "annotate", "use_offset", true),
+ CONF_BOOL_VAR(ANNOTATE_JUMP_ARROWS, "annotate", "jump_arrows", true),
+ CONF_BOOL_VAR(ANNOTATE_SHOW_NR_JUMPS, "annotate", "show_nr_jumps", false),
+ CONF_BOOL_VAR(ANNOTATE_SHOW_LINENR, "annotate", "show_linenr", false),
+ CONF_BOOL_VAR(ANNOTATE_SHOW_TOTAL_PERIOD, "annotate", "show_total_period", false),
+ CONF_BOOL_VAR(GTK_ANNOTATE, "gtk", "annotate", false),
+ CONF_BOOL_VAR(GTK_REPORT, "gtk", "report", false),
+ CONF_BOOL_VAR(GTK_TOP, "gtk", "top", false),
+ CONF_BOOL_VAR(PAGER_CMD, "pager", "cmd", true),
+ CONF_BOOL_VAR(PAGER_REPORT, "pager", "report", true),
+ CONF_BOOL_VAR(PAGER_ANNOTATE, "pager", "annotate", true),
+ CONF_BOOL_VAR(PAGER_TOP, "pager", "top", true),
+ CONF_BOOL_VAR(PAGER_DIFF, "pager", "diff", true),
+ CONF_STR_VAR(HELP_FORMAT, "help", "format", "man"),
+ CONF_INT_VAR(HELP_AUTOCORRECT, "help", "autocorrect", 0),
+ CONF_STR_VAR(HIST_PERCENTAGE, "hist", "percentage", "absolute"),
+ CONF_BOOL_VAR(UI_SHOW_HEADERS, "ui", "show-headers", true),
+ CONF_STR_VAR(CALL_GRAPH_RECORD_MODE, "call-graph", "record-mode", "fp"),
+ CONF_LONG_VAR(CALL_GRAPH_DUMP_SIZE, "call-graph", "dump-size", 8192),
+ CONF_STR_VAR(CALL_GRAPH_PRINT_TYPE, "call-graph", "print-type", "graph"),
+ CONF_STR_VAR(CALL_GRAPH_ORDER, "call-graph", "order", "callee"),
+ CONF_STR_VAR(CALL_GRAPH_SORT_KEY, "call-graph", "sort-key", "function"),
+ CONF_DOUBLE_VAR(CALL_GRAPH_THRESHOLD, "call-graph", "threshold", 0.5),
+ CONF_LONG_VAR(CALL_GRAPH_PRINT_LIMIT, "call-graph", "print-limit", 0),
+ CONF_BOOL_VAR(REPORT_GROUP, "report", "group", true),
+ CONF_BOOL_VAR(REPORT_CHILDREN, "report", "children", true),
+ CONF_FLOAT_VAR(REPORT_PERCENT_LIMIT, "report", "percent-limit", 0),
+ CONF_U64_VAR(REPORT_QUEUE_SIZE, "report", "queue-size", 0),
+ CONF_BOOL_VAR(TOP_CHILDREN, "top", "children", true),
+ CONF_STR_VAR(MAN_VIEWER, "man", "viewer", "man"),
+ CONF_STR_VAR(KMEM_DEFAULT, "kmem", "default", "slab"),
+ CONF_END()
+};
+
static struct config_section *find_section(struct list_head *sections,
const char *section_name)
{
@@ -112,6 +255,78 @@ static int add_element(struct list_head *head,
return 0;
}
+static char *get_value(struct config_item *config)
+{
+ int ret = 0;
+ char *value;
+
+ if (config->type == CONFIG_TYPE_BOOL)
+ ret = asprintf(&value, "%s",
+ config->value.b ? "true" : "false");
+ else if (config->type == CONFIG_TYPE_INT)
+ ret = asprintf(&value, "%d", config->value.i);
+ else if (config->type == CONFIG_TYPE_LONG)
+ ret = asprintf(&value, "%u", config->value.l);
+ else if (config->type == CONFIG_TYPE_U64)
+ ret = asprintf(&value, "%"PRId64, config->value.ll);
+ else if (config->type == CONFIG_TYPE_FLOAT)
+ ret = asprintf(&value, "%f", config->value.f);
+ else if (config->type == CONFIG_TYPE_DOUBLE)
+ ret = asprintf(&value, "%f", config->value.d);
+ else
+ ret = asprintf(&value, "%s", config->value.s);
+
+ if (ret < 0)
+ return NULL;
+
+ return value;
+}
+
+static int show_all_config(struct list_head *sections)
+{
+ int i;
+ bool has_config;
+ struct config_section *section;
+ struct config_element *element;
+
+ for (i = 0; default_configs[i].type != CONFIG_END; i++) {
+ struct config_item *config = &default_configs[i];
+
+ find_config(sections, §ion, &element,
+ config->section, config->name);
+
+ if (!element) {
+ char *value = get_value(config);
+
+ printf("%s.%s=%s\n", config->section, config->name, value);
+ free(value);
+ } else
+ printf("%s.%s=%s\n", section->name,
+ element->name, element->value);
+ }
+
+ /* Print config variables the default configsets haven't */
+ list_for_each_entry(section, sections, list) {
+ list_for_each_entry(element, §ion->element_head, list) {
+ has_config = false;
+ for (i = 0; default_configs[i].type != CONFIG_END; i++) {
+ struct config_item *config = &default_configs[i];
+
+ if (!strcmp(config->section, section->name) &&
+ !strcmp(config->name, element->name)) {
+ has_config = true;
+ break;
+ }
+ }
+ if (!has_config)
+ printf("%s.%s=%s\n", section->name,
+ element->name, element->value);
+ }
+ }
+
+ return 0;
+}
+
static int collect_current_config(const char *var, const char *value,
void *spec_sections)
{
@@ -184,6 +399,9 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
struct list_head sections;
char *user_config = mkpath("%s/.perfconfig", getenv("HOME"));
+ set_option_flag(config_options, 'l', "list", PARSE_OPT_EXCLUSIVE);
+ set_option_flag(config_options, 'a', "list-all", PARSE_OPT_EXCLUSIVE);
+
argc = parse_options(argc, argv, config_options, config_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
@@ -204,10 +422,19 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
perf_config(collect_current_config, §ions);
switch (actions) {
+ case ACTION_LIST_ALL:
+ if (argc == 0) {
+ ret = show_all_config(§ions);
+ break;
+ }
+ /* fall through */
case ACTION_LIST:
if (argc) {
pr_err("Error: takes no arguments\n");
- parse_options_usage(config_usage, config_options, "l", 1);
+ if (actions == ACTION_LIST_ALL)
+ parse_options_usage(config_usage, config_options, "a", 1);
+ else
+ parse_options_usage(config_usage, config_options, "l", 1);
} else {
ret = show_config(§ions);
if (ret < 0) {
--
2.5.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH v15 4/9] perf config: Add a option 'skel' to perf-config
2016-02-10 17:51 [PATCHSET v15 0/9] perf config: Add several options into perf-config Taeung Song
` (2 preceding siblings ...)
2016-02-10 17:51 ` [PATCH v15 3/9] perf config: Add 'list-all' option to perf-config Taeung Song
@ 2016-02-10 17:51 ` Taeung Song
2016-02-10 17:51 ` [PATCH v15 5/9] perf config: Add --verbose option for showing config description Taeung Song
` (4 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Taeung Song @ 2016-02-10 17:51 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: linux-kernel, Jiri Olsa, Namhyung Kim, Ingo Molnar, Taeung Song
Produce an skeleton with the possible config variables so
that one could then use $EDITOR ~/.perfconfig or
$(sysconfdir)/perfconfigand go on setting the knobs.
For the syntax examples,
# perf config -k | --skel
Initialize the possible config variables on config file.
# perf config --skel > ~/.perfconfig
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
---
tools/perf/Documentation/perf-config.txt | 6 ++++++
tools/perf/builtin-config.c | 32 +++++++++++++++++++++++++++++++-
2 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt
index 955b342..987b828 100644
--- a/tools/perf/Documentation/perf-config.txt
+++ b/tools/perf/Documentation/perf-config.txt
@@ -11,6 +11,8 @@ SYNOPSIS
'perf config' [<file-option>] -l | --list
or
'perf config' [<file-option>] -a | --list-all
+or
+'perf config' [<file-option>] -k | --skel
DESCRIPTION
-----------
@@ -35,6 +37,10 @@ OPTIONS
--list-all::
Show current and all possible config variables with default values.
+-k::
+--skel::
+ Produce an skeleton with the possible config variables.
+
CONFIGURATION FILE
------------------
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
index 8a63119..6ab53b2 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -22,7 +22,8 @@ static const char * const config_usage[] = {
enum actions {
ACTION_LIST = 1,
- ACTION_LIST_ALL
+ ACTION_LIST_ALL,
+ ACTION_SKEL
} actions;
static struct option config_options[] = {
@@ -31,6 +32,9 @@ static struct option config_options[] = {
OPT_SET_UINT('a', "list-all", &actions,
"show current and all possible config"
" variables with default values", ACTION_LIST_ALL),
+ OPT_SET_UINT('k', "skel", &actions,
+ "produce an skeleton with the possible"
+ " config variables", ACTION_SKEL),
OPT_BOOLEAN(0, "system", &use_system_config, "use system config file"),
OPT_BOOLEAN(0, "user", &use_user_config, "use user config file"),
OPT_END()
@@ -282,6 +286,26 @@ static char *get_value(struct config_item *config)
return value;
}
+static int show_skel_config(void)
+{
+ int i;
+ const char *section = "";
+
+ for (i = 0; default_configs[i].type != CONFIG_END; i++) {
+ struct config_item *config = &default_configs[i];
+ char *value = get_value(config);
+
+ if (strcmp(section, config->section) != 0) {
+ section = config->section;
+ printf("\n[%s]\n", config->section);
+ }
+ printf("\t%s = %s\n", config->name, value);
+ free(value);
+ }
+
+ return 0;
+}
+
static int show_all_config(struct list_head *sections)
{
int i;
@@ -422,6 +446,12 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
perf_config(collect_current_config, §ions);
switch (actions) {
+ case ACTION_SKEL:
+ if (argc)
+ parse_options_usage(config_usage, config_options, "k", 1);
+ else
+ ret = show_skel_config();
+ break;
case ACTION_LIST_ALL:
if (argc == 0) {
ret = show_all_config(§ions);
--
2.5.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH v15 5/9] perf config: Add --verbose option for showing config description
2016-02-10 17:51 [PATCHSET v15 0/9] perf config: Add several options into perf-config Taeung Song
` (3 preceding siblings ...)
2016-02-10 17:51 ` [PATCH v15 4/9] perf config: Add a option 'skel' " Taeung Song
@ 2016-02-10 17:51 ` Taeung Song
2016-02-10 17:51 ` [PATCH v15 6/9] perf config: Add 'get' functionality Taeung Song
` (3 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Taeung Song @ 2016-02-10 17:51 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: linux-kernel, Jiri Olsa, Namhyung Kim, Ingo Molnar, Taeung Song
To explain what each of variable options configures,
this option can be used with 'skel', 'list' and
'list-all' options, i.e.
print the possible config variables with comments over each of them.
# perf config -vk | --verbose --skel
or
print all or current config variables with descriptions
# perf config -vl | --verbose --list
# perf config -va | --verbose --list-all
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
---
tools/perf/Documentation/perf-config.txt | 4 +
tools/perf/builtin-config.c | 186 +++++++++++++++++++++----------
2 files changed, 130 insertions(+), 60 deletions(-)
diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt
index 987b828..fb74fea 100644
--- a/tools/perf/Documentation/perf-config.txt
+++ b/tools/perf/Documentation/perf-config.txt
@@ -41,6 +41,10 @@ OPTIONS
--skel::
Produce an skeleton with the possible config variables.
+-v::
+--verbose::
+ Be more verbose. (show config description)
+
CONFIGURATION FILE
------------------
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
index 6ab53b2..68d5014 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -35,6 +35,8 @@ static struct option config_options[] = {
OPT_SET_UINT('k', "skel", &actions,
"produce an skeleton with the possible"
" config variables", ACTION_SKEL),
+ OPT_INCR('v', "verbose", &verbose, "Be more verbose"
+ " (show config description)"),
OPT_BOOLEAN(0, "system", &use_system_config, "use system config file"),
OPT_BOOLEAN(0, "user", &use_user_config, "use user config file"),
OPT_END()
@@ -111,71 +113,117 @@ struct config_item {
const char *s;
} value;
enum config_type type;
+ const char *desc;
};
-#define CONF_VAR(_sec, _name, _field, _val, _type) \
- { .section = _sec, .name = _name, .value._field = _val, .type = _type }
-
-#define CONF_BOOL_VAR(_idx, _sec, _name, _val) \
- [CONFIG_##_idx] = CONF_VAR(_sec, _name, b, _val, CONFIG_TYPE_BOOL)
-#define CONF_INT_VAR(_idx, _sec, _name, _val) \
- [CONFIG_##_idx] = CONF_VAR(_sec, _name, i, _val, CONFIG_TYPE_INT)
-#define CONF_LONG_VAR(_idx, _sec, _name, _val) \
- [CONFIG_##_idx] = CONF_VAR(_sec, _name, l, _val, CONFIG_TYPE_LONG)
-#define CONF_U64_VAR(_idx, _sec, _name, _val) \
- [CONFIG_##_idx] = CONF_VAR(_sec, _name, ll, _val, CONFIG_TYPE_U64)
-#define CONF_FLOAT_VAR(_idx, _sec, _name, _val) \
- [CONFIG_##_idx] = CONF_VAR(_sec, _name, f, _val, CONFIG_TYPE_FLOAT)
-#define CONF_DOUBLE_VAR(_idx, _sec, _name, _val) \
- [CONFIG_##_idx] = CONF_VAR(_sec, _name, d, _val, CONFIG_TYPE_DOUBLE)
-#define CONF_STR_VAR(_idx, _sec, _name, _val) \
- [CONFIG_##_idx] = CONF_VAR(_sec, _name, s, _val, CONFIG_TYPE_STRING)
+#define CONF_VAR(_sec, _name, _field, _val, _type, _desc) \
+ { .section = _sec, .name = _name, .value._field = _val, .type = _type, .desc = _desc}
+
+#define CONF_BOOL_VAR(_idx, _sec, _name, _val, _desc) \
+ [CONFIG_##_idx] = CONF_VAR(_sec, _name, b, _val, CONFIG_TYPE_BOOL, _desc)
+#define CONF_INT_VAR(_idx, _sec, _name, _val, _desc) \
+ [CONFIG_##_idx] = CONF_VAR(_sec, _name, i, _val, CONFIG_TYPE_INT, _desc)
+#define CONF_LONG_VAR(_idx, _sec, _name, _val, _desc) \
+ [CONFIG_##_idx] = CONF_VAR(_sec, _name, l, _val, CONFIG_TYPE_LONG, _desc)
+#define CONF_U64_VAR(_idx, _sec, _name, _val, _desc) \
+ [CONFIG_##_idx] = CONF_VAR(_sec, _name, ll, _val, CONFIG_TYPE_U64, _desc)
+#define CONF_FLOAT_VAR(_idx, _sec, _name, _val, _desc) \
+ [CONFIG_##_idx] = CONF_VAR(_sec, _name, f, _val, CONFIG_TYPE_FLOAT, _desc)
+#define CONF_DOUBLE_VAR(_idx, _sec, _name, _val, _desc) \
+ [CONFIG_##_idx] = CONF_VAR(_sec, _name, d, _val, CONFIG_TYPE_DOUBLE, _desc)
+#define CONF_STR_VAR(_idx, _sec, _name, _val, _desc) \
+ [CONFIG_##_idx] = CONF_VAR(_sec, _name, s, _val, CONFIG_TYPE_STRING, _desc)
#define CONF_END() { .type = CONFIG_END }
struct config_item default_configs[] = {
- CONF_STR_VAR(COLORS_TOP, "colors", "top", "red, default"),
- CONF_STR_VAR(COLORS_MEDIUM, "colors", "medium", "green, default"),
- CONF_STR_VAR(COLORS_NORMAL, "colors", "normal", "lightgray, default"),
- CONF_STR_VAR(COLORS_SELECTED, "colors", "selected", "white, lightgray"),
- CONF_STR_VAR(COLORS_JUMP_ARROWS, "colors", "jump_arrows", "blue, default"),
- CONF_STR_VAR(COLORS_ADDR, "colors", "addr", "magenta, default"),
- CONF_STR_VAR(COLORS_ROOT, "colors", "root", "white, blue"),
- CONF_BOOL_VAR(TUI_REPORT, "tui", "report", true),
- CONF_BOOL_VAR(TUI_ANNOTATE, "tui", "annotate", true),
- CONF_BOOL_VAR(TUI_TOP, "tui", "top", true),
- CONF_STR_VAR(BUILDID_DIR, "buildid", "dir", "~/.debug"),
- CONF_BOOL_VAR(ANNOTATE_HIDE_SRC_CODE, "annotate", "hide_src_code", false),
- CONF_BOOL_VAR(ANNOTATE_USE_OFFSET, "annotate", "use_offset", true),
- CONF_BOOL_VAR(ANNOTATE_JUMP_ARROWS, "annotate", "jump_arrows", true),
- CONF_BOOL_VAR(ANNOTATE_SHOW_NR_JUMPS, "annotate", "show_nr_jumps", false),
- CONF_BOOL_VAR(ANNOTATE_SHOW_LINENR, "annotate", "show_linenr", false),
- CONF_BOOL_VAR(ANNOTATE_SHOW_TOTAL_PERIOD, "annotate", "show_total_period", false),
- CONF_BOOL_VAR(GTK_ANNOTATE, "gtk", "annotate", false),
- CONF_BOOL_VAR(GTK_REPORT, "gtk", "report", false),
- CONF_BOOL_VAR(GTK_TOP, "gtk", "top", false),
- CONF_BOOL_VAR(PAGER_CMD, "pager", "cmd", true),
- CONF_BOOL_VAR(PAGER_REPORT, "pager", "report", true),
- CONF_BOOL_VAR(PAGER_ANNOTATE, "pager", "annotate", true),
- CONF_BOOL_VAR(PAGER_TOP, "pager", "top", true),
- CONF_BOOL_VAR(PAGER_DIFF, "pager", "diff", true),
- CONF_STR_VAR(HELP_FORMAT, "help", "format", "man"),
- CONF_INT_VAR(HELP_AUTOCORRECT, "help", "autocorrect", 0),
- CONF_STR_VAR(HIST_PERCENTAGE, "hist", "percentage", "absolute"),
- CONF_BOOL_VAR(UI_SHOW_HEADERS, "ui", "show-headers", true),
- CONF_STR_VAR(CALL_GRAPH_RECORD_MODE, "call-graph", "record-mode", "fp"),
- CONF_LONG_VAR(CALL_GRAPH_DUMP_SIZE, "call-graph", "dump-size", 8192),
- CONF_STR_VAR(CALL_GRAPH_PRINT_TYPE, "call-graph", "print-type", "graph"),
- CONF_STR_VAR(CALL_GRAPH_ORDER, "call-graph", "order", "callee"),
- CONF_STR_VAR(CALL_GRAPH_SORT_KEY, "call-graph", "sort-key", "function"),
- CONF_DOUBLE_VAR(CALL_GRAPH_THRESHOLD, "call-graph", "threshold", 0.5),
- CONF_LONG_VAR(CALL_GRAPH_PRINT_LIMIT, "call-graph", "print-limit", 0),
- CONF_BOOL_VAR(REPORT_GROUP, "report", "group", true),
- CONF_BOOL_VAR(REPORT_CHILDREN, "report", "children", true),
- CONF_FLOAT_VAR(REPORT_PERCENT_LIMIT, "report", "percent-limit", 0),
- CONF_U64_VAR(REPORT_QUEUE_SIZE, "report", "queue-size", 0),
- CONF_BOOL_VAR(TOP_CHILDREN, "top", "children", true),
- CONF_STR_VAR(MAN_VIEWER, "man", "viewer", "man"),
- CONF_STR_VAR(KMEM_DEFAULT, "kmem", "default", "slab"),
+ CONF_STR_VAR(COLORS_TOP, "colors", "top", "red, default",
+ "A overhead percentage which is more than 5%"),
+ CONF_STR_VAR(COLORS_MEDIUM, "colors", "medium", "green, default",
+ "A overhead percentage which has more than 0.5%"),
+ CONF_STR_VAR(COLORS_NORMAL, "colors", "normal", "lightgray, default",
+ "The rest of overhead percentages"),
+ CONF_STR_VAR(COLORS_SELECTED, "colors", "selected", "white, lightgray",
+ "The current entry in a list of entries on TUI"),
+ CONF_STR_VAR(COLORS_JUMP_ARROWS, "colors", "jump_arrows", "blue, default",
+ "Arrows and lines in jumps on assembly code listings"),
+ CONF_STR_VAR(COLORS_ADDR, "colors", "addr", "magenta, default",
+ "Addresses from 'annotate"),
+ CONF_STR_VAR(COLORS_ROOT, "colors", "root", "white, blue",
+ "Headers in the output of a sub-command 'top'"),
+ CONF_BOOL_VAR(TUI_REPORT, "tui", "report", true,
+ "TUI can be enabled or not"),
+ CONF_BOOL_VAR(TUI_ANNOTATE, "tui", "annotate", true,
+ "TUI can be enabled or not"),
+ CONF_BOOL_VAR(TUI_TOP, "tui", "top", true,
+ "TUI can be enabled or not"),
+ CONF_STR_VAR(BUILDID_DIR, "buildid", "dir", "~/.debug",
+ "The directory location of binaries, shared libraries,"
+ " /proc/kallsyms and /proc/kcore files to be used"
+ " at analysis time"),
+ CONF_BOOL_VAR(ANNOTATE_HIDE_SRC_CODE, "annotate", "hide_src_code", false,
+ "Print a list of assembly code without the source code or not"),
+ CONF_BOOL_VAR(ANNOTATE_USE_OFFSET, "annotate", "use_offset", true,
+ "Addresses subtracted from a base address can be printed"),
+ CONF_BOOL_VAR(ANNOTATE_JUMP_ARROWS, "annotate", "jump_arrows", true,
+ "Arrows for jump instruction can be printed or not"),
+ CONF_BOOL_VAR(ANNOTATE_SHOW_NR_JUMPS, "annotate", "show_nr_jumps", false,
+ "The number of branches branching to that address can be printed"),
+ CONF_BOOL_VAR(ANNOTATE_SHOW_LINENR, "annotate", "show_linenr", false,
+ "Show line numbers"),
+ CONF_BOOL_VAR(ANNOTATE_SHOW_TOTAL_PERIOD, "annotate", "show_total_period", false,
+ "Show a column with the sum of periods"),
+ CONF_BOOL_VAR(GTK_ANNOTATE, "gtk", "annotate", false,
+ "GTK can be enabled or not"),
+ CONF_BOOL_VAR(GTK_REPORT, "gtk", "report", false,
+ "GTK can be enabled or not"),
+ CONF_BOOL_VAR(GTK_TOP, "gtk", "top", false,
+ "GTK can be enabled or not"),
+ CONF_BOOL_VAR(PAGER_CMD, "pager", "cmd", true,
+ "As stdio instead of TUI"),
+ CONF_BOOL_VAR(PAGER_REPORT, "pager", "report", true,
+ "As stdio instead of TUI"),
+ CONF_BOOL_VAR(PAGER_ANNOTATE, "pager", "annotate", true,
+ "As stdio instead of TUI"),
+ CONF_BOOL_VAR(PAGER_TOP, "pager", "top", true,
+ "As stdio instead of TUI"),
+ CONF_BOOL_VAR(PAGER_DIFF, "pager", "diff", true,
+ "As stdio instead of TUI"),
+ CONF_STR_VAR(HELP_FORMAT, "help", "format", "man", "A format of manual page"),
+ CONF_INT_VAR(HELP_AUTOCORRECT, "help", "autocorrect", 0,
+ "Automatically correct and execute mistyped commands after"
+ " waiting for the given number of deciseconds"),
+ CONF_STR_VAR(HIST_PERCENTAGE, "hist", "percentage", "absolute",
+ "Control a way to calcurate overhead of filtered entries"),
+ CONF_BOOL_VAR(UI_SHOW_HEADERS, "ui", "show-headers", true,
+ "Show or hide columns as header on TUI"),
+ CONF_STR_VAR(CALL_GRAPH_RECORD_MODE, "call-graph", "record-mode", "fp",
+ "The mode can be 'fp' (frame pointer) and 'dwarf'"),
+ CONF_LONG_VAR(CALL_GRAPH_DUMP_SIZE, "call-graph", "dump-size", 8192,
+ "The size of stack to dump in order to do post-unwinding"),
+ CONF_STR_VAR(CALL_GRAPH_PRINT_TYPE, "call-graph", "print-type", "graph",
+ "The type can be graph (graph absolute), fractal (graph relative), fla"),
+ CONF_STR_VAR(CALL_GRAPH_ORDER, "call-graph", "order", "callee",
+ "Controls print order of callchains (callee or caller)"),
+ CONF_STR_VAR(CALL_GRAPH_SORT_KEY, "call-graph", "sort-key", "function",
+ "It can be 'function' or 'address'"),
+ CONF_DOUBLE_VAR(CALL_GRAPH_THRESHOLD, "call-graph", "threshold", 0.5,
+ "Small callchains can be omitted under a certain overhead (threshold)"),
+ CONF_LONG_VAR(CALL_GRAPH_PRINT_LIMIT, "call-graph", "print-limit", 0,
+ "Control the number of callchains printed for a single entry"),
+ CONF_BOOL_VAR(REPORT_GROUP, "report", "group", true,
+ "Show event group information together"),
+ CONF_BOOL_VAR(REPORT_CHILDREN, "report", "children", true,
+ "Accumulate callchain of children and show total overhead or not"),
+ CONF_FLOAT_VAR(REPORT_PERCENT_LIMIT, "report", "percent-limit", 0,
+ "Entries have overhead lower than this percentage will not be printed"),
+ CONF_U64_VAR(REPORT_QUEUE_SIZE, "report", "queue-size", 0,
+ "The maximum allocation size for session's ordered events queue"),
+ CONF_BOOL_VAR(TOP_CHILDREN, "top", "children", true,
+ "Similar as report.children"),
+ CONF_STR_VAR(MAN_VIEWER, "man", "viewer", "man",
+ "Select manual tools that work a sub-command 'help'"),
+ CONF_STR_VAR(KMEM_DEFAULT, "kmem", "default", "slab",
+ "Which allocator is analyzed between 'slab' and 'page"),
CONF_END()
};
@@ -299,6 +347,8 @@ static int show_skel_config(void)
section = config->section;
printf("\n[%s]\n", config->section);
}
+ if (verbose)
+ printf("\t# %s\n", config->desc);
printf("\t%s = %s\n", config->name, value);
free(value);
}
@@ -319,6 +369,9 @@ static int show_all_config(struct list_head *sections)
find_config(sections, §ion, &element,
config->section, config->name);
+ if (verbose)
+ printf("\n# %s\n", config->desc);
+
if (!element) {
char *value = get_value(config);
@@ -402,6 +455,7 @@ out_err:
static int show_config(struct list_head *sections)
{
+ int i;
struct config_section *section;
struct config_element *element;
@@ -409,6 +463,18 @@ static int show_config(struct list_head *sections)
return -1;
list_for_each_entry(section, sections, list) {
list_for_each_entry(element, §ion->element_head, list) {
+ if (verbose) {
+ for (i = 0; default_configs[i].type != CONFIG_END; i++) {
+ struct config_item *config = &default_configs[i];
+
+ if (!strcmp(config->section, section->name) &&
+ !strcmp(config->name, element->name)) {
+ printf("\n# %s\n", config->desc);
+ break;
+ }
+ }
+ }
+
printf("%s.%s=%s\n", section->name,
element->name, element->value);
}
--
2.5.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH v15 6/9] perf config: Add 'get' functionality
2016-02-10 17:51 [PATCHSET v15 0/9] perf config: Add several options into perf-config Taeung Song
` (4 preceding siblings ...)
2016-02-10 17:51 ` [PATCH v15 5/9] perf config: Add --verbose option for showing config description Taeung Song
@ 2016-02-10 17:51 ` Taeung Song
2016-02-10 17:51 ` [PATCH v15 7/9] perf config: Add 'set' feature Taeung Song
` (2 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Taeung Song @ 2016-02-10 17:51 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: linux-kernel, Jiri Olsa, Namhyung Kim, Ingo Molnar, Taeung Song
This patch consists of functions
which can get specific config variables.
For the syntax examples,
perf config [<file-option>] [section.name ...]
display key-value pairs of specific config variables
# perf config report.queue-size report.children
In addition, the functionality can work with --verbose option
to show the config description, i.e.
# perf config -v report.queue-size
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
---
tools/perf/Documentation/perf-config.txt | 2 +
tools/perf/builtin-config.c | 87 ++++++++++++++++++++++++++++++--
tools/perf/util/cache.h | 1 +
3 files changed, 86 insertions(+), 4 deletions(-)
diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt
index fb74fea..c4923da 100644
--- a/tools/perf/Documentation/perf-config.txt
+++ b/tools/perf/Documentation/perf-config.txt
@@ -8,6 +8,8 @@ perf-config - Get and set variables in a configuration file.
SYNOPSIS
--------
[verse]
+'perf config' [<file-option>] [section.name ...]
+or
'perf config' [<file-option>] -l | --list
or
'perf config' [<file-option>] -a | --list-all
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
index 68d5014..ad7fb79 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -16,7 +16,7 @@
static bool use_system_config, use_user_config;
static const char * const config_usage[] = {
- "perf config [<file-option>] [options]",
+ "perf config [<file-option>] [options] [section.name ...]",
NULL
};
@@ -404,6 +404,44 @@ static int show_all_config(struct list_head *sections)
return 0;
}
+static int show_spec_config(struct list_head *sections,
+ const char *section_name, const char *name)
+{
+ int i;
+ struct config_section *section = NULL;
+ struct config_element *element = NULL;
+
+ find_config(sections, §ion, &element, section_name, name);
+
+ for (i = 0; default_configs[i].type != CONFIG_END; i++) {
+ struct config_item *config = &default_configs[i];
+
+ if (!strcmp(config->section, section_name) &&
+ !strcmp(config->name, name)) {
+ char *value = get_value(config);
+
+ if (verbose)
+ printf("# %s\n", config->desc);
+ printf("%s.%s", config->section, config->name);
+ if (!section && !element)
+ printf("=%s (default)", value);
+ else
+ printf("=%s", element->value);
+ printf("\n");
+ free(value);
+ return 0;
+ }
+ }
+
+ if (section && element) {
+ printf("%s.%s=%s\n", section->name,
+ element->name, element->value);
+ return 0;
+ }
+
+ return -1;
+}
+
static int collect_current_config(const char *var, const char *value,
void *spec_sections)
{
@@ -453,6 +491,43 @@ out_err:
return ret;
}
+static int perf_configset_with_option(configset_fn_t fn, struct list_head *sections,
+ const char *var)
+{
+ int ret = -1;
+ char *ptr, *key;
+ const char *last_dot;
+ char *section_name, *name;
+
+ key = ptr = strdup(var);
+ if (!key) {
+ pr_err("%s: strdup failed\n", __func__);
+ return -1;
+ }
+ last_dot = strchr(key, '.');
+ /*
+ * Since "key" actually contains the section name and the real
+ * key name separated by a dot, we have to know where the dot is.
+ */
+ if (last_dot == NULL || last_dot == key) {
+ pr_err("The config variable does not contain a section: %s\n", key);
+ goto out_err;
+ }
+ if (!last_dot[1]) {
+ pr_err("The config varible does not contain variable name: %s\n", key);
+ goto out_err;
+ }
+
+ section_name = strsep(&ptr, ".");
+ name = ptr;
+ fn(sections, section_name, name);
+ ret = 0;
+
+out_err:
+ free(key);
+ return ret;
+}
+
static int show_config(struct list_head *sections)
{
int i;
@@ -485,7 +560,7 @@ static int show_config(struct list_head *sections)
int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
{
- int ret = 0;
+ int i, ret = 0;
struct list_head sections;
char *user_config = mkpath("%s/.perfconfig", getenv("HOME"));
@@ -523,7 +598,6 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
ret = show_all_config(§ions);
break;
}
- /* fall through */
case ACTION_LIST:
if (argc) {
pr_err("Error: takes no arguments\n");
@@ -543,7 +617,12 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
}
break;
default:
- usage_with_options(config_usage, config_options);
+ if (argc)
+ for (i = 0; argv[i]; i++)
+ ret = perf_configset_with_option(show_spec_config, §ions,
+ argv[i]);
+ else
+ usage_with_options(config_usage, config_options);
}
return ret;
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 92cd739..d5dcc85 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -39,6 +39,7 @@ struct config_section {
extern const char *config_exclusive_filename;
typedef int (*config_fn_t)(const char *, const char *, void *);
+typedef int (*configset_fn_t)(struct list_head *, const char *, const char *);
extern int perf_default_config(const char *, const char *, void *);
extern int perf_config(config_fn_t fn, void *);
extern int perf_config_int(const char *, const char *);
--
2.5.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH v15 7/9] perf config: Add 'set' feature
2016-02-10 17:51 [PATCHSET v15 0/9] perf config: Add several options into perf-config Taeung Song
` (5 preceding siblings ...)
2016-02-10 17:51 ` [PATCH v15 6/9] perf config: Add 'get' functionality Taeung Song
@ 2016-02-10 17:51 ` Taeung Song
2016-02-10 17:51 ` [PATCH v15 8/9] perf config: normalize a value depending on default type of it Taeung Song
2016-02-10 17:51 ` [PATCH v15 9/9] perf config: Add a option 'remove' to perf-config Taeung Song
8 siblings, 0 replies; 11+ messages in thread
From: Taeung Song @ 2016-02-10 17:51 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: linux-kernel, Jiri Olsa, Namhyung Kim, Ingo Molnar, Taeung Song
This patch consists of functions
which can set specific config variables.
For the syntax examples,
perf config [<file-option>] [options] [section.name[=value] ...]
set specific config variables
# perf config report.queue-size=100M report.children=true
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
---
tools/perf/Documentation/perf-config.txt | 2 +-
tools/perf/builtin-config.c | 122 +++++++++++++++++++++++++------
tools/perf/util/cache.h | 5 +-
tools/perf/util/config.c | 27 ++++++-
4 files changed, 131 insertions(+), 25 deletions(-)
diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt
index c4923da..0e0482c 100644
--- a/tools/perf/Documentation/perf-config.txt
+++ b/tools/perf/Documentation/perf-config.txt
@@ -8,7 +8,7 @@ perf-config - Get and set variables in a configuration file.
SYNOPSIS
--------
[verse]
-'perf config' [<file-option>] [section.name ...]
+'perf config' [<file-option>] [section.name[=value] ...]
or
'perf config' [<file-option>] -l | --list
or
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
index ad7fb79..ad50cf5 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -16,7 +16,7 @@
static bool use_system_config, use_user_config;
static const char * const config_usage[] = {
- "perf config [<file-option>] [options] [section.name ...]",
+ "perf config [<file-option>] [options] [section.name[=value] ...]",
NULL
};
@@ -405,7 +405,9 @@ static int show_all_config(struct list_head *sections)
}
static int show_spec_config(struct list_head *sections,
- const char *section_name, const char *name)
+ const char *config_file_name __maybe_unused,
+ const char *section_name, const char *name,
+ char *value)
{
int i;
struct config_section *section = NULL;
@@ -418,7 +420,7 @@ static int show_spec_config(struct list_head *sections,
if (!strcmp(config->section, section_name) &&
!strcmp(config->name, name)) {
- char *value = get_value(config);
+ value = get_value(config);
if (verbose)
printf("# %s\n", config->desc);
@@ -442,6 +444,39 @@ static int show_spec_config(struct list_head *sections,
return -1;
}
+static int set_config(struct list_head *sections, const char *config_file_name,
+ const char *section_name, const char *name, char *value)
+{
+ struct config_section *section = NULL;
+ struct config_element *element = NULL;
+
+ find_config(sections, §ion, &element, section_name, name);
+ if (value != NULL) {
+ value = strdup(value);
+ if (!value) {
+ pr_err("%s: strdup failed\n", __func__);
+ return -1;
+ }
+
+ /* if there isn't existent section, add a new section */
+ if (!section) {
+ section = init_section(section_name);
+ if (!section)
+ return -1;
+ list_add_tail(§ion->list, sections);
+ }
+ /* if nothing to replace, add a new element which contains key-value pair. */
+ if (!element) {
+ add_element(§ion->element_head, name, value);
+ } else {
+ free(element->value);
+ element->value = value;
+ }
+ }
+
+ return perf_configset_write_in_full(sections, config_file_name);
+}
+
static int collect_current_config(const char *var, const char *value,
void *spec_sections)
{
@@ -491,8 +526,10 @@ out_err:
return ret;
}
-static int perf_configset_with_option(configset_fn_t fn, struct list_head *sections,
- const char *var)
+static int perf_configset_with_option(configset_fn_t fn,
+ struct list_head *sections,
+ const char *config_file_name,
+ const char *var, char *value)
{
int ret = -1;
char *ptr, *key;
@@ -519,10 +556,24 @@ static int perf_configset_with_option(configset_fn_t fn, struct list_head *secti
}
section_name = strsep(&ptr, ".");
- name = ptr;
- fn(sections, section_name, name);
- ret = 0;
+ name = strsep(&ptr, "=");
+ if (!value) {
+ /* do nothing */
+ } else if (!strcmp(value, "=")) {
+ pr_err("The config variable does not contain a value: %s.%s\n",
+ section_name, name);
+ goto out_err;
+ } else {
+ value++;
+ name = strsep(&name, "=");
+ if (name[0] == '\0') {
+ pr_err("invalid key: %s\n", var);
+ goto out_err;
+ }
+ }
+ fn(sections, config_file_name, section_name, name, value);
+ ret = 0;
out_err:
free(key);
return ret;
@@ -561,7 +612,9 @@ static int show_config(struct list_head *sections)
int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
{
int i, ret = 0;
- struct list_head sections;
+ struct list_head *sections;
+ struct list_head all_sections, user_sections, system_sections;
+ const char *system_config = perf_etc_perfconfig();
char *user_config = mkpath("%s/.perfconfig", getenv("HOME"));
set_option_flag(config_options, 'l', "list", PARSE_OPT_EXCLUSIVE);
@@ -577,14 +630,22 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
return -1;
}
- INIT_LIST_HEAD(§ions);
+ INIT_LIST_HEAD(&user_sections);
+ INIT_LIST_HEAD(&system_sections);
+ perf_config_from_file(collect_current_config, user_config, &user_sections);
+ perf_config_from_file(collect_current_config, system_config, &system_sections);
- if (use_system_config)
- config_exclusive_filename = perf_etc_perfconfig();
- else if (use_user_config)
+ if (use_system_config) {
+ sections = &system_sections;
+ config_exclusive_filename = system_config;
+ } else if (use_user_config) {
+ sections = &user_sections;
config_exclusive_filename = user_config;
-
- perf_config(collect_current_config, §ions);
+ } else {
+ sections = &all_sections;
+ INIT_LIST_HEAD(&all_sections);
+ perf_config(collect_current_config, &all_sections);
+ }
switch (actions) {
case ACTION_SKEL:
@@ -595,7 +656,7 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
break;
case ACTION_LIST_ALL:
if (argc == 0) {
- ret = show_all_config(§ions);
+ ret = show_all_config(sections);
break;
}
case ACTION_LIST:
@@ -606,7 +667,7 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
else
parse_options_usage(config_usage, config_options, "l", 1);
} else {
- ret = show_config(§ions);
+ ret = show_config(sections);
if (ret < 0) {
const char * config_filename = config_exclusive_filename;
if (!config_exclusive_filename)
@@ -617,11 +678,28 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
}
break;
default:
- if (argc)
- for (i = 0; argv[i]; i++)
- ret = perf_configset_with_option(show_spec_config, §ions,
- argv[i]);
- else
+ if (argc) {
+ for (i = 0; argv[i]; i++) {
+ char *value = strchr(argv[i], '=');
+
+ if (value == NULL)
+ ret = perf_configset_with_option(show_spec_config,
+ sections, NULL,
+ argv[i], value);
+ else {
+ if (!use_system_config && !use_user_config)
+ ret = perf_configset_with_option(set_config,
+ &user_sections,
+ user_config,
+ argv[i], value);
+ else
+ ret = perf_configset_with_option(set_config,
+ sections,
+ config_exclusive_filename,
+ argv[i], value);
+ }
+ }
+ } else
usage_with_options(config_usage, config_options);
}
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index d5dcc85..9614afd 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -39,9 +39,12 @@ struct config_section {
extern const char *config_exclusive_filename;
typedef int (*config_fn_t)(const char *, const char *, void *);
-typedef int (*configset_fn_t)(struct list_head *, const char *, const char *);
+typedef int (*configset_fn_t)(struct list_head *, const char *,
+ const char *, const char *, char *);
+extern int perf_configset_write_in_full(struct list_head *sections, const char *file_name);
extern int perf_default_config(const char *, const char *, void *);
extern int perf_config(config_fn_t fn, void *);
+extern int perf_config_from_file(config_fn_t fn, const char *filename, void *data);
extern int perf_config_int(const char *, const char *);
extern u64 perf_config_u64(const char *, const char *);
extern int perf_config_bool(const char *, const char *);
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 4e72763..34eff22 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -416,7 +416,7 @@ int perf_default_config(const char *var, const char *value,
return 0;
}
-static int perf_config_from_file(config_fn_t fn, const char *filename, void *data)
+int perf_config_from_file(config_fn_t fn, const char *filename, void *data)
{
int ret;
FILE *f = fopen(filename, "r");
@@ -506,6 +506,31 @@ out:
return ret;
}
+int perf_configset_write_in_full(struct list_head *sections, const char *file_name)
+{
+ struct config_section *section;
+ struct config_element *element;
+ const char *first_line = "# this file is auto-generated.";
+ FILE *fp = fopen(file_name, "w");
+
+ if (!fp)
+ return -1;
+
+ fprintf(fp, "%s\n", first_line);
+ /* overwrite configvariables */
+ list_for_each_entry(section, sections, list) {
+ fprintf(fp, "[%s]\n", section->name);
+ list_for_each_entry(element, §ion->element_head, list) {
+ if (element->value)
+ fprintf(fp, "\t%s = %s\n",
+ element->name, element->value);
+ }
+ }
+ fclose(fp);
+
+ return 0;
+}
+
/*
* Call this to report error for your variable that should not
* get a boolean value (i.e. "[my] var" means "true").
--
2.5.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH v15 8/9] perf config: normalize a value depending on default type of it
2016-02-10 17:51 [PATCHSET v15 0/9] perf config: Add several options into perf-config Taeung Song
` (6 preceding siblings ...)
2016-02-10 17:51 ` [PATCH v15 7/9] perf config: Add 'set' feature Taeung Song
@ 2016-02-10 17:51 ` Taeung Song
2016-02-10 17:51 ` [PATCH v15 9/9] perf config: Add a option 'remove' to perf-config Taeung Song
8 siblings, 0 replies; 11+ messages in thread
From: Taeung Song @ 2016-02-10 17:51 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: linux-kernel, Jiri Olsa, Namhyung Kim, Ingo Molnar, Taeung Song
Whether or not user mis-type wrong data type to set config,
normalize the value. If a config user enter isn't contained
in default configs, just pass as it is.
For the examples,
# perf config report.queue-size=1M
# perf config report.queue-size
report.queue-size=1048576
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
---
tools/perf/builtin-config.c | 54 ++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 49 insertions(+), 5 deletions(-)
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
index ad50cf5..92ff842 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -444,6 +444,54 @@ static int show_spec_config(struct list_head *sections,
return -1;
}
+static char *normalize_value(const char *section_name, const char *name, const char *value)
+{
+ int i, ret = 0;
+ char *endptr;
+ char key[BUFSIZ];
+ char *normalized;
+
+ scnprintf(key, sizeof(key), "%s.%s", section_name, name);
+ for (i = 0; default_configs[i].type != CONFIG_END; i++) {
+ struct config_item *config = &default_configs[i];
+
+ if (!strcmp(config->section, section_name) &&
+ !strcmp(config->name, name)) {
+ if (config->type == CONFIG_TYPE_BOOL)
+ ret = asprintf(&normalized, "%s",
+ perf_config_bool(key, value) ? "true" : "false");
+ else if (config->type == CONFIG_TYPE_INT ||
+ config->type == CONFIG_TYPE_LONG)
+ ret = asprintf(&normalized, "%d",
+ perf_config_int(key, value));
+ else if (config->type == CONFIG_TYPE_U64)
+ ret = asprintf(&normalized, "%"PRId64,
+ perf_config_u64(key, value));
+ else if (config->type == CONFIG_TYPE_FLOAT)
+ ret = asprintf(&normalized, "%f",
+ strtof(value, &endptr));
+ else if (config->type == CONFIG_TYPE_DOUBLE)
+ ret = asprintf(&normalized, "%f",
+ strtod(value, &endptr));
+ else
+ ret = asprintf(&normalized, "%s", value);
+
+ if (ret < 0)
+ return NULL;
+
+ return normalized;
+ }
+ }
+
+ normalized = strdup(value);
+ if (!normalized) {
+ pr_err("%s: strdup failed\n", __func__);
+ return NULL;
+ }
+
+ return normalized;
+}
+
static int set_config(struct list_head *sections, const char *config_file_name,
const char *section_name, const char *name, char *value)
{
@@ -452,11 +500,7 @@ static int set_config(struct list_head *sections, const char *config_file_name,
find_config(sections, §ion, &element, section_name, name);
if (value != NULL) {
- value = strdup(value);
- if (!value) {
- pr_err("%s: strdup failed\n", __func__);
- return -1;
- }
+ value = normalize_value(section_name, name, value);
/* if there isn't existent section, add a new section */
if (!section) {
--
2.5.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH v15 9/9] perf config: Add a option 'remove' to perf-config
2016-02-10 17:51 [PATCHSET v15 0/9] perf config: Add several options into perf-config Taeung Song
` (7 preceding siblings ...)
2016-02-10 17:51 ` [PATCH v15 8/9] perf config: normalize a value depending on default type of it Taeung Song
@ 2016-02-10 17:51 ` Taeung Song
8 siblings, 0 replies; 11+ messages in thread
From: Taeung Song @ 2016-02-10 17:51 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: linux-kernel, Jiri Olsa, Namhyung Kim, Ingo Molnar, Taeung Song
A option 'remove' is to remove specific config variables.
For the syntax examples,
# perf config [<file-option>] -r | --remove [section.name ...]
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
---
tools/perf/Documentation/perf-config.txt | 6 ++++++
tools/perf/builtin-config.c | 37 ++++++++++++++++++++++++++++++--
2 files changed, 41 insertions(+), 2 deletions(-)
diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt
index 0e0482c..a99d563 100644
--- a/tools/perf/Documentation/perf-config.txt
+++ b/tools/perf/Documentation/perf-config.txt
@@ -15,6 +15,8 @@ or
'perf config' [<file-option>] -a | --list-all
or
'perf config' [<file-option>] -k | --skel
+or
+'perf config' [<file-option>] -r | --remove [section.name ...]
DESCRIPTION
-----------
@@ -47,6 +49,10 @@ OPTIONS
--verbose::
Be more verbose. (show config description)
+-r::
+--remove::
+ Remove specific config variables.
+
CONFIGURATION FILE
------------------
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
index 92ff842..a40cf78 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -23,7 +23,8 @@ static const char * const config_usage[] = {
enum actions {
ACTION_LIST = 1,
ACTION_LIST_ALL,
- ACTION_SKEL
+ ACTION_SKEL,
+ ACTION_REMOVE
} actions;
static struct option config_options[] = {
@@ -35,6 +36,8 @@ static struct option config_options[] = {
OPT_SET_UINT('k', "skel", &actions,
"produce an skeleton with the possible"
" config variables", ACTION_SKEL),
+ OPT_SET_UINT('r', "remove", &actions,
+ "remove specific variables: [section.name ...]", ACTION_REMOVE),
OPT_INCR('v', "verbose", &verbose, "Be more verbose"
" (show config description)"),
OPT_BOOLEAN(0, "system", &use_system_config, "use system config file"),
@@ -499,7 +502,13 @@ static int set_config(struct list_head *sections, const char *config_file_name,
struct config_element *element = NULL;
find_config(sections, §ion, &element, section_name, name);
- if (value != NULL) {
+ if (!value) {
+ /* value == NULL means remove the variable */
+ if (section && element) {
+ free(element->value);
+ element->value = NULL;
+ }
+ } else {
value = normalize_value(section_name, name, value);
/* if there isn't existent section, add a new section */
@@ -663,6 +672,7 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
set_option_flag(config_options, 'l', "list", PARSE_OPT_EXCLUSIVE);
set_option_flag(config_options, 'a', "list-all", PARSE_OPT_EXCLUSIVE);
+ set_option_flag(config_options, 'r', "remove", PARSE_OPT_EXCLUSIVE);
argc = parse_options(argc, argv, config_options, config_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
@@ -692,6 +702,29 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
}
switch (actions) {
+ case ACTION_REMOVE:
+ if (argc) {
+ for (i = 0; argv[i]; i++) {
+ if (!use_system_config && !use_user_config) {
+ ret = perf_configset_with_option(set_config,
+ &system_sections,
+ system_config,
+ argv[i], NULL);
+ ret = perf_configset_with_option(set_config,
+ &user_sections,
+ user_config,
+ argv[i], NULL);
+ } else
+ ret = perf_configset_with_option(set_config, sections,
+ config_exclusive_filename,
+ argv[i], NULL);
+ }
+ } else {
+ pr_err("Error: Missing arguments\n");
+ parse_options_usage(config_usage, config_options, "r", 1);
+ return -1;
+ }
+ break;
case ACTION_SKEL:
if (argc)
parse_options_usage(config_usage, config_options, "k", 1);
--
2.5.0
^ permalink raw reply related [flat|nested] 11+ messages in thread