1*aeb709c7SAlexei Starovoitov // SPDX-License-Identifier: GPL-2.0 2*aeb709c7SAlexei Starovoitov #include <vmlinux.h> 3*aeb709c7SAlexei Starovoitov #include <bpf/bpf_helpers.h> 4*aeb709c7SAlexei Starovoitov #include <bpf/bpf_core_read.h> 5*aeb709c7SAlexei Starovoitov #include "bpf_kfuncs.h" 6*aeb709c7SAlexei Starovoitov 7*aeb709c7SAlexei Starovoitov struct { 8*aeb709c7SAlexei Starovoitov __uint(type, BPF_MAP_TYPE_HASH); 9*aeb709c7SAlexei Starovoitov __uint(map_flags, BPF_F_NO_PREALLOC); 10*aeb709c7SAlexei Starovoitov __uint(max_entries, 4096); 11*aeb709c7SAlexei Starovoitov __type(key, int); 12*aeb709c7SAlexei Starovoitov __type(value, long); 13*aeb709c7SAlexei Starovoitov } htab SEC(".maps"); 14*aeb709c7SAlexei Starovoitov 15*aeb709c7SAlexei Starovoitov extern const void __per_cpu_offset __ksym; 16*aeb709c7SAlexei Starovoitov 17*aeb709c7SAlexei Starovoitov int nr_cpus; 18*aeb709c7SAlexei Starovoitov int nr_caches; 19*aeb709c7SAlexei Starovoitov int in_progress; 20*aeb709c7SAlexei Starovoitov int not_freed; 21*aeb709c7SAlexei Starovoitov 22*aeb709c7SAlexei Starovoitov /* Look at bpf_mem_cache of every cpu that htab allocates its elements from */ 23*aeb709c7SAlexei Starovoitov SEC("syscall") 24*aeb709c7SAlexei Starovoitov int check_ttrace(void *ctx) 25*aeb709c7SAlexei Starovoitov { 26*aeb709c7SAlexei Starovoitov struct bpf_htab *h = bpf_core_cast(&htab, struct bpf_htab); 27*aeb709c7SAlexei Starovoitov unsigned long cache = (unsigned long)BPF_CORE_READ(h, ma.cache); 28*aeb709c7SAlexei Starovoitov const unsigned long *offsets = &__per_cpu_offset; 29*aeb709c7SAlexei Starovoitov struct bpf_mem_cache *c; 30*aeb709c7SAlexei Starovoitov unsigned long off; 31*aeb709c7SAlexei Starovoitov int cpu; 32*aeb709c7SAlexei Starovoitov 33*aeb709c7SAlexei Starovoitov nr_caches = 0; 34*aeb709c7SAlexei Starovoitov in_progress = 0; 35*aeb709c7SAlexei Starovoitov not_freed = 0; 36*aeb709c7SAlexei Starovoitov bpf_for(cpu, 0, nr_cpus) { 37*aeb709c7SAlexei Starovoitov if (bpf_probe_read_kernel(&off, sizeof(off), offsets + cpu)) 38*aeb709c7SAlexei Starovoitov return -1; 39*aeb709c7SAlexei Starovoitov c = bpf_core_cast((void *)(cache + off), struct bpf_mem_cache); 40*aeb709c7SAlexei Starovoitov if (c->unit_size) 41*aeb709c7SAlexei Starovoitov nr_caches++; 42*aeb709c7SAlexei Starovoitov if (c->call_rcu_ttrace_in_progress.counter) 43*aeb709c7SAlexei Starovoitov in_progress++; 44*aeb709c7SAlexei Starovoitov if (c->free_by_rcu_ttrace.first || c->waiting_for_gp_ttrace.first) 45*aeb709c7SAlexei Starovoitov not_freed++; 46*aeb709c7SAlexei Starovoitov } 47*aeb709c7SAlexei Starovoitov return 0; 48*aeb709c7SAlexei Starovoitov } 49*aeb709c7SAlexei Starovoitov 50*aeb709c7SAlexei Starovoitov char _license[] SEC("license") = "GPL"; 51