Skip to content

Commit 5c4aa75

Browse files
captain5050smb49
authored andcommitted
perf env: Avoid recursively taking env->bpf_progs.lock
BugLink: https://bugs.launchpad.net/bugs/2055145 [ Upstream commit 9c51f87 ] Add variants of perf_env__insert_bpf_prog_info(), perf_env__insert_btf() and perf_env__find_btf prefixed with __ to indicate the env->bpf_progs.lock is assumed held. Call these variants when the lock is held to avoid recursively taking it and potentially having a thread deadlock with itself. Fixes: f8dfeae ("perf bpf: Show more BPF program info in print_bpf_prog_info()") Signed-off-by: Ian Rogers <irogers@google.com> Acked-by: Jiri Olsa <jolsa@kernel.org> Acked-by: Song Liu <song@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Huacai Chen <chenhuacai@kernel.org> Cc: Ingo Molnar <mingo@redhat.com> Cc: K Prateek Nayak <kprateek.nayak@amd.com> Cc: Kan Liang <kan.liang@linux.intel.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Ming Wang <wangming01@loongson.cn> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ravi Bangoria <ravi.bangoria@amd.com> Link: https://lore.kernel.org/r/20231207014655.1252484-1-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Manuel Diewald <manuel.diewald@canonical.com> Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
1 parent 41c7c21 commit 5c4aa75

File tree

5 files changed

+50
-32
lines changed

5 files changed

+50
-32
lines changed

tools/perf/util/bpf-event.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -554,9 +554,9 @@ int evlist__add_bpf_sb_event(struct evlist *evlist, struct perf_env *env)
554554
return evlist__add_sb_event(evlist, &attr, bpf_event__sb_cb, env);
555555
}
556556

557-
void bpf_event__print_bpf_prog_info(struct bpf_prog_info *info,
558-
struct perf_env *env,
559-
FILE *fp)
557+
void __bpf_event__print_bpf_prog_info(struct bpf_prog_info *info,
558+
struct perf_env *env,
559+
FILE *fp)
560560
{
561561
__u32 *prog_lens = (__u32 *)(uintptr_t)(info->jited_func_lens);
562562
__u64 *prog_addrs = (__u64 *)(uintptr_t)(info->jited_ksyms);
@@ -572,7 +572,7 @@ void bpf_event__print_bpf_prog_info(struct bpf_prog_info *info,
572572
if (info->btf_id) {
573573
struct btf_node *node;
574574

575-
node = perf_env__find_btf(env, info->btf_id);
575+
node = __perf_env__find_btf(env, info->btf_id);
576576
if (node)
577577
btf = btf__new((__u8 *)(node->data),
578578
node->data_size);

tools/perf/util/bpf-event.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ struct btf_node {
3434
int machine__process_bpf(struct machine *machine, union perf_event *event,
3535
struct perf_sample *sample);
3636
int evlist__add_bpf_sb_event(struct evlist *evlist, struct perf_env *env);
37-
void bpf_event__print_bpf_prog_info(struct bpf_prog_info *info,
38-
struct perf_env *env,
39-
FILE *fp);
37+
void __bpf_event__print_bpf_prog_info(struct bpf_prog_info *info,
38+
struct perf_env *env,
39+
FILE *fp);
4040
#else
4141
static inline int machine__process_bpf(struct machine *machine __maybe_unused,
4242
union perf_event *event __maybe_unused,
@@ -51,9 +51,9 @@ static inline int evlist__add_bpf_sb_event(struct evlist *evlist __maybe_unused,
5151
return 0;
5252
}
5353

54-
static inline void bpf_event__print_bpf_prog_info(struct bpf_prog_info *info __maybe_unused,
55-
struct perf_env *env __maybe_unused,
56-
FILE *fp __maybe_unused)
54+
static inline void __bpf_event__print_bpf_prog_info(struct bpf_prog_info *info __maybe_unused,
55+
struct perf_env *env __maybe_unused,
56+
FILE *fp __maybe_unused)
5757
{
5858

5959
}

tools/perf/util/env.c

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,19 @@ struct perf_env perf_env;
2020

2121
void perf_env__insert_bpf_prog_info(struct perf_env *env,
2222
struct bpf_prog_info_node *info_node)
23+
{
24+
down_write(&env->bpf_progs.lock);
25+
__perf_env__insert_bpf_prog_info(env, info_node);
26+
up_write(&env->bpf_progs.lock);
27+
}
28+
29+
void __perf_env__insert_bpf_prog_info(struct perf_env *env, struct bpf_prog_info_node *info_node)
2330
{
2431
__u32 prog_id = info_node->info_linear->info.id;
2532
struct bpf_prog_info_node *node;
2633
struct rb_node *parent = NULL;
2734
struct rb_node **p;
2835

29-
down_write(&env->bpf_progs.lock);
3036
p = &env->bpf_progs.infos.rb_node;
3137

3238
while (*p != NULL) {
@@ -38,15 +44,13 @@ void perf_env__insert_bpf_prog_info(struct perf_env *env,
3844
p = &(*p)->rb_right;
3945
} else {
4046
pr_debug("duplicated bpf prog info %u\n", prog_id);
41-
goto out;
47+
return;
4248
}
4349
}
4450

4551
rb_link_node(&info_node->rb_node, parent, p);
4652
rb_insert_color(&info_node->rb_node, &env->bpf_progs.infos);
4753
env->bpf_progs.infos_cnt++;
48-
out:
49-
up_write(&env->bpf_progs.lock);
5054
}
5155

5256
struct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env,
@@ -75,14 +79,22 @@ struct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env,
7579
}
7680

7781
bool perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node)
82+
{
83+
bool ret;
84+
85+
down_write(&env->bpf_progs.lock);
86+
ret = __perf_env__insert_btf(env, btf_node);
87+
up_write(&env->bpf_progs.lock);
88+
return ret;
89+
}
90+
91+
bool __perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node)
7892
{
7993
struct rb_node *parent = NULL;
8094
__u32 btf_id = btf_node->id;
8195
struct btf_node *node;
8296
struct rb_node **p;
83-
bool ret = true;
8497

85-
down_write(&env->bpf_progs.lock);
8698
p = &env->bpf_progs.btfs.rb_node;
8799

88100
while (*p != NULL) {
@@ -94,25 +106,31 @@ bool perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node)
94106
p = &(*p)->rb_right;
95107
} else {
96108
pr_debug("duplicated btf %u\n", btf_id);
97-
ret = false;
98-
goto out;
109+
return false;
99110
}
100111
}
101112

102113
rb_link_node(&btf_node->rb_node, parent, p);
103114
rb_insert_color(&btf_node->rb_node, &env->bpf_progs.btfs);
104115
env->bpf_progs.btfs_cnt++;
105-
out:
106-
up_write(&env->bpf_progs.lock);
107-
return ret;
116+
return true;
108117
}
109118

