Skip to content

Commit

Permalink
tools/biosnoop: Add support for displaying block I/O pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
xingfeng2510 authored and yonghong-song committed Oct 17, 2022
1 parent 95566c9 commit 981a947
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 7 deletions.
5 changes: 4 additions & 1 deletion man/man8/biosnoop.8
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
.SH NAME
biosnoop \- Trace block device I/O and print details incl. issuing PID.
.SH SYNOPSIS
.B biosnoop [\-h] [\-Q] [\-d DISK]
.B biosnoop [\-h] [\-Q] [\-d DISK] [\-P]
.SH DESCRIPTION
This tools traces block device I/O (disk I/O), and prints a one-line summary
for each I/O showing various details. These include the latency from the time of
Expand Down Expand Up @@ -32,6 +32,9 @@ Include a column showing the time spent queued in the OS.
.TP
\-d DISK
Trace this disk only.
.TP
\-P
Display block I/O pattern (sequential or random).
.SH EXAMPLES
.TP
Trace all block device I/O and print a summary line per I/O:
Expand Down
71 changes: 67 additions & 4 deletions tools/biosnoop.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# 16-Sep-2015 Brendan Gregg Created this.
# 11-Feb-2016 Allan McAleavy updated for BPF_PERF_OUTPUT
# 21-Jun-2022 Rocky Xing Added disk filter support.
# 13-Oct-2022 Rocky Xing Added support for displaying block I/O pattern.

from __future__ import print_function
from bcc import BPF
Expand All @@ -24,6 +25,7 @@
./biosnoop # trace all block I/O
./biosnoop -Q # include OS queued time
./biosnoop -d sdc # trace sdc only
./biosnoop -P # display block I/O pattern
"""
parser = argparse.ArgumentParser(
description="Trace block I/O",
Expand All @@ -32,17 +34,24 @@
parser.add_argument("-Q", "--queue", action="store_true",
help="include OS queued time")
parser.add_argument("-d", "--disk", type=str,
help="Trace this disk only")
help="trace this disk only")
parser.add_argument("-P", "--pattern", action="store_true",
help="display block I/O pattern (sequential or random)")
parser.add_argument("--ebpf", action="store_true",
help=argparse.SUPPRESS)
args = parser.parse_args()
debug = 0

# define BPF program
bpf_text="""
bpf_text = """
#include <uapi/linux/ptrace.h>
#include <linux/blk-mq.h>
"""

if args.pattern:
bpf_text += "#define INCLUDE_PATTERN\n"

bpf_text += """
// for saving the timestamp and __data_len of each request
struct start_req_t {
u64 ts;
Expand All @@ -55,18 +64,38 @@
char name[TASK_COMM_LEN];
};
#ifdef INCLUDE_PATTERN
struct sector_key_t {
u32 dev_major;
u32 dev_minor;
};
enum bio_pattern {
UNKNOWN,
SEQUENTIAL,
RANDOM,
};
#endif
struct data_t {
u32 pid;
u64 rwflag;
u64 delta;
u64 qdelta;
u64 sector;
u64 len;
#ifdef INCLUDE_PATTERN
enum bio_pattern pattern;
#endif
u64 ts;
char disk_name[DISK_NAME_LEN];
char name[TASK_COMM_LEN];
};
#ifdef INCLUDE_PATTERN
BPF_HASH(last_sectors, struct sector_key_t, u64);
#endif
BPF_HASH(start, struct request *, struct start_req_t);
BPF_HASH(infobyreq, struct request *, struct val_t);
BPF_PERF_OUTPUT(events);
Expand Down Expand Up @@ -108,6 +137,7 @@
struct start_req_t *startp;
struct val_t *valp;
struct data_t data = {};
struct gendisk *rq_disk;
u64 ts;
// fetch timestamp and calculate delta
Expand All @@ -117,12 +147,13 @@
return 0;
}
ts = bpf_ktime_get_ns();
rq_disk = req->__RQ_DISK__;
data.delta = ts - startp->ts;
data.ts = ts / 1000;
data.qdelta = 0;
data.len = startp->data_len;
valp = infobyreq.lookup(&req);
data.len = startp->data_len;
if (valp == 0) {
data.name[0] = '?';
data.name[1] = 0;
Expand All @@ -133,11 +164,29 @@
data.pid = valp->pid;
data.sector = req->__sector;
bpf_probe_read_kernel(&data.name, sizeof(data.name), valp->name);
struct gendisk *rq_disk = req->__RQ_DISK__;
bpf_probe_read_kernel(&data.disk_name, sizeof(data.disk_name),
rq_disk->disk_name);
}
#ifdef INCLUDE_PATTERN
data.pattern = UNKNOWN;
u64 *sector, last_sector;
struct sector_key_t sector_key = {
.dev_major = rq_disk->major,
.dev_minor = rq_disk->first_minor
};
sector = last_sectors.lookup(&sector_key);
if (sector != 0) {
data.pattern = req->__sector == *sector ? SEQUENTIAL : RANDOM;
}
last_sector = req->__sector + data.len / 512;
last_sectors.update(&sector_key, &last_sector);
#endif
/*
* The following deals with a kernel version change (in mainline 4.7, although
* it may be backported to earlier kernels) with how block request write flags
Expand Down Expand Up @@ -218,15 +267,21 @@
# header
print("%-11s %-14s %-7s %-9s %-1s %-10s %-7s" % ("TIME(s)", "COMM", "PID",
"DISK", "T", "SECTOR", "BYTES"), end="")
if args.pattern:
print("%-1s " % ("P"), end="")
if args.queue:
print("%7s " % ("QUE(ms)"), end="")
print("%7s" % "LAT(ms)")

rwflg = ""
pattern = ""
start_ts = 0
prev_ts = 0
delta = 0

P_SEQUENTIAL = 1
P_RANDOM = 2

# process event
def print_event(cpu, data, size):
event = b["events"].event(data)
Expand All @@ -249,6 +304,14 @@ def print_event(cpu, data, size):
print("%-11.6f %-14.14s %-7s %-9s %-1s %-10s %-7s" % (
delta / 1000000, event.name.decode('utf-8', 'replace'), event.pid,
disk_name, rwflg, event.sector, event.len), end="")
if args.pattern:
if event.pattern == P_SEQUENTIAL:
pattern = "S"
elif event.pattern == P_RANDOM:
pattern = "R"
else:
pattern = "?"
print("%-1s " % pattern, end="")
if args.queue:
print("%7.2f " % (float(event.qdelta) / 1000000), end="")
print("%7.2f" % (float(event.delta) / 1000000))
Expand Down
6 changes: 4 additions & 2 deletions tools/biosnoop_example.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,18 @@ TIME(s) COMM PID DISK T SECTOR BYTES QUE(ms) LAT(ms)

USAGE message:

usage: biosnoop.py [-h] [-Q] [-d DISK]
usage: biosnoop.py [-h] [-Q] [-d DISK] [-P]

Trace block I/O

optional arguments:
-h, --help show this help message and exit
-Q, --queue include OS queued time
-d DISK, --disk DISK Trace this disk only
-d DISK, --disk DISK trace this disk only
-P, --pattern display block I/O pattern (sequential or random)

examples:
./biosnoop # trace all block I/O
./biosnoop -Q # include OS queued time
./biosnoop -d sdc # trace sdc only
./biosnoop -P # display block I/O pattern

0 comments on commit 981a947

Please sign in to comment.