1#!/usr/bin/env python
2# @lint-avoid-python-3-compatibility-imports
3#
4# vfsstat   Count some VFS calls.
5#           For Linux, uses BCC, eBPF. See .c file.
6#
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#
14# 14-Aug-2015   Brendan Gregg   Created this.
15
16from __future__ import print_function
17from bcc import BPF
18from ctypes import c_int
19from time import sleep, strftime
20from sys import argv
21
22def usage():
23    print("USAGE: %s [interval [count]]" % argv[0])
24    exit()
25
26# arguments
27interval = 1
28count = -1
29if len(argv) > 1:
30    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()
38
39# load BPF program
40b = 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_ARRAY(stats, u64, S_MAXSTAT);
53
54static void 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""")
65b.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")
70
71# stat column labels and indexes
72stat_types = {
73    "READ": 1,
74    "WRITE": 2,
75    "FSYNC": 3,
76    "OPEN": 4,
77    "CREATE": 5
78}
79
80# header
81print("%-8s  " % "TIME", end="")
82for stype in stat_types.keys():
83    print(" %8s" % (stype + "/s"), end="")
84    idx = stat_types[stype]
85print("")
86
87# output
88i = 0
89while (1):
90    if count > 0:
91        i += 1
92        if i > count:
93            exit()
94    try:
95        sleep(interval)
96    except KeyboardInterrupt:
97        pass
98        exit()
99
100    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("")
111