Skip to content

Commit 63a1e5d

Browse files
Tom Zanussirostedt
authored andcommitted
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: 02205a6 (tracing: Add support for 'field variables') Signed-off-by: Tom Zanussi <[email protected]> Signed-off-by: Steven Rostedt (VMware) <[email protected]>
1 parent 8fbeb52 commit 63a1e5d

File tree

1 file changed

+32
-2
lines changed

1 file changed

+32
-2
lines changed

kernel/trace/trace_events_hist.c

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ struct hist_field {
147147
*/
148148
unsigned int var_ref_idx;
149149
bool read_once;
150+
151+
unsigned int var_str_idx;
150152
};
151153

152154
static u64 hist_field_none(struct hist_field *field,
@@ -349,6 +351,7 @@ struct hist_trigger_data {
349351
unsigned int n_keys;
350352
unsigned int n_fields;
351353
unsigned int n_vars;
354+
unsigned int n_var_str;
352355
unsigned int key_size;
353356
struct tracing_map_sort_key sort_keys[TRACING_MAP_SORT_KEYS_MAX];
354357
unsigned int n_sort_keys;
@@ -1396,7 +1399,12 @@ static int hist_trigger_elt_data_alloc(struct tracing_map_elt *elt)
13961399
}
13971400
}
13981401

1399-
n_str = hist_data->n_field_var_str + hist_data->n_save_var_str;
1402+
n_str = hist_data->n_field_var_str + hist_data->n_save_var_str +
1403+
hist_data->n_var_str;
1404+
if (n_str > SYNTH_FIELDS_MAX) {
1405+
hist_elt_data_free(elt_data);
1406+
return -EINVAL;
1407+
}
14001408

14011409
BUILD_BUG_ON(STR_VAR_LEN_MAX & (sizeof(u64) - 1));
14021410

@@ -3653,6 +3661,7 @@ static int create_var_field(struct hist_trigger_data *hist_data,
36533661
{
36543662
struct trace_array *tr = hist_data->event_file->tr;
36553663
unsigned long flags = 0;
3664+
int ret;
36563665

36573666
if (WARN_ON(val_idx >= TRACING_MAP_VALS_MAX + TRACING_MAP_VARS_MAX))
36583667
return -EINVAL;
@@ -3667,7 +3676,12 @@ static int create_var_field(struct hist_trigger_data *hist_data,
36673676
if (WARN_ON(hist_data->n_vars > TRACING_MAP_VARS_MAX))
36683677
return -EINVAL;
36693678

3670-
return __create_val_field(hist_data, val_idx, file, var_name, expr_str, flags);
3679+
ret = __create_val_field(hist_data, val_idx, file, var_name, expr_str, flags);
3680+
3681+
if (hist_data->fields[val_idx]->flags & HIST_FIELD_FL_STRING)
3682+
hist_data->fields[val_idx]->var_str_idx = hist_data->n_var_str++;
3683+
3684+
return ret;
36713685
}
36723686

36733687
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,
43944408
hist_val = hist_field->fn(hist_field, elt, rbe, rec);
43954409
if (hist_field->flags & HIST_FIELD_FL_VAR) {
43964410
var_idx = hist_field->var.idx;
4411+
4412+
if (hist_field->flags & HIST_FIELD_FL_STRING) {
4413+
unsigned int str_start, var_str_idx, idx;
4414+
char *str, *val_str;
4415+
4416+
str_start = hist_data->n_field_var_str +
4417+
hist_data->n_save_var_str;
4418+
var_str_idx = hist_field->var_str_idx;
4419+
idx = str_start + var_str_idx;
4420+
4421+
str = elt_data->field_var_str[idx];
4422+
val_str = (char *)(uintptr_t)hist_val;
4423+
strscpy(str, val_str, STR_VAR_LEN_MAX);
4424+
4425+
hist_val = (u64)(uintptr_t)str;
4426+
}
43974427
tracing_map_set_var(elt, var_idx, hist_val);
43984428
continue;
43994429
}

0 commit comments

Comments
 (0)