diff mbox

[10/48] perf tools: Introduce bpf-output event

Message ID 1456132275-98875-11-git-send-email-wangnan0@huawei.com
State Accepted
Commit 03e0a7df3efd959e40cd7ff40b1fabddc234ec5a
Headers show

Commit Message

Wang Nan Feb. 22, 2016, 9:10 a.m. UTC
Commit a43eec304259a6c637f4014a6d4767159b6a3aa3 (bpf: introduce
bpf_perf_event_output() helper) add a helper to enable BPF program
output data to perf ring buffer through a new type of perf event
PERF_COUNT_SW_BPF_OUTPUT. This patch enable perf to create perf
event of that type. Now perf user can use following cmdline to
receive output data from BPF programs:

 # ./perf record -a -e bpf-output/no-inherit,name=evt/ \
                    -e ./test_bpf_output.c/map:channel.event=evt/ ls /
 # ./perf script
            perf  1560 [004] 347747.086295:                       evt:  ffffffff811fd201 sys_write ...
            perf  1560 [004] 347747.086300:                       evt:  ffffffff811fd201 sys_write ...
            perf  1560 [004] 347747.086315:                       evt:  ffffffff811fd201 sys_write ...
            ...

Test result:
 # cat ./test_bpf_output.c
 /************************ BEGIN **************************/
 #include <uapi/linux/bpf.h>
 struct bpf_map_def {
 	unsigned int type;
 	unsigned int key_size;
 	unsigned int value_size;
 	unsigned int max_entries;
 };

 #define SEC(NAME) __attribute__((section(NAME), used))
 static u64 (*ktime_get_ns)(void) =
 	(void *)BPF_FUNC_ktime_get_ns;
 static int (*trace_printk)(const char *fmt, int fmt_size, ...) =
 	(void *)BPF_FUNC_trace_printk;
 static int (*get_smp_processor_id)(void) =
 	(void *)BPF_FUNC_get_smp_processor_id;
 static int (*perf_event_output)(void *, struct bpf_map_def *, int, void *, unsigned long) =
 	(void *)BPF_FUNC_perf_event_output;

 struct bpf_map_def SEC("maps") channel = {
 	.type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
 	.key_size = sizeof(int),
 	.value_size = sizeof(u32),
 	.max_entries = __NR_CPUS__,
 };

 SEC("func_write=sys_write")
 int func_write(void *ctx)
 {
 	struct {
 		u64 ktime;
 		int cpuid;
 	} __attribute__((packed)) output_data;
 	char error_data[] = "Error: failed to output: %d\n";

 	output_data.cpuid = get_smp_processor_id();
 	output_data.ktime = ktime_get_ns();
 	int err = perf_event_output(ctx, &channel, get_smp_processor_id(),
 				    &output_data, sizeof(output_data));
 	if (err)
 		trace_printk(error_data, sizeof(error_data), err);
 	return 0;
 }
 char _license[] SEC("license") = "GPL";
 int _version SEC("version") = LINUX_VERSION_CODE;
 /************************ END ***************************/

 # ./perf record -a -e bpf-output/no-inherit,name=evt/ \
                    -e ./test_bpf_output.c/map:channel.event=evt/ ls /
 # ./perf script | grep ls
          ls  2242 [003] 347851.557563:                       evt:  ffffffff811fd201 sys_write ...
          ls  2242 [003] 347851.557571:                       evt:  ffffffff811fd201 sys_write ...

Signed-off-by: Wang Nan <wangnan0@huawei.com>

Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/util/bpf-loader.c   | 5 ++---
 tools/perf/util/evsel.c        | 5 +++++
 tools/perf/util/evsel.h        | 8 ++++++++
 tools/perf/util/parse-events.l | 1 +
 4 files changed, 16 insertions(+), 3 deletions(-)

-- 
1.8.3.4

Comments

Wang Nan Feb. 24, 2016, 1:58 a.m. UTC | #1
On 2016/2/24 1:45, Arnaldo Carvalho de Melo wrote:
> Em Mon, Feb 22, 2016 at 09:10:37AM +0000, Wang Nan escreveu:

