This class almost same as DECLARE_EVENT_CLASS, it allow user add some init operation before print at output stage. Add a new macro TP_printk_init(), user can add operation in it. Also add a new TRACE_EVENT_PRINT_INIT() macro. Signed-off-by: Linyu Yuan <quic_linyyuan@xxxxxxxxxxx> --- include/linux/tracepoint.h | 22 ++++ include/trace/bpf_probe.h | 4 + include/trace/perf.h | 43 ++++++++ include/trace/stages/stage3_trace_output.h | 3 + include/trace/trace_events.h | 118 +++++++++++++++++++++ 5 files changed, 190 insertions(+) diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h index 88c0ba623ee6..3fd42640236a 100644 --- a/include/linux/tracepoint.h +++ b/include/linux/tracepoint.h @@ -551,6 +551,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p) */ #define DECLARE_EVENT_CLASS(name, proto, args, tstruct, assign, print) +#define DECLARE_EVENT_CLASS_PRINT_INIT(name, proto, args, tstruct, assign, print, init) #define DEFINE_EVENT(template, name, proto, args) \ DECLARE_TRACE(name, PARAMS(proto), PARAMS(args)) #define DEFINE_EVENT_FN(template, name, proto, args, reg, unreg)\ @@ -576,6 +577,20 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p) DECLARE_TRACE_CONDITION(name, PARAMS(proto), \ PARAMS(args), PARAMS(cond)) +#define TRACE_EVENT_PRINT_INIT(name, proto, args, struct, assign, print, init) \ + DECLARE_TRACE(name, PARAMS(proto), PARAMS(args)) +#define TRACE_EVENT_FN_PRINT_INIT(name, proto, args, struct, \ + assign, print, reg, unreg, init) \ + DECLARE_TRACE(name, PARAMS(proto), PARAMS(args)) +#define TRACE_EVENT_FN_COND_PRINT_INIT(name, proto, args, cond, struct, \ + assign, print, reg, unreg, init) \ + DECLARE_TRACE_CONDITION(name, PARAMS(proto), \ + PARAMS(args), PARAMS(cond)) +#define TRACE_EVENT_CONDITION_PRINT_INIT(name, proto, args, cond, \ + struct, assign, print, init) \ + DECLARE_TRACE_CONDITION(name, PARAMS(proto), \ + PARAMS(args), PARAMS(cond)) + #define TRACE_EVENT_FLAGS(event, flag) #define TRACE_EVENT_PERF_PERM(event, expr...) @@ -595,4 +610,11 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p) #define DEFINE_EVENT_NOP(template, name, proto, args) \ DECLARE_EVENT_NOP(name, PARAMS(proto), PARAMS(args)) +#define TRACE_EVENT_NOP_PRINT_INIT(name, proto, args, struct, assign, print, init) \ + DECLARE_EVENT_NOP(name, PARAMS(proto), PARAMS(args)) + +#define DECLARE_EVENT_CLASS_NOP_PRINT_INIT(name, proto, args, tstruct, assign, print, init) +#define DEFINE_EVENT_NOP(template, name, proto, args) \ + DECLARE_EVENT_NOP(name, PARAMS(proto), PARAMS(args)) + #endif /* ifdef TRACE_EVENT (see note above) */ diff --git a/include/trace/bpf_probe.h b/include/trace/bpf_probe.h index e609cd7da47e..99b5594a4a8e 100644 --- a/include/trace/bpf_probe.h +++ b/include/trace/bpf_probe.h @@ -54,6 +54,10 @@ __bpf_trace_##call(void *__data, proto) \ #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ __BPF_DECLARE_TRACE(call, PARAMS(proto), PARAMS(args)) +#undef DECLARE_EVENT_CLASS_PRINT_INIT +#define DECLARE_EVENT_CLASS_PRINT_INIT(call, proto, args, tstruct, assign, print, init) \ + __BPF_DECLARE_TRACE(call, PARAMS(proto), PARAMS(args)) + /* * This part is compiled out, it is only here as a build time check * to make sure that if the tracepoint handling changes, the diff --git a/include/trace/perf.h b/include/trace/perf.h index 2c11181c82e0..bee78e8eef5d 100644 --- a/include/trace/perf.h +++ b/include/trace/perf.h @@ -55,6 +55,49 @@ perf_trace_##call(void *__data, proto) \ head, __task); \ } +#undef DECLARE_EVENT_CLASS_PRINT_INIT +#define DECLARE_EVENT_CLASS_PRINT_INIT(call, proto, args, tstruct, assign, print, init) \ +static notrace void \ +perf_trace_##call(void *__data, proto) \ +{ \ + struct trace_event_call *event_call = __data; \ + struct trace_event_data_offsets_##call __maybe_unused __data_offsets;\ + struct trace_event_raw_##call *entry; \ + struct pt_regs *__regs; \ + u64 __count = 1; \ + struct task_struct *__task = NULL; \ + struct hlist_head *head; \ + int __entry_size; \ + int __data_size; \ + int rctx; \ + \ + __data_size = trace_event_get_offsets_##call(&__data_offsets, args); \ + \ + head = this_cpu_ptr(event_call->perf_events); \ + if (!bpf_prog_array_valid(event_call) && \ + __builtin_constant_p(!__task) && !__task && \ + hlist_empty(head)) \ + return; \ + \ + __entry_size = ALIGN(__data_size + sizeof(*entry) + sizeof(u32),\ + sizeof(u64)); \ + __entry_size -= sizeof(u32); \ + \ + entry = perf_trace_buf_alloc(__entry_size, &__regs, &rctx); \ + if (!entry) \ + return; \ + \ + perf_fetch_caller_regs(__regs); \ + \ + tstruct \ + \ + { assign; } \ + \ + perf_trace_run_bpf_submit(entry, __entry_size, rctx, \ + event_call, __count, __regs, \ + head, __task); \ +} + /* * This part is compiled out, it is only here as a build time check * to make sure that if the tracepoint handling changes, the diff --git a/include/trace/stages/stage3_trace_output.h b/include/trace/stages/stage3_trace_output.h index c1fb1355d309..121425e695f5 100644 --- a/include/trace/stages/stage3_trace_output.h +++ b/include/trace/stages/stage3_trace_output.h @@ -142,3 +142,6 @@ #undef __get_buf #define __get_buf(len) trace_seq_acquire(p, (len)) + +#undef TP_printk_init +#define TP_printk_init(args...) args diff --git a/include/trace/trace_events.h b/include/trace/trace_events.h index c2f9cabf154d..9a8872544a8b 100644 --- a/include/trace/trace_events.h +++ b/include/trace/trace_events.h @@ -45,6 +45,17 @@ PARAMS(print)); \ DEFINE_EVENT(name, name, PARAMS(proto), PARAMS(args)); +#undef TRACE_EVENT_PRINT_INIT +#define TRACE_EVENT_PRINT_INIT(name, proto, args, tstruct, assign, print, init) \ + DECLARE_EVENT_CLASS_PRINT_INIT(name, \ + PARAMS(proto), \ + PARAMS(args), \ + PARAMS(tstruct), \ + PARAMS(assign), \ + PARAMS(print), \ + PARAMS(init)); \ + DEFINE_EVENT(name, name, PARAMS(proto), PARAMS(args)); + #include "stages/stage1_struct_define.h" #undef DECLARE_EVENT_CLASS @@ -57,6 +68,16 @@ \ static struct trace_event_class event_class_##name; +#undef DECLARE_EVENT_CLASS_PRINT_INIT +#define DECLARE_EVENT_CLASS_PRINT_INIT(name, proto, args, tstruct, assign, print, init) \ + struct trace_event_raw_##name { \ + struct trace_entry ent; \ + tstruct \ + char __data[]; \ + }; \ + \ + static struct trace_event_class event_class_##name; + #undef DEFINE_EVENT #define DEFINE_EVENT(template, name, proto, args) \ static struct trace_event_call __used \ @@ -117,6 +138,12 @@ tstruct; \ }; +#undef DECLARE_EVENT_CLASS_PRINT_INIT +#define DECLARE_EVENT_CLASS_PRINT_INIT(call, proto, args, tstruct, assign, print, init) \ + struct trace_event_data_offsets_##call { \ + tstruct; \ + }; + #undef DEFINE_EVENT #define DEFINE_EVENT(template, name, proto, args) @@ -208,6 +235,32 @@ static struct trace_event_functions trace_event_type_funcs_##call = { \ .trace = trace_raw_output_##call, \ }; +#undef DECLARE_EVENT_CLASS_PRINT_INIT +#define DECLARE_EVENT_CLASS_PRINT_INIT(call, proto, args, tstruct, assign, print, init) \ +static notrace enum print_line_t \ +trace_raw_output_##call(struct trace_iterator *iter, int flags, \ + struct trace_event *trace_event) \ +{ \ + struct trace_seq *s = &iter->seq; \ + struct trace_seq __maybe_unused *p = &iter->tmp_seq; \ + struct trace_event_raw_##call *field; \ + int ret; \ + \ + field = (typeof(field))iter->ent; \ + \ + ret = trace_raw_output_prep(iter, trace_event); \ + if (ret != TRACE_TYPE_HANDLED) \ + return ret; \ + \ + init \ + trace_event_printf(iter, print); \ + \ + return trace_handle_return(s); \ +} \ +static struct trace_event_functions trace_event_type_funcs_##call = { \ + .trace = trace_raw_output_##call, \ +}; + #undef DEFINE_EVENT_PRINT #define DEFINE_EVENT_PRINT(template, call, proto, args, print) \ static notrace enum print_line_t \ @@ -244,6 +297,12 @@ static struct trace_event_fields trace_event_fields_##call[] = { \ tstruct \ {} }; +#undef DECLARE_EVENT_CLASS_PRINT_INIT +#define DECLARE_EVENT_CLASS_PRINT_INIT(call, proto, args, tstruct, func, print, init) \ +static struct trace_event_fields trace_event_fields_##call[] = { \ + tstruct \ + {} }; + #undef DEFINE_EVENT_PRINT #define DEFINE_EVENT_PRINT(template, name, proto, args, print) @@ -265,6 +324,20 @@ static inline notrace int trace_event_get_offsets_##call( \ return __data_size; \ } +#undef DECLARE_EVENT_CLASS_PRINT_INIT +#define DECLARE_EVENT_CLASS_PRINT_INIT(call, proto, args, tstruct, assign, print, init) \ +static inline notrace int trace_event_get_offsets_##call( \ + struct trace_event_data_offsets_##call *__data_offsets, proto) \ +{ \ + int __data_size = 0; \ + int __maybe_unused __item_length; \ + struct trace_event_raw_##call __maybe_unused *entry; \ + \ + tstruct; \ + \ + return __data_size; \ +} + #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) /* @@ -403,6 +476,37 @@ trace_event_raw_event_##call(void *__data, proto) \ \ trace_event_buffer_commit(&fbuffer); \ } + +#undef DECLARE_EVENT_CLASS_PRINT_INIT +#define DECLARE_EVENT_CLASS_PRINT_INIT(call, proto, args, tstruct, assign, print, init) \ + \ +static notrace void \ +trace_event_raw_event_##call(void *__data, proto) \ +{ \ + struct trace_event_file *trace_file = __data; \ + struct trace_event_data_offsets_##call __maybe_unused __data_offsets;\ + struct trace_event_buffer fbuffer; \ + struct trace_event_raw_##call *entry; \ + int __data_size; \ + \ + if (trace_trigger_soft_disabled(trace_file)) \ + return; \ + \ + __data_size = trace_event_get_offsets_##call(&__data_offsets, args); \ + \ + entry = trace_event_buffer_reserve(&fbuffer, trace_file, \ + sizeof(*entry) + __data_size); \ + \ + if (!entry) \ + return; \ + \ + tstruct \ + \ + { assign; } \ + \ + trace_event_buffer_commit(&fbuffer); \ +} + /* * The ftrace_test_probe is compiled out, it is only here as a build time check * to make sure that if the tracepoint handling changes, the ftrace probe will @@ -434,6 +538,20 @@ static struct trace_event_class __used __refdata event_class_##call = { \ _TRACE_PERF_INIT(call) \ }; +#undef DECLARE_EVENT_CLASS_PRINT_INIT +#define DECLARE_EVENT_CLASS_PRINT_INIT(call, proto, args, tstruct, assign, print, init) \ +_TRACE_PERF_PROTO(call, PARAMS(proto)); \ +static char print_fmt_##call[] = print; \ +static struct trace_event_class __used __refdata event_class_##call = { \ + .system = TRACE_SYSTEM_STRING, \ + .fields_array = trace_event_fields_##call, \ + .fields = LIST_HEAD_INIT(event_class_##call.fields),\ + .raw_init = trace_event_raw_init, \ + .probe = trace_event_raw_event_##call, \ + .reg = trace_event_reg, \ + _TRACE_PERF_INIT(call) \ +}; + #undef DEFINE_EVENT #define DEFINE_EVENT(template, call, proto, args) \ \ -- 2.17.1