xref: /aosp_15_r20/external/bcc/tools/vfsstat.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# vfsstat   Count some VFS calls.
5*387f9dfdSAndroid Build Coastguard Worker#           For Linux, uses BCC, eBPF. Embedded C.
6*387f9dfdSAndroid Build Coastguard Worker#
7*387f9dfdSAndroid Build Coastguard Worker# Written as a basic example of counting multiple events as a stat tool.
8*387f9dfdSAndroid Build Coastguard Worker#
9*387f9dfdSAndroid Build Coastguard Worker# USAGE: vfsstat [-h] [-p PID] [interval] [count]
10*387f9dfdSAndroid Build Coastguard Worker#
11*387f9dfdSAndroid Build Coastguard Worker# Copyright (c) 2015 Brendan Gregg.
12*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License")
13*387f9dfdSAndroid Build Coastguard Worker#
14*387f9dfdSAndroid Build Coastguard Worker# 14-Aug-2015   Brendan Gregg   Created this.
15*387f9dfdSAndroid Build Coastguard Worker# 12-Oct-2022   Rocky Xing      Added PID filter support.
16*387f9dfdSAndroid Build Coastguard Worker
17*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function
18*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF
19*387f9dfdSAndroid Build Coastguard Workerfrom ctypes import c_int
20*387f9dfdSAndroid Build Coastguard Workerfrom time import sleep, strftime
21*387f9dfdSAndroid Build Coastguard Workerfrom sys import argv
22*387f9dfdSAndroid Build Coastguard Workerimport argparse
23*387f9dfdSAndroid Build Coastguard Worker
24*387f9dfdSAndroid Build Coastguard Worker# arguments
25*387f9dfdSAndroid Build Coastguard Workerexamples = """examples:
26*387f9dfdSAndroid Build Coastguard Worker    ./vfsstat             # count some VFS calls per second
27*387f9dfdSAndroid Build Coastguard Worker    ./vfsstat -p 185      # trace PID 185 only
28*387f9dfdSAndroid Build Coastguard Worker    ./vfsstat 2 5         # print 2 second summaries, 5 times
29*387f9dfdSAndroid Build Coastguard Worker"""
30*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser(
31*387f9dfdSAndroid Build Coastguard Worker    description="Count some VFS calls.",
32*387f9dfdSAndroid Build Coastguard Worker    formatter_class=argparse.RawDescriptionHelpFormatter,
33*387f9dfdSAndroid Build Coastguard Worker    epilog=examples)
34*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-p", "--pid",
35*387f9dfdSAndroid Build Coastguard Worker    help="trace this PID only")
36*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("interval", nargs="?", default=1,
37*387f9dfdSAndroid Build Coastguard Worker    help="output interval, in seconds")
38*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("count", nargs="?", default=99999999,
39*387f9dfdSAndroid Build Coastguard Worker    help="number of outputs")
40*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--ebpf", action="store_true",
41*387f9dfdSAndroid Build Coastguard Worker    help=argparse.SUPPRESS)
42*387f9dfdSAndroid Build Coastguard Worker
43*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args()
44*387f9dfdSAndroid Build Coastguard Workercountdown = int(args.count)
45*387f9dfdSAndroid Build Coastguard Workerdebug = 0
46*387f9dfdSAndroid Build Coastguard Worker
47*387f9dfdSAndroid Build Coastguard Worker# load BPF program
48*387f9dfdSAndroid Build Coastguard Workerbpf_text = """
49*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h>
50*387f9dfdSAndroid Build Coastguard Worker
51*387f9dfdSAndroid Build Coastguard Workerenum stat_types {
52*387f9dfdSAndroid Build Coastguard Worker    S_READ = 1,
53*387f9dfdSAndroid Build Coastguard Worker    S_WRITE,
54*387f9dfdSAndroid Build Coastguard Worker    S_FSYNC,
55*387f9dfdSAndroid Build Coastguard Worker    S_OPEN,
56*387f9dfdSAndroid Build Coastguard Worker    S_CREATE,
57*387f9dfdSAndroid Build Coastguard Worker    S_MAXSTAT
58*387f9dfdSAndroid Build Coastguard Worker};
59*387f9dfdSAndroid Build Coastguard Worker
60*387f9dfdSAndroid Build Coastguard WorkerBPF_ARRAY(stats, u64, S_MAXSTAT);
61*387f9dfdSAndroid Build Coastguard Worker
62*387f9dfdSAndroid Build Coastguard Workerstatic void stats_try_increment(int key) {
63*387f9dfdSAndroid Build Coastguard Worker    PID_FILTER
64*387f9dfdSAndroid Build Coastguard Worker    stats.atomic_increment(key);
65*387f9dfdSAndroid Build Coastguard Worker}
66*387f9dfdSAndroid Build Coastguard Worker"""
67*387f9dfdSAndroid Build Coastguard Worker
68*387f9dfdSAndroid Build Coastguard Workerbpf_text_kprobe = """
69*387f9dfdSAndroid Build Coastguard Workervoid do_read(struct pt_regs *ctx) { stats_try_increment(S_READ); }
70*387f9dfdSAndroid Build Coastguard Workervoid do_write(struct pt_regs *ctx) { stats_try_increment(S_WRITE); }
71*387f9dfdSAndroid Build Coastguard Workervoid do_fsync(struct pt_regs *ctx) { stats_try_increment(S_FSYNC); }
72*387f9dfdSAndroid Build Coastguard Workervoid do_open(struct pt_regs *ctx) { stats_try_increment(S_OPEN); }
73*387f9dfdSAndroid Build Coastguard Workervoid do_create(struct pt_regs *ctx) { stats_try_increment(S_CREATE); }
74*387f9dfdSAndroid Build Coastguard Worker"""
75*387f9dfdSAndroid Build Coastguard Worker
76*387f9dfdSAndroid Build Coastguard Workerbpf_text_kfunc = """
77*387f9dfdSAndroid Build Coastguard WorkerKFUNC_PROBE(vfs_read)         { stats_try_increment(S_READ); return 0; }
78*387f9dfdSAndroid Build Coastguard WorkerKFUNC_PROBE(vfs_write)        { stats_try_increment(S_WRITE); return 0; }
79*387f9dfdSAndroid Build Coastguard WorkerKFUNC_PROBE(vfs_fsync_range)  { stats_try_increment(S_FSYNC); return 0; }
80*387f9dfdSAndroid Build Coastguard WorkerKFUNC_PROBE(vfs_open)         { stats_try_increment(S_OPEN); return 0; }
81*387f9dfdSAndroid Build Coastguard WorkerKFUNC_PROBE(vfs_create)       { stats_try_increment(S_CREATE); return 0; }
82*387f9dfdSAndroid Build Coastguard Worker"""
83*387f9dfdSAndroid Build Coastguard Worker
84*387f9dfdSAndroid Build Coastguard Workeris_support_kfunc = BPF.support_kfunc()
85*387f9dfdSAndroid Build Coastguard Workerif is_support_kfunc:
86*387f9dfdSAndroid Build Coastguard Worker    bpf_text += bpf_text_kfunc
87*387f9dfdSAndroid Build Coastguard Workerelse:
88*387f9dfdSAndroid Build Coastguard Worker    bpf_text += bpf_text_kprobe
89*387f9dfdSAndroid Build Coastguard Worker
90*387f9dfdSAndroid Build Coastguard Workerif args.pid:
91*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('PID_FILTER', """
92*387f9dfdSAndroid Build Coastguard Worker    u32 pid = bpf_get_current_pid_tgid() >> 32;
93*387f9dfdSAndroid Build Coastguard Worker    if (pid != %s) {
94*387f9dfdSAndroid Build Coastguard Worker        return;
95*387f9dfdSAndroid Build Coastguard Worker    }
96*387f9dfdSAndroid Build Coastguard Worker    """ % args.pid)
97*387f9dfdSAndroid Build Coastguard Workerelse:
98*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('PID_FILTER', '')
99*387f9dfdSAndroid Build Coastguard Worker
100*387f9dfdSAndroid Build Coastguard Workerif debug or args.ebpf:
101*387f9dfdSAndroid Build Coastguard Worker    print(bpf_text)
102*387f9dfdSAndroid Build Coastguard Worker    if args.ebpf:
103*387f9dfdSAndroid Build Coastguard Worker        exit()
104*387f9dfdSAndroid Build Coastguard Worker
105*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text)
106*387f9dfdSAndroid Build Coastguard Workerif not is_support_kfunc:
107*387f9dfdSAndroid Build Coastguard Worker    b.attach_kprobe(event="vfs_read",         fn_name="do_read")
108*387f9dfdSAndroid Build Coastguard Worker    b.attach_kprobe(event="vfs_write",        fn_name="do_write")
109*387f9dfdSAndroid Build Coastguard Worker    b.attach_kprobe(event="vfs_fsync_range",  fn_name="do_fsync")
110*387f9dfdSAndroid Build Coastguard Worker    b.attach_kprobe(event="vfs_open",         fn_name="do_open")
111*387f9dfdSAndroid Build Coastguard Worker    b.attach_kprobe(event="vfs_create",       fn_name="do_create")
112*387f9dfdSAndroid Build Coastguard Worker
113*387f9dfdSAndroid Build Coastguard Worker# stat column labels and indexes
114*387f9dfdSAndroid Build Coastguard Workerstat_types = {
115*387f9dfdSAndroid Build Coastguard Worker    "READ": 1,
116*387f9dfdSAndroid Build Coastguard Worker    "WRITE": 2,
117*387f9dfdSAndroid Build Coastguard Worker    "FSYNC": 3,
118*387f9dfdSAndroid Build Coastguard Worker    "OPEN": 4,
119*387f9dfdSAndroid Build Coastguard Worker    "CREATE": 5
120*387f9dfdSAndroid Build Coastguard Worker}
121*387f9dfdSAndroid Build Coastguard Worker
122*387f9dfdSAndroid Build Coastguard Worker# header
123*387f9dfdSAndroid Build Coastguard Workerprint("%-8s  " % "TIME", end="")
124*387f9dfdSAndroid Build Coastguard Workerfor stype in stat_types.keys():
125*387f9dfdSAndroid Build Coastguard Worker    print(" %8s" % (stype + "/s"), end="")
126*387f9dfdSAndroid Build Coastguard Worker    idx = stat_types[stype]
127*387f9dfdSAndroid Build Coastguard Workerprint("")
128*387f9dfdSAndroid Build Coastguard Worker
129*387f9dfdSAndroid Build Coastguard Worker# output
130*387f9dfdSAndroid Build Coastguard Workerexiting = 0 if args.interval else 1
131*387f9dfdSAndroid Build Coastguard Workerwhile (1):
132*387f9dfdSAndroid Build Coastguard Worker    try:
133*387f9dfdSAndroid Build Coastguard Worker        sleep(int(args.interval))
134*387f9dfdSAndroid Build Coastguard Worker    except KeyboardInterrupt:
135*387f9dfdSAndroid Build Coastguard Worker        exiting = 1
136*387f9dfdSAndroid Build Coastguard Worker
137*387f9dfdSAndroid Build Coastguard Worker    print("%-8s: " % strftime("%H:%M:%S"), end="")
138*387f9dfdSAndroid Build Coastguard Worker    # print each statistic as a column
139*387f9dfdSAndroid Build Coastguard Worker    for stype in stat_types.keys():
140*387f9dfdSAndroid Build Coastguard Worker        idx = stat_types[stype]
141*387f9dfdSAndroid Build Coastguard Worker        try:
142*387f9dfdSAndroid Build Coastguard Worker            val = b["stats"][c_int(idx)].value / int(args.interval)
143*387f9dfdSAndroid Build Coastguard Worker            print(" %8d" % val, end="")
144*387f9dfdSAndroid Build Coastguard Worker        except:
145*387f9dfdSAndroid Build Coastguard Worker            print(" %8d" % 0, end="")
146*387f9dfdSAndroid Build Coastguard Worker    b["stats"].clear()
147*387f9dfdSAndroid Build Coastguard Worker    print("")
148*387f9dfdSAndroid Build Coastguard Worker
149*387f9dfdSAndroid Build Coastguard Worker    countdown -= 1
150*387f9dfdSAndroid Build Coastguard Worker    if exiting or countdown == 0:
151*387f9dfdSAndroid Build Coastguard Worker        exit()
152