Currently, the event probes save the type of the event they are attached to when recording the event. For example: # echo 'e:switch sched/sched_switch prev_state=$prev_state prev_prio=$prev_prio next_pid=$next_pid next_prio=$next_prio' > dynamic_events # cat events/eprobes/switch/format name: switch ID: 1717 format: field:unsigned short common_type; offset:0; size:2; signed:0; field:unsigned char common_flags; offset:2; size:1; signed:0; field:unsigned char common_preempt_count; offset:3; size:1; signed:0; field:int common_pid; offset:4; size:4; signed:1; field:unsigned int __probe_type; offset:8; size:4; signed:0; field:u64 prev_state; offset:12; size:8; signed:0; field:u64 prev_prio; offset:20; size:8; signed:0; field:u64 next_pid; offset:28; size:8; signed:0; field:u64 next_prio; offset:36; size:8; signed:0; print fmt: "(%u) prev_state=0x%Lx prev_prio=0x%Lx next_pid=0x%Lx next_prio=0x%Lx", REC->__probe_type, REC->prev_state, REC->prev_prio, REC->next_pid, REC->next_prio The __probe_type adds 4 bytes to every event. One of the reasons for creating eprobes is to limit what is traced in an event to be able to limit what is written into the ring buffer. Having this redundant 4 bytes to every event takes away from this. The event that is recorded can be retrieved from the event probe itself, that is available when the trace is happening. For user space tools, it could simply read the dynamic_event file to find the event they are for. So there is really no reason to write this information into the ring buffer for every event. Link: https://lkml.kernel.org/r/20220218190057.2f5a19a8@gandalf.local.home
Showing the changes to kernel (4 of 4 files). Show all
Unified · Split
| @@ -136,7 +136,6 @@ struct kprobe_trace_entry_head { · 135 unmodified lines | |||
| 136 | 136 | ||
| 137 | struct eprobe_trace_entry_head { | 137 | struct eprobe_trace_entry_head { |
| 138 | struct trace_entry ent; | 138 | struct trace_entry ent; |
| 139 | unsigned int type; | ||
| 140 | }; | 139 | }; |
| 141 | 140 | ||
| 142 | struct kretprobe_trace_entry_head { | 141 | struct kretprobe_trace_entry_head { |
| @@ -242,7 +242,6 @@ static int trace_eprobe_tp_arg_update(struct trace_eprobe *ep, int i) · 241 unmodified lines | |||
| 242 | 242 | ||
| 243 | static int eprobe_event_define_fields(struct trace_event_call *event_call) | 243 | static int eprobe_event_define_fields(struct trace_event_call *event_call) |
| 244 | { | 244 | { |
| 245 | int ret; | ||
| 246 | struct eprobe_trace_entry_head field; | 245 | struct eprobe_trace_entry_head field; |
| 247 | struct trace_probe *tp; | 246 | struct trace_probe *tp; |
| 248 | 247 | ||
| @@ -250,8 +249,6 @@ static int eprobe_event_define_fields(struct trace_event_call *event_call) · 1 unmodified line | |||
| 250 | if (WARN_ON_ONCE(!tp)) | 249 | if (WARN_ON_ONCE(!tp)) |
| 251 | return -ENOENT; | 250 | return -ENOENT; |
| 252 | 251 | ||
| 253 | DEFINE_FIELD(unsigned int, type, FIELD_STRING_TYPE, 0); | ||
| 254 | |||
| 255 | return traceprobe_define_arg_fields(event_call, sizeof(field), tp); | 252 | return traceprobe_define_arg_fields(event_call, sizeof(field), tp); |
| 256 | } | 253 | } |
| 257 | 254 | ||
| @@ -270,7 +267,9 @@ print_eprobe_event(struct trace_iterator *iter, int flags, · 12 unmodified lines | |||
| 270 | struct trace_event_call *pevent; | 267 | struct trace_event_call *pevent; |
| 271 | struct trace_event *probed_event; | 268 | struct trace_event *probed_event; |
| 272 | struct trace_seq *s = &iter->seq; | 269 | struct trace_seq *s = &iter->seq; |
| 270 | struct trace_eprobe *ep; | ||
| 273 | struct trace_probe *tp; | 271 | struct trace_probe *tp; |
| 272 | unsigned int type; | ||
| 274 | 273 | ||
| 275 | field = (struct eprobe_trace_entry_head *)iter->ent; | 274 | field = (struct eprobe_trace_entry_head *)iter->ent; |
| 276 | tp = trace_probe_primary_from_call( | 275 | tp = trace_probe_primary_from_call( |
| @@ -278,15 +277,18 @@ print_eprobe_event(struct trace_iterator *iter, int flags, · 1 unmodified line | |||
| 278 | if (WARN_ON_ONCE(!tp)) | 277 | if (WARN_ON_ONCE(!tp)) |
| 279 | goto out; | 278 | goto out; |
| 280 | 279 | ||
| 280 | ep = container_of(tp, struct trace_eprobe, tp); | ||
| 281 | type = ep->event->event.type; | ||
| 282 | |||
| 281 | trace_seq_printf(s, "%s: (", trace_probe_name(tp)); | 283 | trace_seq_printf(s, "%s: (", trace_probe_name(tp)); |
| 282 | 284 | ||
| 283 | probed_event = ftrace_find_event(field->type); | 285 | probed_event = ftrace_find_event(type); |
| 284 | if (probed_event) { | 286 | if (probed_event) { |
| 285 | pevent = container_of(probed_event, struct trace_event_call, event); | 287 | pevent = container_of(probed_event, struct trace_event_call, event); |
| 286 | trace_seq_printf(s, "%s.%s", pevent->class->system, | 288 | trace_seq_printf(s, "%s.%s", pevent->class->system, |
| 287 | trace_event_name(pevent)); | 289 | trace_event_name(pevent)); |
| 288 | } else { | 290 | } else { |
| 289 | trace_seq_printf(s, "%u", field->type); | 291 | trace_seq_printf(s, "%u", type); |
| 290 | } | 292 | } |
| 291 | 293 | ||
| 292 | trace_seq_putc(s, ')'); | 294 | trace_seq_putc(s, ')'); |
| @@ -498,10 +500,6 @@ __eprobe_trace_func(struct eprobe_data *edata, void *rec) · 205 unmodified lines | |||
| 498 | return; | 500 | return; |
| 499 | 501 | ||
| 500 | entry = fbuffer.entry = ring_buffer_event_data(fbuffer.event); | 502 | entry = fbuffer.entry = ring_buffer_event_data(fbuffer.event); |
| 501 | if (edata->ep->event) | ||
| 502 | entry->type = edata->ep->event->event.type; | ||
| 503 | else | ||
| 504 | entry->type = 0; | ||
| 505 | store_trace_args(&entry[1], &edata->ep->tp, rec, sizeof(*entry), dsize); | 503 | store_trace_args(&entry[1], &edata->ep->tp, rec, sizeof(*entry), dsize); |
| 506 | 504 | ||
| 507 | trace_event_buffer_commit(&fbuffer); | 505 | trace_event_buffer_commit(&fbuffer); |
| @@ -871,15 +871,15 @@ static int __set_print_fmt(struct trace_probe *tp, char *buf, int len, · 870 unmodified lines | |||
| 871 | switch (ptype) { | 871 | switch (ptype) { |
| 872 | case PROBE_PRINT_NORMAL: | 872 | case PROBE_PRINT_NORMAL: |
| 873 | fmt = "(%lx)"; | 873 | fmt = "(%lx)"; |
| 874 | arg = "REC->" FIELD_STRING_IP; | 874 | arg = ", REC->" FIELD_STRING_IP; |
| 875 | break; | 875 | break; |
| 876 | case PROBE_PRINT_RETURN: | 876 | case PROBE_PRINT_RETURN: |
| 877 | fmt = "(%lx <- %lx)"; | 877 | fmt = "(%lx <- %lx)"; |
| 878 | arg = "REC->" FIELD_STRING_FUNC ", REC->" FIELD_STRING_RETIP; | 878 | arg = ", REC->" FIELD_STRING_FUNC ", REC->" FIELD_STRING_RETIP; |
| 879 | break; | 879 | break; |
| 880 | case PROBE_PRINT_EVENT: | 880 | case PROBE_PRINT_EVENT: |
| 881 | fmt = "(%u)"; | 881 | fmt = ""; |
| 882 | arg = "REC->" FIELD_STRING_TYPE; | 882 | arg = ""; |
| 883 | break; | 883 | break; |
| 884 | default: | 884 | default: |
| 885 | WARN_ON_ONCE(1); | 885 | WARN_ON_ONCE(1); |
| @@ -903,7 +903,7 @@ static int __set_print_fmt(struct trace_probe *tp, char *buf, int len, · 17 unmodified lines | |||
| 903 | parg->type->fmt); | 903 | parg->type->fmt); |
| 904 | } | 904 | } |
| 905 | 905 | ||
| 906 | pos += snprintf(buf + pos, LEN_OR_ZERO, "\", %s", arg); | 906 | pos += snprintf(buf + pos, LEN_OR_ZERO, "\"%s", arg); |
| 907 | 907 | ||
| 908 | for (i = 0; i < tp->nr_args; i++) { | 908 | for (i = 0; i < tp->nr_args; i++) { |
| 909 | parg = tp->args + i; | 909 | parg = tp->args + i; |
| @@ -38,7 +38,6 @@ · 37 unmodified lines | |||
| 38 | #define FIELD_STRING_IP "__probe_ip" | 38 | #define FIELD_STRING_IP "__probe_ip" |
| 39 | #define FIELD_STRING_RETIP "__probe_ret_ip" | 39 | #define FIELD_STRING_RETIP "__probe_ret_ip" |
| 40 | #define FIELD_STRING_FUNC "__probe_func" | 40 | #define FIELD_STRING_FUNC "__probe_func" |
| 41 | #define FIELD_STRING_TYPE "__probe_type" | ||
| 42 | 41 | ||
| 43 | #undef DEFINE_FIELD | 42 | #undef DEFINE_FIELD |
| 44 | #define DEFINE_FIELD(type, item, name, is_signed) \ | 43 | #define DEFINE_FIELD(type, item, name, is_signed) \ |