>> Commit a43eec304259a6c637f4014a6d4767159b6a3aa3 (bpf: introduce

>> bpf_perf_event_output() helper) add a helper to enable BPF program

>> output data to perf ring buffer through a new type of perf event

>> PERF_COUNT_SW_BPF_OUTPUT. This patch enable perf to create perf

>> event of that type. Now perf user can use following cmdline to

>> receive output data from BPF programs:

>>

>>   # ./perf record -a -e bpf-output/no-inherit,name=evt/ \

>>                      -e ./test_bpf_output.c/map:channel.event=evt/ ls /

>>   # ./perf script

>>              perf  1560 [004] 347747.086295:                       evt:  ffffffff811fd201 sys_write ...

>>              perf  1560 [004] 347747.086300:                       evt:  ffffffff811fd201 sys_write ...

>>              perf  1560 [004] 347747.086315:                       evt:  ffffffff811fd201 sys_write ...

>>              ...

>>

>> Test result:

>>   # cat ./test_bpf_output.c

>>   /************************ BEGIN **************************/

>>   #include <uapi/linux/bpf.h>

>>   struct bpf_map_def {

>>   	unsigned int type;

>>   	unsigned int key_size;

>>   	unsigned int value_size;

>>   	unsigned int max_entries;

>>   };

>>

>>   #define SEC(NAME) __attribute__((section(NAME), used))

>>   static u64 (*ktime_get_ns)(void) =

>>   	(void *)BPF_FUNC_ktime_get_ns;

>>   static int (*trace_printk)(const char *fmt, int fmt_size, ...) =

>>   	(void *)BPF_FUNC_trace_printk;

>>   static int (*get_smp_processor_id)(void) =

>>   	(void *)BPF_FUNC_get_smp_processor_id;

>>   static int (*perf_event_output)(void *, struct bpf_map_def *, int, void *, unsigned long) =

>>   	(void *)BPF_FUNC_perf_event_output;

>>

>>   struct bpf_map_def SEC("maps") channel = {

>>   	.type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,

>>   	.key_size = sizeof(int),

>>   	.value_size = sizeof(u32),

>>   	.max_entries = __NR_CPUS__,

>>   };

>>

>>   SEC("func_write=sys_write")

>>   int func_write(void *ctx)

>>   {

>>   	struct {

>>   		u64 ktime;

>>   		int cpuid;

>>   	} __attribute__((packed)) output_data;

>>   	char error_data[] = "Error: failed to output: %d\n";

>>

>>   	output_data.cpuid = get_smp_processor_id();

>>   	output_data.ktime = ktime_get_ns();

>>   	int err = perf_event_output(ctx, &channel, get_smp_processor_id(),

>>   				    &output_data, sizeof(output_data));

>>   	if (err)

>>   		trace_printk(error_data, sizeof(error_data), err);

>>   	return 0;

>>   }

>>   char _license[] SEC("license") = "GPL";

>>   int _version SEC("version") = LINUX_VERSION_CODE;

>>   /************************ END ***************************/

>>

>>   # ./perf record -a -e bpf-output/no-inherit,name=evt/ \

>>                      -e ./test_bpf_output.c/map:channel.event=evt/ ls /

>>   # ./perf script | grep ls

>>            ls  2242 [003] 347851.557563:                       evt:  ffffffff811fd201 sys_write ...

>>            ls  2242 [003] 347851.557571:                       evt:  ffffffff811fd201 sys_write ...

> So, there is something strange here:

>

>          if (unlikely(event->oncpu != smp_processor_id()))

>                  return -EOPNOTSUPP;

>

> This is where I am hitting, with:

>

> [acme@jouet linux]$ uname -r

> 4.5.0-rc4

>

>          int err = perf_event_output(ctx, &channel, get_smp_processor_id(),

>                                      &output_data, sizeof(output_data));

>          if (err)

>                  trace_printk(error_data, sizeof(error_data), err);

>

> And then:

>

> [root@jouet bpf]# tail /sys/kernel/debug/tracing/trace

