Commit 0fe2b18d authored by Namhyung Kim's avatar Namhyung Kim Committed by Arnaldo Carvalho de Melo

perf bpf-filter: Support multiple events properly

So far it used tgid as a key to get the filter expressions in the
pinned filters map for regular users but it won't work well if the has
more than one filters at the same time.  Let's add the event id to the
key of the filter hash map so that it can identify the right filter
expression in the BPF program.

As the event can be inherited to child tasks, it should use the primary
id which belongs to the parent (original) event.  Since evsel opens the
event for multiple CPUs and tasks, it needs to maintain a separate hash
map for the event id.

In the user space, it keeps a list for the multiple evsel and release
the entries in the both hash map when it closes the event.
Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: KP Singh <kpsingh@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Song Liu <song@kernel.org>
Link: https://lore.kernel.org/r/20240820154504.128923-1-namhyung@kernel.orgSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 4f3affe0
This diff is collapsed.
#ifndef PERF_UTIL_BPF_SKEL_SAMPLE_FILTER_H
#define PERF_UTIL_BPF_SKEL_SAMPLE_FILTER_H
#define MAX_FILTERS 64
#define MAX_PIDS (16 * 1024)
#define MAX_FILTERS 64
#define MAX_IDX_HASH (16 * 1024)
#define MAX_EVT_HASH (1024 * 1024)
/* supported filter operations */
enum perf_bpf_filter_op {
......@@ -62,4 +63,10 @@ struct perf_bpf_filter_entry {
__u64 value;
};
struct idx_hash_key {
__u64 evt_id;
__u32 tgid;
__u32 reserved;
};
#endif /* PERF_UTIL_BPF_SKEL_SAMPLE_FILTER_H */
......@@ -15,13 +15,25 @@ struct filters {
__uint(max_entries, 1);
} filters SEC(".maps");
/* tgid to filter index */
struct pid_hash {
/*
* An evsel has multiple instances for each CPU or task but we need a single
* id to be used as a key for the idx_hash. This hashmap would translate the
* instance's ID to a representative ID.
*/
struct event_hash {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, int);
__type(key, __u64);
__type(value, __u64);
__uint(max_entries, 1);
} event_hash SEC(".maps");
/* tgid/evtid to filter index */
struct idx_hash {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, struct idx_hash_key);
__type(value, int);
__uint(max_entries, 1);
} pid_hash SEC(".maps");
} idx_hash SEC(".maps");
/* tgid to filter index */
struct lost_count {
......@@ -31,7 +43,7 @@ struct lost_count {
__uint(max_entries, 1);
} dropped SEC(".maps");
volatile const int use_pid_hash;
volatile const int use_idx_hash;
void *bpf_cast_to_kern_ctx(void *) __ksym;
......@@ -202,11 +214,25 @@ int perf_sample_filter(void *ctx)
k = 0;
if (use_pid_hash) {
int tgid = bpf_get_current_pid_tgid() >> 32;
if (use_idx_hash) {
struct idx_hash_key key = {
.tgid = bpf_get_current_pid_tgid() >> 32,
};
__u64 eid = kctx->event->id;
__u64 *key_id;
int *idx;
idx = bpf_map_lookup_elem(&pid_hash, &tgid);
/* get primary_event_id */
if (kctx->event->parent)
eid = kctx->event->parent->id;
key_id = bpf_map_lookup_elem(&event_hash, &eid);
if (key_id == NULL)
goto drop;
key.evt_id = *key_id;
idx = bpf_map_lookup_elem(&idx_hash, &key);
if (idx)
k = *idx;
else
......
......@@ -175,6 +175,11 @@ struct perf_sample_data {
u64 code_page_size;
} __attribute__((__aligned__(64))) __attribute__((preserve_access_index));
struct perf_event {
struct perf_event *parent;
u64 id;
} __attribute__((preserve_access_index));
struct bpf_perf_event_data_kern {
struct perf_sample_data *data;
struct perf_event *event;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment