xref: /aosp_15_r20/external/bcc/tools/biolatency.py (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env python
2*387f9dfdSAndroid Build Coastguard Worker# @lint-avoid-python-3-compatibility-imports
3*387f9dfdSAndroid Build Coastguard Worker#
4*387f9dfdSAndroid Build Coastguard Worker# biolatency    Summarize block device I/O latency as a histogram.
5*387f9dfdSAndroid Build Coastguard Worker#       For Linux, uses BCC, eBPF.
6*387f9dfdSAndroid Build Coastguard Worker#
7*387f9dfdSAndroid Build Coastguard Worker# USAGE: biolatency [-h] [-T] [-Q] [-m] [-D] [-F] [-e] [-j] [-d DISK] [interval] [count]
8*387f9dfdSAndroid Build Coastguard Worker#
9*387f9dfdSAndroid Build Coastguard Worker# Copyright (c) 2015 Brendan Gregg.
10*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License")
11*387f9dfdSAndroid Build Coastguard Worker#
12*387f9dfdSAndroid Build Coastguard Worker# 20-Sep-2015   Brendan Gregg   Created this.
13*387f9dfdSAndroid Build Coastguard Worker# 31-Mar-2022   Rocky Xing      Added disk filter support.
14*387f9dfdSAndroid Build Coastguard Worker# 01-Aug-2023   Jerome Marchand Added support for block tracepoints
15*387f9dfdSAndroid Build Coastguard Worker
16*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function
17*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF
18*387f9dfdSAndroid Build Coastguard Workerfrom time import sleep, strftime
19*387f9dfdSAndroid Build Coastguard Workerimport argparse
20*387f9dfdSAndroid Build Coastguard Workerimport ctypes as ct
21*387f9dfdSAndroid Build Coastguard Workerimport os
22*387f9dfdSAndroid Build Coastguard Worker
23*387f9dfdSAndroid Build Coastguard Worker# arguments
24*387f9dfdSAndroid Build Coastguard Workerexamples = """examples:
25*387f9dfdSAndroid Build Coastguard Worker    ./biolatency                    # summarize block I/O latency as a histogram
26*387f9dfdSAndroid Build Coastguard Worker    ./biolatency 1 10               # print 1 second summaries, 10 times
27*387f9dfdSAndroid Build Coastguard Worker    ./biolatency -mT 1              # 1s summaries, milliseconds, and timestamps
28*387f9dfdSAndroid Build Coastguard Worker    ./biolatency -Q                 # include OS queued time in I/O time
29*387f9dfdSAndroid Build Coastguard Worker    ./biolatency -D                 # show each disk device separately
30*387f9dfdSAndroid Build Coastguard Worker    ./biolatency -F                 # show I/O flags separately
31*387f9dfdSAndroid Build Coastguard Worker    ./biolatency -j                 # print a dictionary
32*387f9dfdSAndroid Build Coastguard Worker    ./biolatency -e                 # show extension summary(total, average)
33*387f9dfdSAndroid Build Coastguard Worker    ./biolatency -d sdc             # Trace sdc only
34*387f9dfdSAndroid Build Coastguard Worker"""
35*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser(
36*387f9dfdSAndroid Build Coastguard Worker    description="Summarize block device I/O latency as a histogram",
37*387f9dfdSAndroid Build Coastguard Worker    formatter_class=argparse.RawDescriptionHelpFormatter,
38*387f9dfdSAndroid Build Coastguard Worker    epilog=examples)
39*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-T", "--timestamp", action="store_true",
40*387f9dfdSAndroid Build Coastguard Worker    help="include timestamp on output")
41*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-Q", "--queued", action="store_true",
42*387f9dfdSAndroid Build Coastguard Worker    help="include OS queued time in I/O time")
43*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-m", "--milliseconds", action="store_true",
44*387f9dfdSAndroid Build Coastguard Worker    help="millisecond histogram")
45*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-D", "--disks", action="store_true",
46*387f9dfdSAndroid Build Coastguard Worker    help="print a histogram per disk device")
47*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-F", "--flags", action="store_true",
48*387f9dfdSAndroid Build Coastguard Worker    help="print a histogram per set of I/O flags")
49*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-e", "--extension", action="store_true",
50*387f9dfdSAndroid Build Coastguard Worker    help="summarize average/total value")
51*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("interval", nargs="?", default=99999999,
52*387f9dfdSAndroid Build Coastguard Worker    help="output interval, in seconds")
53*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("count", nargs="?", default=99999999,
54*387f9dfdSAndroid Build Coastguard Worker    help="number of outputs")
55*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--ebpf", action="store_true",
56*387f9dfdSAndroid Build Coastguard Worker    help=argparse.SUPPRESS)
57*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-j", "--json", action="store_true",
58*387f9dfdSAndroid Build Coastguard Worker    help="json output")
59*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-d", "--disk", type=str,
60*387f9dfdSAndroid Build Coastguard Worker    help="Trace this disk only")
61*387f9dfdSAndroid Build Coastguard Worker
62*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args()
63*387f9dfdSAndroid Build Coastguard Workercountdown = int(args.count)
64*387f9dfdSAndroid Build Coastguard Workerdebug = 0
65*387f9dfdSAndroid Build Coastguard Worker
66*387f9dfdSAndroid Build Coastguard Workerif args.flags and args.disks:
67*387f9dfdSAndroid Build Coastguard Worker    print("ERROR: can only use -D or -F. Exiting.")
68*387f9dfdSAndroid Build Coastguard Worker    exit()
69*387f9dfdSAndroid Build Coastguard Worker
70*387f9dfdSAndroid Build Coastguard Worker# define BPF program
71*387f9dfdSAndroid Build Coastguard Workerbpf_text = """
72*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h>
73*387f9dfdSAndroid Build Coastguard Worker#include <linux/blk-mq.h>
74*387f9dfdSAndroid Build Coastguard Worker
75*387f9dfdSAndroid Build Coastguard Workertypedef struct disk_key {
76*387f9dfdSAndroid Build Coastguard Worker    dev_t dev;
77*387f9dfdSAndroid Build Coastguard Worker    u64 slot;
78*387f9dfdSAndroid Build Coastguard Worker} disk_key_t;
79*387f9dfdSAndroid Build Coastguard Worker
80*387f9dfdSAndroid Build Coastguard Workertypedef struct flag_key {
81*387f9dfdSAndroid Build Coastguard Worker    u64 flags;
82*387f9dfdSAndroid Build Coastguard Worker    u64 slot;
83*387f9dfdSAndroid Build Coastguard Worker} flag_key_t;
84*387f9dfdSAndroid Build Coastguard Worker
85*387f9dfdSAndroid Build Coastguard Workertypedef struct ext_val {
86*387f9dfdSAndroid Build Coastguard Worker    u64 total;
87*387f9dfdSAndroid Build Coastguard Worker    u64 count;
88*387f9dfdSAndroid Build Coastguard Worker} ext_val_t;
89*387f9dfdSAndroid Build Coastguard Worker
90*387f9dfdSAndroid Build Coastguard Workerstruct tp_args {
91*387f9dfdSAndroid Build Coastguard Worker    u64 __unused__;
92*387f9dfdSAndroid Build Coastguard Worker    dev_t dev;
93*387f9dfdSAndroid Build Coastguard Worker    sector_t sector;
94*387f9dfdSAndroid Build Coastguard Worker    unsigned int nr_sector;
95*387f9dfdSAndroid Build Coastguard Worker    unsigned int bytes;
96*387f9dfdSAndroid Build Coastguard Worker    char rwbs[8];
97*387f9dfdSAndroid Build Coastguard Worker    char comm[16];
98*387f9dfdSAndroid Build Coastguard Worker    char cmd[];
99*387f9dfdSAndroid Build Coastguard Worker};
100*387f9dfdSAndroid Build Coastguard Worker
101*387f9dfdSAndroid Build Coastguard Workerstruct start_key {
102*387f9dfdSAndroid Build Coastguard Worker    dev_t dev;
103*387f9dfdSAndroid Build Coastguard Worker    u32 _pad;
104*387f9dfdSAndroid Build Coastguard Worker    sector_t sector;
105*387f9dfdSAndroid Build Coastguard Worker    CMD_FLAGS
106*387f9dfdSAndroid Build Coastguard Worker};
107*387f9dfdSAndroid Build Coastguard Worker
108*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(start, struct start_key);
109*387f9dfdSAndroid Build Coastguard WorkerSTORAGE
110*387f9dfdSAndroid Build Coastguard Worker
111*387f9dfdSAndroid Build Coastguard Workerstatic dev_t ddevt(struct gendisk *disk) {
112*387f9dfdSAndroid Build Coastguard Worker    return (disk->major  << 20) | disk->first_minor;
113*387f9dfdSAndroid Build Coastguard Worker}
114*387f9dfdSAndroid Build Coastguard Worker
115*387f9dfdSAndroid Build Coastguard Worker// time block I/O
116*387f9dfdSAndroid Build Coastguard Workerstatic int __trace_req_start(struct start_key key)
117*387f9dfdSAndroid Build Coastguard Worker{
118*387f9dfdSAndroid Build Coastguard Worker    DISK_FILTER
119*387f9dfdSAndroid Build Coastguard Worker
120*387f9dfdSAndroid Build Coastguard Worker    u64 ts = bpf_ktime_get_ns();
121*387f9dfdSAndroid Build Coastguard Worker    start.update(&key, &ts);
122*387f9dfdSAndroid Build Coastguard Worker    return 0;
123*387f9dfdSAndroid Build Coastguard Worker}
124*387f9dfdSAndroid Build Coastguard Worker
125*387f9dfdSAndroid Build Coastguard Workerint trace_req_start(struct pt_regs *ctx, struct request *req)
126*387f9dfdSAndroid Build Coastguard Worker{
127*387f9dfdSAndroid Build Coastguard Worker    struct start_key key = {
128*387f9dfdSAndroid Build Coastguard Worker        .dev = ddevt(req->__RQ_DISK__),
129*387f9dfdSAndroid Build Coastguard Worker        .sector = req->__sector
130*387f9dfdSAndroid Build Coastguard Worker    };
131*387f9dfdSAndroid Build Coastguard Worker
132*387f9dfdSAndroid Build Coastguard Worker    SET_FLAGS
133*387f9dfdSAndroid Build Coastguard Worker
134*387f9dfdSAndroid Build Coastguard Worker    return __trace_req_start(key);
135*387f9dfdSAndroid Build Coastguard Worker}
136*387f9dfdSAndroid Build Coastguard Worker
137*387f9dfdSAndroid Build Coastguard Workerint trace_req_start_tp(struct tp_args *args)
138*387f9dfdSAndroid Build Coastguard Worker{
139*387f9dfdSAndroid Build Coastguard Worker    struct start_key key = {
140*387f9dfdSAndroid Build Coastguard Worker        .dev = args->dev,
141*387f9dfdSAndroid Build Coastguard Worker        .sector = args->sector
142*387f9dfdSAndroid Build Coastguard Worker    };
143*387f9dfdSAndroid Build Coastguard Worker
144*387f9dfdSAndroid Build Coastguard Worker    return __trace_req_start(key);
145*387f9dfdSAndroid Build Coastguard Worker}
146*387f9dfdSAndroid Build Coastguard Worker
147*387f9dfdSAndroid Build Coastguard Worker// output
148*387f9dfdSAndroid Build Coastguard Workerstatic int __trace_req_done(struct start_key key)
149*387f9dfdSAndroid Build Coastguard Worker{
150*387f9dfdSAndroid Build Coastguard Worker    u64 *tsp, delta;
151*387f9dfdSAndroid Build Coastguard Worker
152*387f9dfdSAndroid Build Coastguard Worker    // fetch timestamp and calculate delta
153*387f9dfdSAndroid Build Coastguard Worker    tsp = start.lookup(&key);
154*387f9dfdSAndroid Build Coastguard Worker    if (tsp == 0) {
155*387f9dfdSAndroid Build Coastguard Worker        return 0;   // missed issue
156*387f9dfdSAndroid Build Coastguard Worker    }
157*387f9dfdSAndroid Build Coastguard Worker    delta = bpf_ktime_get_ns() - *tsp;
158*387f9dfdSAndroid Build Coastguard Worker
159*387f9dfdSAndroid Build Coastguard Worker    FACTOR
160*387f9dfdSAndroid Build Coastguard Worker
161*387f9dfdSAndroid Build Coastguard Worker    // store as histogram
162*387f9dfdSAndroid Build Coastguard Worker    STORE
163*387f9dfdSAndroid Build Coastguard Worker
164*387f9dfdSAndroid Build Coastguard Worker    start.delete(&key);
165*387f9dfdSAndroid Build Coastguard Worker    return 0;
166*387f9dfdSAndroid Build Coastguard Worker}
167*387f9dfdSAndroid Build Coastguard Worker
168*387f9dfdSAndroid Build Coastguard Workerint trace_req_done(struct pt_regs *ctx, struct request *req)
169*387f9dfdSAndroid Build Coastguard Worker{
170*387f9dfdSAndroid Build Coastguard Worker    struct start_key key = {
171*387f9dfdSAndroid Build Coastguard Worker        .dev = ddevt(req->__RQ_DISK__),
172*387f9dfdSAndroid Build Coastguard Worker        .sector = req->__sector
173*387f9dfdSAndroid Build Coastguard Worker    };
174*387f9dfdSAndroid Build Coastguard Worker
175*387f9dfdSAndroid Build Coastguard Worker    SET_FLAGS
176*387f9dfdSAndroid Build Coastguard Worker
177*387f9dfdSAndroid Build Coastguard Worker    return __trace_req_done(key);
178*387f9dfdSAndroid Build Coastguard Worker}
179*387f9dfdSAndroid Build Coastguard Worker
180*387f9dfdSAndroid Build Coastguard Workerint trace_req_done_tp(struct tp_args *args)
181*387f9dfdSAndroid Build Coastguard Worker{
182*387f9dfdSAndroid Build Coastguard Worker    struct start_key key = {
183*387f9dfdSAndroid Build Coastguard Worker        .dev = args->dev,
184*387f9dfdSAndroid Build Coastguard Worker        .sector = args->sector
185*387f9dfdSAndroid Build Coastguard Worker    };
186*387f9dfdSAndroid Build Coastguard Worker
187*387f9dfdSAndroid Build Coastguard Worker    return __trace_req_done(key);
188*387f9dfdSAndroid Build Coastguard Worker}
189*387f9dfdSAndroid Build Coastguard Worker"""
190*387f9dfdSAndroid Build Coastguard Worker
191*387f9dfdSAndroid Build Coastguard Worker# code substitutions
192*387f9dfdSAndroid Build Coastguard Workerif args.milliseconds:
193*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('FACTOR', 'delta /= 1000000;')
194*387f9dfdSAndroid Build Coastguard Worker    label = "msecs"
195*387f9dfdSAndroid Build Coastguard Workerelse:
196*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('FACTOR', 'delta /= 1000;')
197*387f9dfdSAndroid Build Coastguard Worker    label = "usecs"
198*387f9dfdSAndroid Build Coastguard Worker
199*387f9dfdSAndroid Build Coastguard Workerstorage_str = ""
200*387f9dfdSAndroid Build Coastguard Workerstore_str = ""
201*387f9dfdSAndroid Build Coastguard Workerif args.disks:
202*387f9dfdSAndroid Build Coastguard Worker    storage_str += "BPF_HISTOGRAM(dist, disk_key_t);"
203*387f9dfdSAndroid Build Coastguard Worker    disks_str = """
204*387f9dfdSAndroid Build Coastguard Worker    disk_key_t dkey = {};
205*387f9dfdSAndroid Build Coastguard Worker    dkey.dev = key.dev;
206*387f9dfdSAndroid Build Coastguard Worker    dkey.slot = bpf_log2l(delta);
207*387f9dfdSAndroid Build Coastguard Worker    dist.atomic_increment(dkey);
208*387f9dfdSAndroid Build Coastguard Worker    """
209*387f9dfdSAndroid Build Coastguard Worker    store_str += disks_str
210*387f9dfdSAndroid Build Coastguard Workerelif args.flags:
211*387f9dfdSAndroid Build Coastguard Worker    storage_str += "BPF_HISTOGRAM(dist, flag_key_t);"
212*387f9dfdSAndroid Build Coastguard Worker    store_str += """
213*387f9dfdSAndroid Build Coastguard Worker    flag_key_t fkey = {.slot = bpf_log2l(delta)};
214*387f9dfdSAndroid Build Coastguard Worker    fkey.flags = key.flags;
215*387f9dfdSAndroid Build Coastguard Worker    dist.atomic_increment(fkey);
216*387f9dfdSAndroid Build Coastguard Worker    """
217*387f9dfdSAndroid Build Coastguard Workerelse:
218*387f9dfdSAndroid Build Coastguard Worker    storage_str += "BPF_HISTOGRAM(dist);"
219*387f9dfdSAndroid Build Coastguard Worker    store_str += "dist.atomic_increment(bpf_log2l(delta));"
220*387f9dfdSAndroid Build Coastguard Worker
221*387f9dfdSAndroid Build Coastguard Workerif args.disk is not None:
222*387f9dfdSAndroid Build Coastguard Worker    disk_path = os.path.join('/dev', args.disk)
223*387f9dfdSAndroid Build Coastguard Worker    if not os.path.exists(disk_path):
224*387f9dfdSAndroid Build Coastguard Worker        print("no such disk '%s'" % args.disk)
225*387f9dfdSAndroid Build Coastguard Worker        exit(1)
226*387f9dfdSAndroid Build Coastguard Worker
227*387f9dfdSAndroid Build Coastguard Worker    stat_info = os.stat(disk_path)
228*387f9dfdSAndroid Build Coastguard Worker    dev = os.major(stat_info.st_rdev) << 20 | os.minor(stat_info.st_rdev)
229*387f9dfdSAndroid Build Coastguard Worker
230*387f9dfdSAndroid Build Coastguard Worker    disk_filter_str = """
231*387f9dfdSAndroid Build Coastguard Worker    if(key.dev != %s) {
232*387f9dfdSAndroid Build Coastguard Worker        return 0;
233*387f9dfdSAndroid Build Coastguard Worker    }
234*387f9dfdSAndroid Build Coastguard Worker    """ % (dev)
235*387f9dfdSAndroid Build Coastguard Worker
236*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('DISK_FILTER', disk_filter_str)
237*387f9dfdSAndroid Build Coastguard Workerelse:
238*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('DISK_FILTER', '')
239*387f9dfdSAndroid Build Coastguard Worker
240*387f9dfdSAndroid Build Coastguard Workerif args.extension:
241*387f9dfdSAndroid Build Coastguard Worker    storage_str += "BPF_ARRAY(extension, ext_val_t, 1);"
242*387f9dfdSAndroid Build Coastguard Worker    store_str += """
243*387f9dfdSAndroid Build Coastguard Worker    u32 index = 0;
244*387f9dfdSAndroid Build Coastguard Worker    ext_val_t *ext_val = extension.lookup(&index);
245*387f9dfdSAndroid Build Coastguard Worker    if (ext_val) {
246*387f9dfdSAndroid Build Coastguard Worker        lock_xadd(&ext_val->total, delta);
247*387f9dfdSAndroid Build Coastguard Worker        lock_xadd(&ext_val->count, 1);
248*387f9dfdSAndroid Build Coastguard Worker    }
249*387f9dfdSAndroid Build Coastguard Worker    """
250*387f9dfdSAndroid Build Coastguard Worker
251*387f9dfdSAndroid Build Coastguard Workerbpf_text = bpf_text.replace("STORAGE", storage_str)
252*387f9dfdSAndroid Build Coastguard Workerbpf_text = bpf_text.replace("STORE", store_str)
253*387f9dfdSAndroid Build Coastguard Workerif BPF.kernel_struct_has_field(b'request', b'rq_disk') == 1:
254*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('__RQ_DISK__', 'rq_disk')
255*387f9dfdSAndroid Build Coastguard Workerelse:
256*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('__RQ_DISK__', 'q->disk')
257*387f9dfdSAndroid Build Coastguard Workerif args.flags:
258*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('CMD_FLAGS', 'u64 flags;')
259*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('SET_FLAGS', 'key.flags = req->cmd_flags;')
260*387f9dfdSAndroid Build Coastguard Workerelse:
261*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('CMD_FLAGS', '')
262*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('SET_FLAGS', '')
263*387f9dfdSAndroid Build Coastguard Worker
264*387f9dfdSAndroid Build Coastguard Workerif debug or args.ebpf:
265*387f9dfdSAndroid Build Coastguard Worker    print(bpf_text)
266*387f9dfdSAndroid Build Coastguard Worker    if args.ebpf:
267*387f9dfdSAndroid Build Coastguard Worker        exit()
268*387f9dfdSAndroid Build Coastguard Worker
269*387f9dfdSAndroid Build Coastguard Worker# load BPF program
270*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text)
271*387f9dfdSAndroid Build Coastguard Workerif args.queued:
272*387f9dfdSAndroid Build Coastguard Worker    if BPF.get_kprobe_functions(b'__blk_account_io_start'):
273*387f9dfdSAndroid Build Coastguard Worker        b.attach_kprobe(event="__blk_account_io_start", fn_name="trace_req_start")
274*387f9dfdSAndroid Build Coastguard Worker    elif BPF.get_kprobe_functions(b'blk_account_io_start'):
275*387f9dfdSAndroid Build Coastguard Worker        b.attach_kprobe(event="blk_account_io_start", fn_name="trace_req_start")
276*387f9dfdSAndroid Build Coastguard Worker    else:
277*387f9dfdSAndroid Build Coastguard Worker        if args.flags:
278*387f9dfdSAndroid Build Coastguard Worker            # Some flags are accessible in the rwbs field (RAHEAD, SYNC and META)
279*387f9dfdSAndroid Build Coastguard Worker            # but other aren't. Disable the -F option for tracepoint for now.
280*387f9dfdSAndroid Build Coastguard Worker            print("ERROR: blk_account_io_start probe not available. Can't use -F.")
281*387f9dfdSAndroid Build Coastguard Worker            exit()
282*387f9dfdSAndroid Build Coastguard Worker        b.attach_tracepoint(tp="block:block_io_start", fn_name="trace_req_start_tp")
283*387f9dfdSAndroid Build Coastguard Workerelse:
284*387f9dfdSAndroid Build Coastguard Worker    if BPF.get_kprobe_functions(b'blk_start_request'):
285*387f9dfdSAndroid Build Coastguard Worker        b.attach_kprobe(event="blk_start_request", fn_name="trace_req_start")
286*387f9dfdSAndroid Build Coastguard Worker    b.attach_kprobe(event="blk_mq_start_request", fn_name="trace_req_start")
287*387f9dfdSAndroid Build Coastguard Worker
288*387f9dfdSAndroid Build Coastguard Workerif BPF.get_kprobe_functions(b'__blk_account_io_done'):
289*387f9dfdSAndroid Build Coastguard Worker    b.attach_kprobe(event="__blk_account_io_done", fn_name="trace_req_done")
290*387f9dfdSAndroid Build Coastguard Workerelif BPF.get_kprobe_functions(b'blk_account_io_done'):
291*387f9dfdSAndroid Build Coastguard Worker    b.attach_kprobe(event="blk_account_io_done", fn_name="trace_req_done")
292*387f9dfdSAndroid Build Coastguard Workerelse:
293*387f9dfdSAndroid Build Coastguard Worker    if args.flags:
294*387f9dfdSAndroid Build Coastguard Worker        print("ERROR: blk_account_io_done probe not available. Can't use -F.")
295*387f9dfdSAndroid Build Coastguard Worker        exit()
296*387f9dfdSAndroid Build Coastguard Worker    b.attach_tracepoint(tp="block:block_io_done", fn_name="trace_req_done_tp")
297*387f9dfdSAndroid Build Coastguard Worker
298*387f9dfdSAndroid Build Coastguard Worker
299*387f9dfdSAndroid Build Coastguard Workerif not args.json:
300*387f9dfdSAndroid Build Coastguard Worker    print("Tracing block device I/O... Hit Ctrl-C to end.")
301*387f9dfdSAndroid Build Coastguard Worker
302*387f9dfdSAndroid Build Coastguard Worker# cache disk major,minor -> diskname
303*387f9dfdSAndroid Build Coastguard Workerdiskstats = "/proc/diskstats"
304*387f9dfdSAndroid Build Coastguard Workerdisklookup = {}
305*387f9dfdSAndroid Build Coastguard Workerwith open(diskstats) as stats:
306*387f9dfdSAndroid Build Coastguard Worker    for line in stats:
307*387f9dfdSAndroid Build Coastguard Worker        a = line.split()
308*387f9dfdSAndroid Build Coastguard Worker        disklookup[a[0] + "," + a[1]] = a[2]
309*387f9dfdSAndroid Build Coastguard Worker
310*387f9dfdSAndroid Build Coastguard Workerdef disk_print(d):
311*387f9dfdSAndroid Build Coastguard Worker    major = d >> 20
312*387f9dfdSAndroid Build Coastguard Worker    minor = d & ((1 << 20) - 1)
313*387f9dfdSAndroid Build Coastguard Worker
314*387f9dfdSAndroid Build Coastguard Worker    disk = str(major) + "," + str(minor)
315*387f9dfdSAndroid Build Coastguard Worker    if disk in disklookup:
316*387f9dfdSAndroid Build Coastguard Worker        diskname = disklookup[disk]
317*387f9dfdSAndroid Build Coastguard Worker    else:
318*387f9dfdSAndroid Build Coastguard Worker        diskname = "?"
319*387f9dfdSAndroid Build Coastguard Worker
320*387f9dfdSAndroid Build Coastguard Worker    return diskname
321*387f9dfdSAndroid Build Coastguard Worker
322*387f9dfdSAndroid Build Coastguard Worker# see blk_fill_rwbs():
323*387f9dfdSAndroid Build Coastguard Workerreq_opf = {
324*387f9dfdSAndroid Build Coastguard Worker    0: "Read",
325*387f9dfdSAndroid Build Coastguard Worker    1: "Write",
326*387f9dfdSAndroid Build Coastguard Worker    2: "Flush",
327*387f9dfdSAndroid Build Coastguard Worker    3: "Discard",
328*387f9dfdSAndroid Build Coastguard Worker    5: "SecureErase",
329*387f9dfdSAndroid Build Coastguard Worker    6: "ZoneReset",
330*387f9dfdSAndroid Build Coastguard Worker    7: "WriteSame",
331*387f9dfdSAndroid Build Coastguard Worker    9: "WriteZeros"
332*387f9dfdSAndroid Build Coastguard Worker}
333*387f9dfdSAndroid Build Coastguard WorkerREQ_OP_BITS = 8
334*387f9dfdSAndroid Build Coastguard WorkerREQ_OP_MASK = ((1 << REQ_OP_BITS) - 1)
335*387f9dfdSAndroid Build Coastguard WorkerREQ_SYNC = 1 << (REQ_OP_BITS + 3)
336*387f9dfdSAndroid Build Coastguard WorkerREQ_META = 1 << (REQ_OP_BITS + 4)
337*387f9dfdSAndroid Build Coastguard WorkerREQ_PRIO = 1 << (REQ_OP_BITS + 5)
338*387f9dfdSAndroid Build Coastguard WorkerREQ_NOMERGE = 1 << (REQ_OP_BITS + 6)
339*387f9dfdSAndroid Build Coastguard WorkerREQ_IDLE = 1 << (REQ_OP_BITS + 7)
340*387f9dfdSAndroid Build Coastguard WorkerREQ_FUA = 1 << (REQ_OP_BITS + 9)
341*387f9dfdSAndroid Build Coastguard WorkerREQ_RAHEAD = 1 << (REQ_OP_BITS + 11)
342*387f9dfdSAndroid Build Coastguard WorkerREQ_BACKGROUND = 1 << (REQ_OP_BITS + 12)
343*387f9dfdSAndroid Build Coastguard WorkerREQ_NOWAIT = 1 << (REQ_OP_BITS + 13)
344*387f9dfdSAndroid Build Coastguard Workerdef flags_print(flags):
345*387f9dfdSAndroid Build Coastguard Worker    desc = ""
346*387f9dfdSAndroid Build Coastguard Worker    # operation
347*387f9dfdSAndroid Build Coastguard Worker    if flags & REQ_OP_MASK in req_opf:
348*387f9dfdSAndroid Build Coastguard Worker        desc = req_opf[flags & REQ_OP_MASK]
349*387f9dfdSAndroid Build Coastguard Worker    else:
350*387f9dfdSAndroid Build Coastguard Worker        desc = "Unknown"
351*387f9dfdSAndroid Build Coastguard Worker    # flags
352*387f9dfdSAndroid Build Coastguard Worker    if flags & REQ_SYNC:
353*387f9dfdSAndroid Build Coastguard Worker        desc = "Sync-" + desc
354*387f9dfdSAndroid Build Coastguard Worker    if flags & REQ_META:
355*387f9dfdSAndroid Build Coastguard Worker        desc = "Metadata-" + desc
356*387f9dfdSAndroid Build Coastguard Worker    if flags & REQ_FUA:
357*387f9dfdSAndroid Build Coastguard Worker        desc = "ForcedUnitAccess-" + desc
358*387f9dfdSAndroid Build Coastguard Worker    if flags & REQ_PRIO:
359*387f9dfdSAndroid Build Coastguard Worker        desc = "Priority-" + desc
360*387f9dfdSAndroid Build Coastguard Worker    if flags & REQ_NOMERGE:
361*387f9dfdSAndroid Build Coastguard Worker        desc = "NoMerge-" + desc
362*387f9dfdSAndroid Build Coastguard Worker    if flags & REQ_IDLE:
363*387f9dfdSAndroid Build Coastguard Worker        desc = "Idle-" + desc
364*387f9dfdSAndroid Build Coastguard Worker    if flags & REQ_RAHEAD:
365*387f9dfdSAndroid Build Coastguard Worker        desc = "ReadAhead-" + desc
366*387f9dfdSAndroid Build Coastguard Worker    if flags & REQ_BACKGROUND:
367*387f9dfdSAndroid Build Coastguard Worker        desc = "Background-" + desc
368*387f9dfdSAndroid Build Coastguard Worker    if flags & REQ_NOWAIT:
369*387f9dfdSAndroid Build Coastguard Worker        desc = "NoWait-" + desc
370*387f9dfdSAndroid Build Coastguard Worker    return desc
371*387f9dfdSAndroid Build Coastguard Worker
372*387f9dfdSAndroid Build Coastguard Worker# output
373*387f9dfdSAndroid Build Coastguard Workerexiting = 0 if args.interval else 1
374*387f9dfdSAndroid Build Coastguard Workerdist = b.get_table("dist")
375*387f9dfdSAndroid Build Coastguard Workerif args.extension:
376*387f9dfdSAndroid Build Coastguard Worker    extension = b.get_table("extension")
377*387f9dfdSAndroid Build Coastguard Workerwhile (1):
378*387f9dfdSAndroid Build Coastguard Worker    try:
379*387f9dfdSAndroid Build Coastguard Worker        sleep(int(args.interval))
380*387f9dfdSAndroid Build Coastguard Worker    except KeyboardInterrupt:
381*387f9dfdSAndroid Build Coastguard Worker        exiting = 1
382*387f9dfdSAndroid Build Coastguard Worker
383*387f9dfdSAndroid Build Coastguard Worker    print()
384*387f9dfdSAndroid Build Coastguard Worker    if args.json:
385*387f9dfdSAndroid Build Coastguard Worker        if args.timestamp:
386*387f9dfdSAndroid Build Coastguard Worker            print("%-8s\n" % strftime("%H:%M:%S"), end="")
387*387f9dfdSAndroid Build Coastguard Worker
388*387f9dfdSAndroid Build Coastguard Worker        if args.flags:
389*387f9dfdSAndroid Build Coastguard Worker            dist.print_json_hist(label, "flags", flags_print)
390*387f9dfdSAndroid Build Coastguard Worker        else:
391*387f9dfdSAndroid Build Coastguard Worker            dist.print_json_hist(label, "disk", disk_print)
392*387f9dfdSAndroid Build Coastguard Worker
393*387f9dfdSAndroid Build Coastguard Worker    else:
394*387f9dfdSAndroid Build Coastguard Worker        if args.timestamp:
395*387f9dfdSAndroid Build Coastguard Worker            print("%-8s\n" % strftime("%H:%M:%S"), end="")
396*387f9dfdSAndroid Build Coastguard Worker
397*387f9dfdSAndroid Build Coastguard Worker        if args.flags:
398*387f9dfdSAndroid Build Coastguard Worker            dist.print_log2_hist(label, "flags", flags_print)
399*387f9dfdSAndroid Build Coastguard Worker        else:
400*387f9dfdSAndroid Build Coastguard Worker            dist.print_log2_hist(label, "disk", disk_print)
401*387f9dfdSAndroid Build Coastguard Worker        if args.extension:
402*387f9dfdSAndroid Build Coastguard Worker            total = extension[0].total
403*387f9dfdSAndroid Build Coastguard Worker            count = extension[0].count
404*387f9dfdSAndroid Build Coastguard Worker            if count > 0:
405*387f9dfdSAndroid Build Coastguard Worker                print("\navg = %ld %s, total: %ld %s, count: %ld\n" %
406*387f9dfdSAndroid Build Coastguard Worker                      (total / count, label, total, label, count))
407*387f9dfdSAndroid Build Coastguard Worker            extension.clear()
408*387f9dfdSAndroid Build Coastguard Worker
409*387f9dfdSAndroid Build Coastguard Worker    dist.clear()
410*387f9dfdSAndroid Build Coastguard Worker
411*387f9dfdSAndroid Build Coastguard Worker    countdown -= 1
412*387f9dfdSAndroid Build Coastguard Worker    if exiting or countdown == 0:
413*387f9dfdSAndroid Build Coastguard Worker        exit()
414