Skip to content

Commit c9e759b

Browse files
Tom Zanussirostedt
authored andcommitted
tracing: Rework synthetic event command parsing
Now that command parsing has been delegated to the create functions and we're no longer constrained by argv_split(), we can modify the synthetic event command parser to better match the higher-level structure of the synthetic event commands, which is basically an event name followed by a set of semicolon-separated fields. Since we're also now passed the raw command, we can also save it directly and can get rid of save_cmdstr(). Link: https://lkml.kernel.org/r/cb9e2be92d992ce59f2b4f132264a5d467f3933f.1612208610.git.zanussi@kernel.org Signed-off-by: Tom Zanussi <[email protected]> Signed-off-by: Steven Rostedt (VMware) <[email protected]>
1 parent d262271 commit c9e759b

File tree

1 file changed

+143
-102
lines changed

1 file changed

+143
-102
lines changed

kernel/trace/trace_events_synth.c

Lines changed: 143 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ static int errpos(const char *str)
4848
return err_pos(last_cmd, str);
4949
}
5050

51-
static void last_cmd_set(char *str)
51+
static void last_cmd_set(const char *str)
5252
{
5353
if (!str)
5454
return;
@@ -579,18 +579,14 @@ static void free_synth_field(struct synth_field *field)
579579
kfree(field);
580580
}
581581

