Skip to content

Commit 4cd5db4

Browse files
captain5050gregkh
authored andcommitted
perf env: Avoid recursively taking env->bpf_progs.lock
[ 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 <[email protected]> Acked-by: Jiri Olsa <[email protected]> Acked-by: Song Liu <[email protected]> Cc: Adrian Hunter <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Huacai Chen <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: K Prateek Nayak <[email protected]> Cc: Kan Liang <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Ming Wang <[email protected]> Cc: Namhyung Kim <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Ravi Bangoria <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent f19a1cb commit 4cd5db4

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
@@ -442,9 +442,9 @@ int evlist__add_bpf_sb_event(struct evlist *evlist, struct perf_env *env)
442442
return perf_evlist__add_sb_event(evlist, &attr, bpf_event__sb_cb, env);
443443
}
444444

445-
void bpf_event__print_bpf_prog_info(struct bpf_prog_info *info,
446-
struct perf_env *env,
447-
FILE *fp)
445+
void __bpf_event__print_bpf_prog_info(struct bpf_prog_info *info,
446+
struct perf_env *env,
447+
FILE *fp)
448448
{
449449
__u32 *prog_lens = (__u32 *)(uintptr_t)(info->jited_func_lens);
450450
__u64 *prog_addrs = (__u64 *)(uintptr_t)(info->jited_ksyms);
@@ -460,7 +460,7 @@ void bpf_event__print_bpf_prog_info(struct bpf_prog_info *info,
460460
if (info->btf_id) {
461461
struct btf_node *node;
462462

463-
node = perf_env__find_btf(env, info->btf_id);
463+
node = __perf_env__find_btf(env, info->btf_id);
464464
if (node)
465465
btf = btf__new((__u8 *)(node->data),
466466
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
@@ -15,13 +15,19 @@ struct perf_env perf_env;
1515

1616
void perf_env__insert_bpf_prog_info(struct perf_env *env,
1717
struct bpf_prog_info_node *info_node)
18+
{
19+
down_write(&env->bpf_progs.lock);
20+
__perf_env__insert_bpf_prog_info(env, info_node);
21+
up_write(&env->bpf_progs.lock);
22+
}
23+
24+
void __perf_env__insert_bpf_prog_info(struct perf_env *env, struct bpf_prog_info_node *info_node)
1825
{
1926
__u32 prog_id = info_node->info_linear->info.id;
2027
struct bpf_prog_info_node *node;
2128
struct rb_node *parent = NULL;
2229
struct rb_node **p;
2330

24-
down_write(&env->bpf_progs.lock);
2531
p = &env->bpf_progs.infos.rb_node;
2632

2733
while (*p != NULL) {
@@ -33,15 +39,13 @@ void perf_env__insert_bpf_prog_info(struct perf_env *env,
3339
p = &(*p)->rb_right;
3440
} else {
3541
pr_debug("duplicated bpf prog info %u\n", prog_id);
36-
goto out;
42+
return;
3743
}
3844
}
3945

4046
rb_link_node(&info_node->rb_node, parent, p);
4147
rb_insert_color(&info_node->rb_node, &env->bpf_progs.infos);
4248
env->bpf_progs.infos_cnt++;
43-
out:
44-
up_write(&env->bpf_progs.lock);
4549
}
4650

4751
struct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env,
@@ -70,14 +74,22 @@ struct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env,
7074
}
7175

7276
bool perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node)
77+
{
78+
bool ret;
79+
80+
down_write(&env->bpf_progs.lock);
81+
ret = __perf_env__insert_btf(env, btf_node);
82+
up_write(&env->bpf_progs.lock);
83+
return ret;
84+
}
85+
86+
bool __perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node)
7387
{
7488
struct rb_node *parent = NULL;
7589
__u32 btf_id = btf_node->id;
7690
struct btf_node *node;
7791
struct rb_node **p;
78-
bool ret = true;
7992

80-
down_write(&env->bpf_progs.lock);
8193
p = &env->bpf_progs.btfs.rb_node;
8294

8395
while (*p != NULL) {
@@ -89,25 +101,31 @@ bool perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node)
89101
p = &(*p)->rb_right;
90102
} else {
91103
pr_debug("duplicated btf %u\n", btf_id);
92-
ret = false;
93-
goto out;
104+
return false;
94105
}
95106
}
96107

