On Fri, Dec 20, 2019 at 8:52 AM Martin Lau <kafai@xxxxxx> wrote: > > On Thu, Dec 19, 2019 at 11:22:17PM -0800, Martin Lau wrote: > > > [ ... ] > > > > > > +/* __bpf_##_name (e.g. __bpf_tcp_congestion_ops) is the map's value > > > > + * exposed to the userspace and its btf-type-id is stored > > > > + * at the map->btf_vmlinux_value_type_id. > > > > + * > > > > + * The *_name##_dummy is to ensure the BTF type is emitted. > > > > + */ > > > > + > > > > #define BPF_STRUCT_OPS_TYPE(_name) \ > > > > -extern struct bpf_struct_ops bpf_##_name; > > > > +extern struct bpf_struct_ops bpf_##_name; \ > > > > + \ > > > > +static struct __bpf_##_name { \ > > > > + BPF_STRUCT_OPS_COMMON_VALUE; \ > > > > + struct _name data ____cacheline_aligned_in_smp; \ > > > > +} *_name##_dummy; > > > > > > There are other ways to retain types in debug info without > > > creating new variables. For example, you can use it in a cast > > > like > > > (void *)(struct __bpf_##_name *)v > > hmm... What is v? > Got it. "v" could be any dummy pointer in a function. > I will use (void) instead of (void *) to avoid compiler warning. > This discussion inspired me to try this: #define PRESERVE_TYPE_INFO(type) ((void)(type *)0) ... somewhere in any function ... PRESERVE_TYPE_INFO(struct whatever_struct); And it works! We should probably put this helper macro somewhere in include/linux/bpf.h and use it consistently for cases like this. > > > > > Not sure whether we could easily find a place for such casting or not. > This can be done in bpf_struct_ops_init(). > > Thanks for the tips!