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