Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fs_watcher: add fs_watcher to MagicEyes #929

Merged
merged 1 commit into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 120 additions & 0 deletions MagicEyes/src/backend/fs/fs_watcher/bpf/CacheTrack.bpf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>
#include "fs_watcher.h"

char LICENSE[] SEC("license") = "Dual BSD/GPL";

// struct {
// __uint(type, BPF_MAP_TYPE_HASH);
// __uint(max_entries, 1024);
// __type(key, char[30] );
// __type(value,struct event_CacheTrack);
// } data SEC(".maps");

// struct {
// __uint(type, BPF_MAP_TYPE_HASH);
// __uint(max_entries, 1024);
// __type(key, u64 );
// __type(value,struct event_CacheTrack);
// } unique_map SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 256 * 1024);
} rb SEC(".maps");


SEC("tracepoint/writeback/writeback_dirty_inode_start")
int trace_writeback_start(struct trace_event_raw_writeback_dirty_inode_template *ctx){
pid_t pid = bpf_get_current_pid_tgid() >> 32;
u64 timestamp = bpf_ktime_get_ns();
struct event_CacheTrack event_info ={};
char name[32];

event_info.ino = ctx->ino;

event_info.state = ctx->state;

event_info.flags = ctx->flags;

event_info.time = timestamp;

// bpf_probe_read(name, sizeof(name), ctx->name); // 从 ctx 复制设备名称

// 检查 name 是否为空字符串
// if (name[0] == '\0') {
// return 0;
// }
// if(name == NULL)
// return 0;

// __builtin_memcpy(event_info.name, name, sizeof(name));
// bpf_printk("comm_123:%s\n",event_info.name);

struct event_CacheTrack *ring_event = bpf_ringbuf_reserve(&rb, sizeof(struct event_CacheTrack), 0);
if (!ring_event)
return 0;

__builtin_memcpy(ring_event, &event_info, sizeof(event_info));

bpf_printk("event_info_ino:%d\n",event_info.ino);

bpf_ringbuf_submit(ring_event, 0);


// bpf_map_update_elem(&data,name,&event_info,BPF_ANY);
// bpf_map_update_elem(&unique_map,&event_info.queue_id,&event_info,BPF_ANY);
return 0;
}

// SEC("tracepoint/writeback/writeback_written")
// int trace_writeback_end(struct trace_event_raw_writeback_work_class *ctx) {
// bpf_printk("2222222\n");
// u64 timestamp = bpf_ktime_get_ns();
// char name[30];
// bpf_probe_read_str(name, sizeof(name), ctx->name); // 从 ctx 复制设备名称

// if(name == NULL)
// return 0;

// bpf_printk("comm:%s\n",name);

// struct event_CacheTrack *e = bpf_map_lookup_elem(&data,name);
// if(!e){
// bpf_printk("e failed\n");
// return 0;
// }


// struct event_CacheTrack *q = bpf_map_lookup_elem(&unique_map,&e->queue_id);
// if(!q){
// bpf_printk("q failed\n");
// return 0;
// }

// struct event_CacheTrack *q_event = bpf_ringbuf_reserve(&rb, sizeof(struct event_CacheTrack), 0);
// if (!q_event){
// bpf_printk("Ring buffer is full!\n");
// return 0;
// }

// q_event->nr_pages = ctx->nr_pages;
// q_event->sb_dev = ctx->sb_dev;
// q_event->sync_mode = ctx->sync_mode;
// q_event->for_kupdate = ctx->for_kupdate;
// q_event->range_cyclic = ctx->range_cyclic;
// q_event->for_background = ctx->for_background;
// q_event->reason = ctx->reason;
// q_event->cgroup_ino = ctx->cgroup_ino;
// q_event->time = timestamp - q->start_timestamp;

// bpf_printk("time:%llu\n",q_event->time);
// bpf_printk("123\n");

// bpf_ringbuf_submit(q_event, 0);

// return 0;

// }
69 changes: 69 additions & 0 deletions MagicEyes/src/backend/fs/fs_watcher/bpf/block_rq_issue.bpf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>
#include "fs_watcher.h"

char LICENSE[] SEC("license") = "Dual BSD/GPL";

struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 256 * 1024);
} rb SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 1024);
__type(key, u32); // 使用进程 PID 作为键
__type(value, u64); // I/O 总大小作为值
} io_size_map SEC(".maps");

SEC("tracepoint/block/block_rq_issue")
int tracepoint_block_rq_issue(struct trace_event_raw_block_rq_completion *ctx) {
struct event_block_rq_issue *e;
u32 pid = bpf_get_current_pid_tgid() >> 32; // 获取进程 ID
u64 *size, total_size;

// 分配 ringbuf 空间
e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0);
if (!e) {
return 0; // 如果分配失败,提前返回
}

// 获取当前进程名
bpf_get_current_comm(e->comm, sizeof(e->comm));

// 填充事件数据
e->timestamp = bpf_ktime_get_ns();
e->dev = ctx->dev;
e->sector = ctx->sector;
e->nr_sectors = ctx->nr_sector;

// 日志输出调试信息
bpf_printk("PID: %u, Sector: %d, nr_sectors: %d\n", pid, ctx->sector, ctx->nr_sector);

// 查找或初始化该进程的 I/O 总大小
size = bpf_map_lookup_elem(&io_size_map, &pid);
if (size) {
total_size = *size;
} else {
total_size = 0;
}

// 计算本次 I/O 请求的大小
const u64 sector_size = 512; // 标准扇区大小
total_size += ctx->nr_sector * sector_size;

// 更新 I/O 总大小
bpf_map_update_elem(&io_size_map, &pid, &total_size, BPF_ANY);

e->total_io = total_size;

