Re: [PATCH v5 perf,bpf 07/15] perf, bpf: save bpf_prog_info information as headers to perf.data

From: Song Liu
Date: Mon Mar 04 2019 - 14:41:50 EST




> On Mar 4, 2019, at 5:52 AM, Jiri Olsa <jolsa@xxxxxxxxxx> wrote:
>
> On Wed, Feb 27, 2019 at 09:06:35PM -0800, Song Liu wrote:
>> This patch enables perf-record to save bpf_prog_info information as
>> headers to perf.data. A new header type HEADER_BPF_PROG_INFO is
>> introduced for this data.
>>
>> Signed-off-by: Song Liu <songliubraving@xxxxxx>
>> ---
>> tools/perf/util/header.c | 143 ++++++++++++++++++++++++++++++++++++++-
>> tools/perf/util/header.h | 1 +
>> 2 files changed, 143 insertions(+), 1 deletion(-)
>>
>> diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
>> index 4b88de5e9192..16f5bedb0b7d 100644
>> --- a/tools/perf/util/header.c
>> +++ b/tools/perf/util/header.c
>> @@ -18,6 +18,7 @@
>> #include <sys/utsname.h>
>> #include <linux/time64.h>
>> #include <dirent.h>
>> +#include <bpf/libbpf.h>
>>
>> #include "evlist.h"
>> #include "evsel.h"
>> @@ -39,6 +40,7 @@
>> #include "tool.h"
>> #include "time-utils.h"
>> #include "units.h"
>> +#include "bpf-event.h"
>>
>> #include "sane_ctype.h"
>>
>> @@ -1074,6 +1076,51 @@ static int write_clockid(struct feat_fd *ff,
>> sizeof(ff->ph->env.clockid_res_ns));
>> }
>>
>> +static int write_bpf_prog_info(struct feat_fd *ff,
>> + struct perf_evlist *evlist __maybe_unused)
>> +{
>> + struct perf_env *env = &ff->ph->env;
>> + struct rb_root *root;
>> + struct rb_node *next;
>> + u32 count = 0;
>> + int ret;
>> +
>> + down_read(&env->bpf_progs.lock);
>> +
>> + root = &env->bpf_progs.infos;
>> + next = rb_first(root);
>> + while (next) {
>> + ++count;
>> + next = rb_next(next);
>> + }
>> +
>> + ret = do_write(ff, &count, sizeof(count));
>> +
>> + if (ret < 0)
>> + goto out;
>> +
>> + next = rb_first(root);
>> + while (next) {
>> + struct bpf_prog_info_node *node;
>> + size_t len;
>> +
>> + node = rb_entry(next, struct bpf_prog_info_node, rb_node);
>> + next = rb_next(&node->rb_node);
>> + len = sizeof(struct bpf_prog_info_linear) +
>> + node->info_linear->data_len;
>> +
>> + /* before writing to file, translate address to offset */
>> + bpf_program__bpil_addr_to_offs(node->info_linear);
>> + ret = do_write(ff, node->info_linear, len);
>> + bpf_program__bpil_offs_to_addr(node->info_linear);
>
> what's the reason to call this before the error check?

This will translate the all the pointers to the right address
(instead of offsets). We only need the offsets when writing to
files. With this approach, the data is not changed whether the
function succeeds or not. It is probably not necessary right
now. But I think this may save us some debugging efforts in
the future.

Thanks,
Song

>
> thanks,
> jirka
>
>> + if (ret < 0)
>> + goto out;
>> + }
>> +out:
>> + up_read(&env->bpf_progs.lock);
>> + return ret;
>> +}
>
> SNIP