97108
rb_link_node(&btf_node->rb_node, parent, p);
98109
rb_insert_color(&btf_node->rb_node, &env->bpf_progs.btfs);
99110
env->bpf_progs.btfs_cnt++;
100-
out:
101-
up_write(&env->bpf_progs.lock);
102-
return ret;
111+
return true;
103112
}
104113

105114
struct btf_node *perf_env__find_btf(struct perf_env *env, __u32 btf_id)
115+
{
116+
struct btf_node *res;
117+
118+
down_read(&env->bpf_progs.lock);
119+
res = __perf_env__find_btf(env, btf_id);
120+
up_read(&env->bpf_progs.lock);
121+
return res;
122+
}
123+
124+
struct btf_node *__perf_env__find_btf(struct perf_env *env, __u32 btf_id)
106125
{
107126
struct btf_node *node = NULL;
108127
struct rb_node *n;
109128

110-
down_read(&env->bpf_progs.lock);
111129
n = env->bpf_progs.btfs.rb_node;
112130

113131
while (n) {
@@ -117,13 +135,9 @@ struct btf_node *perf_env__find_btf(struct perf_env *env, __u32 btf_id)
117135
else if (btf_id > node->id)
118136
n = n->rb_right;
119137
else
120-
goto out;
138+
return node;
121139
}
122-
node = NULL;
123-
124-
out:
125-
up_read(&env->bpf_progs.lock);
126-
return node;
140+
return NULL;
127141
}
128142

129143
/* 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
@@ -117,12 +117,16 @@ const char *perf_env__raw_arch(struct perf_env *env);
117117
int perf_env__nr_cpus_avail(struct perf_env *env);
118118

119119
void perf_env__init(struct perf_env *env);
120+
void __perf_env__insert_bpf_prog_info(struct perf_env *env,
121+
struct bpf_prog_info_node *info_node);
120122
void perf_env__insert_bpf_prog_info(struct perf_env *env,
121123
struct bpf_prog_info_node *info_node);
122124
struct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env,
123125
__u32 prog_id);
124126
bool perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node);
127+
bool __perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node);
125128
struct btf_node *perf_env__find_btf(struct perf_env *env, __u32 btf_id);
129+
struct btf_node *__perf_env__find_btf(struct perf_env *env, __u32 btf_id);
126130

127131
int perf_env__numa_node(struct perf_env *env, int cpu);
128132
#endif /* __PERF_ENV_H */

tools/perf/util/header.c

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

1549-
bpf_event__print_bpf_prog_info(&node->info_linear->info,
1550-
env, fp);
1549+
__bpf_event__print_bpf_prog_info(&node->info_linear->info,
1550+
env, fp);
15511551
}
15521552

15531553
up_read(&env->bpf_progs.lock);
@@ -2724,7 +2724,7 @@ static int process_bpf_prog_info(struct feat_fd *ff, void *data __maybe_unused)
27242724
/* after reading from file, translate offset to address */
27252725
bpf_program__bpil_offs_to_addr(info_linear);
27262726
info_node->info_linear = info_linear;
2727-
perf_env__insert_bpf_prog_info(env, info_node);
2727+
__perf_env__insert_bpf_prog_info(env, info_node);
27282728
}
27292729

27302730
up_write(&env->bpf_progs.lock);
@@ -2777,7 +2777,7 @@ static int process_bpf_btf(struct feat_fd *ff, void *data __maybe_unused)
27772777
if (__do_read(ff, node->data, data_size))
27782778
goto out;
27792779

2780-
perf_env__insert_btf(env, node);
2780+
__perf_env__insert_btf(env, node);
27812781
node = NULL;
27822782
}
27832783

0 commit comments

Comments
 (0)