Skip to content

Commit 86599db

Browse files
Tom Zanussirostedt
authored andcommitted
tracing: Add helper functions to simplify event_command.parse() callback handling
The event_command.parse() callback is responsible for parsing and registering triggers. The existing command implementions for this callback duplicate a lot of the same code, so to clean up and consolidate those implementations, introduce a handful of helper functions for implementors to use. This also makes it easier for new commands to be implemented and allows them to focus more on the customizations they provide rather than obscuring and complicating it with boilerplate code. Link: https://lkml.kernel.org/r/c1ff71f594d45177706571132bd3119491097221.1641823001.git.zanussi@kernel.org Signed-off-by: Tom Zanussi <[email protected]> Signed-off-by: Steven Rostedt <[email protected]>
1 parent 2378a2d commit 86599db

File tree

2 files changed

+366
-0
lines changed

2 files changed

+366
-0
lines changed

kernel/trace/trace.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1610,6 +1610,30 @@ get_named_trigger_data(struct event_trigger_data *data);
16101610
extern int register_event_command(struct event_command *cmd);
16111611
extern int unregister_event_command(struct event_command *cmd);
16121612
extern int register_trigger_hist_enable_disable_cmds(void);
1613+
extern bool event_trigger_check_remove(const char *glob);
1614+
extern bool event_trigger_empty_param(const char *param);
1615+
extern int event_trigger_separate_filter(char *param_and_filter, char **param,
1616+
char **filter, bool param_required);
1617+
extern struct event_trigger_data *
1618+
event_trigger_alloc(struct event_command *cmd_ops,
1619+
char *cmd,
1620+
char *param,
1621+
void *private_data);
1622+
extern int event_trigger_parse_num(char *trigger,
1623+
struct event_trigger_data *trigger_data);
1624+
extern int event_trigger_set_filter(struct event_command *cmd_ops,
1625+
struct trace_event_file *file,
1626+
char *param,
1627+
struct event_trigger_data *trigger_data);
1628+
extern void event_trigger_reset_filter(struct event_command *cmd_ops,
1629+
struct event_trigger_data *trigger_data);
1630+
extern int event_trigger_register(struct event_command *cmd_ops,
1631+
struct trace_event_file *file,
1632+
char *glob,
1633+
char *cmd,
1634+
char *trigger,
1635+
struct event_trigger_data *trigger_data,
1636+
int *n_registered);
16131637

