Skip to content

Commit

Permalink
Merge branch 'linuxkerneltravel:develop' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
Monkey857 authored Jan 10, 2025
2 parents de5213f + d500c06 commit a9c1a67
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 103 deletions.
111 changes: 72 additions & 39 deletions MagicEyes/src/backend/fs/fs_watcher/bpf/open.bpf.c
Original file line number Diff line number Diff line change
@@ -1,71 +1,104 @@
#define BPF_NO_GLOBAL_DATA
#include <vmlinux.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>
#include "fs_watcher.h"

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

#define O_CREAT 0x0200 // 手动定义 O_CREAT 标志的常量值
#define O_WRONLY 01 /* open for writing only */

struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 1024);
__type(key, pid_t);
__type(value, char[TASK_COMM_LEN]);
__type(value, struct event_open);
} data SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 256 * 1024);
} 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;
struct event_open e = {};
pid_t pid = bpf_get_current_pid_tgid() >> 32;
e.pid = pid;
e.dfd = ctx->args[0];// 目录文件描述符
bpf_probe_read_user_str(e.filename, sizeof(e.filename), (const char *)ctx->args[1]); // 文件路径
e.flags = ctx->args[2]; // 打开标志

// 如果包含 O_CREAT 标志,则标记为文件创建
if (e.flags & O_CREAT || (e.flags & O_WRONLY) ) {
e.is_created = true;
} else {
e.is_created = false;
}

bpf_map_update_elem(&data,&pid,&e,BPF_ANY);
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);
// 跟踪文件描述符分配过程
SEC("kprobe/get_unused_fd_flags")
int kprobe_get_unused_fd_flags(struct pt_regs *ctx){
pid_t pid = bpf_get_current_pid_tgid() >> 32;
struct event_open *e = bpf_map_lookup_elem(&data,&pid);
if(!e){
bpf_printk("get_unused_fd_flags is failed to found fd\n");
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]));
//获取分配的文件描述符
e->fd = PT_REGS_RC(ctx);

bpf_printk("path name: %s,pid:%d,ppid:%d\n", e->path_name_, pid, ppid);
bpf_map_update_elem(&data,&pid,e,BPF_ANY);
return 0;
}

