Skip to content

Commit bd82631

Browse files
Tom Zanussirostedt
Tom Zanussi
authored andcommitted
tracing: Add support for dynamic strings to synthetic events
Currently, sythetic events only support static string fields such as: # echo 'test_latency u64 lat; char somename[32]' > /sys/kernel/debug/tracing/synthetic_events Which is fine, but wastes a lot of space in the event. It also prevents the most commonly-defined strings in the existing trace events e.g. those defined using __string(), from being passed to synthetic events via the trace() action. With this change, synthetic events with dynamic fields can be defined: # echo 'test_latency u64 lat; char somename[]' > /sys/kernel/debug/tracing/synthetic_events And the trace() action can be used to generate events using either dynamic or static strings: # echo 'hist:keys=name:lat=common_timestamp.usecs-$ts0:onmatch(sys.event).test_latency($lat,name)' > /sys/kernel/debug/tracing/events The synthetic event dynamic strings are implemented in the same way as the existing __data_loc strings and appear as such in the format file. [ <[email protected]>: added __set_synth_event_print_fmt() changes: I added the following to make it work with trace-cmd. Dynamic strings must have __get_str() for events in the print_fmt otherwise it can't be parsed correctly. ] Link: https://lore.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/3ed35b6d0e390f5b94cb4a9ba1cc18f5982ab277.1601848695.git.zanussi@kernel.org Tested-by: Axel Rasmussen <[email protected]> Signed-off-by: Tom Zanussi <[email protected]> Signed-off-by: Steven Rostedt (VMware) <[email protected]>
1 parent 63a1e5d commit bd82631

File tree

6 files changed

+272
-40
lines changed

6 files changed

+272
-40
lines changed

Documentation/trace/events.rst

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -589,8 +589,19 @@ name::
589589
{ .type = "int", .name = "my_int_field" },
590590
};
591591

592-
See synth_field_size() for available types. If field_name contains [n]
593-
the field is considered to be an array.
592+
See synth_field_size() for available types.
593+
594+
If field_name contains [n], the field is considered to be a static array.
595+
596+
If field_names contains[] (no subscript), the field is considered to
597+
be a dynamic array, which will only take as much space in the event as
598+
is required to hold the array.
599+
600+
Because space for an event is reserved before assigning field values
601+
to the event, using dynamic arrays implies that the piecewise
602+
in-kernel API described below can't be used with dynamic arrays. The
603+
other non-piecewise in-kernel APIs can, however, be used with dynamic
604+
arrays.
594605

595606
If the event is created from within a module, a pointer to the module
596607
must be passed to synth_event_create(). This will ensure that the

Documentation/trace/histogram.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1776,6 +1776,24 @@ consisting of the name of the new event along with one or more
17761776
variables and their types, which can be any valid field type,
17771777
separated by semicolons, to the tracing/synthetic_events file.
17781778

1779+
See synth_field_size() for available types.
1780+
1781+
If field_name contains [n], the field is considered to be a static array.
1782+
1783+
If field_names contains[] (no subscript), the field is considered to
1784+
be a dynamic array, which will only take as much space in the event as
1785+
is required to hold the array.
1786+
1787+
A string field can be specified using either the static notation:
1788+
1789+
char name[32];
1790+
1791+
Or the dynamic:
1792+
1793+
char name[];
1794+
1795+
The size limit for either is 256.
1796+
17791797
For instance, the following creates a new event named 'wakeup_latency'
17801798
with 3 fields: lat, pid, and prio. Each of those fields is simply a
17811799
variable reference to a variable on another event::

kernel/trace/synth_event_gen_test.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -242,9 +242,11 @@ static struct synth_field_desc create_synth_test_fields[] = {
242242
{ .type = "pid_t", .name = "next_pid_field" },
243243
{ .type = "char[16]", .name = "next_comm_field" },
244244
{ .type = "u64", .name = "ts_ns" },
245+
{ .type = "char[]", .name = "dynstring_field_1" },
245246
{ .type = "u64", .name = "ts_ms" },
246247
{ .type = "unsigned int", .name = "cpu" },
247248
{ .type = "char[64]", .name = "my_string_field" },
249+
{ .type = "char[]", .name = "dynstring_field_2" },
248250
{ .type = "int", .name = "my_int_field" },
249251
};
250252

@@ -254,7 +256,7 @@ static struct synth_field_desc create_synth_test_fields[] = {
254256
*/
255257
static int __init test_create_synth_event(void)
256258
{
257-
u64 vals[7];
259+
u64 vals[9];
258260
int ret;
259261

260262
/* Create the create_synth_test event with the fields above */
@@ -292,10 +294,12 @@ static int __init test_create_synth_event(void)
292294
vals[0] = 777; /* next_pid_field */
293295
vals[1] = (u64)(long)"tiddlywinks"; /* next_comm_field */
294296
vals[2] = 1000000; /* ts_ns */
295-
vals[3] = 1000; /* ts_ms */
296-
vals[4] = raw_smp_processor_id(); /* cpu */
297-
vals[5] = (u64)(long)"thneed"; /* my_string_field */
298-
vals[6] = 398; /* my_int_field */
297+
vals[3] = (u64)(long)"xrayspecs"; /* dynstring_field_1 */
298+
vals[4] = 1000; /* ts_ms */
299+
vals[5] = raw_smp_processor_id(); /* cpu */
300+
vals[6] = (u64)(long)"thneed"; /* my_string_field */
301+
vals[7] = (u64)(long)"kerplunk"; /* dynstring_field_2 */
302+
vals[8] = 398; /* my_int_field */
299303

300304
/* Now generate a create_synth_test event */
301305
ret = synth_event_trace_array(create_synth_test, vals, ARRAY_SIZE(vals));
@@ -422,13 +426,15 @@ static int __init test_trace_synth_event(void)
422426
int ret;
423427

424428
/* Trace some bogus values just for testing */
425-
ret = synth_event_trace(create_synth_test, 7, /* number of values */
429+
ret = synth_event_trace(create_synth_test, 9, /* number of values */
426430
(u64)444, /* next_pid_field */
427431
(u64)(long)"clackers", /* next_comm_field */
428432
(u64)1000000, /* ts_ns */
433+
(u64)(long)"viewmaster",/* dynstring_field_1 */
429434
(u64)1000, /* ts_ms */
430435
(u64)raw_smp_processor_id(), /* cpu */
431436
(u64)(long)"Thneed", /* my_string_field */
437+
(u64)(long)"yoyos", /* dynstring_field_2 */
432438
(u64)999); /* my_int_field */
433439
return ret;
434440
}

kernel/trace/trace_events_hist.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3289,6 +3289,15 @@ static int check_synth_field(struct synth_event *event,
32893289

32903290
field = event->fields[field_pos];
32913291

3292+
/*
3293+
* A dynamic string synth field can accept static or
3294+
* dynamic. A static string synth field can only accept a
3295+
* same-sized static string, which is checked for later.
3296+
*/
3297+
if (strstr(hist_field->type, "char[") && field->is_string
3298+
&& field->is_dynamic)
3299+
return 0;
3300+
32923301
if (strcmp(field->type, hist_field->type) != 0) {
32933302
if (field->size != hist_field->size ||
32943303
field->is_signed != hist_field->is_signed)

0 commit comments

Comments
 (0)