Skip to content

Commit f11f10b

Browse files
khueyIngo Molnar
authored andcommitted
perf/bpf: Call BPF handler directly, not through overflow machinery
To ultimately allow BPF programs attached to perf events to completely suppress all of the effects of a perf event overflow (rather than just the sample output, as they do today), call bpf_overflow_handler() from __perf_event_overflow() directly rather than modifying struct perf_event's overflow_handler. Return the BPF program's return value from bpf_overflow_handler() so that __perf_event_overflow() knows how to proceed. Remove the now unnecessary orig_overflow_handler from struct perf_event. This patch is solely a refactoring and results in no behavior change. Suggested-by: Namhyung Kim <[email protected]> Signed-off-by: Kyle Huey <[email protected]> Signed-off-by: Ingo Molnar <[email protected]> Acked-by: Song Liu <[email protected]> Acked-by: Jiri Olsa <[email protected]> Acked-by: Andrii Nakryiko <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 14e40a9 commit f11f10b

File tree

2 files changed

+12
-21
lines changed

2 files changed

+12
-21
lines changed

include/linux/perf_event.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -809,7 +809,6 @@ struct perf_event {
809809
u64 (*clock)(void);
810810
perf_overflow_handler_t overflow_handler;
811811
void *overflow_handler_context;
812-
perf_overflow_handler_t orig_overflow_handler;
813812
struct bpf_prog *prog;
814813
u64 bpf_cookie;
815814

@@ -1361,10 +1360,7 @@ __is_default_overflow_handler(perf_overflow_handler_t overflow_handler)
13611360
#ifdef CONFIG_BPF_SYSCALL
13621361
static inline bool uses_default_overflow_handler(struct perf_event *event)
13631362
{
1364-
if (likely(is_default_overflow_handler(event)))
1365-
return true;
1366-
1367-
return __is_default_overflow_handler(event->orig_overflow_handler);
1363+
return is_default_overflow_handler(event);
13681364
}
13691365
#else
13701366
#define uses_default_overflow_handler(event) \

kernel/events/core.c

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9564,9 +9564,9 @@ static inline bool sample_is_allowed(struct perf_event *event, struct pt_regs *r
95649564
}
95659565

95669566
#ifdef CONFIG_BPF_SYSCALL
9567-
static void bpf_overflow_handler(struct perf_event *event,
9568-
struct perf_sample_data *data,
9569-
struct pt_regs *regs)
9567+
static int bpf_overflow_handler(struct perf_event *event,
9568+
struct perf_sample_data *data,
9569+
struct pt_regs *regs)
95709570
{
95719571
struct bpf_perf_event_data_kern ctx = {
95729572
.data = data,
@@ -9587,10 +9587,8 @@ static void bpf_overflow_handler(struct perf_event *event,
95879587
rcu_read_unlock();
95889588
out:
95899589
__this_cpu_dec(bpf_prog_active);
9590-
if (!ret)
9591-
return;
95929590

9593-
event->orig_overflow_handler(event, data, regs);
9591+
return ret;
95949592
}
95959593

95969594
static int perf_event_set_bpf_handler(struct perf_event *event,
@@ -9626,8 +9624,6 @@ static int perf_event_set_bpf_handler(struct perf_event *event,
96269624

96279625
event->prog = prog;
96289626
event->bpf_cookie = bpf_cookie;
9629-
event->orig_overflow_handler = READ_ONCE(event->overflow_handler);
9630-
WRITE_ONCE(event->overflow_handler, bpf_overflow_handler);
96319627
return 0;
96329628
}
96339629

@@ -9638,15 +9634,15 @@ static void perf_event_free_bpf_handler(struct perf_event *event)
96389634
if (!prog)
96399635
return;
96409636

9641-
WRITE_ONCE(event->overflow_handler, event->orig_overflow_handler);
96429637
event->prog = NULL;
96439638
bpf_prog_put(prog);
96449639
}
96459640
#else
9646-
static void bpf_overflow_handler(struct perf_event *event,
9647-
struct perf_sample_data *data,
9648-
struct pt_regs *regs)
9641+
static int bpf_overflow_handler(struct perf_event *event,
9642+
struct perf_sample_data *data,
9643+
struct pt_regs *regs)
96499644
{
9645+
return 1;
96509646
}
96519647

96529648
static int perf_event_set_bpf_handler(struct perf_event *event,
@@ -9730,7 +9726,8 @@ static int __perf_event_overflow(struct perf_event *event,
97309726
irq_work_queue(&event->pending_irq);
97319727
}
97329728

9733-
READ_ONCE(event->overflow_handler)(event, data, regs);
9729+
if (!(event->prog && !bpf_overflow_handler(event, data, regs)))
9730+
READ_ONCE(event->overflow_handler)(event, data, regs);
97349731

97359732
if (*perf_event_fasync(event) && event->pending_kill) {
97369733
event->pending_wakeup = 1;
@@ -11997,13 +11994,11 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
1199711994
overflow_handler = parent_event->overflow_handler;
1199811995
context = parent_event->overflow_handler_context;
1199911996
#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_EVENT_TRACING)
12000-
if (overflow_handler == bpf_overflow_handler) {
11997+
if (parent_event->prog) {
1200111998
struct bpf_prog *prog = parent_event->prog;
1200211999

1200312000
bpf_prog_inc(prog);
1200412001
event->prog = prog;
12005-
event->orig_overflow_handler =
12006-
parent_event->orig_overflow_handler;
1200712002
}
1200812003
#endif
1200912004
}

0 commit comments

Comments
 (0)