>              perf-13040 [003] d... 12062.807729: : Error: failed to output: -95

>              perf-13040 [003] d... 12062.807731: : Error: failed to output: -95

>              perf-13040 [003] d... 12062.807732: : Error: failed to output: -95

>              perf-13040 [003] d... 12062.807735: : Error: failed to output: -95

>              perf-13040 [003] d... 12062.807737: : Error: failed to output: -95

>              perf-13040 [003] d... 12062.807744: : Error: failed to output: -95

>   gnome-terminal--3091  [001] d... 12062.807773: : Error: failed to output: -95

>   gnome-terminal--3091  [001] d... 12062.807784: : Error: failed to output: -95

>             gmain-2830  [002] d... 12062.811791: : Error: failed to output: -95

>             gmain-2830  [002] d... 12062.811810: : Error: failed to output: -95

> [root@jouet bpf]#

>

> Ideas? AFK for a while, will continue investigating.


I also noticed this output, but didn't digg into it because all events
I concerned is okay. I'll look into this today.

> This already was submitted to Ingo, BTW.

>

> I used, as in the changeset comment tests:

>

> perf record -a -e bpf-output/no-inherit,name=evt/ -e ./test_bpf_output.c/map:channel.event=evt/ ls /

>

> And perf script told me:

>

> [root@jouet bpf]# perf script | tail

>      perf 13040 [003] 12062.708337:  evt:  ffffffff81234eb1 sys_write (/lib/modules/4.5.0-rc4/build/vmlinux)

>      perf 13040 [003] 12062.708339:  evt:  ffffffff81234eb1 sys_write (/lib/modules/4.5.0-rc4/build/vmlinux)

>      perf 13040 [003] 12062.708340:  evt:  ffffffff81234eb1 sys_write (/lib/modules/4.5.0-rc4/build/vmlinux)

>      perf 13040 [003] 12062.708341:  evt:  ffffffff81234eb1 sys_write (/lib/modules/4.5.0-rc4/build/vmlinux)

>      perf 13040 [003] 12062.708343:  evt:  ffffffff81234eb1 sys_write (/lib/modules/4.5.0-rc4/build/vmlinux)

>      perf 13040 [003] 12062.708344:  evt:  ffffffff81234eb1 sys_write (/lib/modules/4.5.0-rc4/build/vmlinux)

>      perf 13040 [003] 12062.708346:  evt:  ffffffff81234eb1 sys_write (/lib/modules/4.5.0-rc4/build/vmlinux)

>      perf 13040 [003] 12062.708347:  evt:  ffffffff81234eb1 sys_write (/lib/modules/4.5.0-rc4/build/vmlinux)

>      perf 13040 [003] 12062.708348:  evt:  ffffffff81234eb1 sys_write (/lib/modules/4.5.0-rc4/build/vmlinux)

>      perf 13040 [003] 12062.708350:  evt:  ffffffff81234eb1 sys_write (/lib/modules/4.5.0-rc4/build/vmlinux)

> [root@jouet bpf]#

>

> Wonder where that /lib/modules/4.5.0-rc4/build/vmlinux came from...

>

> [root@jouet bpf]# perf script | cut -d'(' -f2 | sort | uniq -c

>     1141 /lib/modules/4.5.0-rc4/build/vmlinux)


It's a standard directory for perf searching vmlinux. Isn't it?

tools/perf/util/symbol.c:

static const char * const vmlinux_paths_upd[] = {
         "/boot/vmlinux-%s",
         "/usr/lib/debug/boot/vmlinux-%s",
         "/lib/modules/%s/build/vmlinux",
         "/usr/lib/debug/lib/modules/%s/vmlinux",
         "/usr/lib/debug/boot/vmlinux-%s.debug"
};

So what's your problem?

Thank you.
Wang Nan Feb. 24, 2016, 2:04 a.m. UTC | #2
On 2016/2/24 9:58, Wangnan (F) wrote:
>

>

> On 2016/2/24 1:45, Arnaldo Carvalho de Melo wrote:

