#!/usr/bin/python # # disksnoop.py Trace block device I/O: basic version of iosnoop. # For Linux, uses BCC, eBPF. Embedded C. # # Written as a basic example of tracing latency. # # Copyright (c) 2015 Brendan Gregg. # Licensed under the Apache License, Version 2.0 (the "License") # # 11-Aug-2015 Brendan Gregg Created this. from __future__ import print_function from bcc import BPF REQ_WRITE = 1 # from include/linux/blk_types.h # load BPF program b = BPF(text=""" #include <uapi/linux/ptrace.h> #include <linux/blkdev.h> BPF_HASH(start, struct request *); void trace_start(struct pt_regs *ctx, struct request *req) { // stash start timestamp by request ptr u64 ts = bpf_ktime_get_ns(); start.update(&req, &ts); } void trace_completion(struct pt_regs *ctx, struct request *req) { u64 *tsp, delta; tsp = start.lookup(&req); if (tsp != 0) { delta = bpf_ktime_get_ns() - *tsp; bpf_trace_printk("%d %x %d\\n", req->__data_len, req->cmd_flags, delta / 1000); start.delete(&req); } } """) b.attach_kprobe(event="blk_start_request", fn_name="trace_start") b.attach_kprobe(event="blk_mq_start_request", fn_name="trace_start") b.attach_kprobe(event="blk_account_io_completion", fn_name="trace_completion") # header print("%-18s %-2s %-7s %8s" % ("TIME(s)", "T", "BYTES", "LAT(ms)")) # format output while 1: (task, pid, cpu, flags, ts, msg) = b.trace_fields() (bytes_s, bflags_s, us_s) = msg.split() if int(bflags_s, 16) & REQ_WRITE: type_s = "W" elif bytes_s == "0": # see blk_fill_rwbs() for logic type_s = "M" else: type_s = "R" ms = float(int(us_s, 10)) / 1000 print("%-18.9f %-2s %-7s %8.2f" % (ts, type_s, bytes_s, ms))