* [PATCH v2 0/4] perf lock contention: Symbolize locks using slab cache names
@ 2024-11-08 6:14 Namhyung Kim
2024-11-08 6:14 ` [PATCH v2 1/4] perf lock contention: Add and use LCB_F_TYPE_MASK Namhyung Kim
` (4 more replies)
0 siblings, 5 replies; 19+ messages in thread
From: Namhyung Kim @ 2024-11-08 6:14 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo, Ian Rogers, Kan Liang
Cc: Jiri Olsa, Adrian Hunter, Peter Zijlstra, Ingo Molnar, LKML,
linux-perf-users, Andrii Nakryiko, Song Liu, bpf,
Stephane Eranian, Vlastimil Babka, Roman Gushchin, Hyeonggon Yoo,
Kees Cook
Hello,
This is to support symbolization of dynamic locks using slab
allocator's metadata. The kernel support is in the bpf-next tree now.
It provides the new "kmem_cache" BPF iterator and "bpf_get_kmem_cache"
kfunc to get the information from an address. The feature detection is
done using BTF type info and it won't have any effect on old kernels.
v2 changes)
* don't use libbpf_get_error() (Andrii)
v1) https://lore.kernel.org/linux-perf-users/20241105172635.2463800-1-namhyung@kernel.org
With this change, it can show locks in a slab object like below. I
added "&" sign to distinguish them from global locks.
# perf lock con -abl sleep 1
contended total wait max wait avg wait address symbol
2 1.95 us 1.77 us 975 ns ffff9d5e852d3498 &task_struct (mutex)
1 1.18 us 1.18 us 1.18 us ffff9d5e852d3538 &task_struct (mutex)
4 1.12 us 354 ns 279 ns ffff9d5e841ca800 &kmalloc-cg-512 (mutex)
2 859 ns 617 ns 429 ns ffffffffa41c3620 delayed_uprobe_lock (mutex)
3 691 ns 388 ns 230 ns ffffffffa41c0940 pack_mutex (mutex)
3 421 ns 164 ns 140 ns ffffffffa3a8b3a0 text_mutex (mutex)
1 409 ns 409 ns 409 ns ffffffffa41b4cf8 tracepoint_srcu_srcu_usage (mutex)
2 362 ns 239 ns 181 ns ffffffffa41cf840 pcpu_alloc_mutex (mutex)
1 220 ns 220 ns 220 ns ffff9d5e82b534d8 &signal_cache (mutex)
1 215 ns 215 ns 215 ns ffffffffa41b4c28 tracepoint_srcu_srcu_usage (mutex)
The first two were from "task_struct" slab cache. It happened to
match with the type name of object but there's no guarantee. We need
to add type info to slab cache to resolve the lock inside the object.
Anyway, the third one has no dedicated slab cache and was allocated by
kmalloc.
Those slab objects can be used to filter specific locks using -L or
--lock-filter option. (It needs quotes to avoid special handling in
the shell).
# perf lock con -ab -L '&task_struct' sleep 1
contended total wait max wait avg wait type caller
1 25.10 us 25.10 us 25.10 us mutex perf_event_exit_task+0x39
1 21.60 us 21.60 us 21.60 us mutex futex_exit_release+0x21
1 5.56 us 5.56 us 5.56 us mutex futex_exec_release+0x21
The code is available at 'perf/lock-slab-v2' branch in my tree
git://git.kernel.org/pub/scm/linux/kernel/git/namhyung/linux-perf.git
Thanks,
Namhyung
Namhyung Kim (4):
perf lock contention: Add and use LCB_F_TYPE_MASK
perf lock contention: Run BPF slab cache iterator
perf lock contention: Resolve slab object name using BPF
perf lock contention: Handle slab objects in -L/--lock-filter option
tools/perf/builtin-lock.c | 39 ++++-
tools/perf/util/bpf_lock_contention.c | 140 +++++++++++++++++-
.../perf/util/bpf_skel/lock_contention.bpf.c | 70 ++++++++-
tools/perf/util/bpf_skel/lock_data.h | 15 +-
tools/perf/util/bpf_skel/vmlinux/vmlinux.h | 8 +
tools/perf/util/lock-contention.h | 2 +
6 files changed, 267 insertions(+), 7 deletions(-)
--
2.47.0.277.g8800431eea-goog
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v2 1/4] perf lock contention: Add and use LCB_F_TYPE_MASK
2024-11-08 6:14 [PATCH v2 0/4] perf lock contention: Symbolize locks using slab cache names Namhyung Kim
@ 2024-11-08 6:14 ` Namhyung Kim
2024-11-08 6:14 ` [PATCH v2 2/4] perf lock contention: Run BPF slab cache iterator Namhyung Kim
` (3 subsequent siblings)
4 siblings, 0 replies; 19+ messages in thread
From: Namhyung Kim @ 2024-11-08 6:14 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo, Ian Rogers, Kan Liang
Cc: Jiri Olsa, Adrian Hunter, Peter Zijlstra, Ingo Molnar, LKML,
linux-perf-users, Andrii Nakryiko, Song Liu, bpf,
Stephane Eranian, Vlastimil Babka, Roman Gushchin, Hyeonggon Yoo,
Kees Cook
This is a preparation for the later change. It'll use more bits in the
flags so let's rename the type part and use the mask to extract the
type.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/builtin-lock.c | 4 ++--
tools/perf/util/bpf_skel/lock_data.h | 3 ++-
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 062e2b56a2ab570e..89ee2a2f78603906 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -1597,7 +1597,7 @@ static const struct {
static const char *get_type_str(unsigned int flags)
{
- flags &= LCB_F_MAX_FLAGS - 1;
+ flags &= LCB_F_TYPE_MASK;
for (unsigned int i = 0; i < ARRAY_SIZE(lock_type_table); i++) {
if (lock_type_table[i].flags == flags)
@@ -1608,7 +1608,7 @@ static const char *get_type_str(unsigned int flags)
static const char *get_type_name(unsigned int flags)
{
- flags &= LCB_F_MAX_FLAGS - 1;
+ flags &= LCB_F_TYPE_MASK;
for (unsigned int i = 0; i < ARRAY_SIZE(lock_type_table); i++) {
if (lock_type_table[i].flags == flags)
diff --git a/tools/perf/util/bpf_skel/lock_data.h b/tools/perf/util/bpf_skel/lock_data.h
index de12892f992f8d43..4f0aae5483745dfa 100644
--- a/tools/perf/util/bpf_skel/lock_data.h
+++ b/tools/perf/util/bpf_skel/lock_data.h
@@ -32,7 +32,8 @@ struct contention_task_data {
#define LCD_F_MMAP_LOCK (1U << 31)
#define LCD_F_SIGHAND_LOCK (1U << 30)
-#define LCB_F_MAX_FLAGS (1U << 7)
+#define LCB_F_TYPE_MAX (1U << 7)
+#define LCB_F_TYPE_MASK 0x0000007FU
struct contention_data {
u64 total_time;
--
2.47.0.277.g8800431eea-goog
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 2/4] perf lock contention: Run BPF slab cache iterator
2024-11-08 6:14 [PATCH v2 0/4] perf lock contention: Symbolize locks using slab cache names Namhyung Kim
2024-11-08 6:14 ` [PATCH v2 1/4] perf lock contention: Add and use LCB_F_TYPE_MASK Namhyung Kim
@ 2024-11-08 6:14 ` Namhyung Kim
2024-12-09 16:36 ` Arnaldo Carvalho de Melo
2024-11-08 6:14 ` [PATCH v2 3/4] perf lock contention: Resolve slab object name using BPF Namhyung Kim
` (2 subsequent siblings)
4 siblings, 1 reply; 19+ messages in thread
From: Namhyung Kim @ 2024-11-08 6:14 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo, Ian Rogers, Kan Liang
Cc: Jiri Olsa, Adrian Hunter, Peter Zijlstra, Ingo Molnar, LKML,
linux-perf-users, Andrii Nakryiko, Song Liu, bpf,
Stephane Eranian, Vlastimil Babka, Roman Gushchin, Hyeonggon Yoo,
Kees Cook
Recently the kernel got the kmem_cache iterator to traverse metadata of
slab objects. This can be used to symbolize dynamic locks in a slab.
The new slab_caches hash map will have the pointer of the kmem_cache as
a key and save the name and a id. The id will be saved in the flags
part of the lock.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/util/bpf_lock_contention.c | 50 +++++++++++++++++++
.../perf/util/bpf_skel/lock_contention.bpf.c | 28 +++++++++++
tools/perf/util/bpf_skel/lock_data.h | 12 +++++
tools/perf/util/bpf_skel/vmlinux/vmlinux.h | 8 +++
4 files changed, 98 insertions(+)
diff --git a/tools/perf/util/bpf_lock_contention.c b/tools/perf/util/bpf_lock_contention.c
index 41a1ad08789511c3..558590c3111390fc 100644
--- a/tools/perf/util/bpf_lock_contention.c
+++ b/tools/perf/util/bpf_lock_contention.c
@@ -12,12 +12,59 @@
#include <linux/zalloc.h>
#include <linux/string.h>
#include <bpf/bpf.h>
+#include <bpf/btf.h>
#include <inttypes.h>
#include "bpf_skel/lock_contention.skel.h"
#include "bpf_skel/lock_data.h"
static struct lock_contention_bpf *skel;
+static bool has_slab_iter;
+
+static void check_slab_cache_iter(struct lock_contention *con)
+{
+ struct btf *btf = btf__load_vmlinux_btf();
+ s32 ret;
+
+ if (btf == NULL) {
+ pr_debug("BTF loading failed: %s\n", strerror(errno));
+ return;
+ }
+
+ ret = btf__find_by_name_kind(btf, "bpf_iter__kmem_cache", BTF_KIND_STRUCT);
+ if (ret < 0) {
+ bpf_program__set_autoload(skel->progs.slab_cache_iter, false);
+ pr_debug("slab cache iterator is not available: %d\n", ret);
+ goto out;
+ }
+
+ has_slab_iter = true;
+
+ bpf_map__set_max_entries(skel->maps.slab_caches, con->map_nr_entries);
+out:
+ btf__free(btf);
+}
+
+static void run_slab_cache_iter(void)
+{
+ int fd;
+ char buf[256];
+
+ if (!has_slab_iter)
+ return;
+
+ fd = bpf_iter_create(bpf_link__fd(skel->links.slab_cache_iter));
+ if (fd < 0) {
+ pr_debug("cannot create slab cache iter: %d\n", fd);
+ return;
+ }
+
+ /* This will run the bpf program */
+ while (read(fd, buf, sizeof(buf)) > 0)
+ continue;
+
+ close(fd);
+}
int lock_contention_prepare(struct lock_contention *con)
{
@@ -109,6 +156,8 @@ int lock_contention_prepare(struct lock_contention *con)
skel->rodata->use_cgroup_v2 = 1;
}
+ check_slab_cache_iter(con);
+
if (lock_contention_bpf__load(skel) < 0) {
pr_err("Failed to load lock-contention BPF skeleton\n");
return -1;
@@ -304,6 +353,7 @@ static void account_end_timestamp(struct lock_contention *con)
int lock_contention_start(void)
{
+ run_slab_cache_iter();
skel->bss->enabled = 1;
return 0;
}
diff --git a/tools/perf/util/bpf_skel/lock_contention.bpf.c b/tools/perf/util/bpf_skel/lock_contention.bpf.c
index 1069bda5d733887f..fd24ccb00faec0ba 100644
--- a/tools/perf/util/bpf_skel/lock_contention.bpf.c
+++ b/tools/perf/util/bpf_skel/lock_contention.bpf.c
@@ -100,6 +100,13 @@ struct {
__uint(max_entries, 1);
} cgroup_filter SEC(".maps");
+struct {
+ __uint(type, BPF_MAP_TYPE_HASH);
+ __uint(key_size, sizeof(long));
+ __uint(value_size, sizeof(struct slab_cache_data));
+ __uint(max_entries, 1);
+} slab_caches SEC(".maps");
+
struct rw_semaphore___old {
struct task_struct *owner;
} __attribute__((preserve_access_index));
@@ -136,6 +143,8 @@ int perf_subsys_id = -1;
__u64 end_ts;
+__u32 slab_cache_id;
+
/* error stat */
int task_fail;
int stack_fail;
@@ -563,4 +572,23 @@ int BPF_PROG(end_timestamp)
return 0;
}
+SEC("iter/kmem_cache")
+int slab_cache_iter(struct bpf_iter__kmem_cache *ctx)
+{
+ struct kmem_cache *s = ctx->s;
+ struct slab_cache_data d;
+
+ if (s == NULL)
+ return 0;
+
+ d.id = ++slab_cache_id << LCB_F_SLAB_ID_SHIFT;
+ bpf_probe_read_kernel_str(d.name, sizeof(d.name), s->name);
+
+ if (d.id >= LCB_F_SLAB_ID_END)
+ return 0;
+
+ bpf_map_update_elem(&slab_caches, &s, &d, BPF_NOEXIST);
+ return 0;
+}
+
char LICENSE[] SEC("license") = "Dual BSD/GPL";
diff --git a/tools/perf/util/bpf_skel/lock_data.h b/tools/perf/util/bpf_skel/lock_data.h
index 4f0aae5483745dfa..c15f734d7fc4aecb 100644
--- a/tools/perf/util/bpf_skel/lock_data.h
+++ b/tools/perf/util/bpf_skel/lock_data.h
@@ -32,9 +32,16 @@ struct contention_task_data {
#define LCD_F_MMAP_LOCK (1U << 31)
#define LCD_F_SIGHAND_LOCK (1U << 30)
+#define LCB_F_SLAB_ID_SHIFT 16
+#define LCB_F_SLAB_ID_START (1U << 16)
+#define LCB_F_SLAB_ID_END (1U << 26)
+#define LCB_F_SLAB_ID_MASK 0x03FF0000U
+
#define LCB_F_TYPE_MAX (1U << 7)
#define LCB_F_TYPE_MASK 0x0000007FU
+#define SLAB_NAME_MAX 28
+
struct contention_data {
u64 total_time;
u64 min_time;
@@ -55,4 +62,9 @@ enum lock_class_sym {
LOCK_CLASS_RQLOCK,
};
+struct slab_cache_data {
+ u32 id;
+ char name[SLAB_NAME_MAX];
+};
+
#endif /* UTIL_BPF_SKEL_LOCK_DATA_H */
diff --git a/tools/perf/util/bpf_skel/vmlinux/vmlinux.h b/tools/perf/util/bpf_skel/vmlinux/vmlinux.h
index 4dcad7b682bdee9c..7b81d3173917fdb5 100644
--- a/tools/perf/util/bpf_skel/vmlinux/vmlinux.h
+++ b/tools/perf/util/bpf_skel/vmlinux/vmlinux.h
@@ -195,4 +195,12 @@ struct bpf_perf_event_data_kern {
*/
struct rq {};
+struct kmem_cache {
+ const char *name;
+} __attribute__((preserve_access_index));
+
+struct bpf_iter__kmem_cache {
+ struct kmem_cache *s;
+} __attribute__((preserve_access_index));
+
#endif // __VMLINUX_H
--
2.47.0.277.g8800431eea-goog
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 3/4] perf lock contention: Resolve slab object name using BPF
2024-11-08 6:14 [PATCH v2 0/4] perf lock contention: Symbolize locks using slab cache names Namhyung Kim
2024-11-08 6:14 ` [PATCH v2 1/4] perf lock contention: Add and use LCB_F_TYPE_MASK Namhyung Kim
2024-11-08 6:14 ` [PATCH v2 2/4] perf lock contention: Run BPF slab cache iterator Namhyung Kim
@ 2024-11-08 6:14 ` Namhyung Kim
2024-11-12 11:09 ` Vlastimil Babka
2024-11-08 6:14 ` [PATCH v2 4/4] perf lock contention: Handle slab objects in -L/--lock-filter option Namhyung Kim
2024-11-11 19:46 ` [PATCH v2 0/4] perf lock contention: Symbolize locks using slab cache names Ian Rogers
4 siblings, 1 reply; 19+ messages in thread
From: Namhyung Kim @ 2024-11-08 6:14 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo, Ian Rogers, Kan Liang
Cc: Jiri Olsa, Adrian Hunter, Peter Zijlstra, Ingo Molnar, LKML,
linux-perf-users, Andrii Nakryiko, Song Liu, bpf,
Stephane Eranian, Vlastimil Babka, Roman Gushchin, Hyeonggon Yoo,
Kees Cook
The bpf_get_kmem_cache() kfunc can return an address of the slab cache
(kmem_cache). As it has the name of the slab cache from the iterator,
we can use it to symbolize some dynamic kernel locks in a slab.
Before:
root@virtme-ng:/home/namhyung/project/linux# tools/perf/perf lock con -abl sleep 1
contended total wait max wait avg wait address symbol
2 3.34 us 2.87 us 1.67 us ffff9d7800ad9600 (mutex)
2 2.16 us 1.93 us 1.08 us ffff9d7804b992d8 (mutex)
4 1.37 us 517 ns 343 ns ffff9d78036e6e00 (mutex)
1 1.27 us 1.27 us 1.27 us ffff9d7804b99378 (mutex)
2 845 ns 599 ns 422 ns ffffffff9e1c3620 delayed_uprobe_lock (mutex)
1 845 ns 845 ns 845 ns ffffffff9da0b280 jiffies_lock (spinlock)
2 377 ns 259 ns 188 ns ffffffff9e1cf840 pcpu_alloc_mutex (mutex)
1 305 ns 305 ns 305 ns ffffffff9e1b4cf8 tracepoint_srcu_srcu_usage (mutex)
1 295 ns 295 ns 295 ns ffffffff9e1c0940 pack_mutex (mutex)
1 232 ns 232 ns 232 ns ffff9d7804b7d8d8 (mutex)
1 180 ns 180 ns 180 ns ffffffff9e1b4c28 tracepoint_srcu_srcu_usage (mutex)
1 165 ns 165 ns 165 ns ffffffff9da8b3a0 text_mutex (mutex)
After:
root@virtme-ng:/home/namhyung/project/linux# tools/perf/perf lock con -abl sleep 1
contended total wait max wait avg wait address symbol
2 1.95 us 1.77 us 975 ns ffff9d5e852d3498 &task_struct (mutex)
1 1.18 us 1.18 us 1.18 us ffff9d5e852d3538 &task_struct (mutex)
4 1.12 us 354 ns 279 ns ffff9d5e841ca800 &kmalloc-cg-512 (mutex)
2 859 ns 617 ns 429 ns ffffffffa41c3620 delayed_uprobe_lock (mutex)
3 691 ns 388 ns 230 ns ffffffffa41c0940 pack_mutex (mutex)
3 421 ns 164 ns 140 ns ffffffffa3a8b3a0 text_mutex (mutex)
1 409 ns 409 ns 409 ns ffffffffa41b4cf8 tracepoint_srcu_srcu_usage (mutex)
2 362 ns 239 ns 181 ns ffffffffa41cf840 pcpu_alloc_mutex (mutex)
1 220 ns 220 ns 220 ns ffff9d5e82b534d8 &signal_cache (mutex)
1 215 ns 215 ns 215 ns ffffffffa41b4c28 tracepoint_srcu_srcu_usage (mutex)
Note that the name starts with '&' sign for slab objects to inform they
are dynamic locks. It won't give the accurate lock or type names but
it's still useful. We may add type info to the slab cache later to get
the exact name of the lock in the type later.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/util/bpf_lock_contention.c | 52 +++++++++++++++++++
.../perf/util/bpf_skel/lock_contention.bpf.c | 21 +++++++-
2 files changed, 71 insertions(+), 2 deletions(-)
diff --git a/tools/perf/util/bpf_lock_contention.c b/tools/perf/util/bpf_lock_contention.c
index 558590c3111390fc..3f127fc6b95f8326 100644
--- a/tools/perf/util/bpf_lock_contention.c
+++ b/tools/perf/util/bpf_lock_contention.c
@@ -2,6 +2,7 @@
#include "util/cgroup.h"
#include "util/debug.h"
#include "util/evlist.h"
+#include "util/hashmap.h"
#include "util/machine.h"
#include "util/map.h"
#include "util/symbol.h"
@@ -20,12 +21,25 @@
static struct lock_contention_bpf *skel;
static bool has_slab_iter;
+static struct hashmap slab_hash;
+
+static size_t slab_cache_hash(long key, void *ctx __maybe_unused)
+{
+ return key;
+}
+
+static bool slab_cache_equal(long key1, long key2, void *ctx __maybe_unused)
+{
+ return key1 == key2;
+}
static void check_slab_cache_iter(struct lock_contention *con)
{
struct btf *btf = btf__load_vmlinux_btf();
s32 ret;
+ hashmap__init(&slab_hash, slab_cache_hash, slab_cache_equal, /*ctx=*/NULL);
+
if (btf == NULL) {
pr_debug("BTF loading failed: %s\n", strerror(errno));
return;
@@ -49,6 +63,7 @@ static void run_slab_cache_iter(void)
{
int fd;
char buf[256];
+ long key, *prev_key;
if (!has_slab_iter)
return;
@@ -64,6 +79,34 @@ static void run_slab_cache_iter(void)
continue;
close(fd);
+
+ /* Read the slab cache map and build a hash with IDs */
+ fd = bpf_map__fd(skel->maps.slab_caches);
+ prev_key = NULL;
+ while (!bpf_map_get_next_key(fd, prev_key, &key)) {
+ struct slab_cache_data *data;
+
+ data = malloc(sizeof(*data));
+ if (data == NULL)
+ break;
+
+ if (bpf_map_lookup_elem(fd, &key, data) < 0)
+ break;
+
+ hashmap__add(&slab_hash, data->id, data);
+ prev_key = &key;
+ }
+}
+
+static void exit_slab_cache_iter(void)
+{
+ struct hashmap_entry *cur;
+ unsigned bkt;
+
+ hashmap__for_each_entry(&slab_hash, cur, bkt)
+ free(cur->pvalue);
+
+ hashmap__clear(&slab_hash);
}
int lock_contention_prepare(struct lock_contention *con)
@@ -397,6 +440,7 @@ static const char *lock_contention_get_name(struct lock_contention *con,
if (con->aggr_mode == LOCK_AGGR_ADDR) {
int lock_fd = bpf_map__fd(skel->maps.lock_syms);
+ struct slab_cache_data *slab_data;
/* per-process locks set upper bits of the flags */
if (flags & LCD_F_MMAP_LOCK)
@@ -415,6 +459,12 @@ static const char *lock_contention_get_name(struct lock_contention *con,
return "rq_lock";
}
+ /* look slab_hash for dynamic locks in a slab object */
+ if (hashmap__find(&slab_hash, flags & LCB_F_SLAB_ID_MASK, &slab_data)) {
+ snprintf(name_buf, sizeof(name_buf), "&%s", slab_data->name);
+ return name_buf;
+ }
+
return "";
}
@@ -589,5 +639,7 @@ int lock_contention_finish(struct lock_contention *con)
cgroup__put(cgrp);
}
+ exit_slab_cache_iter();
+
return 0;
}
diff --git a/tools/perf/util/bpf_skel/lock_contention.bpf.c b/tools/perf/util/bpf_skel/lock_contention.bpf.c
index fd24ccb00faec0ba..b5bc37955560a58e 100644
--- a/tools/perf/util/bpf_skel/lock_contention.bpf.c
+++ b/tools/perf/util/bpf_skel/lock_contention.bpf.c
@@ -123,6 +123,8 @@ struct mm_struct___new {
struct rw_semaphore mmap_lock;
} __attribute__((preserve_access_index));
+extern struct kmem_cache *bpf_get_kmem_cache(u64 addr) __ksym __weak;
+
/* control flags */
const volatile int has_cpu;
const volatile int has_task;
@@ -496,8 +498,23 @@ int contention_end(u64 *ctx)
};
int err;
- if (aggr_mode == LOCK_AGGR_ADDR)
- first.flags |= check_lock_type(pelem->lock, pelem->flags);
+ if (aggr_mode == LOCK_AGGR_ADDR) {
+ first.flags |= check_lock_type(pelem->lock,
+ pelem->flags & LCB_F_TYPE_MASK);
+
+ /* Check if it's from a slab object */
+ if (bpf_get_kmem_cache) {
+ struct kmem_cache *s;
+ struct slab_cache_data *d;
+
+ s = bpf_get_kmem_cache(pelem->lock);
+ if (s != NULL) {
+ d = bpf_map_lookup_elem(&slab_caches, &s);
+ if (d != NULL)
+ first.flags |= d->id;
+ }
+ }
+ }
err = bpf_map_update_elem(&lock_stat, &key, &first, BPF_NOEXIST);
if (err < 0) {
--
2.47.0.277.g8800431eea-goog
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 4/4] perf lock contention: Handle slab objects in -L/--lock-filter option
2024-11-08 6:14 [PATCH v2 0/4] perf lock contention: Symbolize locks using slab cache names Namhyung Kim
` (2 preceding siblings ...)
2024-11-08 6:14 ` [PATCH v2 3/4] perf lock contention: Resolve slab object name using BPF Namhyung Kim
@ 2024-11-08 6:14 ` Namhyung Kim
2024-11-11 19:46 ` [PATCH v2 0/4] perf lock contention: Symbolize locks using slab cache names Ian Rogers
4 siblings, 0 replies; 19+ messages in thread
From: Namhyung Kim @ 2024-11-08 6:14 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo, Ian Rogers, Kan Liang
Cc: Jiri Olsa, Adrian Hunter, Peter Zijlstra, Ingo Molnar, LKML,
linux-perf-users, Andrii Nakryiko, Song Liu, bpf,
Stephane Eranian, Vlastimil Babka, Roman Gushchin, Hyeonggon Yoo,
Kees Cook
This is to filter lock contention from specific slab objects only.
Like in the lock symbol output, we can use '&' prefix to filter slab
object names.
root@virtme-ng:/home/namhyung/project/linux# tools/perf/perf lock con -abl sleep 1
contended total wait max wait avg wait address symbol
3 14.99 us 14.44 us 5.00 us ffffffff851c0940 pack_mutex (mutex)
2 2.75 us 2.56 us 1.38 us ffff98d7031fb498 &task_struct (mutex)
4 1.42 us 557 ns 355 ns ffff98d706311400 &kmalloc-cg-512 (mutex)
2 953 ns 714 ns 476 ns ffffffff851c3620 delayed_uprobe_lock (mutex)
1 929 ns 929 ns 929 ns ffff98d7031fb538 &task_struct (mutex)
3 561 ns 210 ns 187 ns ffffffff84a8b3a0 text_mutex (mutex)
1 479 ns 479 ns 479 ns ffffffff851b4cf8 tracepoint_srcu_srcu_usage (mutex)
2 320 ns 195 ns 160 ns ffffffff851cf840 pcpu_alloc_mutex (mutex)
1 212 ns 212 ns 212 ns ffff98d7031784d8 &signal_cache (mutex)
1 177 ns 177 ns 177 ns ffffffff851b4c28 tracepoint_srcu_srcu_usage (mutex)
With the filter, it can show contentions from the task_struct only.
root@virtme-ng:/home/namhyung/project/linux# tools/perf/perf lock con -abl -L '&task_struct' sleep 1
contended total wait max wait avg wait address symbol
2 1.97 us 1.71 us 987 ns ffff98d7032fd658 &task_struct (mutex)
1 1.20 us 1.20 us 1.20 us ffff98d7032fd6f8 &task_struct (mutex)
It can work with other aggregation mode:
root@virtme-ng:/home/namhyung/project/linux# tools/perf/perf lock con -ab -L '&task_struct' sleep 1
contended total wait max wait avg wait type caller
1 25.10 us 25.10 us 25.10 us mutex perf_event_exit_task+0x39
1 21.60 us 21.60 us 21.60 us mutex futex_exit_release+0x21
1 5.56 us 5.56 us 5.56 us mutex futex_exec_release+0x21
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/builtin-lock.c | 35 ++++++++++++++++
tools/perf/util/bpf_lock_contention.c | 40 ++++++++++++++++++-
.../perf/util/bpf_skel/lock_contention.bpf.c | 21 +++++++++-
tools/perf/util/lock-contention.h | 2 +
4 files changed, 95 insertions(+), 3 deletions(-)
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 89ee2a2f78603906..405e95666257b7fe 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -1646,6 +1646,12 @@ static void lock_filter_finish(void)
zfree(&filters.cgrps);
filters.nr_cgrps = 0;
+
+ for (int i = 0; i < filters.nr_slabs; i++)
+ free(filters.slabs[i]);
+
+ zfree(&filters.slabs);
+ filters.nr_slabs = 0;
}
static void sort_contention_result(void)
@@ -2412,6 +2418,27 @@ static bool add_lock_sym(char *name)
return true;
}
+static bool add_lock_slab(char *name)
+{
+ char **tmp;
+ char *sym = strdup(name);
+
+ if (sym == NULL) {
+ pr_err("Memory allocation failure\n");
+ return false;
+ }
+
+ tmp = realloc(filters.slabs, (filters.nr_slabs + 1) * sizeof(*filters.slabs));
+ if (tmp == NULL) {
+ pr_err("Memory allocation failure\n");
+ return false;
+ }
+
+ tmp[filters.nr_slabs++] = sym;
+ filters.slabs = tmp;
+ return true;
+}
+
static int parse_lock_addr(const struct option *opt __maybe_unused, const char *str,
int unset __maybe_unused)
{
@@ -2435,6 +2462,14 @@ static int parse_lock_addr(const struct option *opt __maybe_unused, const char *
continue;
}
+ if (*tok == '&') {
+ if (!add_lock_slab(tok + 1)) {
+ ret = -1;
+ break;
+ }
+ continue;
+ }
+
/*
* At this moment, we don't have kernel symbols. Save the symbols
* in a separate list and resolve them to addresses later.
diff --git a/tools/perf/util/bpf_lock_contention.c b/tools/perf/util/bpf_lock_contention.c
index 3f127fc6b95f8326..5ca1c7ffe4ce5073 100644
--- a/tools/perf/util/bpf_lock_contention.c
+++ b/tools/perf/util/bpf_lock_contention.c
@@ -112,7 +112,7 @@ static void exit_slab_cache_iter(void)
int lock_contention_prepare(struct lock_contention *con)
{
int i, fd;
- int ncpus = 1, ntasks = 1, ntypes = 1, naddrs = 1, ncgrps = 1;
+ int ncpus = 1, ntasks = 1, ntypes = 1, naddrs = 1, ncgrps = 1, nslabs = 1;
struct evlist *evlist = con->evlist;
struct target *target = con->target;
@@ -201,6 +201,13 @@ int lock_contention_prepare(struct lock_contention *con)
check_slab_cache_iter(con);
+ if (con->filters->nr_slabs && has_slab_iter) {
+ skel->rodata->has_slab = 1;
+ nslabs = con->filters->nr_slabs;
+ }
+
+ bpf_map__set_max_entries(skel->maps.slab_filter, nslabs);
+
if (lock_contention_bpf__load(skel) < 0) {
pr_err("Failed to load lock-contention BPF skeleton\n");
return -1;
@@ -271,6 +278,36 @@ int lock_contention_prepare(struct lock_contention *con)
bpf_program__set_autoload(skel->progs.collect_lock_syms, false);
lock_contention_bpf__attach(skel);
+
+ /* run the slab iterator after attaching */
+ run_slab_cache_iter();
+
+ if (con->filters->nr_slabs) {
+ u8 val = 1;
+ int cache_fd;
+ long key, *prev_key;
+
+ fd = bpf_map__fd(skel->maps.slab_filter);
+
+ /* Read the slab cache map and build a hash with its address */
+ cache_fd = bpf_map__fd(skel->maps.slab_caches);
+ prev_key = NULL;
+ while (!bpf_map_get_next_key(cache_fd, prev_key, &key)) {
+ struct slab_cache_data data;
+
+ if (bpf_map_lookup_elem(cache_fd, &key, &data) < 0)
+ break;
+
+ for (i = 0; i < con->filters->nr_slabs; i++) {
+ if (!strcmp(con->filters->slabs[i], data.name)) {
+ bpf_map_update_elem(fd, &key, &val, BPF_ANY);
+ break;
+ }
+ }
+ prev_key = &key;
+ }
+ }
+
return 0;
}
@@ -396,7 +433,6 @@ static void account_end_timestamp(struct lock_contention *con)
int lock_contention_start(void)
{
- run_slab_cache_iter();
skel->bss->enabled = 1;
return 0;
}
diff --git a/tools/perf/util/bpf_skel/lock_contention.bpf.c b/tools/perf/util/bpf_skel/lock_contention.bpf.c
index b5bc37955560a58e..048a04fc3a7fc27d 100644
--- a/tools/perf/util/bpf_skel/lock_contention.bpf.c
+++ b/tools/perf/util/bpf_skel/lock_contention.bpf.c
@@ -100,6 +100,13 @@ struct {
__uint(max_entries, 1);
} cgroup_filter SEC(".maps");
+struct {
+ __uint(type, BPF_MAP_TYPE_HASH);
+ __uint(key_size, sizeof(long));
+ __uint(value_size, sizeof(__u8));
+ __uint(max_entries, 1);
+} slab_filter SEC(".maps");
+
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(key_size, sizeof(long));
@@ -131,6 +138,7 @@ const volatile int has_task;
const volatile int has_type;
const volatile int has_addr;
const volatile int has_cgroup;
+const volatile int has_slab;
const volatile int needs_callstack;
const volatile int stack_skip;
const volatile int lock_owner;
@@ -213,7 +221,7 @@ static inline int can_record(u64 *ctx)
__u64 addr = ctx[0];
ok = bpf_map_lookup_elem(&addr_filter, &addr);
- if (!ok)
+ if (!ok && !has_slab)
return 0;
}
@@ -226,6 +234,17 @@ static inline int can_record(u64 *ctx)
return 0;
}
+ if (has_slab && bpf_get_kmem_cache) {
+ __u8 *ok;
+ __u64 addr = ctx[0];
+ long kmem_cache_addr;
+
+ kmem_cache_addr = (long)bpf_get_kmem_cache(addr);
+ ok = bpf_map_lookup_elem(&slab_filter, &kmem_cache_addr);
+ if (!ok)
+ return 0;
+ }
+
return 1;
}
diff --git a/tools/perf/util/lock-contention.h b/tools/perf/util/lock-contention.h
index 1a7248ff388947e1..95331b6ec062410d 100644
--- a/tools/perf/util/lock-contention.h
+++ b/tools/perf/util/lock-contention.h
@@ -10,10 +10,12 @@ struct lock_filter {
int nr_addrs;
int nr_syms;
int nr_cgrps;
+ int nr_slabs;
unsigned int *types;
unsigned long *addrs;
char **syms;
u64 *cgrps;
+ char **slabs;
};
struct lock_stat {
--
2.47.0.277.g8800431eea-goog
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH v2 0/4] perf lock contention: Symbolize locks using slab cache names
2024-11-08 6:14 [PATCH v2 0/4] perf lock contention: Symbolize locks using slab cache names Namhyung Kim
` (3 preceding siblings ...)
2024-11-08 6:14 ` [PATCH v2 4/4] perf lock contention: Handle slab objects in -L/--lock-filter option Namhyung Kim
@ 2024-11-11 19:46 ` Ian Rogers
2024-11-18 18:35 ` Namhyung Kim
4 siblings, 1 reply; 19+ messages in thread
From: Ian Rogers @ 2024-11-11 19:46 UTC (permalink / raw)
To: Namhyung Kim
Cc: Arnaldo Carvalho de Melo, Kan Liang, Jiri Olsa, Adrian Hunter,
Peter Zijlstra, Ingo Molnar, LKML, linux-perf-users,
Andrii Nakryiko, Song Liu, bpf, Stephane Eranian, Vlastimil Babka,
Roman Gushchin, Hyeonggon Yoo, Kees Cook
On Thu, Nov 7, 2024 at 10:15 PM Namhyung Kim <namhyung@kernel.org> wrote:
>
> Hello,
>
> This is to support symbolization of dynamic locks using slab
> allocator's metadata. The kernel support is in the bpf-next tree now.
>
> It provides the new "kmem_cache" BPF iterator and "bpf_get_kmem_cache"
> kfunc to get the information from an address. The feature detection is
> done using BTF type info and it won't have any effect on old kernels.
>
> v2 changes)
>
> * don't use libbpf_get_error() (Andrii)
>
> v1) https://lore.kernel.org/linux-perf-users/20241105172635.2463800-1-namhyung@kernel.org
>
> With this change, it can show locks in a slab object like below. I
> added "&" sign to distinguish them from global locks.
I know the & is intentional but I worry it could later complicate
parsing of filters. Perhaps @ is a viable alternative. Other than
that:
Acked-by: Ian Rogers <irogers@google.com>
Thanks,
Ian
> # perf lock con -abl sleep 1
> contended total wait max wait avg wait address symbol
>
> 2 1.95 us 1.77 us 975 ns ffff9d5e852d3498 &task_struct (mutex)
> 1 1.18 us 1.18 us 1.18 us ffff9d5e852d3538 &task_struct (mutex)
> 4 1.12 us 354 ns 279 ns ffff9d5e841ca800 &kmalloc-cg-512 (mutex)
> 2 859 ns 617 ns 429 ns ffffffffa41c3620 delayed_uprobe_lock (mutex)
> 3 691 ns 388 ns 230 ns ffffffffa41c0940 pack_mutex (mutex)
> 3 421 ns 164 ns 140 ns ffffffffa3a8b3a0 text_mutex (mutex)
> 1 409 ns 409 ns 409 ns ffffffffa41b4cf8 tracepoint_srcu_srcu_usage (mutex)
> 2 362 ns 239 ns 181 ns ffffffffa41cf840 pcpu_alloc_mutex (mutex)
> 1 220 ns 220 ns 220 ns ffff9d5e82b534d8 &signal_cache (mutex)
> 1 215 ns 215 ns 215 ns ffffffffa41b4c28 tracepoint_srcu_srcu_usage (mutex)
>
> The first two were from "task_struct" slab cache. It happened to
> match with the type name of object but there's no guarantee. We need
> to add type info to slab cache to resolve the lock inside the object.
> Anyway, the third one has no dedicated slab cache and was allocated by
> kmalloc.
>
> Those slab objects can be used to filter specific locks using -L or
> --lock-filter option. (It needs quotes to avoid special handling in
> the shell).
>
> # perf lock con -ab -L '&task_struct' sleep 1
> contended total wait max wait avg wait type caller
>
> 1 25.10 us 25.10 us 25.10 us mutex perf_event_exit_task+0x39
> 1 21.60 us 21.60 us 21.60 us mutex futex_exit_release+0x21
> 1 5.56 us 5.56 us 5.56 us mutex futex_exec_release+0x21
>
> The code is available at 'perf/lock-slab-v2' branch in my tree
>
> git://git.kernel.org/pub/scm/linux/kernel/git/namhyung/linux-perf.git
>
> Thanks,
> Namhyung
>
>
> Namhyung Kim (4):
> perf lock contention: Add and use LCB_F_TYPE_MASK
> perf lock contention: Run BPF slab cache iterator
> perf lock contention: Resolve slab object name using BPF
> perf lock contention: Handle slab objects in -L/--lock-filter option
>
> tools/perf/builtin-lock.c | 39 ++++-
> tools/perf/util/bpf_lock_contention.c | 140 +++++++++++++++++-
> .../perf/util/bpf_skel/lock_contention.bpf.c | 70 ++++++++-
> tools/perf/util/bpf_skel/lock_data.h | 15 +-
> tools/perf/util/bpf_skel/vmlinux/vmlinux.h | 8 +
> tools/perf/util/lock-contention.h | 2 +
> 6 files changed, 267 insertions(+), 7 deletions(-)
>
> --
> 2.47.0.277.g8800431eea-goog
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 3/4] perf lock contention: Resolve slab object name using BPF
2024-11-08 6:14 ` [PATCH v2 3/4] perf lock contention: Resolve slab object name using BPF Namhyung Kim
@ 2024-11-12 11:09 ` Vlastimil Babka
2024-11-12 14:50 ` Arnaldo Carvalho de Melo
0 siblings, 1 reply; 19+ messages in thread
From: Vlastimil Babka @ 2024-11-12 11:09 UTC (permalink / raw)
To: Namhyung Kim, Arnaldo Carvalho de Melo, Ian Rogers, Kan Liang
Cc: Jiri Olsa, Adrian Hunter, Peter Zijlstra, Ingo Molnar, LKML,
linux-perf-users, Andrii Nakryiko, Song Liu, bpf,
Stephane Eranian, Roman Gushchin, Hyeonggon Yoo, Kees Cook
On 11/8/24 07:14, Namhyung Kim wrote:
> The bpf_get_kmem_cache() kfunc can return an address of the slab cache
> (kmem_cache). As it has the name of the slab cache from the iterator,
> we can use it to symbolize some dynamic kernel locks in a slab.
>
> Before:
> root@virtme-ng:/home/namhyung/project/linux# tools/perf/perf lock con -abl sleep 1
> contended total wait max wait avg wait address symbol
>
> 2 3.34 us 2.87 us 1.67 us ffff9d7800ad9600 (mutex)
> 2 2.16 us 1.93 us 1.08 us ffff9d7804b992d8 (mutex)
> 4 1.37 us 517 ns 343 ns ffff9d78036e6e00 (mutex)
> 1 1.27 us 1.27 us 1.27 us ffff9d7804b99378 (mutex)
> 2 845 ns 599 ns 422 ns ffffffff9e1c3620 delayed_uprobe_lock (mutex)
> 1 845 ns 845 ns 845 ns ffffffff9da0b280 jiffies_lock (spinlock)
> 2 377 ns 259 ns 188 ns ffffffff9e1cf840 pcpu_alloc_mutex (mutex)
> 1 305 ns 305 ns 305 ns ffffffff9e1b4cf8 tracepoint_srcu_srcu_usage (mutex)
> 1 295 ns 295 ns 295 ns ffffffff9e1c0940 pack_mutex (mutex)
> 1 232 ns 232 ns 232 ns ffff9d7804b7d8d8 (mutex)
> 1 180 ns 180 ns 180 ns ffffffff9e1b4c28 tracepoint_srcu_srcu_usage (mutex)
> 1 165 ns 165 ns 165 ns ffffffff9da8b3a0 text_mutex (mutex)
>
> After:
> root@virtme-ng:/home/namhyung/project/linux# tools/perf/perf lock con -abl sleep 1
> contended total wait max wait avg wait address symbol
>
> 2 1.95 us 1.77 us 975 ns ffff9d5e852d3498 &task_struct (mutex)
> 1 1.18 us 1.18 us 1.18 us ffff9d5e852d3538 &task_struct (mutex)
> 4 1.12 us 354 ns 279 ns ffff9d5e841ca800 &kmalloc-cg-512 (mutex)
> 2 859 ns 617 ns 429 ns ffffffffa41c3620 delayed_uprobe_lock (mutex)
> 3 691 ns 388 ns 230 ns ffffffffa41c0940 pack_mutex (mutex)
> 3 421 ns 164 ns 140 ns ffffffffa3a8b3a0 text_mutex (mutex)
> 1 409 ns 409 ns 409 ns ffffffffa41b4cf8 tracepoint_srcu_srcu_usage (mutex)
> 2 362 ns 239 ns 181 ns ffffffffa41cf840 pcpu_alloc_mutex (mutex)
> 1 220 ns 220 ns 220 ns ffff9d5e82b534d8 &signal_cache (mutex)
> 1 215 ns 215 ns 215 ns ffffffffa41b4c28 tracepoint_srcu_srcu_usage (mutex)
>
> Note that the name starts with '&' sign for slab objects to inform they
> are dynamic locks. It won't give the accurate lock or type names but
> it's still useful. We may add type info to the slab cache later to get
> the exact name of the lock in the type later.
>
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
<snip>
> diff --git a/tools/perf/util/bpf_skel/lock_contention.bpf.c b/tools/perf/util/bpf_skel/lock_contention.bpf.c
> index fd24ccb00faec0ba..b5bc37955560a58e 100644
> --- a/tools/perf/util/bpf_skel/lock_contention.bpf.c
> +++ b/tools/perf/util/bpf_skel/lock_contention.bpf.c
> @@ -123,6 +123,8 @@ struct mm_struct___new {
> struct rw_semaphore mmap_lock;
> } __attribute__((preserve_access_index));
>
> +extern struct kmem_cache *bpf_get_kmem_cache(u64 addr) __ksym __weak;
> +
> /* control flags */
> const volatile int has_cpu;
> const volatile int has_task;
> @@ -496,8 +498,23 @@ int contention_end(u64 *ctx)
> };
> int err;
>
> - if (aggr_mode == LOCK_AGGR_ADDR)
> - first.flags |= check_lock_type(pelem->lock, pelem->flags);
> + if (aggr_mode == LOCK_AGGR_ADDR) {
> + first.flags |= check_lock_type(pelem->lock,
> + pelem->flags & LCB_F_TYPE_MASK);
> +
> + /* Check if it's from a slab object */
> + if (bpf_get_kmem_cache) {
> + struct kmem_cache *s;
> + struct slab_cache_data *d;
> +
> + s = bpf_get_kmem_cache(pelem->lock);
> + if (s != NULL) {
> + d = bpf_map_lookup_elem(&slab_caches, &s);
> + if (d != NULL)
> + first.flags |= d->id;
> + }
Is this being executed as part of obtaining a perf event record, or as part
of a postprocessing pass? I'm not familiar enough with the code to be certain.
- if it's part of perf event record, can you just store 's' and defer
resolving the cache by bpf_map_lookup_elem() to postprocessing?
- if it's postprocessing, it would be too late for bpf_get_kmem_cache() as
the object might be gone already?
The second alternative would be worse as it could miss the cache or
misattribute (in case page is reallocated by another cache), the first is
just less efficient than possible.
> + }
> + }
>
> err = bpf_map_update_elem(&lock_stat, &key, &first, BPF_NOEXIST);
> if (err < 0) {
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 3/4] perf lock contention: Resolve slab object name using BPF
2024-11-12 11:09 ` Vlastimil Babka
@ 2024-11-12 14:50 ` Arnaldo Carvalho de Melo
2024-11-13 14:20 ` Vlastimil Babka
0 siblings, 1 reply; 19+ messages in thread
From: Arnaldo Carvalho de Melo @ 2024-11-12 14:50 UTC (permalink / raw)
To: Vlastimil Babka
Cc: Namhyung Kim, Ian Rogers, Kan Liang, Jiri Olsa, Adrian Hunter,
Peter Zijlstra, Ingo Molnar, LKML, linux-perf-users,
Andrii Nakryiko, Song Liu, bpf, Stephane Eranian, Roman Gushchin,
Hyeonggon Yoo, Kees Cook
On Tue, Nov 12, 2024 at 12:09:24PM +0100, Vlastimil Babka wrote:
> On 11/8/24 07:14, Namhyung Kim wrote:
> > The bpf_get_kmem_cache() kfunc can return an address of the slab cache
> > (kmem_cache). As it has the name of the slab cache from the iterator,
> > we can use it to symbolize some dynamic kernel locks in a slab.
> >
> > Before:
> > root@virtme-ng:/home/namhyung/project/linux# tools/perf/perf lock con -abl sleep 1
> > contended total wait max wait avg wait address symbol
> >
> > 2 3.34 us 2.87 us 1.67 us ffff9d7800ad9600 (mutex)
> > 2 2.16 us 1.93 us 1.08 us ffff9d7804b992d8 (mutex)
> > 4 1.37 us 517 ns 343 ns ffff9d78036e6e00 (mutex)
> > 1 1.27 us 1.27 us 1.27 us ffff9d7804b99378 (mutex)
> > 2 845 ns 599 ns 422 ns ffffffff9e1c3620 delayed_uprobe_lock (mutex)
> > 1 845 ns 845 ns 845 ns ffffffff9da0b280 jiffies_lock (spinlock)
> > 2 377 ns 259 ns 188 ns ffffffff9e1cf840 pcpu_alloc_mutex (mutex)
> > 1 305 ns 305 ns 305 ns ffffffff9e1b4cf8 tracepoint_srcu_srcu_usage (mutex)
> > 1 295 ns 295 ns 295 ns ffffffff9e1c0940 pack_mutex (mutex)
> > 1 232 ns 232 ns 232 ns ffff9d7804b7d8d8 (mutex)
> > 1 180 ns 180 ns 180 ns ffffffff9e1b4c28 tracepoint_srcu_srcu_usage (mutex)
> > 1 165 ns 165 ns 165 ns ffffffff9da8b3a0 text_mutex (mutex)
> >
> > After:
> > root@virtme-ng:/home/namhyung/project/linux# tools/perf/perf lock con -abl sleep 1
> > contended total wait max wait avg wait address symbol
> >
> > 2 1.95 us 1.77 us 975 ns ffff9d5e852d3498 &task_struct (mutex)
> > 1 1.18 us 1.18 us 1.18 us ffff9d5e852d3538 &task_struct (mutex)
> > 4 1.12 us 354 ns 279 ns ffff9d5e841ca800 &kmalloc-cg-512 (mutex)
> > 2 859 ns 617 ns 429 ns ffffffffa41c3620 delayed_uprobe_lock (mutex)
> > 3 691 ns 388 ns 230 ns ffffffffa41c0940 pack_mutex (mutex)
> > 3 421 ns 164 ns 140 ns ffffffffa3a8b3a0 text_mutex (mutex)
> > 1 409 ns 409 ns 409 ns ffffffffa41b4cf8 tracepoint_srcu_srcu_usage (mutex)
> > 2 362 ns 239 ns 181 ns ffffffffa41cf840 pcpu_alloc_mutex (mutex)
> > 1 220 ns 220 ns 220 ns ffff9d5e82b534d8 &signal_cache (mutex)
> > 1 215 ns 215 ns 215 ns ffffffffa41b4c28 tracepoint_srcu_srcu_usage (mutex)
> >
> > Note that the name starts with '&' sign for slab objects to inform they
> > are dynamic locks. It won't give the accurate lock or type names but
> > it's still useful. We may add type info to the slab cache later to get
> > the exact name of the lock in the type later.
> >
> > Signed-off-by: Namhyung Kim <namhyung@kernel.org>
>
> <snip>
>
> > diff --git a/tools/perf/util/bpf_skel/lock_contention.bpf.c b/tools/perf/util/bpf_skel/lock_contention.bpf.c
> > index fd24ccb00faec0ba..b5bc37955560a58e 100644
> > --- a/tools/perf/util/bpf_skel/lock_contention.bpf.c
> > +++ b/tools/perf/util/bpf_skel/lock_contention.bpf.c
> > @@ -123,6 +123,8 @@ struct mm_struct___new {
> > struct rw_semaphore mmap_lock;
> > } __attribute__((preserve_access_index));
> >
> > +extern struct kmem_cache *bpf_get_kmem_cache(u64 addr) __ksym __weak;
> > +
> > /* control flags */
> > const volatile int has_cpu;
> > const volatile int has_task;
> > @@ -496,8 +498,23 @@ int contention_end(u64 *ctx)
> > };
> > int err;
> >
> > - if (aggr_mode == LOCK_AGGR_ADDR)
> > - first.flags |= check_lock_type(pelem->lock, pelem->flags);
> > + if (aggr_mode == LOCK_AGGR_ADDR) {
> > + first.flags |= check_lock_type(pelem->lock,
> > + pelem->flags & LCB_F_TYPE_MASK);
> > +
> > + /* Check if it's from a slab object */
> > + if (bpf_get_kmem_cache) {
> > + struct kmem_cache *s;
> > + struct slab_cache_data *d;
> > +
> > + s = bpf_get_kmem_cache(pelem->lock);
> > + if (s != NULL) {
> > + d = bpf_map_lookup_elem(&slab_caches, &s);
> > + if (d != NULL)
> > + first.flags |= d->id;
> > + }
>
> Is this being executed as part of obtaining a perf event record, or as part
> of a postprocessing pass? I'm not familiar enough with the code to be certain.
>
> - if it's part of perf event record, can you just store 's' and defer
> resolving the cache by bpf_map_lookup_elem() to postprocessing?
Namhyung is in vacation this week, so lemme try to help (and learn more
about this patchset since we discussed about it back in LSFMM :-)):
tldr;: He wants to store a 10 bit cookie for the slab cache, to avoid
storing 64 bits per contention record.
My reading of his code:
'first' is a 'struct contention_data' instance, that he will use for
post processing in tools/perf/builtin-lock.c, the relevant part:
if (use_bpf) {
lock_contention_start();
if (argc)
evlist__start_workload(con.evlist);
/* wait for signal */
pause();
lock_contention_stop();
lock_contention_read(&con);
} else
process records from a perf.data file with tons
of lock:lock_contention_{begin,end}, which the use_bpf
mode above "pre-processes" at begin+end pairs and
turns into 'struct contention_data' records in a BPF
map for later post processing in the common part after
this if/else block.
The post processing is in lock_contention_read(), that is in
tools/perf/util/bpf_lock_contention.c, I stripped out prep steps, etc,
the "meat" is:
struct contention_data data = {};
struct lock_stat *st = NULL;
<SNIP>
while (!bpf_map_get_next_key(fd, prev_key, &key)) {
s64 ls_key;
const char *name;
bpf_map_lookup_elem(fd, &key, &data);
name = lock_contention_get_name(con, &key, stack_trace, data.flags);
st = lock_stat_findnew(ls_key, name, data.flags);
That 'lock_stat' struct is then filled up and later, in the common part
to using or not BPF, it gets printed out in the builtin-lock.c main tool
codebase.
The part we're interested here is that lock_contention_get_name(), that
before this patch series returns "(mutex)" and now resolves it to the
slab cache name "&task_struct (mutex)".
key is:
struct contention_key {
s32 stack_id;
u32 pid;
u64 lock_addr_or_cgroup;
};
lock_contention_get_name() tries to resolve the name to the usual
suspects:
/* per-process locks set upper bits of the flags */
if (flags & LCD_F_MMAP_LOCK)
return "mmap_lock";
if (flags & LCD_F_SIGHAND_LOCK)
return "siglock";
/* global locks with symbols */
sym = machine__find_kernel_symbol(machine, key->lock_addr_or_cgroup, &kmap);
if (sym)
return sym->name;
And then if all of the above (there is another case for rq_lock) it
then gets to look the the ID area of contention_data->flags:
+#define LCB_F_SLAB_ID_SHIFT 16
+#define LCB_F_SLAB_ID_START (1U << 16)
+#define LCB_F_SLAB_ID_END (1U << 26)
+#define LCB_F_SLAB_ID_MASK 0x03FF0000U
>>> bin(0x03FF0000)
'0b11111111110000000000000000'
>>>
+ /* look slab_hash for dynamic locks in a slab object */
+ if (hashmap__find(&slab_hash, flags & LCB_F_SLAB_ID_MASK, &slab_data)) {
+ snprintf(name_buf, sizeof(name_buf), "&%s", slab_data->name);
+ return name_buf;
+ }
He wants to avoid storing 64 bytes (the slab cache pointer, 's'), instead
he wants to store a shorter 'id' and encode it in the upper bits of the
'struct contention_data' 'flags' field.
The iterator, at the beggining of the session attributes this id,
starting from zero, to each of the slab caches, so it needs to map it
back from the address at contention_end tracepoint.
At post processing time it converts the id back to the name of the slab
cache.
I hope this helps,
- Arnaldo
> - if it's postprocessing, it would be too late for bpf_get_kmem_cache() as
> the object might be gone already?
>
> The second alternative would be worse as it could miss the cache or
> misattribute (in case page is reallocated by another cache), the first is
> just less efficient than possible.
>
> > + }
> > + }
> >
> > err = bpf_map_update_elem(&lock_stat, &key, &first, BPF_NOEXIST);
> > if (err < 0) {
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 3/4] perf lock contention: Resolve slab object name using BPF
2024-11-12 14:50 ` Arnaldo Carvalho de Melo
@ 2024-11-13 14:20 ` Vlastimil Babka
2024-11-18 18:45 ` Namhyung Kim
0 siblings, 1 reply; 19+ messages in thread
From: Vlastimil Babka @ 2024-11-13 14:20 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: Namhyung Kim, Ian Rogers, Kan Liang, Jiri Olsa, Adrian Hunter,
Peter Zijlstra, Ingo Molnar, LKML, linux-perf-users,
Andrii Nakryiko, Song Liu, bpf, Stephane Eranian, Roman Gushchin,
Hyeonggon Yoo, Kees Cook
On 11/12/24 15:50, Arnaldo Carvalho de Melo wrote:
> On Tue, Nov 12, 2024 at 12:09:24PM +0100, Vlastimil Babka wrote:
> + /* look slab_hash for dynamic locks in a slab object */
> + if (hashmap__find(&slab_hash, flags & LCB_F_SLAB_ID_MASK, &slab_data)) {
> + snprintf(name_buf, sizeof(name_buf), "&%s", slab_data->name);
> + return name_buf;
> + }
>
> He wants to avoid storing 64 bytes (the slab cache pointer, 's'), instead
> he wants to store a shorter 'id' and encode it in the upper bits of the
> 'struct contention_data' 'flags' field.
>
> The iterator, at the beggining of the session attributes this id,
> starting from zero, to each of the slab caches, so it needs to map it
> back from the address at contention_end tracepoint.
>
> At post processing time it converts the id back to the name of the slab
> cache.
>
> I hope this helps,
Thanks a lot, if it's a tradeoff to do a bit more work in order to store
less data, then it makes sense to me.
Vlastimil
> - Arnaldo
>
>> - if it's postprocessing, it would be too late for bpf_get_kmem_cache() as
>> the object might be gone already?
>>
>> The second alternative would be worse as it could miss the cache or
>> misattribute (in case page is reallocated by another cache), the first is
>> just less efficient than possible.
>>
>> > + }
>> > + }
>> >
>> > err = bpf_map_update_elem(&lock_stat, &key, &first, BPF_NOEXIST);
>> > if (err < 0) {
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 0/4] perf lock contention: Symbolize locks using slab cache names
2024-11-11 19:46 ` [PATCH v2 0/4] perf lock contention: Symbolize locks using slab cache names Ian Rogers
@ 2024-11-18 18:35 ` Namhyung Kim
2024-12-13 17:10 ` Namhyung Kim
0 siblings, 1 reply; 19+ messages in thread
From: Namhyung Kim @ 2024-11-18 18:35 UTC (permalink / raw)
To: Ian Rogers
Cc: Arnaldo Carvalho de Melo, Kan Liang, Jiri Olsa, Adrian Hunter,
Peter Zijlstra, Ingo Molnar, LKML, linux-perf-users,
Andrii Nakryiko, Song Liu, bpf, Stephane Eranian, Vlastimil Babka,
Roman Gushchin, Hyeonggon Yoo, Kees Cook
On Mon, Nov 11, 2024 at 11:46:37AM -0800, Ian Rogers wrote:
> On Thu, Nov 7, 2024 at 10:15 PM Namhyung Kim <namhyung@kernel.org> wrote:
> >
> > Hello,
> >
> > This is to support symbolization of dynamic locks using slab
> > allocator's metadata. The kernel support is in the bpf-next tree now.
> >
> > It provides the new "kmem_cache" BPF iterator and "bpf_get_kmem_cache"
> > kfunc to get the information from an address. The feature detection is
> > done using BTF type info and it won't have any effect on old kernels.
> >
> > v2 changes)
> >
> > * don't use libbpf_get_error() (Andrii)
> >
> > v1) https://lore.kernel.org/linux-perf-users/20241105172635.2463800-1-namhyung@kernel.org
> >
> > With this change, it can show locks in a slab object like below. I
> > added "&" sign to distinguish them from global locks.
>
> I know the & is intentional but I worry it could later complicate
> parsing of filters. Perhaps @ is a viable alternative. Other than
> that:
>
> Acked-by: Ian Rogers <irogers@google.com>
Thanks for the review!
I don't think it clashes with BPF sample filters which works on sample
data generated from a perf_event. Technically this command doesn't use
perf_event and just attaches the BPF program to tracepoint directly.
Also sample filters don't use '&' symbol in the syntax as of now. :)
Thanks,
Namhyung
>
> > # perf lock con -abl sleep 1
> > contended total wait max wait avg wait address symbol
> >
> > 2 1.95 us 1.77 us 975 ns ffff9d5e852d3498 &task_struct (mutex)
> > 1 1.18 us 1.18 us 1.18 us ffff9d5e852d3538 &task_struct (mutex)
> > 4 1.12 us 354 ns 279 ns ffff9d5e841ca800 &kmalloc-cg-512 (mutex)
> > 2 859 ns 617 ns 429 ns ffffffffa41c3620 delayed_uprobe_lock (mutex)
> > 3 691 ns 388 ns 230 ns ffffffffa41c0940 pack_mutex (mutex)
> > 3 421 ns 164 ns 140 ns ffffffffa3a8b3a0 text_mutex (mutex)
> > 1 409 ns 409 ns 409 ns ffffffffa41b4cf8 tracepoint_srcu_srcu_usage (mutex)
> > 2 362 ns 239 ns 181 ns ffffffffa41cf840 pcpu_alloc_mutex (mutex)
> > 1 220 ns 220 ns 220 ns ffff9d5e82b534d8 &signal_cache (mutex)
> > 1 215 ns 215 ns 215 ns ffffffffa41b4c28 tracepoint_srcu_srcu_usage (mutex)
> >
> > The first two were from "task_struct" slab cache. It happened to
> > match with the type name of object but there's no guarantee. We need
> > to add type info to slab cache to resolve the lock inside the object.
> > Anyway, the third one has no dedicated slab cache and was allocated by
> > kmalloc.
> >
> > Those slab objects can be used to filter specific locks using -L or
> > --lock-filter option. (It needs quotes to avoid special handling in
> > the shell).
> >
> > # perf lock con -ab -L '&task_struct' sleep 1
> > contended total wait max wait avg wait type caller
> >
> > 1 25.10 us 25.10 us 25.10 us mutex perf_event_exit_task+0x39
> > 1 21.60 us 21.60 us 21.60 us mutex futex_exit_release+0x21
> > 1 5.56 us 5.56 us 5.56 us mutex futex_exec_release+0x21
> >
> > The code is available at 'perf/lock-slab-v2' branch in my tree
> >
> > git://git.kernel.org/pub/scm/linux/kernel/git/namhyung/linux-perf.git
> >
> > Thanks,
> > Namhyung
> >
> >
> > Namhyung Kim (4):
> > perf lock contention: Add and use LCB_F_TYPE_MASK
> > perf lock contention: Run BPF slab cache iterator
> > perf lock contention: Resolve slab object name using BPF
> > perf lock contention: Handle slab objects in -L/--lock-filter option
> >
> > tools/perf/builtin-lock.c | 39 ++++-
> > tools/perf/util/bpf_lock_contention.c | 140 +++++++++++++++++-
> > .../perf/util/bpf_skel/lock_contention.bpf.c | 70 ++++++++-
> > tools/perf/util/bpf_skel/lock_data.h | 15 +-
> > tools/perf/util/bpf_skel/vmlinux/vmlinux.h | 8 +
> > tools/perf/util/lock-contention.h | 2 +
> > 6 files changed, 267 insertions(+), 7 deletions(-)
> >
> > --
> > 2.47.0.277.g8800431eea-goog
> >
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 3/4] perf lock contention: Resolve slab object name using BPF
2024-11-13 14:20 ` Vlastimil Babka
@ 2024-11-18 18:45 ` Namhyung Kim
0 siblings, 0 replies; 19+ messages in thread
From: Namhyung Kim @ 2024-11-18 18:45 UTC (permalink / raw)
To: Vlastimil Babka
Cc: Arnaldo Carvalho de Melo, Ian Rogers, Kan Liang, Jiri Olsa,
Adrian Hunter, Peter Zijlstra, Ingo Molnar, LKML,
linux-perf-users, Andrii Nakryiko, Song Liu, bpf,
Stephane Eranian, Roman Gushchin, Hyeonggon Yoo, Kees Cook
Hello,
On Wed, Nov 13, 2024 at 03:20:43PM +0100, Vlastimil Babka wrote:
> On 11/12/24 15:50, Arnaldo Carvalho de Melo wrote:
> > On Tue, Nov 12, 2024 at 12:09:24PM +0100, Vlastimil Babka wrote:
> > + /* look slab_hash for dynamic locks in a slab object */
> > + if (hashmap__find(&slab_hash, flags & LCB_F_SLAB_ID_MASK, &slab_data)) {
> > + snprintf(name_buf, sizeof(name_buf), "&%s", slab_data->name);
> > + return name_buf;
> > + }
> >
> > He wants to avoid storing 64 bytes (the slab cache pointer, 's'), instead
> > he wants to store a shorter 'id' and encode it in the upper bits of the
> > 'struct contention_data' 'flags' field.
> >
> > The iterator, at the beggining of the session attributes this id,
> > starting from zero, to each of the slab caches, so it needs to map it
> > back from the address at contention_end tracepoint.
> >
> > At post processing time it converts the id back to the name of the slab
> > cache.
> >
> > I hope this helps,
Thanks Analdo for the explanation!
>
> Thanks a lot, if it's a tradeoff to do a bit more work in order to store
> less data, then it makes sense to me.
Right, I don't want to increase the data size for this as we have some
unused bits in the flags. It'd call one more bpf hashmap lookup during
record but I don't think it's gonna be a problem.
Thanks,
Namhyung
> >
> >> - if it's postprocessing, it would be too late for bpf_get_kmem_cache() as
> >> the object might be gone already?
> >>
> >> The second alternative would be worse as it could miss the cache or
> >> misattribute (in case page is reallocated by another cache), the first is
> >> just less efficient than possible.
> >>
> >> > + }
> >> > + }
> >> >
> >> > err = bpf_map_update_elem(&lock_stat, &key, &first, BPF_NOEXIST);
> >> > if (err < 0) {
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 2/4] perf lock contention: Run BPF slab cache iterator
2024-11-08 6:14 ` [PATCH v2 2/4] perf lock contention: Run BPF slab cache iterator Namhyung Kim
@ 2024-12-09 16:36 ` Arnaldo Carvalho de Melo
2024-12-09 16:38 ` Arnaldo Carvalho de Melo
0 siblings, 1 reply; 19+ messages in thread
From: Arnaldo Carvalho de Melo @ 2024-12-09 16:36 UTC (permalink / raw)
To: Namhyung Kim
Cc: Ian Rogers, Kan Liang, Jiri Olsa, Adrian Hunter, Peter Zijlstra,
Ingo Molnar, LKML, linux-perf-users, Andrii Nakryiko, Song Liu,
bpf, Stephane Eranian, Vlastimil Babka, Roman Gushchin,
Hyeonggon Yoo, Kees Cook
On Thu, Nov 07, 2024 at 10:14:57PM -0800, Namhyung Kim wrote:
> Recently the kernel got the kmem_cache iterator to traverse metadata of
> slab objects. This can be used to symbolize dynamic locks in a slab.
>
> The new slab_caches hash map will have the pointer of the kmem_cache as
> a key and save the name and a id. The id will be saved in the flags
> part of the lock.
Trying to fix this
cd . && make GEN_VMLINUX_H=1 FEATURES_DUMP=/home/acme/git/perf-tools-next/tools/perf/BUILD_TEST_FEATURE_DUMP -j28 O=/tmp/tmp.DWo9tIFvWU DESTDIR=/tmp/tmp.ex3iljqLBT
BUILD: Doing 'make -j28' parallel build
Warning: Kernel ABI header differences:
diff -u tools/include/uapi/drm/drm.h include/uapi/drm/drm.h
diff -u tools/include/uapi/linux/kvm.h include/uapi/linux/kvm.h
diff -u tools/include/uapi/linux/perf_event.h include/uapi/linux/perf_event.h
diff -u tools/arch/x86/include/asm/cpufeatures.h arch/x86/include/asm/cpufeatures.h
diff -u tools/arch/x86/include/uapi/asm/kvm.h arch/x86/include/uapi/asm/kvm.h
diff -u tools/arch/arm64/include/uapi/asm/kvm.h arch/arm64/include/uapi/asm/kvm.h
diff -u tools/arch/arm64/include/uapi/asm/unistd.h arch/arm64/include/uapi/asm/unistd.h
diff -u tools/include/uapi/asm-generic/unistd.h include/uapi/asm-generic/unistd.h
diff -u tools/include/uapi/asm-generic/mman.h include/uapi/asm-generic/mman.h
diff -u tools/perf/arch/x86/entry/syscalls/syscall_32.tbl arch/x86/entry/syscalls/syscall_32.tbl
diff -u tools/perf/arch/x86/entry/syscalls/syscall_64.tbl arch/x86/entry/syscalls/syscall_64.tbl
diff -u tools/perf/arch/powerpc/entry/syscalls/syscall.tbl arch/powerpc/kernel/syscalls/syscall.tbl
diff -u tools/perf/arch/s390/entry/syscalls/syscall.tbl arch/s390/kernel/syscalls/syscall.tbl
diff -u tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl arch/mips/kernel/syscalls/syscall_n64.tbl
diff -u tools/perf/trace/beauty/include/uapi/linux/fcntl.h include/uapi/linux/fcntl.h
diff -u tools/perf/trace/beauty/include/uapi/linux/mount.h include/uapi/linux/mount.h
diff -u tools/perf/trace/beauty/include/uapi/linux/prctl.h include/uapi/linux/prctl.h
Makefile.config:989: No libllvm 13+ found, slower source file resolution, please install llvm-devel/llvm-dev
Makefile.config:1171: No openjdk development package found, please install JDK package, e.g. openjdk-8-jdk, java-1.8.0-openjdk-devel
GEN /tmp/tmp.DWo9tIFvWU/common-cmds.h
CC /tmp/tmp.DWo9tIFvWU/dlfilters/dlfilter-test-api-v0.o
CC /tmp/tmp.DWo9tIFvWU/dlfilters/dlfilter-test-api-v2.o
CC /tmp/tmp.DWo9tIFvWU/dlfilters/dlfilter-show-cycles.o
GEN /tmp/tmp.DWo9tIFvWU/arch/arm64/include/generated/asm/sysreg-defs.h
LINK /tmp/tmp.DWo9tIFvWU/dlfilters/dlfilter-test-api-v2.so
LINK /tmp/tmp.DWo9tIFvWU/dlfilters/dlfilter-show-cycles.so
LINK /tmp/tmp.DWo9tIFvWU/dlfilters/dlfilter-test-api-v0.so
PERF_VERSION = 6.13.rc1.g61c6ae4ddd41
GEN perf-iostat
GEN perf-archive
INSTALL /tmp/tmp.DWo9tIFvWU/libsubcmd/include/subcmd/exec-cmd.h
INSTALL /tmp/tmp.DWo9tIFvWU/libsubcmd/include/subcmd/help.h
INSTALL /tmp/tmp.DWo9tIFvWU/libsubcmd/include/subcmd/pager.h
INSTALL /tmp/tmp.DWo9tIFvWU/libsubcmd/include/subcmd/parse-options.h
INSTALL /tmp/tmp.DWo9tIFvWU/libsubcmd/include/subcmd/run-command.h
INSTALL libsubcmd_headers
INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/perf/bpf_perf.h
INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/perf/core.h
INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/perf/cpumap.h
INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/perf/threadmap.h
INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/perf/evlist.h
INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/perf/evsel.h
INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/perf/event.h
INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/perf/mmap.h
CC /tmp/tmp.DWo9tIFvWU/libperf/core.o
INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/internal/cpumap.h
INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/internal/evlist.h
INSTALL /tmp/tmp.DWo9tIFvWU/libapi/include/api/cpu.h
CC /tmp/tmp.DWo9tIFvWU/libperf/cpumap.o
INSTALL /tmp/tmp.DWo9tIFvWU/libsymbol/include/symbol/kallsyms.h
INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/internal/evsel.h
INSTALL /tmp/tmp.DWo9tIFvWU/libapi/include/api/io.h
INSTALL /tmp/tmp.DWo9tIFvWU/libapi/include/api/debug.h
INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/internal/lib.h
CC /tmp/tmp.DWo9tIFvWU/libsymbol/kallsyms.o
CC /tmp/tmp.DWo9tIFvWU/libperf/threadmap.o
GEN /tmp/tmp.DWo9tIFvWU/libbpf/bpf_helper_defs.h
INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/internal/mmap.h
MKDIR /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf
CC /tmp/tmp.DWo9tIFvWU/libperf/evsel.o
INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/internal/rc_check.h
INSTALL /tmp/tmp.DWo9tIFvWU/libapi/include/api/fd/array.h
INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/internal/threadmap.h
INSTALL /tmp/tmp.DWo9tIFvWU/libbpf/include/bpf/bpf.h
CC /tmp/tmp.DWo9tIFvWU/libperf/evlist.o
INSTALL /tmp/tmp.DWo9tIFvWU/libapi/include/api/fs/fs.h
CC /tmp/tmp.DWo9tIFvWU/libapi/cpu.o
INSTALL libsymbol_headers
INSTALL /tmp/tmp.DWo9tIFvWU/libapi/include/api/fs/tracing_path.h
MKDIR /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/
INSTALL /tmp/tmp.DWo9tIFvWU/libbpf/include/bpf/libbpf.h
CC /tmp/tmp.DWo9tIFvWU/libperf/mmap.o
MKDIR /tmp/tmp.DWo9tIFvWU/libapi/fd/
INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/internal/xyarray.h
MKDIR /tmp/tmp.DWo9tIFvWU/libapi/fs/
INSTALL /tmp/tmp.DWo9tIFvWU/libbpf/include/bpf/btf.h
CC /tmp/tmp.DWo9tIFvWU/libperf/zalloc.o
CC /tmp/tmp.DWo9tIFvWU/libapi/debug.o
CC /tmp/tmp.DWo9tIFvWU/libapi/fd/array.o
CC /tmp/tmp.DWo9tIFvWU/libapi/fs/fs.o
INSTALL /tmp/tmp.DWo9tIFvWU/libbpf/include/bpf/libbpf_common.h
INSTALL /tmp/tmp.DWo9tIFvWU/libbpf/include/bpf/libbpf_legacy.h
CC /tmp/tmp.DWo9tIFvWU/libapi/str_error_r.o
INSTALL /tmp/tmp.DWo9tIFvWU/libbpf/include/bpf/bpf_helpers.h
MKDIR /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/
INSTALL libperf_headers
INSTALL libapi_headers
INSTALL /tmp/tmp.DWo9tIFvWU/libbpf/include/bpf/bpf_tracing.h
CC /tmp/tmp.DWo9tIFvWU/libapi/fs/tracing_path.o
INSTALL /tmp/tmp.DWo9tIFvWU/libbpf/include/bpf/bpf_endian.h
CC /tmp/tmp.DWo9tIFvWU/libperf/xyarray.o
CC /tmp/tmp.DWo9tIFvWU/libapi/fs/cgroup.o
INSTALL /tmp/tmp.DWo9tIFvWU/libbpf/include/bpf/bpf_core_read.h
INSTALL /tmp/tmp.DWo9tIFvWU/libbpf/include/bpf/skel_internal.h
INSTALL /tmp/tmp.DWo9tIFvWU/libbpf/include/bpf/libbpf_version.h
CC /tmp/tmp.DWo9tIFvWU/libperf/lib.o
INSTALL /tmp/tmp.DWo9tIFvWU/libbpf/include/bpf/usdt.bpf.h
INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/hashmap.h
INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/relo_core.h
INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/libbpf_internal.h
CC /tmp/tmp.DWo9tIFvWU/libsubcmd/help.o
CC /tmp/tmp.DWo9tIFvWU/libsubcmd/exec-cmd.o
CC /tmp/tmp.DWo9tIFvWU/libsubcmd/pager.o
CC /tmp/tmp.DWo9tIFvWU/libsubcmd/parse-options.o
CC /tmp/tmp.DWo9tIFvWU/libsubcmd/run-command.o
CC /tmp/tmp.DWo9tIFvWU/libsubcmd/sigchain.o
CC /tmp/tmp.DWo9tIFvWU/libsubcmd/subcmd-config.o
INSTALL /tmp/tmp.DWo9tIFvWU/libbpf/include/bpf/bpf_helper_defs.h
INSTALL libbpf_headers
GEN /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/bpf_helper_defs.h
INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/bpf.h
INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/libbpf.h
INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/btf.h
INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/libbpf_common.h
INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/libbpf_legacy.h
INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/bpf_helpers.h
INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/bpf_tracing.h
INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/bpf_endian.h
INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/bpf_core_read.h
INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/skel_internal.h
INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/libbpf_version.h
INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/usdt.bpf.h
LD /tmp/tmp.DWo9tIFvWU/libapi/fd/libapi-in.o
LD /tmp/tmp.DWo9tIFvWU/libsymbol/libsymbol-in.o
AR /tmp/tmp.DWo9tIFvWU/libsymbol/libsymbol.a
LD /tmp/tmp.DWo9tIFvWU/libapi/fs/libapi-in.o
INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/bpf_helper_defs.h
INSTALL libbpf_headers
LD /tmp/tmp.DWo9tIFvWU/libapi/libapi-in.o
CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/libbpf.o
CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/bpf.o
CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/nlattr.o
CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/btf.o
CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/libbpf_errno.o
CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/str_error.o
LD /tmp/tmp.DWo9tIFvWU/libperf/libperf-in.o
AR /tmp/tmp.DWo9tIFvWU/libapi/libapi.a
CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/netlink.o
CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/bpf_prog_linfo.o
CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/libbpf_probes.o
CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/hashmap.o
CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/btf_dump.o
CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/ringbuf.o
CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/strset.o
CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/linker.o
CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/gen_loader.o
CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/relo_core.o
CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/usdt.o
AR /tmp/tmp.DWo9tIFvWU/libperf/libperf.a
CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/zip.o
CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/elf.o
CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/features.o
CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/btf_iter.o
CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/btf_relocate.o
CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/libbpf.o
CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/bpf.o
CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/nlattr.o
CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/btf.o
CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/libbpf_errno.o
CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/str_error.o
CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/netlink.o
CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/bpf_prog_linfo.o
CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/libbpf_probes.o
CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/hashmap.o
CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/btf_dump.o
CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/ringbuf.o
CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/strset.o
CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/linker.o
CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/gen_loader.o
CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/relo_core.o
CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/usdt.o
CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/zip.o
CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/elf.o
CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/features.o
CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/btf_iter.o
CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/btf_relocate.o
LD /tmp/tmp.DWo9tIFvWU/libsubcmd/libsubcmd-in.o
AR /tmp/tmp.DWo9tIFvWU/libsubcmd/libsubcmd.a
LD /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/libbpf-in.o
LINK /tmp/tmp.DWo9tIFvWU/libbpf/libbpf.a
LD /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/libbpf-in.o
LINK /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/libbpf.a
CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/main.o
CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/common.o
CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/json_writer.o
CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/gen.o
CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/btf.o
LINK /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/bpftool
GEN /tmp/tmp.DWo9tIFvWU/util/bpf_skel/vmlinux.h
CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bpf_prog_profiler.bpf.o
CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bperf_leader.bpf.o
CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bperf_follower.bpf.o
CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bperf_cgroup.bpf.o
CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/func_latency.bpf.o
CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/off_cpu.bpf.o
CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/lock_contention.bpf.o
CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/kwork_trace.bpf.o
CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/sample_filter.bpf.o
CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/kwork_top.bpf.o
CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bench_uprobe.bpf.o
CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/augmented_raw_syscalls.bpf.o
GENSKEL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/bench_uprobe.skel.h
GENSKEL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/func_latency.skel.h
util/bpf_skel/lock_contention.bpf.c:612:28: error: declaration of 'struct bpf_iter__kmem_cache' will not be visible outside of this function [-Werror,-Wvisibility]
612 | int slab_cache_iter(struct bpf_iter__kmem_cache *ctx)
| ^
util/bpf_skel/lock_contention.bpf.c:614:28: error: incomplete definition of type 'struct bpf_iter__kmem_cache'
614 | struct kmem_cache *s = ctx->s;
| ~~~^
util/bpf_skel/lock_contention.bpf.c:612:28: note: forward declaration of 'struct bpf_iter__kmem_cache'
612 | int slab_cache_iter(struct bpf_iter__kmem_cache *ctx)
| ^
2 errors generated.
make[4]: *** [Makefile.perf:1248: /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/lock_contention.bpf.o] Error 1
make[4]: *** Waiting for unfinished jobs....
make[3]: *** [Makefile.perf:292: sub-make] Error 2
make[2]: *** [Makefile:76: all] Error 2
make[1]: *** [tests/make:344: make_gen_vmlinux_h_O] Error 1
make: *** [Makefile:109: build-test] Error 2
make: Leaving directory '/home/acme/git/perf-tools-next/tools/perf'
real 3m43.896s
user 29m30.716s
sys 6m36.609s
⬢ [acme@toolbox perf-tools-next]$
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> ---
> tools/perf/util/bpf_lock_contention.c | 50 +++++++++++++++++++
> .../perf/util/bpf_skel/lock_contention.bpf.c | 28 +++++++++++
> tools/perf/util/bpf_skel/lock_data.h | 12 +++++
> tools/perf/util/bpf_skel/vmlinux/vmlinux.h | 8 +++
> 4 files changed, 98 insertions(+)
>
> diff --git a/tools/perf/util/bpf_lock_contention.c b/tools/perf/util/bpf_lock_contention.c
> index 41a1ad08789511c3..558590c3111390fc 100644
> --- a/tools/perf/util/bpf_lock_contention.c
> +++ b/tools/perf/util/bpf_lock_contention.c
> @@ -12,12 +12,59 @@
> #include <linux/zalloc.h>
> #include <linux/string.h>
> #include <bpf/bpf.h>
> +#include <bpf/btf.h>
> #include <inttypes.h>
>
> #include "bpf_skel/lock_contention.skel.h"
> #include "bpf_skel/lock_data.h"
>
> static struct lock_contention_bpf *skel;
> +static bool has_slab_iter;
> +
> +static void check_slab_cache_iter(struct lock_contention *con)
> +{
> + struct btf *btf = btf__load_vmlinux_btf();
> + s32 ret;
> +
> + if (btf == NULL) {
> + pr_debug("BTF loading failed: %s\n", strerror(errno));
> + return;
> + }
> +
> + ret = btf__find_by_name_kind(btf, "bpf_iter__kmem_cache", BTF_KIND_STRUCT);
> + if (ret < 0) {
> + bpf_program__set_autoload(skel->progs.slab_cache_iter, false);
> + pr_debug("slab cache iterator is not available: %d\n", ret);
> + goto out;
> + }
> +
> + has_slab_iter = true;
> +
> + bpf_map__set_max_entries(skel->maps.slab_caches, con->map_nr_entries);
> +out:
> + btf__free(btf);
> +}
> +
> +static void run_slab_cache_iter(void)
> +{
> + int fd;
> + char buf[256];
> +
> + if (!has_slab_iter)
> + return;
> +
> + fd = bpf_iter_create(bpf_link__fd(skel->links.slab_cache_iter));
> + if (fd < 0) {
> + pr_debug("cannot create slab cache iter: %d\n", fd);
> + return;
> + }
> +
> + /* This will run the bpf program */
> + while (read(fd, buf, sizeof(buf)) > 0)
> + continue;
> +
> + close(fd);
> +}
>
> int lock_contention_prepare(struct lock_contention *con)
> {
> @@ -109,6 +156,8 @@ int lock_contention_prepare(struct lock_contention *con)
> skel->rodata->use_cgroup_v2 = 1;
> }
>
> + check_slab_cache_iter(con);
> +
> if (lock_contention_bpf__load(skel) < 0) {
> pr_err("Failed to load lock-contention BPF skeleton\n");
> return -1;
> @@ -304,6 +353,7 @@ static void account_end_timestamp(struct lock_contention *con)
>
> int lock_contention_start(void)
> {
> + run_slab_cache_iter();
> skel->bss->enabled = 1;
> return 0;
> }
> diff --git a/tools/perf/util/bpf_skel/lock_contention.bpf.c b/tools/perf/util/bpf_skel/lock_contention.bpf.c
> index 1069bda5d733887f..fd24ccb00faec0ba 100644
> --- a/tools/perf/util/bpf_skel/lock_contention.bpf.c
> +++ b/tools/perf/util/bpf_skel/lock_contention.bpf.c
> @@ -100,6 +100,13 @@ struct {
> __uint(max_entries, 1);
> } cgroup_filter SEC(".maps");
>
> +struct {
> + __uint(type, BPF_MAP_TYPE_HASH);
> + __uint(key_size, sizeof(long));
> + __uint(value_size, sizeof(struct slab_cache_data));
> + __uint(max_entries, 1);
> +} slab_caches SEC(".maps");
> +
> struct rw_semaphore___old {
> struct task_struct *owner;
> } __attribute__((preserve_access_index));
> @@ -136,6 +143,8 @@ int perf_subsys_id = -1;
>
> __u64 end_ts;
>
> +__u32 slab_cache_id;
> +
> /* error stat */
> int task_fail;
> int stack_fail;
> @@ -563,4 +572,23 @@ int BPF_PROG(end_timestamp)
> return 0;
> }
>
> +SEC("iter/kmem_cache")
> +int slab_cache_iter(struct bpf_iter__kmem_cache *ctx)
> +{
> + struct kmem_cache *s = ctx->s;
> + struct slab_cache_data d;
> +
> + if (s == NULL)
> + return 0;
> +
> + d.id = ++slab_cache_id << LCB_F_SLAB_ID_SHIFT;
> + bpf_probe_read_kernel_str(d.name, sizeof(d.name), s->name);
> +
> + if (d.id >= LCB_F_SLAB_ID_END)
> + return 0;
> +
> + bpf_map_update_elem(&slab_caches, &s, &d, BPF_NOEXIST);
> + return 0;
> +}
> +
> char LICENSE[] SEC("license") = "Dual BSD/GPL";
> diff --git a/tools/perf/util/bpf_skel/lock_data.h b/tools/perf/util/bpf_skel/lock_data.h
> index 4f0aae5483745dfa..c15f734d7fc4aecb 100644
> --- a/tools/perf/util/bpf_skel/lock_data.h
> +++ b/tools/perf/util/bpf_skel/lock_data.h
> @@ -32,9 +32,16 @@ struct contention_task_data {
> #define LCD_F_MMAP_LOCK (1U << 31)
> #define LCD_F_SIGHAND_LOCK (1U << 30)
>
> +#define LCB_F_SLAB_ID_SHIFT 16
> +#define LCB_F_SLAB_ID_START (1U << 16)
> +#define LCB_F_SLAB_ID_END (1U << 26)
> +#define LCB_F_SLAB_ID_MASK 0x03FF0000U
> +
> #define LCB_F_TYPE_MAX (1U << 7)
> #define LCB_F_TYPE_MASK 0x0000007FU
>
> +#define SLAB_NAME_MAX 28
> +
> struct contention_data {
> u64 total_time;
> u64 min_time;
> @@ -55,4 +62,9 @@ enum lock_class_sym {
> LOCK_CLASS_RQLOCK,
> };
>
> +struct slab_cache_data {
> + u32 id;
> + char name[SLAB_NAME_MAX];
> +};
> +
> #endif /* UTIL_BPF_SKEL_LOCK_DATA_H */
> diff --git a/tools/perf/util/bpf_skel/vmlinux/vmlinux.h b/tools/perf/util/bpf_skel/vmlinux/vmlinux.h
> index 4dcad7b682bdee9c..7b81d3173917fdb5 100644
> --- a/tools/perf/util/bpf_skel/vmlinux/vmlinux.h
> +++ b/tools/perf/util/bpf_skel/vmlinux/vmlinux.h
> @@ -195,4 +195,12 @@ struct bpf_perf_event_data_kern {
> */
> struct rq {};
>
> +struct kmem_cache {
> + const char *name;
> +} __attribute__((preserve_access_index));
> +
> +struct bpf_iter__kmem_cache {
> + struct kmem_cache *s;
> +} __attribute__((preserve_access_index));
> +
> #endif // __VMLINUX_H
> --
> 2.47.0.277.g8800431eea-goog
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 2/4] perf lock contention: Run BPF slab cache iterator
2024-12-09 16:36 ` Arnaldo Carvalho de Melo
@ 2024-12-09 16:38 ` Arnaldo Carvalho de Melo
2024-12-09 20:23 ` Arnaldo Carvalho de Melo
2024-12-09 22:16 ` Namhyung Kim
0 siblings, 2 replies; 19+ messages in thread
From: Arnaldo Carvalho de Melo @ 2024-12-09 16:38 UTC (permalink / raw)
To: Namhyung Kim
Cc: Ian Rogers, Kan Liang, Jiri Olsa, Adrian Hunter, Peter Zijlstra,
Ingo Molnar, LKML, linux-perf-users, Andrii Nakryiko, Song Liu,
bpf, Stephane Eranian, Vlastimil Babka, Roman Gushchin,
Hyeonggon Yoo, Kees Cook
On Mon, Dec 09, 2024 at 01:36:52PM -0300, Arnaldo Carvalho de Melo wrote:
> On Thu, Nov 07, 2024 at 10:14:57PM -0800, Namhyung Kim wrote:
> > Recently the kernel got the kmem_cache iterator to traverse metadata of
> > slab objects. This can be used to symbolize dynamic locks in a slab.
> >
> > The new slab_caches hash map will have the pointer of the kmem_cache as
> > a key and save the name and a id. The id will be saved in the flags
> > part of the lock.
>
> Trying to fix this
So you have that struct in tools/perf/util/bpf_skel/vmlinux/vmlinux.h,
but then, this kernel is old and doesn't have the kmem_cache iterator,
so using the generated vmlinux.h will fail the build.
- Arnaldo
> cd . && make GEN_VMLINUX_H=1 FEATURES_DUMP=/home/acme/git/perf-tools-next/tools/perf/BUILD_TEST_FEATURE_DUMP -j28 O=/tmp/tmp.DWo9tIFvWU DESTDIR=/tmp/tmp.ex3iljqLBT
> BUILD: Doing 'make -j28' parallel build
> Warning: Kernel ABI header differences:
> diff -u tools/include/uapi/drm/drm.h include/uapi/drm/drm.h
> diff -u tools/include/uapi/linux/kvm.h include/uapi/linux/kvm.h
> diff -u tools/include/uapi/linux/perf_event.h include/uapi/linux/perf_event.h
> diff -u tools/arch/x86/include/asm/cpufeatures.h arch/x86/include/asm/cpufeatures.h
> diff -u tools/arch/x86/include/uapi/asm/kvm.h arch/x86/include/uapi/asm/kvm.h
> diff -u tools/arch/arm64/include/uapi/asm/kvm.h arch/arm64/include/uapi/asm/kvm.h
> diff -u tools/arch/arm64/include/uapi/asm/unistd.h arch/arm64/include/uapi/asm/unistd.h
> diff -u tools/include/uapi/asm-generic/unistd.h include/uapi/asm-generic/unistd.h
> diff -u tools/include/uapi/asm-generic/mman.h include/uapi/asm-generic/mman.h
> diff -u tools/perf/arch/x86/entry/syscalls/syscall_32.tbl arch/x86/entry/syscalls/syscall_32.tbl
> diff -u tools/perf/arch/x86/entry/syscalls/syscall_64.tbl arch/x86/entry/syscalls/syscall_64.tbl
> diff -u tools/perf/arch/powerpc/entry/syscalls/syscall.tbl arch/powerpc/kernel/syscalls/syscall.tbl
> diff -u tools/perf/arch/s390/entry/syscalls/syscall.tbl arch/s390/kernel/syscalls/syscall.tbl
> diff -u tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl arch/mips/kernel/syscalls/syscall_n64.tbl
> diff -u tools/perf/trace/beauty/include/uapi/linux/fcntl.h include/uapi/linux/fcntl.h
> diff -u tools/perf/trace/beauty/include/uapi/linux/mount.h include/uapi/linux/mount.h
> diff -u tools/perf/trace/beauty/include/uapi/linux/prctl.h include/uapi/linux/prctl.h
> Makefile.config:989: No libllvm 13+ found, slower source file resolution, please install llvm-devel/llvm-dev
> Makefile.config:1171: No openjdk development package found, please install JDK package, e.g. openjdk-8-jdk, java-1.8.0-openjdk-devel
>
> GEN /tmp/tmp.DWo9tIFvWU/common-cmds.h
> CC /tmp/tmp.DWo9tIFvWU/dlfilters/dlfilter-test-api-v0.o
> CC /tmp/tmp.DWo9tIFvWU/dlfilters/dlfilter-test-api-v2.o
> CC /tmp/tmp.DWo9tIFvWU/dlfilters/dlfilter-show-cycles.o
> GEN /tmp/tmp.DWo9tIFvWU/arch/arm64/include/generated/asm/sysreg-defs.h
> LINK /tmp/tmp.DWo9tIFvWU/dlfilters/dlfilter-test-api-v2.so
> LINK /tmp/tmp.DWo9tIFvWU/dlfilters/dlfilter-show-cycles.so
> LINK /tmp/tmp.DWo9tIFvWU/dlfilters/dlfilter-test-api-v0.so
> PERF_VERSION = 6.13.rc1.g61c6ae4ddd41
> GEN perf-iostat
> GEN perf-archive
> INSTALL /tmp/tmp.DWo9tIFvWU/libsubcmd/include/subcmd/exec-cmd.h
> INSTALL /tmp/tmp.DWo9tIFvWU/libsubcmd/include/subcmd/help.h
> INSTALL /tmp/tmp.DWo9tIFvWU/libsubcmd/include/subcmd/pager.h
> INSTALL /tmp/tmp.DWo9tIFvWU/libsubcmd/include/subcmd/parse-options.h
> INSTALL /tmp/tmp.DWo9tIFvWU/libsubcmd/include/subcmd/run-command.h
> INSTALL libsubcmd_headers
> INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/perf/bpf_perf.h
> INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/perf/core.h
> INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/perf/cpumap.h
> INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/perf/threadmap.h
> INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/perf/evlist.h
> INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/perf/evsel.h
> INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/perf/event.h
> INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/perf/mmap.h
> CC /tmp/tmp.DWo9tIFvWU/libperf/core.o
> INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/internal/cpumap.h
> INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/internal/evlist.h
> INSTALL /tmp/tmp.DWo9tIFvWU/libapi/include/api/cpu.h
> CC /tmp/tmp.DWo9tIFvWU/libperf/cpumap.o
> INSTALL /tmp/tmp.DWo9tIFvWU/libsymbol/include/symbol/kallsyms.h
> INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/internal/evsel.h
> INSTALL /tmp/tmp.DWo9tIFvWU/libapi/include/api/io.h
> INSTALL /tmp/tmp.DWo9tIFvWU/libapi/include/api/debug.h
> INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/internal/lib.h
> CC /tmp/tmp.DWo9tIFvWU/libsymbol/kallsyms.o
> CC /tmp/tmp.DWo9tIFvWU/libperf/threadmap.o
> GEN /tmp/tmp.DWo9tIFvWU/libbpf/bpf_helper_defs.h
> INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/internal/mmap.h
> MKDIR /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf
> CC /tmp/tmp.DWo9tIFvWU/libperf/evsel.o
> INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/internal/rc_check.h
> INSTALL /tmp/tmp.DWo9tIFvWU/libapi/include/api/fd/array.h
> INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/internal/threadmap.h
> INSTALL /tmp/tmp.DWo9tIFvWU/libbpf/include/bpf/bpf.h
> CC /tmp/tmp.DWo9tIFvWU/libperf/evlist.o
> INSTALL /tmp/tmp.DWo9tIFvWU/libapi/include/api/fs/fs.h
> CC /tmp/tmp.DWo9tIFvWU/libapi/cpu.o
> INSTALL libsymbol_headers
> INSTALL /tmp/tmp.DWo9tIFvWU/libapi/include/api/fs/tracing_path.h
> MKDIR /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/
> INSTALL /tmp/tmp.DWo9tIFvWU/libbpf/include/bpf/libbpf.h
> CC /tmp/tmp.DWo9tIFvWU/libperf/mmap.o
> MKDIR /tmp/tmp.DWo9tIFvWU/libapi/fd/
> INSTALL /tmp/tmp.DWo9tIFvWU/libperf/include/internal/xyarray.h
> MKDIR /tmp/tmp.DWo9tIFvWU/libapi/fs/
> INSTALL /tmp/tmp.DWo9tIFvWU/libbpf/include/bpf/btf.h
> CC /tmp/tmp.DWo9tIFvWU/libperf/zalloc.o
> CC /tmp/tmp.DWo9tIFvWU/libapi/debug.o
> CC /tmp/tmp.DWo9tIFvWU/libapi/fd/array.o
> CC /tmp/tmp.DWo9tIFvWU/libapi/fs/fs.o
> INSTALL /tmp/tmp.DWo9tIFvWU/libbpf/include/bpf/libbpf_common.h
> INSTALL /tmp/tmp.DWo9tIFvWU/libbpf/include/bpf/libbpf_legacy.h
> CC /tmp/tmp.DWo9tIFvWU/libapi/str_error_r.o
> INSTALL /tmp/tmp.DWo9tIFvWU/libbpf/include/bpf/bpf_helpers.h
> MKDIR /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/
> INSTALL libperf_headers
> INSTALL libapi_headers
> INSTALL /tmp/tmp.DWo9tIFvWU/libbpf/include/bpf/bpf_tracing.h
> CC /tmp/tmp.DWo9tIFvWU/libapi/fs/tracing_path.o
> INSTALL /tmp/tmp.DWo9tIFvWU/libbpf/include/bpf/bpf_endian.h
> CC /tmp/tmp.DWo9tIFvWU/libperf/xyarray.o
> CC /tmp/tmp.DWo9tIFvWU/libapi/fs/cgroup.o
> INSTALL /tmp/tmp.DWo9tIFvWU/libbpf/include/bpf/bpf_core_read.h
> INSTALL /tmp/tmp.DWo9tIFvWU/libbpf/include/bpf/skel_internal.h
> INSTALL /tmp/tmp.DWo9tIFvWU/libbpf/include/bpf/libbpf_version.h
> CC /tmp/tmp.DWo9tIFvWU/libperf/lib.o
> INSTALL /tmp/tmp.DWo9tIFvWU/libbpf/include/bpf/usdt.bpf.h
> INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/hashmap.h
> INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/relo_core.h
> INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/libbpf_internal.h
> CC /tmp/tmp.DWo9tIFvWU/libsubcmd/help.o
> CC /tmp/tmp.DWo9tIFvWU/libsubcmd/exec-cmd.o
> CC /tmp/tmp.DWo9tIFvWU/libsubcmd/pager.o
> CC /tmp/tmp.DWo9tIFvWU/libsubcmd/parse-options.o
> CC /tmp/tmp.DWo9tIFvWU/libsubcmd/run-command.o
> CC /tmp/tmp.DWo9tIFvWU/libsubcmd/sigchain.o
> CC /tmp/tmp.DWo9tIFvWU/libsubcmd/subcmd-config.o
> INSTALL /tmp/tmp.DWo9tIFvWU/libbpf/include/bpf/bpf_helper_defs.h
> INSTALL libbpf_headers
> GEN /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/bpf_helper_defs.h
> INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/bpf.h
> INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/libbpf.h
> INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/btf.h
> INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/libbpf_common.h
> INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/libbpf_legacy.h
> INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/bpf_helpers.h
> INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/bpf_tracing.h
> INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/bpf_endian.h
> INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/bpf_core_read.h
> INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/skel_internal.h
> INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/libbpf_version.h
> INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/usdt.bpf.h
> LD /tmp/tmp.DWo9tIFvWU/libapi/fd/libapi-in.o
> LD /tmp/tmp.DWo9tIFvWU/libsymbol/libsymbol-in.o
> AR /tmp/tmp.DWo9tIFvWU/libsymbol/libsymbol.a
> LD /tmp/tmp.DWo9tIFvWU/libapi/fs/libapi-in.o
> INSTALL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/include/bpf/bpf_helper_defs.h
> INSTALL libbpf_headers
> LD /tmp/tmp.DWo9tIFvWU/libapi/libapi-in.o
> CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/libbpf.o
> CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/bpf.o
> CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/nlattr.o
> CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/btf.o
> CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/libbpf_errno.o
> CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/str_error.o
> LD /tmp/tmp.DWo9tIFvWU/libperf/libperf-in.o
> AR /tmp/tmp.DWo9tIFvWU/libapi/libapi.a
> CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/netlink.o
> CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/bpf_prog_linfo.o
> CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/libbpf_probes.o
> CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/hashmap.o
> CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/btf_dump.o
> CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/ringbuf.o
> CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/strset.o
> CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/linker.o
> CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/gen_loader.o
> CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/relo_core.o
> CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/usdt.o
> AR /tmp/tmp.DWo9tIFvWU/libperf/libperf.a
> CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/zip.o
> CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/elf.o
> CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/features.o
> CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/btf_iter.o
> CC /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/btf_relocate.o
> CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/libbpf.o
> CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/bpf.o
> CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/nlattr.o
> CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/btf.o
> CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/libbpf_errno.o
> CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/str_error.o
> CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/netlink.o
> CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/bpf_prog_linfo.o
> CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/libbpf_probes.o
> CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/hashmap.o
> CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/btf_dump.o
> CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/ringbuf.o
> CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/strset.o
> CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/linker.o
> CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/gen_loader.o
> CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/relo_core.o
> CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/usdt.o
> CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/zip.o
> CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/elf.o
> CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/features.o
> CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/btf_iter.o
> CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/btf_relocate.o
> LD /tmp/tmp.DWo9tIFvWU/libsubcmd/libsubcmd-in.o
> AR /tmp/tmp.DWo9tIFvWU/libsubcmd/libsubcmd.a
> LD /tmp/tmp.DWo9tIFvWU/libbpf/staticobjs/libbpf-in.o
> LINK /tmp/tmp.DWo9tIFvWU/libbpf/libbpf.a
> LD /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/staticobjs/libbpf-in.o
> LINK /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/libbpf/libbpf.a
> CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/main.o
> CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/common.o
> CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/json_writer.o
> CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/gen.o
> CC /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/btf.o
> LINK /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bootstrap/bpftool
> GEN /tmp/tmp.DWo9tIFvWU/util/bpf_skel/vmlinux.h
> CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bpf_prog_profiler.bpf.o
> CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bperf_leader.bpf.o
> CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bperf_follower.bpf.o
> CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bperf_cgroup.bpf.o
> CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/func_latency.bpf.o
> CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/off_cpu.bpf.o
> CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/lock_contention.bpf.o
> CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/kwork_trace.bpf.o
> CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/sample_filter.bpf.o
> CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/kwork_top.bpf.o
> CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bench_uprobe.bpf.o
> CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/augmented_raw_syscalls.bpf.o
> GENSKEL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/bench_uprobe.skel.h
> GENSKEL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/func_latency.skel.h
> util/bpf_skel/lock_contention.bpf.c:612:28: error: declaration of 'struct bpf_iter__kmem_cache' will not be visible outside of this function [-Werror,-Wvisibility]
> 612 | int slab_cache_iter(struct bpf_iter__kmem_cache *ctx)
> | ^
> util/bpf_skel/lock_contention.bpf.c:614:28: error: incomplete definition of type 'struct bpf_iter__kmem_cache'
> 614 | struct kmem_cache *s = ctx->s;
> | ~~~^
> util/bpf_skel/lock_contention.bpf.c:612:28: note: forward declaration of 'struct bpf_iter__kmem_cache'
> 612 | int slab_cache_iter(struct bpf_iter__kmem_cache *ctx)
> | ^
> 2 errors generated.
> make[4]: *** [Makefile.perf:1248: /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/lock_contention.bpf.o] Error 1
> make[4]: *** Waiting for unfinished jobs....
> make[3]: *** [Makefile.perf:292: sub-make] Error 2
> make[2]: *** [Makefile:76: all] Error 2
> make[1]: *** [tests/make:344: make_gen_vmlinux_h_O] Error 1
> make: *** [Makefile:109: build-test] Error 2
> make: Leaving directory '/home/acme/git/perf-tools-next/tools/perf'
>
> real 3m43.896s
> user 29m30.716s
> sys 6m36.609s
> ⬢ [acme@toolbox perf-tools-next]$
>
>
>
> > Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> > ---
> > tools/perf/util/bpf_lock_contention.c | 50 +++++++++++++++++++
> > .../perf/util/bpf_skel/lock_contention.bpf.c | 28 +++++++++++
> > tools/perf/util/bpf_skel/lock_data.h | 12 +++++
> > tools/perf/util/bpf_skel/vmlinux/vmlinux.h | 8 +++
> > 4 files changed, 98 insertions(+)
> >
> > diff --git a/tools/perf/util/bpf_lock_contention.c b/tools/perf/util/bpf_lock_contention.c
> > index 41a1ad08789511c3..558590c3111390fc 100644
> > --- a/tools/perf/util/bpf_lock_contention.c
> > +++ b/tools/perf/util/bpf_lock_contention.c
> > @@ -12,12 +12,59 @@
> > #include <linux/zalloc.h>
> > #include <linux/string.h>
> > #include <bpf/bpf.h>
> > +#include <bpf/btf.h>
> > #include <inttypes.h>
> >
> > #include "bpf_skel/lock_contention.skel.h"
> > #include "bpf_skel/lock_data.h"
> >
> > static struct lock_contention_bpf *skel;
> > +static bool has_slab_iter;
> > +
> > +static void check_slab_cache_iter(struct lock_contention *con)
> > +{
> > + struct btf *btf = btf__load_vmlinux_btf();
> > + s32 ret;
> > +
> > + if (btf == NULL) {
> > + pr_debug("BTF loading failed: %s\n", strerror(errno));
> > + return;
> > + }
> > +
> > + ret = btf__find_by_name_kind(btf, "bpf_iter__kmem_cache", BTF_KIND_STRUCT);
> > + if (ret < 0) {
> > + bpf_program__set_autoload(skel->progs.slab_cache_iter, false);
> > + pr_debug("slab cache iterator is not available: %d\n", ret);
> > + goto out;
> > + }
> > +
> > + has_slab_iter = true;
> > +
> > + bpf_map__set_max_entries(skel->maps.slab_caches, con->map_nr_entries);
> > +out:
> > + btf__free(btf);
> > +}
> > +
> > +static void run_slab_cache_iter(void)
> > +{
> > + int fd;
> > + char buf[256];
> > +
> > + if (!has_slab_iter)
> > + return;
> > +
> > + fd = bpf_iter_create(bpf_link__fd(skel->links.slab_cache_iter));
> > + if (fd < 0) {
> > + pr_debug("cannot create slab cache iter: %d\n", fd);
> > + return;
> > + }
> > +
> > + /* This will run the bpf program */
> > + while (read(fd, buf, sizeof(buf)) > 0)
> > + continue;
> > +
> > + close(fd);
> > +}
> >
> > int lock_contention_prepare(struct lock_contention *con)
> > {
> > @@ -109,6 +156,8 @@ int lock_contention_prepare(struct lock_contention *con)
> > skel->rodata->use_cgroup_v2 = 1;
> > }
> >
> > + check_slab_cache_iter(con);
> > +
> > if (lock_contention_bpf__load(skel) < 0) {
> > pr_err("Failed to load lock-contention BPF skeleton\n");
> > return -1;
> > @@ -304,6 +353,7 @@ static void account_end_timestamp(struct lock_contention *con)
> >
> > int lock_contention_start(void)
> > {
> > + run_slab_cache_iter();
> > skel->bss->enabled = 1;
> > return 0;
> > }
> > diff --git a/tools/perf/util/bpf_skel/lock_contention.bpf.c b/tools/perf/util/bpf_skel/lock_contention.bpf.c
> > index 1069bda5d733887f..fd24ccb00faec0ba 100644
> > --- a/tools/perf/util/bpf_skel/lock_contention.bpf.c
> > +++ b/tools/perf/util/bpf_skel/lock_contention.bpf.c
> > @@ -100,6 +100,13 @@ struct {
> > __uint(max_entries, 1);
> > } cgroup_filter SEC(".maps");
> >
> > +struct {
> > + __uint(type, BPF_MAP_TYPE_HASH);
> > + __uint(key_size, sizeof(long));
> > + __uint(value_size, sizeof(struct slab_cache_data));
> > + __uint(max_entries, 1);
> > +} slab_caches SEC(".maps");
> > +
> > struct rw_semaphore___old {
> > struct task_struct *owner;
> > } __attribute__((preserve_access_index));
> > @@ -136,6 +143,8 @@ int perf_subsys_id = -1;
> >
> > __u64 end_ts;
> >
> > +__u32 slab_cache_id;
> > +
> > /* error stat */
> > int task_fail;
> > int stack_fail;
> > @@ -563,4 +572,23 @@ int BPF_PROG(end_timestamp)
> > return 0;
> > }
> >
> > +SEC("iter/kmem_cache")
> > +int slab_cache_iter(struct bpf_iter__kmem_cache *ctx)
> > +{
> > + struct kmem_cache *s = ctx->s;
> > + struct slab_cache_data d;
> > +
> > + if (s == NULL)
> > + return 0;
> > +
> > + d.id = ++slab_cache_id << LCB_F_SLAB_ID_SHIFT;
> > + bpf_probe_read_kernel_str(d.name, sizeof(d.name), s->name);
> > +
> > + if (d.id >= LCB_F_SLAB_ID_END)
> > + return 0;
> > +
> > + bpf_map_update_elem(&slab_caches, &s, &d, BPF_NOEXIST);
> > + return 0;
> > +}
> > +
> > char LICENSE[] SEC("license") = "Dual BSD/GPL";
> > diff --git a/tools/perf/util/bpf_skel/lock_data.h b/tools/perf/util/bpf_skel/lock_data.h
> > index 4f0aae5483745dfa..c15f734d7fc4aecb 100644
> > --- a/tools/perf/util/bpf_skel/lock_data.h
> > +++ b/tools/perf/util/bpf_skel/lock_data.h
> > @@ -32,9 +32,16 @@ struct contention_task_data {
> > #define LCD_F_MMAP_LOCK (1U << 31)
> > #define LCD_F_SIGHAND_LOCK (1U << 30)
> >
> > +#define LCB_F_SLAB_ID_SHIFT 16
> > +#define LCB_F_SLAB_ID_START (1U << 16)
> > +#define LCB_F_SLAB_ID_END (1U << 26)
> > +#define LCB_F_SLAB_ID_MASK 0x03FF0000U
> > +
> > #define LCB_F_TYPE_MAX (1U << 7)
> > #define LCB_F_TYPE_MASK 0x0000007FU
> >
> > +#define SLAB_NAME_MAX 28
> > +
> > struct contention_data {
> > u64 total_time;
> > u64 min_time;
> > @@ -55,4 +62,9 @@ enum lock_class_sym {
> > LOCK_CLASS_RQLOCK,
> > };
> >
> > +struct slab_cache_data {
> > + u32 id;
> > + char name[SLAB_NAME_MAX];
> > +};
> > +
> > #endif /* UTIL_BPF_SKEL_LOCK_DATA_H */
> > diff --git a/tools/perf/util/bpf_skel/vmlinux/vmlinux.h b/tools/perf/util/bpf_skel/vmlinux/vmlinux.h
> > index 4dcad7b682bdee9c..7b81d3173917fdb5 100644
> > --- a/tools/perf/util/bpf_skel/vmlinux/vmlinux.h
> > +++ b/tools/perf/util/bpf_skel/vmlinux/vmlinux.h
> > @@ -195,4 +195,12 @@ struct bpf_perf_event_data_kern {
> > */
> > struct rq {};
> >
> > +struct kmem_cache {
> > + const char *name;
> > +} __attribute__((preserve_access_index));
> > +
> > +struct bpf_iter__kmem_cache {
> > + struct kmem_cache *s;
> > +} __attribute__((preserve_access_index));
> > +
> > #endif // __VMLINUX_H
> > --
> > 2.47.0.277.g8800431eea-goog
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 2/4] perf lock contention: Run BPF slab cache iterator
2024-12-09 16:38 ` Arnaldo Carvalho de Melo
@ 2024-12-09 20:23 ` Arnaldo Carvalho de Melo
2024-12-09 23:00 ` Andrii Nakryiko
2024-12-09 22:16 ` Namhyung Kim
1 sibling, 1 reply; 19+ messages in thread
From: Arnaldo Carvalho de Melo @ 2024-12-09 20:23 UTC (permalink / raw)
To: Namhyung Kim
Cc: Ian Rogers, Kan Liang, Jiri Olsa, Adrian Hunter, Peter Zijlstra,
Ingo Molnar, LKML, linux-perf-users, Andrii Nakryiko, Song Liu,
bpf, Stephane Eranian, Vlastimil Babka, Roman Gushchin,
Hyeonggon Yoo, Kees Cook
On Mon, Dec 09, 2024 at 01:38:39PM -0300, Arnaldo Carvalho de Melo wrote:
> On Mon, Dec 09, 2024 at 01:36:52PM -0300, Arnaldo Carvalho de Melo wrote:
> > On Thu, Nov 07, 2024 at 10:14:57PM -0800, Namhyung Kim wrote:
> > > Recently the kernel got the kmem_cache iterator to traverse metadata of
> > > slab objects. This can be used to symbolize dynamic locks in a slab.
> > > The new slab_caches hash map will have the pointer of the kmem_cache as
> > > a key and save the name and a id. The id will be saved in the flags
> > > part of the lock.
> > Trying to fix this
>
> So you have that struct in tools/perf/util/bpf_skel/vmlinux/vmlinux.h,
> but then, this kernel is old and doesn't have the kmem_cache iterator,
> so using the generated vmlinux.h will fail the build.
I tried passing the right offset to the iterator so as not to try to use
a type that isn't in vmlinux.h generated from the old kernel BTF:
+++ b/tools/perf/util/bpf_lock_contention.c
@@ -52,7 +52,7 @@ static void check_slab_cache_iter(struct lock_contention *con)
pr_debug("slab cache iterator is not available: %d\n", ret);
goto out;
} else {
- const struct btf_member *s = __btf_type__find_member_by_name(btf, ret, "s");
+ const struct btf_member *s = __btf_type__find_unnamed_union_with_member_by_name(btf, ret, "s");
if (s == NULL) {
skel->rodata->slab_cache_iter_member_offset = -1;
@@ -60,7 +60,9 @@ static void check_slab_cache_iter(struct lock_contention *con)
goto out;
}
skel->rodata->slab_cache_iter_member_offset = s->offset / 8; // bits -> bytes
+ pr_debug("slab cache iterator kmem_cache pointer offset: %d\n",
+ skel->rodata->slab_cache_iter_member_offset);
}
but the verifier doesn't like that:
; struct kmem_cache *s = slab_cache_iter_member_offset < 0 ? NULL : @ lock_contention.bpf.c:615
12: (7b) *(u64 *)(r10 -8) = r2 ; R2_w=ctx(off=8) R10=fp0 fp-8_w=ctx(off=8)
; if (s == NULL) @ lock_contention.bpf.c:619
13: (15) if r1 == 0x0 goto pc+22 ; R1=ctx()
; d.id = ++slab_cache_id << LCB_F_SLAB_ID_SHIFT; @ lock_contention.bpf.c:622
14: (18) r1 = 0xffffc14bcde3a014 ; R1_w=map_value(map=lock_con.bss,ks=4,vs=40,off=20)
16: (61) r3 = *(u32 *)(r1 +0) ; R1_w=map_value(map=lock_con.bss,ks=4,vs=40,off=20) R3_w=scalar(smin=0,smax=umax=0xffffffff,var_off=(0x0; 0xffffffff))
17: (07) r3 += 1 ; R3_w=scalar(smin=umin=1,smax=umax=0x100000000,var_off=(0x0; 0x1ffffffff))
18: (63) *(u32 *)(r1 +0) = r3 ; R1_w=map_value(map=lock_con.bss,ks=4,vs=40,off=20) R3_w=scalar(smin=umin=1,smax=umax=0x100000000,var_off=(0x0; 0x1ffffffff))
19: (67) r3 <<= 16 ; R3_w=scalar(smin=umin=0x10000,smax=umax=0x1000000000000,smax32=0x7fff0000,umax32=0xffff0000,var_off=(0x0; 0x1ffffffff0000))
20: (63) *(u32 *)(r10 -40) = r3 ; R3_w=scalar(smin=umin=0x10000,smax=umax=0x1000000000000,smax32=0x7fff0000,umax32=0xffff0000,var_off=(0x0; 0x1ffffffff0000)) R10=fp0 fp-40=????scalar(smin=umin=0x10000,smax=umax=0x1000000000000,smax32=0x7fff0000,umax32=0xffff0000,var_off=(0x0; 0x1ffffffff0000))
; bpf_probe_read_kernel_str(d.name, sizeof(d.name), s->name); @ lock_contention.bpf.c:623
21: (79) r3 = *(u64 *)(r2 +96)
dereference of modified ctx ptr R2 off=8 disallowed
processed 19 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0
-- END PROG LOAD LOG --
libbpf: prog 'slab_cache_iter': failed to load: -EACCES
libbpf: failed to load object 'lock_contention_bpf'
libbpf: failed to load BPF skeleton 'lock_contention_bpf': -EACCES
Failed to load lock-contention BPF skeleton
lock contention BPF setup failed
root@number:~#
and additionally the type is not like the one you added to the barebones
vmlinux.h:
⬢ [acme@toolbox perf-tools-next]$ git show d82e2e170d1c756b | grep 'struct bpf_iter__kmem_cache {' -A3
+struct bpf_iter__kmem_cache {
+ struct kmem_cache *s;
+} __attribute__((preserve_access_index));
+
⬢ [acme@toolbox perf-tools-next]$
But:
⬢ [acme@toolbox perf-tools-next]$ uname -a
Linux toolbox 6.13.0-rc2 #1 SMP PREEMPT_DYNAMIC Mon Dec 9 12:33:35 -03 2024 x86_64 GNU/Linux
⬢ [acme@toolbox perf-tools-next]$ pahole bpf_iter__kmem_cache
struct bpf_iter__kmem_cache {
union {
struct bpf_iter_meta * meta; /* 0 8 */
}; /* 0 8 */
union {
struct kmem_cache * s; /* 8 8 */
}; /* 8 8 */
/* size: 16, cachelines: 1, members: 2 */
/* last cacheline: 16 bytes */
};
⬢ [acme@toolbox perf-tools-next]$
Do CO-RE handle this?
- Arnaldo
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 2/4] perf lock contention: Run BPF slab cache iterator
2024-12-09 16:38 ` Arnaldo Carvalho de Melo
2024-12-09 20:23 ` Arnaldo Carvalho de Melo
@ 2024-12-09 22:16 ` Namhyung Kim
2024-12-09 22:23 ` Ian Rogers
1 sibling, 1 reply; 19+ messages in thread
From: Namhyung Kim @ 2024-12-09 22:16 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: Ian Rogers, Kan Liang, Jiri Olsa, Adrian Hunter, Peter Zijlstra,
Ingo Molnar, LKML, linux-perf-users, Andrii Nakryiko, Song Liu,
bpf, Stephane Eranian, Vlastimil Babka, Roman Gushchin,
Hyeonggon Yoo, Kees Cook
On Mon, Dec 09, 2024 at 01:38:39PM -0300, Arnaldo Carvalho de Melo wrote:
> On Mon, Dec 09, 2024 at 01:36:52PM -0300, Arnaldo Carvalho de Melo wrote:
> > On Thu, Nov 07, 2024 at 10:14:57PM -0800, Namhyung Kim wrote:
> > > Recently the kernel got the kmem_cache iterator to traverse metadata of
> > > slab objects. This can be used to symbolize dynamic locks in a slab.
> > >
> > > The new slab_caches hash map will have the pointer of the kmem_cache as
> > > a key and save the name and a id. The id will be saved in the flags
> > > part of the lock.
> >
> > Trying to fix this
>
> So you have that struct in tools/perf/util/bpf_skel/vmlinux/vmlinux.h,
> but then, this kernel is old and doesn't have the kmem_cache iterator,
> so using the generated vmlinux.h will fail the build.
Thanks for checking this. I think we handle compatibility issues by
checking BTF at runtime but this is a build-time issue. :(
I wonder if it's really needed to generate vmlinux.h for perf. Can we
simply use the minimal vmlinux.h always?
Thanks,
Namhyung
>
> > cd . && make GEN_VMLINUX_H=1 FEATURES_DUMP=/home/acme/git/perf-tools-next/tools/perf/BUILD_TEST_FEATURE_DUMP -j28 O=/tmp/tmp.DWo9tIFvWU DESTDIR=/tmp/tmp.ex3iljqLBT
> > BUILD: Doing 'make -j28' parallel build
[...]
> > GEN /tmp/tmp.DWo9tIFvWU/util/bpf_skel/vmlinux.h
> > CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bpf_prog_profiler.bpf.o
> > CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bperf_leader.bpf.o
> > CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bperf_follower.bpf.o
> > CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bperf_cgroup.bpf.o
> > CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/func_latency.bpf.o
> > CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/off_cpu.bpf.o
> > CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/lock_contention.bpf.o
> > CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/kwork_trace.bpf.o
> > CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/sample_filter.bpf.o
> > CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/kwork_top.bpf.o
> > CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bench_uprobe.bpf.o
> > CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/augmented_raw_syscalls.bpf.o
> > GENSKEL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/bench_uprobe.skel.h
> > GENSKEL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/func_latency.skel.h
> > util/bpf_skel/lock_contention.bpf.c:612:28: error: declaration of 'struct bpf_iter__kmem_cache' will not be visible outside of this function [-Werror,-Wvisibility]
> > 612 | int slab_cache_iter(struct bpf_iter__kmem_cache *ctx)
> > | ^
> > util/bpf_skel/lock_contention.bpf.c:614:28: error: incomplete definition of type 'struct bpf_iter__kmem_cache'
> > 614 | struct kmem_cache *s = ctx->s;
> > | ~~~^
> > util/bpf_skel/lock_contention.bpf.c:612:28: note: forward declaration of 'struct bpf_iter__kmem_cache'
> > 612 | int slab_cache_iter(struct bpf_iter__kmem_cache *ctx)
> > | ^
> > 2 errors generated.
> > make[4]: *** [Makefile.perf:1248: /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/lock_contention.bpf.o] Error 1
> > make[4]: *** Waiting for unfinished jobs....
> > make[3]: *** [Makefile.perf:292: sub-make] Error 2
> > make[2]: *** [Makefile:76: all] Error 2
> > make[1]: *** [tests/make:344: make_gen_vmlinux_h_O] Error 1
> > make: *** [Makefile:109: build-test] Error 2
> > make: Leaving directory '/home/acme/git/perf-tools-next/tools/perf'
> >
> > real 3m43.896s
> > user 29m30.716s
> > sys 6m36.609s
> > ⬢ [acme@toolbox perf-tools-next]$
> >
> >
> >
> > > Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> > > ---
> > > tools/perf/util/bpf_lock_contention.c | 50 +++++++++++++++++++
> > > .../perf/util/bpf_skel/lock_contention.bpf.c | 28 +++++++++++
> > > tools/perf/util/bpf_skel/lock_data.h | 12 +++++
> > > tools/perf/util/bpf_skel/vmlinux/vmlinux.h | 8 +++
> > > 4 files changed, 98 insertions(+)
> > >
> > > diff --git a/tools/perf/util/bpf_lock_contention.c b/tools/perf/util/bpf_lock_contention.c
> > > index 41a1ad08789511c3..558590c3111390fc 100644
> > > --- a/tools/perf/util/bpf_lock_contention.c
> > > +++ b/tools/perf/util/bpf_lock_contention.c
> > > @@ -12,12 +12,59 @@
> > > #include <linux/zalloc.h>
> > > #include <linux/string.h>
> > > #include <bpf/bpf.h>
> > > +#include <bpf/btf.h>
> > > #include <inttypes.h>
> > >
> > > #include "bpf_skel/lock_contention.skel.h"
> > > #include "bpf_skel/lock_data.h"
> > >
> > > static struct lock_contention_bpf *skel;
> > > +static bool has_slab_iter;
> > > +
> > > +static void check_slab_cache_iter(struct lock_contention *con)
> > > +{
> > > + struct btf *btf = btf__load_vmlinux_btf();
> > > + s32 ret;
> > > +
> > > + if (btf == NULL) {
> > > + pr_debug("BTF loading failed: %s\n", strerror(errno));
> > > + return;
> > > + }
> > > +
> > > + ret = btf__find_by_name_kind(btf, "bpf_iter__kmem_cache", BTF_KIND_STRUCT);
> > > + if (ret < 0) {
> > > + bpf_program__set_autoload(skel->progs.slab_cache_iter, false);
> > > + pr_debug("slab cache iterator is not available: %d\n", ret);
> > > + goto out;
> > > + }
> > > +
> > > + has_slab_iter = true;
> > > +
> > > + bpf_map__set_max_entries(skel->maps.slab_caches, con->map_nr_entries);
> > > +out:
> > > + btf__free(btf);
> > > +}
> > > +
> > > +static void run_slab_cache_iter(void)
> > > +{
> > > + int fd;
> > > + char buf[256];
> > > +
> > > + if (!has_slab_iter)
> > > + return;
> > > +
> > > + fd = bpf_iter_create(bpf_link__fd(skel->links.slab_cache_iter));
> > > + if (fd < 0) {
> > > + pr_debug("cannot create slab cache iter: %d\n", fd);
> > > + return;
> > > + }
> > > +
> > > + /* This will run the bpf program */
> > > + while (read(fd, buf, sizeof(buf)) > 0)
> > > + continue;
> > > +
> > > + close(fd);
> > > +}
> > >
> > > int lock_contention_prepare(struct lock_contention *con)
> > > {
> > > @@ -109,6 +156,8 @@ int lock_contention_prepare(struct lock_contention *con)
> > > skel->rodata->use_cgroup_v2 = 1;
> > > }
> > >
> > > + check_slab_cache_iter(con);
> > > +
> > > if (lock_contention_bpf__load(skel) < 0) {
> > > pr_err("Failed to load lock-contention BPF skeleton\n");
> > > return -1;
> > > @@ -304,6 +353,7 @@ static void account_end_timestamp(struct lock_contention *con)
> > >
> > > int lock_contention_start(void)
> > > {
> > > + run_slab_cache_iter();
> > > skel->bss->enabled = 1;
> > > return 0;
> > > }
> > > diff --git a/tools/perf/util/bpf_skel/lock_contention.bpf.c b/tools/perf/util/bpf_skel/lock_contention.bpf.c
> > > index 1069bda5d733887f..fd24ccb00faec0ba 100644
> > > --- a/tools/perf/util/bpf_skel/lock_contention.bpf.c
> > > +++ b/tools/perf/util/bpf_skel/lock_contention.bpf.c
> > > @@ -100,6 +100,13 @@ struct {
> > > __uint(max_entries, 1);
> > > } cgroup_filter SEC(".maps");
> > >
> > > +struct {
> > > + __uint(type, BPF_MAP_TYPE_HASH);
> > > + __uint(key_size, sizeof(long));
> > > + __uint(value_size, sizeof(struct slab_cache_data));
> > > + __uint(max_entries, 1);
> > > +} slab_caches SEC(".maps");
> > > +
> > > struct rw_semaphore___old {
> > > struct task_struct *owner;
> > > } __attribute__((preserve_access_index));
> > > @@ -136,6 +143,8 @@ int perf_subsys_id = -1;
> > >
> > > __u64 end_ts;
> > >
> > > +__u32 slab_cache_id;
> > > +
> > > /* error stat */
> > > int task_fail;
> > > int stack_fail;
> > > @@ -563,4 +572,23 @@ int BPF_PROG(end_timestamp)
> > > return 0;
> > > }
> > >
> > > +SEC("iter/kmem_cache")
> > > +int slab_cache_iter(struct bpf_iter__kmem_cache *ctx)
> > > +{
> > > + struct kmem_cache *s = ctx->s;
> > > + struct slab_cache_data d;
> > > +
> > > + if (s == NULL)
> > > + return 0;
> > > +
> > > + d.id = ++slab_cache_id << LCB_F_SLAB_ID_SHIFT;
> > > + bpf_probe_read_kernel_str(d.name, sizeof(d.name), s->name);
> > > +
> > > + if (d.id >= LCB_F_SLAB_ID_END)
> > > + return 0;
> > > +
> > > + bpf_map_update_elem(&slab_caches, &s, &d, BPF_NOEXIST);
> > > + return 0;
> > > +}
> > > +
> > > char LICENSE[] SEC("license") = "Dual BSD/GPL";
> > > diff --git a/tools/perf/util/bpf_skel/lock_data.h b/tools/perf/util/bpf_skel/lock_data.h
> > > index 4f0aae5483745dfa..c15f734d7fc4aecb 100644
> > > --- a/tools/perf/util/bpf_skel/lock_data.h
> > > +++ b/tools/perf/util/bpf_skel/lock_data.h
> > > @@ -32,9 +32,16 @@ struct contention_task_data {
> > > #define LCD_F_MMAP_LOCK (1U << 31)
> > > #define LCD_F_SIGHAND_LOCK (1U << 30)
> > >
> > > +#define LCB_F_SLAB_ID_SHIFT 16
> > > +#define LCB_F_SLAB_ID_START (1U << 16)
> > > +#define LCB_F_SLAB_ID_END (1U << 26)
> > > +#define LCB_F_SLAB_ID_MASK 0x03FF0000U
> > > +
> > > #define LCB_F_TYPE_MAX (1U << 7)
> > > #define LCB_F_TYPE_MASK 0x0000007FU
> > >
> > > +#define SLAB_NAME_MAX 28
> > > +
> > > struct contention_data {
> > > u64 total_time;
> > > u64 min_time;
> > > @@ -55,4 +62,9 @@ enum lock_class_sym {
> > > LOCK_CLASS_RQLOCK,
> > > };
> > >
> > > +struct slab_cache_data {
> > > + u32 id;
> > > + char name[SLAB_NAME_MAX];
> > > +};
> > > +
> > > #endif /* UTIL_BPF_SKEL_LOCK_DATA_H */
> > > diff --git a/tools/perf/util/bpf_skel/vmlinux/vmlinux.h b/tools/perf/util/bpf_skel/vmlinux/vmlinux.h
> > > index 4dcad7b682bdee9c..7b81d3173917fdb5 100644
> > > --- a/tools/perf/util/bpf_skel/vmlinux/vmlinux.h
> > > +++ b/tools/perf/util/bpf_skel/vmlinux/vmlinux.h
> > > @@ -195,4 +195,12 @@ struct bpf_perf_event_data_kern {
> > > */
> > > struct rq {};
> > >
> > > +struct kmem_cache {
> > > + const char *name;
> > > +} __attribute__((preserve_access_index));
> > > +
> > > +struct bpf_iter__kmem_cache {
> > > + struct kmem_cache *s;
> > > +} __attribute__((preserve_access_index));
> > > +
> > > #endif // __VMLINUX_H
> > > --
> > > 2.47.0.277.g8800431eea-goog
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 2/4] perf lock contention: Run BPF slab cache iterator
2024-12-09 22:16 ` Namhyung Kim
@ 2024-12-09 22:23 ` Ian Rogers
0 siblings, 0 replies; 19+ messages in thread
From: Ian Rogers @ 2024-12-09 22:23 UTC (permalink / raw)
To: Namhyung Kim
Cc: Arnaldo Carvalho de Melo, Kan Liang, Jiri Olsa, Adrian Hunter,
Peter Zijlstra, Ingo Molnar, LKML, linux-perf-users,
Andrii Nakryiko, Song Liu, bpf, Stephane Eranian, Vlastimil Babka,
Roman Gushchin, Hyeonggon Yoo, Kees Cook
On Mon, Dec 9, 2024 at 2:16 PM Namhyung Kim <namhyung@kernel.org> wrote:
>
> On Mon, Dec 09, 2024 at 01:38:39PM -0300, Arnaldo Carvalho de Melo wrote:
> > On Mon, Dec 09, 2024 at 01:36:52PM -0300, Arnaldo Carvalho de Melo wrote:
> > > On Thu, Nov 07, 2024 at 10:14:57PM -0800, Namhyung Kim wrote:
> > > > Recently the kernel got the kmem_cache iterator to traverse metadata of
> > > > slab objects. This can be used to symbolize dynamic locks in a slab.
> > > >
> > > > The new slab_caches hash map will have the pointer of the kmem_cache as
> > > > a key and save the name and a id. The id will be saved in the flags
> > > > part of the lock.
> > >
> > > Trying to fix this
> >
> > So you have that struct in tools/perf/util/bpf_skel/vmlinux/vmlinux.h,
> > but then, this kernel is old and doesn't have the kmem_cache iterator,
> > so using the generated vmlinux.h will fail the build.
>
> Thanks for checking this. I think we handle compatibility issues by
> checking BTF at runtime but this is a build-time issue. :(
>
> I wonder if it's really needed to generate vmlinux.h for perf. Can we
> simply use the minimal vmlinux.h always?
Agreed, it shouldn't be necessary. There are certain compilation
errors that will happen with a generated one that can't happen with
the minimal. They could be indicative of bugs, like a renamed struct.
Thanks,
Ian
> >
> > > cd . && make GEN_VMLINUX_H=1 FEATURES_DUMP=/home/acme/git/perf-tools-next/tools/perf/BUILD_TEST_FEATURE_DUMP -j28 O=/tmp/tmp.DWo9tIFvWU DESTDIR=/tmp/tmp.ex3iljqLBT
> > > BUILD: Doing 'make -j28' parallel build
> [...]
> > > GEN /tmp/tmp.DWo9tIFvWU/util/bpf_skel/vmlinux.h
> > > CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bpf_prog_profiler.bpf.o
> > > CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bperf_leader.bpf.o
> > > CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bperf_follower.bpf.o
> > > CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bperf_cgroup.bpf.o
> > > CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/func_latency.bpf.o
> > > CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/off_cpu.bpf.o
> > > CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/lock_contention.bpf.o
> > > CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/kwork_trace.bpf.o
> > > CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/sample_filter.bpf.o
> > > CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/kwork_top.bpf.o
> > > CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/bench_uprobe.bpf.o
> > > CLANG /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/augmented_raw_syscalls.bpf.o
> > > GENSKEL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/bench_uprobe.skel.h
> > > GENSKEL /tmp/tmp.DWo9tIFvWU/util/bpf_skel/func_latency.skel.h
> > > util/bpf_skel/lock_contention.bpf.c:612:28: error: declaration of 'struct bpf_iter__kmem_cache' will not be visible outside of this function [-Werror,-Wvisibility]
> > > 612 | int slab_cache_iter(struct bpf_iter__kmem_cache *ctx)
> > > | ^
> > > util/bpf_skel/lock_contention.bpf.c:614:28: error: incomplete definition of type 'struct bpf_iter__kmem_cache'
> > > 614 | struct kmem_cache *s = ctx->s;
> > > | ~~~^
> > > util/bpf_skel/lock_contention.bpf.c:612:28: note: forward declaration of 'struct bpf_iter__kmem_cache'
> > > 612 | int slab_cache_iter(struct bpf_iter__kmem_cache *ctx)
> > > | ^
> > > 2 errors generated.
> > > make[4]: *** [Makefile.perf:1248: /tmp/tmp.DWo9tIFvWU/util/bpf_skel/.tmp/lock_contention.bpf.o] Error 1
> > > make[4]: *** Waiting for unfinished jobs....
> > > make[3]: *** [Makefile.perf:292: sub-make] Error 2
> > > make[2]: *** [Makefile:76: all] Error 2
> > > make[1]: *** [tests/make:344: make_gen_vmlinux_h_O] Error 1
> > > make: *** [Makefile:109: build-test] Error 2
> > > make: Leaving directory '/home/acme/git/perf-tools-next/tools/perf'
> > >
> > > real 3m43.896s
> > > user 29m30.716s
> > > sys 6m36.609s
> > > ⬢ [acme@toolbox perf-tools-next]$
> > >
> > >
> > >
> > > > Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> > > > ---
> > > > tools/perf/util/bpf_lock_contention.c | 50 +++++++++++++++++++
> > > > .../perf/util/bpf_skel/lock_contention.bpf.c | 28 +++++++++++
> > > > tools/perf/util/bpf_skel/lock_data.h | 12 +++++
> > > > tools/perf/util/bpf_skel/vmlinux/vmlinux.h | 8 +++
> > > > 4 files changed, 98 insertions(+)
> > > >
> > > > diff --git a/tools/perf/util/bpf_lock_contention.c b/tools/perf/util/bpf_lock_contention.c
> > > > index 41a1ad08789511c3..558590c3111390fc 100644
> > > > --- a/tools/perf/util/bpf_lock_contention.c
> > > > +++ b/tools/perf/util/bpf_lock_contention.c
> > > > @@ -12,12 +12,59 @@
> > > > #include <linux/zalloc.h>
> > > > #include <linux/string.h>
> > > > #include <bpf/bpf.h>
> > > > +#include <bpf/btf.h>
> > > > #include <inttypes.h>
> > > >
> > > > #include "bpf_skel/lock_contention.skel.h"
> > > > #include "bpf_skel/lock_data.h"
> > > >
> > > > static struct lock_contention_bpf *skel;
> > > > +static bool has_slab_iter;
> > > > +
> > > > +static void check_slab_cache_iter(struct lock_contention *con)
> > > > +{
> > > > + struct btf *btf = btf__load_vmlinux_btf();
> > > > + s32 ret;
> > > > +
> > > > + if (btf == NULL) {
> > > > + pr_debug("BTF loading failed: %s\n", strerror(errno));
> > > > + return;
> > > > + }
> > > > +
> > > > + ret = btf__find_by_name_kind(btf, "bpf_iter__kmem_cache", BTF_KIND_STRUCT);
> > > > + if (ret < 0) {
> > > > + bpf_program__set_autoload(skel->progs.slab_cache_iter, false);
> > > > + pr_debug("slab cache iterator is not available: %d\n", ret);
> > > > + goto out;
> > > > + }
> > > > +
> > > > + has_slab_iter = true;
> > > > +
> > > > + bpf_map__set_max_entries(skel->maps.slab_caches, con->map_nr_entries);
> > > > +out:
> > > > + btf__free(btf);
> > > > +}
> > > > +
> > > > +static void run_slab_cache_iter(void)
> > > > +{
> > > > + int fd;
> > > > + char buf[256];
> > > > +
> > > > + if (!has_slab_iter)
> > > > + return;
> > > > +
> > > > + fd = bpf_iter_create(bpf_link__fd(skel->links.slab_cache_iter));
> > > > + if (fd < 0) {
> > > > + pr_debug("cannot create slab cache iter: %d\n", fd);
> > > > + return;
> > > > + }
> > > > +
> > > > + /* This will run the bpf program */
> > > > + while (read(fd, buf, sizeof(buf)) > 0)
> > > > + continue;
> > > > +
> > > > + close(fd);
> > > > +}
> > > >
> > > > int lock_contention_prepare(struct lock_contention *con)
> > > > {
> > > > @@ -109,6 +156,8 @@ int lock_contention_prepare(struct lock_contention *con)
> > > > skel->rodata->use_cgroup_v2 = 1;
> > > > }
> > > >
> > > > + check_slab_cache_iter(con);
> > > > +
> > > > if (lock_contention_bpf__load(skel) < 0) {
> > > > pr_err("Failed to load lock-contention BPF skeleton\n");
> > > > return -1;
> > > > @@ -304,6 +353,7 @@ static void account_end_timestamp(struct lock_contention *con)
> > > >
> > > > int lock_contention_start(void)
> > > > {
> > > > + run_slab_cache_iter();
> > > > skel->bss->enabled = 1;
> > > > return 0;
> > > > }
> > > > diff --git a/tools/perf/util/bpf_skel/lock_contention.bpf.c b/tools/perf/util/bpf_skel/lock_contention.bpf.c
> > > > index 1069bda5d733887f..fd24ccb00faec0ba 100644
> > > > --- a/tools/perf/util/bpf_skel/lock_contention.bpf.c
> > > > +++ b/tools/perf/util/bpf_skel/lock_contention.bpf.c
> > > > @@ -100,6 +100,13 @@ struct {
> > > > __uint(max_entries, 1);
> > > > } cgroup_filter SEC(".maps");
> > > >
> > > > +struct {
> > > > + __uint(type, BPF_MAP_TYPE_HASH);
> > > > + __uint(key_size, sizeof(long));
> > > > + __uint(value_size, sizeof(struct slab_cache_data));
> > > > + __uint(max_entries, 1);
> > > > +} slab_caches SEC(".maps");
> > > > +
> > > > struct rw_semaphore___old {
> > > > struct task_struct *owner;
> > > > } __attribute__((preserve_access_index));
> > > > @@ -136,6 +143,8 @@ int perf_subsys_id = -1;
> > > >
> > > > __u64 end_ts;
> > > >
> > > > +__u32 slab_cache_id;
> > > > +
> > > > /* error stat */
> > > > int task_fail;
> > > > int stack_fail;
> > > > @@ -563,4 +572,23 @@ int BPF_PROG(end_timestamp)
> > > > return 0;
> > > > }
> > > >
> > > > +SEC("iter/kmem_cache")
> > > > +int slab_cache_iter(struct bpf_iter__kmem_cache *ctx)
> > > > +{
> > > > + struct kmem_cache *s = ctx->s;
> > > > + struct slab_cache_data d;
> > > > +
> > > > + if (s == NULL)
> > > > + return 0;
> > > > +
> > > > + d.id = ++slab_cache_id << LCB_F_SLAB_ID_SHIFT;
> > > > + bpf_probe_read_kernel_str(d.name, sizeof(d.name), s->name);
> > > > +
> > > > + if (d.id >= LCB_F_SLAB_ID_END)
> > > > + return 0;
> > > > +
> > > > + bpf_map_update_elem(&slab_caches, &s, &d, BPF_NOEXIST);
> > > > + return 0;
> > > > +}
> > > > +
> > > > char LICENSE[] SEC("license") = "Dual BSD/GPL";
> > > > diff --git a/tools/perf/util/bpf_skel/lock_data.h b/tools/perf/util/bpf_skel/lock_data.h
> > > > index 4f0aae5483745dfa..c15f734d7fc4aecb 100644
> > > > --- a/tools/perf/util/bpf_skel/lock_data.h
> > > > +++ b/tools/perf/util/bpf_skel/lock_data.h
> > > > @@ -32,9 +32,16 @@ struct contention_task_data {
> > > > #define LCD_F_MMAP_LOCK (1U << 31)
> > > > #define LCD_F_SIGHAND_LOCK (1U << 30)
> > > >
> > > > +#define LCB_F_SLAB_ID_SHIFT 16
> > > > +#define LCB_F_SLAB_ID_START (1U << 16)
> > > > +#define LCB_F_SLAB_ID_END (1U << 26)
> > > > +#define LCB_F_SLAB_ID_MASK 0x03FF0000U
> > > > +
> > > > #define LCB_F_TYPE_MAX (1U << 7)
> > > > #define LCB_F_TYPE_MASK 0x0000007FU
> > > >
> > > > +#define SLAB_NAME_MAX 28
> > > > +
> > > > struct contention_data {
> > > > u64 total_time;
> > > > u64 min_time;
> > > > @@ -55,4 +62,9 @@ enum lock_class_sym {
> > > > LOCK_CLASS_RQLOCK,
> > > > };
> > > >
> > > > +struct slab_cache_data {
> > > > + u32 id;
> > > > + char name[SLAB_NAME_MAX];
> > > > +};
> > > > +
> > > > #endif /* UTIL_BPF_SKEL_LOCK_DATA_H */
> > > > diff --git a/tools/perf/util/bpf_skel/vmlinux/vmlinux.h b/tools/perf/util/bpf_skel/vmlinux/vmlinux.h
> > > > index 4dcad7b682bdee9c..7b81d3173917fdb5 100644
> > > > --- a/tools/perf/util/bpf_skel/vmlinux/vmlinux.h
> > > > +++ b/tools/perf/util/bpf_skel/vmlinux/vmlinux.h
> > > > @@ -195,4 +195,12 @@ struct bpf_perf_event_data_kern {
> > > > */
> > > > struct rq {};
> > > >
> > > > +struct kmem_cache {
> > > > + const char *name;
> > > > +} __attribute__((preserve_access_index));
> > > > +
> > > > +struct bpf_iter__kmem_cache {
> > > > + struct kmem_cache *s;
> > > > +} __attribute__((preserve_access_index));
> > > > +
> > > > #endif // __VMLINUX_H
> > > > --
> > > > 2.47.0.277.g8800431eea-goog
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 2/4] perf lock contention: Run BPF slab cache iterator
2024-12-09 20:23 ` Arnaldo Carvalho de Melo
@ 2024-12-09 23:00 ` Andrii Nakryiko
[not found] ` <CA+JHD91Ai_ObUye4Unz2e2Hku2BH5_+0q3HyUtf7ay23uDnkjQ@mail.gmail.com>
0 siblings, 1 reply; 19+ messages in thread
From: Andrii Nakryiko @ 2024-12-09 23:00 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: Namhyung Kim, Ian Rogers, Kan Liang, Jiri Olsa, Adrian Hunter,
Peter Zijlstra, Ingo Molnar, LKML, linux-perf-users,
Andrii Nakryiko, Song Liu, bpf, Stephane Eranian, Vlastimil Babka,
Roman Gushchin, Hyeonggon Yoo, Kees Cook
On Mon, Dec 9, 2024 at 12:23 PM Arnaldo Carvalho de Melo
<acme@kernel.org> wrote:
>
> On Mon, Dec 09, 2024 at 01:38:39PM -0300, Arnaldo Carvalho de Melo wrote:
> > On Mon, Dec 09, 2024 at 01:36:52PM -0300, Arnaldo Carvalho de Melo wrote:
> > > On Thu, Nov 07, 2024 at 10:14:57PM -0800, Namhyung Kim wrote:
> > > > Recently the kernel got the kmem_cache iterator to traverse metadata of
> > > > slab objects. This can be used to symbolize dynamic locks in a slab.
>
> > > > The new slab_caches hash map will have the pointer of the kmem_cache as
> > > > a key and save the name and a id. The id will be saved in the flags
> > > > part of the lock.
>
> > > Trying to fix this
> >
> > So you have that struct in tools/perf/util/bpf_skel/vmlinux/vmlinux.h,
> > but then, this kernel is old and doesn't have the kmem_cache iterator,
> > so using the generated vmlinux.h will fail the build.
>
> I tried passing the right offset to the iterator so as not to try to use
> a type that isn't in vmlinux.h generated from the old kernel BTF:
>
> +++ b/tools/perf/util/bpf_lock_contention.c
> @@ -52,7 +52,7 @@ static void check_slab_cache_iter(struct lock_contention *con)
> pr_debug("slab cache iterator is not available: %d\n", ret);
> goto out;
> } else {
> - const struct btf_member *s = __btf_type__find_member_by_name(btf, ret, "s");
> + const struct btf_member *s = __btf_type__find_unnamed_union_with_member_by_name(btf, ret, "s");
>
> if (s == NULL) {
> skel->rodata->slab_cache_iter_member_offset = -1;
> @@ -60,7 +60,9 @@ static void check_slab_cache_iter(struct lock_contention *con)
> goto out;
> }
>
> skel->rodata->slab_cache_iter_member_offset = s->offset / 8; // bits -> bytes
> + pr_debug("slab cache iterator kmem_cache pointer offset: %d\n",
> + skel->rodata->slab_cache_iter_member_offset);
> }
>
>
> but the verifier doesn't like that:
>
> ; struct kmem_cache *s = slab_cache_iter_member_offset < 0 ? NULL : @ lock_contention.bpf.c:615
> 12: (7b) *(u64 *)(r10 -8) = r2 ; R2_w=ctx(off=8) R10=fp0 fp-8_w=ctx(off=8)
> ; if (s == NULL) @ lock_contention.bpf.c:619
> 13: (15) if r1 == 0x0 goto pc+22 ; R1=ctx()
> ; d.id = ++slab_cache_id << LCB_F_SLAB_ID_SHIFT; @ lock_contention.bpf.c:622
> 14: (18) r1 = 0xffffc14bcde3a014 ; R1_w=map_value(map=lock_con.bss,ks=4,vs=40,off=20)
> 16: (61) r3 = *(u32 *)(r1 +0) ; R1_w=map_value(map=lock_con.bss,ks=4,vs=40,off=20) R3_w=scalar(smin=0,smax=umax=0xffffffff,var_off=(0x0; 0xffffffff))
> 17: (07) r3 += 1 ; R3_w=scalar(smin=umin=1,smax=umax=0x100000000,var_off=(0x0; 0x1ffffffff))
> 18: (63) *(u32 *)(r1 +0) = r3 ; R1_w=map_value(map=lock_con.bss,ks=4,vs=40,off=20) R3_w=scalar(smin=umin=1,smax=umax=0x100000000,var_off=(0x0; 0x1ffffffff))
> 19: (67) r3 <<= 16 ; R3_w=scalar(smin=umin=0x10000,smax=umax=0x1000000000000,smax32=0x7fff0000,umax32=0xffff0000,var_off=(0x0; 0x1ffffffff0000))
> 20: (63) *(u32 *)(r10 -40) = r3 ; R3_w=scalar(smin=umin=0x10000,smax=umax=0x1000000000000,smax32=0x7fff0000,umax32=0xffff0000,var_off=(0x0; 0x1ffffffff0000)) R10=fp0 fp-40=????scalar(smin=umin=0x10000,smax=umax=0x1000000000000,smax32=0x7fff0000,umax32=0xffff0000,var_off=(0x0; 0x1ffffffff0000))
> ; bpf_probe_read_kernel_str(d.name, sizeof(d.name), s->name); @ lock_contention.bpf.c:623
> 21: (79) r3 = *(u64 *)(r2 +96)
> dereference of modified ctx ptr R2 off=8 disallowed
> processed 19 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0
> -- END PROG LOAD LOG --
> libbpf: prog 'slab_cache_iter': failed to load: -EACCES
> libbpf: failed to load object 'lock_contention_bpf'
> libbpf: failed to load BPF skeleton 'lock_contention_bpf': -EACCES
> Failed to load lock-contention BPF skeleton
> lock contention BPF setup failed
> root@number:~#
>
> and additionally the type is not like the one you added to the barebones
> vmlinux.h:
>
> ⬢ [acme@toolbox perf-tools-next]$ git show d82e2e170d1c756b | grep 'struct bpf_iter__kmem_cache {' -A3
> +struct bpf_iter__kmem_cache {
> + struct kmem_cache *s;
> +} __attribute__((preserve_access_index));
> +
> ⬢ [acme@toolbox perf-tools-next]$
>
> But:
>
> ⬢ [acme@toolbox perf-tools-next]$ uname -a
> Linux toolbox 6.13.0-rc2 #1 SMP PREEMPT_DYNAMIC Mon Dec 9 12:33:35 -03 2024 x86_64 GNU/Linux
> ⬢ [acme@toolbox perf-tools-next]$ pahole bpf_iter__kmem_cache
> struct bpf_iter__kmem_cache {
> union {
> struct bpf_iter_meta * meta; /* 0 8 */
> }; /* 0 8 */
> union {
> struct kmem_cache * s; /* 8 8 */
> }; /* 8 8 */
>
> /* size: 16, cachelines: 1, members: 2 */
> /* last cacheline: 16 bytes */
> };
>
> ⬢ [acme@toolbox perf-tools-next]$
>
> Do CO-RE handle this?
>
I don't know exactly what the problem you are running into is, but
yes, BPF CO-RE allows handling missing fields, incompatible field type
changes, field renames, etc. All without having to break a
compilation. See [0] (and one subsection after that) for
"documentation" and examples.
[0] https://nakryiko.com/posts/bpf-core-reference-guide/#defining-own-co-re-relocatable-type-definitions
> - Arnaldo
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 2/4] perf lock contention: Run BPF slab cache iterator
[not found] ` <CA+JHD91Ai_ObUye4Unz2e2Hku2BH5_+0q3HyUtf7ay23uDnkjQ@mail.gmail.com>
@ 2024-12-10 0:23 ` Andrii Nakryiko
0 siblings, 0 replies; 19+ messages in thread
From: Andrii Nakryiko @ 2024-12-10 0:23 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: Arnaldo Carvalho de Melo, Namhyung Kim, Ian Rogers, Kan Liang,
Jiri Olsa, Adrian Hunter, Peter Zijlstra, Ingo Molnar, LKML,
linux-perf-users, Andrii Nakryiko, Song Liu, bpf,
Stephane Eranian, Vlastimil Babka, Roman Gushchin, Hyeonggon Yoo,
Kees Cook
On Mon, Dec 9, 2024 at 3:33 PM Arnaldo Carvalho de Melo
<arnaldo.melo@gmail.com> wrote:
>
> On Mon, Dec 9, 2024, 8:00 PM Andrii Nakryiko <andrii.nakryiko@gmail.com> wrote:
>>
>> On Mon, Dec 9, 2024 at 12:23 PM Arnaldo Carvalho de Melo
>> <acme@kernel.org> wrote:
>>
>> > and additionally the type is not like the one you added to the barebones
>> > vmlinux.h:
>>
>> > ⬢ [acme@toolbox perf-tools-next]$ git show d82e2e170d1c756b | grep 'struct bpf_iter__kmem_cache {' -A3
>> > +struct bpf_iter__kmem_cache {
>> > + struct kmem_cache *s;
>> > +} __attribute__((preserve_access_index));
>> > +
>> > ⬢ [acme@toolbox perf-tools-next]$
>>
>> > But:
>>
>> > ⬢ [acme@toolbox perf-tools-next]$ uname -a
>> > Linux toolbox 6.13.0-rc2 #1 SMP PREEMPT_DYNAMIC Mon Dec 9 12:33:35 -03 2024 x86_64 GNU/Linux
>> > ⬢ [acme@toolbox perf-tools-next]$ pahole bpf_iter__kmem_cache
>> > struct bpf_iter__kmem_cache {
>> > union {
>> > struct bpf_iter_meta * meta; /* 0 8 */
>> > }; /* 0 8 */
>> > union {
>> > struct kmem_cache * s; /* 8 8 */
>> > }; /* 8 8 */
>> >
>> > /* size: 16, cachelines: 1, members: 2 */
>> > /* last cacheline: 16 bytes */
>> > };
>>
>> > ⬢ [acme@toolbox perf-tools-next]$
>>
>> > Do CO-RE handle this?
>>
>> I don't know exactly what the problem you are running into is, but
>> yes, BPF CO-RE allows handling missing fields, incompatible field type
>> changes, field renames, etc. All without having to break a
>> compilation. See [0] (and one subsection after that) for
>> "documentation" and examples.
>>
>> [0] https://nakryiko.com/posts/bpf-core-reference-guide/#defining-own-co-re-relocatable-type-definitions
>
>
>>
> The doubt is the extra layer of unnamed unions in the BTF for the kernel that's not present in the minimal representation shipped with perf.
anonymous unions or structs are transparent to BPF CO-RE relocation,
so that shouldn't be a problem
>
> - Arnaldo
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 0/4] perf lock contention: Symbolize locks using slab cache names
2024-11-18 18:35 ` Namhyung Kim
@ 2024-12-13 17:10 ` Namhyung Kim
0 siblings, 0 replies; 19+ messages in thread
From: Namhyung Kim @ 2024-12-13 17:10 UTC (permalink / raw)
To: Ian Rogers
Cc: Arnaldo Carvalho de Melo, Kan Liang, Jiri Olsa, Adrian Hunter,
Peter Zijlstra, Ingo Molnar, LKML, linux-perf-users,
Andrii Nakryiko, Song Liu, bpf, Stephane Eranian, Vlastimil Babka,
Roman Gushchin, Hyeonggon Yoo, Kees Cook
Hello,
On Mon, Nov 18, 2024 at 10:35:43AM -0800, Namhyung Kim wrote:
> On Mon, Nov 11, 2024 at 11:46:37AM -0800, Ian Rogers wrote:
> > On Thu, Nov 7, 2024 at 10:15 PM Namhyung Kim <namhyung@kernel.org> wrote:
> > >
> > > Hello,
> > >
> > > This is to support symbolization of dynamic locks using slab
> > > allocator's metadata. The kernel support is in the bpf-next tree now.
> > >
> > > It provides the new "kmem_cache" BPF iterator and "bpf_get_kmem_cache"
> > > kfunc to get the information from an address. The feature detection is
> > > done using BTF type info and it won't have any effect on old kernels.
> > >
> > > v2 changes)
> > >
> > > * don't use libbpf_get_error() (Andrii)
> > >
> > > v1) https://lore.kernel.org/linux-perf-users/20241105172635.2463800-1-namhyung@kernel.org
> > >
> > > With this change, it can show locks in a slab object like below. I
> > > added "&" sign to distinguish them from global locks.
> >
> > I know the & is intentional but I worry it could later complicate
> > parsing of filters. Perhaps @ is a viable alternative. Other than
> > that:
> >
> > Acked-by: Ian Rogers <irogers@google.com>
>
> Thanks for the review!
>
> I don't think it clashes with BPF sample filters which works on sample
> data generated from a perf_event. Technically this command doesn't use
> perf_event and just attaches the BPF program to tracepoint directly.
>
> Also sample filters don't use '&' symbol in the syntax as of now. :)
Can we merge this series if no more feedback?
About the build issue, I think it's transient and it's not the default
to build with generated vmlinux.h. We could disable the generation but
it might be better to keep it to test other issues. Anyway, it can be
done independently.
Thanks,
Namhyung
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2024-12-13 17:10 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-11-08 6:14 [PATCH v2 0/4] perf lock contention: Symbolize locks using slab cache names Namhyung Kim
2024-11-08 6:14 ` [PATCH v2 1/4] perf lock contention: Add and use LCB_F_TYPE_MASK Namhyung Kim
2024-11-08 6:14 ` [PATCH v2 2/4] perf lock contention: Run BPF slab cache iterator Namhyung Kim
2024-12-09 16:36 ` Arnaldo Carvalho de Melo
2024-12-09 16:38 ` Arnaldo Carvalho de Melo
2024-12-09 20:23 ` Arnaldo Carvalho de Melo
2024-12-09 23:00 ` Andrii Nakryiko
[not found] ` <CA+JHD91Ai_ObUye4Unz2e2Hku2BH5_+0q3HyUtf7ay23uDnkjQ@mail.gmail.com>
2024-12-10 0:23 ` Andrii Nakryiko
2024-12-09 22:16 ` Namhyung Kim
2024-12-09 22:23 ` Ian Rogers
2024-11-08 6:14 ` [PATCH v2 3/4] perf lock contention: Resolve slab object name using BPF Namhyung Kim
2024-11-12 11:09 ` Vlastimil Babka
2024-11-12 14:50 ` Arnaldo Carvalho de Melo
2024-11-13 14:20 ` Vlastimil Babka
2024-11-18 18:45 ` Namhyung Kim
2024-11-08 6:14 ` [PATCH v2 4/4] perf lock contention: Handle slab objects in -L/--lock-filter option Namhyung Kim
2024-11-11 19:46 ` [PATCH v2 0/4] perf lock contention: Symbolize locks using slab cache names Ian Rogers
2024-11-18 18:35 ` Namhyung Kim
2024-12-13 17:10 ` Namhyung Kim
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).