>> Em Mon, Feb 22, 2016 at 09:10:37AM +0000, Wang Nan escreveu:

>>> Commit a43eec304259a6c637f4014a6d4767159b6a3aa3 (bpf: introduce

>>> bpf_perf_event_output() helper) add a helper to enable BPF program

>>> output data to perf ring buffer through a new type of perf event

>>> PERF_COUNT_SW_BPF_OUTPUT. This patch enable perf to create perf

>>> event of that type. Now perf user can use following cmdline to

>>> receive output data from BPF programs:

>>>

>>>   # ./perf record -a -e bpf-output/no-inherit,name=evt/ \

>>>                      -e ./test_bpf_output.c/map:channel.event=evt/ ls /

>>>   # ./perf script

>>>              perf  1560 [004] 347747.086295:                       

>>> evt:  ffffffff811fd201 sys_write ...

>>>              perf  1560 [004] 347747.086300:                       

>>> evt:  ffffffff811fd201 sys_write ...

>>>              perf  1560 [004] 347747.086315:                       

>>> evt:  ffffffff811fd201 sys_write ...

>>>              ...

>>>

>>> Test result:

>>>   # cat ./test_bpf_output.c

>>>   /************************ BEGIN **************************/

>>>   #include <uapi/linux/bpf.h>

>>>   struct bpf_map_def {

>>>       unsigned int type;

>>>       unsigned int key_size;

>>>       unsigned int value_size;

>>>       unsigned int max_entries;

>>>   };

>>>

>>>   #define SEC(NAME) __attribute__((section(NAME), used))

>>>   static u64 (*ktime_get_ns)(void) =

>>>       (void *)BPF_FUNC_ktime_get_ns;

>>>   static int (*trace_printk)(const char *fmt, int fmt_size, ...) =

>>>       (void *)BPF_FUNC_trace_printk;

>>>   static int (*get_smp_processor_id)(void) =

>>>       (void *)BPF_FUNC_get_smp_processor_id;

>>>   static int (*perf_event_output)(void *, struct bpf_map_def *, int, 

>>> void *, unsigned long) =

>>>       (void *)BPF_FUNC_perf_event_output;

>>>

>>>   struct bpf_map_def SEC("maps") channel = {

>>>       .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,

>>>       .key_size = sizeof(int),

>>>       .value_size = sizeof(u32),

>>>       .max_entries = __NR_CPUS__,

>>>   };

>>>

>>>   SEC("func_write=sys_write")

>>>   int func_write(void *ctx)

>>>   {

>>>       struct {

>>>           u64 ktime;

>>>           int cpuid;

>>>       } __attribute__((packed)) output_data;

>>>       char error_data[] = "Error: failed to output: %d\n";

>>>

>>>       output_data.cpuid = get_smp_processor_id();

>>>       output_data.ktime = ktime_get_ns();

>>>       int err = perf_event_output(ctx, &channel, 

>>> get_smp_processor_id(),

>>>                       &output_data, sizeof(output_data));

>>>       if (err)

>>>           trace_printk(error_data, sizeof(error_data), err);

>>>       return 0;

>>>   }

>>>   char _license[] SEC("license") = "GPL";

>>>   int _version SEC("version") = LINUX_VERSION_CODE;

>>>   /************************ END ***************************/

>>>

>>>   # ./perf record -a -e bpf-output/no-inherit,name=evt/ \

>>>                      -e ./test_bpf_output.c/map:channel.event=evt/ ls /

>>>   # ./perf script | grep ls

>>>            ls  2242 [003] 347851.557563: evt:  ffffffff811fd201 

>>> sys_write ...

>>>            ls  2242 [003] 347851.557571: evt:  ffffffff811fd201 

>>> sys_write ...

>> So, there is something strange here:

>>

>>          if (unlikely(event->oncpu != smp_processor_id()))

>>                  return -EOPNOTSUPP;

>>

>


All failures have 'event->oncpu == -1' here. I guess we should suppress 
warning in
this case. But why event->oncpu becomes -1?

