1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/python 2*387f9dfdSAndroid Build Coastguard Worker# @lint-avoid-python-3-compatibility-imports 3*387f9dfdSAndroid Build Coastguard Worker# 4*387f9dfdSAndroid Build Coastguard Worker# biosnoop Trace block device I/O and print details including issuing PID. 5*387f9dfdSAndroid Build Coastguard Worker# For Linux, uses BCC, eBPF. 6*387f9dfdSAndroid Build Coastguard Worker# 7*387f9dfdSAndroid Build Coastguard Worker# This uses in-kernel eBPF maps to cache process details (PID and comm) by I/O 8*387f9dfdSAndroid Build Coastguard Worker# request, as well as a starting timestamp for calculating I/O latency. 9*387f9dfdSAndroid Build Coastguard Worker# 10*387f9dfdSAndroid Build Coastguard Worker# Copyright (c) 2015 Brendan Gregg. 11*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License") 12*387f9dfdSAndroid Build Coastguard Worker# 13*387f9dfdSAndroid Build Coastguard Worker# 16-Sep-2015 Brendan Gregg Created this. 14*387f9dfdSAndroid Build Coastguard Worker 15*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function 16*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF 17*387f9dfdSAndroid Build Coastguard Worker 18*387f9dfdSAndroid Build Coastguard Worker# load BPF program 19*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=""" 20*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h> 21*387f9dfdSAndroid Build Coastguard Worker#include <linux/blkdev.h> 22*387f9dfdSAndroid Build Coastguard Worker 23*387f9dfdSAndroid Build Coastguard Workerstruct val_t { 24*387f9dfdSAndroid Build Coastguard Worker u32 pid; 25*387f9dfdSAndroid Build Coastguard Worker char name[TASK_COMM_LEN]; 26*387f9dfdSAndroid Build Coastguard Worker}; 27*387f9dfdSAndroid Build Coastguard Worker 28*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(start, struct request *); 29*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(infobyreq, struct request *, struct val_t); 30*387f9dfdSAndroid Build Coastguard Worker 31*387f9dfdSAndroid Build Coastguard Worker// cache PID and comm by-req 32*387f9dfdSAndroid Build Coastguard Workerint trace_pid_start(struct pt_regs *ctx, struct request *req) 33*387f9dfdSAndroid Build Coastguard Worker{ 34*387f9dfdSAndroid Build Coastguard Worker struct val_t val = {}; 35*387f9dfdSAndroid Build Coastguard Worker 36*387f9dfdSAndroid Build Coastguard Worker if (bpf_get_current_comm(&val.name, sizeof(val.name)) == 0) { 37*387f9dfdSAndroid Build Coastguard Worker val.pid = bpf_get_current_pid_tgid(); 38*387f9dfdSAndroid Build Coastguard Worker infobyreq.update(&req, &val); 39*387f9dfdSAndroid Build Coastguard Worker } 40*387f9dfdSAndroid Build Coastguard Worker 41*387f9dfdSAndroid Build Coastguard Worker return 0; 42*387f9dfdSAndroid Build Coastguard Worker} 43*387f9dfdSAndroid Build Coastguard Worker 44*387f9dfdSAndroid Build Coastguard Worker// time block I/O 45*387f9dfdSAndroid Build Coastguard Workerint trace_req_start(struct pt_regs *ctx, struct request *req) 46*387f9dfdSAndroid Build Coastguard Worker{ 47*387f9dfdSAndroid Build Coastguard Worker u64 ts; 48*387f9dfdSAndroid Build Coastguard Worker 49*387f9dfdSAndroid Build Coastguard Worker ts = bpf_ktime_get_ns(); 50*387f9dfdSAndroid Build Coastguard Worker start.update(&req, &ts); 51*387f9dfdSAndroid Build Coastguard Worker 52*387f9dfdSAndroid Build Coastguard Worker return 0; 53*387f9dfdSAndroid Build Coastguard Worker} 54*387f9dfdSAndroid Build Coastguard Worker 55*387f9dfdSAndroid Build Coastguard Worker// output 56*387f9dfdSAndroid Build Coastguard Workerint trace_req_completion(struct pt_regs *ctx, struct request *req) 57*387f9dfdSAndroid Build Coastguard Worker{ 58*387f9dfdSAndroid Build Coastguard Worker u64 *tsp, delta; 59*387f9dfdSAndroid Build Coastguard Worker u32 *pidp = 0; 60*387f9dfdSAndroid Build Coastguard Worker struct val_t *valp; 61*387f9dfdSAndroid Build Coastguard Worker 62*387f9dfdSAndroid Build Coastguard Worker // fetch timestamp and calculate delta 63*387f9dfdSAndroid Build Coastguard Worker tsp = start.lookup(&req); 64*387f9dfdSAndroid Build Coastguard Worker if (tsp == 0) { 65*387f9dfdSAndroid Build Coastguard Worker // missed tracing issue 66*387f9dfdSAndroid Build Coastguard Worker return 0; 67*387f9dfdSAndroid Build Coastguard Worker } 68*387f9dfdSAndroid Build Coastguard Worker delta = bpf_ktime_get_ns() - *tsp; 69*387f9dfdSAndroid Build Coastguard Worker 70*387f9dfdSAndroid Build Coastguard Worker // 71*387f9dfdSAndroid Build Coastguard Worker // Fetch and output issuing pid and comm. 72*387f9dfdSAndroid Build Coastguard Worker // As bpf_trace_prink() is limited to a maximum of 1 string and 2 73*387f9dfdSAndroid Build Coastguard Worker // integers, we'll use more than one to output the data. 74*387f9dfdSAndroid Build Coastguard Worker // 75*387f9dfdSAndroid Build Coastguard Worker valp = infobyreq.lookup(&req); 76*387f9dfdSAndroid Build Coastguard Worker if (valp == 0) { 77*387f9dfdSAndroid Build Coastguard Worker bpf_trace_printk("0 0 ? %d\\n", req->__data_len); 78*387f9dfdSAndroid Build Coastguard Worker } else { 79*387f9dfdSAndroid Build Coastguard Worker bpf_trace_printk("0 %d %s %d\\n", valp->pid, valp->name, 80*387f9dfdSAndroid Build Coastguard Worker req->__data_len); 81*387f9dfdSAndroid Build Coastguard Worker } 82*387f9dfdSAndroid Build Coastguard Worker 83*387f9dfdSAndroid Build Coastguard Worker // output remaining details 84*387f9dfdSAndroid Build Coastguard Worker if (req->cmd_flags & REQ_WRITE) { 85*387f9dfdSAndroid Build Coastguard Worker bpf_trace_printk("1 W %s %d %d ?\\n", req->rq_disk->disk_name, 86*387f9dfdSAndroid Build Coastguard Worker req->__sector, delta / 1000); 87*387f9dfdSAndroid Build Coastguard Worker } else { 88*387f9dfdSAndroid Build Coastguard Worker bpf_trace_printk("1 R %s %d %d ?\\n", req->rq_disk->disk_name, 89*387f9dfdSAndroid Build Coastguard Worker req->__sector, delta / 1000); 90*387f9dfdSAndroid Build Coastguard Worker } 91*387f9dfdSAndroid Build Coastguard Worker 92*387f9dfdSAndroid Build Coastguard Worker start.delete(&req); 93*387f9dfdSAndroid Build Coastguard Worker infobyreq.delete(&req); 94*387f9dfdSAndroid Build Coastguard Worker 95*387f9dfdSAndroid Build Coastguard Worker return 0; 96*387f9dfdSAndroid Build Coastguard Worker} 97*387f9dfdSAndroid Build Coastguard Worker""", debug=0) 98*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event="blk_account_io_start", fn_name="trace_pid_start") 99*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event="blk_start_request", fn_name="trace_req_start") 100*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event="blk_mq_start_request", fn_name="trace_req_start") 101*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event="blk_account_io_done", 102*387f9dfdSAndroid Build Coastguard Worker fn_name="trace_req_completion") 103*387f9dfdSAndroid Build Coastguard Worker 104*387f9dfdSAndroid Build Coastguard Worker# header 105*387f9dfdSAndroid Build Coastguard Workerprint("%-14s %-14s %-6s %-7s %-2s %-9s %-7s %7s" % ("TIME(s)", "COMM", "PID", 106*387f9dfdSAndroid Build Coastguard Worker "DISK", "T", "SECTOR", "BYTES", "LAT(ms)")) 107*387f9dfdSAndroid Build Coastguard Worker 108*387f9dfdSAndroid Build Coastguard Workerstart_ts = 0 109*387f9dfdSAndroid Build Coastguard Worker 110*387f9dfdSAndroid Build Coastguard Worker# format output 111*387f9dfdSAndroid Build Coastguard Workerwhile 1: 112*387f9dfdSAndroid Build Coastguard Worker (task, pid, cpu, flags, ts, msg) = b.trace_fields() 113*387f9dfdSAndroid Build Coastguard Worker args = msg.split(" ") 114*387f9dfdSAndroid Build Coastguard Worker 115*387f9dfdSAndroid Build Coastguard Worker if start_ts == 0: 116*387f9dfdSAndroid Build Coastguard Worker start_ts = ts 117*387f9dfdSAndroid Build Coastguard Worker 118*387f9dfdSAndroid Build Coastguard Worker if args[0] == "0": 119*387f9dfdSAndroid Build Coastguard Worker (real_pid, real_comm, bytes_s) = (args[1], args[2], args[3]) 120*387f9dfdSAndroid Build Coastguard Worker continue 121*387f9dfdSAndroid Build Coastguard Worker else: 122*387f9dfdSAndroid Build Coastguard Worker (type_s, disk_s, sector_s, us_s) = (args[1], args[2], args[3], 123*387f9dfdSAndroid Build Coastguard Worker args[4]) 124*387f9dfdSAndroid Build Coastguard Worker 125*387f9dfdSAndroid Build Coastguard Worker ms = float(int(us_s, 10)) / 1000 126*387f9dfdSAndroid Build Coastguard Worker 127*387f9dfdSAndroid Build Coastguard Worker print("%-14.9f %-14.14s %-6s %-7s %-2s %-9s %-7s %7.2f" % ( 128*387f9dfdSAndroid Build Coastguard Worker ts - start_ts, real_comm, real_pid, disk_s, type_s, sector_s, 129*387f9dfdSAndroid Build Coastguard Worker bytes_s, ms)) 130