@@ -33,6 +33,7 @@ typedef u64 (*hist_field_fn_t) (struct hist_field *field,
33
33
34
34
#define HIST_FIELD_OPERANDS_MAX 2
35
35
#define HIST_FIELDS_MAX (TRACING_MAP_FIELDS_MAX + TRACING_MAP_VARS_MAX)
36
+ #define HIST_ACTIONS_MAX 8
36
37
37
38
enum field_op_id {
38
39
FIELD_OP_NONE ,
@@ -242,6 +243,9 @@ struct hist_trigger_attrs {
242
243
char * assignment_str [TRACING_MAP_VARS_MAX ];
243
244
unsigned int n_assignments ;
244
245
246
+ char * action_str [HIST_ACTIONS_MAX ];
247
+ unsigned int n_actions ;
248
+
245
249
struct var_defs var_defs ;
246
250
};
247
251
@@ -261,6 +265,21 @@ struct hist_trigger_data {
261
265
bool remove ;
262
266
struct hist_field * var_refs [TRACING_MAP_VARS_MAX ];
263
267
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 ;
264
283
};
265
284
266
285
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)
764
783
for (i = 0 ; i < attrs -> n_assignments ; i ++ )
765
784
kfree (attrs -> assignment_str [i ]);
766
785
786
+ for (i = 0 ; i < attrs -> n_actions ; i ++ )
787
+ kfree (attrs -> action_str [i ]);
788
+
767
789
kfree (attrs -> name );
768
790
kfree (attrs -> sort_key_str );
769
791
kfree (attrs -> keys_str );
770
792
kfree (attrs -> vals_str );
771
793
kfree (attrs );
772
794
}
773
795
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
+
774
806
static int parse_assignment (char * str , struct hist_trigger_attrs * attrs )
775
807
{
776
808
int ret = 0 ;
@@ -854,8 +886,9 @@ static struct hist_trigger_attrs *parse_hist_trigger_attrs(char *trigger_str)
854
886
else if (strcmp (str , "clear" ) == 0 )
855
887
attrs -> clear = true;
856
888
else {
857
- ret = - EINVAL ;
858
- goto free ;
889
+ ret = parse_action (str , attrs );
890
+ if (ret )
891
+ goto free ;
859
892
}
860
893
}
861
894
@@ -2047,11 +2080,55 @@ static int create_sort_keys(struct hist_trigger_data *hist_data)
2047
2080
return ret ;
2048
2081
}
2049
2082
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
+
2050
2121
static void destroy_hist_data (struct hist_trigger_data * hist_data )
2051
2122
{
2123
+ if (!hist_data )
2124
+ return ;
2125
+
2052
2126
destroy_hist_trigger_attrs (hist_data -> attrs );
2053
2127
destroy_hist_fields (hist_data );
2054
2128
tracing_map_destroy (hist_data -> map );
2129
+
2130
+ destroy_actions (hist_data );
2131
+
2055
2132
kfree (hist_data );
2056
2133
}
2057
2134
@@ -2118,6 +2195,10 @@ create_hist_data(unsigned int map_bits,
2118
2195
hist_data -> remove = remove ;
2119
2196
hist_data -> event_file = file ;
2120
2197
2198
+ ret = parse_actions (hist_data );
2199
+ if (ret )
2200
+ goto free ;
2201
+
2121
2202
ret = create_hist_fields (hist_data , file );
2122
2203
if (ret )
2123
2204
goto free ;
@@ -2209,6 +2290,20 @@ static inline void add_to_key(char *compound_key, void *key,
2209
2290
memcpy (compound_key + key_field -> offset , key , size );
2210
2291
}
2211
2292
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
+
2212
2307
static void event_hist_trigger (struct event_trigger_data * data , void * rec ,
2213
2308
struct ring_buffer_event * rbe )
2214
2309
{
@@ -2264,6 +2359,9 @@ static void event_hist_trigger(struct event_trigger_data *data, void *rec,
2264
2359
return ;
2265
2360
2266
2361
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 );
2267
2365
}
2268
2366
2269
2367
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,
3048
3146
if (has_hist_vars (hist_data ))
3049
3147
save_hist_vars (hist_data );
3050
3148
3149
+ ret = create_actions (hist_data , file );
3150
+ if (ret )
3151
+ goto out_unreg ;
3152
+
3051
3153
ret = tracing_map_init (hist_data -> map );
3052
3154
if (ret )
3053
3155
goto out_unreg ;
0 commit comments