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