From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: Fri, 15 Dec 2017 18:49:49 +0100
Subject: tracing: Update the "tracing: Inter-event (e.g. latency) support"
patch
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git
Git-commit: a2cbddd92900d1cbb667c36780b03832eaf6b16f
Patch-mainline: Queued in subsystem maintainer repository
References: SLE Realtime Extension
This commit is an all-in-one update of Tom Zanussi's "tracing: Inter-event
(e.g. latency) support" series from v8 to v9 as posted on 2018-01-16. It
includes the following patches:
tracing: Move hist trigger Documentation to histogram.txt
tracing: Add Documentation for log2 modifier
tracing: Add support to detect and avoid duplicates
tracing: Remove code which merges duplicates
ring-buffer: Add interface for setting absolute time stamps
ring-buffer: Redefine the unimplemented RINGBUF_TYPE_TIME_STAMP
tracing: Add timestamp_mode trace file
tracing: Give event triggers access to ring_buffer_event
tracing: Add ring buffer event param to hist field functions
tracing: Break out hist trigger assignment parsing
tracing: Add hist trigger timestamp support
tracing: Add per-element variable support to tracing_map
tracing: Add hist_data member to hist_field
tracing: Add usecs modifier for hist trigger timestamps
tracing: Add variable support to hist triggers
tracing: Account for variables in named trigger compatibility
tracing: Move get_hist_field_flags()
tracing: Add simple expression support to hist triggers
tracing: Generalize per-element hist trigger data
tracing: Pass tracing_map_elt to hist_field accessor functions
tracing: Add hist_field 'type' field
tracing: Add variable reference handling to hist triggers
tracing: Add hist trigger action hook
tracing: Add support for 'synthetic' events
tracing: Add support for 'field variables'
tracing: Add 'onmatch' hist trigger action support
tracing: Add 'onmax' hist trigger action support
tracing: Allow whitespace to surround hist trigger filter
tracing: Add cpu field for hist triggers
tracing: Add hist trigger support for variable reference aliases
tracing: Add 'last error' error facility for hist triggers
tracing: Add inter-event hist trigger Documentation
tracing: Make tracing_set_clock() non-static
tracing: Add a clock attribute for hist triggers
tracing: Increase trace_recursive_lock() limit for synthetic events
tracing: Add inter-event blurb to HIST_TRIGGERS config option
selftests: ftrace: Add inter-event hist triggers testcases
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Mike Galbraith <mgalbraith@suse.de>
---
kernel/trace/trace_events_hist.c | 105 +++++++++++++++++++++------------------
1 file changed, 58 insertions(+), 47 deletions(-)
--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -1108,7 +1108,7 @@ static int release_all_synth_events(void
{
struct list_head release_events;
struct synth_event *event, *e;
- int ret = 0, err = 0;
+ int ret = 0;
INIT_LIST_HEAD(&release_events);
@@ -1121,8 +1121,7 @@ static int release_all_synth_events(void
}
}
- list_for_each_entry_safe(event, e, &synth_event_list, list)
- list_move(&event->list, &release_events);
+ list_splice_init(&event->list, &release_events);
mutex_unlock(&synth_event_mutex);
@@ -1133,9 +1132,6 @@ static int release_all_synth_events(void
add_or_delete_synth_event(event, !ret);
}
- if (err)
- ret = err;
-
return ret;
}
@@ -1267,7 +1263,7 @@ check_field_for_var_refs(struct hist_tri
struct hist_field *found = NULL;
unsigned int i;
- if (level > 2)
+ if (level > 3)
return found;
if (!hist_field)
@@ -1373,7 +1369,7 @@ static bool field_has_hist_vars(struct h
{
int i;
- if (level > 2)
+ if (level > 3)
return false;
if (!hist_field)
@@ -2040,6 +2036,23 @@ static const char *get_hist_field_flags(
return flags_str;
}
+static void expr_field_str(struct hist_field *field, char *expr)
+{
+ if (field->flags & HIST_FIELD_FL_VAR_REF)
+ strcat(expr, "$");
+
+ strcat(expr, hist_field_name(field, 0));
+
+ if (field->flags) {
+ const char *flags_str = get_hist_field_flags(field);
+
+ if (flags_str) {
+ strcat(expr, ".");
+ strcat(expr, flags_str);
+ }
+ }
+}
+
static char *expr_str(struct hist_field *field, unsigned int level)
{
char *expr;
@@ -2051,6 +2064,11 @@ static char *expr_str(struct hist_field
if (!expr)
return NULL;
+ if (!field->operands[0]) {
+ expr_field_str(field, expr);
+ return expr;
+ }
+
if (field->operator == FIELD_OP_UNARY_MINUS) {
char *subexpr;
@@ -2068,17 +2086,7 @@ static char *expr_str(struct hist_field
return expr;
}
- if (field->operands[0]->flags & HIST_FIELD_FL_VAR_REF)
- strcat(expr, "$");
- strcat(expr, hist_field_name(field->operands[0], 0));
- if (field->operands[0]->flags) {
- const char *flags_str = get_hist_field_flags(field->operands[0]);
-
- if (flags_str) {
- strcat(expr, ".");
- strcat(expr, flags_str);
- }
- }
+ expr_field_str(field->operands[0], expr);
switch (field->operator) {
case FIELD_OP_MINUS:
@@ -2092,17 +2100,7 @@ static char *expr_str(struct hist_field
return NULL;
}
- if (field->operands[1]->flags & HIST_FIELD_FL_VAR_REF)
- strcat(expr, "$");
- strcat(expr, hist_field_name(field->operands[1], 0));
- if (field->operands[1]->flags) {
- const char *flags_str = get_hist_field_flags(field->operands[1]);
-
- if (flags_str) {
- strcat(expr, ".");
- strcat(expr, flags_str);
- }
- }
+ expr_field_str(field->operands[1], expr);
return expr;
}
@@ -2138,7 +2136,7 @@ static void destroy_hist_field(struct hi
{
unsigned int i;
- if (level > 2)
+ if (level > 3)
return;
if (!hist_field)
@@ -2290,6 +2288,8 @@ static int init_var_ref(struct hist_fiel
ref_field->var.hist_data = var_field->hist_data;
ref_field->size = var_field->size;
ref_field->is_signed = var_field->is_signed;
+ ref_field->flags |= var_field->flags &
+ (HIST_FIELD_FL_TIMESTAMP | HIST_FIELD_FL_TIMESTAMP_USECS);
if (system) {
ref_field->system = kstrdup(system, GFP_KERNEL);
@@ -2305,10 +2305,18 @@ static int init_var_ref(struct hist_fiel
}
}
- ref_field->name = kstrdup(var_field->var.name, GFP_KERNEL);
- if (!ref_field->name) {
- err = -ENOMEM;
- goto free;
+ if (var_field->var.name) {
+ ref_field->name = kstrdup(var_field->var.name, GFP_KERNEL);
+ if (!ref_field->name) {
+ err = -ENOMEM;
+ goto free;
+ }
+ } else if (var_field->name) {
+ ref_field->name = kstrdup(var_field->name, GFP_KERNEL);
+ if (!ref_field->name) {
+ err = -ENOMEM;
+ goto free;
+ }
}
ref_field->type = kstrdup(var_field->type, GFP_KERNEL);
@@ -2496,9 +2504,9 @@ static struct hist_field *create_alias(s
return alias;
}
-struct hist_field *parse_atom(struct hist_trigger_data *hist_data,
- struct trace_event_file *file, char *str,
- unsigned long *flags, char *var_name)
+static struct hist_field *parse_atom(struct hist_trigger_data *hist_data,
+ struct trace_event_file *file, char *str,
+ unsigned long *flags, char *var_name)
{
char *s, *ref_system = NULL, *ref_event = NULL, *ref_var = str;
struct ftrace_event_field *field = NULL;
@@ -2575,7 +2583,8 @@ static struct hist_field *parse_unary(st
// we support only -(xxx) i.e. explicit parens required
- if (level > 2) {
+ if (level > 3) {
+ hist_err("Too many subexpressions (3 max): ", str);
ret = -EINVAL;
goto free;
}
@@ -2590,7 +2599,7 @@ static struct hist_field *parse_unary(st
goto free;
}
- s = strchr(str, ')');
+ s = strrchr(str, ')');
if (s)
*s = '\0';
else {
@@ -2598,12 +2607,6 @@ static struct hist_field *parse_unary(st
goto free;
}
- strsep(&str, "(");
- if (!str) {
- ret = -EINVAL;
- goto free;
- }
-
flags |= HIST_FIELD_FL_EXPR;
expr = create_hist_field(hist_data, NULL, flags, var_name);
if (!expr) {
@@ -2618,6 +2621,8 @@ static struct hist_field *parse_unary(st
goto free;
}
+ expr->flags |= operand1->flags &
+ (HIST_FIELD_FL_TIMESTAMP | HIST_FIELD_FL_TIMESTAMP_USECS);
expr->fn = hist_field_unary_minus;
expr->operands[0] = operand1;
expr->operator = FIELD_OP_UNARY_MINUS;
@@ -2679,8 +2684,10 @@ static struct hist_field *parse_expr(str
int field_op, ret = -EINVAL;
char *sep, *operand1_str;
- if (level > 2)
+ if (level > 3) {
+ hist_err("Too many subexpressions (3 max): ", str);
return ERR_PTR(-EINVAL);
+ }
field_op = contains_operator(str);
@@ -2728,6 +2735,10 @@ static struct hist_field *parse_expr(str
goto free;
flags |= HIST_FIELD_FL_EXPR;
+
+ flags |= operand1->flags &
+ (HIST_FIELD_FL_TIMESTAMP | HIST_FIELD_FL_TIMESTAMP_USECS);
+
expr = create_hist_field(hist_data, NULL, flags, var_name);
if (!expr) {
ret = -ENOMEM;