Thank you.
Wang Nan Feb. 24, 2016, 4:03 a.m. UTC | #3
On 2016/2/24 10:04, Wangnan (F) wrote:
>

>

> On 2016/2/24 9:58, Wangnan (F) wrote:

>>

>>

>> On 2016/2/24 1:45, Arnaldo Carvalho de Melo wrote:

>>> Em Mon, Feb 22, 2016 at 09:10:37AM +0000, Wang Nan escreveu:

>>>> Commit a43eec304259a6c637f4014a6d4767159b6a3aa3 (bpf: introduce

>>>> bpf_perf_event_output() helper) add a helper to enable BPF program

>>>> output data to perf ring buffer through a new type of perf event

>>>> PERF_COUNT_SW_BPF_OUTPUT. This patch enable perf to create perf

>>>> event of that type. Now perf user can use following cmdline to

>>>> receive output data from BPF programs:

>>>>

>>>>   # ./perf record -a -e bpf-output/no-inherit,name=evt/ \

>>>>                      -e ./test_bpf_output.c/map:channel.event=evt/ 

>>>> ls /

>>>>   # ./perf script

>>>>              perf  1560 [004] 347747.086295:                       

>>>> evt:  ffffffff811fd201 sys_write ...

>>>>              perf  1560 [004] 347747.086300:                       

>>>> evt:  ffffffff811fd201 sys_write ...

>>>>              perf  1560 [004] 347747.086315:                       

>>>> evt:  ffffffff811fd201 sys_write ...

>>>>              ...

>>>>

>>>> Test result:

>>>>   # cat ./test_bpf_output.c

>>>>   /************************ BEGIN **************************/

>>>>   #include <uapi/linux/bpf.h>

>>>>   struct bpf_map_def {

>>>>       unsigned int type;

>>>>       unsigned int key_size;

>>>>       unsigned int value_size;

>>>>       unsigned int max_entries;

>>>>   };

>>>>

>>>>   #define SEC(NAME) __attribute__((section(NAME), used))

>>>>   static u64 (*ktime_get_ns)(void) =

>>>>       (void *)BPF_FUNC_ktime_get_ns;

>>>>   static int (*trace_printk)(const char *fmt, int fmt_size, ...) =

>>>>       (void *)BPF_FUNC_trace_printk;

>>>>   static int (*get_smp_processor_id)(void) =

>>>>       (void *)BPF_FUNC_get_smp_processor_id;

>>>>   static int (*perf_event_output)(void *, struct bpf_map_def *, 

>>>> int, void *, unsigned long) =

>>>>       (void *)BPF_FUNC_perf_event_output;

>>>>

>>>>   struct bpf_map_def SEC("maps") channel = {

>>>>       .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,

>>>>       .key_size = sizeof(int),

>>>>       .value_size = sizeof(u32),

>>>>       .max_entries = __NR_CPUS__,

>>>>   };

>>>>

>>>>   SEC("func_write=sys_write")

>>>>   int func_write(void *ctx)

>>>>   {

>>>>       struct {

>>>>           u64 ktime;

>>>>           int cpuid;

>>>>       } __attribute__((packed)) output_data;

>>>>       char error_data[] = "Error: failed to output: %d\n";

>>>>

>>>>       output_data.cpuid = get_smp_processor_id();

>>>>       output_data.ktime = ktime_get_ns(); supr

>>>>       int err = perf_event_output(ctx, &channel, 

>>>> get_smp_processor_id(),

>>>>                       &output_data, sizeof(output_data));

>>>>       if (err)

>>>>           trace_printk(error_data, sizeof(error_data), err);

>>>>       return 0;

>>>>   }

>>>>   char _license[] SEC("license") = "GPL";

>>>>   int _version SEC("version") = LINUX_VERSION_CODE;

>>>>   /************************ END ***************************/

>>>>

>>>>   # ./perf record -a -e bpf-output/no-inherit,name=evt/ \

>>>>                      -e ./test_bpf_output.c/map:channel.event=evt/ 

>>>> ls /

>>>>   # ./perf script | grep ls

>>>>            ls  2242 [003] 347851.557563: evt: ffffffff811fd201 

