• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/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