Thread (15 messages) flat view 15 messages, 3 authors, 2020-09-29

Re: [PATCH v6 bpf-next 6/6] selftests/bpf: add test for bpf_seq_printf_btf helper

From: Alexei Starovoitov <hidden>
Date: 2020-09-29 01:54:57
Also in: bpf, linux-kselftest, lkml

On Mon, Sep 28, 2020 at 10:51:19AM -0700, Andrii Nakryiko wrote:
On Mon, Sep 28, 2020 at 7:14 AM Alan Maguire [off-list ref] wrote:
quoted


On Thu, 24 Sep 2020, Alexei Starovoitov wrote:
quoted
to whatever number, but printing single task_struct needs ~800 lines and
~18kbytes. Humans can scroll through that much spam, but can we make it less
verbose by default somehow?
May be not in this patch set, but in the follow up?
One approach that might work would be to devote 4 bits or so of
flag space to a "maximum depth" specifier; i.e. at depth 1,
only base types are displayed, no aggregate types like arrays,
structs and unions.  We've already got depth processing in the
code to figure out if possibly zeroed nested data needs to be
displayed, so it should hopefully be a simple follow-up.
That sounds great to me.

Would it be possible to specify the depth from the other side as well?
Like a lot of 'leaf' fields are struct list_head, struct lockdep_map,
atomic_t, struct callback_head, etc.
When printing a big struct I'm interested in the data that the
struct provides, but many small inner structs are not that useful.
So the data is at the top level and in few layers down,
but depth is different at different fields.
If I could tell printf to avoid printing the last depth I think
it will make the output more concise.
Whereas if I say print depth=2 from the top it will still print
'struct list_head' that happened to be at the top level.
quoted
One way to express it would be to use "..." to denote field(s)
were omitted. We could even use the number of "."s to denote
cases where multiple fields were omitted, giving a visual sense
of how much data was omitted.  So for example with
BTF_F_MAX_DEPTH(1), task_struct looks like this:

(struct task_struct){
 .state = ()1,
 .stack = ( *)0x00000000029d1e6f,
 ...
 .flags = (unsigned int)4194560,
 ...
 .cpu = (unsigned int)36,
 .wakee_flips = (unsigned int)11,
 .wakee_flip_decay_ts = (long unsigned int)4294914874,
 .last_wakee = (struct task_struct *)0x000000006c7dfe6d,
 .recent_used_cpu = (int)19,
 .wake_cpu = (int)36,
 .prio = (int)120,
 .static_prio = (int)120,
 .normal_prio = (int)120,
 .sched_class = (struct sched_class *)0x00000000ad1561e6,
 ...
 .exec_start = (u64)674402577156,
 .sum_exec_runtime = (u64)5009664110,
 .vruntime = (u64)167038057,
 .prev_sum_exec_runtime = (u64)5009578167,
 .nr_migrations = (u64)54,
 .depth = (int)1,
 .parent = (struct sched_entity *)0x00000000cba60e7d,
 .cfs_rq = (struct cfs_rq *)0x0000000014f353ed,
 ...

...etc. What do you think?
It's not clear to me what exactly is omitted with ... ? Would it make
sense to still at least list a field name and "abbreviated" value.
E.g., for arrays:

.array_field = (int[16]){ ... },

Similarly for struct:

.struct_field = (struct my_struct){ ... },
+1
Something like this would be great.

Another idea...
If there is only one field in the struct can we omit it?
Like instead of:
   .refs = (atomic_t){
    .counter = (int)2,
   },
print
   .refs = (atomic_t){ 2 },

From C point of view it is still a valid initializer and
it's not ambiguous which field being inited, since there is only
one field.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help