blob: a862d3333ed6fa77f1b292e674589bdb5fd58c34 [file] [log] [blame]
Alexey Ivanovcc01a9c2019-01-16 09:50:46 -08001#!/usr/bin/python
Alexei Starovoitovbdf07732016-01-14 10:09:20 -08002# @lint-avoid-python-3-compatibility-imports
Brendan Gregg48fbc3e2015-08-18 14:56:14 -07003#
Alexei Starovoitovbdf07732016-01-14 10:09:20 -08004# vfsstat Count some VFS calls.
5# For Linux, uses BCC, eBPF. See .c file.
Brendan Gregg48fbc3e2015-08-18 14:56:14 -07006#
7# Written as a basic example of counting multiple events as a stat tool.
8#
9# USAGE: vfsstat [interval [count]]
10#
11# Copyright (c) 2015 Brendan Gregg.
12# Licensed under the Apache License, Version 2.0 (the "License")
13#
Alexei Starovoitovbdf07732016-01-14 10:09:20 -080014# 14-Aug-2015 Brendan Gregg Created this.
Brendan Gregg48fbc3e2015-08-18 14:56:14 -070015
16from __future__ import print_function
Brenden Blancoc35989d2015-09-02 18:04:07 -070017from bcc import BPF
Alexei Starovoitovbdf07732016-01-14 10:09:20 -080018from ctypes import c_int
Brendan Gregg48fbc3e2015-08-18 14:56:14 -070019from time import sleep, strftime
20from sys import argv
21
22def usage():
Alexei Starovoitovbdf07732016-01-14 10:09:20 -080023 print("USAGE: %s [interval [count]]" % argv[0])
24 exit()
Brendan Gregg48fbc3e2015-08-18 14:56:14 -070025
26# arguments
27interval = 1
28count = -1
29if len(argv) > 1:
Alexei Starovoitovbdf07732016-01-14 10:09:20 -080030 try:
31 interval = int(argv[1])
32 if interval == 0:
33 raise
34 if len(argv) > 2:
35 count = int(argv[2])
36 except: # also catches -h, --help
37 usage()
Brendan Gregg48fbc3e2015-08-18 14:56:14 -070038
39# load BPF program
Jiri Olsa2fa54c02020-02-19 18:48:44 +010040bpf_text = """
Brendan Greggb90bbab2016-02-15 15:55:08 -080041#include <uapi/linux/ptrace.h>
42
43enum stat_types {
44 S_READ = 1,
45 S_WRITE,
46 S_FSYNC,
47 S_OPEN,
48 S_CREATE,
49 S_MAXSTAT
50};
51
Brenden Blancod51870b2017-08-16 11:29:23 -070052BPF_ARRAY(stats, u64, S_MAXSTAT);
Brendan Greggb90bbab2016-02-15 15:55:08 -080053
Brenden Blanco3f28e7b2017-04-20 09:33:44 -070054static void stats_increment(int key) {
zcy80242fb2021-07-02 00:12:32 +080055 stats.atomic_increment(key);
Brendan Greggb90bbab2016-02-15 15:55:08 -080056}
Jiri Olsa2fa54c02020-02-19 18:48:44 +010057"""
Brendan Greggb90bbab2016-02-15 15:55:08 -080058
Jiri Olsa2fa54c02020-02-19 18:48:44 +010059bpf_text_kprobe = """
Brendan Greggb90bbab2016-02-15 15:55:08 -080060void do_read(struct pt_regs *ctx) { stats_increment(S_READ); }
61void do_write(struct pt_regs *ctx) { stats_increment(S_WRITE); }
62void do_fsync(struct pt_regs *ctx) { stats_increment(S_FSYNC); }
63void do_open(struct pt_regs *ctx) { stats_increment(S_OPEN); }
64void do_create(struct pt_regs *ctx) { stats_increment(S_CREATE); }
Jiri Olsa2fa54c02020-02-19 18:48:44 +010065"""
66
67bpf_text_kfunc = """
Hengqi Chen065ec132022-03-20 17:03:56 +080068KFUNC_PROBE(vfs_read) { stats_increment(S_READ); return 0; }
69KFUNC_PROBE(vfs_write) { stats_increment(S_WRITE); return 0; }
70KFUNC_PROBE(vfs_fsync_range) { stats_increment(S_FSYNC); return 0; }
71KFUNC_PROBE(vfs_open) { stats_increment(S_OPEN); return 0; }
72KFUNC_PROBE(vfs_create) { stats_increment(S_CREATE); return 0; }
Jiri Olsa2fa54c02020-02-19 18:48:44 +010073"""
74
75is_support_kfunc = BPF.support_kfunc()
76#is_support_kfunc = False #BPF.support_kfunc()
77if is_support_kfunc:
78 bpf_text += bpf_text_kfunc
79else:
80 bpf_text += bpf_text_kprobe
81
82b = BPF(text=bpf_text)
83if not is_support_kfunc:
Hengqi Chen065ec132022-03-20 17:03:56 +080084 b.attach_kprobe(event="vfs_read", fn_name="do_read")
85 b.attach_kprobe(event="vfs_write", fn_name="do_write")
86 b.attach_kprobe(event="vfs_fsync_range", fn_name="do_fsync")
87 b.attach_kprobe(event="vfs_open", fn_name="do_open")
88 b.attach_kprobe(event="vfs_create", fn_name="do_create")
Brendan Gregg48fbc3e2015-08-18 14:56:14 -070089
90# stat column labels and indexes
91stat_types = {
Alexei Starovoitovbdf07732016-01-14 10:09:20 -080092 "READ": 1,
93 "WRITE": 2,
94 "FSYNC": 3,
95 "OPEN": 4,
96 "CREATE": 5
Brendan Gregg48fbc3e2015-08-18 14:56:14 -070097}
98
99# header
100print("%-8s " % "TIME", end="")
Brendan Gregg48fbc3e2015-08-18 14:56:14 -0700101for stype in stat_types.keys():
Alexei Starovoitovbdf07732016-01-14 10:09:20 -0800102 print(" %8s" % (stype + "/s"), end="")
103 idx = stat_types[stype]
Brendan Gregg48fbc3e2015-08-18 14:56:14 -0700104print("")
105
106# output
107i = 0
108while (1):
Alexei Starovoitovbdf07732016-01-14 10:09:20 -0800109 if count > 0:
110 i += 1
111 if i > count:
112 exit()
113 try:
114 sleep(interval)
115 except KeyboardInterrupt:
116 pass
117 exit()
Brendan Gregg48fbc3e2015-08-18 14:56:14 -0700118
Alexei Starovoitovbdf07732016-01-14 10:09:20 -0800119 print("%-8s: " % strftime("%H:%M:%S"), end="")
120 # print each statistic as a column
121 for stype in stat_types.keys():
122 idx = stat_types[stype]
123 try:
124 val = b["stats"][c_int(idx)].value / interval
125 print(" %8d" % val, end="")
126 except:
127 print(" %8d" % 0, end="")
128 b["stats"].clear()
129 print("")