1#!/usr/bin/env python 2# 3# disksnoop.py Trace block device I/O: basic version of iosnoop. 4# For Linux, uses BCC, eBPF. Embedded C. 5# 6# Written as a basic example of tracing latency. 7# 8# Copyright (c) 2015 Brendan Gregg. 9# Licensed under the Apache License, Version 2.0 (the "License") 10# 11# 11-Aug-2015 Brendan Gregg Created this. 12 13from __future__ import print_function 14from bcc import BPF 15 16REQ_WRITE = 1 # from include/linux/blk_types.h 17 18# load BPF program 19b = BPF(text=""" 20#include <uapi/linux/ptrace.h> 21#include <linux/blkdev.h> 22 23BPF_HASH(start, struct request *); 24 25void trace_start(struct pt_regs *ctx, struct request *req) { 26 // stash start timestamp by request ptr 27 u64 ts = bpf_ktime_get_ns(); 28 29 start.update(&req, &ts); 30} 31 32void trace_completion(struct pt_regs *ctx, struct request *req) { 33 u64 *tsp, delta; 34 35 tsp = start.lookup(&req); 36 if (tsp != 0) { 37 delta = bpf_ktime_get_ns() - *tsp; 38 bpf_trace_printk("%d %x %d\\n", req->__data_len, 39 req->cmd_flags, delta / 1000); 40 start.delete(&req); 41 } 42} 43""") 44 45b.attach_kprobe(event="blk_start_request", fn_name="trace_start") 46b.attach_kprobe(event="blk_mq_start_request", fn_name="trace_start") 47b.attach_kprobe(event="blk_account_io_completion", fn_name="trace_completion") 48 49# header 50print("%-18s %-2s %-7s %8s" % ("TIME(s)", "T", "BYTES", "LAT(ms)")) 51 52# format output 53while 1: 54 (task, pid, cpu, flags, ts, msg) = b.trace_fields() 55 (bytes_s, bflags_s, us_s) = msg.split() 56 57 if int(bflags_s, 16) & REQ_WRITE: 58 type_s = "W" 59 elif bytes_s == "0": # see blk_fill_rwbs() for logic 60 type_s = "M" 61 else: 62 type_s = "R" 63 ms = float(int(us_s, 10)) / 1000 64 65 print("%-18.9f %-2s %-7s %8.2f" % (ts, type_s, bytes_s, ms)) 66