perf stat: Support old kernels for bperf cgroup counting
authorNamhyung Kim <namhyung@kernel.org>
Tue, 11 Oct 2022 05:28:08 +0000 (22:28 -0700)
committerTejun Heo <tj@kernel.org>
Tue, 11 Oct 2022 16:53:12 +0000 (06:53 -1000)
The recent change in the cgroup will break the backward compatiblity in
the BPF program.  It should support both old and new kernels using BPF
CO-RE technique.

Like the task_struct->__state handling in the offcpu analysis, we can
check the field name in the cgroup struct.

Acked-by: Jiri Olsa <jolsa@kernel.org>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Tejun Heo <tj@kernel.org>
tools/perf/util/bpf_skel/bperf_cgroup.bpf.c

index 435a875..6a438e0 100644 (file)
@@ -43,6 +43,18 @@ struct {
        __uint(value_size, sizeof(struct bpf_perf_event_value));
 } cgrp_readings SEC(".maps");
 
+/* new kernel cgroup definition */
+struct cgroup___new {
+       int level;
+       struct cgroup *ancestors[];
+} __attribute__((preserve_access_index));
+
+/* old kernel cgroup definition */
+struct cgroup___old {
+       int level;
+       u64 ancestor_ids[];
+} __attribute__((preserve_access_index));
+
 const volatile __u32 num_events = 1;
 const volatile __u32 num_cpus = 1;
 
@@ -50,6 +62,21 @@ int enabled = 0;
 int use_cgroup_v2 = 0;
 int perf_subsys_id = -1;
 
+static inline __u64 get_cgroup_v1_ancestor_id(struct cgroup *cgrp, int level)
+{
+       /* recast pointer to capture new type for compiler */
+       struct cgroup___new *cgrp_new = (void *)cgrp;
+
+       if (bpf_core_field_exists(cgrp_new->ancestors)) {
+               return BPF_CORE_READ(cgrp_new, ancestors[level], kn, id);
+       } else {
+               /* recast pointer to capture old type for compiler */
+               struct cgroup___old *cgrp_old = (void *)cgrp;
+
+               return BPF_CORE_READ(cgrp_old, ancestor_ids[level]);
+       }
+}
+
 static inline int get_cgroup_v1_idx(__u32 *cgrps, int size)
 {
        struct task_struct *p = (void *)bpf_get_current_task();
@@ -77,7 +104,7 @@ static inline int get_cgroup_v1_idx(__u32 *cgrps, int size)
                        break;
 
                // convert cgroup-id to a map index
-               cgrp_id = BPF_CORE_READ(cgrp, ancestors[i], kn, id);
+               cgrp_id = get_cgroup_v1_ancestor_id(cgrp, i);
                elem = bpf_map_lookup_elem(&cgrp_idx, &cgrp_id);
                if (!elem)
                        continue;