>>>> sys_write ...

>>>>            ls  2242 [003] 347851.557571: evt: ffffffff811fd201 

>>>> sys_write ...

>>> So, there is something strange here:

>>>

>>>          if (unlikely(event->oncpu != smp_processor_id()))

>>>                  return -EOPNOTSUPP;

>>>

>>

>

> All failures have 'event->oncpu == -1' here. I guess we should 

> suppress warning in

> this case. But why event->oncpu becomes -1?

>


For this specific test it is not surprising to see these error messages. 
In this test
we create bpf-output channel on 'ls' process only, but the BPF script is 
triggered
on all procs (BPF triggering is not related to perf event scheduling). 
Trying to
output data through 'ls' specific bpf-output channel should fail if this 
'sys_write'
is not issued by 'ls' or its children. So it is a correct behavior.

However, I also see them in system wide channel:

  # echo "" > /sys/kernel/debug/tracing/trace
  # ./perf record -a -e bpf-output/no-inherit,name=evt/ \
                     -e ./test_bpf_output.c/map:channel.event=evt/
                     -a
  ^C[ perf record: Woken up 0 times to write data ]
  [ perf record: Captured and wrote 17.534 MB perf.data (264326 samples) ]
  # cat /sys/kernel/debug/tracing/trace | tail
    rs:main Q:Reg-582   [000] d..2  4858.711225: : Error: failed to 
output: -95
    rs:main Q:Reg-582   [000] d..2  4858.711241: : Error: failed to 
output: -95
            gmain-1858  [003] d..2  4858.711436: : Error: failed to 
output: -95
            gmain-1858  [003] d..2  4858.711441: : Error: failed to 
output: -95
            gmain-1858  [003] d..2  4858.711473: : Error: failed to 
output: -95
    rs:main Q:Reg-582   [002] d..2  4858.712215: : Error: failed to 
output: -95
    rs:main Q:Reg-582   [002] d..2  4858.712224: : Error: failed to 
output: -95
            gmain-1858  [003] d..2  4858.712230: : Error: failed to 
output: -95
    rs:main Q:Reg-582   [002] d..2  4858.712235: : Error: failed to 
output: -95
    rs:main Q:Reg-582   [002] d..2  4858.712239: : Error: failed to 
output: -95

System wide events can also be scheduled in and out. If the bpf-output 
events
are scheduled out, trying to output data through it causes the above 
failure.
I don't think it is a problem.

Peter, Could you please give some infomation? In which case a system wide
bpf output channel would be scheduled out?

Thank you.
Wang Nan Feb. 24, 2016, 5:03 a.m. UTC | #4
On 2016/2/24 12:03, Wangnan (F) wrote:
>

>

> On 2016/2/24 10:04, Wangnan (F) wrote:

>>

>>

>> On 2016/2/24 9:58, Wangnan (F) wrote:

>>>


[SNIP]

>>> So, there is something strange here:

>>>>

>>>>          if (unlikely(event->oncpu != smp_processor_id()))

>>>>                  return -EOPNOTSUPP;

>>>>

>>>

>>

>> All failures have 'event->oncpu == -1' here. I guess we should 

>> suppress warning in

>> this case. But why event->oncpu becomes -1?

>>

>

> For this specific test it is not surprising to see these error 

> messages. In this test

> we create bpf-output channel on 'ls' process only, but the BPF script 

> is triggered

> on all procs (BPF triggering is not related to perf event scheduling). 

> Trying to

> output data through 'ls' specific bpf-output channel should fail if 

> this 'sys_write'

> is not issued by 'ls' or its children. So it is a correct behavior.

>

> However, I also see them in system wide channel:

>

>  # echo "" > /sys/kernel/debug/tracing/trace

>  # ./perf record -a -e bpf-output/no-inherit,name=evt/ \

>                     -e ./test_bpf_output.c/map:channel.event=evt/

>                     -a

>  ^C[ perf record: Woken up 0 times to write data ]

>  [ perf record: Captured and wrote 17.534 MB perf.data (264326 samples) ]

