• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/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
40bpf_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    stats.atomic_increment(key);
56}
57"""
58
59bpf_text_kprobe = """
60void 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); }
65"""
66
67bpf_text_kfunc = """
68KFUNC_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; }
73"""
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:
84    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")
89
90# stat column labels and indexes
91stat_types = {
92    "READ": 1,
93    "WRITE": 2,
94    "FSYNC": 3,
95    "OPEN": 4,
96    "CREATE": 5
97}
98
99# header
100print("%-8s  " % "TIME", end="")
101for stype in stat_types.keys():
102    print(" %8s" % (stype + "/s"), end="")
103    idx = stat_types[stype]
104print("")
105
106# output
107i = 0
108while (1):
109    if count > 0:
110        i += 1
111        if i > count:
112            exit()
113    try:
114        sleep(interval)
115    except KeyboardInterrupt:
116        pass
117        exit()
118
119    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("")
130