1*387f9dfdSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0
2*387f9dfdSAndroid Build Coastguard Worker // Copyright (c) 2022 Francis Laniel <[email protected]>
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 "biotop.h"
9*387f9dfdSAndroid Build Coastguard Worker #include "maps.bpf.h"
10*387f9dfdSAndroid Build Coastguard Worker #include "core_fixes.bpf.h"
11*387f9dfdSAndroid Build Coastguard Worker
12*387f9dfdSAndroid Build Coastguard Worker struct {
13*387f9dfdSAndroid Build Coastguard Worker __uint(type, BPF_MAP_TYPE_HASH);
14*387f9dfdSAndroid Build Coastguard Worker __uint(max_entries, 10240);
15*387f9dfdSAndroid Build Coastguard Worker __type(key, struct request *);
16*387f9dfdSAndroid Build Coastguard Worker __type(value, struct start_req_t);
17*387f9dfdSAndroid Build Coastguard Worker } start SEC(".maps");
18*387f9dfdSAndroid Build Coastguard Worker
19*387f9dfdSAndroid Build Coastguard Worker struct {
20*387f9dfdSAndroid Build Coastguard Worker __uint(type, BPF_MAP_TYPE_HASH);
21*387f9dfdSAndroid Build Coastguard Worker __uint(max_entries, 10240);
22*387f9dfdSAndroid Build Coastguard Worker __type(key, struct request *);
23*387f9dfdSAndroid Build Coastguard Worker __type(value, struct who_t);
24*387f9dfdSAndroid Build Coastguard Worker } whobyreq SEC(".maps");
25*387f9dfdSAndroid Build Coastguard Worker
26*387f9dfdSAndroid Build Coastguard Worker struct {
27*387f9dfdSAndroid Build Coastguard Worker __uint(type, BPF_MAP_TYPE_HASH);
28*387f9dfdSAndroid Build Coastguard Worker __uint(max_entries, 10240);
29*387f9dfdSAndroid Build Coastguard Worker __type(key, struct info_t);
30*387f9dfdSAndroid Build Coastguard Worker __type(value, struct val_t);
31*387f9dfdSAndroid Build Coastguard Worker } counts SEC(".maps");
32*387f9dfdSAndroid Build Coastguard Worker
33*387f9dfdSAndroid Build Coastguard Worker static __always_inline
trace_start(struct request * req)34*387f9dfdSAndroid Build Coastguard Worker int trace_start(struct request *req)
35*387f9dfdSAndroid Build Coastguard Worker {
36*387f9dfdSAndroid Build Coastguard Worker struct who_t who = {};
37*387f9dfdSAndroid Build Coastguard Worker
38*387f9dfdSAndroid Build Coastguard Worker /* cache PID and comm by-req */
39*387f9dfdSAndroid Build Coastguard Worker bpf_get_current_comm(&who.name, sizeof(who.name));
40*387f9dfdSAndroid Build Coastguard Worker who.pid = bpf_get_current_pid_tgid() >> 32;
41*387f9dfdSAndroid Build Coastguard Worker bpf_map_update_elem(&whobyreq, &req, &who, 0);
42*387f9dfdSAndroid Build Coastguard Worker
43*387f9dfdSAndroid Build Coastguard Worker return 0;
44*387f9dfdSAndroid Build Coastguard Worker }
45*387f9dfdSAndroid Build Coastguard Worker
46*387f9dfdSAndroid Build Coastguard Worker SEC("kprobe/blk_mq_start_request")
BPF_KPROBE(blk_mq_start_request,struct request * req)47*387f9dfdSAndroid Build Coastguard Worker int BPF_KPROBE(blk_mq_start_request, struct request *req)
48*387f9dfdSAndroid Build Coastguard Worker {
49*387f9dfdSAndroid Build Coastguard Worker /* time block I/O */
50*387f9dfdSAndroid Build Coastguard Worker struct start_req_t start_req;
51*387f9dfdSAndroid Build Coastguard Worker
52*387f9dfdSAndroid Build Coastguard Worker start_req.ts = bpf_ktime_get_ns();
53*387f9dfdSAndroid Build Coastguard Worker start_req.data_len = BPF_CORE_READ(req, __data_len);
54*387f9dfdSAndroid Build Coastguard Worker
55*387f9dfdSAndroid Build Coastguard Worker bpf_map_update_elem(&start, &req, &start_req, 0);
56*387f9dfdSAndroid Build Coastguard Worker return 0;
57*387f9dfdSAndroid Build Coastguard Worker }
58*387f9dfdSAndroid Build Coastguard Worker
59*387f9dfdSAndroid Build Coastguard Worker static __always_inline
trace_done(struct request * req)60*387f9dfdSAndroid Build Coastguard Worker int trace_done(struct request *req)
61*387f9dfdSAndroid Build Coastguard Worker {
62*387f9dfdSAndroid Build Coastguard Worker struct val_t *valp, zero = {};
63*387f9dfdSAndroid Build Coastguard Worker struct info_t info = {};
64*387f9dfdSAndroid Build Coastguard Worker struct start_req_t *startp;
65*387f9dfdSAndroid Build Coastguard Worker unsigned int cmd_flags;
66*387f9dfdSAndroid Build Coastguard Worker struct gendisk *disk;
67*387f9dfdSAndroid Build Coastguard Worker struct who_t *whop;
68*387f9dfdSAndroid Build Coastguard Worker u64 delta_us;
69*387f9dfdSAndroid Build Coastguard Worker
70*387f9dfdSAndroid Build Coastguard Worker /* fetch timestamp and calculate delta */
71*387f9dfdSAndroid Build Coastguard Worker startp = bpf_map_lookup_elem(&start, &req);
72*387f9dfdSAndroid Build Coastguard Worker if (!startp)
73*387f9dfdSAndroid Build Coastguard Worker return 0; /* missed tracing issue */
74*387f9dfdSAndroid Build Coastguard Worker
75*387f9dfdSAndroid Build Coastguard Worker delta_us = (bpf_ktime_get_ns() - startp->ts) / 1000;
76*387f9dfdSAndroid Build Coastguard Worker
77*387f9dfdSAndroid Build Coastguard Worker /* setup info_t key */
78*387f9dfdSAndroid Build Coastguard Worker cmd_flags = BPF_CORE_READ(req, cmd_flags);
79*387f9dfdSAndroid Build Coastguard Worker
80*387f9dfdSAndroid Build Coastguard Worker disk = get_disk(req);
81*387f9dfdSAndroid Build Coastguard Worker info.major = BPF_CORE_READ(disk, major);
82*387f9dfdSAndroid Build Coastguard Worker info.minor = BPF_CORE_READ(disk, first_minor);
83*387f9dfdSAndroid Build Coastguard Worker info.rwflag = !!((cmd_flags & REQ_OP_MASK) == REQ_OP_WRITE);
84*387f9dfdSAndroid Build Coastguard Worker
85*387f9dfdSAndroid Build Coastguard Worker whop = bpf_map_lookup_elem(&whobyreq, &req);
86*387f9dfdSAndroid Build Coastguard Worker if (whop) {
87*387f9dfdSAndroid Build Coastguard Worker info.pid = whop->pid;
88*387f9dfdSAndroid Build Coastguard Worker __builtin_memcpy(&info.name, whop->name, sizeof(info.name));
89*387f9dfdSAndroid Build Coastguard Worker }
90*387f9dfdSAndroid Build Coastguard Worker
91*387f9dfdSAndroid Build Coastguard Worker valp = bpf_map_lookup_or_try_init(&counts, &info, &zero);
92*387f9dfdSAndroid Build Coastguard Worker
93*387f9dfdSAndroid Build Coastguard Worker if (valp) {
94*387f9dfdSAndroid Build Coastguard Worker /* save stats */
95*387f9dfdSAndroid Build Coastguard Worker valp->us += delta_us;
96*387f9dfdSAndroid Build Coastguard Worker valp->bytes += startp->data_len;
97*387f9dfdSAndroid Build Coastguard Worker valp->io++;
98*387f9dfdSAndroid Build Coastguard Worker }
99*387f9dfdSAndroid Build Coastguard Worker
100*387f9dfdSAndroid Build Coastguard Worker bpf_map_delete_elem(&start, &req);
101*387f9dfdSAndroid Build Coastguard Worker bpf_map_delete_elem(&whobyreq, &req);
102*387f9dfdSAndroid Build Coastguard Worker
103*387f9dfdSAndroid Build Coastguard Worker return 0;
104*387f9dfdSAndroid Build Coastguard Worker }
105*387f9dfdSAndroid Build Coastguard Worker
106*387f9dfdSAndroid Build Coastguard Worker SEC("kprobe/blk_account_io_start")
BPF_KPROBE(blk_account_io_start,struct request * req)107*387f9dfdSAndroid Build Coastguard Worker int BPF_KPROBE(blk_account_io_start, struct request *req)
108*387f9dfdSAndroid Build Coastguard Worker {
109*387f9dfdSAndroid Build Coastguard Worker return trace_start(req);
110*387f9dfdSAndroid Build Coastguard Worker }
111*387f9dfdSAndroid Build Coastguard Worker
112*387f9dfdSAndroid Build Coastguard Worker SEC("kprobe/blk_account_io_done")
BPF_KPROBE(blk_account_io_done,struct request * req)113*387f9dfdSAndroid Build Coastguard Worker int BPF_KPROBE(blk_account_io_done, struct request *req)
114*387f9dfdSAndroid Build Coastguard Worker {
115*387f9dfdSAndroid Build Coastguard Worker return trace_done(req);
116*387f9dfdSAndroid Build Coastguard Worker }
117*387f9dfdSAndroid Build Coastguard Worker
118*387f9dfdSAndroid Build Coastguard Worker SEC("kprobe/__blk_account_io_start")
BPF_KPROBE(__blk_account_io_start,struct request * req)119*387f9dfdSAndroid Build Coastguard Worker int BPF_KPROBE(__blk_account_io_start, struct request *req)
120*387f9dfdSAndroid Build Coastguard Worker {
121*387f9dfdSAndroid Build Coastguard Worker return trace_start(req);
122*387f9dfdSAndroid Build Coastguard Worker }
123*387f9dfdSAndroid Build Coastguard Worker
124*387f9dfdSAndroid Build Coastguard Worker SEC("kprobe/__blk_account_io_done")
BPF_KPROBE(__blk_account_io_done,struct request * req)125*387f9dfdSAndroid Build Coastguard Worker int BPF_KPROBE(__blk_account_io_done, struct request *req)
126*387f9dfdSAndroid Build Coastguard Worker {
127*387f9dfdSAndroid Build Coastguard Worker return trace_done(req);
128*387f9dfdSAndroid Build Coastguard Worker }
129*387f9dfdSAndroid Build Coastguard Worker
130*387f9dfdSAndroid Build Coastguard Worker SEC("tp_btf/block_io_start")
BPF_PROG(block_io_start,struct request * req)131*387f9dfdSAndroid Build Coastguard Worker int BPF_PROG(block_io_start, struct request *req)
132*387f9dfdSAndroid Build Coastguard Worker {
133*387f9dfdSAndroid Build Coastguard Worker return trace_start(req);
134*387f9dfdSAndroid Build Coastguard Worker }
135*387f9dfdSAndroid Build Coastguard Worker
136*387f9dfdSAndroid Build Coastguard Worker SEC("tp_btf/block_io_done")
BPF_PROG(block_io_done,struct request * req)137*387f9dfdSAndroid Build Coastguard Worker int BPF_PROG(block_io_done, struct request *req)
138*387f9dfdSAndroid Build Coastguard Worker {
139*387f9dfdSAndroid Build Coastguard Worker return trace_done(req);
140*387f9dfdSAndroid Build Coastguard Worker }
141*387f9dfdSAndroid Build Coastguard Worker
142*387f9dfdSAndroid Build Coastguard Worker char LICENSE[] SEC("license") = "GPL";
143