xref: /aosp_15_r20/external/bcc/libbpf-tools/biolatency.bpf.c (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0
2*387f9dfdSAndroid Build Coastguard Worker // Copyright (c) 2020 Wenbo Zhang
3*387f9dfdSAndroid Build Coastguard Worker #include <vmlinux.h>
4*387f9dfdSAndroid Build Coastguard Worker #include <bpf/bpf_helpers.h>
5*387f9dfdSAndroid Build Coastguard Worker #include <bpf/bpf_core_read.h>
6*387f9dfdSAndroid Build Coastguard Worker #include <bpf/bpf_tracing.h>
7*387f9dfdSAndroid Build Coastguard Worker 
8*387f9dfdSAndroid Build Coastguard Worker #include "biolatency.h"
9*387f9dfdSAndroid Build Coastguard Worker #include "bits.bpf.h"
10*387f9dfdSAndroid Build Coastguard Worker #include "core_fixes.bpf.h"
11*387f9dfdSAndroid Build Coastguard Worker 
12*387f9dfdSAndroid Build Coastguard Worker #define MAX_ENTRIES	10240
13*387f9dfdSAndroid Build Coastguard Worker 
14*387f9dfdSAndroid Build Coastguard Worker extern int LINUX_KERNEL_VERSION __kconfig;
15*387f9dfdSAndroid Build Coastguard Worker 
16*387f9dfdSAndroid Build Coastguard Worker const volatile bool filter_cg = false;
17*387f9dfdSAndroid Build Coastguard Worker const volatile bool targ_per_disk = false;
18*387f9dfdSAndroid Build Coastguard Worker const volatile bool targ_per_flag = false;
19*387f9dfdSAndroid Build Coastguard Worker const volatile bool targ_queued = false;
20*387f9dfdSAndroid Build Coastguard Worker const volatile bool targ_ms = false;
21*387f9dfdSAndroid Build Coastguard Worker const volatile bool filter_dev = false;
22*387f9dfdSAndroid Build Coastguard Worker const volatile __u32 targ_dev = 0;
23*387f9dfdSAndroid Build Coastguard Worker 
24*387f9dfdSAndroid Build Coastguard Worker struct {
25*387f9dfdSAndroid Build Coastguard Worker 	__uint(type, BPF_MAP_TYPE_CGROUP_ARRAY);
26*387f9dfdSAndroid Build Coastguard Worker 	__type(key, u32);
27*387f9dfdSAndroid Build Coastguard Worker 	__type(value, u32);
28*387f9dfdSAndroid Build Coastguard Worker 	__uint(max_entries, 1);
29*387f9dfdSAndroid Build Coastguard Worker } cgroup_map SEC(".maps");
30*387f9dfdSAndroid Build Coastguard Worker 
31*387f9dfdSAndroid Build Coastguard Worker struct {
32*387f9dfdSAndroid Build Coastguard Worker 	__uint(type, BPF_MAP_TYPE_HASH);
33*387f9dfdSAndroid Build Coastguard Worker 	__uint(max_entries, MAX_ENTRIES);
34*387f9dfdSAndroid Build Coastguard Worker 	__type(key, struct request *);
35*387f9dfdSAndroid Build Coastguard Worker 	__type(value, u64);
36*387f9dfdSAndroid Build Coastguard Worker } start SEC(".maps");
37*387f9dfdSAndroid Build Coastguard Worker 
38*387f9dfdSAndroid Build Coastguard Worker static struct hist initial_hist;
39*387f9dfdSAndroid Build Coastguard Worker 
40*387f9dfdSAndroid Build Coastguard Worker struct {
41*387f9dfdSAndroid Build Coastguard Worker 	__uint(type, BPF_MAP_TYPE_HASH);
42*387f9dfdSAndroid Build Coastguard Worker 	__uint(max_entries, MAX_ENTRIES);
43*387f9dfdSAndroid Build Coastguard Worker 	__type(key, struct hist_key);
44*387f9dfdSAndroid Build Coastguard Worker 	__type(value, struct hist);
45*387f9dfdSAndroid Build Coastguard Worker } hists SEC(".maps");
46*387f9dfdSAndroid Build Coastguard Worker 
trace_rq_start(struct request * rq,int issue)47*387f9dfdSAndroid Build Coastguard Worker static int __always_inline trace_rq_start(struct request *rq, int issue)
48*387f9dfdSAndroid Build Coastguard Worker {
49*387f9dfdSAndroid Build Coastguard Worker 	u64 ts;
50*387f9dfdSAndroid Build Coastguard Worker 
51*387f9dfdSAndroid Build Coastguard Worker 	if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0))
52*387f9dfdSAndroid Build Coastguard Worker 		return 0;
53*387f9dfdSAndroid Build Coastguard Worker 
54*387f9dfdSAndroid Build Coastguard Worker 	if (issue && targ_queued && BPF_CORE_READ(rq, q, elevator))
55*387f9dfdSAndroid Build Coastguard Worker 		return 0;
56*387f9dfdSAndroid Build Coastguard Worker 
57*387f9dfdSAndroid Build Coastguard Worker 	ts = bpf_ktime_get_ns();
58*387f9dfdSAndroid Build Coastguard Worker 
59*387f9dfdSAndroid Build Coastguard Worker 	if (filter_dev) {
60*387f9dfdSAndroid Build Coastguard Worker 		struct gendisk *disk = get_disk(rq);
61*387f9dfdSAndroid Build Coastguard Worker 		u32 dev;
62*387f9dfdSAndroid Build Coastguard Worker 
63*387f9dfdSAndroid Build Coastguard Worker 		dev = disk ? MKDEV(BPF_CORE_READ(disk, major),
64*387f9dfdSAndroid Build Coastguard Worker 				BPF_CORE_READ(disk, first_minor)) : 0;
65*387f9dfdSAndroid Build Coastguard Worker 		if (targ_dev != dev)
66*387f9dfdSAndroid Build Coastguard Worker 			return 0;
67*387f9dfdSAndroid Build Coastguard Worker 	}
68*387f9dfdSAndroid Build Coastguard Worker 	bpf_map_update_elem(&start, &rq, &ts, 0);
69*387f9dfdSAndroid Build Coastguard Worker 	return 0;
70*387f9dfdSAndroid Build Coastguard Worker }
71*387f9dfdSAndroid Build Coastguard Worker 
handle_block_rq_insert(__u64 * ctx)72*387f9dfdSAndroid Build Coastguard Worker static int handle_block_rq_insert(__u64 *ctx)
73*387f9dfdSAndroid Build Coastguard Worker {
74*387f9dfdSAndroid Build Coastguard Worker 	/**
75*387f9dfdSAndroid Build Coastguard Worker 	 * commit a54895fa (v5.11-rc1) changed tracepoint argument list
76*387f9dfdSAndroid Build Coastguard Worker 	 * from TP_PROTO(struct request_queue *q, struct request *rq)
77*387f9dfdSAndroid Build Coastguard Worker 	 * to TP_PROTO(struct request *rq)
78*387f9dfdSAndroid Build Coastguard Worker 	 */
79*387f9dfdSAndroid Build Coastguard Worker 	if (LINUX_KERNEL_VERSION < KERNEL_VERSION(5, 11, 0))
80*387f9dfdSAndroid Build Coastguard Worker 		return trace_rq_start((void *)ctx[1], false);
81*387f9dfdSAndroid Build Coastguard Worker 	else
82*387f9dfdSAndroid Build Coastguard Worker 		return trace_rq_start((void *)ctx[0], false);
83*387f9dfdSAndroid Build Coastguard Worker }
84*387f9dfdSAndroid Build Coastguard Worker 
handle_block_rq_issue(__u64 * ctx)85*387f9dfdSAndroid Build Coastguard Worker static int handle_block_rq_issue(__u64 *ctx)
86*387f9dfdSAndroid Build Coastguard Worker {
87*387f9dfdSAndroid Build Coastguard Worker 	/**
88*387f9dfdSAndroid Build Coastguard Worker 	 * commit a54895fa (v5.11-rc1) changed tracepoint argument list
89*387f9dfdSAndroid Build Coastguard Worker 	 * from TP_PROTO(struct request_queue *q, struct request *rq)
90*387f9dfdSAndroid Build Coastguard Worker 	 * to TP_PROTO(struct request *rq)
91*387f9dfdSAndroid Build Coastguard Worker 	 */
92*387f9dfdSAndroid Build Coastguard Worker 	if (LINUX_KERNEL_VERSION < KERNEL_VERSION(5, 11, 0))
93*387f9dfdSAndroid Build Coastguard Worker 		return trace_rq_start((void *)ctx[1], true);
94*387f9dfdSAndroid Build Coastguard Worker 	else
95*387f9dfdSAndroid Build Coastguard Worker 		return trace_rq_start((void *)ctx[0], true);
96*387f9dfdSAndroid Build Coastguard Worker }
97*387f9dfdSAndroid Build Coastguard Worker 
handle_block_rq_complete(struct request * rq,int error,unsigned int nr_bytes)98*387f9dfdSAndroid Build Coastguard Worker static int handle_block_rq_complete(struct request *rq, int error, unsigned int nr_bytes)
99*387f9dfdSAndroid Build Coastguard Worker {
100*387f9dfdSAndroid Build Coastguard Worker 	u64 slot, *tsp, ts = bpf_ktime_get_ns();
101*387f9dfdSAndroid Build Coastguard Worker 	struct hist_key hkey = {};
102*387f9dfdSAndroid Build Coastguard Worker 	struct hist *histp;
103*387f9dfdSAndroid Build Coastguard Worker 	s64 delta;
104*387f9dfdSAndroid Build Coastguard Worker 	u64 udelta;
105*387f9dfdSAndroid Build Coastguard Worker 
106*387f9dfdSAndroid Build Coastguard Worker 	if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0))
107*387f9dfdSAndroid Build Coastguard Worker 		return 0;
108*387f9dfdSAndroid Build Coastguard Worker 
109*387f9dfdSAndroid Build Coastguard Worker 	tsp = bpf_map_lookup_elem(&start, &rq);
110*387f9dfdSAndroid Build Coastguard Worker 	if (!tsp)
111*387f9dfdSAndroid Build Coastguard Worker 		return 0;
112*387f9dfdSAndroid Build Coastguard Worker 
113*387f9dfdSAndroid Build Coastguard Worker 	delta = (s64)(ts - *tsp);
114*387f9dfdSAndroid Build Coastguard Worker 	if (delta < 0)
115*387f9dfdSAndroid Build Coastguard Worker 		goto cleanup;
116*387f9dfdSAndroid Build Coastguard Worker 
117*387f9dfdSAndroid Build Coastguard Worker 	udelta = (u64)delta;
118*387f9dfdSAndroid Build Coastguard Worker 
119*387f9dfdSAndroid Build Coastguard Worker 	if (targ_per_disk) {
120*387f9dfdSAndroid Build Coastguard Worker 		struct gendisk *disk = get_disk(rq);
121*387f9dfdSAndroid Build Coastguard Worker 
122*387f9dfdSAndroid Build Coastguard Worker 		hkey.dev = disk ? MKDEV(BPF_CORE_READ(disk, major),
123*387f9dfdSAndroid Build Coastguard Worker 					BPF_CORE_READ(disk, first_minor)) : 0;
124*387f9dfdSAndroid Build Coastguard Worker 	}
125*387f9dfdSAndroid Build Coastguard Worker 	if (targ_per_flag)
126*387f9dfdSAndroid Build Coastguard Worker 		hkey.cmd_flags = BPF_CORE_READ(rq, cmd_flags);
127*387f9dfdSAndroid Build Coastguard Worker 
128*387f9dfdSAndroid Build Coastguard Worker 	histp = bpf_map_lookup_elem(&hists, &hkey);
129*387f9dfdSAndroid Build Coastguard Worker 	if (!histp) {
130*387f9dfdSAndroid Build Coastguard Worker 		bpf_map_update_elem(&hists, &hkey, &initial_hist, 0);
131*387f9dfdSAndroid Build Coastguard Worker 		histp = bpf_map_lookup_elem(&hists, &hkey);
132*387f9dfdSAndroid Build Coastguard Worker 		if (!histp)
133*387f9dfdSAndroid Build Coastguard Worker 			goto cleanup;
134*387f9dfdSAndroid Build Coastguard Worker 	}
135*387f9dfdSAndroid Build Coastguard Worker 
136*387f9dfdSAndroid Build Coastguard Worker 	if (targ_ms)
137*387f9dfdSAndroid Build Coastguard Worker 		udelta /= 1000000U;
138*387f9dfdSAndroid Build Coastguard Worker 	else
139*387f9dfdSAndroid Build Coastguard Worker 		udelta /= 1000U;
140*387f9dfdSAndroid Build Coastguard Worker 	slot = log2l(udelta);
141*387f9dfdSAndroid Build Coastguard Worker 	if (slot >= MAX_SLOTS)
142*387f9dfdSAndroid Build Coastguard Worker 		slot = MAX_SLOTS - 1;
143*387f9dfdSAndroid Build Coastguard Worker 	__sync_fetch_and_add(&histp->slots[slot], 1);
144*387f9dfdSAndroid Build Coastguard Worker 
145*387f9dfdSAndroid Build Coastguard Worker cleanup:
146*387f9dfdSAndroid Build Coastguard Worker 	bpf_map_delete_elem(&start, &rq);
147*387f9dfdSAndroid Build Coastguard Worker 	return 0;
148*387f9dfdSAndroid Build Coastguard Worker }
149*387f9dfdSAndroid Build Coastguard Worker 
150*387f9dfdSAndroid Build Coastguard Worker SEC("tp_btf/block_rq_insert")
block_rq_insert_btf(u64 * ctx)151*387f9dfdSAndroid Build Coastguard Worker int block_rq_insert_btf(u64 *ctx)
152*387f9dfdSAndroid Build Coastguard Worker {
153*387f9dfdSAndroid Build Coastguard Worker 	return handle_block_rq_insert(ctx);
154*387f9dfdSAndroid Build Coastguard Worker }
155*387f9dfdSAndroid Build Coastguard Worker 
156*387f9dfdSAndroid Build Coastguard Worker SEC("tp_btf/block_rq_issue")
block_rq_issue_btf(u64 * ctx)157*387f9dfdSAndroid Build Coastguard Worker int block_rq_issue_btf(u64 *ctx)
158*387f9dfdSAndroid Build Coastguard Worker {
159*387f9dfdSAndroid Build Coastguard Worker 	return handle_block_rq_issue(ctx);
160*387f9dfdSAndroid Build Coastguard Worker }
161*387f9dfdSAndroid Build Coastguard Worker 
162*387f9dfdSAndroid Build Coastguard Worker SEC("tp_btf/block_rq_complete")
BPF_PROG(block_rq_complete_btf,struct request * rq,int error,unsigned int nr_bytes)163*387f9dfdSAndroid Build Coastguard Worker int BPF_PROG(block_rq_complete_btf, struct request *rq, int error, unsigned int nr_bytes)
164*387f9dfdSAndroid Build Coastguard Worker {
165*387f9dfdSAndroid Build Coastguard Worker 	return handle_block_rq_complete(rq, error, nr_bytes);
166*387f9dfdSAndroid Build Coastguard Worker }
167*387f9dfdSAndroid Build Coastguard Worker 
168*387f9dfdSAndroid Build Coastguard Worker SEC("raw_tp/block_rq_insert")
BPF_PROG(block_rq_insert)169*387f9dfdSAndroid Build Coastguard Worker int BPF_PROG(block_rq_insert)
170*387f9dfdSAndroid Build Coastguard Worker {
171*387f9dfdSAndroid Build Coastguard Worker 	return handle_block_rq_insert(ctx);
172*387f9dfdSAndroid Build Coastguard Worker }
173*387f9dfdSAndroid Build Coastguard Worker 
174*387f9dfdSAndroid Build Coastguard Worker SEC("raw_tp/block_rq_issue")
BPF_PROG(block_rq_issue)175*387f9dfdSAndroid Build Coastguard Worker int BPF_PROG(block_rq_issue)
176*387f9dfdSAndroid Build Coastguard Worker {
177*387f9dfdSAndroid Build Coastguard Worker 	return handle_block_rq_issue(ctx);
178*387f9dfdSAndroid Build Coastguard Worker }
179*387f9dfdSAndroid Build Coastguard Worker 
180*387f9dfdSAndroid Build Coastguard Worker SEC("raw_tp/block_rq_complete")
BPF_PROG(block_rq_complete,struct request * rq,int error,unsigned int nr_bytes)181*387f9dfdSAndroid Build Coastguard Worker int BPF_PROG(block_rq_complete, struct request *rq, int error, unsigned int nr_bytes)
182*387f9dfdSAndroid Build Coastguard Worker {
183*387f9dfdSAndroid Build Coastguard Worker 	return handle_block_rq_complete(rq, error, nr_bytes);
184*387f9dfdSAndroid Build Coastguard Worker }
185*387f9dfdSAndroid Build Coastguard Worker 
186*387f9dfdSAndroid Build Coastguard Worker char LICENSE[] SEC("license") = "GPL";
187