582-
static struct synth_field *parse_synth_field(int argc, const char **argv,
583-
int *consumed)
582+
static struct synth_field *parse_synth_field(int argc, char **argv)
584583
{
585-
struct synth_field *field;
586584
const char *prefix = NULL, *field_type = argv[0], *field_name, *array;
587-
int len, ret = -ENOMEM;
585+
int len, consumed, ret = -ENOMEM;
586+
struct synth_field *field;
588587
struct seq_buf s;
589588
ssize_t size;
590589

591-
if (field_type[0] == ';')
592-
field_type++;
593-
594590
if (!strcmp(field_type, "unsigned")) {
595591
if (argc < 3) {
596592
synth_err(SYNTH_ERR_INCOMPLETE_TYPE, errpos(field_type));
@@ -599,10 +595,20 @@ static struct synth_field *parse_synth_field(int argc, const char **argv,
599595
prefix = "unsigned ";
600596
field_type = argv[1];
601597
field_name = argv[2];
602-
*consumed = 3;
598+
consumed = 3;
603599
} else {
604600
field_name = argv[1];
605-
*consumed = 2;
601+
consumed = 2;
602+
}
603+
604+
if (consumed < argc) {
605+
synth_err(SYNTH_ERR_INVALID_FIELD, errpos(field_type));
606+
return ERR_PTR(-EINVAL);
607+
}
608+
609+
if (!field_name) {
610+
synth_err(SYNTH_ERR_INVALID_FIELD, errpos(field_type));
611+
return ERR_PTR(-EINVAL);
606612
}
607613

608614
field = kzalloc(sizeof(*field), GFP_KERNEL);
@@ -613,8 +619,6 @@ static struct synth_field *parse_synth_field(int argc, const char **argv,
613619
array = strchr(field_name, '[');
614620
if (array)
615621
len -= strlen(array);
616-
else if (field_name[len - 1] == ';')
617-
len--;
618622

619623
field->name = kmemdup_nul(field_name, len, GFP_KERNEL);
620624
if (!field->name)
@@ -626,8 +630,6 @@ static struct synth_field *parse_synth_field(int argc, const char **argv,
626630
goto free;
627631
}
628632

629-
if (field_type[0] == ';')
630-
field_type++;
631633
len = strlen(field_type) + 1;
632634

633635
if (array)
@@ -644,11 +646,8 @@ static struct synth_field *parse_synth_field(int argc, const char **argv,
644646
if (prefix)
645647
seq_buf_puts(&s, prefix);
646648
seq_buf_puts(&s, field_type);
647-
if (array) {
649+
if (array)
648650
seq_buf_puts(&s, array);
649-
if (s.buffer[s.len - 1] == ';')
650-
s.len--;
651-
}
652651
if (WARN_ON_ONCE(!seq_buf_buffer_left(&s)))
653652
goto free;
654653

@@ -1160,46 +1159,12 @@ int synth_event_gen_cmd_array_start(struct dynevent_cmd *cmd, const char *name,
11601159
}
11611160
EXPORT_SYMBOL_GPL(synth_event_gen_cmd_array_start);
11621161

1163-
static int save_cmdstr(int argc, const char *name, const char **argv)
1164-
{
1165-
struct seq_buf s;
1166-
char *buf;
1167-
int i;
1168-
1169-
buf = kzalloc(MAX_DYNEVENT_CMD_LEN, GFP_KERNEL);
1170-
if (!buf)
1171-
return -ENOMEM;
1172-
1173-
seq_buf_init(&s, buf, MAX_DYNEVENT_CMD_LEN);
1174-
1175-
seq_buf_puts(&s, name);
1176-
1177-
for (i = 0; i < argc; i++) {
1178-
seq_buf_putc(&s, ' ');
1179-
seq_buf_puts(&s, argv[i]);
1180-
}
1181-
1182-
if (!seq_buf_buffer_left(&s)) {
1183-
synth_err(SYNTH_ERR_CMD_TOO_LONG, 0);
1184-
kfree(buf);
1185-
return -EINVAL;
1186-
}
1187-
buf[s.len] = 0;
1188-
last_cmd_set(buf);
1189-
1190-
kfree(buf);
1191-
return 0;
1192-
}
1193-
1194-
static int __create_synth_event(int argc, const char *name, const char **argv)
1162+
static int __create_synth_event(const char *name, const char *raw_fields)
11951163
{
1164+
char **argv, *field_str, *tmp_fields, *saved_fields = NULL;
11961165
struct synth_field *field, *fields[SYNTH_FIELDS_MAX];
1166+
int i, argc, n_fields = 0, ret = 0;
11971167
struct synth_event *event = NULL;
1198-
int i, consumed = 0, n_fields = 0, ret = 0;
1199-
1200-
ret = save_cmdstr(argc, name, argv);
1201-
if (ret)
1202-
return ret;
12031168

12041169
/*
12051170
* Argument syntax:
@@ -1208,46 +1173,60 @@ static int __create_synth_event(int argc, const char *name, const char **argv)
12081173
* where 'field' = type field_name
12091174
*/
12101175

1211-
if (name[0] == '\0' || argc < 1) {
1176+
if (name[0] == '\0') {
12121177
synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0);
12131178
return -EINVAL;
12141179
}
12151180

1216-
mutex_lock(&event_mutex);
1217-
12181181
if (!is_good_name(name)) {
12191182
synth_err(SYNTH_ERR_BAD_NAME, errpos(name));
1220-
ret = -EINVAL;
1221-
goto out;
1183+
return -EINVAL;
12221184
}
12231185

1186+
mutex_lock(&event_mutex);
1187+
12241188
event = find_synth_event(name);
12251189
if (event) {
12261190
synth_err(SYNTH_ERR_EVENT_EXISTS, errpos(name));
12271191
ret = -EEXIST;
1228-
goto out;
1192+
goto err;
12291193
}
12301194

1231-
for (i = 0; i < argc - 1; i++) {
1232-
if (strcmp(argv[i], ";") == 0)
1233-
continue;
1234-
if (n_fields == SYNTH_FIELDS_MAX) {
1235-
synth_err(SYNTH_ERR_TOO_MANY_FIELDS, 0);
1236-
ret = -EINVAL;
1195+
tmp_fields = saved_fields = kstrdup(raw_fields, GFP_KERNEL);
1196+
if (!tmp_fields) {
1197+
ret = -ENOMEM;
1198+
goto err;
1199+
}
1200+
1201+
while ((field_str = strsep(&tmp_fields, ";")) != NULL) {
1202+
argv = argv_split(GFP_KERNEL, field_str, &argc);
1203+
if (!argv) {
1204+
ret = -ENOMEM;
12371205
goto err;
12381206
}
12391207

1240-
field = parse_synth_field(argc - i, &argv[i], &consumed);
1208+
if (!argc)
1209+
continue;
1210+
1211+
field = parse_synth_field(argc, argv);
12411212
if (IS_ERR(field)) {
1213+
argv_free(argv);
12421214
ret = PTR_ERR(field);
12431215
goto err;
12441216
}
1217+
1218+
argv_free(argv);
1219+
12451220
fields[n_fields++] = field;
1246-
i += consumed - 1;
1221+
if (n_fields == SYNTH_FIELDS_MAX) {
1222+
synth_err(SYNTH_ERR_TOO_MANY_FIELDS, 0);
1223+
ret = -EINVAL;
1224+
goto err;
1225+
}
12471226
}
12481227

1249-
if (i < argc && strcmp(argv[i], ";") != 0) {
1250-
synth_err(SYNTH_ERR_INVALID_FIELD, errpos(argv[i]));
1228+
if (n_fields == 0) {
1229+
synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0);
12511230
ret = -EINVAL;
12521231
goto err;
12531232
}
@@ -1266,6 +1245,8 @@ static int __create_synth_event(int argc, const char *name, const char **argv)
12661245
out:
12671246
mutex_unlock(&event_mutex);
12681247

1248+
kfree(saved_fields);
1249+
12691250
return ret;
12701251
err:
12711252
for (i = 0; i < n_fields; i++)
@@ -1383,31 +1364,79 @@ int synth_event_delete(const char *event_name)
13831364
}
13841365
EXPORT_SYMBOL_GPL(synth_event_delete);
13851366

1386-
static int create_or_delete_synth_event(const char *raw_command)
1367+
static int check_command(const char *raw_command)
13871368
{
1388-
char **argv, *name = NULL;
1389-
int argc = 0, ret = 0;
1369+
char **argv = NULL, *cmd, *saved_cmd, *name_and_field;
1370+
int argc, ret = 0;
13901371

1391-
argv = argv_split(GFP_KERNEL, raw_command, &argc);
1392-
if (!argv)
1372+
cmd = saved_cmd = kstrdup(raw_command, GFP_KERNEL);
1373+
if (!cmd)
13931374
return -ENOMEM;
13941375

1395-
if (!argc)
1376+
name_and_field = strsep(&cmd, ";");
1377+
if (!name_and_field) {
1378+
ret = -EINVAL;
1379+
goto free;
1380+
}
1381+
1382+
if (name_and_field[0] == '!')
1383+
goto free;
1384+
1385+
argv = argv_split(GFP_KERNEL, name_and_field, &argc);
1386+
if (!argv) {
1387+
ret = -ENOMEM;
13961388
goto free;
1389+
}
1390+
argv_free(argv);
1391+
1392+
if (argc < 3)
1393+
ret = -EINVAL;
1394+
free:
1395+
kfree(saved_cmd);
13971396

1398-
name = argv[0];
1397+
return ret;
1398+
}
1399+
1400+
static int create_or_delete_synth_event(const char *raw_command)
1401+
{
1402+
char *name = NULL, *fields, *p;
1403+
int ret = 0;
1404+
1405+
raw_command = skip_spaces(raw_command);
1406+
if (raw_command[0] == '\0')
1407+
return ret;
1408+
1409+
last_cmd_set(raw_command);
1410+
1411+
ret = check_command(raw_command);
1412+
if (ret) {
1413+
synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0);
1414+
return ret;
1415+
}
1416+
1417+
p = strpbrk(raw_command, " \t");
1418+
if (!p && raw_command[0] != '!') {
1419+
synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0);
1420+
ret = -EINVAL;
1421+
goto free;
1422+
}
1423+
1424+
name = kmemdup_nul(raw_command, p ? p - raw_command : strlen(raw_command), GFP_KERNEL);
1425+
if (!name)
1426+
return -ENOMEM;
13991427

1400-
/* trace_run_command() ensures argc != 0 */
14011428
if (name[0] == '!') {
14021429
ret = synth_event_delete(name + 1);
14031430
goto free;
14041431
}
14051432

1406-
ret = __create_synth_event(argc - 1, name, (const char **)argv + 1);
1433+
fields = skip_spaces(p);
1434+
1435+
ret = __create_synth_event(name, fields);
14071436
free:
1408-
argv_free(argv);
1437+
kfree(name);
14091438

1410-
return ret == -ECANCELED ? -EINVAL : ret;
1439+
return ret;
14111440
}
14121441

14131442
static int synth_event_run_command(struct dynevent_cmd *cmd)
@@ -1953,39 +1982,51 @@ EXPORT_SYMBOL_GPL(synth_event_trace_end);
19531982

19541983
static int create_synth_event(const char *raw_command)
19551984
{
1956-
char **argv, *name;
1957-
int len, argc = 0, ret = 0;
1985+
char *fields, *p;
1986+
const char *name;
1987+
int len, ret = 0;
19581988

1959-
argv = argv_split(GFP_KERNEL, raw_command, &argc);
1960-
if (!argv) {
1961-
ret = -ENOMEM;
1989+
raw_command = skip_spaces(raw_command);
1990+
if (raw_command[0] == '\0')
19621991
return ret;
1963-
}
19641992

1965-
if (!argc)
1966-
goto free;
1993+
last_cmd_set(raw_command);
19671994

1968-
name = argv[0];
1995+
p = strpbrk(raw_command, " \t");
1996+
if (!p)
1997+
return -EINVAL;
19691998

1970-
if (name[0] != 's' || name[1] != ':') {
1971-
ret = -ECANCELED;
1972-
goto free;
1973-
}
1999+
fields = skip_spaces(p);
2000+
2001+
name = raw_command;
2002+
2003+
if (name[0] != 's' || name[1] != ':')
2004+
return -ECANCELED;
19742005
name += 2;
19752006

19762007
/* This interface accepts group name prefix */
19772008
if (strchr(name, '/')) {
19782009
len = str_has_prefix(name, SYNTH_SYSTEM "/");
1979-
if (len == 0) {
1980-
ret = -EINVAL;
1981-
goto free;
1982-
}
2010+
if (len == 0)
2011+
return -EINVAL;
19832012
name += len;
19842013
}
19852014

1986-
ret = __create_synth_event(argc - 1, name, (const char **)argv + 1);
1987-
free:
1988-
argv_free(argv);
2015+
len = name - raw_command;
2016+
2017+
ret = check_command(raw_command + len);
2018+
if (ret) {
2019+
synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0);
2020+
return ret;
2021+
}
2022+
2023+
name = kmemdup_nul(raw_command + len, p - raw_command - len, GFP_KERNEL);
2024+
if (!name)
2025+
return -ENOMEM;
2026+
2027+
ret = __create_synth_event(name, fields);
2028+
2029+
kfree(name);
19892030

19902031
return ret;
19912032
}

0 commit comments

Comments
 (0)