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