25
25
26
26
#include <bpf/libbpf.h>
27
27
#include <bpf/bpf.h>
28
+ #include <bpf/btf.h>
28
29
#include "klockstat.h"
29
30
#include "klockstat.skel.h"
30
31
#include "compat.h"
@@ -117,6 +118,10 @@ static const char *lock_ksym_names[] = {
117
118
118
119
static unsigned long lock_ksym_addr [ARRAY_SIZE (lock_ksym_names )];
119
120
121
+ static struct btf * vmlinux_btf ;
122
+ static const char * * nltype_map ;
123
+ static size_t nltype_max = 0 ;
124
+
120
125
static const struct argp_option opts [] = {
121
126
{ "pid" , 'p' , "PID" , 0 , "Filter by process ID" , 0 },
122
127
{ "tid" , 't' , "TID" , 0 , "Filter by thread ID" , 0 },
@@ -139,6 +144,93 @@ static const struct argp_option opts[] = {
139
144
{},
140
145
};
141
146
147
+ static char * get_nltype (unsigned long nltype )
148
+ {
149
+ static char buf [100 ];
150
+
151
+ if (!nltype )
152
+ return "" ;
153
+
154
+ if (nltype >= nltype_max || !nltype_map [nltype ])
155
+ snprintf (buf , sizeof (buf ), " nltype %lu" , nltype );
156
+ else
157
+ snprintf (buf , sizeof (buf ), " nltype %s" , nltype_map [nltype ]);
158
+
159
+ buf [sizeof (buf )- 1 ] = '\0' ;
160
+ return buf ;
161
+ }
162
+
163
+ static int build_nlmsg_name_table (const struct btf_type * t )
164
+ {
165
+ const struct btf_enum * e ;
166
+ unsigned short vlen ;
167
+ size_t max_val = 0 ;
168
+ const char * name ;
169
+ int i ;
170
+
171
+ vlen = btf_vlen (t );
172
+ e = btf_enum (t );
173
+
174
+ /* first pass - find the value of __RTM_MAX to size the allocation */
175
+ for (i = 0 ; i < vlen ; i ++ ) {
176
+ name = btf__name_by_offset (vmlinux_btf , e [i ].name_off );
177
+ if (!strcmp (name , "__RTM_MAX" )) {
178
+ max_val = e [i ].val ;
179
+ break ;
180
+ }
181
+ }
182
+
183
+ if (!max_val )
184
+ return - ENOENT ;
185
+
186
+ nltype_map = calloc (max_val , sizeof (void * ));
187
+ if (!nltype_map )
188
+ return - ENOMEM ;
189
+
190
+ nltype_max = max_val ;
191
+
192
+ for (i = 0 ; i < vlen ; i ++ ) {
193
+ if (e [i ].val >= max_val )
194
+ break ;
195
+
196
+ nltype_map [e [i ].val ] = btf__name_by_offset (vmlinux_btf , e [i ].name_off );
197
+ }
198
+
199
+ return 0 ;
200
+ }
201
+
202
+ static int resolve_nlmsg_names (void )
203
+ {
204
+ const struct btf_type * t ;
205
+ const struct btf_enum * e ;
206
+ int nr_types , i , j , err ;
207
+ unsigned short vlen ;
208
+ const char * name ;
209
+
210
+ if (!vmlinux_btf )
211
+ vmlinux_btf = btf__load_vmlinux_btf ();
212
+
213
+ if ((err = libbpf_get_error (vmlinux_btf )))
214
+ return err ;
215
+
216
+ nr_types = btf__type_cnt (vmlinux_btf );
217
+ for (i = 1 ; i < nr_types ; i ++ ) {
218
+ t = btf__type_by_id (vmlinux_btf , i );
219
+ if (!btf_is_enum (t ))
220
+ continue ;
221
+
222
+ vlen = btf_vlen (t );
223
+ e = btf_enum (t );
224
+ for (j = 0 ; j < vlen ; j ++ ) {
225
+ name = btf__name_by_offset (vmlinux_btf , e [j ].name_off );
226
+ if (!strcmp (name , "RTM_BASE" ))
227
+ return build_nlmsg_name_table (t );
228
+ }
229
+ }
230
+
231
+ return - ENOENT ;
232
+ }
233
+
142
234
static void * parse_lock_addr (const char * lock_name )
143
235
{
144
236
unsigned long lock_addr ;
@@ -479,11 +571,12 @@ static void print_acq_stat(struct ksyms *ksyms, struct stack_stat *ss,
479
571
printf ("%37s\n" , symname (ksyms , ss -> bt [i ], buf , sizeof (buf )));
480
572
}
481
573
if (nr_stack_entries > 1 && !env .per_thread )
482
- printf (" Max PID %llu, COMM %s, Lock %s (0x%llx)\n" ,
574
+ printf (" Max PID %llu, COMM %s, Lock %s (0x%llx)%s \n" ,
483
575
ss -> ls .acq_max_id >> 32 ,
484
576
ss -> ls .acq_max_comm ,
485
- get_lock_name (ksyms , ss -> ls .acq_max_lock_ptr ),
486
- ss -> ls .acq_max_lock_ptr );
577
+ get_lock_name (ksyms , ss -> ls .acq_max_lock_ptr ),
578
+ ss -> ls .acq_max_lock_ptr ,
579
+ get_nltype (ss -> ls .acq_max_nltype ));
487
580
}
488
581
489
582
static void print_acq_task (struct stack_stat * ss )
@@ -533,11 +626,12 @@ static void print_hld_stat(struct ksyms *ksyms, struct stack_stat *ss,
533
626
printf ("%37s\n" , symname (ksyms , ss -> bt [i ], buf , sizeof (buf )));
534
627
}
535
628
if (nr_stack_entries > 1 && !env .per_thread )
536
- printf (" Max PID %llu, COMM %s, Lock %s (0x%llx)\n" ,
629
+ printf (" Max PID %llu, COMM %s, Lock %s (0x%llx)%s \n" ,
537
630
ss -> ls .hld_max_id >> 32 ,
538
631
ss -> ls .hld_max_comm ,
539
- get_lock_name (ksyms , ss -> ls .hld_max_lock_ptr ),
540
- ss -> ls .hld_max_lock_ptr );
632
+ get_lock_name (ksyms , ss -> ls .hld_max_lock_ptr ),
633
+ ss -> ls .hld_max_lock_ptr ,
634
+ get_nltype (ss -> ls .hld_max_nltype ));
541
635
}
542
636
543
637
static void print_hld_task (struct stack_stat * ss )
@@ -633,7 +727,7 @@ static int print_stats(struct ksyms *ksyms, int stack_map, int stat_map)
633
727
if (env .reset ) {
634
728
ss = stats [i ];
635
729
bpf_map_delete_elem (stat_map , & ss -> stack_id );
636
- }
730
+ }
637
731
free (stats [i ]);
638
732
}
639
733
free (stats );
@@ -688,6 +782,11 @@ static void enable_fentry(struct klockstat_bpf *obj)
688
782
bpf_program__set_autoload (obj -> progs .kprobe_down_write_killable_exit , false);
689
783
bpf_program__set_autoload (obj -> progs .kprobe_up_write , false);
690
784
785
+ bpf_program__set_autoload (obj -> progs .kprobe_rtnetlink_rcv_msg , false);
786
+ bpf_program__set_autoload (obj -> progs .kprobe_rtnetlink_rcv_msg_exit , false);
787
+ bpf_program__set_autoload (obj -> progs .kprobe_netlink_dump , false);
788
+ bpf_program__set_autoload (obj -> progs .kprobe_netlink_dump_exit , false);
789
+
691
790
/* CONFIG_DEBUG_LOCK_ALLOC is on */
692
791
debug_lock = fentry_can_attach ("mutex_lock_nested" , NULL );
693
792
if (!debug_lock )
@@ -749,6 +848,24 @@ static void enable_kprobes(struct klockstat_bpf *obj)
749
848
bpf_program__set_autoload (obj -> progs .down_write_killable , false);
750
849
bpf_program__set_autoload (obj -> progs .down_write_killable_exit , false);
751
850
bpf_program__set_autoload (obj -> progs .up_write , false);
851
+
852
+ bpf_program__set_autoload (obj -> progs .rtnetlink_rcv_msg , false);
853
+ bpf_program__set_autoload (obj -> progs .rtnetlink_rcv_msg_exit , false);
854
+ bpf_program__set_autoload (obj -> progs .netlink_dump , false);
855
+ bpf_program__set_autoload (obj -> progs .netlink_dump_exit , false);
856
+ }
857
+
858
+ static void disable_nldump_probes (struct klockstat_bpf * obj )
859
+ {
860
+ bpf_program__set_autoload (obj -> progs .rtnetlink_rcv_msg , false);
861
+ bpf_program__set_autoload (obj -> progs .rtnetlink_rcv_msg_exit , false);
862
+ bpf_program__set_autoload (obj -> progs .netlink_dump , false);
863
+ bpf_program__set_autoload (obj -> progs .netlink_dump_exit , false);
864
+
865
+ bpf_program__set_autoload (obj -> progs .kprobe_rtnetlink_rcv_msg , false);
866
+ bpf_program__set_autoload (obj -> progs .kprobe_rtnetlink_rcv_msg_exit , false);
867
+ bpf_program__set_autoload (obj -> progs .kprobe_netlink_dump , false);
868
+ bpf_program__set_autoload (obj -> progs .kprobe_netlink_dump_exit , false);
752
869
}
753
870
754
871
int main (int argc , char * * argv )
@@ -815,6 +932,14 @@ int main(int argc, char **argv)
815
932
else
816
933
enable_kprobes (obj );
817
934
935
+ if (env .nr_stack_entries != 1 ) {
936
+ err = resolve_nlmsg_names ();
937
+ if (err )
938
+ warn ("failed to resolve nlmsg names\n" );
939
+ } else {
940
+ disable_nldump_probes (obj );
941
+ }
942
+
818
943
err = klockstat_bpf__load (obj );
819
944
if (err ) {
820
945
warn ("failed to load BPF object\n" );
0 commit comments