// 日志输出当前总 I/O 大小
bpf_printk("Updated Total I/O for PID %u: %llu\n", pid, total_size);

// 提交事件
bpf_ringbuf_submit(e, 0);

return 0;
}
71 changes: 71 additions & 0 deletions MagicEyes/src/backend/fs/fs_watcher/bpf/disk_io_visit.bpf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>
#include "fs_watcher.h"

char LICENSE[] SEC("license") = "Dual BSD/GPL";

// 定义 ringbuf,用于传输事件信息
struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 256 * 1024);
} rb SEC(".maps");

// 进程名与 I/O 计数映射
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 1024);
__type(key, char[TASK_COMM_LEN]);
__type(value, u32);
} io_count_map SEC(".maps");

// 这里挂载点得是这个struct trace_event_raw_block_rq_completion *ctx
SEC("tracepoint/block/block_rq_complete")
int tracepoint_block_visit(struct trace_event_raw_block_rq_completion *ctx) {
struct event_disk_io_visit *e;
u32 *count, new_count;
char comm[TASK_COMM_LEN];

// 获取当前进程名
bpf_get_current_comm(comm, sizeof(comm));

// 查找或初始化该进程的I/O计数
count = bpf_map_lookup_elem(&io_count_map, comm);
if (count) {
new_count = *count + 1;
} else {
new_count = 1;
}
bpf_map_update_elem(&io_count_map, comm, &new_count, BPF_ANY);

// 分配 ringbuf 空间
e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0);
if (!e) {
return 0; // 如果分配失败,提前返回
}

// 填充事件数据
e->timestamp = bpf_ktime_get_ns();
e->blk_dev = ctx->dev; // 直接读取块设备号
e->sectors = ctx->nr_sector; // 读取操作的扇区数

// 判断读写标识符 (检查 rwbs 数组的内容)
if (ctx->rwbs[0] == 'R') {
e->rwbs = 1; // 1 表示读操作
} else {
e->rwbs = 0; // 0 表示写操作
}

// 更新 I/O 操作计数
e->count = new_count;

// 复制进程名
__builtin_memcpy(e->comm, comm, sizeof(comm));
bpf_printk("comm : %s\n",e->comm);

// 提交事件
bpf_ringbuf_submit(e, 0);

return 0;
}
102 changes: 55 additions & 47 deletions MagicEyes/src/backend/fs/fs_watcher/bpf/open.bpf.c
Original file line number Diff line number Diff line change
@@ -1,63 +1,71 @@
#include "vmlinux.h"
#include <bpf/bpf_helpers.h> //包含了BPF 辅助函数
#define BPF_NO_GLOBAL_DATA
#include <vmlinux.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include "open.h"
#include <bpf/bpf_core_read.h>
#include "fs_watcher.h"

char LICENSE[] SEC("license") = "Dual BSD/GPL";
#define TASK_COMM_LEN 100
#define path_size 256

// 定义哈希映射
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 1024);
__type(key, pid_t);
__type(value, u64);
} fdtmp SEC(".maps");
__type(value, char[TASK_COMM_LEN]);
} data SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 256 * 1024);
} rb SEC(".maps");

SEC("kprobe/do_sys_openat2")
int BPF_KPROBE(do_sys_openat2)
{
struct fs_t fs;
pid_t pid;

//pid
pid = bpf_get_current_pid_tgid() >> 32;
fs.pid = pid;

//uid
fs.uid = bpf_get_current_uid_gid();

//fd,file descriptor
int fd = PT_REGS_RC(ctx);
if (fd >= 0)
fs.fd = fd;
else
fs.fd= -1;

//time
unsigned long long ts = bpf_ktime_get_ns();
fs.ts = ts;
bpf_map_update_elem(&fdtmp, &pid, &ts, BPF_ANY);

//从环形缓冲区(ring buffer)中分配一块内存来存储一个名为 struct fs_t 类型的数据,并将该内存块的指针赋值给指针变量 e
struct fs_t *e;
} rb SEC(".maps"); // 环形缓冲区


SEC("tracepoint/syscalls/sys_enter_openat")
int do_syscall_trace(struct trace_event_raw_sys_enter *ctx)
{
struct event_open *e;
char comm[TASK_COMM_LEN];
bpf_get_current_comm(&comm,sizeof(comm));
e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0);
if (!e) return 0;

//给变量e赋值
e->pid = fs.pid;
e->uid = fs.uid;
e->fd = fs.fd;
e->ts = fs.ts;
bpf_get_current_comm(e->comm, sizeof(e->comm));

// 成功地将其提交到用户空间进行后期处理
if (!e)
return 0;

char filename[path_size];
struct task_struct *task = (struct task_struct *)bpf_get_current_task(),
*real_parent;
if (task == NULL) {
bpf_printk("task\n");
bpf_ringbuf_discard(e, 0);
return 0;
}
int pid = bpf_get_current_pid_tgid() >> 32, tgid;

bpf_map_update_elem(&data, &pid, &comm, BPF_ANY);

int ppid = BPF_CORE_READ(task, real_parent, tgid);

bpf_probe_read_str(e->path_name_, sizeof(e->path_name_),
(void *)(ctx->args[1]));

bpf_printk("path name: %s,pid:%d,ppid:%d\n", e->path_name_, pid, ppid);

struct fdtable *fdt = BPF_CORE_READ(task, files, fdt);
if (fdt == NULL) {
bpf_printk("fdt\n");
bpf_ringbuf_discard(e, 0);
return 0;
}

unsigned int i = 0, count = 0, n = BPF_CORE_READ(fdt, max_fds);
bpf_printk("n:%d\n", n);

e->n_ = n;
e->pid_ = pid;

bpf_ringbuf_submit(e, 0);

return 0;
return 0;
}

char LICENSE[] SEC("license") = "GPL";
Loading
Loading