tracing: Clean up trigger code my merging structures
cover tracing: Clean up trigger code my merging structures
The struct event_command has a callback function called get_trigger_ops(). This callback returns the "trigger_ops" to use for the trigger. These ops define the trigger function, how to init the trigger, how to print the trigger and how to free it.
The only reason there's a callback function to get these ops is because some triggers have two types of operations. One is an "always on" operation, and the other is a "count down" operation. If a user passes in a parameter to say how many times the trigger should execute. For example:
echo stacktrace:5 > events/kmem/kmem_cache_alloc/trigger
It will trigger the stacktrace for the first 5 times the kmem_cache_alloc event is hit.
Instead of having two different trigger_ops since the only difference between them is the tigger itself (the print, init and free functions are all the same), just use a single ops that the event_command points to and add a function field to the trigger_ops to have a count_func.
When a trigger is added to an event, if there's a count attached to it and the trigger ops has the count_func field, the data allocated to represent this trigger will have a new flag set called COUNT.
Then when the trigger executes, it will check if the COUNT data flag is set, and if so, it will call the ops count_func(). If that returns false, it returns without executing the trigger.
After making the struct event_trigger_ops be mapped one to one with the struct event_command, merge the former into the latter.
Steven Rostedt (2):
tracing: Remove get_trigger_ops() and add count_func() from trigger ops
tracing: Merge struct event_trigger_ops into struct event_command
----
kernel/trace/trace.h | 124 ++++++------- kernel/trace/trace_eprobe.c | 19 +- kernel/trace/trace_events_hist.c | 143 +++++---------- kernel/trace/trace_events_trigger.c | 344 +++++++++++++----------------------- 4 files changed, 231 insertions(+), 399 deletions(-)
PATCH 1/2 tracing: Remove get_trigger_ops() and add count_func() from trigger ops
From: Steven Rostedt <[email protected]>
The struct event_command has a callback function called get_trigger_ops(). This callback returns the "trigger_ops" to use for the trigger. These ops define the trigger function, how to init the trigger, how to print the trigger and how to free it.
The only reason there's a callback function to get these ops is because some triggers have two types of operations. One is an "always on" operation, and the other is a "count down" operation. If a user passes in a parameter to say how many times the trigger should execute. For example:
echo stacktrace:5 > events/kmem/kmem_cache_alloc/trigger
It will trigger the stacktrace for the first 5 times the kmem_cache_alloc event is hit.
Instead of having two different trigger_ops since the only difference between them is the tigger itself (the print, init and free functions are all the same), just use a single ops that the event_command points to and add a function field to the trigger_ops to have a count_func.
When a trigger is added to an event, if there's a count attached to it and the trigger ops has the count_func field, the data allocated to represent this trigger will have a new flag set called COUNT.
Then when the trigger executes, it will check if the COUNT data flag is set, and if so, it will call the ops count_func(). If that returns false, it returns without executing the trigger.
This removes the need for duplicate event_trigger_ops structures.
--- kernel/trace/trace.h | 26 ++- kernel/trace/trace_eprobe.c | 8 +- kernel/trace/trace_events_hist.c | 60 +------ kernel/trace/trace_events_trigger.c | 257 ++++++++++------------------ 4 files changed, 116 insertions(+), 235 deletions(-)
kernel/trace/trace.h +18 -8
@@ -1791,6 +1791,7 @@ extern void clear_event_triggers(struct trace_array *tr);enum {EVENT_TRIGGER_FL_PROBE =BIT (0 ), +EVENT_TRIGGER_FL_COUNT =BIT (1 ), };struct event_trigger_data {
@@ -1822,6 +1823,10 @@ struct enable_trigger_data {bool hist; }; +bool event_trigger_count (struct event_trigger_data *data, +struct trace_buffer *buffer,void *rec, +struct ring_buffer_event *event); +extern int event_enable_trigger_print (struct seq_file *m,struct event_trigger_data *data);extern void event_enable_trigger_free (struct event_trigger_data *data);
@@ -1909,6 +1914,11 @@ extern void event_file_put(struct trace_event_file *file);* registered the trigger (see struct event_command) along with * the trace record, rec. * +* @count_func: If defined and a numeric parameter is passed to the +* trigger, then this function will be called before @trigger +* is called. If this function returns false, then @trigger is not +* executed. +* * @init: An optional initialization function called for the trigger * when the trigger is registered (via the event_command reg() * function). This can be used to perform per-trigger
@@ -1936,6 +1946,10 @@ struct event_trigger_ops {struct trace_buffer *buffer, void *rec, struct ring_buffer_event *rbe); +bool (*count_func)(struct event_trigger_data *data, +struct trace_buffer *buffer, +void *rec, +struct ring_buffer_event *rbe);int (*init)(struct event_trigger_data *data);void (*free)(struct event_trigger_data *data); int (*print)(struct seq_file *m,
@@ -1962,6 +1976,9 @@ struct event_trigger_ops {* @name: The unique name that identifies the event command. This is * the name used when setting triggers via trigger files. * +* @trigger_ops: The event_trigger_ops implementation associated with +* the command. +* * @trigger_type: A unique id that identifies the event command * 'type'. This value has two purposes, the first to ensure that * only one trigger of the same type can be set at a given time
@@ -2013,17 +2030,11 @@ struct event_trigger_ops {* event command, filters set by the user for the command will be * ignored. This is usually implemented by the generic utility * function @set_trigger_filter() (see trace_event_triggers.c). -* -* @get_trigger_ops: The callback function invoked to retrieve the -* event_trigger_ops implementation associated with the command. -* This callback function allows a single event_command to -* support multiple trigger implementations via different sets of -* event_trigger_ops, depending on the value of the @param -* string. */ struct event_command {struct list_head list;char *name; +const struct event_trigger_ops *trigger_ops;enum event_trigger_type trigger_type;int flags; int (*parse)(struct event_command *cmd_ops,
@@ -2040,7 +2051,6 @@ struct event_command {int (*set_filter)(char *filter_str,struct event_trigger_data *data,struct trace_event_file *file); -const struct event_trigger_ops *(*get_trigger_ops)(char *cmd,char *param); };/**
kernel/trace/trace_eprobe.c +1 -7
@@ -513,21 +513,15 @@ static void eprobe_trigger_unreg_func(char *glob, } -static const struct event_trigger_ops *eprobe_trigger_get_ops (char *cmd, -char *param) -{ -return &eprobe_trigger_ops; -} -static struct event_command event_trigger_cmd = { .name ="eprobe" , .trigger_type =ETT_EVENT_EPROBE , .flags =EVENT_CMD_FL_NEEDS_REC , + .trigger_ops = &eprobe_trigger_ops, .parse = eprobe_trigger_cmd_parse, .reg = eprobe_trigger_reg_func, .unreg = eprobe_trigger_unreg_func, .unreg_all =NULL , - .get_trigger_ops = eprobe_trigger_get_ops, .set_filter =NULL , };
kernel/trace/trace_events_hist.c +5 -55
115 lines not on this page · raw message
kernel/trace/trace_events_trigger.c +92 -165
476 lines not on this page · raw message
Signature · 1 line
2.51.0
Re: [PATCH 1/2] tracing: Remove get_trigger_ops() and add count_func() from trigger ops
Hi Steve,
Quoted 26 lines · Steven Rostedt
From: Steven Rostedt <[email protected]>
The struct
event_commandhas a callback function calledget_trigger_ops(). This callback returns the "trigger_ops" to use for the trigger. These ops define the trigger function, how to init the trigger, how to print the trigger and how to free it.The only reason there's a callback function to get these ops is because some triggers have two types of operations. One is an "always on" operation, and the other is a "count down" operation. If a user passes in a parameter to say how many times the trigger should execute. For example:
echo stacktrace:5 > events/kmem/kmem_cache_alloc/trigger
It will trigger the stacktrace for the first 5 times the
kmem_cache_allocevent is hit.Instead of having two different
trigger_opssince the only difference between them is the tigger itself (the print, init and free functions are all the same), just use a single ops that theevent_commandpoints to and add a function field to thetrigger_opsto have acount_func.When a trigger is added to an event, if there's a count attached to it and the trigger ops has the
count_funcfield, the data allocated to represent this trigger will have a new flag set called COUNT.
Quoted 7 lines
Then when the trigger executes, it will check if the COUNT data flag is set, and if so, it will call the ops
count_func(). If that returns false, it returns without executing the trigger.This removes the need for duplicate
event_trigger_opsstructures.Signed-off-by Steven Rostedt (Google) <[email protected]>
Very nice cleanup, thanks!
Quoted 741 lines
---
kernel/trace/trace.h | 26 ++- kernel/trace/trace_eprobe.c | 8 +- kernel/trace/trace_events_hist.c | 60 +------kernel/trace/trace_events_trigger.c| 257 ++++++++++------------------4 files changed, 116 insertions(+), 235 deletions(-)kernel/trace/trace.h +0
-0@@ -1791,6 +1791,7 @@ extern void clear_event_triggers(struct trace_array *tr);
enum {
EVENT_TRIGGER_FL_PROBE= BIT(0),kernel/trace/trace.h +1
-0+ EVENT_TRIGGER_FL_COUNT = BIT(1),};
structevent_trigger_data{kernel/trace/trace.h +0
-0@@ -1822,6 +1823,10 @@ struct enable_trigger_data { bool hist; };kernel/trace/trace.h +4
-0+bool event_trigger_count (struct event_trigger_data *data, + struct trace_buffer *buffer, void *rec, +struct ring_buffer_event *event); +extern int
event_enable_trigger_print(struct seq_file *m, struct event_trigger_data *data); extern voidevent_enable_trigger_free(struct event_trigger_data *data);kernel/trace/trace.h +13
-8@@ -1909,6 +1914,11 @@ extern void event_file_put(struct trace_event_file *file); * registered the trigger (see struct event_command) along with * the trace record, rec. * + * @count_func: If defined and a numeric parameter is passed to the + * trigger, then this function will be called before @trigger + * is called. If this function returns false, then @trigger is not + * executed. + * * @init: An optional initialization function called for the trigger * when the trigger is registered (via the event_command reg() * function). This can be used to perform per-trigger@@ -1936,6 +1946,10 @@ struct event_trigger_ops { struct trace_buffer *buffer, void *rec, struct ring_buffer_event *rbe); +bool (*count_func)(struct event_trigger_data *data, + struct trace_buffer *buffer, + void *rec, + struct ring_buffer_event *rbe); int (*init)(struct event_trigger_data *data); void (*free)(struct event_trigger_data *data); int (*print)(struct seq_file *m,@@ -1962,6 +1976,9 @@ struct event_trigger_ops { * @name: The unique name that identifies the event command. This is * the name used when setting triggers via trigger files. * + * @trigger_ops: The event_trigger_ops implementation associated with + * the command. + * * @trigger_type: A unique id that identifies the event command * 'type'. This value has two purposes, the first to ensure that * only one trigger of the same type can be set at a given time@@ -2013,17 +2030,11 @@ struct event_trigger_ops {* event command, filters set by the user for the command will be * ignored. This is usually implemented by the generic utility * function @set_trigger_filter() (see trace_event_triggers.c). -* -* @get_trigger_ops: The callback function invoked to retrieve the -* event_trigger_ops implementation associated with the command. -* This callback function allows a single event_command to -* support multiple trigger implementations via different sets of -* event_trigger_ops, depending on the value of the @param -* string. */ struct event_command { struct list_head list; char *name; +const struct event_trigger_ops *trigger_ops; enum event_trigger_type trigger_type; int flags; int (*parse)(struct event_command *cmd_ops,@@ -2040,7 +2051,6 @@ struct event_command { int (*set_filter)(char *filter_str, struct event_trigger_data *data, struct trace_event_file *file); -const struct event_trigger_ops *(*get_trigger_ops)(char *cmd,char *param); };
/**kernel/trace/trace_eprobe.c +0
-0@@ -513,21 +513,15 @@ static void eprobe_trigger_unreg_func(char *glob,
}kernel/trace/trace_eprobe.c +0
-6-static const struct event_trigger_ops *eprobe_trigger_get_ops (char *cmd, - char *param) -{ -return &eprobe_trigger_ops; -} -static struct
event_commandevent_trigger_cmd= {
.name = "eprobe",
.trigger_type =ETT_EVENT_EPROBE,
.flags =EVENT_CMD_FL_NEEDS_REC,kernel/trace/trace_eprobe.c +1
-0+ .trigger_ops = &eprobe_trigger_ops,.parse =
eprobe_trigger_cmd_parse,
.reg =eprobe_trigger_reg_func,
.unreg =eprobe_trigger_unreg_func,
.unreg_all = NULL,kernel/trace/trace_eprobe.c +0
-1- .get_trigger_ops = eprobe_trigger_get_ops,.set_filter = NULL,
};kernel/trace/trace_events_hist.c +0
-0@@ -6363,12 +6363,6 @@ static const struct event_trigger_ops event_hist_trigger_named_ops = { .free = event_hist_trigger_named_free, };kernel/trace/trace_events_hist.c +0
-6-static const struct event_trigger_ops *event_hist_get_trigger_ops (char *cmd, - char *param) -{ -return &event_hist_trigger_ops; -} -static void
hist_clear(struct event_trigger_data *data){
structhist_trigger_data*hist_data=data->private_data;kernel/trace/trace_events_hist.c +1
-1@@ -6908,11 +6902,11 @@ static struct event_command trigger_hist_cmd = { .name = "hist", .trigger_type = ETT_EVENT_HIST, .flags = EVENT_CMD_FL_NEEDS_REC, + .trigger_ops = &event_hist_trigger_ops, .parse = event_hist_trigger_parse, .reg = hist_register_trigger, .unreg = hist_unregister_trigger, .unreg_all = hist_unreg_all, - .get_trigger_ops = event_hist_get_trigger_ops, .set_filter = set_trigger_filter, };kernel/trace/trace_events_hist.c +0
-0@@ -6945,29 +6939,9 @@ hist_enable_trigger(struct event_trigger_data *data, } }kernel/trace/trace_events_hist.c +0
-14-static void -hist_enable_count_trigger (struct event_trigger_data *data, - struct trace_buffer *buffer, void *rec, - struct ring_buffer_event *event) -{ -if (!data->count) -return ; - -if (data->count !=-1 ) - (data->count)--; - -hist_enable_trigger (data, buffer, rec, event); -} -static const struct
event_trigger_opshist_enable_trigger_ops= {
.trigger =hist_enable_trigger,kernel/trace/trace_events_hist.c +1
-7- .print = event_enable_trigger_print, - .init = event_trigger_init, - .free = event_enable_trigger_free, -}; - -static const struct event_trigger_ops hist_enable_count_trigger_ops = { - .trigger = hist_enable_count_trigger, + .count_func = event_trigger_count,.print =
event_enable_trigger_print,
.init =event_trigger_init,
.free =event_enable_trigger_free,kernel/trace/trace_events_hist.c +0
-0@@ -6975,36 +6949,12 @@ static const struct event_trigger_ops hist_enable_count_trigger_ops = {
static const structevent_trigger_opshist_disable_trigger_ops= {
.trigger =hist_enable_trigger,kernel/trace/trace_events_hist.c +1
-0+ .count_func = event_trigger_count,.print =
event_enable_trigger_print,
.init =event_trigger_init,
.free =event_enable_trigger_free,
};kernel/trace/trace_events_hist.c +0
-25-static const struct event_trigger_ops hist_disable_count_trigger_ops = { - .trigger = hist_enable_count_trigger, - .print = event_enable_trigger_print, - .init = event_trigger_init, - .free = event_enable_trigger_free, -}; - -static const struct event_trigger_ops * -hist_enable_get_trigger_ops (char *cmd,char *param) -{ -const struct event_trigger_ops *ops; -bool enable; - - enable = (strcmp (cmd,ENABLE_HIST_STR ) ==0 ); - -if (enable) - ops = param ? &hist_enable_count_trigger_ops : - &hist_enable_trigger_ops; -else - ops = param ? &hist_disable_count_trigger_ops : - &hist_disable_trigger_ops; - -return ops; -} -static void
hist_enable_unreg_all(struct trace_event_file *file){
structevent_trigger_data*test, *n;kernel/trace/trace_events_hist.c +1
-1@@ -7023,22 +6973,22 @@ static void hist_enable_unreg_all(struct trace_event_file *file) static struct event_command trigger_hist_enable_cmd = { .name = ENABLE_HIST_STR, .trigger_type = ETT_HIST_ENABLE, + .trigger_ops = &hist_enable_trigger_ops, .parse = event_enable_trigger_parse, .reg = event_enable_register_trigger, .unreg = event_enable_unregister_trigger, .unreg_all = hist_enable_unreg_all, - .get_trigger_ops = hist_enable_get_trigger_ops, .set_filter = set_trigger_filter, };
static structevent_commandtrigger_hist_disable_cmd= {
.name =DISABLE_HIST_STR,
.trigger_type =ETT_HIST_ENABLE,kernel/trace/trace_events_hist.c +1
-0+ .trigger_ops = &hist_disable_trigger_ops,.parse =
event_enable_trigger_parse,
.reg =event_enable_register_trigger,
.unreg =event_enable_unregister_trigger,
.unreg_all =hist_enable_unreg_all,kernel/trace/trace_events_hist.c +0
-1- .get_trigger_ops = hist_enable_get_trigger_ops,.set_filter =
set_trigger_filter,
};kernel/trace/trace_events_trigger.c +0
-0@@ -28,6 +28,20 @@ void trigger_data_free(struct event_trigger_data *data) kfree(data); }kernel/trace/trace_events_trigger.c +14
-0+static inline void data_ops_trigger (struct event_trigger_data *data, + struct trace_buffer *buffer, void *rec, + struct ring_buffer_event *event) +{ +const struct event_trigger_ops *ops = data->ops; + +if (data->flags &EVENT_TRIGGER_FL_COUNT ) { +if (!ops->count_func (data, buffer, rec, event)) +return ; + } + + ops->trigger (data, buffer, rec, event); +} +/**
*event_triggers_call- Call triggers associated with a trace event
* @file: Thetrace_event_fileassociated with the eventkernel/trace/trace_events_trigger.c +3
-3@@ -70,7 +84,7 @@ event_triggers_call(struct trace_event_file *file, if (data->paused) continue; if (!rec) { - data->ops->trigger (data, buffer, rec, event); +data_ops_trigger (data, buffer, rec, event); continue; } filter = rcu_dereference_sched(data->filter);@@ -80,7 +94,7 @@ event_triggers_call(struct trace_event_file *file, tt |= data->cmd_ops->trigger_type; continue; } - data->ops->trigger (data, buffer, rec, event); +data_ops_trigger (data, buffer, rec, event); } return tt; }@@ -122,7 +136,7 @@ event_triggers_post_call(struct trace_event_file *file, if (data->paused) continue; if (data->cmd_ops->trigger_type & tt) - data->ops->trigger (data,NULL ,NULL ,NULL ); +data_ops_trigger (data,NULL ,NULL ,NULL ); } } EXPORT_SYMBOL_GPL(event_triggers_post_call);@@ -377,6 +391,36 @@ __init int unregister_event_command(struct event_command *cmd) return -ENODEV; }kernel/trace/trace_events_trigger.c +30
-0+/** +* event_trigger_count - Optional count function for event triggers +* @data: Trigger-specific data +* @buffer: The ring buffer that the event is being written to +* @rec: The trace entry for the event, NULL for unconditional invocation +* @event: The event meta data in the ring buffer +* +* For triggers that can take a count parameter that doesn't do anything +* special, they can use this function to assign to their .count_func +* field. +* +* This simply does a count down of the @data->count field. +* +* If the @data->count is greater than zero, it will decrement it. +* +* Returns false if @data->count is zero, otherwise true. +*/ +bool event_trigger_count (struct event_trigger_data *data, + struct trace_buffer *buffer, void *rec, +struct ring_buffer_event *event) +{ +if (!data->count) +return false; + +if (data->count !=-1 ) + (data->count)--; + +return true; +} +/**
*event_trigger_print- Genericevent_trigger_ops@print implementation
* @name: The name of the event triggerkernel/trace/trace_events_trigger.c +7
-6@@ -807,9 +851,13 @@ int event_trigger_separate_filter(char *param_and_filter, char **param, * @private_data: User data to associate with the event trigger * * Allocate an event_trigger_data instance and initialize it. The - * @cmd_ops are used along with the @cmd and @param to get the - * trigger_ops to assign to the event_trigger_data. @private_data can - * also be passed in and associated with the event_trigger_data. + * @cmd_ops defines how the trigger will operate. If @param is set, + * and @cmd_ops->trigger_ops->count_func is non NULL, then the + * data->count is set to @param and before the trigger is executed, the + * @cmd_ops->trigger_ops->count_func() is called. If that function returns + * false, the @cmd_ops->trigger_ops->trigger() function will not be called. + * @private_data can also be passed in and associated with the + * event_trigger_data. * * Use trigger_data_free() to free an event_trigger_data object. *@@ -821,18 +869,17 @@ struct event_trigger_data *trigger_data_alloc(struct event_command *cmd_ops, void *private_data) { struct event_trigger_data *trigger_data; -const struct event_trigger_ops *trigger_ops; - - trigger_ops = cmd_ops->get_trigger_ops (cmd, param);
trigger_data=kzalloc(sizeof(*trigger_data), GFP_KERNEL); if (!trigger_data)
return NULL;
trigger_data->count= -1;kernel/trace/trace_events_trigger.c +1
-1- trigger_data->ops = trigger_ops; + trigger_data->ops = cmd_ops->trigger_ops;
trigger_data->cmd_ops=cmd_ops;trigger_data->private_data=private_data;kernel/trace/trace_events_trigger.c +2
-0+if (param && cmd_ops->trigger_ops->count_func) + trigger_data->flags |=EVENT_TRIGGER_FL_COUNT ;
INIT_LIST_HEAD(&trigger_data->list);INIT_LIST_HEAD(&trigger_data->named_list);kernel/trace/trace_events_trigger.c +0
-0@@ -1271,31 +1318,28 @@ traceon_trigger(struct event_trigger_data *data, tracing_on(); }kernel/trace/trace_events_trigger.c +4
-4-static void -traceon_count_trigger (struct event_trigger_data *data, - struct trace_buffer *buffer, void *rec, - struct ring_buffer_event *event) +static bool +traceon_count_func (struct event_trigger_data *data, + struct trace_buffer *buffer, void *rec, + struct ring_buffer_event *event){
structtrace_event_file*file =data->private_data;
if (file) {
if (tracer_tracing_is_on(file->tr))kernel/trace/trace_events_trigger.c +1
-1-return ; +return false;} else {
if (tracing_is_on())kernel/trace/trace_events_trigger.c +1
-1-return ; +return false;}
if (!data->count)kernel/trace/trace_events_trigger.c +1
-1-return ; +return false;
if (data->count!= -1)
(data->count)--;kernel/trace/trace_events_trigger.c +1
-4-if (file) -tracer_tracing_on (file->tr); -else -tracing_on (); +return true;}
static voidkernel/trace/trace_events_trigger.c +0
-0@@ -1319,31 +1363,28 @@ traceoff_trigger(struct event_trigger_data *data, tracing_off(); }kernel/trace/trace_events_trigger.c +4
-4-static void -traceoff_count_trigger (struct event_trigger_data *data, - struct trace_buffer *buffer, void *rec, - struct ring_buffer_event *event) +static bool +traceoff_count_func (struct event_trigger_data *data, + struct trace_buffer *buffer, void *rec, + struct ring_buffer_event *event){
structtrace_event_file*file =data->private_data;
if (file) {
if (!tracer_tracing_is_on(file->tr))kernel/trace/trace_events_trigger.c +1
-1-return ; +return false;} else {
if (!tracing_is_on())kernel/trace/trace_events_trigger.c +1
-1-return ; +return false;}
if (!data->count)kernel/trace/trace_events_trigger.c +1
-1-return ; +return false;
if (data->count!= -1)
(data->count)--;kernel/trace/trace_events_trigger.c +1
-4-if (file) -tracer_tracing_off (file->tr); -else -tracing_off (); +return true;}
static intkernel/trace/trace_events_trigger.c +0
-0@@ -1362,13 +1403,7 @@ traceoff_trigger_print(struct seq_file *m, struct event_trigger_data *data)
static const structevent_trigger_opstraceon_trigger_ops= {
.trigger =traceon_trigger,kernel/trace/trace_events_trigger.c +1
-7- .print = traceon_trigger_print, - .init = event_trigger_init, - .free = event_trigger_free, -}; - -static const struct event_trigger_ops traceon_count_trigger_ops = { - .trigger = traceon_count_trigger, + .count_func = traceon_count_func,.print =
traceon_trigger_print,
.init =event_trigger_init,
.free =event_trigger_free,kernel/trace/trace_events_trigger.c +0
-0@@ -1376,41 +1411,19 @@ static const struct event_trigger_ops traceon_count_trigger_ops = {
static const structevent_trigger_opstraceoff_trigger_ops= {
.trigger =traceoff_trigger,kernel/trace/trace_events_trigger.c +1
-0+ .count_func = traceoff_count_func,.print =
traceoff_trigger_print,
.init =event_trigger_init,
.free =event_trigger_free,
};kernel/trace/trace_events_trigger.c +0
-23-static const struct event_trigger_ops traceoff_count_trigger_ops = { - .trigger = traceoff_count_trigger, - .print = traceoff_trigger_print, - .init = event_trigger_init, - .free = event_trigger_free, -}; - -static const struct event_trigger_ops * -onoff_get_trigger_ops (char *cmd,char *param) -{ -const struct event_trigger_ops *ops; - -/* we register both traceon and traceoff to this callback */ -if (strcmp (cmd,"traceon" ) ==0 ) - ops = param ? &traceon_count_trigger_ops : - &traceon_trigger_ops; -else - ops = param ? &traceoff_count_trigger_ops : - &traceoff_trigger_ops; - -return ops; -} -static struct
event_commandtrigger_traceon_cmd= {
.name = "traceon",
.trigger_type =ETT_TRACE_ONOFF,kernel/trace/trace_events_trigger.c +1
-0+ .trigger_ops = &traceon_trigger_ops,.parse =
event_trigger_parse,
.reg =register_trigger,
.unreg =unregister_trigger,kernel/trace/trace_events_trigger.c +0
-1- .get_trigger_ops = onoff_get_trigger_ops,.set_filter =
set_trigger_filter,
};kernel/trace/trace_events_trigger.c +1
-1@@ -1418,10 +1431,10 @@ static struct event_command trigger_traceoff_cmd = { .name = "traceoff", .trigger_type = ETT_TRACE_ONOFF, .flags = EVENT_CMD_FL_POST_TRIGGER, + .trigger_ops = &traceoff_trigger_ops, .parse = event_trigger_parse, .reg = register_trigger, .unreg = unregister_trigger, - .get_trigger_ops = onoff_get_trigger_ops, .set_filter = set_trigger_filter, };kernel/trace/trace_events_trigger.c +0
-0@@ -1439,20 +1452,6 @@ snapshot_trigger(struct event_trigger_data *data, tracing_snapshot(); }kernel/trace/trace_events_trigger.c +0
-14-static void -snapshot_count_trigger (struct event_trigger_data *data, - struct trace_buffer *buffer, void *rec, - struct ring_buffer_event *event) -{ -if (!data->count) -return ; - -if (data->count !=-1 ) - (data->count)--; - -snapshot_trigger (data, buffer, rec, event); -} -static int
register_snapshot_trigger(char *glob,
structevent_trigger_data*data,kernel/trace/trace_events_trigger.c +0
-0@@ -1486,31 +1485,19 @@ snapshot_trigger_print(struct seq_file *m, struct event_trigger_data *data)
static const structevent_trigger_opssnapshot_trigger_ops= {
.trigger =snapshot_trigger,kernel/trace/trace_events_trigger.c +1
-0+ .count_func = event_trigger_count,.print =
snapshot_trigger_print,
.init =event_trigger_init,
.free =event_trigger_free,
};kernel/trace/trace_events_trigger.c +0
-13-static const struct event_trigger_ops snapshot_count_trigger_ops = { - .trigger = snapshot_count_trigger, - .print = snapshot_trigger_print, - .init = event_trigger_init, - .free = event_trigger_free, -}; - -static const struct event_trigger_ops * -snapshot_get_trigger_ops (char *cmd,char *param) -{ -return param ? &snapshot_count_trigger_ops : &snapshot_trigger_ops; -} -static struct
event_commandtrigger_snapshot_cmd= {
.name = "snapshot",
.trigger_type =ETT_SNAPSHOT,kernel/trace/trace_events_trigger.c +1
-0+ .trigger_ops = &snapshot_trigger_ops,.parse =
event_trigger_parse,
.reg =register_snapshot_trigger,
.unreg =unregister_snapshot_trigger,kernel/trace/trace_events_trigger.c +0
-1- .get_trigger_ops = snapshot_get_trigger_ops,.set_filter =
set_trigger_filter,
};kernel/trace/trace_events_trigger.c +0
-0@@ -1558,20 +1545,6 @@ stacktrace_trigger(struct event_trigger_data *data, trace_dump_stack(STACK_SKIP); }kernel/trace/trace_events_trigger.c +0
-14-static void -stacktrace_count_trigger (struct event_trigger_data *data, -struct trace_buffer *buffer,void *rec, -struct ring_buffer_event *event) -{ -if (!data->count) -return ; - -if (data->count !=-1 ) - (data->count)--; - -stacktrace_trigger (data, buffer, rec, event); -} -static int
stacktrace_trigger_print(structseq_file*m, structevent_trigger_data*data) {kernel/trace/trace_events_trigger.c +0
-0@@ -1581,32 +1554,20 @@ stacktrace_trigger_print(struct seq_file *m, struct event_trigger_data *data)
static const structevent_trigger_opsstacktrace_trigger_ops= {
.trigger =stacktrace_trigger,kernel/trace/trace_events_trigger.c +1
-0+ .count_func = event_trigger_count,.print =
stacktrace_trigger_print,
.init =event_trigger_init,
.free =event_trigger_free,
};kernel/trace/trace_events_trigger.c +0
-13-static const struct event_trigger_ops stacktrace_count_trigger_ops = { - .trigger = stacktrace_count_trigger, - .print = stacktrace_trigger_print, - .init = event_trigger_init, - .free = event_trigger_free, -}; - -static const struct event_trigger_ops * -stacktrace_get_trigger_ops (char *cmd,char *param) -{ -return param ? &stacktrace_count_trigger_ops : &stacktrace_trigger_ops; -} -static struct
event_commandtrigger_stacktrace_cmd= {
.name = "stacktrace",
.trigger_type =ETT_STACKTRACE,kernel/trace/trace_events_trigger.c +1
-0+ .trigger_ops = &stacktrace_trigger_ops,.flags =
EVENT_CMD_FL_POST_TRIGGER,
.parse =event_trigger_parse,
.reg =register_trigger,
.unreg =unregister_trigger,kernel/trace/trace_events_trigger.c +0
-1- .get_trigger_ops = stacktrace_get_trigger_ops,.set_filter =
set_trigger_filter,
};kernel/trace/trace_events_trigger.c +0
-0@@ -1642,24 +1603,24 @@ event_enable_trigger(struct event_trigger_data *data, set_bit(EVENT_FILE_FL_SOFT_DISABLED_BIT, &enable_data->file->flags); }kernel/trace/trace_events_trigger.c +4
-4-static void -event_enable_count_trigger (struct event_trigger_data *data, - struct trace_buffer *buffer, void *rec, - struct ring_buffer_event *event) +static bool +event_enable_count_func (struct event_trigger_data *data, + struct trace_buffer *buffer, void *rec, +struct ring_buffer_event *event){
structenable_trigger_data*enable_data=data->private_data;
if (!data->count)kernel/trace/trace_events_trigger.c +1
-1-return ; +return false;
/* Skip if the event is in a state we want to switch to */
if (enable_data->enable== !(enable_data->file->flags &EVENT_FILE_FL_SOFT_DISABLED))kernel/trace/trace_events_trigger.c +1
-1-return ; +return false;
if (data->count!= -1)
(data->count)--;kernel/trace/trace_events_trigger.c +1
-1-event_enable_trigger (data, buffer, rec, event); +return true;}
int event_enable_trigger_print(structseq_file*m,kernel/trace/trace_events_trigger.c +0
-0@@ -1706,13 +1667,7 @@ void event_enable_trigger_free(struct event_trigger_data *data)
static const structevent_trigger_opsevent_enable_trigger_ops= {
.trigger =event_enable_trigger,kernel/trace/trace_events_trigger.c +1
-7- .print = event_enable_trigger_print, - .init = event_trigger_init, - .free = event_enable_trigger_free, -}; - -static const struct event_trigger_ops event_enable_count_trigger_ops = { - .trigger = event_enable_count_trigger, + .count_func = event_enable_count_func,.print =
event_enable_trigger_print,
.init =event_trigger_init,
.free =event_enable_trigger_free,kernel/trace/trace_events_trigger.c +0
-0@@ -1720,13 +1675,7 @@ static const struct event_trigger_ops event_enable_count_trigger_ops = {
static const structevent_trigger_opsevent_disable_trigger_ops= {
.trigger =event_enable_trigger,kernel/trace/trace_events_trigger.c +1
-7- .print = event_enable_trigger_print, - .init = event_trigger_init, - .free = event_enable_trigger_free, -}; - -static const struct event_trigger_ops event_disable_count_trigger_ops = { - .trigger = event_enable_count_trigger, + .count_func = event_enable_count_func,.print =
event_enable_trigger_print,
.init =event_trigger_init,
.free =event_enable_trigger_free,kernel/trace/trace_events_trigger.c +0
-0@@ -1906,45 +1855,23 @@ void event_enable_unregister_trigger(char *glob, data->ops->free(data); }kernel/trace/trace_events_trigger.c +0
-22-static const struct event_trigger_ops * -event_enable_get_trigger_ops (char *cmd,char *param) -{ -const struct event_trigger_ops *ops; -bool enable; - -#ifdef CONFIG_HIST_TRIGGERS - enable = ((strcmp (cmd,ENABLE_EVENT_STR ) ==0 ) || - (strcmp(cmd, ENABLE_HIST_STR) == 0)); -#else - enable =strcmp (cmd,ENABLE_EVENT_STR ) ==0 ; -#endif -if (enable) - ops = param ? &event_enable_count_trigger_ops : - &event_enable_trigger_ops; -else - ops = param ? &event_disable_count_trigger_ops : - &event_disable_trigger_ops; - -return ops; -} -static struct
event_commandtrigger_enable_cmd= {
.name =ENABLE_EVENT_STR,
.trigger_type =ETT_EVENT_ENABLE,kernel/trace/trace_events_trigger.c +1
-0+ .trigger_ops = &event_enable_trigger_ops,.parse =
event_enable_trigger_parse,
.reg =event_enable_register_trigger,
.unreg =event_enable_unregister_trigger,kernel/trace/trace_events_trigger.c +0
-1- .get_trigger_ops = event_enable_get_trigger_ops,.set_filter =
set_trigger_filter,
};
static structevent_commandtrigger_disable_cmd= {
.name =DISABLE_EVENT_STR,
.trigger_type =ETT_EVENT_ENABLE,kernel/trace/trace_events_trigger.c +1
-0+ .trigger_ops = &event_disable_trigger_ops,.parse =
event_enable_trigger_parse,
.reg =event_enable_register_trigger,
.unreg =event_enable_unregister_trigger,kernel/trace/trace_events_trigger.c +0
-1- .get_trigger_ops = event_enable_get_trigger_ops,.set_filter =
set_trigger_filter,
};
PATCH 2/2 tracing: Merge struct event_trigger_ops into struct event_command
In reply to Steven RostedtFrom: Steven Rostedt <[email protected]>
Now that there's pretty much a one to one mapping between the struct event_trigger_ops and struct event_command, there's no reason to have two different structures. Merge the function pointers of event_trigger_ops into event_command.
There's one exception in trace_events_hist.c for the event_hist_trigger_named_ops. This has special logic for the init and free function pointers for "named histograms". In this case, allocate the cmd_ops of the event_trigger_data and set it to the proper init and free functions, which are used to initialize and free the event_trigger_data respectively. Have the free function and the init function (on failure) free the cmd_ops of the data element.
--- kernel/trace/trace.h | 126 +++++++++++----------------- kernel/trace/trace_eprobe.c | 13 +-- kernel/trace/trace_events_hist.c | 93 ++++++++++---------- kernel/trace/trace_events_trigger.c | 121 +++++++++++--------------- 4 files changed, 152 insertions(+), 201 deletions(-)
kernel/trace/trace.h +51 -75
@@ -1798,7 +1798,6 @@ struct event_trigger_data {unsigned long count;int ref;int flags; -const struct event_trigger_ops *ops;struct event_command *cmd_ops;struct event_filter __rcu *filter;char *filter_str;
@@ -1889,73 +1888,6 @@ extern void event_trigger_unregister(struct event_command *cmd_ops,extern void event_file_get (struct trace_event_file *file);extern void event_file_put (struct trace_event_file *file); -/** -* struct event_trigger_ops - callbacks for trace event triggers -* -* The methods in this structure provide per-event trigger hooks for -* various trigger operations. -* -* The @init and @free methods are used during trigger setup and -* teardown, typically called from an event_command's @parse() -* function implementation. -* -* The @print method is used to print the trigger spec. -* -* The @trigger method is the function that actually implements the -* trigger and is called in the context of the triggering event -* whenever that event occurs. -* -* All the methods below, except for @init() and @free(), must be -* implemented. -* -* @trigger: The trigger 'probe' function called when the triggering -* event occurs. The data passed into this callback is the data -* that was supplied to the event_command @reg() function that -* registered the trigger (see struct event_command) along with -* the trace record, rec. -* -* @count_func: If defined and a numeric parameter is passed to the -* trigger, then this function will be called before @trigger -* is called. If this function returns false, then @trigger is not -* executed. -* -* @init: An optional initialization function called for the trigger -* when the trigger is registered (via the event_command reg() -* function). This can be used to perform per-trigger -* initialization such as incrementing a per-trigger reference -* count, for instance. This is usually implemented by the -* generic utility function @event_trigger_init() (see -* trace_event_triggers.c). -* -* @free: An optional de-initialization function called for the -* trigger when the trigger is unregistered (via the -* event_command @reg() function). This can be used to perform -* per-trigger de-initialization such as decrementing a -* per-trigger reference count and freeing corresponding trigger -* data, for instance. This is usually implemented by the -* generic utility function @event_trigger_free() (see -* trace_event_triggers.c). -* -* @print: The callback function invoked to have the trigger print -* itself. This is usually implemented by a wrapper function -* that calls the generic utility function @event_trigger_print() -* (see trace_event_triggers.c). -*/ -struct event_trigger_ops { -void (*trigger)(struct event_trigger_data *data, -struct trace_buffer *buffer, -void *rec, -struct ring_buffer_event *rbe); -bool (*count_func)(struct event_trigger_data *data, -struct trace_buffer *buffer, -void *rec, -struct ring_buffer_event *rbe); -int (*init)(struct event_trigger_data *data); -void (*free)(struct event_trigger_data *data); -int (*print)(struct seq_file *m, -struct event_trigger_data *data); -}; -/** * struct event_command - callbacks and data members for event commands *
@@ -1976,9 +1908,6 @@ struct event_trigger_ops {* @name: The unique name that identifies the event command. This is * the name used when setting triggers via trigger files. * -* @trigger_ops: The event_trigger_ops implementation associated with -* the command. -* * @trigger_type: A unique id that identifies the event command * 'type'. This value has two purposes, the first to ensure that * only one trigger of the same type can be set at a given time
@@ -2008,7 +1937,7 @@ struct event_trigger_ops {* * @reg: Adds the trigger to the list of triggers associated with the * event, and enables the event trigger itself, after -* initializing it (via the event_trigger_ops @init() function). +* initializing it (via the event_command @init() function). * This is also where commands can use the @trigger_type value to * make the decision as to whether or not multiple instances of * the trigger should be allowed. This is usually implemented by
@@ -2017,7 +1946,7 @@ struct event_trigger_ops {* * @unreg: Removes the trigger from the list of triggers associated * with the event, and disables the event trigger itself, after -* initializing it (via the event_trigger_ops @free() function). +* initializing it (via the event_command @free() function). * This is usually implemented by the generic utility function * @unregister_trigger() (see trace_event_triggers.c). *
@@ -2030,11 +1959,46 @@ struct event_trigger_ops {* event command, filters set by the user for the command will be * ignored. This is usually implemented by the generic utility * function @set_trigger_filter() (see trace_event_triggers.c). +* +* All the methods below, except for @init() and @free(), must be +* implemented. +* +* @trigger: The trigger 'probe' function called when the triggering +* event occurs. The data passed into this callback is the data +* that was supplied to the event_command @reg() function that +* registered the trigger (see struct event_command) along with +* the trace record, rec. +* +* @count_func: If defined and a numeric parameter is passed to the +* trigger, then this function will be called before @trigger +* is called. If this function returns false, then @trigger is not +* executed. +* +* @init: An optional initialization function called for the trigger +* when the trigger is registered (via the event_command reg() +* function). This can be used to perform per-trigger +* initialization such as incrementing a per-trigger reference +* count, for instance. This is usually implemented by the +* generic utility function @event_trigger_init() (see +* trace_event_triggers.c). +* +* @free: An optional de-initialization function called for the +* trigger when the trigger is unregistered (via the +* event_command @reg() function). This can be used to perform +* per-trigger de-initialization such as decrementing a +* per-trigger reference count and freeing corresponding trigger +* data, for instance. This is usually implemented by the +* generic utility function @event_trigger_free() (see +* trace_event_triggers.c). +* +* @print: The callback function invoked to have the trigger print +* itself. This is usually implemented by a wrapper function +* that calls the generic utility function @event_trigger_print() +* (see trace_event_triggers.c). */ struct event_command {struct list_head list;char *name; -const struct event_trigger_ops *trigger_ops;enum event_trigger_type trigger_type;int flags; int (*parse)(struct event_command *cmd_ops,
@@ -2051,6 +2015,18 @@ struct event_command {int (*set_filter)(char *filter_str,struct event_trigger_data *data,struct trace_event_file *file); +void (*trigger)(struct event_trigger_data *data, +struct trace_buffer *buffer, +void *rec, +struct ring_buffer_event *rbe); +bool (*count_func)(struct event_trigger_data *data, +struct trace_buffer *buffer, +void *rec, +struct ring_buffer_event *rbe); +int (*init)(struct event_trigger_data *data); +void (*free)(struct event_trigger_data *data); +int (*print)(struct seq_file *m, +struct event_trigger_data *data); };/**
@@ -2071,7 +2047,7 @@ struct event_command {* either committed or discarded. At that point, if any commands * have deferred their triggers, those commands are finally * invoked following the close of the current event. In other -* words, if the event_trigger_ops @func() probe implementation +* words, if the event_command @func() probe implementation * itself logs to the trace buffer, this flag should be set, * otherwise it can be left unspecified. *
kernel/trace/trace_eprobe.c +4 -9
@@ -484,13 +484,6 @@ static void eprobe_trigger_func(struct event_trigger_data *data,__eprobe_trace_func (edata, rec); } -static const struct event_trigger_ops eprobe_trigger_ops = { - .trigger = eprobe_trigger_func, - .print = eprobe_trigger_print, - .init = eprobe_trigger_init, - .free = eprobe_trigger_free, -}; - static int eprobe_trigger_cmd_parse(struct event_command *cmd_ops, struct trace_event_file *file, char *glob, char *cmd,
@@ -517,12 +510,15 @@ static struct event_command event_trigger_cmd = { .name = "eprobe", .trigger_type = ETT_EVENT_EPROBE, .flags = EVENT_CMD_FL_NEEDS_REC, - .trigger_ops = &eprobe_trigger_ops, .parse = eprobe_trigger_cmd_parse, .reg = eprobe_trigger_reg_func, .unreg = eprobe_trigger_unreg_func, .unreg_all = NULL, .set_filter = NULL, + .trigger = eprobe_trigger_func, + .print = eprobe_trigger_print, + .init = eprobe_trigger_init, + .free = eprobe_trigger_free, }; static struct event_trigger_data *
@@ -542,7 +538,6 @@ new_eprobe_trigger(struct trace_eprobe *ep, struct trace_event_file *file) trigger->flags =EVENT_TRIGGER_FL_PROBE ; trigger->count =-1 ; - trigger->ops = &eprobe_trigger_ops;/* * EVENT PROBE triggers are not registered as commands with
kernel/trace/trace_events_hist.c +49 -44
195 lines not on this page · raw message
kernel/trace/trace_events_trigger.c +48 -73
268 lines not on this page · raw message
Signature · 1 line
2.51.0
Re: [PATCH 2/2] tracing: Merge struct event_trigger_ops into struct event_command
Hi Steve,
Quoted 15 lines · Steven Rostedt
From: Steven Rostedt <[email protected]>
Now that there's pretty much a one to one mapping between the struct
event_trigger_opsand structevent_command, there's no reason to have two different structures. Merge the function pointers ofevent_trigger_opsintoevent_command.There's one exception in
trace_events_hist.cfor theevent_hist_trigger_named_ops. This has special logic for the init and free function pointers for "named histograms". In this case, allocate thecmd_opsof theevent_trigger_dataand set it to the proper init and free functions, which are used to initialize and free theevent_trigger_datarespectively. Have the free function and the init function (on failure) free thecmd_opsof the data element.
Quoted 1 line
Signed-off-by Steven Rostedt (Google) <[email protected]>
Very nice as well, just one tiny note below..
Quoted 7 lines
---
kernel/trace/trace.h | 126 +++++++++++----------------- kernel/trace/trace_eprobe.c | 13 +-- kernel/trace/trace_events_hist.c | 93 ++++++++++----------kernel/trace/trace_events_trigger.c| 121 +++++++++++---------------4 files changed, 152 insertions(+), 201 deletions(-)
[...]
Quoted 33 lines
kernel/trace/trace_events_hist.c +0
-0@@ -5694,7 +5694,7 @@ static void hist_trigger_show(struct seq_file *m, seq_puts(m, "\n\n");
seq_puts(m, "# event histogram\n#\n# trigger info: ");kernel/trace/trace_events_hist.c +1
-1- data->ops->
seq_puts(m, "#\n\n");
hist_data=data->private_data;kernel/trace/trace_events_hist.c +0
-0@@ -6016,7 +6016,7 @@ static void hist_trigger_debug_show(struct seq_file *m, seq_puts(m, "\n\n");
seq_puts(m, "# event histogram\n#\n# trigger info: ");kernel/trace/trace_events_hist.c +1
-1- data->ops->
seq_puts(m, "#\n\n");
hist_data=data->private_data;kernel/trace/trace_events_hist.c +0
-0@@ -6326,20 +6326,23 @@ static void event_hist_trigger_free(struct event_trigger_data *data) free_hist_pad(); }kernel/trace/trace_events_hist.c +1
-6-static const struct event_trigger_ops event_hist_trigger_ops = { - .trigger = event_hist_trigger, - .print = event_hist_trigger_print, - .init = event_hist_trigger_init, - .free = event_hist_trigger_free, -}; +static struct event_command trigger_hist_cmd;
Quoted 1 line
I don't think this is needed, since the same declaration already appears just above the event_hist_trigger_parse() declaration.
Thanks,
Tom
Steven Rostedt
maintainerRe: [PATCH 2/2] tracing: Merge struct event_trigger_ops into struct event_command
Quoted 11 lines · On Tue, 25 Nov 2025 07:01:43 -0600 Tom Zanussi <[email protected]> wrote:
Quoted 8 lines
kernel/trace/trace_events_hist.c +1
-6-static const struct event_trigger_ops event_hist_trigger_ops = { - .trigger = event_hist_trigger, - .print = event_hist_trigger_print, - .init = event_hist_trigger_init, - .free = event_hist_trigger_free, -}; +static struct event_command trigger_hist_cmd;I don't think this is needed, since the same declaration already appears just above the
event_hist_trigger_parse()declaration.
No it doesn't. Nice catch. I'll send a v2.
Thanks for the review.
-- Steve