110119
struct btf_node *perf_env__find_btf(struct perf_env *env, __u32 btf_id)
120+
{
121+
struct btf_node *res;
122+
123+
down_read(&env->bpf_progs.lock);
124+
res = __perf_env__find_btf(env, btf_id);
125+
up_read(&env->bpf_progs.lock);
126+
return res;
127+
}
128+
129+
struct btf_node *__perf_env__find_btf(struct perf_env *env, __u32 btf_id)
111130
{
112131
struct btf_node *node = NULL;
113132
struct rb_node *n;
114133

115-
down_read(&env->bpf_progs.lock);
116134
n = env->bpf_progs.btfs.rb_node;
117135

118136
while (n) {
@@ -122,13 +140,9 @@ struct btf_node *perf_env__find_btf(struct perf_env *env, __u32 btf_id)
122140
else if (btf_id > node->id)
123141
n = n->rb_right;
124142
else
125-
goto out;
143+
return node;
126144
}
127-
node = NULL;
128-
129-
out:
130-
up_read(&env->bpf_progs.lock);
131-
return node;
145+
return NULL;
132146
}
133147

134148
/* purge data in bpf_progs.infos tree */

tools/perf/util/env.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,12 +163,16 @@ const char *perf_env__raw_arch(struct perf_env *env);
163163
int perf_env__nr_cpus_avail(struct perf_env *env);
164164

165165
void perf_env__init(struct perf_env *env);
166+
void __perf_env__insert_bpf_prog_info(struct perf_env *env,
167+
struct bpf_prog_info_node *info_node);
166168
void perf_env__insert_bpf_prog_info(struct perf_env *env,
167169
struct bpf_prog_info_node *info_node);
168170
struct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env,
169171
__u32 prog_id);
170172
bool perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node);
173+
bool __perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node);
171174
struct btf_node *perf_env__find_btf(struct perf_env *env, __u32 btf_id);
175+
struct btf_node *__perf_env__find_btf(struct perf_env *env, __u32 btf_id);
172176

173177
int perf_env__numa_node(struct perf_env *env, int cpu);
174178
#endif /* __PERF_ENV_H */

tools/perf/util/header.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1735,8 +1735,8 @@ static void print_bpf_prog_info(struct feat_fd *ff, FILE *fp)
17351735
node = rb_entry(next, struct bpf_prog_info_node, rb_node);
17361736
next = rb_next(&node->rb_node);
17371737

1738-
bpf_event__print_bpf_prog_info(&node->info_linear->info,
1739-
env, fp);
1738+
__bpf_event__print_bpf_prog_info(&node->info_linear->info,
1739+
env, fp);
17401740
}
17411741

17421742
up_read(&env->bpf_progs.lock);
@@ -3073,7 +3073,7 @@ static int process_bpf_prog_info(struct feat_fd *ff, void *data __maybe_unused)
30733073
/* after reading from file, translate offset to address */
30743074
bpf_program__bpil_offs_to_addr(info_linear);
30753075
info_node->info_linear = info_linear;
3076-
perf_env__insert_bpf_prog_info(env, info_node);
3076+
__perf_env__insert_bpf_prog_info(env, info_node);
30773077
}
30783078

30793079
up_write(&env->bpf_progs.lock);
@@ -3120,7 +3120,7 @@ static int process_bpf_btf(struct feat_fd *ff, void *data __maybe_unused)
31203120
if (__do_read(ff, node->data, data_size))
31213121
goto out;
31223122

3123-
perf_env__insert_btf(env, node);
3123+
__perf_env__insert_btf(env, node);
31243124
node = NULL;
31253125
}
31263126

0 commit comments

Comments
 (0)