bpf: permit multiple bpf attachments for a single perf event
This patch enables multiple bpf attachments for a kprobe/uprobe/tracepoint single trace event. Each trace_event keeps a list of attached perf events. When an event happens, all attached bpf programs will be executed based on the order of attachment. A global bpf_event_mutex lock is introduced to protect prog_array attaching and detaching. An alternative will be introduce a mutex lock in every trace_event_call structure, but it takes a lot of extra memory. So a global bpf_event_mutex lock is a good compromise. The bpf prog detachment involves allocation of memory. If the allocation fails, a dummy do-nothing program will replace to-be-detached program in-place. Signed-off-by: Yonghong Song <yhs@fb.com> Acked-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Martin KaFai Lau <kafai@fb.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

zatwierdzone przez
David S. Miller

rodzic
0b4c6841fe
commit
e87c6bc385
@@ -7954,11 +7954,9 @@ void perf_trace_run_bpf_submit(void *raw_data, int size, int rctx,
|
||||
struct pt_regs *regs, struct hlist_head *head,
|
||||
struct task_struct *task)
|
||||
{
|
||||
struct bpf_prog *prog = call->prog;
|
||||
|
||||
if (prog) {
|
||||
if (bpf_prog_array_valid(call)) {
|
||||
*(struct pt_regs **)raw_data = regs;
|
||||
if (!trace_call_bpf(prog, raw_data) || hlist_empty(head)) {
|
||||
if (!trace_call_bpf(call, raw_data) || hlist_empty(head)) {
|
||||
perf_swevent_put_recursion_context(rctx);
|
||||
return;
|
||||
}
|
||||
@@ -8147,13 +8145,11 @@ static int perf_event_set_bpf_prog(struct perf_event *event, u32 prog_fd)
|
||||
{
|
||||
bool is_kprobe, is_tracepoint, is_syscall_tp;
|
||||
struct bpf_prog *prog;
|
||||
int ret;
|
||||
|
||||
if (event->attr.type != PERF_TYPE_TRACEPOINT)
|
||||
return perf_event_set_bpf_handler(event, prog_fd);
|
||||
|
||||
if (event->tp_event->prog)
|
||||
return -EEXIST;
|
||||
|
||||
is_kprobe = event->tp_event->flags & TRACE_EVENT_FL_UKPROBE;
|
||||
is_tracepoint = event->tp_event->flags & TRACE_EVENT_FL_TRACEPOINT;
|
||||
is_syscall_tp = is_syscall_trace_event(event->tp_event);
|
||||
@@ -8181,26 +8177,20 @@ static int perf_event_set_bpf_prog(struct perf_event *event, u32 prog_fd)
|
||||
return -EACCES;
|
||||
}
|
||||
}
|
||||
event->tp_event->prog = prog;
|
||||
event->tp_event->bpf_prog_owner = event;
|
||||
|
||||
return 0;
|
||||
ret = perf_event_attach_bpf_prog(event, prog);
|
||||
if (ret)
|
||||
bpf_prog_put(prog);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void perf_event_free_bpf_prog(struct perf_event *event)
|
||||
{
|
||||
struct bpf_prog *prog;
|
||||
|
||||
if (event->attr.type != PERF_TYPE_TRACEPOINT) {
|
||||
perf_event_free_bpf_handler(event);
|
||||
return;
|
||||
}
|
||||
|
||||
prog = event->tp_event->prog;
|
||||
if (prog && event->tp_event->bpf_prog_owner == event) {
|
||||
event->tp_event->prog = NULL;
|
||||
bpf_prog_put(prog);
|
||||
}
|
||||
perf_event_detach_bpf_prog(event);
|
||||
}
|
||||
|
||||
#else
|
||||
|
Reference in New Issue
Block a user