blob: bfcb1a0e3ffd2e1ae09d9b01e695985dc49847c6 [file] [log] [blame]
Brendan Greggebdb2422015-08-18 16:53:41 -07001#!/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
Brendan Greggb90bbab2016-02-15 15:55:08 -080040b = BPF(text="""
41#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
52BPF_TABLE("array", int, u64, stats, S_MAXSTAT + 1);
53
54void stats_increment(int key) {
55 u64 *leaf = stats.lookup(&key);
56 if (leaf) (*leaf)++;
57}
58
59void do_read(struct pt_regs *ctx) { stats_increment(S_READ); }
60void do_write(struct pt_regs *ctx) { stats_increment(S_WRITE); }
61void do_fsync(struct pt_regs *ctx) { stats_increment(S_FSYNC); }
62void do_open(struct pt_regs *ctx) { stats_increment(S_OPEN); }
63void do_create(struct pt_regs *ctx) { stats_increment(S_CREATE); }
64""")
Brenden Blanco5eef65e2015-08-19 15:39:19 -070065b.attach_kprobe(event="vfs_read", fn_name="do_read")
66b.attach_kprobe(event="vfs_write", fn_name="do_write")
67b.attach_kprobe(event="vfs_fsync", fn_name="do_fsync")
68b.attach_kprobe(event="vfs_open", fn_name="do_open")
69b.attach_kprobe(event="vfs_create", fn_name="do_create")
Brendan Gregg48fbc3e2015-08-18 14:56:14 -070070
71# stat column labels and indexes
72stat_types = {
Alexei Starovoitovbdf07732016-01-14 10:09:20 -080073 "READ": 1,
74 "WRITE": 2,
75 "FSYNC": 3,
76 "OPEN": 4,
77 "CREATE": 5
Brendan Gregg48fbc3e2015-08-18 14:56:14 -070078}
79
80# header
81print("%-8s " % "TIME", end="")
Brendan Gregg48fbc3e2015-08-18 14:56:14 -070082for stype in stat_types.keys():
Alexei Starovoitovbdf07732016-01-14 10:09:20 -080083 print(" %8s" % (stype + "/s"), end="")
84 idx = stat_types[stype]
Brendan Gregg48fbc3e2015-08-18 14:56:14 -070085print("")
86
87# output
88i = 0
89while (1):
Alexei Starovoitovbdf07732016-01-14 10:09:20 -080090 if count > 0:
91 i += 1
92 if i > count:
93 exit()
94 try:
95 sleep(interval)
96 except KeyboardInterrupt:
97 pass
98 exit()
Brendan Gregg48fbc3e2015-08-18 14:56:14 -070099
Alexei Starovoitovbdf07732016-01-14 10:09:20 -0800100 print("%-8s: " % strftime("%H:%M:%S"), end="")
101 # print each statistic as a column
102 for stype in stat_types.keys():
103 idx = stat_types[stype]
104 try:
105 val = b["stats"][c_int(idx)].value / interval
106 print(" %8d" % val, end="")
107 except:
108 print(" %8d" % 0, end="")
109 b["stats"].clear()
110 print("")