Skip to content

Commit d4d7046

Browse files
Tom Zanussirostedt
authored andcommitted
tracing: Add synthetic event error logging
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. Link: https://lkml.kernel.org/r/ed099c66df13b40cfc633aaeb17f66c37a923066.1602598160.git.zanussi@kernel.org [ <rostedt@goodmis.org>: wrote save_cmdstr() seq_buf implementation. ] Tested-by: Masami Hiramatsu <mhiramat@kernel.org> Signed-off-by: Tom Zanussi <zanussi@kernel.org> Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
1 parent 9bbb332 commit d4d7046

1 file changed

Lines changed: 90 additions & 2 deletions

File tree

kernel/trace/trace_events_synth.c

Lines changed: 90 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,48 @@
2020

2121
#include "trace_synth.h"
2222

23+
#undef ERRORS
24+
#define ERRORS \
25+
C(BAD_NAME, "Illegal name"), \
26+
C(CMD_INCOMPLETE, "Incomplete command"), \
27+
C(EVENT_EXISTS, "Event already exists"), \
28+
C(TOO_MANY_FIELDS, "Too many fields"), \
29+
C(INCOMPLETE_TYPE, "Incomplete type"), \
30+
C(INVALID_TYPE, "Invalid type"), \
31+
C(INVALID_FIELD, "Invalid field"), \
32+
C(CMD_TOO_LONG, "Command too long"),
33+
34+
#undef C
35+
#define C(a, b) SYNTH_ERR_##a
36+
37+
enum { ERRORS };
38+
39+
#undef C
40+
#define C(a, b) b
41+
42+
static const char *err_text[] = { ERRORS };
43+
44+
static char last_cmd[MAX_FILTER_STR_VAL];
45+
46+
static int errpos(const char *str)
47+
{
48+
return err_pos(last_cmd, str);
49+
}
50+
51+
static void last_cmd_set(char *str)
52+
{
53+
if (!str)
54+
return;
55+
56+
strncpy(last_cmd, str, MAX_FILTER_STR_VAL - 1);
57+
}
58+
59+
static void synth_err(u8 err_type, u8 err_pos)
60+
{
61+
tracing_log_err(NULL, "synthetic_events", last_cmd, err_text,
62+
err_type, err_pos);
63+
}
64+
2365
static int create_synth_event(int argc, const char **argv);
2466
static int synth_event_show(struct seq_file *m, struct dyn_event *ev);
2567
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,
545587
field_type++;
546588

547589
if (!strcmp(field_type, "unsigned")) {
548-
if (argc < 3)
590+
if (argc < 3) {
591+
synth_err(SYNTH_ERR_INCOMPLETE_TYPE, errpos(field_type));
549592
return ERR_PTR(-EINVAL);
593+
}
550594
prefix = "unsigned ";
551595
field_type = argv[1];
552596
field_name = argv[2];
@@ -573,6 +617,7 @@ static struct synth_field *parse_synth_field(int argc, const char **argv,
573617
goto free;
574618
}
575619
if (!is_good_name(field->name)) {
620+
synth_err(SYNTH_ERR_BAD_NAME, errpos(field_name));
576621
ret = -EINVAL;
577622
goto free;
578623
}
@@ -601,6 +646,7 @@ static struct synth_field *parse_synth_field(int argc, const char **argv,
601646

602647
size = synth_field_size(field->type);
603648
if (size < 0) {
649+
synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field_type));
604650
ret = -EINVAL;
605651
goto free;
606652
} else if (size == 0) {
@@ -621,6 +667,7 @@ static struct synth_field *parse_synth_field(int argc, const char **argv,
621667
field->is_dynamic = true;
622668
size = sizeof(u64);
623669
} else {
670+
synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field_type));
624671
ret = -EINVAL;
625672
goto free;
626673
}
@@ -1098,31 +1145,70 @@ int synth_event_gen_cmd_array_start(struct dynevent_cmd *cmd, const char *name,
10981145
}
10991146
EXPORT_SYMBOL_GPL(synth_event_gen_cmd_array_start);
11001147

1148+
static int save_cmdstr(int argc, const char *name, const char **argv)
1149+
{
1150+
struct seq_buf s;
1151+
char *buf;
1152+
int i;
1153+
1154+
buf = kzalloc(MAX_DYNEVENT_CMD_LEN, GFP_KERNEL);
1155+
if (!buf)
1156+
return -ENOMEM;
1157+
1158+
seq_buf_init(&s, buf, MAX_DYNEVENT_CMD_LEN);
1159+
1160+
seq_buf_puts(&s, name);
1161+
1162+
for (i = 0; i < argc; i++) {
1163+
seq_buf_putc(&s, ' ');
1164+
seq_buf_puts(&s, argv[i]);
1165+
}
1166+
1167+
if (!seq_buf_buffer_left(&s)) {
1168+
synth_err(SYNTH_ERR_CMD_TOO_LONG, 0);
1169+
kfree(buf);
1170+
return -EINVAL;
1171+
}
1172+
buf[s.len] = 0;
1173+
last_cmd_set(buf);
1174+
1175+
kfree(buf);
1176+
return 0;
1177+
}
1178+
11011179
static int __create_synth_event(int argc, const char *name, const char **argv)
11021180
{
11031181
struct synth_field *field, *fields[SYNTH_FIELDS_MAX];
11041182
struct synth_event *event = NULL;
11051183
int i, consumed = 0, n_fields = 0, ret = 0;
11061184

1185+
ret = save_cmdstr(argc, name, argv);
1186+
if (ret)
1187+
return ret;
1188+
11071189
/*
11081190
* Argument syntax:
11091191
* - Add synthetic event: <event_name> field[;field] ...
11101192
* - Remove synthetic event: !<event_name> field[;field] ...
11111193
* where 'field' = type field_name
11121194
*/
11131195

1114-
if (name[0] == '\0' || argc < 1)
1196+
if (name[0] == '\0' || argc < 1) {
1197+
synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0);
11151198
return -EINVAL;
1199+
}
11161200

11171201
mutex_lock(&event_mutex);
11181202

11191203
if (!is_good_name(name)) {
1204+
synth_err(SYNTH_ERR_BAD_NAME, errpos(name));
11201205
ret = -EINVAL;
11211206
goto out;
11221207
}
11231208

11241209
event = find_synth_event(name);
11251210
if (event) {
1211+
synth_err(SYNTH_ERR_EVENT_EXISTS, errpos(name));
11261212
ret = -EEXIST;
11271213
goto out;
11281214
}
@@ -1131,6 +1217,7 @@ static int __create_synth_event(int argc, const char *name, const char **argv)
11311217
if (strcmp(argv[i], ";") == 0)
11321218
continue;
11331219
if (n_fields == SYNTH_FIELDS_MAX) {
1220+
synth_err(SYNTH_ERR_TOO_MANY_FIELDS, 0);
11341221
ret = -EINVAL;
11351222
goto err;
11361223
}
@@ -1145,6 +1232,7 @@ static int __create_synth_event(int argc, const char *name, const char **argv)
11451232
}
11461233

11471234
if (i < argc && strcmp(argv[i], ";") != 0) {
1235+
synth_err(SYNTH_ERR_INVALID_FIELD, errpos(argv[i]));
11481236
ret = -EINVAL;
11491237
goto err;
11501238
}

0 commit comments

Comments
 (0)