This patch consists of functions which can set specific config variables. For the syntax examples,
perf config [options] [section.name[=value] ...] set specific config variables # perf config report.queue-size=100M report.children=true Signed-off-by: Taeung Song <treeze.tae...@gmail.com> --- tools/perf/Documentation/perf-config.txt | 2 +- tools/perf/builtin-config.c | 55 +++++++++++++++++++++++++++++--- tools/perf/util/cache.h | 3 +- tools/perf/util/config.c | 27 ++++++++++++++++ 4 files changed, 80 insertions(+), 7 deletions(-) diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt index 691d52b..9c95af8 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 0f2193a..d5cc3e8 100644 --- a/tools/perf/builtin-config.c +++ b/tools/perf/builtin-config.c @@ -17,7 +17,7 @@ static bool use_system_config, use_user_config; static const char *config_file_name; static const char * const config_usage[] = { - "perf config [options] [section.name ...]", + "perf config [options] [section.name[=value] ...]", NULL }; @@ -412,7 +412,8 @@ static void find_config(struct config_section **section_node, *element_node = NULL; } -static int show_spec_config(const char *section_name, const char *name) +static int show_spec_config(const char *section_name, const char *name, + char *value __maybe_unused) { int i; struct config_section *section_node = NULL; @@ -488,6 +489,34 @@ static char *normalize_value(const char *section_name, const char *name, const c return normalized; } +static int set_config(const char *section_name, const char *name, char *value) +{ + struct config_section *section_node = NULL; + struct config_element *element_node = NULL; + + find_config(§ion_node, &element_node, section_name, name); + if (value != NULL) { + value = normalize_value(section_name, name, value); + + /* if there isn't existent section, add a new section */ + if (!section_node) { + section_node = init_section(section_name); + if (!section_node) + return -1; + list_add_tail(§ion_node->list, §ions); + } + /* if nothing to replace, add a new element which contains key-value pair. */ + if (!element_node) { + add_element(§ion_node->element_head, name, value); + } else { + free(element_node->value); + element_node->value = value; + } + } + + return perf_configset_write_in_full(config_file_name); +} + static int collect_current_config(const char *var, const char *value, void *cb __maybe_unused) { @@ -557,7 +586,7 @@ static int show_all_config(void) return 0; } -static int perf_configset_with_option(configset_fn_t fn, const char *var) +static int perf_configset_with_option(configset_fn_t fn, const char *var, char *value) { char *section_name; char *name; @@ -585,8 +614,18 @@ static int perf_configset_with_option(configset_fn_t fn, const char *var) section_name = strsep(&key, "."); name = strsep(&key, "."); free(key); + if (!value) { + /* do nothing */ + } else if (!strcmp(value, "=")) { + pr_err("The config variable does not contain a value: %s.%s\n", + section_name, name); + return -1; + } else { + value++; + name = strsep(&name, "="); + } - return fn(section_name, name); + return fn(section_name, name, value); pr_err("invalid key: %s\n", var); return -1; @@ -625,7 +664,13 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused) default: if (argc) { for (i = 0; argv[i]; i++) { - ret = perf_configset_with_option(show_spec_config, argv[i]); + char *value = strchr(argv[i], '='); + if (value == NULL) + ret = perf_configset_with_option(show_spec_config, + argv[i], value); + else + ret = perf_configset_with_option(set_config, + argv[i], value); if (ret < 0) break; } diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h index 6fe734c..0b68c89 100644 --- a/tools/perf/util/cache.h +++ b/tools/perf/util/cache.h @@ -34,7 +34,8 @@ struct config_section { struct list_head sections; -typedef int (*configset_fn_t)(const char *, const char *); +extern int perf_configset_write_in_full(const char *file_name); +typedef int (*configset_fn_t)(const char *, const char *, char*); 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 *); diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index 23fa8c5..4c13991 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c @@ -506,6 +506,33 @@ out: return ret; } +int perf_configset_write_in_full(const char *file_name) +{ + struct config_section *section_node; + struct config_element *element_node; + const char *first_line = "# this file is auto-generated."; + FILE *fp = fopen(file_name, "w"); + + if (!fp) { + pr_err("Error: %s: Can't open this file\n", file_name); + return -1; + } + + fprintf(fp, "%s\n", first_line); + /* overwrite configvariables */ + list_for_each_entry(section_node, §ions, list) { + fprintf(fp, "[%s]\n", section_node->name); + list_for_each_entry(element_node, §ion_node->element_head, list) { + if (element_node->value) + fprintf(fp, "\t%s = %s\n", + element_node->name, element_node->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"). -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/