xref: /linux/kernel/trace/trace_dynevent.h (revision 8b0e6c74)
15448d44cSMasami Hiramatsu /* SPDX-License-Identifier: GPL-2.0 */
25448d44cSMasami Hiramatsu /*
35448d44cSMasami Hiramatsu  * Common header file for generic dynamic events.
45448d44cSMasami Hiramatsu  */
55448d44cSMasami Hiramatsu 
65448d44cSMasami Hiramatsu #ifndef _TRACE_DYNEVENT_H
75448d44cSMasami Hiramatsu #define _TRACE_DYNEVENT_H
85448d44cSMasami Hiramatsu 
95448d44cSMasami Hiramatsu #include <linux/kernel.h>
105448d44cSMasami Hiramatsu #include <linux/list.h>
115448d44cSMasami Hiramatsu #include <linux/mutex.h>
125448d44cSMasami Hiramatsu #include <linux/seq_file.h>
135448d44cSMasami Hiramatsu 
145448d44cSMasami Hiramatsu #include "trace.h"
155448d44cSMasami Hiramatsu 
165448d44cSMasami Hiramatsu struct dyn_event;
175448d44cSMasami Hiramatsu 
185448d44cSMasami Hiramatsu /**
195448d44cSMasami Hiramatsu  * struct dyn_event_operations - Methods for each type of dynamic events
205448d44cSMasami Hiramatsu  *
215448d44cSMasami Hiramatsu  * These methods must be set for each type, since there is no default method.
225448d44cSMasami Hiramatsu  * Before using this for dyn_event_init(), it must be registered by
235448d44cSMasami Hiramatsu  * dyn_event_register().
245448d44cSMasami Hiramatsu  *
255448d44cSMasami Hiramatsu  * @create: Parse and create event method. This is invoked when user passes
265448d44cSMasami Hiramatsu  *  a event definition to dynamic_events interface. This must not destruct
275448d44cSMasami Hiramatsu  *  the arguments and return -ECANCELED if given arguments doesn't match its
285448d44cSMasami Hiramatsu  *  command prefix.
295448d44cSMasami Hiramatsu  * @show: Showing method. This is invoked when user reads the event definitions
305448d44cSMasami Hiramatsu  *  via dynamic_events interface.
315448d44cSMasami Hiramatsu  * @is_busy: Check whether given event is busy so that it can not be deleted.
322b5894ccSQiujun Huang  *  Return true if it is busy, otherwise false.
332b5894ccSQiujun Huang  * @free: Delete the given event. Return 0 if success, otherwise error.
3430199137SMasami Hiramatsu  * @match: Check whether given event and system name match this event. The argc
352b5894ccSQiujun Huang  *  and argv is used for exact match. Return true if it matches, otherwise
3630199137SMasami Hiramatsu  *  false.
375448d44cSMasami Hiramatsu  *
385448d44cSMasami Hiramatsu  * Except for @create, these methods are called under holding event_mutex.
395448d44cSMasami Hiramatsu  */
405448d44cSMasami Hiramatsu struct dyn_event_operations {
415448d44cSMasami Hiramatsu 	struct list_head	list;
42d262271dSMasami Hiramatsu 	int (*create)(const char *raw_command);
435448d44cSMasami Hiramatsu 	int (*show)(struct seq_file *m, struct dyn_event *ev);
445448d44cSMasami Hiramatsu 	bool (*is_busy)(struct dyn_event *ev);
455448d44cSMasami Hiramatsu 	int (*free)(struct dyn_event *ev);
465448d44cSMasami Hiramatsu 	bool (*match)(const char *system, const char *event,
4730199137SMasami Hiramatsu 		      int argc, const char **argv, struct dyn_event *ev);
485448d44cSMasami Hiramatsu };
495448d44cSMasami Hiramatsu 
505448d44cSMasami Hiramatsu /* Register new dyn_event type -- must be called at first */
515448d44cSMasami Hiramatsu int dyn_event_register(struct dyn_event_operations *ops);
525448d44cSMasami Hiramatsu 
535448d44cSMasami Hiramatsu /**
545448d44cSMasami Hiramatsu  * struct dyn_event - Dynamic event list header
555448d44cSMasami Hiramatsu  *
565448d44cSMasami Hiramatsu  * The dyn_event structure encapsulates a list and a pointer to the operators
575448d44cSMasami Hiramatsu  * for making a global list of dynamic events.
585448d44cSMasami Hiramatsu  * User must includes this in each event structure, so that those events can
595448d44cSMasami Hiramatsu  * be added/removed via dynamic_events interface.
605448d44cSMasami Hiramatsu  */
615448d44cSMasami Hiramatsu struct dyn_event {
625448d44cSMasami Hiramatsu 	struct list_head		list;
635448d44cSMasami Hiramatsu 	struct dyn_event_operations	*ops;
645448d44cSMasami Hiramatsu };
655448d44cSMasami Hiramatsu 
665448d44cSMasami Hiramatsu extern struct list_head dyn_event_list;
675448d44cSMasami Hiramatsu 
685448d44cSMasami Hiramatsu static inline
dyn_event_init(struct dyn_event * ev,struct dyn_event_operations * ops)695448d44cSMasami Hiramatsu int dyn_event_init(struct dyn_event *ev, struct dyn_event_operations *ops)
705448d44cSMasami Hiramatsu {
715448d44cSMasami Hiramatsu 	if (!ev || !ops)
725448d44cSMasami Hiramatsu 		return -EINVAL;
735448d44cSMasami Hiramatsu 
745448d44cSMasami Hiramatsu 	INIT_LIST_HEAD(&ev->list);
755448d44cSMasami Hiramatsu 	ev->ops = ops;
765448d44cSMasami Hiramatsu 	return 0;
775448d44cSMasami Hiramatsu }
785448d44cSMasami Hiramatsu 
dyn_event_add(struct dyn_event * ev,struct trace_event_call * call)79*8b0e6c74SSteven Rostedt (VMware) static inline int dyn_event_add(struct dyn_event *ev,
80*8b0e6c74SSteven Rostedt (VMware) 				struct trace_event_call *call)
815448d44cSMasami Hiramatsu {
825448d44cSMasami Hiramatsu 	lockdep_assert_held(&event_mutex);
835448d44cSMasami Hiramatsu 
845448d44cSMasami Hiramatsu 	if (!ev || !ev->ops)
855448d44cSMasami Hiramatsu 		return -EINVAL;
865448d44cSMasami Hiramatsu 
87*8b0e6c74SSteven Rostedt (VMware) 	call->flags |= TRACE_EVENT_FL_DYNAMIC;
885448d44cSMasami Hiramatsu 	list_add_tail(&ev->list, &dyn_event_list);
895448d44cSMasami Hiramatsu 	return 0;
905448d44cSMasami Hiramatsu }
915448d44cSMasami Hiramatsu 
dyn_event_remove(struct dyn_event * ev)925448d44cSMasami Hiramatsu static inline void dyn_event_remove(struct dyn_event *ev)
935448d44cSMasami Hiramatsu {
945448d44cSMasami Hiramatsu 	lockdep_assert_held(&event_mutex);
955448d44cSMasami Hiramatsu 	list_del_init(&ev->list);
965448d44cSMasami Hiramatsu }
975448d44cSMasami Hiramatsu 
985448d44cSMasami Hiramatsu void *dyn_event_seq_start(struct seq_file *m, loff_t *pos);
995448d44cSMasami Hiramatsu void *dyn_event_seq_next(struct seq_file *m, void *v, loff_t *pos);
1005448d44cSMasami Hiramatsu void dyn_event_seq_stop(struct seq_file *m, void *v);
1015448d44cSMasami Hiramatsu int dyn_events_release_all(struct dyn_event_operations *type);
102d262271dSMasami Hiramatsu int dyn_event_release(const char *raw_command, struct dyn_event_operations *type);
1035448d44cSMasami Hiramatsu 
1045448d44cSMasami Hiramatsu /*
1055448d44cSMasami Hiramatsu  * for_each_dyn_event	-	iterate over the dyn_event list
1065448d44cSMasami Hiramatsu  * @pos:	the struct dyn_event * to use as a loop cursor
1075448d44cSMasami Hiramatsu  *
1085448d44cSMasami Hiramatsu  * This is just a basement of for_each macro. Wrap this for
1095448d44cSMasami Hiramatsu  * each actual event structure with ops filtering.
1105448d44cSMasami Hiramatsu  */
1115448d44cSMasami Hiramatsu #define for_each_dyn_event(pos)	\
1125448d44cSMasami Hiramatsu 	list_for_each_entry(pos, &dyn_event_list, list)
1135448d44cSMasami Hiramatsu 
1145448d44cSMasami Hiramatsu /*
1155448d44cSMasami Hiramatsu  * for_each_dyn_event	-	iterate over the dyn_event list safely
1165448d44cSMasami Hiramatsu  * @pos:	the struct dyn_event * to use as a loop cursor
1175448d44cSMasami Hiramatsu  * @n:		the struct dyn_event * to use as temporary storage
1185448d44cSMasami Hiramatsu  */
1195448d44cSMasami Hiramatsu #define for_each_dyn_event_safe(pos, n)	\
1205448d44cSMasami Hiramatsu 	list_for_each_entry_safe(pos, n, &dyn_event_list, list)
1215448d44cSMasami Hiramatsu 
12286c5426bSTom Zanussi extern void dynevent_cmd_init(struct dynevent_cmd *cmd, char *buf, int maxlen,
12386c5426bSTom Zanussi 			      enum dynevent_type type,
12486c5426bSTom Zanussi 			      dynevent_create_fn_t run_command);
12586c5426bSTom Zanussi 
12686c5426bSTom Zanussi typedef int (*dynevent_check_arg_fn_t)(void *data);
12786c5426bSTom Zanussi 
12886c5426bSTom Zanussi struct dynevent_arg {
12986c5426bSTom Zanussi 	const char		*str;
13086c5426bSTom Zanussi 	char			separator; /* e.g. ';', ',', or nothing */
13186c5426bSTom Zanussi };
13286c5426bSTom Zanussi 
13386c5426bSTom Zanussi extern void dynevent_arg_init(struct dynevent_arg *arg,
13486c5426bSTom Zanussi 			      char separator);
13586c5426bSTom Zanussi extern int dynevent_arg_add(struct dynevent_cmd *cmd,
13674403b6cSTom Zanussi 			    struct dynevent_arg *arg,
13774403b6cSTom Zanussi 			    dynevent_check_arg_fn_t check_arg);
13886c5426bSTom Zanussi 
13986c5426bSTom Zanussi struct dynevent_arg_pair {
14086c5426bSTom Zanussi 	const char		*lhs;
14186c5426bSTom Zanussi 	const char		*rhs;
14286c5426bSTom Zanussi 	char			operator; /* e.g. '=' or nothing */
14386c5426bSTom Zanussi 	char			separator; /* e.g. ';', ',', or nothing */
14486c5426bSTom Zanussi };
14586c5426bSTom Zanussi 
14686c5426bSTom Zanussi extern void dynevent_arg_pair_init(struct dynevent_arg_pair *arg_pair,
14786c5426bSTom Zanussi 				   char operator, char separator);
14874403b6cSTom Zanussi 
14986c5426bSTom Zanussi extern int dynevent_arg_pair_add(struct dynevent_cmd *cmd,
15074403b6cSTom Zanussi 				 struct dynevent_arg_pair *arg_pair,
15174403b6cSTom Zanussi 				 dynevent_check_arg_fn_t check_arg);
15286c5426bSTom Zanussi extern int dynevent_str_add(struct dynevent_cmd *cmd, const char *str);
15386c5426bSTom Zanussi 
1545448d44cSMasami Hiramatsu #endif
155