xref: /aosp_15_r20/external/bcc/tools/dcsnoop.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# dcsnoop   Trace directory entry cache (dcache) lookups.
5*387f9dfdSAndroid Build Coastguard Worker#           For Linux, uses BCC, eBPF. Embedded C.
6*387f9dfdSAndroid Build Coastguard Worker#
7*387f9dfdSAndroid Build Coastguard Worker# USAGE: dcsnoop [-h] [-a]
8*387f9dfdSAndroid Build Coastguard Worker#
9*387f9dfdSAndroid Build Coastguard Worker# By default, this traces every failed dcache lookup, and shows the process
10*387f9dfdSAndroid Build Coastguard Worker# performing the lookup and the filename requested. A -a option can be used
11*387f9dfdSAndroid Build Coastguard Worker# to show all lookups, not just failed ones.
12*387f9dfdSAndroid Build Coastguard Worker#
13*387f9dfdSAndroid Build Coastguard Worker# This uses kernel dynamic tracing of the d_lookup() function, and will need
14*387f9dfdSAndroid Build Coastguard Worker# to be modified to match kernel changes.
15*387f9dfdSAndroid Build Coastguard Worker#
16*387f9dfdSAndroid Build Coastguard Worker# Also see dcstat(8), for per-second summaries.
17*387f9dfdSAndroid Build Coastguard Worker#
18*387f9dfdSAndroid Build Coastguard Worker# Copyright 2016 Netflix, Inc.
19*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License")
20*387f9dfdSAndroid Build Coastguard Worker#
21*387f9dfdSAndroid Build Coastguard Worker# 09-Feb-2016   Brendan Gregg   Created this.
22*387f9dfdSAndroid Build Coastguard Worker
23*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function
24*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF
25*387f9dfdSAndroid Build Coastguard Workerimport argparse
26*387f9dfdSAndroid Build Coastguard Workerimport re
27*387f9dfdSAndroid Build Coastguard Workerimport time
28*387f9dfdSAndroid Build Coastguard Worker
29*387f9dfdSAndroid Build Coastguard Worker# arguments
30*387f9dfdSAndroid Build Coastguard Workerexamples = """examples:
31*387f9dfdSAndroid Build Coastguard Worker    ./dcsnoop           # trace failed dcache lookups
32*387f9dfdSAndroid Build Coastguard Worker    ./dcsnoop -a        # trace all dcache lookups
33*387f9dfdSAndroid Build Coastguard Worker"""
34*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser(
35*387f9dfdSAndroid Build Coastguard Worker    description="Trace directory entry cache (dcache) lookups",
36*387f9dfdSAndroid Build Coastguard Worker    formatter_class=argparse.RawDescriptionHelpFormatter,
37*387f9dfdSAndroid Build Coastguard Worker    epilog=examples)
38*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-a", "--all", action="store_true",
39*387f9dfdSAndroid Build Coastguard Worker    help="trace all lookups (default is fails only)")
40*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--ebpf", action="store_true",
41*387f9dfdSAndroid Build Coastguard Worker    help=argparse.SUPPRESS)
42*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args()
43*387f9dfdSAndroid Build Coastguard Worker
44*387f9dfdSAndroid Build Coastguard Worker# define BPF program
45*387f9dfdSAndroid Build Coastguard Workerbpf_text = """
46*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h>
47*387f9dfdSAndroid Build Coastguard Worker#include <linux/fs.h>
48*387f9dfdSAndroid Build Coastguard Worker#include <linux/sched.h>
49*387f9dfdSAndroid Build Coastguard Worker
50*387f9dfdSAndroid Build Coastguard Worker#define MAX_FILE_LEN  64
51*387f9dfdSAndroid Build Coastguard Worker
52*387f9dfdSAndroid Build Coastguard Workerenum lookup_type {
53*387f9dfdSAndroid Build Coastguard Worker    LOOKUP_MISS,
54*387f9dfdSAndroid Build Coastguard Worker    LOOKUP_REFERENCE,
55*387f9dfdSAndroid Build Coastguard Worker};
56*387f9dfdSAndroid Build Coastguard Worker
57*387f9dfdSAndroid Build Coastguard Workerstruct entry_t {
58*387f9dfdSAndroid Build Coastguard Worker    char name[MAX_FILE_LEN];
59*387f9dfdSAndroid Build Coastguard Worker};
60*387f9dfdSAndroid Build Coastguard Worker
61*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(entrybypid, u32, struct entry_t);
62*387f9dfdSAndroid Build Coastguard Worker
63*387f9dfdSAndroid Build Coastguard Workerstruct data_t {
64*387f9dfdSAndroid Build Coastguard Worker    u32 pid;
65*387f9dfdSAndroid Build Coastguard Worker    enum lookup_type type;
66*387f9dfdSAndroid Build Coastguard Worker    char comm[TASK_COMM_LEN];
67*387f9dfdSAndroid Build Coastguard Worker    char filename[MAX_FILE_LEN];
68*387f9dfdSAndroid Build Coastguard Worker};
69*387f9dfdSAndroid Build Coastguard Worker
70*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(events);
71*387f9dfdSAndroid Build Coastguard Worker
72*387f9dfdSAndroid Build Coastguard Worker/* from fs/namei.c: */
73*387f9dfdSAndroid Build Coastguard Workerstruct nameidata {
74*387f9dfdSAndroid Build Coastguard Worker        struct path     path;
75*387f9dfdSAndroid Build Coastguard Worker        struct qstr     last;
76*387f9dfdSAndroid Build Coastguard Worker        // [...]
77*387f9dfdSAndroid Build Coastguard Worker};
78*387f9dfdSAndroid Build Coastguard Worker
79*387f9dfdSAndroid Build Coastguard Workerstatic inline
80*387f9dfdSAndroid Build Coastguard Workervoid submit_event(struct pt_regs *ctx, void *name, int type, u32 pid)
81*387f9dfdSAndroid Build Coastguard Worker{
82*387f9dfdSAndroid Build Coastguard Worker    struct data_t data = {
83*387f9dfdSAndroid Build Coastguard Worker        .pid = pid,
84*387f9dfdSAndroid Build Coastguard Worker        .type = type,
85*387f9dfdSAndroid Build Coastguard Worker    };
86*387f9dfdSAndroid Build Coastguard Worker    bpf_get_current_comm(&data.comm, sizeof(data.comm));
87*387f9dfdSAndroid Build Coastguard Worker    bpf_probe_read_kernel(&data.filename, sizeof(data.filename), name);
88*387f9dfdSAndroid Build Coastguard Worker    events.perf_submit(ctx, &data, sizeof(data));
89*387f9dfdSAndroid Build Coastguard Worker}
90*387f9dfdSAndroid Build Coastguard Worker
91*387f9dfdSAndroid Build Coastguard Workerint trace_fast(struct pt_regs *ctx, struct nameidata *nd, struct path *path)
92*387f9dfdSAndroid Build Coastguard Worker{
93*387f9dfdSAndroid Build Coastguard Worker    u32 pid = bpf_get_current_pid_tgid() >> 32;
94*387f9dfdSAndroid Build Coastguard Worker    submit_event(ctx, (void *)nd->last.name, LOOKUP_REFERENCE, pid);
95*387f9dfdSAndroid Build Coastguard Worker    return 1;
96*387f9dfdSAndroid Build Coastguard Worker}
97*387f9dfdSAndroid Build Coastguard Worker
98*387f9dfdSAndroid Build Coastguard Workerint kprobe__d_lookup(struct pt_regs *ctx, const struct dentry *parent,
99*387f9dfdSAndroid Build Coastguard Worker    const struct qstr *name)
100*387f9dfdSAndroid Build Coastguard Worker{
101*387f9dfdSAndroid Build Coastguard Worker    u32 tid = bpf_get_current_pid_tgid();
102*387f9dfdSAndroid Build Coastguard Worker    struct entry_t entry = {};
103*387f9dfdSAndroid Build Coastguard Worker    const char *fname = name->name;
104*387f9dfdSAndroid Build Coastguard Worker    if (fname) {
105*387f9dfdSAndroid Build Coastguard Worker        bpf_probe_read_kernel(&entry.name, sizeof(entry.name), (void *)fname);
106*387f9dfdSAndroid Build Coastguard Worker    }
107*387f9dfdSAndroid Build Coastguard Worker    entrybypid.update(&tid, &entry);
108*387f9dfdSAndroid Build Coastguard Worker    return 0;
109*387f9dfdSAndroid Build Coastguard Worker}
110*387f9dfdSAndroid Build Coastguard Worker
111*387f9dfdSAndroid Build Coastguard Workerint kretprobe__d_lookup(struct pt_regs *ctx)
112*387f9dfdSAndroid Build Coastguard Worker{
113*387f9dfdSAndroid Build Coastguard Worker    u64 pid_tgid = bpf_get_current_pid_tgid();
114*387f9dfdSAndroid Build Coastguard Worker    u32 pid = pid_tgid >> 32;
115*387f9dfdSAndroid Build Coastguard Worker    u32 tid = (u32)pid_tgid;
116*387f9dfdSAndroid Build Coastguard Worker    struct entry_t *ep;
117*387f9dfdSAndroid Build Coastguard Worker
118*387f9dfdSAndroid Build Coastguard Worker    ep = entrybypid.lookup(&tid);
119*387f9dfdSAndroid Build Coastguard Worker    if (ep == 0) {
120*387f9dfdSAndroid Build Coastguard Worker        return 0;   // missed entry
121*387f9dfdSAndroid Build Coastguard Worker    }
122*387f9dfdSAndroid Build Coastguard Worker    if (PT_REGS_RC(ctx) != 0) {
123*387f9dfdSAndroid Build Coastguard Worker        entrybypid.delete(&tid);
124*387f9dfdSAndroid Build Coastguard Worker        return 0;   // lookup didn't fail
125*387f9dfdSAndroid Build Coastguard Worker    }
126*387f9dfdSAndroid Build Coastguard Worker
127*387f9dfdSAndroid Build Coastguard Worker    submit_event(ctx, (void *)ep->name, LOOKUP_MISS, pid);
128*387f9dfdSAndroid Build Coastguard Worker    entrybypid.delete(&tid);
129*387f9dfdSAndroid Build Coastguard Worker    return 0;
130*387f9dfdSAndroid Build Coastguard Worker}
131*387f9dfdSAndroid Build Coastguard Worker"""
132*387f9dfdSAndroid Build Coastguard Worker
133*387f9dfdSAndroid Build Coastguard Workerif args.ebpf:
134*387f9dfdSAndroid Build Coastguard Worker    print(bpf_text)
135*387f9dfdSAndroid Build Coastguard Worker    exit()
136*387f9dfdSAndroid Build Coastguard Worker
137*387f9dfdSAndroid Build Coastguard Worker# initialize BPF
138*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text)
139*387f9dfdSAndroid Build Coastguard Workerif args.all:
140*387f9dfdSAndroid Build Coastguard Worker    b.attach_kprobe(event_re="^lookup_fast$|^lookup_fast.constprop.*.\d$", fn_name="trace_fast")
141*387f9dfdSAndroid Build Coastguard Worker
142*387f9dfdSAndroid Build Coastguard Workermode_s = {
143*387f9dfdSAndroid Build Coastguard Worker    0: 'M',
144*387f9dfdSAndroid Build Coastguard Worker    1: 'R',
145*387f9dfdSAndroid Build Coastguard Worker}
146*387f9dfdSAndroid Build Coastguard Worker
147*387f9dfdSAndroid Build Coastguard Workerstart_ts = time.time()
148*387f9dfdSAndroid Build Coastguard Worker
149*387f9dfdSAndroid Build Coastguard Workerdef print_event(cpu, data, size):
150*387f9dfdSAndroid Build Coastguard Worker    event = b["events"].event(data)
151*387f9dfdSAndroid Build Coastguard Worker    print("%-11.6f %-7d %-16s %1s %s" % (
152*387f9dfdSAndroid Build Coastguard Worker            time.time() - start_ts, event.pid,
153*387f9dfdSAndroid Build Coastguard Worker            event.comm.decode('utf-8', 'replace'), mode_s[event.type],
154*387f9dfdSAndroid Build Coastguard Worker            event.filename.decode('utf-8', 'replace')))
155*387f9dfdSAndroid Build Coastguard Worker
156*387f9dfdSAndroid Build Coastguard Worker# header
157*387f9dfdSAndroid Build Coastguard Workerprint("%-11s %-7s %-16s %1s %s" % ("TIME(s)", "PID", "COMM", "T", "FILE"))
158*387f9dfdSAndroid Build Coastguard Worker
159*387f9dfdSAndroid Build Coastguard Workerb["events"].open_perf_buffer(print_event, page_cnt=64)
160*387f9dfdSAndroid Build Coastguard Workerwhile 1:
161*387f9dfdSAndroid Build Coastguard Worker    try:
162*387f9dfdSAndroid Build Coastguard Worker        b.perf_buffer_poll()
163*387f9dfdSAndroid Build Coastguard Worker    except KeyboardInterrupt:
164*387f9dfdSAndroid Build Coastguard Worker        exit()
165