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


Groups > linux.kernel > #1231182 > unrolled thread

[PATCH v6 0/7] perf tools: Add 'perf-config' command

Started byTaeung Song <treeze.taeung@gmail.com>
First post2015-09-23 09:00 +0200
Last post2015-09-23 09:00 +0200
Articles 2 — 1 participant

Back to article view | Back to linux.kernel


Contents

  [PATCH v6 0/7] perf tools: Add 'perf-config' command Taeung Song <treeze.taeung@gmail.com> - 2015-09-23 09:00 +0200
    [PATCH v6 2/7] perf config: Add '--system' and '--user' options to select which config file is used Taeung Song <treeze.taeung@gmail.com> - 2015-09-23 09:00 +0200

#1231182 — [PATCH v6 0/7] perf tools: Add 'perf-config' command

FromTaeung Song <treeze.taeung@gmail.com>
Date2015-09-23 09:00 +0200
Subject[PATCH v6 0/7] perf tools: Add 'perf-config' command
Message-ID<qbMc1-4YA-3@gated-at.bofh.it>
So far, it is difficult that the state of perf configs is looked through
and there's no knowing what kind of other variables except variables in perfconfig.example.
Also perf configs can't be changed without manually modifying $HOME/.perfconfig or
$(sysconfdir)/perfconfig file. So I suggest this patchset of the perf-config command
which can list, get, set, remove perf configs or list with default config values as below.

Taeung Song (7):
[PATCH v6 1/7] perf tools: Add 'perf-config' command
[PATCH v6 2/7] perf config: Add '--system' and '--user' options to select which
       	       	    	    config file is used
[PATCH v6 3/7] perf config: Add a option 'list-all' to perf-config
[PATCH v6 4/7] perf config: Add 'get' functionality
[PATCH v6 5/7] perf config: Add 'set' feature
[PATCH v6 6/7] perf config: normalize a value depending on default type of it
[PATCH v6 7/7] perf config: Add a option 'remove' to perf-config

Changes in v6:
	- Split a 'set' feature patch into two patch to separate normalize_value() from it. 
	(PATCH v6 5/7, PATCH v6 6/7)
	- Bug fix : 'remove' and 'set' malfunctions when without a specific file-option.
	(If file-option isn't used, 'remove' feature had to use both user and system
	config file and 'set' feature had to only handle user config file.)
	(PATCH v6 5/7, PATCH v6 7/7)

Changes in v5:
	- Simplify the switch statement in cmd_config()
	- Set a config file path with '--system' or '--user'
	instead of '--global' or '--system' as suggested by Namhyung. (PATCH v5 2/6)
	- The patch about 'get' and 'set 'split into two patchs
	as suggested by Namhyung. (PATCH v5 4/6, PATCH v5 5/6)

Changes in v4:
	- If some config value is default value, notice it is '(default)'
	as suggested by Jirka. (PATCH v4 3/5)

	- If there wasn't any perfconfig file, perf-config malfunctioned like
	Jirka pointed out. So add exception routine with '--global' and '--system'
	option which can select perf config file path. (PATCH v4 2/5)

Changes in v3:
	- Add a config variable 'kmem.default' with a default value as suggested by Namhyung.
	(PATCH v3 2/5, PATCH v4 3/5)

Changes in v2:
	- Change option name of listing all configs as '--list-all' instead of '--all'
	as suggested by Namhyung. (PATCH v2 3/4, PATCH v4 4/5)

	- Correct small infelicities or typing errors in a perf-config documention
	as suggested by Arnaldo. (PATCH v2 1/4, PATCH v4 1/5)

	- Declaration a global variable 'static struct default_configsets' has config variables
	with default values instead of using a 'util/PERFCONFIG-DEFAULT' file.
	(PATCH v2 3/4, PATCH v4 3/5)

	- Add a function to normalize a value and check data type of it.
	(PATCH v2 2/4, PATCH v4 3/5)

	- Simplify parsing arguments as arguments is just divided by '=' and then
	in front of '.' is a section, between '.' and '=' is a name, and behind '=' is a value.
	(PATCH v2 2/4, PATCH v4 3/5)

	- If run perf-config command without any option, perf-config work as '--list'.
	(PATCH v2 1/4, PATCH v4 1/5)

 tools/perf/Build                         |   1 +
 tools/perf/Documentation/perf-config.txt | 407 ++++++++++++++++
 tools/perf/builtin-config.c              | 768 +++++++++++++++++++++++++++++++
 tools/perf/builtin.h                     |   1 +
 tools/perf/command-list.txt              |   1 +
 tools/perf/perf.c                        |   1 +
 tools/perf/util/cache.h                  |  18 +
 tools/perf/util/config.c                 |  31 +-
 8 files changed, 1226 insertions(+), 2 deletions(-)
 create mode 100644 tools/perf/Documentation/perf-config.txt
 create mode 100644 tools/perf/builtin-config.c

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [next] | [standalone]


