disksnoop.py 1.63 KB
Newer Older
Brendan Gregg's avatar
Brendan Gregg committed
1
#!/usr/bin/python
2 3
#
# disksnoop.py	Trace block device I/O: basic version of iosnoop.
Brendan Gregg's avatar
Brendan Gregg committed
4
#		For Linux, uses BCC, eBPF. Embedded C.
5 6 7 8 9 10 11 12
#
# 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.

Brendan Gregg's avatar
Brendan Gregg committed
13
from __future__ import print_function
14
from bcc import BPF
15 16 17 18

REQ_WRITE = 1		# from include/linux/blk_types.h

# load BPF program
Brendan Gregg's avatar
Brendan Gregg committed
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
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);
	}
}
""")

45 46 47
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")
48 49

# header
Brendan Gregg's avatar
Brendan Gregg committed
50
print("%-18s %-2s %-7s %8s" % ("TIME(s)", "T", "BYTES", "LAT(ms)"))
51 52 53

# format output
while 1:
54
	(task, pid, cpu, flags, ts, msg) = b.trace_fields()
55 56 57
	(bytes_s, bflags_s, us_s) = msg.split()

	if int(bflags_s, 16) & REQ_WRITE:
58 59 60 61 62 63 64
		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

65
	print("%-18.9f %-2s %-7s %8.2f" % (ts, type_s, bytes_s, ms))