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