xref: /aosp_15_r20/external/bcc/tools/zfsslower.py (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env python
2*387f9dfdSAndroid Build Coastguard Worker# @lint-avoid-python-3-compatibility-imports
3*387f9dfdSAndroid Build Coastguard Worker#
4*387f9dfdSAndroid Build Coastguard Worker# zfsslower  Trace slow ZFS operations.
5*387f9dfdSAndroid Build Coastguard Worker#            For Linux, uses BCC, eBPF.
6*387f9dfdSAndroid Build Coastguard Worker#
7*387f9dfdSAndroid Build Coastguard Worker# USAGE: zfsslower [-h] [-j] [-p PID] [min_ms]
8*387f9dfdSAndroid Build Coastguard Worker#
9*387f9dfdSAndroid Build Coastguard Worker# This script traces common ZFS file operations: reads, writes, opens, and
10*387f9dfdSAndroid Build Coastguard Worker# syncs. It measures the time spent in these operations, and prints details
11*387f9dfdSAndroid Build Coastguard Worker# for each that exceeded a threshold.
12*387f9dfdSAndroid Build Coastguard Worker#
13*387f9dfdSAndroid Build Coastguard Worker# WARNING: This adds low-overhead instrumentation to these ZFS operations,
14*387f9dfdSAndroid Build Coastguard Worker# including reads and writes from the file system cache. Such reads and writes
15*387f9dfdSAndroid Build Coastguard Worker# can be very frequent (depending on the workload; eg, 1M/sec), at which
16*387f9dfdSAndroid Build Coastguard Worker# point the overhead of this tool (even if it prints no "slower" events) can
17*387f9dfdSAndroid Build Coastguard Worker# begin to become significant.
18*387f9dfdSAndroid Build Coastguard Worker#
19*387f9dfdSAndroid Build Coastguard Worker# This works by using kernel dynamic tracing of the ZPL interface, and will
20*387f9dfdSAndroid Build Coastguard Worker# need updates to match any changes to this interface.
21*387f9dfdSAndroid Build Coastguard Worker#
22*387f9dfdSAndroid Build Coastguard Worker# By default, a minimum millisecond threshold of 10 is used.
23*387f9dfdSAndroid Build Coastguard Worker#
24*387f9dfdSAndroid Build Coastguard Worker# Copyright 2016 Netflix, Inc.
25*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License")
26*387f9dfdSAndroid Build Coastguard Worker#
27*387f9dfdSAndroid Build Coastguard Worker# 14-Feb-2016   Brendan Gregg   Created this.
28*387f9dfdSAndroid Build Coastguard Worker# 16-Oct-2016   Dina Goldshtein -p to filter by process ID.
29*387f9dfdSAndroid Build Coastguard Worker
30*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function
31*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF
32*387f9dfdSAndroid Build Coastguard Workerimport argparse
33*387f9dfdSAndroid Build Coastguard Workerfrom time import strftime
34*387f9dfdSAndroid Build Coastguard Worker
35*387f9dfdSAndroid Build Coastguard Worker# arguments
36*387f9dfdSAndroid Build Coastguard Workerexamples = """examples:
37*387f9dfdSAndroid Build Coastguard Worker    ./zfsslower             # trace operations slower than 10 ms (default)
38*387f9dfdSAndroid Build Coastguard Worker    ./zfsslower 1           # trace operations slower than 1 ms
39*387f9dfdSAndroid Build Coastguard Worker    ./zfsslower -j 1        # ... 1 ms, parsable output (csv)
40*387f9dfdSAndroid Build Coastguard Worker    ./zfsslower 0           # trace all operations (warning: verbose)
41*387f9dfdSAndroid Build Coastguard Worker    ./zfsslower -p 185      # trace PID 185 only
42*387f9dfdSAndroid Build Coastguard Worker"""
43*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser(
44*387f9dfdSAndroid Build Coastguard Worker    description="Trace common ZFS file operations slower than a threshold",
45*387f9dfdSAndroid Build Coastguard Worker    formatter_class=argparse.RawDescriptionHelpFormatter,
46*387f9dfdSAndroid Build Coastguard Worker    epilog=examples)
47*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-j", "--csv", action="store_true",
48*387f9dfdSAndroid Build Coastguard Worker    help="just print fields: comma-separated values")
49*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-p", "--pid",
50*387f9dfdSAndroid Build Coastguard Worker    help="trace this PID only")
51*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("min_ms", nargs="?", default='10',
52*387f9dfdSAndroid Build Coastguard Worker    help="minimum I/O duration to trace, in ms (default 10)")
53*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--ebpf", action="store_true",
54*387f9dfdSAndroid Build Coastguard Worker    help=argparse.SUPPRESS)
55*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args()
56*387f9dfdSAndroid Build Coastguard Workermin_ms = int(args.min_ms)
57*387f9dfdSAndroid Build Coastguard Workerpid = args.pid
58*387f9dfdSAndroid Build Coastguard Workercsv = args.csv
59*387f9dfdSAndroid Build Coastguard Workerdebug = 0
60*387f9dfdSAndroid Build Coastguard Worker
61*387f9dfdSAndroid Build Coastguard Worker# define BPF program
62*387f9dfdSAndroid Build Coastguard Workerbpf_text = """
63*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h>
64*387f9dfdSAndroid Build Coastguard Worker#include <linux/fs.h>
65*387f9dfdSAndroid Build Coastguard Worker#include <linux/sched.h>
66*387f9dfdSAndroid Build Coastguard Worker#include <linux/dcache.h>
67*387f9dfdSAndroid Build Coastguard Worker
68*387f9dfdSAndroid Build Coastguard Worker// XXX: switch these to char's when supported
69*387f9dfdSAndroid Build Coastguard Worker#define TRACE_READ      0
70*387f9dfdSAndroid Build Coastguard Worker#define TRACE_WRITE     1
71*387f9dfdSAndroid Build Coastguard Worker#define TRACE_OPEN      2
72*387f9dfdSAndroid Build Coastguard Worker#define TRACE_FSYNC     3
73*387f9dfdSAndroid Build Coastguard Worker
74*387f9dfdSAndroid Build Coastguard Workerstruct val_t {
75*387f9dfdSAndroid Build Coastguard Worker    u64 ts;
76*387f9dfdSAndroid Build Coastguard Worker    u64 offset;
77*387f9dfdSAndroid Build Coastguard Worker    struct file *fp;
78*387f9dfdSAndroid Build Coastguard Worker};
79*387f9dfdSAndroid Build Coastguard Worker
80*387f9dfdSAndroid Build Coastguard Workerstruct data_t {
81*387f9dfdSAndroid Build Coastguard Worker    // XXX: switch some to u32's when supported
82*387f9dfdSAndroid Build Coastguard Worker    u64 ts_us;
83*387f9dfdSAndroid Build Coastguard Worker    u64 type;
84*387f9dfdSAndroid Build Coastguard Worker    u32 size;
85*387f9dfdSAndroid Build Coastguard Worker    u64 offset;
86*387f9dfdSAndroid Build Coastguard Worker    u64 delta_us;
87*387f9dfdSAndroid Build Coastguard Worker    u32 pid;
88*387f9dfdSAndroid Build Coastguard Worker    char task[TASK_COMM_LEN];
89*387f9dfdSAndroid Build Coastguard Worker    char file[DNAME_INLINE_LEN];
90*387f9dfdSAndroid Build Coastguard Worker};
91*387f9dfdSAndroid Build Coastguard Worker
92*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(entryinfo, u64, struct val_t);
93*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(events);
94*387f9dfdSAndroid Build Coastguard Worker
95*387f9dfdSAndroid Build Coastguard Worker//
96*387f9dfdSAndroid Build Coastguard Worker// Store timestamp and size on entry
97*387f9dfdSAndroid Build Coastguard Worker//
98*387f9dfdSAndroid Build Coastguard Worker
99*387f9dfdSAndroid Build Coastguard Worker// zpl_read(), zpl_write():
100*387f9dfdSAndroid Build Coastguard Workerint trace_rw_entry(struct pt_regs *ctx, struct file *filp, char __user *buf,
101*387f9dfdSAndroid Build Coastguard Worker    size_t len, loff_t *ppos)
102*387f9dfdSAndroid Build Coastguard Worker{
103*387f9dfdSAndroid Build Coastguard Worker    u64 id = bpf_get_current_pid_tgid();
104*387f9dfdSAndroid Build Coastguard Worker    u32 pid = id >> 32; // PID is higher part
105*387f9dfdSAndroid Build Coastguard Worker
106*387f9dfdSAndroid Build Coastguard Worker    if (FILTER_PID)
107*387f9dfdSAndroid Build Coastguard Worker        return 0;
108*387f9dfdSAndroid Build Coastguard Worker
109*387f9dfdSAndroid Build Coastguard Worker    // store filep and timestamp by id
110*387f9dfdSAndroid Build Coastguard Worker    struct val_t val = {};
111*387f9dfdSAndroid Build Coastguard Worker    val.ts = bpf_ktime_get_ns();
112*387f9dfdSAndroid Build Coastguard Worker    val.fp = filp;
113*387f9dfdSAndroid Build Coastguard Worker    val.offset = *ppos;
114*387f9dfdSAndroid Build Coastguard Worker    if (val.fp)
115*387f9dfdSAndroid Build Coastguard Worker        entryinfo.update(&id, &val);
116*387f9dfdSAndroid Build Coastguard Worker
117*387f9dfdSAndroid Build Coastguard Worker    return 0;
118*387f9dfdSAndroid Build Coastguard Worker}
119*387f9dfdSAndroid Build Coastguard Worker
120*387f9dfdSAndroid Build Coastguard Worker// zpl_open():
121*387f9dfdSAndroid Build Coastguard Workerint trace_open_entry(struct pt_regs *ctx, struct inode *inode,
122*387f9dfdSAndroid Build Coastguard Worker    struct file *filp)
123*387f9dfdSAndroid Build Coastguard Worker{
124*387f9dfdSAndroid Build Coastguard Worker    u64 id = bpf_get_current_pid_tgid();
125*387f9dfdSAndroid Build Coastguard Worker    u32 pid = id >> 32; // PID is higher part
126*387f9dfdSAndroid Build Coastguard Worker
127*387f9dfdSAndroid Build Coastguard Worker    if (FILTER_PID)
128*387f9dfdSAndroid Build Coastguard Worker        return 0;
129*387f9dfdSAndroid Build Coastguard Worker
130*387f9dfdSAndroid Build Coastguard Worker    // store filep and timestamp by id
131*387f9dfdSAndroid Build Coastguard Worker    struct val_t val = {};
132*387f9dfdSAndroid Build Coastguard Worker    val.ts = bpf_ktime_get_ns();
133*387f9dfdSAndroid Build Coastguard Worker    val.fp = filp;
134*387f9dfdSAndroid Build Coastguard Worker    val.offset = 0;
135*387f9dfdSAndroid Build Coastguard Worker    if (val.fp)
136*387f9dfdSAndroid Build Coastguard Worker        entryinfo.update(&id, &val);
137*387f9dfdSAndroid Build Coastguard Worker
138*387f9dfdSAndroid Build Coastguard Worker    return 0;
139*387f9dfdSAndroid Build Coastguard Worker}
140*387f9dfdSAndroid Build Coastguard Worker
141*387f9dfdSAndroid Build Coastguard Worker// zpl_fsync():
142*387f9dfdSAndroid Build Coastguard Workerint trace_fsync_entry(struct pt_regs *ctx, struct file *filp)
143*387f9dfdSAndroid Build Coastguard Worker{
144*387f9dfdSAndroid Build Coastguard Worker    u64 id = bpf_get_current_pid_tgid();
145*387f9dfdSAndroid Build Coastguard Worker    u32 pid = id >> 32; // PID is higher part
146*387f9dfdSAndroid Build Coastguard Worker
147*387f9dfdSAndroid Build Coastguard Worker    if (FILTER_PID)
148*387f9dfdSAndroid Build Coastguard Worker        return 0;
149*387f9dfdSAndroid Build Coastguard Worker
150*387f9dfdSAndroid Build Coastguard Worker    // store filp and timestamp by id
151*387f9dfdSAndroid Build Coastguard Worker    struct val_t val = {};
152*387f9dfdSAndroid Build Coastguard Worker    val.ts = bpf_ktime_get_ns();
153*387f9dfdSAndroid Build Coastguard Worker    val.fp = filp;
154*387f9dfdSAndroid Build Coastguard Worker    val.offset = 0;
155*387f9dfdSAndroid Build Coastguard Worker    if (val.fp)
156*387f9dfdSAndroid Build Coastguard Worker        entryinfo.update(&id, &val);
157*387f9dfdSAndroid Build Coastguard Worker
158*387f9dfdSAndroid Build Coastguard Worker    return 0;
159*387f9dfdSAndroid Build Coastguard Worker}
160*387f9dfdSAndroid Build Coastguard Worker
161*387f9dfdSAndroid Build Coastguard Worker//
162*387f9dfdSAndroid Build Coastguard Worker// Output
163*387f9dfdSAndroid Build Coastguard Worker//
164*387f9dfdSAndroid Build Coastguard Worker
165*387f9dfdSAndroid Build Coastguard Workerstatic int trace_return(struct pt_regs *ctx, int type)
166*387f9dfdSAndroid Build Coastguard Worker{
167*387f9dfdSAndroid Build Coastguard Worker    struct val_t *valp;
168*387f9dfdSAndroid Build Coastguard Worker    u64 id = bpf_get_current_pid_tgid();
169*387f9dfdSAndroid Build Coastguard Worker    u32 pid = id >> 32; // PID is higher part
170*387f9dfdSAndroid Build Coastguard Worker
171*387f9dfdSAndroid Build Coastguard Worker    valp = entryinfo.lookup(&id);
172*387f9dfdSAndroid Build Coastguard Worker    if (valp == 0) {
173*387f9dfdSAndroid Build Coastguard Worker        // missed tracing issue or filtered
174*387f9dfdSAndroid Build Coastguard Worker        return 0;
175*387f9dfdSAndroid Build Coastguard Worker    }
176*387f9dfdSAndroid Build Coastguard Worker
177*387f9dfdSAndroid Build Coastguard Worker    // calculate delta
178*387f9dfdSAndroid Build Coastguard Worker    u64 ts = bpf_ktime_get_ns();
179*387f9dfdSAndroid Build Coastguard Worker    u64 delta_us = (ts - valp->ts) / 1000;
180*387f9dfdSAndroid Build Coastguard Worker    entryinfo.delete(&id);
181*387f9dfdSAndroid Build Coastguard Worker    if (FILTER_US)
182*387f9dfdSAndroid Build Coastguard Worker        return 0;
183*387f9dfdSAndroid Build Coastguard Worker
184*387f9dfdSAndroid Build Coastguard Worker    // populate output struct
185*387f9dfdSAndroid Build Coastguard Worker    struct data_t data = {};
186*387f9dfdSAndroid Build Coastguard Worker    data.type = type;
187*387f9dfdSAndroid Build Coastguard Worker    data.size = PT_REGS_RC(ctx);
188*387f9dfdSAndroid Build Coastguard Worker    data.delta_us = delta_us;
189*387f9dfdSAndroid Build Coastguard Worker    data.pid = pid;
190*387f9dfdSAndroid Build Coastguard Worker    data.ts_us = ts / 1000;
191*387f9dfdSAndroid Build Coastguard Worker    data.offset = valp->offset;
192*387f9dfdSAndroid Build Coastguard Worker    bpf_get_current_comm(&data.task, sizeof(data.task));
193*387f9dfdSAndroid Build Coastguard Worker
194*387f9dfdSAndroid Build Coastguard Worker    struct qstr qs = valp->fp->f_path.dentry->d_name;
195*387f9dfdSAndroid Build Coastguard Worker    if (qs.len == 0)
196*387f9dfdSAndroid Build Coastguard Worker        return 0;
197*387f9dfdSAndroid Build Coastguard Worker    bpf_probe_read_kernel(&data.file, sizeof(data.file), (void *)qs.name);
198*387f9dfdSAndroid Build Coastguard Worker
199*387f9dfdSAndroid Build Coastguard Worker    // output
200*387f9dfdSAndroid Build Coastguard Worker    events.perf_submit(ctx, &data, sizeof(data));
201*387f9dfdSAndroid Build Coastguard Worker
202*387f9dfdSAndroid Build Coastguard Worker    return 0;
203*387f9dfdSAndroid Build Coastguard Worker}
204*387f9dfdSAndroid Build Coastguard Worker
205*387f9dfdSAndroid Build Coastguard Workerint trace_read_return(struct pt_regs *ctx)
206*387f9dfdSAndroid Build Coastguard Worker{
207*387f9dfdSAndroid Build Coastguard Worker    return trace_return(ctx, TRACE_READ);
208*387f9dfdSAndroid Build Coastguard Worker}
209*387f9dfdSAndroid Build Coastguard Worker
210*387f9dfdSAndroid Build Coastguard Workerint trace_write_return(struct pt_regs *ctx)
211*387f9dfdSAndroid Build Coastguard Worker{
212*387f9dfdSAndroid Build Coastguard Worker    return trace_return(ctx, TRACE_WRITE);
213*387f9dfdSAndroid Build Coastguard Worker}
214*387f9dfdSAndroid Build Coastguard Worker
215*387f9dfdSAndroid Build Coastguard Workerint trace_open_return(struct pt_regs *ctx)
216*387f9dfdSAndroid Build Coastguard Worker{
217*387f9dfdSAndroid Build Coastguard Worker    return trace_return(ctx, TRACE_OPEN);
218*387f9dfdSAndroid Build Coastguard Worker}
219*387f9dfdSAndroid Build Coastguard Worker
220*387f9dfdSAndroid Build Coastguard Workerint trace_fsync_return(struct pt_regs *ctx)
221*387f9dfdSAndroid Build Coastguard Worker{
222*387f9dfdSAndroid Build Coastguard Worker    return trace_return(ctx, TRACE_FSYNC);
223*387f9dfdSAndroid Build Coastguard Worker}
224*387f9dfdSAndroid Build Coastguard Worker
225*387f9dfdSAndroid Build Coastguard Worker"""
226*387f9dfdSAndroid Build Coastguard Workerif min_ms == 0:
227*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('FILTER_US', '0')
228*387f9dfdSAndroid Build Coastguard Workerelse:
229*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('FILTER_US',
230*387f9dfdSAndroid Build Coastguard Worker        'delta_us <= %s' % str(min_ms * 1000))
231*387f9dfdSAndroid Build Coastguard Workerif args.pid:
232*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('FILTER_PID', 'pid != %s' % pid)
233*387f9dfdSAndroid Build Coastguard Workerelse:
234*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('FILTER_PID', '0')
235*387f9dfdSAndroid Build Coastguard Workerif debug or args.ebpf:
236*387f9dfdSAndroid Build Coastguard Worker    print(bpf_text)
237*387f9dfdSAndroid Build Coastguard Worker    if args.ebpf:
238*387f9dfdSAndroid Build Coastguard Worker        exit()
239*387f9dfdSAndroid Build Coastguard Worker
240*387f9dfdSAndroid Build Coastguard Worker# process event
241*387f9dfdSAndroid Build Coastguard Workerdef print_event(cpu, data, size):
242*387f9dfdSAndroid Build Coastguard Worker    event = b["events"].event(data)
243*387f9dfdSAndroid Build Coastguard Worker
244*387f9dfdSAndroid Build Coastguard Worker    type = 'R'
245*387f9dfdSAndroid Build Coastguard Worker    if event.type == 1:
246*387f9dfdSAndroid Build Coastguard Worker        type = 'W'
247*387f9dfdSAndroid Build Coastguard Worker    elif event.type == 2:
248*387f9dfdSAndroid Build Coastguard Worker        type = 'O'
249*387f9dfdSAndroid Build Coastguard Worker    elif event.type == 3:
250*387f9dfdSAndroid Build Coastguard Worker        type = 'S'
251*387f9dfdSAndroid Build Coastguard Worker
252*387f9dfdSAndroid Build Coastguard Worker    if (csv):
253*387f9dfdSAndroid Build Coastguard Worker        print("%d,%s,%d,%s,%d,%d,%d,%s" % (
254*387f9dfdSAndroid Build Coastguard Worker            event.ts_us, event.task.decode('utf-8', 'replace'), event.pid,
255*387f9dfdSAndroid Build Coastguard Worker            type, event.size, event.offset, event.delta_us,
256*387f9dfdSAndroid Build Coastguard Worker            event.file.decode('utf-8', 'replace')))
257*387f9dfdSAndroid Build Coastguard Worker        return
258*387f9dfdSAndroid Build Coastguard Worker    print("%-8s %-14.14s %-6s %1s %-7s %-8d %7.2f %s" % (strftime("%H:%M:%S"),
259*387f9dfdSAndroid Build Coastguard Worker        event.task.decode('utf-8', 'replace'), event.pid, type, event.size,
260*387f9dfdSAndroid Build Coastguard Worker        event.offset / 1024, float(event.delta_us) / 1000,
261*387f9dfdSAndroid Build Coastguard Worker        event.file.decode('utf-8', 'replace')))
262*387f9dfdSAndroid Build Coastguard Worker
263*387f9dfdSAndroid Build Coastguard Worker# initialize BPF
264*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text)
265*387f9dfdSAndroid Build Coastguard Worker
266*387f9dfdSAndroid Build Coastguard Worker# common file functions
267*387f9dfdSAndroid Build Coastguard Workerif BPF.get_kprobe_functions(b'zpl_iter'):
268*387f9dfdSAndroid Build Coastguard Worker    b.attach_kprobe(event="zpl_iter_read", fn_name="trace_rw_entry")
269*387f9dfdSAndroid Build Coastguard Worker    b.attach_kprobe(event="zpl_iter_write", fn_name="trace_rw_entry")
270*387f9dfdSAndroid Build Coastguard Workerelif BPF.get_kprobe_functions(b'zpl_aio'):
271*387f9dfdSAndroid Build Coastguard Worker    b.attach_kprobe(event="zpl_aio_read", fn_name="trace_rw_entry")
272*387f9dfdSAndroid Build Coastguard Worker    b.attach_kprobe(event="zpl_aio_write", fn_name="trace_rw_entry")
273*387f9dfdSAndroid Build Coastguard Workerelse:
274*387f9dfdSAndroid Build Coastguard Worker    b.attach_kprobe(event="zpl_read", fn_name="trace_rw_entry")
275*387f9dfdSAndroid Build Coastguard Worker    b.attach_kprobe(event="zpl_write", fn_name="trace_rw_entry")
276*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event="zpl_open", fn_name="trace_open_entry")
277*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event="zpl_fsync", fn_name="trace_fsync_entry")
278*387f9dfdSAndroid Build Coastguard Workerif BPF.get_kprobe_functions(b'zpl_iter'):
279*387f9dfdSAndroid Build Coastguard Worker    b.attach_kretprobe(event="zpl_iter_read", fn_name="trace_read_return")
280*387f9dfdSAndroid Build Coastguard Worker    b.attach_kretprobe(event="zpl_iter_write", fn_name="trace_write_return")
281*387f9dfdSAndroid Build Coastguard Workerelif BPF.get_kprobe_functions(b'zpl_aio'):
282*387f9dfdSAndroid Build Coastguard Worker    b.attach_kretprobe(event="zpl_aio_read", fn_name="trace_read_return")
283*387f9dfdSAndroid Build Coastguard Worker    b.attach_kretprobe(event="zpl_aio_write", fn_name="trace_write_return")
284*387f9dfdSAndroid Build Coastguard Workerelse:
285*387f9dfdSAndroid Build Coastguard Worker    b.attach_kretprobe(event="zpl_read", fn_name="trace_read_return")
286*387f9dfdSAndroid Build Coastguard Worker    b.attach_kretprobe(event="zpl_write", fn_name="trace_write_return")
287*387f9dfdSAndroid Build Coastguard Workerb.attach_kretprobe(event="zpl_open", fn_name="trace_open_return")
288*387f9dfdSAndroid Build Coastguard Workerb.attach_kretprobe(event="zpl_fsync", fn_name="trace_fsync_return")
289*387f9dfdSAndroid Build Coastguard Worker
290*387f9dfdSAndroid Build Coastguard Worker# header
291*387f9dfdSAndroid Build Coastguard Workerif (csv):
292*387f9dfdSAndroid Build Coastguard Worker    print("ENDTIME_us,TASK,PID,TYPE,BYTES,OFFSET_b,LATENCY_us,FILE")
293*387f9dfdSAndroid Build Coastguard Workerelse:
294*387f9dfdSAndroid Build Coastguard Worker    if min_ms == 0:
295*387f9dfdSAndroid Build Coastguard Worker        print("Tracing ZFS operations")
296*387f9dfdSAndroid Build Coastguard Worker    else:
297*387f9dfdSAndroid Build Coastguard Worker        print("Tracing ZFS operations slower than %d ms" % min_ms)
298*387f9dfdSAndroid Build Coastguard Worker    print("%-8s %-14s %-6s %1s %-7s %-8s %7s %s" % ("TIME", "COMM", "PID", "T",
299*387f9dfdSAndroid Build Coastguard Worker        "BYTES", "OFF_KB", "LAT(ms)", "FILENAME"))
300*387f9dfdSAndroid Build Coastguard Worker
301*387f9dfdSAndroid Build Coastguard Worker# read events
302*387f9dfdSAndroid Build Coastguard Workerb["events"].open_perf_buffer(print_event, page_cnt=64)
303*387f9dfdSAndroid Build Coastguard Workerwhile 1:
304*387f9dfdSAndroid Build Coastguard Worker    try:
305*387f9dfdSAndroid Build Coastguard Worker        b.perf_buffer_poll()
306*387f9dfdSAndroid Build Coastguard Worker    except KeyboardInterrupt:
307*387f9dfdSAndroid Build Coastguard Worker        exit()
308