Re: [PATCH v3 4/7] tracing: Add synthetic event error logging

2020-10-13 Thread Steven Rostedt
On Tue, 13 Oct 2020 09:17:55 -0500
Tom Zanussi  wrote:

> +static int save_cmdstr(int argc, const char *name, const char **argv)
> +{
> +struct seq_buf s;
> + char *buf;
> + int i;
> +
> +buf = kzalloc(MAX_DYNEVENT_CMD_LEN, GFP_KERNEL);
> +if (!buf)
> +return -ENOMEM;
> +
> +seq_buf_init(, buf, MAX_DYNEVENT_CMD_LEN);
> +
> +seq_buf_puts(, name);
> +
> +for (i = 0; i < argc; i++) {
> +seq_buf_putc(, ' ');
> +seq_buf_puts(, argv[i]);
> +}
> +
> +if (!seq_buf_buffer_left()) {
> +synth_err(SYNTH_ERR_CMD_TOO_LONG, 0);
> +kfree(buf);
> +return -EINVAL;
> +}
> +buf[s.len] = 0;
> +last_cmd_set(buf);
> +
> +kfree(buf);
> +return 0;
> +}

I see you cut and pasted this ;-)

I fixed up the whitespace.

-- Steve


[PATCH v3 4/7] tracing: Add synthetic event error logging

2020-10-13 Thread Tom Zanussi
Add support for synthetic event error logging, which entails adding a
logging function for it, a way to save the synthetic event command,
and a set of specific synthetic event parse error strings and
handling.

[ : wrote save_cmdstr() seq_buf implementation. ]
Signed-off-by: Tom Zanussi 
---
 kernel/trace/trace_events_synth.c | 92 ++-
 1 file changed, 90 insertions(+), 2 deletions(-)

diff --git a/kernel/trace/trace_events_synth.c 
b/kernel/trace/trace_events_synth.c
index 8c9d6e464da0..7efe39be6576 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -20,6 +20,48 @@
 
 #include "trace_synth.h"
 
+#undef ERRORS
+#define ERRORS \
+   C(BAD_NAME, "Illegal name"),\
+   C(CMD_INCOMPLETE,   "Incomplete command"),  \
+   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"),
+
+#undef C
+#define C(a, b)SYNTH_ERR_##a
+
+enum { ERRORS };
+
+#undef C
+#define C(a, b)b
+
+static const char *err_text[] = { ERRORS };
+
+static char last_cmd[MAX_FILTER_STR_VAL];
+
+static int errpos(const char *str)
+{
+   return err_pos(last_cmd, str);
+}
+
+static void last_cmd_set(char *str)
+{
+   if (!str)
+   return;
+
+   strncpy(last_cmd, str, MAX_FILTER_STR_VAL - 1);
+}
+
+static void synth_err(u8 err_type, u8 err_pos)
+{
+   tracing_log_err(NULL, "synthetic_events", last_cmd, err_text,
+   err_type, err_pos);
+}
+
 static int create_synth_event(int argc, const char **argv);
 static int synth_event_show(struct seq_file *m, struct dyn_event *ev);
 static int synth_event_release(struct dyn_event *ev);
@@ -545,8 +587,10 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
field_type++;
 
if (!strcmp(field_type, "unsigned")) {
-   if (argc < 3)
+   if (argc < 3) {
+   synth_err(SYNTH_ERR_INCOMPLETE_TYPE, 
errpos(field_type));
return ERR_PTR(-EINVAL);
+   }
prefix = "unsigned ";
field_type = argv[1];
field_name = argv[2];
@@ -573,6 +617,7 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
goto free;
}
if (!is_good_name(field->name)) {
+   synth_err(SYNTH_ERR_BAD_NAME, errpos(field_name));
ret = -EINVAL;
goto free;
}
@@ -601,6 +646,7 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
 
size = synth_field_size(field->type);
if (size < 0) {
+   synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field_type));
ret = -EINVAL;
goto free;
} else if (size == 0) {
@@ -621,6 +667,7 @@ static struct synth_field *parse_synth_field(int argc, 
const char **argv,
field->is_dynamic = true;
size = sizeof(u64);
} else {
+   synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field_type));
ret = -EINVAL;
goto free;
}
@@ -1098,12 +1145,47 @@ int synth_event_gen_cmd_array_start(struct dynevent_cmd 
*cmd, const char *name,
 }
 EXPORT_SYMBOL_GPL(synth_event_gen_cmd_array_start);
 
+static int save_cmdstr(int argc, const char *name, const char **argv)
+{
+struct seq_buf s;
+   char *buf;
+   int i;
+
+buf = kzalloc(MAX_DYNEVENT_CMD_LEN, GFP_KERNEL);
+if (!buf)
+return -ENOMEM;
+
+seq_buf_init(, buf, MAX_DYNEVENT_CMD_LEN);
+
+seq_buf_puts(, name);
+
+for (i = 0; i < argc; i++) {
+seq_buf_putc(, ' ');
+seq_buf_puts(, argv[i]);
+}
+
+if (!seq_buf_buffer_left()) {
+synth_err(SYNTH_ERR_CMD_TOO_LONG, 0);
+kfree(buf);
+return -EINVAL;
+}
+buf[s.len] = 0;
+last_cmd_set(buf);
+
+kfree(buf);
+return 0;
+}
+
 static int __create_synth_event(int argc, const char *name, const char **argv)
 {
struct synth_field *field, *fields[SYNTH_FIELDS_MAX];
struct synth_event *event = NULL;
int i, consumed = 0, n_fields = 0, ret = 0;
 
+   ret = save_cmdstr(argc, name, argv);
+   if (ret)
+   return ret;
+
/*
 * Argument syntax:
 *  - Add synthetic event:  field[;field] ...
@@ -,18 +1193,22 @@ static int __create_synth_event(int argc, const char 
*name, const char **argv)
 *  where