xref: /aosp_15_r20/external/bcc/tools/btrfsslower.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# btrfsslower  Trace slow btrfs operations.
5*387f9dfdSAndroid Build Coastguard Worker#              For Linux, uses BCC, eBPF.
6*387f9dfdSAndroid Build Coastguard Worker#
7*387f9dfdSAndroid Build Coastguard Worker# USAGE: btrfsslower [-h] [-j] [-p PID] [min_ms] [-d DURATION]
8*387f9dfdSAndroid Build Coastguard Worker#
9*387f9dfdSAndroid Build Coastguard Worker# This script traces common btrfs 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 btrfs 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# By default, a minimum millisecond threshold of 10 is used.
20*387f9dfdSAndroid Build Coastguard Worker#
21*387f9dfdSAndroid Build Coastguard Worker# Copyright 2016 Netflix, Inc.
22*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License")
23*387f9dfdSAndroid Build Coastguard Worker#
24*387f9dfdSAndroid Build Coastguard Worker# 15-Feb-2016   Brendan Gregg   Created this.
25*387f9dfdSAndroid Build Coastguard Worker# 16-Oct-2016   Dina Goldshtein -p to filter by process ID.
26*387f9dfdSAndroid Build Coastguard Worker
27*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function
28*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF
29*387f9dfdSAndroid Build Coastguard Workerimport argparse
30*387f9dfdSAndroid Build Coastguard Workerfrom datetime import datetime, timedelta
31*387f9dfdSAndroid Build Coastguard Workerfrom time import strftime
32*387f9dfdSAndroid Build Coastguard Worker
33*387f9dfdSAndroid Build Coastguard Worker# symbols
34*387f9dfdSAndroid Build Coastguard Workerkallsyms = "/proc/kallsyms"
35*387f9dfdSAndroid Build Coastguard Worker
36*387f9dfdSAndroid Build Coastguard Worker# arguments
37*387f9dfdSAndroid Build Coastguard Workerexamples = """examples:
38*387f9dfdSAndroid Build Coastguard Worker    ./btrfsslower             # trace operations slower than 10 ms (default)
39*387f9dfdSAndroid Build Coastguard Worker    ./btrfsslower 1           # trace operations slower than 1 ms
40*387f9dfdSAndroid Build Coastguard Worker    ./btrfsslower -j 1        # ... 1 ms, parsable output (csv)
41*387f9dfdSAndroid Build Coastguard Worker    ./btrfsslower 0           # trace all operations (warning: verbose)
42*387f9dfdSAndroid Build Coastguard Worker    ./btrfsslower -p 185      # trace PID 185 only
43*387f9dfdSAndroid Build Coastguard Worker    ./btrfsslower -d 10       # trace for 10 seconds only
44*387f9dfdSAndroid Build Coastguard Worker"""
45*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser(
46*387f9dfdSAndroid Build Coastguard Worker    description="Trace common btrfs file operations slower than a threshold",
47*387f9dfdSAndroid Build Coastguard Worker    formatter_class=argparse.RawDescriptionHelpFormatter,
48*387f9dfdSAndroid Build Coastguard Worker    epilog=examples)
49*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-j", "--csv", action="store_true",
50*387f9dfdSAndroid Build Coastguard Worker    help="just print fields: comma-separated values")
51*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-p", "--pid",
52*387f9dfdSAndroid Build Coastguard Worker    help="trace this PID only")
53*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("min_ms", nargs="?", default='10',
54*387f9dfdSAndroid Build Coastguard Worker    help="minimum I/O duration to trace, in ms (default 10)")
55*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--ebpf", action="store_true",
56*387f9dfdSAndroid Build Coastguard Worker    help=argparse.SUPPRESS)
57*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-d", "--duration",
58*387f9dfdSAndroid Build Coastguard Worker    help="total duration of trace in seconds")
59*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args()
60*387f9dfdSAndroid Build Coastguard Workermin_ms = int(args.min_ms)
61*387f9dfdSAndroid Build Coastguard Workerpid = args.pid
62*387f9dfdSAndroid Build Coastguard Workercsv = args.csv
63*387f9dfdSAndroid Build Coastguard Workerdebug = 0
64*387f9dfdSAndroid Build Coastguard Workerif args.duration:
65*387f9dfdSAndroid Build Coastguard Worker    args.duration = timedelta(seconds=int(args.duration))
66*387f9dfdSAndroid Build Coastguard Worker
67*387f9dfdSAndroid Build Coastguard Worker# define BPF program
68*387f9dfdSAndroid Build Coastguard Workerbpf_text = """
69*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h>
70*387f9dfdSAndroid Build Coastguard Worker#include <linux/fs.h>
71*387f9dfdSAndroid Build Coastguard Worker#include <linux/sched.h>
72*387f9dfdSAndroid Build Coastguard Worker#include <linux/dcache.h>
73*387f9dfdSAndroid Build Coastguard Worker
74*387f9dfdSAndroid Build Coastguard Worker// XXX: switch these to char's when supported
75*387f9dfdSAndroid Build Coastguard Worker#define TRACE_READ      0
76*387f9dfdSAndroid Build Coastguard Worker#define TRACE_WRITE     1
77*387f9dfdSAndroid Build Coastguard Worker#define TRACE_OPEN      2
78*387f9dfdSAndroid Build Coastguard Worker#define TRACE_FSYNC     3
79*387f9dfdSAndroid Build Coastguard Worker
80*387f9dfdSAndroid Build Coastguard Workerstruct val_t {
81*387f9dfdSAndroid Build Coastguard Worker    u64 ts;
82*387f9dfdSAndroid Build Coastguard Worker    u64 offset;
83*387f9dfdSAndroid Build Coastguard Worker    struct file *fp;
84*387f9dfdSAndroid Build Coastguard Worker};
85*387f9dfdSAndroid Build Coastguard Worker
86*387f9dfdSAndroid Build Coastguard Workerstruct data_t {
87*387f9dfdSAndroid Build Coastguard Worker    // XXX: switch some to u32's when supported
88*387f9dfdSAndroid Build Coastguard Worker    u64 ts_us;
89*387f9dfdSAndroid Build Coastguard Worker    u64 type;
90*387f9dfdSAndroid Build Coastguard Worker    u32 size;
91*387f9dfdSAndroid Build Coastguard Worker    u64 offset;
92*387f9dfdSAndroid Build Coastguard Worker    u64 delta_us;
93*387f9dfdSAndroid Build Coastguard Worker    u32 pid;
94*387f9dfdSAndroid Build Coastguard Worker    char task[TASK_COMM_LEN];
95*387f9dfdSAndroid Build Coastguard Worker    char file[DNAME_INLINE_LEN];
96*387f9dfdSAndroid Build Coastguard Worker};
97*387f9dfdSAndroid Build Coastguard Worker
98*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(entryinfo, u64, struct val_t);
99*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(events);
100*387f9dfdSAndroid Build Coastguard Worker
101*387f9dfdSAndroid Build Coastguard Worker//
102*387f9dfdSAndroid Build Coastguard Worker// Store timestamp and size on entry
103*387f9dfdSAndroid Build Coastguard Worker//
104*387f9dfdSAndroid Build Coastguard Worker
105*387f9dfdSAndroid Build Coastguard Worker// The current btrfs (Linux 4.5) uses generic_file_read_iter() instead of it's
106*387f9dfdSAndroid Build Coastguard Worker// own read function. So we need to trace that and then filter on btrfs, which
107*387f9dfdSAndroid Build Coastguard Worker// I do by checking file->f_op.
108*387f9dfdSAndroid Build Coastguard Workerint trace_read_entry(struct pt_regs *ctx, struct kiocb *iocb)
109*387f9dfdSAndroid Build Coastguard Worker{
110*387f9dfdSAndroid Build Coastguard Worker    u64 id =  bpf_get_current_pid_tgid();
111*387f9dfdSAndroid Build Coastguard Worker    u32 pid = id >> 32; // PID is higher part
112*387f9dfdSAndroid Build Coastguard Worker
113*387f9dfdSAndroid Build Coastguard Worker    if (FILTER_PID)
114*387f9dfdSAndroid Build Coastguard Worker        return 0;
115*387f9dfdSAndroid Build Coastguard Worker
116*387f9dfdSAndroid Build Coastguard Worker    // btrfs filter on file->f_op == btrfs_file_operations
117*387f9dfdSAndroid Build Coastguard Worker    struct file *fp = iocb->ki_filp;
118*387f9dfdSAndroid Build Coastguard Worker    if ((u64)fp->f_op != BTRFS_FILE_OPERATIONS)
119*387f9dfdSAndroid Build Coastguard Worker        return 0;
120*387f9dfdSAndroid Build Coastguard Worker
121*387f9dfdSAndroid Build Coastguard Worker    // store filep and timestamp by pid
122*387f9dfdSAndroid Build Coastguard Worker    struct val_t val = {};
123*387f9dfdSAndroid Build Coastguard Worker    val.ts = bpf_ktime_get_ns();
124*387f9dfdSAndroid Build Coastguard Worker    val.fp = fp;
125*387f9dfdSAndroid Build Coastguard Worker    val.offset = iocb->ki_pos;
126*387f9dfdSAndroid Build Coastguard Worker    if (val.fp)
127*387f9dfdSAndroid Build Coastguard Worker        entryinfo.update(&id, &val);
128*387f9dfdSAndroid Build Coastguard Worker
129*387f9dfdSAndroid Build Coastguard Worker    return 0;
130*387f9dfdSAndroid Build Coastguard Worker}
131*387f9dfdSAndroid Build Coastguard Worker
132*387f9dfdSAndroid Build Coastguard Worker// btrfs_file_write_iter():
133*387f9dfdSAndroid Build Coastguard Workerint trace_write_entry(struct pt_regs *ctx, struct kiocb *iocb)
134*387f9dfdSAndroid Build Coastguard Worker{
135*387f9dfdSAndroid Build Coastguard Worker    u64 id = bpf_get_current_pid_tgid();
136*387f9dfdSAndroid Build Coastguard Worker    u32 pid = id >> 32; // PID is higher part
137*387f9dfdSAndroid Build Coastguard Worker
138*387f9dfdSAndroid Build Coastguard Worker    if (FILTER_PID)
139*387f9dfdSAndroid Build Coastguard Worker        return 0;
140*387f9dfdSAndroid Build Coastguard Worker
141*387f9dfdSAndroid Build Coastguard Worker    // store filep and timestamp by id
142*387f9dfdSAndroid Build Coastguard Worker    struct val_t val = {};
143*387f9dfdSAndroid Build Coastguard Worker    val.ts = bpf_ktime_get_ns();
144*387f9dfdSAndroid Build Coastguard Worker    val.fp = iocb->ki_filp;
145*387f9dfdSAndroid Build Coastguard Worker    val.offset = iocb->ki_pos;
146*387f9dfdSAndroid Build Coastguard Worker    if (val.fp)
147*387f9dfdSAndroid Build Coastguard Worker        entryinfo.update(&id, &val);
148*387f9dfdSAndroid Build Coastguard Worker
149*387f9dfdSAndroid Build Coastguard Worker    return 0;
150*387f9dfdSAndroid Build Coastguard Worker}
151*387f9dfdSAndroid Build Coastguard Worker
152*387f9dfdSAndroid Build Coastguard Worker// The current btrfs (Linux 4.5) uses generic_file_open(), instead of it's own
153*387f9dfdSAndroid Build Coastguard Worker// function. Same as with reads. Trace the generic path and filter:
154*387f9dfdSAndroid Build Coastguard Workerint trace_open_entry(struct pt_regs *ctx, struct inode *inode,
155*387f9dfdSAndroid Build Coastguard Worker    struct file *file)
156*387f9dfdSAndroid Build Coastguard Worker{
157*387f9dfdSAndroid Build Coastguard Worker    u64 id = bpf_get_current_pid_tgid();
158*387f9dfdSAndroid Build Coastguard Worker    u32 pid = id >> 32; // PID is higher part
159*387f9dfdSAndroid Build Coastguard Worker
160*387f9dfdSAndroid Build Coastguard Worker    if (FILTER_PID)
161*387f9dfdSAndroid Build Coastguard Worker        return 0;
162*387f9dfdSAndroid Build Coastguard Worker
163*387f9dfdSAndroid Build Coastguard Worker    // btrfs filter on file->f_op == btrfs_file_operations
164*387f9dfdSAndroid Build Coastguard Worker    if ((u64)file->f_op != BTRFS_FILE_OPERATIONS)
165*387f9dfdSAndroid Build Coastguard Worker        return 0;
166*387f9dfdSAndroid Build Coastguard Worker
167*387f9dfdSAndroid Build Coastguard Worker    // store filep and timestamp by id
168*387f9dfdSAndroid Build Coastguard Worker    struct val_t val = {};
169*387f9dfdSAndroid Build Coastguard Worker    val.ts = bpf_ktime_get_ns();
170*387f9dfdSAndroid Build Coastguard Worker    val.fp = file;
171*387f9dfdSAndroid Build Coastguard Worker    val.offset = 0;
172*387f9dfdSAndroid Build Coastguard Worker    if (val.fp)
173*387f9dfdSAndroid Build Coastguard Worker        entryinfo.update(&id, &val);
174*387f9dfdSAndroid Build Coastguard Worker
175*387f9dfdSAndroid Build Coastguard Worker    return 0;
176*387f9dfdSAndroid Build Coastguard Worker}
177*387f9dfdSAndroid Build Coastguard Worker
178*387f9dfdSAndroid Build Coastguard Worker// btrfs_sync_file():
179*387f9dfdSAndroid Build Coastguard Workerint trace_fsync_entry(struct pt_regs *ctx, struct file *file)
180*387f9dfdSAndroid Build Coastguard Worker{
181*387f9dfdSAndroid Build Coastguard Worker    u64 id = bpf_get_current_pid_tgid();
182*387f9dfdSAndroid Build Coastguard Worker    u32 pid = id >> 32; // PID is higher part
183*387f9dfdSAndroid Build Coastguard Worker
184*387f9dfdSAndroid Build Coastguard Worker    if (FILTER_PID)
185*387f9dfdSAndroid Build Coastguard Worker        return 0;
186*387f9dfdSAndroid Build Coastguard Worker
187*387f9dfdSAndroid Build Coastguard Worker    // store filep and timestamp by id
188*387f9dfdSAndroid Build Coastguard Worker    struct val_t val = {};
189*387f9dfdSAndroid Build Coastguard Worker    val.ts = bpf_ktime_get_ns();
190*387f9dfdSAndroid Build Coastguard Worker    val.fp = file;
191*387f9dfdSAndroid Build Coastguard Worker    val.offset = 0;
192*387f9dfdSAndroid Build Coastguard Worker    if (val.fp)
193*387f9dfdSAndroid Build Coastguard Worker        entryinfo.update(&id, &val);
194*387f9dfdSAndroid Build Coastguard Worker
195*387f9dfdSAndroid Build Coastguard Worker    return 0;
196*387f9dfdSAndroid Build Coastguard Worker}
197*387f9dfdSAndroid Build Coastguard Worker
198*387f9dfdSAndroid Build Coastguard Worker//
199*387f9dfdSAndroid Build Coastguard Worker// Output
200*387f9dfdSAndroid Build Coastguard Worker//
201*387f9dfdSAndroid Build Coastguard Worker
202*387f9dfdSAndroid Build Coastguard Workerstatic int trace_return(struct pt_regs *ctx, int type)
203*387f9dfdSAndroid Build Coastguard Worker{
204*387f9dfdSAndroid Build Coastguard Worker    struct val_t *valp;
205*387f9dfdSAndroid Build Coastguard Worker    u64 id = bpf_get_current_pid_tgid();
206*387f9dfdSAndroid Build Coastguard Worker    u32 pid = id >> 32; // PID is higher part
207*387f9dfdSAndroid Build Coastguard Worker
208*387f9dfdSAndroid Build Coastguard Worker    valp = entryinfo.lookup(&id);
209*387f9dfdSAndroid Build Coastguard Worker    if (valp == 0) {
210*387f9dfdSAndroid Build Coastguard Worker        // missed tracing issue or filtered
211*387f9dfdSAndroid Build Coastguard Worker        return 0;
212*387f9dfdSAndroid Build Coastguard Worker    }
213*387f9dfdSAndroid Build Coastguard Worker
214*387f9dfdSAndroid Build Coastguard Worker    // calculate delta
215*387f9dfdSAndroid Build Coastguard Worker    u64 ts = bpf_ktime_get_ns();
216*387f9dfdSAndroid Build Coastguard Worker    u64 delta_us = (ts - valp->ts) / 1000;
217*387f9dfdSAndroid Build Coastguard Worker    entryinfo.delete(&id);
218*387f9dfdSAndroid Build Coastguard Worker    if (FILTER_US)
219*387f9dfdSAndroid Build Coastguard Worker        return 0;
220*387f9dfdSAndroid Build Coastguard Worker
221*387f9dfdSAndroid Build Coastguard Worker    // populate output struct
222*387f9dfdSAndroid Build Coastguard Worker    struct data_t data = {};
223*387f9dfdSAndroid Build Coastguard Worker    data.type = type;
224*387f9dfdSAndroid Build Coastguard Worker    data.size = PT_REGS_RC(ctx);
225*387f9dfdSAndroid Build Coastguard Worker    data.delta_us = delta_us;
226*387f9dfdSAndroid Build Coastguard Worker    data.pid = pid;
227*387f9dfdSAndroid Build Coastguard Worker    data.ts_us = ts / 1000;
228*387f9dfdSAndroid Build Coastguard Worker    data.offset = valp->offset;
229*387f9dfdSAndroid Build Coastguard Worker    bpf_get_current_comm(&data.task, sizeof(data.task));
230*387f9dfdSAndroid Build Coastguard Worker
231*387f9dfdSAndroid Build Coastguard Worker    // workaround (rewriter should handle file to d_name in one step):
232*387f9dfdSAndroid Build Coastguard Worker    struct dentry *de = NULL;
233*387f9dfdSAndroid Build Coastguard Worker    struct qstr qs = {};
234*387f9dfdSAndroid Build Coastguard Worker    de = valp->fp->f_path.dentry;
235*387f9dfdSAndroid Build Coastguard Worker    qs = de->d_name;
236*387f9dfdSAndroid Build Coastguard Worker    if (qs.len == 0)
237*387f9dfdSAndroid Build Coastguard Worker        return 0;
238*387f9dfdSAndroid Build Coastguard Worker    bpf_probe_read_kernel(&data.file, sizeof(data.file), (void *)qs.name);
239*387f9dfdSAndroid Build Coastguard Worker
240*387f9dfdSAndroid Build Coastguard Worker    // output
241*387f9dfdSAndroid Build Coastguard Worker    events.perf_submit(ctx, &data, sizeof(data));
242*387f9dfdSAndroid Build Coastguard Worker
243*387f9dfdSAndroid Build Coastguard Worker    return 0;
244*387f9dfdSAndroid Build Coastguard Worker}
245*387f9dfdSAndroid Build Coastguard Worker
246*387f9dfdSAndroid Build Coastguard Workerint trace_read_return(struct pt_regs *ctx)
247*387f9dfdSAndroid Build Coastguard Worker{
248*387f9dfdSAndroid Build Coastguard Worker    return trace_return(ctx, TRACE_READ);
249*387f9dfdSAndroid Build Coastguard Worker}
250*387f9dfdSAndroid Build Coastguard Worker
251*387f9dfdSAndroid Build Coastguard Workerint trace_write_return(struct pt_regs *ctx)
252*387f9dfdSAndroid Build Coastguard Worker{
253*387f9dfdSAndroid Build Coastguard Worker    return trace_return(ctx, TRACE_WRITE);
254*387f9dfdSAndroid Build Coastguard Worker}
255*387f9dfdSAndroid Build Coastguard Worker
256*387f9dfdSAndroid Build Coastguard Workerint trace_open_return(struct pt_regs *ctx)
257*387f9dfdSAndroid Build Coastguard Worker{
258*387f9dfdSAndroid Build Coastguard Worker    return trace_return(ctx, TRACE_OPEN);
259*387f9dfdSAndroid Build Coastguard Worker}
260*387f9dfdSAndroid Build Coastguard Worker
261*387f9dfdSAndroid Build Coastguard Workerint trace_fsync_return(struct pt_regs *ctx)
262*387f9dfdSAndroid Build Coastguard Worker{
263*387f9dfdSAndroid Build Coastguard Worker    return trace_return(ctx, TRACE_FSYNC);
264*387f9dfdSAndroid Build Coastguard Worker}
265*387f9dfdSAndroid Build Coastguard Worker
266*387f9dfdSAndroid Build Coastguard Worker"""
267*387f9dfdSAndroid Build Coastguard Worker
268*387f9dfdSAndroid Build Coastguard Worker# code replacements
269*387f9dfdSAndroid Build Coastguard Workerwith open(kallsyms) as syms:
270*387f9dfdSAndroid Build Coastguard Worker    ops = ''
271*387f9dfdSAndroid Build Coastguard Worker    for line in syms:
272*387f9dfdSAndroid Build Coastguard Worker        a = line.rstrip().split()
273*387f9dfdSAndroid Build Coastguard Worker        (addr, name) = (a[0], a[2])
274*387f9dfdSAndroid Build Coastguard Worker        name = name.split("\t")[0]
275*387f9dfdSAndroid Build Coastguard Worker        if name == "btrfs_file_operations":
276*387f9dfdSAndroid Build Coastguard Worker            ops = "0x" + addr
277*387f9dfdSAndroid Build Coastguard Worker            break
278*387f9dfdSAndroid Build Coastguard Worker    if ops == '':
279*387f9dfdSAndroid Build Coastguard Worker        print("ERROR: no btrfs_file_operations in /proc/kallsyms. Exiting.")
280*387f9dfdSAndroid Build Coastguard Worker        print("HINT: the kernel should be built with CONFIG_KALLSYMS_ALL.")
281*387f9dfdSAndroid Build Coastguard Worker        exit()
282*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('BTRFS_FILE_OPERATIONS', ops)
283*387f9dfdSAndroid Build Coastguard Workerif min_ms == 0:
284*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('FILTER_US', '0')
285*387f9dfdSAndroid Build Coastguard Workerelse:
286*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('FILTER_US',
287*387f9dfdSAndroid Build Coastguard Worker        'delta_us <= %s' % str(min_ms * 1000))
288*387f9dfdSAndroid Build Coastguard Workerif args.pid:
289*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('FILTER_PID', 'pid != %s' % pid)
290*387f9dfdSAndroid Build Coastguard Workerelse:
291*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('FILTER_PID', '0')
292*387f9dfdSAndroid Build Coastguard Workerif debug or args.ebpf:
293*387f9dfdSAndroid Build Coastguard Worker    print(bpf_text)
294*387f9dfdSAndroid Build Coastguard Worker    if args.ebpf:
295*387f9dfdSAndroid Build Coastguard Worker        exit()
296*387f9dfdSAndroid Build Coastguard Worker
297*387f9dfdSAndroid Build Coastguard Worker# process event
298*387f9dfdSAndroid Build Coastguard Workerdef print_event(cpu, data, size):
299*387f9dfdSAndroid Build Coastguard Worker    event = b["events"].event(data)
300*387f9dfdSAndroid Build Coastguard Worker
301*387f9dfdSAndroid Build Coastguard Worker    type = 'R'
302*387f9dfdSAndroid Build Coastguard Worker    if event.type == 1:
303*387f9dfdSAndroid Build Coastguard Worker        type = 'W'
304*387f9dfdSAndroid Build Coastguard Worker    elif event.type == 2:
305*387f9dfdSAndroid Build Coastguard Worker        type = 'O'
306*387f9dfdSAndroid Build Coastguard Worker    elif event.type == 3:
307*387f9dfdSAndroid Build Coastguard Worker        type = 'S'
308*387f9dfdSAndroid Build Coastguard Worker
309*387f9dfdSAndroid Build Coastguard Worker    if (csv):
310*387f9dfdSAndroid Build Coastguard Worker        print("%d,%s,%d,%s,%d,%d,%d,%s" % (
311*387f9dfdSAndroid Build Coastguard Worker            event.ts_us, event.task.decode('utf-8', 'replace'), event.pid,
312*387f9dfdSAndroid Build Coastguard Worker            type, event.size, event.offset, event.delta_us,
313*387f9dfdSAndroid Build Coastguard Worker            event.file.decode('utf-8', 'replace')))
314*387f9dfdSAndroid Build Coastguard Worker        return
315*387f9dfdSAndroid Build Coastguard Worker    print("%-8s %-14.14s %-7d %1s %-7s %-8d %7.2f %s" % (strftime("%H:%M:%S"),
316*387f9dfdSAndroid Build Coastguard Worker        event.task.decode('utf-8', 'replace'), event.pid, type, event.size,
317*387f9dfdSAndroid Build Coastguard Worker        event.offset / 1024, float(event.delta_us) / 1000,
318*387f9dfdSAndroid Build Coastguard Worker        event.file.decode('utf-8', 'replace')))
319*387f9dfdSAndroid Build Coastguard Worker
320*387f9dfdSAndroid Build Coastguard Worker# initialize BPF
321*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text)
322*387f9dfdSAndroid Build Coastguard Worker
323*387f9dfdSAndroid Build Coastguard Worker# Common file functions. See earlier comment about generic_*().
324*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event="generic_file_read_iter", fn_name="trace_read_entry")
325*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event="btrfs_file_write_iter", fn_name="trace_write_entry")
326*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event="generic_file_open", fn_name="trace_open_entry")
327*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event="btrfs_sync_file", fn_name="trace_fsync_entry")
328*387f9dfdSAndroid Build Coastguard Workerb.attach_kretprobe(event="generic_file_read_iter", fn_name="trace_read_return")
329*387f9dfdSAndroid Build Coastguard Workerb.attach_kretprobe(event="btrfs_file_write_iter", fn_name="trace_write_return")
330*387f9dfdSAndroid Build Coastguard Workerb.attach_kretprobe(event="generic_file_open", fn_name="trace_open_return")
331*387f9dfdSAndroid Build Coastguard Workerb.attach_kretprobe(event="btrfs_sync_file", fn_name="trace_fsync_return")
332*387f9dfdSAndroid Build Coastguard Worker
333*387f9dfdSAndroid Build Coastguard Worker# header
334*387f9dfdSAndroid Build Coastguard Workerif (csv):
335*387f9dfdSAndroid Build Coastguard Worker    print("ENDTIME_us,TASK,PID,TYPE,BYTES,OFFSET_b,LATENCY_us,FILE")
336*387f9dfdSAndroid Build Coastguard Workerelse:
337*387f9dfdSAndroid Build Coastguard Worker    if min_ms == 0:
338*387f9dfdSAndroid Build Coastguard Worker        print("Tracing btrfs operations")
339*387f9dfdSAndroid Build Coastguard Worker    else:
340*387f9dfdSAndroid Build Coastguard Worker        print("Tracing btrfs operations slower than %d ms" % min_ms)
341*387f9dfdSAndroid Build Coastguard Worker    print("%-8s %-14s %-7s %1s %-7s %-8s %7s %s" % ("TIME", "COMM", "PID", "T",
342*387f9dfdSAndroid Build Coastguard Worker        "BYTES", "OFF_KB", "LAT(ms)", "FILENAME"))
343*387f9dfdSAndroid Build Coastguard Worker
344*387f9dfdSAndroid Build Coastguard Worker# read events
345*387f9dfdSAndroid Build Coastguard Workerb["events"].open_perf_buffer(print_event, page_cnt=64)
346*387f9dfdSAndroid Build Coastguard Workerstart_time = datetime.now()
347*387f9dfdSAndroid Build Coastguard Workerwhile not args.duration or datetime.now() - start_time < args.duration:
348*387f9dfdSAndroid Build Coastguard Worker    try:
349*387f9dfdSAndroid Build Coastguard Worker        b.perf_buffer_poll(timeout=1000)
350*387f9dfdSAndroid Build Coastguard Worker    except KeyboardInterrupt:
351*387f9dfdSAndroid Build Coastguard Worker        exit()
352