>  # cat /sys/kernel/debug/tracing/trace | tail

>    rs:main Q:Reg-582   [000] d..2  4858.711225: : Error: failed to 

> output: -95

>    rs:main Q:Reg-582   [000] d..2  4858.711241: : Error: failed to 

> output: -95

>            gmain-1858  [003] d..2  4858.711436: : Error: failed to 

> output: -95

>            gmain-1858  [003] d..2  4858.711441: : Error: failed to 

> output: -95

>            gmain-1858  [003] d..2  4858.711473: : Error: failed to 

> output: -95

>    rs:main Q:Reg-582   [002] d..2  4858.712215: : Error: failed to 

> output: -95

>    rs:main Q:Reg-582   [002] d..2  4858.712224: : Error: failed to 

> output: -95

>            gmain-1858  [003] d..2  4858.712230: : Error: failed to 

> output: -95

>    rs:main Q:Reg-582   [002] d..2  4858.712235: : Error: failed to 

> output: -95

>    rs:main Q:Reg-582   [002] d..2  4858.712239: : Error: failed to 

> output: -95

>

> System wide events can also be scheduled in and out. If the bpf-output 

> events

> are scheduled out, trying to output data through it causes the above 

> failure.

> I don't think it is a problem.

>

> Peter, Could you please give some infomation? In which case a system wide

> bpf output channel would be scheduled out?

>


Sorry, I think my brain is not quite well. Actually this is a easy question:
all ENOTSUPP results are generated before PERF_EVENT_IOC_ENABLE or after
PERF_EVENT_IOC_DISABLE. You saw so many failure messages because it is 
sys_write,
and perf itself needs it.

So you can simply ignore these messages.

Thank you.
diff mbox

Patch

diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 44824e3..0967ce6 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -1331,13 +1331,12 @@  apply_config_evsel_for_key(const char *name, int map_fd, void *pkey,
 		return -BPF_LOADER_ERRNO__OBJCONF_MAP_EVTINH;
 	}
 
+	if (perf_evsel__is_bpf_output(evsel))
+		check_pass = true;
 	if (attr->type == PERF_TYPE_RAW)
 		check_pass = true;
 	if (attr->type == PERF_TYPE_HARDWARE)
 		check_pass = true;
-	if (attr->type == PERF_TYPE_SOFTWARE &&
-			attr->config == PERF_COUNT_SW_BPF_OUTPUT)
-		check_pass = true;
 	if (!check_pass) {
 		pr_debug("ERROR: Event type is wrong for map %s\n", name);
 		return -BPF_LOADER_ERRNO__OBJCONF_MAP_EVTTYPE;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 6ae20d0..0902fe4 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -225,6 +225,11 @@  struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
 	if (evsel != NULL)
 		perf_evsel__init(evsel, attr, idx);
 
+	if (perf_evsel__is_bpf_output(evsel)) {
+		evsel->attr.sample_type |= PERF_SAMPLE_RAW;
+		evsel->attr.sample_period = 1;
+	}
+
 	return evsel;
 }
 
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 8e75434..efad78f 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -364,6 +364,14 @@  static inline bool perf_evsel__is_function_event(struct perf_evsel *evsel)
 #undef FUNCTION_EVENT
 }
 
+static inline bool perf_evsel__is_bpf_output(struct perf_evsel *evsel)
+{
+	struct perf_event_attr *attr = &evsel->attr;
+
+	return (attr->config == PERF_COUNT_SW_BPF_OUTPUT) &&
+		(attr->type == PERF_TYPE_SOFTWARE);
+}
+
 struct perf_attr_details {
 	bool freq;
 	bool verbose;
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index fb85d03..1477fbc 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -248,6 +248,7 @@  cpu-migrations|migrations			{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COU
 alignment-faults				{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); }
 emulation-faults				{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); }
 dummy						{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY); }
+bpf-output					{ return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_BPF_OUTPUT); }
 
 	/*
 	 * We have to handle the kernel PMU event cycles-ct/cycles-t/mem-loads/mem-stores separately.