16141638
/**
16151639
* struct event_trigger_ops - callbacks for trace event triggers

kernel/trace/trace_events_trigger.c

Lines changed: 342 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,348 @@ static void unregister_trigger(char *glob,
619619
data->ops->free(data->ops, data);
620620
}
621621

622+
/*
623+
* Event trigger parsing helper functions.
624+
*
625+
* These functions help make it easier to write an event trigger
626+
* parsing function i.e. the struct event_command.parse() callback
627+
* function responsible for parsing and registering a trigger command
628+
* written to the 'trigger' file.
629+
*
630+
* A trigger command (or just 'trigger' for short) takes the form:
631+
* [trigger] [if filter]
632+
*
633+
* The struct event_command.parse() callback (and other struct
634+
* event_command functions) refer to several components of a trigger
635+
* command. Those same components are referenced by the event trigger
636+
* parsing helper functions defined below. These components are:
637+
*
638+
* cmd - the trigger command name
639+
* glob - the trigger command name optionally prefaced with '!'
640+
* param_and_filter - text following cmd and ':'
641+
* param - text following cmd and ':' and stripped of filter
642+
* filter - the optional filter text following (and including) 'if'
643+
*
644+
* To illustrate the use of these componenents, here are some concrete
645+
* examples. For the following triggers:
646+
*
647+
* echo 'traceon:5 if pid == 0' > trigger
648+
* - 'traceon' is both cmd and glob
649+
* - '5 if pid == 0' is the param_and_filter
650+
* - '5' is the param
651+
* - 'if pid == 0' is the filter
652+
*
653+
* echo 'enable_event:sys:event:n' > trigger
654+
* - 'enable_event' is both cmd and glob
655+
* - 'sys:event:n' is the param_and_filter
656+
* - 'sys:event:n' is the param
657+
* - there is no filter
658+
*
659+
* echo 'hist:keys=pid if prio > 50' > trigger
660+
* - 'hist' is both cmd and glob
661+
* - 'keys=pid if prio > 50' is the param_and_filter
662+
* - 'keys=pid' is the param
663+
* - 'if prio > 50' is the filter
664+
*
665+
* echo '!enable_event:sys:event:n' > trigger
666+
* - 'enable_event' the cmd
667+
* - '!enable_event' is the glob
668+
* - 'sys:event:n' is the param_and_filter
669+
* - 'sys:event:n' is the param
670+
* - there is no filter
671+
*
672+
* echo 'traceoff' > trigger
673+
* - 'traceoff' is both cmd and glob
674+
* - there is no param_and_filter
675+
* - there is no param
676+
* - there is no filter
677+
*
678+
* There are a few different categories of event trigger covered by
679+
* these helpers:
680+
*
681+
* - triggers that don't require a parameter e.g. traceon
682+
* - triggers that do require a parameter e.g. enable_event and hist
683+
* - triggers that though they may not require a param may support an
684+
* optional 'n' param (n = number of times the trigger should fire)
685+
* e.g.: traceon:5 or enable_event:sys:event:n
686+
* - triggers that do not support an 'n' param e.g. hist
687+
*
688+
* These functions can be used or ignored as necessary - it all
689+
* depends on the complexity of the trigger, and the granularity of
690+
* the functions supported reflects the fact that some implementations
691+
* may need to customize certain aspects of their implementations and
692+
* won't need certain functions. For instance, the hist trigger
693+
* implementation doesn't use event_trigger_separate_filter() because
694+
* it has special requirements for handling the filter.
695+
*/
696+
697+
/**
698+
* event_trigger_check_remove - check whether an event trigger specifies remove
699+
* @glob: The trigger command string, with optional remove(!) operator
700+
*
701+
* The event trigger callback implementations pass in 'glob' as a
702+
* parameter. This is the command name either with or without a
703+
* remove(!) operator. This function simply parses the glob and
704+
* determines whether the command corresponds to a trigger removal or
705+
* a trigger addition.
706+
*
707+
* Return: true if this is a remove command, false otherwise
708+
*/
709+
bool event_trigger_check_remove(const char *glob)
710+
{
711+
return (glob && glob[0] == '!') ? true : false;
712+
}
713+
714+
/**
715+
* event_trigger_empty_param - check whether the param is empty
716+
* @param: The trigger param string
717+
*
718+
* The event trigger callback implementations pass in 'param' as a
719+
* parameter. This corresponds to the string following the command
720+
* name minus the command name. This function can be called by a
721+
* callback implementation for any command that requires a param; a
722+
* callback that doesn't require a param can ignore it.
723+
*
724+
* Return: true if this is an empty param, false otherwise
725+
*/
726+
bool event_trigger_empty_param(const char *param)
727+
{
728+
return !param;
729+
}
730+
731+
/**
732+
* event_trigger_separate_filter - separate an event trigger from a filter
733+
* @param: The param string containing trigger and possibly filter
734+
* @trigger: outparam, will be filled with a pointer to the trigger
735+
* @filter: outparam, will be filled with a pointer to the filter
736+
* @param_required: Specifies whether or not the param string is required
737+
*
738+
* Given a param string of the form '[trigger] [if filter]', this
739+
* function separates the filter from the trigger and returns the
740+
* trigger in *trigger and the filter in *filter. Either the *trigger
741+
* or the *filter may be set to NULL by this function - if not set to
742+
* NULL, they will contain strings corresponding to the trigger and
743+
* filter.
744+
*
745+
* There are two cases that need to be handled with respect to the
746+
* passed-in param: either the param is required, or it is not
747+
* required. If @param_required is set, and there's no param, it will
748+
* return -EINVAL. If @param_required is not set and there's a param
749+
* that starts with a number, that corresponds to the case of a
750+
* trigger with :n (n = number of times the trigger should fire) and
751+
* the parsing continues normally; otherwise the function just returns
752+
* and assumes param just contains a filter and there's nothing else
753+
* to do.
754+
*
755+
* Return: 0 on success, errno otherwise
756+
*/
757+
int event_trigger_separate_filter(char *param_and_filter, char **param,
758+
char **filter, bool param_required)
759+
{
760+
int ret = 0;
761+
762+
*param = *filter = NULL;
763+
764+
if (!param_and_filter) {
765+
if (param_required)
766+
ret = -EINVAL;
767+
goto out;
768+
}
769+
770+
/*
771+
* Here we check for an optional param. The only legal
772+
* optional param is :n, and if that's the case, continue
773+
* below. Otherwise we assume what's left is a filter and
774+
* return it as the filter string for the caller to deal with.
775+
*/
776+
if (!param_required && param_and_filter && !isdigit(param_and_filter[0])) {
777+
*filter = param_and_filter;
778+
goto out;
779+
}
780+
781+
/*
782+
* Separate the param from the filter (param [if filter]).
783+
* Here we have either an optional :n param or a required
784+
* param and an optional filter.
785+
*/
786+
*param = strsep(&param_and_filter, " \t");
787+
788+
/*
789+
* Here we have a filter, though it may be empty.
790+
*/
791+
if (param_and_filter) {
792+
*filter = skip_spaces(param_and_filter);
793+
if (!**filter)
794+
*filter = NULL;
795+
}
796+
out:
797+
return ret;
798+
}
799+
800+
/**
801+
* event_trigger_alloc - allocate and init event_trigger_data for a trigger
802+
* @cmd_ops: The event_command operations for the trigger
803+
* @cmd: The cmd string
804+
* @param: The param string
805+
* @private_data: User data to associate with the event trigger
806+
*
807+
* Allocate an event_trigger_data instance and initialize it. The
808+
* @cmd_ops are used along with the @cmd and @param to get the
809+
* trigger_ops to assign to the event_trigger_data. @private_data can
810+
* also be passed in and associated with the event_trigger_data.
811+
*
812+
* Use event_trigger_free() to free an event_trigger_data object.
813+
*
814+
* Return: The trigger_data object success, NULL otherwise
815+
*/
816+
struct event_trigger_data *event_trigger_alloc(struct event_command *cmd_ops,
817+
char *cmd,
818+
char *param,
819+
void *private_data)
820+
{
821+
struct event_trigger_data *trigger_data;
822+
struct event_trigger_ops *trigger_ops;
823+
824+
trigger_ops = cmd_ops->get_trigger_ops(cmd, param);
825+
826+
trigger_data = kzalloc(sizeof(*trigger_data), GFP_KERNEL);
827+
if (!trigger_data)
828+
return NULL;
829+
830+
trigger_data->count = -1;
831+
trigger_data->ops = trigger_ops;
832+
trigger_data->cmd_ops = cmd_ops;
833+
trigger_data->private_data = private_data;
834+
835+
INIT_LIST_HEAD(&trigger_data->list);
836+
INIT_LIST_HEAD(&trigger_data->named_list);
837+
RCU_INIT_POINTER(trigger_data->filter, NULL);
838+
839+
return trigger_data;
840+
}
841+
842+
/**
843+
* event_trigger_parse_num - parse and return the number param for a trigger
844+
* @param: The param string
845+
* @trigger_data: The trigger_data for the trigger
846+
*
847+
* Parse the :n (n = number of times the trigger should fire) param
848+
* and set the count variable in the trigger_data to the parsed count.
849+
*
850+
* Return: 0 on success, errno otherwise
851+
*/
852+
int event_trigger_parse_num(char *param,
853+
struct event_trigger_data *trigger_data)
854+
{
855+
char *number;
856+
int ret = 0;
857+
858+
if (param) {
859+
number = strsep(&param, ":");
860+
861+
if (!strlen(number))
862+
return -EINVAL;
863+
864+
/*
865+
* We use the callback data field (which is a pointer)
866+
* as our counter.
867+
*/
868+
ret = kstrtoul(number, 0, &trigger_data->count);
869+
}
870+
871+
return ret;
872+
}
873+
874+
/**
875+
* event_trigger_set_filter - set an event trigger's filter
876+
* @cmd_ops: The event_command operations for the trigger
877+
* @file: The event file for the trigger's event
878+
* @param: The string containing the filter
879+
* @trigger_data: The trigger_data for the trigger
880+
*
881+
* Set the filter for the trigger. If the filter is NULL, just return
882+
* without error.
883+
*
884+
* Return: 0 on success, errno otherwise
885+
*/
886+
int event_trigger_set_filter(struct event_command *cmd_ops,
887+
struct trace_event_file *file,
888+
char *param,
889+
struct event_trigger_data *trigger_data)
890+
{
891+
if (param && cmd_ops->set_filter)
892+
return cmd_ops->set_filter(param, trigger_data, file);
893+
894+
return 0;
895+
}
896+
897+
/**
898+
* event_trigger_reset_filter - reset an event trigger's filter
899+
* @cmd_ops: The event_command operations for the trigger
900+
* @trigger_data: The trigger_data for the trigger
901+
*
902+
* Reset the filter for the trigger to no filter.
903+
*/
904+
void event_trigger_reset_filter(struct event_command *cmd_ops,
905+
struct event_trigger_data *trigger_data)
906+
{
907+
if (cmd_ops->set_filter)
908+
cmd_ops->set_filter(NULL, trigger_data, NULL);
909+
}
910+
911+
/**
912+
* event_trigger_register - register an event trigger
913+
* @cmd_ops: The event_command operations for the trigger
914+
* @file: The event file for the trigger's event
915+
* @glob: The trigger command string, with optional remove(!) operator
916+
* @cmd: The cmd string
917+
* @param: The param string
918+
* @trigger_data: The trigger_data for the trigger
919+
* @n_registered: optional outparam, the number of triggers registered
920+
*
921+
* Register an event trigger. The @cmd_ops are used to call the
922+
* cmd_ops->reg() function which actually does the registration. The
923+
* cmd_ops->reg() function returns the number of triggers registered,
924+
* which is assigned to n_registered, if n_registered is non-NULL.
925+
*
926+
* Return: 0 on success, errno otherwise
927+
*/
928+
int event_trigger_register(struct event_command *cmd_ops,
929+
struct trace_event_file *file,
930+
char *glob,
931+
char *cmd,
932+
char *param,
933+
struct event_trigger_data *trigger_data,
934+
int *n_registered)
935+
{
936+
int ret;
937+
938+
if (n_registered)
939+
*n_registered = 0;
940+
941+
ret = cmd_ops->reg(glob, trigger_data, file);
942+
/*
943+
* The above returns on success the # of functions enabled,
944+
* but if it didn't find any functions it returns zero.
945+
* Consider no functions a failure too.
946+
*/
947+
if (!ret) {
948+
cmd_ops->unreg(glob, trigger_data, file);
949+
ret = -ENOENT;
950+
} else if (ret > 0) {
951+
if (n_registered)
952+
*n_registered = ret;
953+
/* Just return zero, not the number of enabled functions */
954+
ret = 0;
955+
}
956+
957+
return ret;
958+
}
959+
960+
/*
961+
* End event trigger parsing helper functions.
962+
*/
963+
622964
/**
623965
* event_trigger_parse - Generic event_command @parse implementation
624966
* @cmd_ops: The command ops, used for trigger registration

0 commit comments

Comments
 (0)