struct fdtable *fdt = BPF_CORE_READ(task, files, fdt);
if (fdt == NULL) {
bpf_printk("fdt\n");
bpf_ringbuf_discard(e, 0);
// 跟踪 openat 系统调用的退出
SEC("tracepoint/syscalls/sys_exit_openat")
int do_syscall_exit(struct trace_event_raw_sys_exit *ctx)
{
pid_t pid = bpf_get_current_pid_tgid() >> 32;
struct event_open *e = bpf_map_lookup_elem(&data,&pid);
if(!e){
bpf_printk("sys_exit_openat is failed to found fd\n");
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);

e->ret = ctx->ret;

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

//复制数据
new_e->dfd = e->dfd;
new_e->flags = e->flags;
new_e->fd = e->fd;
new_e->ret =e->ret;
new_e->is_created = e->is_created;
new_e->pid = e->pid;

// 手动读取文件路径,确保不超过最大长度,并添加 '\0' 结束符
int filename_len = 0;
while (filename_len < sizeof(new_e->filename) - 1) {
char c = 0;
// 读取路径中的每个字符
bpf_probe_read(&c, sizeof(c), e->filename + filename_len);
if (c == '\0') break; // 如果遇到 null 字符就停止读取
new_e->filename[filename_len++] = c;
}
// 确保字符串以 '\0' 结束
new_e->filename[filename_len] = '\0';
bpf_printk("Opening file: %s, pid: %d, flags: %d\n", new_e->filename, pid, e->flags);

bpf_ringbuf_submit(new_e, 0);
return 0;
}

char LICENSE[] SEC("license") = "GPL";
11 changes: 7 additions & 4 deletions MagicEyes/src/backend/fs/fs_watcher/include/fs_watcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@
#define TASK_COMM_LEN 16

struct event_open {
int pid_;
char path_name_[path_size];
int n_;
char comm[TASK_COMM_LEN];
pid_t pid;
int dfd;
char filename[path_size];
int flags;
int fd; // 文件描述符
int ret; // 系统调用返回值
bool is_created; // 标记文件是否创建
};

/*read*/
Expand Down
121 changes: 61 additions & 60 deletions MagicEyes/src/backend/fs/fs_watcher/src/fs_watcher.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <time.h>
#include <stdint.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/resource.h>
#include <bpf/libbpf.h>
Expand All @@ -14,6 +15,7 @@
#include <inttypes.h>
#include <linux/fs.h>
#include <errno.h>
#include <fcntl.h> // 包含文件打开标志宏
#include <argp.h>
#include "fs/fs_watcher/open.skel.h"
#include "fs/fs_watcher/read.skel.h"
Expand Down Expand Up @@ -105,15 +107,13 @@ static struct env{
bool disk_io_visit;
bool block_rq_issue;
bool CacheTrack;
pid_t pid;
}env = {
.open = false,
.read = false,
.write = false,
.disk_io_visit = false,
.block_rq_issue = false,
.CacheTrack = false,
.pid = -1,
};

static const struct argp_option opts[] = {
Expand All @@ -123,7 +123,6 @@ static const struct argp_option opts[] = {
{"disk_io_visit", 'd', 0, 0, "Print disk I/O visit report"},
{"block_rq_issue", 'b', 0, 0, "Print block I/O request submission events. Reports when block I/O requests are submitted to device drivers."},
{"CacheTrack", 't' , 0 ,0 , "WriteBack dirty lagency and other information"},
{"pid", 'p', "PID", 0, "Specify pid number when report weite. Only support for write report now"},
{0} // 结束标记,用于指示选项列表的结束
};

Expand All @@ -142,19 +141,7 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) {
env.block_rq_issue = true;break;
case 't':
env.CacheTrack = true;break;
case 'p':
if (arg) {
env.pid = atoi(arg);
if (env.pid <= 0) {
fprintf(stderr, "Invalid PID value: %s\n", arg);
argp_usage(state);
}
} else {
fprintf(stderr, "-p option requires an argument\n");
argp_usage(state);
}
break;
default:
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
Expand Down Expand Up @@ -244,38 +231,65 @@ int main(int argc,char **argv){
}
}

const char* flags_to_str(int flags) {
static char str[256];
str[0] = '\0'; // 清空字符串

if (flags & O_RDONLY) strcat(str, "O_RDONLY ");
if (flags & O_WRONLY) strcat(str, "O_WRONLY ");
if (flags & O_RDWR) strcat(str, "O_RDWR ");
if (flags & O_CREAT) strcat(str, "O_CREAT ");
if (flags & O_EXCL) strcat(str, "O_EXCL ");
if (flags & O_TRUNC) strcat(str, "O_TRUNC ");
if (flags & O_APPEND) strcat(str, "O_APPEND ");
if (flags & O_NOFOLLOW) strcat(str, "O_NOFOLLOW ");
if (flags & O_CLOEXEC) strcat(str, "O_CLOEXEC ");
if (flags & O_NONBLOCK) strcat(str, "O_NONBLOCK ");
if (flags & O_SYNC) strcat(str, "O_SYNC ");
if (flags & O_DSYNC) strcat(str, "O_DSYNC ");
if (flags & O_RSYNC) strcat(str, "O_RSYNC ");
if (flags & O_DIRECTORY) strcat(str, "O_DIRECTORY ");

// 条件编译部分:如果系统定义了 O_NOATIME 和 O_PATH
#ifdef O_NOATIME
if (flags & O_NOATIME) strcat(str, "O_NOATIME ");
#endif

#ifdef O_PATH
if (flags & O_PATH) strcat(str, "O_PATH ");
#endif

// 如果没有匹配到标志,返回 "Unknown"
if (str[0] == '\0') {
return "Unknown";
}

return str;
}

static int handle_event_open(void *ctx, void *data, size_t data_sz)
{
struct event_open *e = (struct event_open *)data;
char *filename = strrchr(e->path_name_, '/');
++filename;

char fd_path[path_size];
char actual_path[path_size];
char comm[TASK_COMM_LEN];
int i = 0;
int map_fd = *(int *)ctx;//传递map得文件描述符


for (; i < e->n_; ++i) {
snprintf(fd_path, sizeof(fd_path), "/proc/%d/fd/%d", e->pid_,
i);
ssize_t len =
readlink(fd_path, actual_path, sizeof(actual_path) - 1);
if (len != -1) {
actual_path[len] = '\0';
int result = strcmp(e->path_name_, actual_path);
if (result == 0) {
if(bpf_map_lookup_elem(map_fd,&e->pid_,&comm)==0){
printf("%-60s %-8d %-8d %-8s\n",
e->path_name_, i,e->pid_,comm);
}else{
fprintf(stderr, "Failed to lookup value for key %d\n", e->pid_);
}

}
}
}
const struct event_open *e = data;
struct tm *tm;
char ts[32];
time_t t;

time(&t);
tm = localtime(&t);
strftime(ts, sizeof(ts), "%H:%M:%S", tm);
const char *ret_str;
// 如果返回值是负数,则是错误码,使用 strerror
if (e->ret < 0) {
ret_str = strerror(-e->ret); // 负数表示错误码
} else {
// 正数表示文件描述符,直接打印文件描述符
ret_str = "Success"; // 如果是文件描述符,表示成功
}

const char *flags_str = flags_to_str(e->flags);

printf("%-8s %-8d %-8d %-100s %-8s %-8d %-8s %-8s\n",
ts, e->dfd, e->pid,e->filename, flags_str, e->fd, ret_str, e->is_created ? "true" : "false");
return 0;
}

Expand Down Expand Up @@ -352,7 +366,7 @@ static int process_open(struct open_bpf *skel_open){

LOAD_AND_ATTACH_SKELETON_MAP(skel_open,open);

printf("%-60s %-8s %-8s %-8s\n","filenamename","fd","pid","comm");
printf("%-8s %-8s %-8s %-100s %-8s %-8s %-8s %-8s\n", "TIME","dfd","PID", "filename", "flags", "fd", "ret", "is_created");
POLL_RING_BUFFER(rb, 1000, err);

open_cleanup:
Expand Down Expand Up @@ -381,22 +395,9 @@ static int process_read(struct read_bpf *skel_read){
static int process_write(struct write_bpf *skel_write){
int err;
struct ring_buffer *rb;
int arg_index = 0;

struct dist_args d_args = {-1};


LOAD_AND_ATTACH_SKELETON(skel_write,write);

d_args.pid = env.pid;
struct bpf_map *arg_map = bpf_object__find_map_by_name((const struct bpf_object *)*(skel_write->skeleton->obj), "args_map");
err = bpf_map__update_elem(arg_map, &arg_index, sizeof(arg_index), &d_args, sizeof(d_args), BPF_ANY);

if (err < 0) {
fprintf(stderr, "ERROR: failed to update args map\n");
goto write_cleanup;
}

printf("%-8s %-8s %-8s %-8s %-8s\n","ds","inode_number","pid","real_count","count");
POLL_RING_BUFFER(rb, 1000, err);

Expand Down

0 comments on commit a9c1a67

Please sign in to comment.