xref: /aosp_15_r20/external/bcc/tools/biosnoop.lua (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env bcc-lua
2*387f9dfdSAndroid Build Coastguard Worker--[[
3*387f9dfdSAndroid Build Coastguard WorkerCopyright 2016 GitHub, Inc
4*387f9dfdSAndroid Build Coastguard Worker
5*387f9dfdSAndroid Build Coastguard WorkerLicensed under the Apache License, Version 2.0 (the "License");
6*387f9dfdSAndroid Build Coastguard Workeryou may not use this file except in compliance with the License.
7*387f9dfdSAndroid Build Coastguard WorkerYou may obtain a copy of the License at
8*387f9dfdSAndroid Build Coastguard Worker
9*387f9dfdSAndroid Build Coastguard Workerhttp://www.apache.org/licenses/LICENSE-2.0
10*387f9dfdSAndroid Build Coastguard Worker
11*387f9dfdSAndroid Build Coastguard WorkerUnless required by applicable law or agreed to in writing, software
12*387f9dfdSAndroid Build Coastguard Workerdistributed under the License is distributed on an "AS IS" BASIS,
13*387f9dfdSAndroid Build Coastguard WorkerWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*387f9dfdSAndroid Build Coastguard WorkerSee the License for the specific language governing permissions and
15*387f9dfdSAndroid Build Coastguard Workerlimitations under the License.
16*387f9dfdSAndroid Build Coastguard Worker--]]
17*387f9dfdSAndroid Build Coastguard Worker
18*387f9dfdSAndroid Build Coastguard Workerlocal program = [[
19*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h>
20*387f9dfdSAndroid Build Coastguard Worker#include <linux/blkdev.h>
21*387f9dfdSAndroid Build Coastguard Worker
22*387f9dfdSAndroid Build Coastguard Workerstruct val_t {
23*387f9dfdSAndroid Build Coastguard Worker    u32 pid;
24*387f9dfdSAndroid Build Coastguard Worker    char name[TASK_COMM_LEN];
25*387f9dfdSAndroid Build Coastguard Worker};
26*387f9dfdSAndroid Build Coastguard Worker
27*387f9dfdSAndroid Build Coastguard Workerstruct data_t {
28*387f9dfdSAndroid Build Coastguard Worker    u32 pid;
29*387f9dfdSAndroid Build Coastguard Worker    u64 rwflag;
30*387f9dfdSAndroid Build Coastguard Worker    u64 delta;
31*387f9dfdSAndroid Build Coastguard Worker    u64 sector;
32*387f9dfdSAndroid Build Coastguard Worker    u64 len;
33*387f9dfdSAndroid Build Coastguard Worker    u64 ts;
34*387f9dfdSAndroid Build Coastguard Worker    char disk_name[DISK_NAME_LEN];
35*387f9dfdSAndroid Build Coastguard Worker    char name[TASK_COMM_LEN];
36*387f9dfdSAndroid Build Coastguard Worker};
37*387f9dfdSAndroid Build Coastguard Worker
38*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(start, struct request *);
39*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(infobyreq, struct request *, struct val_t);
40*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(events);
41*387f9dfdSAndroid Build Coastguard Worker
42*387f9dfdSAndroid Build Coastguard Worker// cache PID and comm by-req
43*387f9dfdSAndroid Build Coastguard Workerint trace_pid_start(struct pt_regs *ctx, struct request *req)
44*387f9dfdSAndroid Build Coastguard Worker{
45*387f9dfdSAndroid Build Coastguard Worker    struct val_t val = {};
46*387f9dfdSAndroid Build Coastguard Worker
47*387f9dfdSAndroid Build Coastguard Worker    if (bpf_get_current_comm(&val.name, sizeof(val.name)) == 0) {
48*387f9dfdSAndroid Build Coastguard Worker        val.pid = bpf_get_current_pid_tgid();
49*387f9dfdSAndroid Build Coastguard Worker        infobyreq.update(&req, &val);
50*387f9dfdSAndroid Build Coastguard Worker    }
51*387f9dfdSAndroid Build Coastguard Worker    return 0;
52*387f9dfdSAndroid Build Coastguard Worker}
53*387f9dfdSAndroid Build Coastguard Worker
54*387f9dfdSAndroid Build Coastguard Worker// time block I/O
55*387f9dfdSAndroid Build Coastguard Workerint trace_req_start(struct pt_regs *ctx, struct request *req)
56*387f9dfdSAndroid Build Coastguard Worker{
57*387f9dfdSAndroid Build Coastguard Worker    u64 ts;
58*387f9dfdSAndroid Build Coastguard Worker
59*387f9dfdSAndroid Build Coastguard Worker    ts = bpf_ktime_get_ns();
60*387f9dfdSAndroid Build Coastguard Worker    start.update(&req, &ts);
61*387f9dfdSAndroid Build Coastguard Worker
62*387f9dfdSAndroid Build Coastguard Worker    return 0;
63*387f9dfdSAndroid Build Coastguard Worker}
64*387f9dfdSAndroid Build Coastguard Worker
65*387f9dfdSAndroid Build Coastguard Worker// output
66*387f9dfdSAndroid Build Coastguard Workerint trace_req_completion(struct pt_regs *ctx, struct request *req)
67*387f9dfdSAndroid Build Coastguard Worker{
68*387f9dfdSAndroid Build Coastguard Worker    u64 *tsp, delta;
69*387f9dfdSAndroid Build Coastguard Worker    u32 *pidp = 0;
70*387f9dfdSAndroid Build Coastguard Worker    struct val_t *valp;
71*387f9dfdSAndroid Build Coastguard Worker    struct data_t data ={};
72*387f9dfdSAndroid Build Coastguard Worker    u64 ts;
73*387f9dfdSAndroid Build Coastguard Worker
74*387f9dfdSAndroid Build Coastguard Worker    // fetch timestamp and calculate delta
75*387f9dfdSAndroid Build Coastguard Worker    tsp = start.lookup(&req);
76*387f9dfdSAndroid Build Coastguard Worker    if (tsp == 0) {
77*387f9dfdSAndroid Build Coastguard Worker        // missed tracing issue
78*387f9dfdSAndroid Build Coastguard Worker        return 0;
79*387f9dfdSAndroid Build Coastguard Worker    }
80*387f9dfdSAndroid Build Coastguard Worker    ts = bpf_ktime_get_ns();
81*387f9dfdSAndroid Build Coastguard Worker    data.delta = ts - *tsp;
82*387f9dfdSAndroid Build Coastguard Worker    data.ts = ts / 1000;
83*387f9dfdSAndroid Build Coastguard Worker
84*387f9dfdSAndroid Build Coastguard Worker    valp = infobyreq.lookup(&req);
85*387f9dfdSAndroid Build Coastguard Worker    if (valp == 0) {
86*387f9dfdSAndroid Build Coastguard Worker        data.len = req->__data_len;
87*387f9dfdSAndroid Build Coastguard Worker        data.name[0] = '?';
88*387f9dfdSAndroid Build Coastguard Worker        data.name[1] = 0;
89*387f9dfdSAndroid Build Coastguard Worker    } else {
90*387f9dfdSAndroid Build Coastguard Worker        data.pid = valp->pid;
91*387f9dfdSAndroid Build Coastguard Worker        data.len = req->__data_len;
92*387f9dfdSAndroid Build Coastguard Worker        data.sector = req->__sector;
93*387f9dfdSAndroid Build Coastguard Worker        bpf_probe_read_kernel(&data.name, sizeof(data.name), valp->name);
94*387f9dfdSAndroid Build Coastguard Worker        bpf_probe_read_kernel(&data.disk_name, sizeof(data.disk_name),
95*387f9dfdSAndroid Build Coastguard Worker                       req->rq_disk->disk_name);
96*387f9dfdSAndroid Build Coastguard Worker    }
97*387f9dfdSAndroid Build Coastguard Worker
98*387f9dfdSAndroid Build Coastguard Worker/*
99*387f9dfdSAndroid Build Coastguard Worker * The following deals with a kernel version change (in mainline 4.7, although
100*387f9dfdSAndroid Build Coastguard Worker * it may be backported to earlier kernels) with how block request write flags
101*387f9dfdSAndroid Build Coastguard Worker * are tested. We handle both pre- and post-change versions here. Please avoid
102*387f9dfdSAndroid Build Coastguard Worker * kernel version tests like this as much as possible: they inflate the code,
103*387f9dfdSAndroid Build Coastguard Worker * test, and maintenance burden.
104*387f9dfdSAndroid Build Coastguard Worker */
105*387f9dfdSAndroid Build Coastguard Worker#ifdef REQ_WRITE
106*387f9dfdSAndroid Build Coastguard Worker    data.rwflag = !!(req->cmd_flags & REQ_WRITE);
107*387f9dfdSAndroid Build Coastguard Worker#elif defined(REQ_OP_SHIFT)
108*387f9dfdSAndroid Build Coastguard Worker    data.rwflag = !!((req->cmd_flags >> REQ_OP_SHIFT) == REQ_OP_WRITE);
109*387f9dfdSAndroid Build Coastguard Worker#else
110*387f9dfdSAndroid Build Coastguard Worker    data.rwflag = !!((req->cmd_flags & REQ_OP_MASK) == REQ_OP_WRITE);
111*387f9dfdSAndroid Build Coastguard Worker#endif
112*387f9dfdSAndroid Build Coastguard Worker
113*387f9dfdSAndroid Build Coastguard Worker    events.perf_submit(ctx,&data,sizeof(data));
114*387f9dfdSAndroid Build Coastguard Worker    start.delete(&req);
115*387f9dfdSAndroid Build Coastguard Worker    infobyreq.delete(&req);
116*387f9dfdSAndroid Build Coastguard Worker
117*387f9dfdSAndroid Build Coastguard Worker    return 0;
118*387f9dfdSAndroid Build Coastguard Worker}
119*387f9dfdSAndroid Build Coastguard Worker]]
120*387f9dfdSAndroid Build Coastguard Worker
121*387f9dfdSAndroid Build Coastguard Workerlocal ffi = require("ffi")
122*387f9dfdSAndroid Build Coastguard Worker
123*387f9dfdSAndroid Build Coastguard Workerreturn function(BPF, utils)
124*387f9dfdSAndroid Build Coastguard Worker  local bpf = BPF:new{text=program}
125*387f9dfdSAndroid Build Coastguard Worker
126*387f9dfdSAndroid Build Coastguard Worker  bpf:attach_kprobe{event="blk_account_io_start", fn_name="trace_pid_start"}
127*387f9dfdSAndroid Build Coastguard Worker  bpf:attach_kprobe{event="blk_start_request", fn_name="trace_req_start"}
128*387f9dfdSAndroid Build Coastguard Worker  bpf:attach_kprobe{event="blk_mq_start_request", fn_name="trace_req_start"}
129*387f9dfdSAndroid Build Coastguard Worker  bpf:attach_kprobe{event="blk_account_io_done",
130*387f9dfdSAndroid Build Coastguard Worker      fn_name="trace_req_completion"}
131*387f9dfdSAndroid Build Coastguard Worker
132*387f9dfdSAndroid Build Coastguard Worker  print("%-14s %-14s %-6s %-7s %-2s %-9s %-7s %7s" % {"TIME(s)", "COMM", "PID",
133*387f9dfdSAndroid Build Coastguard Worker    "DISK", "T", "SECTOR", "BYTES", "LAT(ms)"})
134*387f9dfdSAndroid Build Coastguard Worker
135*387f9dfdSAndroid Build Coastguard Worker  local rwflg = ""
136*387f9dfdSAndroid Build Coastguard Worker  local start_ts = 0
137*387f9dfdSAndroid Build Coastguard Worker  local prev_ts = 0
138*387f9dfdSAndroid Build Coastguard Worker  local delta = 0
139*387f9dfdSAndroid Build Coastguard Worker
140*387f9dfdSAndroid Build Coastguard Worker  local function print_event(cpu, event)
141*387f9dfdSAndroid Build Coastguard Worker    local val = -1
142*387f9dfdSAndroid Build Coastguard Worker    local event_pid = event.pid
143*387f9dfdSAndroid Build Coastguard Worker    local event_delta = tonumber(event.delta)
144*387f9dfdSAndroid Build Coastguard Worker    local event_sector = tonumber(event.sector)
145*387f9dfdSAndroid Build Coastguard Worker    local event_len = tonumber(event.len)
146*387f9dfdSAndroid Build Coastguard Worker    local event_ts = tonumber(event.ts)
147*387f9dfdSAndroid Build Coastguard Worker    local event_disk_name = ffi.string(event.disk_name)
148*387f9dfdSAndroid Build Coastguard Worker    local event_name = ffi.string(event.name)
149*387f9dfdSAndroid Build Coastguard Worker
150*387f9dfdSAndroid Build Coastguard Worker    if event.rwflag == 1 then
151*387f9dfdSAndroid Build Coastguard Worker      rwflg = "W"
152*387f9dfdSAndroid Build Coastguard Worker    end
153*387f9dfdSAndroid Build Coastguard Worker
154*387f9dfdSAndroid Build Coastguard Worker    if event.rwflag == 0 then
155*387f9dfdSAndroid Build Coastguard Worker      rwflg = "R"
156*387f9dfdSAndroid Build Coastguard Worker    end
157*387f9dfdSAndroid Build Coastguard Worker
158*387f9dfdSAndroid Build Coastguard Worker    if not event_name:match("%?") then
159*387f9dfdSAndroid Build Coastguard Worker      val = event_sector
160*387f9dfdSAndroid Build Coastguard Worker    end
161*387f9dfdSAndroid Build Coastguard Worker
162*387f9dfdSAndroid Build Coastguard Worker    if start_ts == 0 then
163*387f9dfdSAndroid Build Coastguard Worker      prev_ts = start_ts
164*387f9dfdSAndroid Build Coastguard Worker    end
165*387f9dfdSAndroid Build Coastguard Worker
166*387f9dfdSAndroid Build Coastguard Worker    if start_ts == 1 then
167*387f9dfdSAndroid Build Coastguard Worker      delta = delta + (event_ts - prev_ts)
168*387f9dfdSAndroid Build Coastguard Worker    end
169*387f9dfdSAndroid Build Coastguard Worker
170*387f9dfdSAndroid Build Coastguard Worker    print("%-14.9f %-14.14s %-6s %-7s %-2s %-9s %-7s %7.2f" % {
171*387f9dfdSAndroid Build Coastguard Worker      delta / 1000000, event_name, event_pid, event_disk_name, rwflg, val,
172*387f9dfdSAndroid Build Coastguard Worker      event_len, event_delta / 1000000})
173*387f9dfdSAndroid Build Coastguard Worker
174*387f9dfdSAndroid Build Coastguard Worker    prev_ts = event_ts
175*387f9dfdSAndroid Build Coastguard Worker    start_ts = 1
176*387f9dfdSAndroid Build Coastguard Worker  end
177*387f9dfdSAndroid Build Coastguard Worker
178*387f9dfdSAndroid Build Coastguard Worker  local TASK_COMM_LEN = 16 -- linux/sched.h
179*387f9dfdSAndroid Build Coastguard Worker  local DISK_NAME_LEN = 32 -- linux/genhd.h
180*387f9dfdSAndroid Build Coastguard Worker
181*387f9dfdSAndroid Build Coastguard Worker  bpf:get_table("events"):open_perf_buffer(print_event, [[
182*387f9dfdSAndroid Build Coastguard Worker    struct {
183*387f9dfdSAndroid Build Coastguard Worker      uint32_t pid;
184*387f9dfdSAndroid Build Coastguard Worker      uint64_t rwflag;
185*387f9dfdSAndroid Build Coastguard Worker      uint64_t delta;
186*387f9dfdSAndroid Build Coastguard Worker      uint64_t sector;
187*387f9dfdSAndroid Build Coastguard Worker      uint64_t len;
188*387f9dfdSAndroid Build Coastguard Worker      uint64_t ts;
189*387f9dfdSAndroid Build Coastguard Worker      char disk_name[$];
190*387f9dfdSAndroid Build Coastguard Worker      char name[$];
191*387f9dfdSAndroid Build Coastguard Worker    }
192*387f9dfdSAndroid Build Coastguard Worker  ]], {DISK_NAME_LEN, TASK_COMM_LEN}, 64)
193*387f9dfdSAndroid Build Coastguard Worker  bpf:perf_buffer_poll_loop()
194*387f9dfdSAndroid Build Coastguard Workerend
195