[RFC] btf: Some structs are doubled because of struct ring_buffer

Jiri Olsa
2019-12-13T20:38:28Z

hi,
the current BTF vmlinux file have some of the structs doubled:

$ bpftool btf dump file /sys/kernel/btf/vmlinux | grep task_struct
[150] STRUCT 'task_struct' size=11008 vlen=205
[12262] STRUCT 'task_struct' size=11008 vlen=205

$ bpftool btf dump file /sys/kernel/btf/vmlinux | grep "STRUCT 'perf_event'"
[1666] STRUCT 'perf_event' size=1160 vlen=70
[12301] STRUCT 'perf_event' size=1160 vlen=70

The reason seems to be that we have two distinct 'struct ring_buffer'
objects used in kernel: one in perf subsystem and one in kernel trace
subsystem.

When we compile kernel/trace/ring_buffer.c we have 'struct task_struct',
which references 'struct ring_buffer', which is at that compile time
defined in kernel/trace/ring_buffer.c.

While when we compile kernel/events/core.c we have 'struct task_struct',
which references ring buffer, which is at that compile time defined
in kernel/events/internal.h.

So we end up with 2 different 'struct task_struct' objects, and few
other objects which are on the way to the 'struct ring_buffer' field,
like:

[1666] STRUCT 'perf_event' size=1160 vlen=70
...
'rb' type_id=2289 bits_offset=5632
...

[2289] PTR '(anon)' type_id=10872

-> trace ring buffer

[10872] STRUCT 'ring_buffer' size=184 vlen=12
'flags' type_id=10 bits_offset=0
'cpus' type_id=22 bits_offset=32
'record_disabled' type_id=81 bits_offset=64
...

[12301] STRUCT 'perf_event' size=1160 vlen=70
...
'rb' type_id=13148 bits_offset=5632
...

[13148] PTR '(anon)' type_id=13147

-> perf ring buffer

[13147] STRUCT 'ring_buffer' size=240 vlen=33
'refcount' type_id=795 bits_offset=0
'callback_head' type_id=90 bits_offset=64
'nr_pages' type_id=22 bits_offset=192
'overwrite' type_id=22 bits_offset=224
'paused' type_id=22 bits_offset=256
...

I don't think dedup algorithm can handle this and I'm not sure if there's
some way in pahole to detect/prevent this.

I only found that if I rename the ring_buffer objects to have distinct
names, it will help:

$ bpftool btf dump file /sys/kernel/btf/vmlinux | grep task_struct
[150] STRUCT 'task_struct' size=11008 vlen=205

$ bpftool btf dump file /sys/kernel/btf/vmlinux | grep "STRUCT 'perf_event'"
[1665] STRUCT 'perf_event' size=1160 vlen=70

also the BTF data get smaller ;-) before:

$ ll /sys/kernel/btf/vmlinux
-r--r--r--. 1 root root 2067432 Dec 13 22:56 /sys/kernel/btf/vmlinux

after:
$ ll /sys/kernel/btf/vmlinux
-r--r--r--. 1 root root 1984345 Dec 13 23:02 /sys/kernel/btf/vmlinux

Peter, Steven,
if above is correct and there's no other better solution, would it be possible
to straighten up the namespace and user some distinct names for perf and ftrace
ring buffers?

thoughts?
jirka