Skip to content

Commit 0212e2a

Browse files
tzanussirostedt
authored andcommitted
tracing: Add hist trigger action hook
Add a hook for executing extra actions whenever a histogram entry is added or updated. The default 'action' when a hist entry is added to a histogram is to update the set of values associated with it. Some applications may want to perform additional actions at that point, such as generate another event, or compare and save a maximum. Add a simple framework for doing that; specific actions will be implemented on top of it in later patches. Link: http://lkml.kernel.org/r/9482ba6a3eaf5ca6e60954314beacd0e25c05b24.1516069914.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi <tom.zanussi@linux.intel.com> Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
1 parent 067fe03 commit 0212e2a

File tree

1 file changed

+104
-2
lines changed

1 file changed

+104
-2
lines changed

kernel/trace/trace_events_hist.c

Lines changed: 104 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ typedef u64 (*hist_field_fn_t) (struct hist_field *field,
3333

3434
#define HIST_FIELD_OPERANDS_MAX 2
3535
#define HIST_FIELDS_MAX (TRACING_MAP_FIELDS_MAX + TRACING_MAP_VARS_MAX)
36+
#define HIST_ACTIONS_MAX 8
3637

3738
enum field_op_id {
3839
FIELD_OP_NONE,
@@ -242,6 +243,9 @@ struct hist_trigger_attrs {
242243
char *assignment_str[TRACING_MAP_VARS_MAX];
243244
unsigned int n_assignments;
244245

246+
char *action_str[HIST_ACTIONS_MAX];
247+
unsigned int n_actions;
248+
245249
struct var_defs var_defs;
246250
};
247251

@@ -261,6 +265,21 @@ struct hist_trigger_data {
261265
bool remove;
262266
struct hist_field *var_refs[TRACING_MAP_VARS_MAX];
263267
unsigned int n_var_refs;
268+
269+
struct action_data *actions[HIST_ACTIONS_MAX];
270+
unsigned int n_actions;
271+
};
272+
273+
struct action_data;
274+
275+
typedef void (*action_fn_t) (struct hist_trigger_data *hist_data,
276+
struct tracing_map_elt *elt, void *rec,
277+
struct ring_buffer_event *rbe,
278+
struct action_data *data, u64 *var_ref_vals);
279+
280+
struct action_data {
281+
action_fn_t fn;
282+
unsigned int var_ref_idx;
264283
};
265284

266285
static u64 hist_field_timestamp(struct hist_field *hist_field,
@@ -764,13 +783,26 @@ static void destroy_hist_trigger_attrs(struct hist_trigger_attrs *attrs)
764783
for (i = 0; i < attrs->n_assignments; i++)
765784
kfree(attrs->assignment_str[i]);
766785

786+
for (i = 0; i < attrs->n_actions; i++)
787+
kfree(attrs->action_str[i]);
788+
767789
kfree(attrs->name);
768790
kfree(attrs->sort_key_str);
769791
kfree(attrs->keys_str);
770792
kfree(attrs->vals_str);
771793
kfree(attrs);
772794
}
773795

796+
static int parse_action(char *str, struct hist_trigger_attrs *attrs)
797+
{
798+
int ret = 0;
799+
800+
if (attrs->n_actions >= HIST_ACTIONS_MAX)
801+
return ret;
802+
803+
return ret;
804+
}
805+
774806
static int parse_assignment(char *str, struct hist_trigger_attrs *attrs)
775807
{
776808
int ret = 0;
@@ -854,8 +886,9 @@ static struct hist_trigger_attrs *parse_hist_trigger_attrs(char *trigger_str)
854886
else if (strcmp(str, "clear") == 0)
855887
attrs->clear = true;
856888
else {
857-
ret = -EINVAL;
858-
goto free;
889+
ret = parse_action(str, attrs);
890+
if (ret)
891+
goto free;
859892
}
860893
}
861894

@@ -2047,11 +2080,55 @@ static int create_sort_keys(struct hist_trigger_data *hist_data)
20472080
return ret;
20482081
}
20492082

2083+
static void destroy_actions(struct hist_trigger_data *hist_data)
2084+
{
2085+
unsigned int i;
2086+
2087+
for (i = 0; i < hist_data->n_actions; i++) {
2088+
struct action_data *data = hist_data->actions[i];
2089+
2090+
kfree(data);
2091+
}
2092+
}
2093+
2094+
static int parse_actions(struct hist_trigger_data *hist_data)
2095+
{
2096+
unsigned int i;
2097+
int ret = 0;
2098+
char *str;
2099+
2100+
for (i = 0; i < hist_data->attrs->n_actions; i++) {
2101+
str = hist_data->attrs->action_str[i];
2102+
}
2103+
2104+
return ret;
2105+
}
2106+
2107+
static int create_actions(struct hist_trigger_data *hist_data,
2108+
struct trace_event_file *file)
2109+
{
2110+
struct action_data *data;
2111+
unsigned int i;
2112+
int ret = 0;
2113+
2114+
for (i = 0; i < hist_data->attrs->n_actions; i++) {
2115+
data = hist_data->actions[i];
2116+
}
2117+
2118+
return ret;
2119+
}
2120+
20502121
static void destroy_hist_data(struct hist_trigger_data *hist_data)
20512122
{
2123+
if (!hist_data)
2124+
return;
2125+
20522126
destroy_hist_trigger_attrs(hist_data->attrs);
20532127
destroy_hist_fields(hist_data);
20542128
tracing_map_destroy(hist_data->map);
2129+
2130+
destroy_actions(hist_data);
2131+
20552132
kfree(hist_data);
20562133
}
20572134

@@ -2118,6 +2195,10 @@ create_hist_data(unsigned int map_bits,
21182195
hist_data->remove = remove;
21192196
hist_data->event_file = file;
21202197

2198+
ret = parse_actions(hist_data);
2199+
if (ret)
2200+
goto free;
2201+
21212202
ret = create_hist_fields(hist_data, file);
21222203
if (ret)
21232204
goto free;
@@ -2209,6 +2290,20 @@ static inline void add_to_key(char *compound_key, void *key,
22092290
memcpy(compound_key + key_field->offset, key, size);
22102291
}
22112292

2293+
static void
2294+
hist_trigger_actions(struct hist_trigger_data *hist_data,
2295+
struct tracing_map_elt *elt, void *rec,
2296+
struct ring_buffer_event *rbe, u64 *var_ref_vals)
2297+
{
2298+
struct action_data *data;
2299+
unsigned int i;
2300+
2301+
for (i = 0; i < hist_data->n_actions; i++) {
2302+
data = hist_data->actions[i];
2303+
data->fn(hist_data, elt, rec, rbe, data, var_ref_vals);
2304+
}
2305+
}
2306+
22122307
static void event_hist_trigger(struct event_trigger_data *data, void *rec,
22132308
struct ring_buffer_event *rbe)
22142309
{
@@ -2264,6 +2359,9 @@ static void event_hist_trigger(struct event_trigger_data *data, void *rec,
22642359
return;
22652360

22662361
hist_trigger_elt_update(hist_data, elt, rec, rbe, var_ref_vals);
2362+
2363+
if (resolve_var_refs(hist_data, key, var_ref_vals, true))
2364+
hist_trigger_actions(hist_data, elt, rec, rbe, var_ref_vals);
22672365
}
22682366

22692367
static void hist_trigger_stacktrace_print(struct seq_file *m,
@@ -3048,6 +3146,10 @@ static int event_hist_trigger_func(struct event_command *cmd_ops,
30483146
if (has_hist_vars(hist_data))
30493147
save_hist_vars(hist_data);
30503148

3149+
ret = create_actions(hist_data, file);
3150+
if (ret)
3151+
goto out_unreg;
3152+
30513153
ret = tracing_map_init(hist_data->map);
30523154
if (ret)
30533155
goto out_unreg;

0 commit comments

Comments
 (0)