github.com/inspektor-gadget/inspektor-gadget@v0.28.1/pkg/gadgets/top/file/tracer/bpf/filetop.bpf.c (about) 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 #include <gadget/mntns_filter.h> 10 11 #define MAX_ENTRIES 10240 12 13 const volatile pid_t target_pid = 0; 14 const volatile bool regular_file_only = true; 15 static struct file_stat zero_value = {}; 16 17 struct { 18 __uint(type, BPF_MAP_TYPE_HASH); 19 __uint(max_entries, MAX_ENTRIES); 20 __type(key, struct file_id); 21 __type(value, struct file_stat); 22 } entries SEC(".maps"); 23 24 static void get_file_path(struct file *file, __u8 *buf, size_t size) 25 { 26 struct qstr dname; 27 28 dname = BPF_CORE_READ(file, f_path.dentry, d_name); 29 bpf_probe_read_kernel(buf, size, dname.name); 30 } 31 32 static int probe_entry(struct pt_regs *ctx, struct file *file, size_t count, 33 enum op op) 34 { 35 __u64 pid_tgid = bpf_get_current_pid_tgid(); 36 __u32 pid = pid_tgid >> 32; 37 __u32 tid = (__u32)pid_tgid; 38 int mode; 39 struct file_id key = {}; 40 struct file_stat *valuep; 41 u64 mntns_id; 42 43 if (target_pid && target_pid != pid) 44 return 0; 45 46 mntns_id = gadget_get_mntns_id(); 47 48 if (gadget_should_discard_mntns_id(mntns_id)) 49 return 0; 50 51 mode = BPF_CORE_READ(file, f_inode, i_mode); 52 if (regular_file_only && !S_ISREG(mode)) 53 return 0; 54 55 key.dev = BPF_CORE_READ(file, f_inode, i_rdev); 56 key.inode = BPF_CORE_READ(file, f_inode, i_ino); 57 key.pid = pid; 58 key.tid = tid; 59 valuep = bpf_map_lookup_elem(&entries, &key); 60 if (!valuep) { 61 bpf_map_update_elem(&entries, &key, &zero_value, BPF_ANY); 62 valuep = bpf_map_lookup_elem(&entries, &key); 63 if (!valuep) 64 return 0; 65 valuep->pid = pid; 66 valuep->tid = tid; 67 valuep->mntns_id = mntns_id; 68 bpf_get_current_comm(&valuep->comm, sizeof(valuep->comm)); 69 get_file_path(file, valuep->filename, sizeof(valuep->filename)); 70 if (S_ISREG(mode)) { 71 valuep->type_ = 'R'; 72 } else if (S_ISSOCK(mode)) { 73 valuep->type_ = 'S'; 74 } else { 75 valuep->type_ = 'O'; 76 } 77 } 78 if (op == READ) { 79 valuep->reads++; 80 valuep->read_bytes += count; 81 } else { /* op == WRITE */ 82 valuep->writes++; 83 valuep->write_bytes += count; 84 } 85 return 0; 86 }; 87 88 SEC("kprobe/vfs_read") 89 int BPF_KPROBE(ig_topfile_rd_e, struct file *file, char *buf, size_t count, 90 loff_t *pos) 91 { 92 return probe_entry(ctx, file, count, READ); 93 } 94 95 SEC("kprobe/vfs_write") 96 int BPF_KPROBE(ig_topfile_wr_e, struct file *file, const char *buf, 97 size_t count, loff_t *pos) 98 { 99 return probe_entry(ctx, file, count, WRITE); 100 } 101 102 char LICENSE[] SEC("license") = "Dual BSD/GPL";