#1231183 — [PATCH v6 2/7] perf config: Add '--system' and '--user' options to select which config file is used

FromTaeung Song <treeze.taeung@gmail.com>
Date2015-09-23 09:00 +0200
Subject[PATCH v6 2/7] perf config: Add '--system' and '--user' options to select which config file is used
Message-ID<qbMc1-4YA-1@gated-at.bofh.it>
In reply to#1231182
Which config file is used is decided in only perf_config().
And a perf-config command depend on perf_config() to list
config variables with values. So add '--system' and '--user'
options to select which config file to be used without perf_config().

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
but user config have priority. 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

In addition, use List data structure which has config info.
Because perf_config() isn't used any more and directly collect
config info by perf_config_from_file() with a specific config
file path. Whichever config file or both are used, list is required
to keep and handle config variables and values.

Signed-off-by: Taeung Song <treeze.taeung@gmail.com>
---
 tools/perf/Documentation/perf-config.txt |  14 ++-
 tools/perf/builtin-config.c              | 163 +++++++++++++++++++++++++++++--
 tools/perf/util/cache.h                  |  15 +++
 tools/perf/util/config.c                 |   4 +-
 4 files changed, 187 insertions(+), 9 deletions(-)

diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt
index a3a12cc..b2abb16 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 with key and value into each 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
 ------------------
 
@@ -33,6 +41,10 @@ store a system-wide default configuration.
 The variables are divided into sections. In each section, the variables
 can are composed of a key and value.
 
+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 30b1500..92be3eb 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
 };
 
@@ -23,19 +25,150 @@ enum actions {
 } actions;
 
 static struct option config_options[] = {
+	OPT_GROUP("Config file location"),
+	OPT_BOOLEAN(0, "system", &use_system_config, "use system config file"),
+	OPT_BOOLEAN(0, "user", &use_user_config, "use user config file"),
 	OPT_GROUP("Action"),
 	OPT_SET_UINT('l', "list", &actions,
 		     "show current config variables", ACTION_LIST),
 	OPT_END()
 };
+static int show_config(struct list_head *sections)
+{
+	struct config_section *section;
+	struct config_element *element;
+
+	list_for_each_entry(section, sections, list) {
+		list_for_each_entry(element, &section->element_head, list) {
+			printf("%s.%s=%s\n", section->name,
+				       element->name, element->value);
+		}
+	}
+
+	return 0;
+}
 
-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, &section->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(&section->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 __maybe_unused)
+{
+	struct config_section *section = NULL;
+	struct config_element *element = NULL;
+	struct list_head *sections = (struct list_head *)spec_sections;
+	char *key = strdup(var);
+	char *section_name, *name;
+
+	if (!key) {
+		pr_err("%s: strdup failed\n", __func__);
+		return -1;
+	}
+
+	section_name = strsep(&key, ".");
+	name = strsep(&key, ".");
+	free(key);
+	if (name == NULL)
+		return -1;
+
+	find_config(sections, &section, &element, section_name, name);
+
+	if (!section) {
+		section = init_section(section_name);
+		if (!section)
+			return -1;
+		list_add_tail(&section->list, sections);
+	}
+
+	value = strdup(value);
+	if (!value) {
+		pr_err("%s: strdup failed\n", __func__);
+		return -1;
+	}
+
+	if (!element)
+		return add_element(&section->element_head, name, value);
+	else {
+		free(element->value);
+		element->value = (char *)value;
+	}
 
 	return 0;
 }
@@ -43,10 +176,28 @@ 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;
+	const char *system_config = perf_etc_perfconfig();
+	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;
+	}
+
+	INIT_LIST_HEAD(&sections);
+
+	if (use_system_config || (!use_system_config && !use_user_config))
+		perf_config_from_file(collect_current_config, system_config, &sections);
+
+	if (use_user_config || (!use_system_config && !use_user_config))
+		perf_config_from_file(collect_current_config, user_config, &sections);
+
 	switch (actions) {
 	case ACTION_LIST:
 	default:
@@ -55,7 +206,7 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
 			parse_options_usage(config_usage, config_options, "l", 1);
 			return -1;
 		} else
-			ret = perf_config(show_config, NULL);
+			ret = show_config(&sections);
 	}
 
 	return ret;
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index c861373..712e82b 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"
@@ -19,14 +20,28 @@
 #define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR"
 #define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR"
 
+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;
+};
+
 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 *);
+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 *);
 extern int config_error_nonbool(const char *);
 extern const char *perf_config_dirname(const char *, const char *);
+extern const char *perf_etc_perfconfig(void);
 
 /* pager.c */
 extern void setup_pager(void);
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 2e452ac..23fa8c5 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");
@@ -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)
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web