xref: /aosp_15_r20/external/bcc/tools/biotop.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# biotop  block device (disk) I/O by process.
5*387f9dfdSAndroid Build Coastguard Worker#         For Linux, uses BCC, eBPF.
6*387f9dfdSAndroid Build Coastguard Worker#
7*387f9dfdSAndroid Build Coastguard Worker# USAGE: biotop.py [-h] [-C] [-r MAXROWS] [-p PID] [interval] [count]
8*387f9dfdSAndroid Build Coastguard Worker#
9*387f9dfdSAndroid Build Coastguard Worker# This uses in-kernel eBPF maps to cache process details (PID and comm) by I/O
10*387f9dfdSAndroid Build Coastguard Worker# request, as well as a starting timestamp for calculating I/O latency.
11*387f9dfdSAndroid Build Coastguard Worker#
12*387f9dfdSAndroid Build Coastguard Worker# Copyright 2016 Netflix, Inc.
13*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License")
14*387f9dfdSAndroid Build Coastguard Worker#
15*387f9dfdSAndroid Build Coastguard Worker# 06-Feb-2016   Brendan Gregg   Created this.
16*387f9dfdSAndroid Build Coastguard Worker# 17-Mar-2022   Rocky Xing      Added PID filter support.
17*387f9dfdSAndroid Build Coastguard Worker# 01-Aug-2023   Jerome Marchand Added support for block tracepoints
18*387f9dfdSAndroid Build Coastguard Worker
19*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function
20*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF
21*387f9dfdSAndroid Build Coastguard Workerfrom time import sleep, strftime
22*387f9dfdSAndroid Build Coastguard Workerimport argparse
23*387f9dfdSAndroid Build Coastguard Workerfrom subprocess import call
24*387f9dfdSAndroid Build Coastguard Worker
25*387f9dfdSAndroid Build Coastguard Worker# arguments
26*387f9dfdSAndroid Build Coastguard Workerexamples = """examples:
27*387f9dfdSAndroid Build Coastguard Worker    ./biotop            # block device I/O top, 1 second refresh
28*387f9dfdSAndroid Build Coastguard Worker    ./biotop -C         # don't clear the screen
29*387f9dfdSAndroid Build Coastguard Worker    ./biotop -p 181     # only trace PID 181
30*387f9dfdSAndroid Build Coastguard Worker    ./biotop 5          # 5 second summaries
31*387f9dfdSAndroid Build Coastguard Worker    ./biotop 5 10       # 5 second summaries, 10 times only
32*387f9dfdSAndroid Build Coastguard Worker"""
33*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser(
34*387f9dfdSAndroid Build Coastguard Worker    description="Block device (disk) I/O by process",
35*387f9dfdSAndroid Build Coastguard Worker    formatter_class=argparse.RawDescriptionHelpFormatter,
36*387f9dfdSAndroid Build Coastguard Worker    epilog=examples)
37*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-C", "--noclear", action="store_true",
38*387f9dfdSAndroid Build Coastguard Worker    help="don't clear the screen")
39*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-r", "--maxrows", default=20,
40*387f9dfdSAndroid Build Coastguard Worker    help="maximum rows to print, default 20")
41*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-p", "--pid", type=int, metavar="PID",
42*387f9dfdSAndroid Build Coastguard Worker    help="trace this PID only")
43*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("interval", nargs="?", default=1,
44*387f9dfdSAndroid Build Coastguard Worker    help="output interval, in seconds")
45*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("count", nargs="?", default=99999999,
46*387f9dfdSAndroid Build Coastguard Worker    help="number of outputs")
47*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--ebpf", action="store_true",
48*387f9dfdSAndroid Build Coastguard Worker    help=argparse.SUPPRESS)
49*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args()
50*387f9dfdSAndroid Build Coastguard Workerinterval = int(args.interval)
51*387f9dfdSAndroid Build Coastguard Workercountdown = int(args.count)
52*387f9dfdSAndroid Build Coastguard Workermaxrows = int(args.maxrows)
53*387f9dfdSAndroid Build Coastguard Workerclear = not int(args.noclear)
54*387f9dfdSAndroid Build Coastguard Worker
55*387f9dfdSAndroid Build Coastguard Worker# linux stats
56*387f9dfdSAndroid Build Coastguard Workerloadavg = "/proc/loadavg"
57*387f9dfdSAndroid Build Coastguard Workerdiskstats = "/proc/diskstats"
58*387f9dfdSAndroid Build Coastguard Worker
59*387f9dfdSAndroid Build Coastguard Worker# load BPF program
60*387f9dfdSAndroid Build Coastguard Workerbpf_text = """
61*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h>
62*387f9dfdSAndroid Build Coastguard Worker#include <linux/blk-mq.h>
63*387f9dfdSAndroid Build Coastguard Worker
64*387f9dfdSAndroid Build Coastguard Worker// for saving the timestamp and __data_len of each request
65*387f9dfdSAndroid Build Coastguard Workerstruct start_req_t {
66*387f9dfdSAndroid Build Coastguard Worker    u64 ts;
67*387f9dfdSAndroid Build Coastguard Worker    u64 data_len;
68*387f9dfdSAndroid Build Coastguard Worker};
69*387f9dfdSAndroid Build Coastguard Worker
70*387f9dfdSAndroid Build Coastguard Worker// for saving process info by request
71*387f9dfdSAndroid Build Coastguard Workerstruct who_t {
72*387f9dfdSAndroid Build Coastguard Worker    u32 pid;
73*387f9dfdSAndroid Build Coastguard Worker    char name[TASK_COMM_LEN];
74*387f9dfdSAndroid Build Coastguard Worker};
75*387f9dfdSAndroid Build Coastguard Worker
76*387f9dfdSAndroid Build Coastguard Worker// the key for the output summary
77*387f9dfdSAndroid Build Coastguard Workerstruct info_t {
78*387f9dfdSAndroid Build Coastguard Worker    u32 pid;
79*387f9dfdSAndroid Build Coastguard Worker    int rwflag;
80*387f9dfdSAndroid Build Coastguard Worker    int major;
81*387f9dfdSAndroid Build Coastguard Worker    int minor;
82*387f9dfdSAndroid Build Coastguard Worker    char name[TASK_COMM_LEN];
83*387f9dfdSAndroid Build Coastguard Worker};
84*387f9dfdSAndroid Build Coastguard Worker
85*387f9dfdSAndroid Build Coastguard Worker// the value of the output summary
86*387f9dfdSAndroid Build Coastguard Workerstruct val_t {
87*387f9dfdSAndroid Build Coastguard Worker    u64 bytes;
88*387f9dfdSAndroid Build Coastguard Worker    u64 us;
89*387f9dfdSAndroid Build Coastguard Worker    u32 io;
90*387f9dfdSAndroid Build Coastguard Worker};
91*387f9dfdSAndroid Build Coastguard Worker
92*387f9dfdSAndroid Build Coastguard Workerstruct tp_args {
93*387f9dfdSAndroid Build Coastguard Worker    u64 __unused__;
94*387f9dfdSAndroid Build Coastguard Worker    dev_t dev;
95*387f9dfdSAndroid Build Coastguard Worker    sector_t sector;
96*387f9dfdSAndroid Build Coastguard Worker    unsigned int nr_sector;
97*387f9dfdSAndroid Build Coastguard Worker    unsigned int bytes;
98*387f9dfdSAndroid Build Coastguard Worker    char rwbs[8];
99*387f9dfdSAndroid Build Coastguard Worker    char comm[16];
100*387f9dfdSAndroid Build Coastguard Worker    char cmd[];
101*387f9dfdSAndroid Build Coastguard Worker};
102*387f9dfdSAndroid Build Coastguard Worker
103*387f9dfdSAndroid Build Coastguard Workerstruct hash_key {
104*387f9dfdSAndroid Build Coastguard Worker    dev_t dev;
105*387f9dfdSAndroid Build Coastguard Worker    u32 _pad;
106*387f9dfdSAndroid Build Coastguard Worker    sector_t sector;
107*387f9dfdSAndroid Build Coastguard Worker};
108*387f9dfdSAndroid Build Coastguard Worker
109*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(start, struct hash_key, struct start_req_t);
110*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(whobyreq, struct hash_key, struct who_t);
111*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(counts, struct info_t, struct val_t);
112*387f9dfdSAndroid Build Coastguard Worker
113*387f9dfdSAndroid Build Coastguard Workerstatic dev_t ddevt(struct gendisk *disk) {
114*387f9dfdSAndroid Build Coastguard Worker    return (disk->major  << 20) | disk->first_minor;
115*387f9dfdSAndroid Build Coastguard Worker}
116*387f9dfdSAndroid Build Coastguard Worker
117*387f9dfdSAndroid Build Coastguard Worker// cache PID and comm by-req
118*387f9dfdSAndroid Build Coastguard Workerstatic int __trace_pid_start(struct hash_key key)
119*387f9dfdSAndroid Build Coastguard Worker{
120*387f9dfdSAndroid Build Coastguard Worker    struct who_t who;
121*387f9dfdSAndroid Build Coastguard Worker    u32 pid;
122*387f9dfdSAndroid Build Coastguard Worker
123*387f9dfdSAndroid Build Coastguard Worker    if (bpf_get_current_comm(&who.name, sizeof(who.name)) == 0) {
124*387f9dfdSAndroid Build Coastguard Worker        pid = bpf_get_current_pid_tgid() >> 32;
125*387f9dfdSAndroid Build Coastguard Worker        if (FILTER_PID)
126*387f9dfdSAndroid Build Coastguard Worker            return 0;
127*387f9dfdSAndroid Build Coastguard Worker
128*387f9dfdSAndroid Build Coastguard Worker        who.pid = pid;
129*387f9dfdSAndroid Build Coastguard Worker        whobyreq.update(&key, &who);
130*387f9dfdSAndroid Build Coastguard Worker    }
131*387f9dfdSAndroid Build Coastguard Worker
132*387f9dfdSAndroid Build Coastguard Worker    return 0;
133*387f9dfdSAndroid Build Coastguard Worker}
134*387f9dfdSAndroid Build Coastguard Worker
135*387f9dfdSAndroid Build Coastguard Workerint trace_pid_start(struct pt_regs *ctx, struct request *req)
136*387f9dfdSAndroid Build Coastguard Worker{
137*387f9dfdSAndroid Build Coastguard Worker    struct hash_key key = {
138*387f9dfdSAndroid Build Coastguard Worker        .dev = ddevt(req->__RQ_DISK__),
139*387f9dfdSAndroid Build Coastguard Worker        .sector = req->__sector
140*387f9dfdSAndroid Build Coastguard Worker    };
141*387f9dfdSAndroid Build Coastguard Worker
142*387f9dfdSAndroid Build Coastguard Worker    return __trace_pid_start(key);
143*387f9dfdSAndroid Build Coastguard Worker}
144*387f9dfdSAndroid Build Coastguard Worker
145*387f9dfdSAndroid Build Coastguard Workerint trace_pid_start_tp(struct tp_args *args)
146*387f9dfdSAndroid Build Coastguard Worker{
147*387f9dfdSAndroid Build Coastguard Worker    struct hash_key key = {
148*387f9dfdSAndroid Build Coastguard Worker        .dev = args->dev,
149*387f9dfdSAndroid Build Coastguard Worker        .sector = args->sector
150*387f9dfdSAndroid Build Coastguard Worker    };
151*387f9dfdSAndroid Build Coastguard Worker
152*387f9dfdSAndroid Build Coastguard Worker    return __trace_pid_start(key);
153*387f9dfdSAndroid Build Coastguard Worker}
154*387f9dfdSAndroid Build Coastguard Worker
155*387f9dfdSAndroid Build Coastguard Worker// time block I/O
156*387f9dfdSAndroid Build Coastguard Workerint trace_req_start(struct pt_regs *ctx, struct request *req)
157*387f9dfdSAndroid Build Coastguard Worker{
158*387f9dfdSAndroid Build Coastguard Worker    struct hash_key key = {
159*387f9dfdSAndroid Build Coastguard Worker        .dev = ddevt(req->__RQ_DISK__),
160*387f9dfdSAndroid Build Coastguard Worker        .sector = req->__sector
161*387f9dfdSAndroid Build Coastguard Worker    };
162*387f9dfdSAndroid Build Coastguard Worker    struct start_req_t start_req = {
163*387f9dfdSAndroid Build Coastguard Worker        .ts = bpf_ktime_get_ns(),
164*387f9dfdSAndroid Build Coastguard Worker        .data_len = req->__data_len
165*387f9dfdSAndroid Build Coastguard Worker    };
166*387f9dfdSAndroid Build Coastguard Worker    start.update(&key, &start_req);
167*387f9dfdSAndroid Build Coastguard Worker    return 0;
168*387f9dfdSAndroid Build Coastguard Worker}
169*387f9dfdSAndroid Build Coastguard Worker
170*387f9dfdSAndroid Build Coastguard Worker// output
171*387f9dfdSAndroid Build Coastguard Workerstatic int __trace_req_completion(struct hash_key key)
172*387f9dfdSAndroid Build Coastguard Worker{
173*387f9dfdSAndroid Build Coastguard Worker    struct start_req_t *startp;
174*387f9dfdSAndroid Build Coastguard Worker
175*387f9dfdSAndroid Build Coastguard Worker    // fetch timestamp and calculate delta
176*387f9dfdSAndroid Build Coastguard Worker    startp = start.lookup(&key);
177*387f9dfdSAndroid Build Coastguard Worker    if (startp == 0) {
178*387f9dfdSAndroid Build Coastguard Worker        return 0;    // missed tracing issue
179*387f9dfdSAndroid Build Coastguard Worker    }
180*387f9dfdSAndroid Build Coastguard Worker
181*387f9dfdSAndroid Build Coastguard Worker    struct who_t *whop;
182*387f9dfdSAndroid Build Coastguard Worker    u32 pid;
183*387f9dfdSAndroid Build Coastguard Worker
184*387f9dfdSAndroid Build Coastguard Worker    whop = whobyreq.lookup(&key);
185*387f9dfdSAndroid Build Coastguard Worker    pid = whop != 0 ? whop->pid : 0;
186*387f9dfdSAndroid Build Coastguard Worker    if (FILTER_PID) {
187*387f9dfdSAndroid Build Coastguard Worker        start.delete(&key);
188*387f9dfdSAndroid Build Coastguard Worker        if (whop != 0) {
189*387f9dfdSAndroid Build Coastguard Worker            whobyreq.delete(&key);
190*387f9dfdSAndroid Build Coastguard Worker        }
191*387f9dfdSAndroid Build Coastguard Worker        return 0;
192*387f9dfdSAndroid Build Coastguard Worker    }
193*387f9dfdSAndroid Build Coastguard Worker
194*387f9dfdSAndroid Build Coastguard Worker    struct val_t *valp, zero = {};
195*387f9dfdSAndroid Build Coastguard Worker    u64 delta_us = (bpf_ktime_get_ns() - startp->ts) / 1000;
196*387f9dfdSAndroid Build Coastguard Worker
197*387f9dfdSAndroid Build Coastguard Worker    // setup info_t key
198*387f9dfdSAndroid Build Coastguard Worker    struct info_t info = {};
199*387f9dfdSAndroid Build Coastguard Worker    info.major = key.dev >> 20;
200*387f9dfdSAndroid Build Coastguard Worker    info.minor = key.dev & ((1 << 20) - 1);
201*387f9dfdSAndroid Build Coastguard Worker/*
202*387f9dfdSAndroid Build Coastguard Worker * The following deals with a kernel version change (in mainline 4.7, although
203*387f9dfdSAndroid Build Coastguard Worker * it may be backported to earlier kernels) with how block request write flags
204*387f9dfdSAndroid Build Coastguard Worker * are tested. We handle both pre- and post-change versions here. Please avoid
205*387f9dfdSAndroid Build Coastguard Worker * kernel version tests like this as much as possible: they inflate the code,
206*387f9dfdSAndroid Build Coastguard Worker * test, and maintenance burden.
207*387f9dfdSAndroid Build Coastguard Worker */
208*387f9dfdSAndroid Build Coastguard Worker/*#ifdef REQ_WRITE
209*387f9dfdSAndroid Build Coastguard Worker    info.rwflag = !!(req->cmd_flags & REQ_WRITE);
210*387f9dfdSAndroid Build Coastguard Worker#elif defined(REQ_OP_SHIFT)
211*387f9dfdSAndroid Build Coastguard Worker    info.rwflag = !!((req->cmd_flags >> REQ_OP_SHIFT) == REQ_OP_WRITE);
212*387f9dfdSAndroid Build Coastguard Worker#else
213*387f9dfdSAndroid Build Coastguard Worker    info.rwflag = !!((req->cmd_flags & REQ_OP_MASK) == REQ_OP_WRITE);
214*387f9dfdSAndroid Build Coastguard Worker#endif*/
215*387f9dfdSAndroid Build Coastguard Worker
216*387f9dfdSAndroid Build Coastguard Worker    if (whop == 0) {
217*387f9dfdSAndroid Build Coastguard Worker        // missed pid who, save stats as pid 0
218*387f9dfdSAndroid Build Coastguard Worker        valp = counts.lookup_or_try_init(&info, &zero);
219*387f9dfdSAndroid Build Coastguard Worker    } else {
220*387f9dfdSAndroid Build Coastguard Worker        info.pid = whop->pid;
221*387f9dfdSAndroid Build Coastguard Worker        __builtin_memcpy(&info.name, whop->name, sizeof(info.name));
222*387f9dfdSAndroid Build Coastguard Worker        valp = counts.lookup_or_try_init(&info, &zero);
223*387f9dfdSAndroid Build Coastguard Worker    }
224*387f9dfdSAndroid Build Coastguard Worker
225*387f9dfdSAndroid Build Coastguard Worker    if (valp) {
226*387f9dfdSAndroid Build Coastguard Worker        // save stats
227*387f9dfdSAndroid Build Coastguard Worker        valp->us += delta_us;
228*387f9dfdSAndroid Build Coastguard Worker        valp->bytes += startp->data_len;
229*387f9dfdSAndroid Build Coastguard Worker        valp->io++;
230*387f9dfdSAndroid Build Coastguard Worker    }
231*387f9dfdSAndroid Build Coastguard Worker
232*387f9dfdSAndroid Build Coastguard Worker    start.delete(&key);
233*387f9dfdSAndroid Build Coastguard Worker    whobyreq.delete(&key);
234*387f9dfdSAndroid Build Coastguard Worker
235*387f9dfdSAndroid Build Coastguard Worker    return 0;
236*387f9dfdSAndroid Build Coastguard Worker}
237*387f9dfdSAndroid Build Coastguard Worker
238*387f9dfdSAndroid Build Coastguard Workerint trace_req_completion(struct pt_regs *ctx, struct request *req)
239*387f9dfdSAndroid Build Coastguard Worker{
240*387f9dfdSAndroid Build Coastguard Worker    struct hash_key key = {
241*387f9dfdSAndroid Build Coastguard Worker        .dev = ddevt(req->__RQ_DISK__),
242*387f9dfdSAndroid Build Coastguard Worker        .sector = req->__sector
243*387f9dfdSAndroid Build Coastguard Worker    };
244*387f9dfdSAndroid Build Coastguard Worker
245*387f9dfdSAndroid Build Coastguard Worker    return __trace_req_completion(key);
246*387f9dfdSAndroid Build Coastguard Worker}
247*387f9dfdSAndroid Build Coastguard Worker
248*387f9dfdSAndroid Build Coastguard Workerint trace_req_completion_tp(struct tp_args *args)
249*387f9dfdSAndroid Build Coastguard Worker{
250*387f9dfdSAndroid Build Coastguard Worker    struct hash_key key = {
251*387f9dfdSAndroid Build Coastguard Worker        .dev = args->dev,
252*387f9dfdSAndroid Build Coastguard Worker        .sector = args->sector
253*387f9dfdSAndroid Build Coastguard Worker    };
254*387f9dfdSAndroid Build Coastguard Worker
255*387f9dfdSAndroid Build Coastguard Worker    return __trace_req_completion(key);
256*387f9dfdSAndroid Build Coastguard Worker}
257*387f9dfdSAndroid Build Coastguard Worker"""
258*387f9dfdSAndroid Build Coastguard Worker
259*387f9dfdSAndroid Build Coastguard Workerif args.ebpf:
260*387f9dfdSAndroid Build Coastguard Worker    print(bpf_text)
261*387f9dfdSAndroid Build Coastguard Worker    exit()
262*387f9dfdSAndroid Build Coastguard Worker
263*387f9dfdSAndroid Build Coastguard Workerif BPF.kernel_struct_has_field(b'request', b'rq_disk') == 1:
264*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('__RQ_DISK__', 'rq_disk')
265*387f9dfdSAndroid Build Coastguard Workerelse:
266*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('__RQ_DISK__', 'q->disk')
267*387f9dfdSAndroid Build Coastguard Worker
268*387f9dfdSAndroid Build Coastguard Workerif args.pid is not None:
269*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('FILTER_PID', 'pid != %d' % args.pid)
270*387f9dfdSAndroid Build Coastguard Workerelse:
271*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('FILTER_PID', '0')
272*387f9dfdSAndroid Build Coastguard Worker
273*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text)
274*387f9dfdSAndroid Build Coastguard Workerif 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_pid_start")
276*387f9dfdSAndroid Build Coastguard Workerelif BPF.get_kprobe_functions(b'blk_account_io_start'):
277*387f9dfdSAndroid Build Coastguard Worker    b.attach_kprobe(event="blk_account_io_start", fn_name="trace_pid_start")
278*387f9dfdSAndroid Build Coastguard Workerelse:
279*387f9dfdSAndroid Build Coastguard Worker    b.attach_tracepoint(tp="block:block_io_start", fn_name="trace_pid_start_tp")
280*387f9dfdSAndroid Build Coastguard Workerif BPF.get_kprobe_functions(b'blk_start_request'):
281*387f9dfdSAndroid Build Coastguard Worker    b.attach_kprobe(event="blk_start_request", fn_name="trace_req_start")
282*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event="blk_mq_start_request", fn_name="trace_req_start")
283*387f9dfdSAndroid Build Coastguard Workerif BPF.get_kprobe_functions(b'__blk_account_io_done'):
284*387f9dfdSAndroid Build Coastguard Worker    b.attach_kprobe(event="__blk_account_io_done", fn_name="trace_req_completion")
285*387f9dfdSAndroid Build Coastguard Workerelif BPF.get_kprobe_functions(b'blk_account_io_done'):
286*387f9dfdSAndroid Build Coastguard Worker    b.attach_kprobe(event="blk_account_io_done", fn_name="trace_req_completion")
287*387f9dfdSAndroid Build Coastguard Workerelse:
288*387f9dfdSAndroid Build Coastguard Worker    b.attach_tracepoint(tp="block:block_io_done", fn_name="trace_req_completion_tp")
289*387f9dfdSAndroid Build Coastguard Worker
290*387f9dfdSAndroid Build Coastguard Workerprint('Tracing... Output every %d secs. Hit Ctrl-C to end' % interval)
291*387f9dfdSAndroid Build Coastguard Worker
292*387f9dfdSAndroid Build Coastguard Worker# cache disk major,minor -> diskname
293*387f9dfdSAndroid Build Coastguard Workerdisklookup = {}
294*387f9dfdSAndroid Build Coastguard Workerwith open(diskstats) as stats:
295*387f9dfdSAndroid Build Coastguard Worker    for line in stats:
296*387f9dfdSAndroid Build Coastguard Worker        a = line.split()
297*387f9dfdSAndroid Build Coastguard Worker        disklookup[a[0] + "," + a[1]] = a[2]
298*387f9dfdSAndroid Build Coastguard Worker
299*387f9dfdSAndroid Build Coastguard Worker# output
300*387f9dfdSAndroid Build Coastguard Workerexiting = 0
301*387f9dfdSAndroid Build Coastguard Workerwhile 1:
302*387f9dfdSAndroid Build Coastguard Worker    try:
303*387f9dfdSAndroid Build Coastguard Worker        sleep(interval)
304*387f9dfdSAndroid Build Coastguard Worker    except KeyboardInterrupt:
305*387f9dfdSAndroid Build Coastguard Worker        exiting = 1
306*387f9dfdSAndroid Build Coastguard Worker
307*387f9dfdSAndroid Build Coastguard Worker    # header
308*387f9dfdSAndroid Build Coastguard Worker    if clear:
309*387f9dfdSAndroid Build Coastguard Worker        call("clear")
310*387f9dfdSAndroid Build Coastguard Worker    else:
311*387f9dfdSAndroid Build Coastguard Worker        print()
312*387f9dfdSAndroid Build Coastguard Worker    with open(loadavg) as stats:
313*387f9dfdSAndroid Build Coastguard Worker        print("%-8s loadavg: %s" % (strftime("%H:%M:%S"), stats.read()))
314*387f9dfdSAndroid Build Coastguard Worker    print("%-7s %-16s %1s %-3s %-3s %-8s %5s %7s %6s" % ("PID", "COMM",
315*387f9dfdSAndroid Build Coastguard Worker        "D", "MAJ", "MIN", "DISK", "I/O", "Kbytes", "AVGms"))
316*387f9dfdSAndroid Build Coastguard Worker
317*387f9dfdSAndroid Build Coastguard Worker    # by-PID output
318*387f9dfdSAndroid Build Coastguard Worker    counts = b.get_table("counts")
319*387f9dfdSAndroid Build Coastguard Worker    line = 0
320*387f9dfdSAndroid Build Coastguard Worker    for k, v in reversed(sorted(counts.items(),
321*387f9dfdSAndroid Build Coastguard Worker                                key=lambda counts: counts[1].bytes)):
322*387f9dfdSAndroid Build Coastguard Worker
323*387f9dfdSAndroid Build Coastguard Worker        # lookup disk
324*387f9dfdSAndroid Build Coastguard Worker        disk = str(k.major) + "," + str(k.minor)
325*387f9dfdSAndroid Build Coastguard Worker        if disk in disklookup:
326*387f9dfdSAndroid Build Coastguard Worker            diskname = disklookup[disk]
327*387f9dfdSAndroid Build Coastguard Worker        else:
328*387f9dfdSAndroid Build Coastguard Worker            diskname = "?"
329*387f9dfdSAndroid Build Coastguard Worker
330*387f9dfdSAndroid Build Coastguard Worker        # print line
331*387f9dfdSAndroid Build Coastguard Worker        avg_ms = (float(v.us) / 1000) / v.io
332*387f9dfdSAndroid Build Coastguard Worker        print("%-7d %-16s %1s %-3d %-3d %-8s %5s %7s %6.2f" % (k.pid,
333*387f9dfdSAndroid Build Coastguard Worker            k.name.decode('utf-8', 'replace'), "W" if k.rwflag else "R",
334*387f9dfdSAndroid Build Coastguard Worker            k.major, k.minor, diskname, v.io, v.bytes / 1024, avg_ms))
335*387f9dfdSAndroid Build Coastguard Worker
336*387f9dfdSAndroid Build Coastguard Worker        line += 1
337*387f9dfdSAndroid Build Coastguard Worker        if line >= maxrows:
338*387f9dfdSAndroid Build Coastguard Worker            break
339*387f9dfdSAndroid Build Coastguard Worker    counts.clear()
340*387f9dfdSAndroid Build Coastguard Worker
341*387f9dfdSAndroid Build Coastguard Worker    countdown -= 1
342*387f9dfdSAndroid Build Coastguard Worker    if exiting or countdown == 0:
343*387f9dfdSAndroid Build Coastguard Worker        print("Detaching...")
344*387f9dfdSAndroid Build Coastguard Worker        exit()
345