Commit 63a1e5de authored by Tom Zanussi's avatar Tom Zanussi Committed by Steven Rostedt (VMware)

tracing: Save normal string variables

String variables created as field variables and save variables are
already handled properly by having their values copied when set.  The
same isn't done for normal variables, but needs to be - simply saving
a pointer to a string contained in an old event isn't sufficient,
since that event's data may quickly become overwritten and therefore a
string pointer to it could yield garbage.

This change uses the same mechanism as field variables and simply
appends the new strings to the existing per-element field_var_str[]
array allocated for that purpose.

Link: https://lkml.kernel.org/r/1c1a03798b02e67307412a0c719d1bfb69b13007.1601848695.git.zanussi@kernel.org

Fixes: 02205a67 (tracing: Add support for 'field variables')
Signed-off-by: default avatarTom Zanussi <zanussi@kernel.org>
Signed-off-by: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
parent 8fbeb52a
...@@ -147,6 +147,8 @@ struct hist_field { ...@@ -147,6 +147,8 @@ struct hist_field {
*/ */
unsigned int var_ref_idx; unsigned int var_ref_idx;
bool read_once; bool read_once;
unsigned int var_str_idx;
}; };
static u64 hist_field_none(struct hist_field *field, static u64 hist_field_none(struct hist_field *field,
...@@ -349,6 +351,7 @@ struct hist_trigger_data { ...@@ -349,6 +351,7 @@ struct hist_trigger_data {
unsigned int n_keys; unsigned int n_keys;
unsigned int n_fields; unsigned int n_fields;
unsigned int n_vars; unsigned int n_vars;
unsigned int n_var_str;
unsigned int key_size; unsigned int key_size;
struct tracing_map_sort_key sort_keys[TRACING_MAP_SORT_KEYS_MAX]; struct tracing_map_sort_key sort_keys[TRACING_MAP_SORT_KEYS_MAX];
unsigned int n_sort_keys; unsigned int n_sort_keys;
...@@ -1396,7 +1399,12 @@ static int hist_trigger_elt_data_alloc(struct tracing_map_elt *elt) ...@@ -1396,7 +1399,12 @@ static int hist_trigger_elt_data_alloc(struct tracing_map_elt *elt)
} }
} }
n_str = hist_data->n_field_var_str + hist_data->n_save_var_str; n_str = hist_data->n_field_var_str + hist_data->n_save_var_str +
hist_data->n_var_str;
if (n_str > SYNTH_FIELDS_MAX) {
hist_elt_data_free(elt_data);
return -EINVAL;
}
BUILD_BUG_ON(STR_VAR_LEN_MAX & (sizeof(u64) - 1)); BUILD_BUG_ON(STR_VAR_LEN_MAX & (sizeof(u64) - 1));
...@@ -3653,6 +3661,7 @@ static int create_var_field(struct hist_trigger_data *hist_data, ...@@ -3653,6 +3661,7 @@ static int create_var_field(struct hist_trigger_data *hist_data,
{ {
struct trace_array *tr = hist_data->event_file->tr; struct trace_array *tr = hist_data->event_file->tr;
unsigned long flags = 0; unsigned long flags = 0;
int ret;
if (WARN_ON(val_idx >= TRACING_MAP_VALS_MAX + TRACING_MAP_VARS_MAX)) if (WARN_ON(val_idx >= TRACING_MAP_VALS_MAX + TRACING_MAP_VARS_MAX))
return -EINVAL; return -EINVAL;
...@@ -3667,7 +3676,12 @@ static int create_var_field(struct hist_trigger_data *hist_data, ...@@ -3667,7 +3676,12 @@ static int create_var_field(struct hist_trigger_data *hist_data,
if (WARN_ON(hist_data->n_vars > TRACING_MAP_VARS_MAX)) if (WARN_ON(hist_data->n_vars > TRACING_MAP_VARS_MAX))
return -EINVAL; return -EINVAL;
return __create_val_field(hist_data, val_idx, file, var_name, expr_str, flags); ret = __create_val_field(hist_data, val_idx, file, var_name, expr_str, flags);
if (hist_data->fields[val_idx]->flags & HIST_FIELD_FL_STRING)
hist_data->fields[val_idx]->var_str_idx = hist_data->n_var_str++;
return ret;
} }
static int create_val_fields(struct hist_trigger_data *hist_data, static int create_val_fields(struct hist_trigger_data *hist_data,
...@@ -4394,6 +4408,22 @@ static void hist_trigger_elt_update(struct hist_trigger_data *hist_data, ...@@ -4394,6 +4408,22 @@ static void hist_trigger_elt_update(struct hist_trigger_data *hist_data,
hist_val = hist_field->fn(hist_field, elt, rbe, rec); hist_val = hist_field->fn(hist_field, elt, rbe, rec);
if (hist_field->flags & HIST_FIELD_FL_VAR) { if (hist_field->flags & HIST_FIELD_FL_VAR) {
var_idx = hist_field->var.idx; var_idx = hist_field->var.idx;
if (hist_field->flags & HIST_FIELD_FL_STRING) {
unsigned int str_start, var_str_idx, idx;
char *str, *val_str;
str_start = hist_data->n_field_var_str +
hist_data->n_save_var_str;
var_str_idx = hist_field->var_str_idx;
idx = str_start + var_str_idx;
str = elt_data->field_var_str[idx];
val_str = (char *)(uintptr_t)hist_val;
strscpy(str, val_str, STR_VAR_LEN_MAX);
hist_val = (u64)(uintptr_t)str;
}
tracing_map_set_var(elt, var_idx, hist_val); tracing_map_set_var(elt, var_idx, hist_val);
continue; continue;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment