Since array types are handled differently, errors referencing them also need to be handled differently. Add and use a new INVALID_ARRAY_SPEC error. Also add INVALID_CMD and INVALID_DYN_CMD to catch and display the correct form for badly-formed commands, which can also be used in place of CMD_INCOMPLETE, which is removed, and remove CMD_TOO_LONG, since it's no longer used.
Signed-off-by: Tom Zanussi <zanu...@kernel.org> --- kernel/trace/trace_events_synth.c | 66 +++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 8 deletions(-) diff --git a/kernel/trace/trace_events_synth.c b/kernel/trace/trace_events_synth.c index 90c1790ed1d6..1aa808791f56 100644 --- a/kernel/trace/trace_events_synth.c +++ b/kernel/trace/trace_events_synth.c @@ -23,13 +23,14 @@ #undef ERRORS #define ERRORS \ C(BAD_NAME, "Illegal name"), \ - C(CMD_INCOMPLETE, "Incomplete command"), \ + C(INVALID_CMD, "Command must be of the form: <name> field[;field] ..."),\ + C(INVALID_DYN_CMD, "Command must be of the form: s or -:[synthetic/]<name> field[;field] ..."),\ C(EVENT_EXISTS, "Event already exists"), \ C(TOO_MANY_FIELDS, "Too many fields"), \ C(INCOMPLETE_TYPE, "Incomplete type"), \ C(INVALID_TYPE, "Invalid type"), \ - C(INVALID_FIELD, "Invalid field"), \ - C(CMD_TOO_LONG, "Command too long"), + C(INVALID_FIELD, "Invalid field"), \ + C(INVALID_ARRAY_SPEC, "Invalid array specification"), #undef C #define C(a, b) SYNTH_ERR_##a @@ -643,6 +644,10 @@ static struct synth_field *parse_synth_field(int argc, char **argv) size = synth_field_size(field->type); if (size < 0) { + if (array) + synth_err(SYNTH_ERR_INVALID_ARRAY_SPEC, errpos(field_name)); + else + synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field_type)); ret = -EINVAL; goto free; } else if (size == 0) { @@ -1158,7 +1163,7 @@ static int __create_synth_event(const char *name, const char *raw_fields) mutex_lock(&event_mutex); if (name[0] == '\0') { - synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0); + synth_err(SYNTH_ERR_INVALID_CMD, 0); ret = -EINVAL; goto out; } @@ -1212,7 +1217,7 @@ static int __create_synth_event(const char *name, const char *raw_fields) } if (n_fields == 0) { - synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0); + synth_err(SYNTH_ERR_INVALID_CMD, 0); ret = -EINVAL; goto err; } @@ -1350,13 +1355,42 @@ int synth_event_delete(const char *event_name) } EXPORT_SYMBOL_GPL(synth_event_delete); +static int check_command(const char *raw_command) +{ + char **argv = NULL, *cmd, *saved_cmd, *name_and_field; + int argc, ret = 0; + + cmd = saved_cmd = kstrdup(raw_command, GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + name_and_field = strsep(&cmd, ";"); + if (!name_and_field) { + ret = -EINVAL; + goto free; + } + + argv = argv_split(GFP_KERNEL, name_and_field, &argc); + if (!argv) { + ret = -ENOMEM; + goto free; + } + + if (argc < 3) + ret = -EINVAL; +free: + kfree(saved_cmd); + if (argv) + argv_free(argv); + + return ret; +} + static int create_or_delete_synth_event(const char *raw_command) { char **argv, *name = NULL, *fields; int argc = 0, ret = 0; - last_cmd_set(raw_command); - argv = argv_split(GFP_KERNEL, raw_command, &argc); if (!argv) return -ENOMEM; @@ -1364,9 +1398,16 @@ static int create_or_delete_synth_event(const char *raw_command) if (!argc) goto free; + last_cmd_set(raw_command); + + ret = check_command(raw_command); + if (ret) { + synth_err(SYNTH_ERR_INVALID_CMD, 0); + goto free; + } + name = argv[0]; - /* trace_run_command() ensures argc != 0 */ if (name[0] == '!') { ret = synth_event_delete(name + 1); goto free; @@ -1951,12 +1992,21 @@ static int create_synth_event(const char *raw_command) if (strchr(name, '/')) { len = str_has_prefix(name, SYNTH_SYSTEM "/"); if (len == 0) { + synth_err(SYNTH_ERR_INVALID_DYN_CMD, 0); ret = -EINVAL; goto free; } name += len; } + len = name - argv[0]; + + ret = check_command(raw_command + len); + if (ret) { + synth_err(SYNTH_ERR_INVALID_CMD, 0); + goto free; + } + fields = strstr(raw_command, name); fields += strlen(name); -- 2.17.1