Skip to content

Commit b912d0b

Browse files
chenhengqiyonghong-song
authored andcommitted
libbpf-tools: add filetop
Signed-off-by: Hengqi Chen <[email protected]>
1 parent 2464501 commit b912d0b

File tree

6 files changed

+465
-0
lines changed

6 files changed

+465
-0
lines changed

libbpf-tools/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
/ext4dist
1616
/ext4slower
1717
/filelife
18+
/filetop
1819
/fsdist
1920
/fsslower
2021
/funclatency

libbpf-tools/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ APPS = \
2828
drsnoop \
2929
execsnoop \
3030
filelife \
31+
filetop \
3132
fsdist \
3233
fsslower \
3334
funclatency \

libbpf-tools/filetop.bpf.c

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
2+
/* Copyright (c) 2021 Hengqi Chen */
3+
#include <vmlinux.h>
4+
#include <bpf/bpf_helpers.h>
5+
#include <bpf/bpf_core_read.h>
6+
#include <bpf/bpf_tracing.h>
7+
#include "filetop.h"
8+
#include "stat.h"
9+
10+
#define MAX_ENTRIES 10240
11+
12+
const volatile pid_t target_pid = 0;
13+
const volatile bool regular_file_only = true;
14+
static struct file_stat zero_value = {};
15+
16+
struct {
17+
__uint(type, BPF_MAP_TYPE_HASH);
18+
__uint(max_entries, MAX_ENTRIES);
19+
__type(key, struct file_id);
20+
__type(value, struct file_stat);
21+
} entries SEC(".maps");
22+
23+
static void get_file_path(struct file *file, char *buf, size_t size)
24+
{
25+
struct qstr dname;
26+
27+
dname = BPF_CORE_READ(file, f_path.dentry, d_name);
28+
bpf_probe_read_kernel(buf, size, dname.name);
29+
}
30+
31+
static int probe_entry(struct pt_regs *ctx, struct file *file, size_t count, enum op op)
32+
{
33+
__u64 pid_tgid = bpf_get_current_pid_tgid();
34+
__u32 pid = pid_tgid >> 32;
35+
__u32 tid = (__u32)pid_tgid;
36+
int mode;
37+
struct file_id key = {};
38+
struct file_stat *valuep;
39+
40+
if (target_pid && target_pid != pid)
41+
return 0;
42+
43+
mode = BPF_CORE_READ(file, f_inode, i_mode);
44+
if (regular_file_only && !S_ISREG(mode))
45+
return 0;
46+
47+
key.dev = BPF_CORE_READ(file, f_inode, i_rdev);
48+
key.inode = BPF_CORE_READ(file, f_inode, i_ino);
49+
key.pid = pid;
50+
key.tid = tid;
51+
valuep = bpf_map_lookup_elem(&entries, &key);
52+
if (!valuep) {
53+
bpf_map_update_elem(&entries, &key, &zero_value, BPF_ANY);
54+
valuep = bpf_map_lookup_elem(&entries, &key);
55+
if (!valuep)
56+
return 0;
57+
valuep->pid = pid;
58+
valuep->tid = tid;
59+
bpf_get_current_comm(&valuep->comm, sizeof(valuep->comm));
60+
get_file_path(file, valuep->filename, sizeof(valuep->filename));
61+
if (S_ISREG(mode)) {
62+
valuep->type = 'R';
63+
} else if (S_ISSOCK(mode)) {
64+
valuep->type = 'S';
65+
} else {
66+
valuep->type = 'O';
67+
}
68+
}
69+
if (op == READ) {
70+
valuep->reads++;
71+
valuep->read_bytes += count;
72+
} else { /* op == WRITE */
73+
valuep->writes++;
74+
valuep->write_bytes += count;
75+
}
76+
return 0;
77+
};
78+
79+
SEC("kprobe/vfs_read")
80+
int BPF_KPROBE(vfs_read_entry, struct file *file, char *buf, size_t count, loff_t *pos)
81+
{
82+
return probe_entry(ctx, file, count, READ);
83+
}
84+
85+
SEC("kprobe/vfs_write")
86+
int BPF_KPROBE(vfs_write_entry, struct file *file, const char *buf, size_t count, loff_t *pos)
87+
{
88+
return probe_entry(ctx, file, count, WRITE);
89+
}
90+
91+
char LICENSE[] SEC("license") = "Dual BSD/GPL";

0 commit comments

Comments
 (0)