Skip to content

Commit a9c1a67

Browse files
authored
Merge branch 'linuxkerneltravel:develop' into develop
2 parents de5213f + d500c06 commit a9c1a67

File tree

3 files changed

+140
-103
lines changed

3 files changed

+140
-103
lines changed

MagicEyes/src/backend/fs/fs_watcher/bpf/open.bpf.c

Lines changed: 72 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,104 @@
1-
#define BPF_NO_GLOBAL_DATA
21
#include <vmlinux.h>
32
#include <bpf/bpf_helpers.h>
43
#include <bpf/bpf_tracing.h>
54
#include <bpf/bpf_core_read.h>
65
#include "fs_watcher.h"
76

8-
#define TASK_COMM_LEN 100
9-
#define path_size 256
7+
char LICENSE[] SEC("license") = "GPL";
8+
9+
#define O_CREAT 0x0200 // 手动定义 O_CREAT 标志的常量值
10+
#define O_WRONLY 01 /* open for writing only */
1011

1112
struct {
1213
__uint(type, BPF_MAP_TYPE_HASH);
1314
__uint(max_entries, 1024);
1415
__type(key, pid_t);
15-
__type(value, char[TASK_COMM_LEN]);
16+
__type(value, struct event_open);
1617
} data SEC(".maps");
1718

1819
struct {
1920
__uint(type, BPF_MAP_TYPE_RINGBUF);
2021
__uint(max_entries, 256 * 1024);
2122
} rb SEC(".maps"); // 环形缓冲区
2223

23-
2424
SEC("tracepoint/syscalls/sys_enter_openat")
2525
int do_syscall_trace(struct trace_event_raw_sys_enter *ctx)
2626
{
27-
struct event_open *e;
28-
char comm[TASK_COMM_LEN];
29-
bpf_get_current_comm(&comm,sizeof(comm));
30-
e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0);
31-
if (!e)
32-
return 0;
27+
struct event_open e = {};
28+
pid_t pid = bpf_get_current_pid_tgid() >> 32;
29+
e.pid = pid;
30+
e.dfd = ctx->args[0];// 目录文件描述符
31+
bpf_probe_read_user_str(e.filename, sizeof(e.filename), (const char *)ctx->args[1]); // 文件路径
32+
e.flags = ctx->args[2]; // 打开标志
33+
34+
// 如果包含 O_CREAT 标志,则标记为文件创建
35+
if (e.flags & O_CREAT || (e.flags & O_WRONLY) ) {
36+
e.is_created = true;
37+
} else {
38+
e.is_created = false;
39+
}
40+
41+
bpf_map_update_elem(&data,&pid,&e,BPF_ANY);
42+
return 0;
43+
}
3344

34-
char filename[path_size];
35-
struct task_struct *task = (struct task_struct *)bpf_get_current_task(),
36-
*real_parent;
37-
if (task == NULL) {
38-
bpf_printk("task\n");
39-
bpf_ringbuf_discard(e, 0);
45+
// 跟踪文件描述符分配过程
46+
SEC("kprobe/get_unused_fd_flags")
47+
int kprobe_get_unused_fd_flags(struct pt_regs *ctx){
48+
pid_t pid = bpf_get_current_pid_tgid() >> 32;
49+
struct event_open *e = bpf_map_lookup_elem(&data,&pid);
50+
if(!e){
51+
bpf_printk("get_unused_fd_flags is failed to found fd\n");
4052
return 0;
4153
}
42-
int pid = bpf_get_current_pid_tgid() >> 32, tgid;
43-
44-
bpf_map_update_elem(&data, &pid, &comm, BPF_ANY);
45-
46-
int ppid = BPF_CORE_READ(task, real_parent, tgid);
4754

48-
bpf_probe_read_str(e->path_name_, sizeof(e->path_name_),
49-
(void *)(ctx->args[1]));
55+
//获取分配的文件描述符
56+
e->fd = PT_REGS_RC(ctx);
5057

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

53-
struct fdtable *fdt = BPF_CORE_READ(task, files, fdt);
54-
if (fdt == NULL) {
55-
bpf_printk("fdt\n");
56-
bpf_ringbuf_discard(e, 0);
62+
// 跟踪 openat 系统调用的退出
63+
SEC("tracepoint/syscalls/sys_exit_openat")
64+
int do_syscall_exit(struct trace_event_raw_sys_exit *ctx)
65+
{
66+
pid_t pid = bpf_get_current_pid_tgid() >> 32;
67+
struct event_open *e = bpf_map_lookup_elem(&data,&pid);
68+
if(!e){
69+
bpf_printk("sys_exit_openat is failed to found fd\n");
5770
return 0;
5871
}
5972

60-
unsigned int i = 0, count = 0, n = BPF_CORE_READ(fdt, max_fds);
61-
bpf_printk("n:%d\n", n);
62-
63-
e->n_ = n;
64-
e->pid_ = pid;
65-
66-
bpf_ringbuf_submit(e, 0);
67-
73+
e->ret = ctx->ret;
74+
75+
// 分配 ringbuf 空间
76+
struct event_open *new_e = bpf_ringbuf_reserve(&rb, sizeof(*new_e), 0);
77+
if (!new_e) {
78+
return 0; // 如果分配失败,提前返回
79+
}
80+
81+
//复制数据
82+
new_e->dfd = e->dfd;
83+
new_e->flags = e->flags;
84+
new_e->fd = e->fd;
85+
new_e->ret =e->ret;
86+
new_e->is_created = e->is_created;
87+
new_e->pid = e->pid;
88+
89+
// 手动读取文件路径,确保不超过最大长度,并添加 '\0' 结束符
90+
int filename_len = 0;
91+
while (filename_len < sizeof(new_e->filename) - 1) {
92+
char c = 0;
93+
// 读取路径中的每个字符
94+
bpf_probe_read(&c, sizeof(c), e->filename + filename_len);
95+
if (c == '\0') break; // 如果遇到 null 字符就停止读取
96+
new_e->filename[filename_len++] = c;
97+
}
98+
// 确保字符串以 '\0' 结束
99+
new_e->filename[filename_len] = '\0';
100+
bpf_printk("Opening file: %s, pid: %d, flags: %d\n", new_e->filename, pid, e->flags);
101+
102+
bpf_ringbuf_submit(new_e, 0);
68103
return 0;
69104
}
70-
71-
char LICENSE[] SEC("license") = "GPL";

MagicEyes/src/backend/fs/fs_watcher/include/fs_watcher.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@
66
#define TASK_COMM_LEN 16
77

88
struct event_open {
9-
int pid_;
10-
char path_name_[path_size];
11-
int n_;
12-
char comm[TASK_COMM_LEN];
9+
pid_t pid;
10+
int dfd;
11+
char filename[path_size];
12+
int flags;
13+
int fd; // 文件描述符
14+
int ret; // 系统调用返回值
15+
bool is_created; // 标记文件是否创建
1316
};
1417

1518
/*read*/

MagicEyes/src/backend/fs/fs_watcher/src/fs_watcher.c

Lines changed: 61 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <time.h>
66
#include <stdint.h>
77
#include <stdlib.h>
8+
#include <errno.h>
89
#include <string.h>
910
#include <sys/resource.h>
1011
#include <bpf/libbpf.h>
@@ -14,6 +15,7 @@
1415
#include <inttypes.h>
1516
#include <linux/fs.h>
1617
#include <errno.h>
18+
#include <fcntl.h> // 包含文件打开标志宏
1719
#include <argp.h>
1820
#include "fs/fs_watcher/open.skel.h"
1921
#include "fs/fs_watcher/read.skel.h"
@@ -105,15 +107,13 @@ static struct env{
105107
bool disk_io_visit;
106108
bool block_rq_issue;
107109
bool CacheTrack;
108-
pid_t pid;
109110
}env = {
110111
.open = false,
111112
.read = false,
112113
.write = false,
113114
.disk_io_visit = false,
114115
.block_rq_issue = false,
115116
.CacheTrack = false,
116-
.pid = -1,
117117
};
118118

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

@@ -142,19 +141,7 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) {
142141
env.block_rq_issue = true;break;
143142
case 't':
144143
env.CacheTrack = true;break;
145-
case 'p':
146-
if (arg) {
147-
env.pid = atoi(arg);
148-
if (env.pid <= 0) {
149-
fprintf(stderr, "Invalid PID value: %s\n", arg);
150-
argp_usage(state);
151-
}
152-
} else {
153-
fprintf(stderr, "-p option requires an argument\n");
154-
argp_usage(state);
155-
}
156-
break;
157-
default:
144+
default:
158145
return ARGP_ERR_UNKNOWN;
159146
}
160147
return 0;
@@ -244,38 +231,65 @@ int main(int argc,char **argv){
244231
}
245232
}
246233

234+
const char* flags_to_str(int flags) {
235+
static char str[256];
236+
str[0] = '\0'; // 清空字符串
237+
238+
if (flags & O_RDONLY) strcat(str, "O_RDONLY ");
239+
if (flags & O_WRONLY) strcat(str, "O_WRONLY ");
240+
if (flags & O_RDWR) strcat(str, "O_RDWR ");
241+
if (flags & O_CREAT) strcat(str, "O_CREAT ");
242+
if (flags & O_EXCL) strcat(str, "O_EXCL ");
243+
if (flags & O_TRUNC) strcat(str, "O_TRUNC ");
244+
if (flags & O_APPEND) strcat(str, "O_APPEND ");
245+
if (flags & O_NOFOLLOW) strcat(str, "O_NOFOLLOW ");
246+
if (flags & O_CLOEXEC) strcat(str, "O_CLOEXEC ");
247+
if (flags & O_NONBLOCK) strcat(str, "O_NONBLOCK ");
248+
if (flags & O_SYNC) strcat(str, "O_SYNC ");
249+
if (flags & O_DSYNC) strcat(str, "O_DSYNC ");
250+
if (flags & O_RSYNC) strcat(str, "O_RSYNC ");
251+
if (flags & O_DIRECTORY) strcat(str, "O_DIRECTORY ");
252+
253+
// 条件编译部分:如果系统定义了 O_NOATIME 和 O_PATH
254+
#ifdef O_NOATIME
255+
if (flags & O_NOATIME) strcat(str, "O_NOATIME ");
256+
#endif
257+
258+
#ifdef O_PATH
259+
if (flags & O_PATH) strcat(str, "O_PATH ");
260+
#endif
261+
262+
// 如果没有匹配到标志,返回 "Unknown"
263+
if (str[0] == '\0') {
264+
return "Unknown";
265+
}
266+
267+
return str;
268+
}
269+
247270
static int handle_event_open(void *ctx, void *data, size_t data_sz)
248271
{
249-
struct event_open *e = (struct event_open *)data;
250-
char *filename = strrchr(e->path_name_, '/');
251-
++filename;
252-
253-
char fd_path[path_size];
254-
char actual_path[path_size];
255-
char comm[TASK_COMM_LEN];
256-
int i = 0;
257-
int map_fd = *(int *)ctx;//传递map得文件描述符
258-
259-
260-
for (; i < e->n_; ++i) {
261-
snprintf(fd_path, sizeof(fd_path), "/proc/%d/fd/%d", e->pid_,
262-
i);
263-
ssize_t len =
264-
readlink(fd_path, actual_path, sizeof(actual_path) - 1);
265-
if (len != -1) {
266-
actual_path[len] = '\0';
267-
int result = strcmp(e->path_name_, actual_path);
268-
if (result == 0) {
269-
if(bpf_map_lookup_elem(map_fd,&e->pid_,&comm)==0){
270-
printf("%-60s %-8d %-8d %-8s\n",
271-
e->path_name_, i,e->pid_,comm);
272-
}else{
273-
fprintf(stderr, "Failed to lookup value for key %d\n", e->pid_);
274-
}
275-
276-
}
277-
}
278-
}
272+
const struct event_open *e = data;
273+
struct tm *tm;
274+
char ts[32];
275+
time_t t;
276+
277+
time(&t);
278+
tm = localtime(&t);
279+
strftime(ts, sizeof(ts), "%H:%M:%S", tm);
280+
const char *ret_str;
281+
// 如果返回值是负数,则是错误码,使用 strerror
282+
if (e->ret < 0) {
283+
ret_str = strerror(-e->ret); // 负数表示错误码
284+
} else {
285+
// 正数表示文件描述符,直接打印文件描述符
286+
ret_str = "Success"; // 如果是文件描述符,表示成功
287+
}
288+
289+
const char *flags_str = flags_to_str(e->flags);
290+
291+
printf("%-8s %-8d %-8d %-100s %-8s %-8d %-8s %-8s\n",
292+
ts, e->dfd, e->pid,e->filename, flags_str, e->fd, ret_str, e->is_created ? "true" : "false");
279293
return 0;
280294
}
281295

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

353367
LOAD_AND_ATTACH_SKELETON_MAP(skel_open,open);
354368

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

358372
open_cleanup:
@@ -381,22 +395,9 @@ static int process_read(struct read_bpf *skel_read){
381395
static int process_write(struct write_bpf *skel_write){
382396
int err;
383397
struct ring_buffer *rb;
384-
int arg_index = 0;
385-
386-
struct dist_args d_args = {-1};
387-
388398

389399
LOAD_AND_ATTACH_SKELETON(skel_write,write);
390400

391-
d_args.pid = env.pid;
392-
struct bpf_map *arg_map = bpf_object__find_map_by_name((const struct bpf_object *)*(skel_write->skeleton->obj), "args_map");
393-
err = bpf_map__update_elem(arg_map, &arg_index, sizeof(arg_index), &d_args, sizeof(d_args), BPF_ANY);
394-
395-
if (err < 0) {
396-
fprintf(stderr, "ERROR: failed to update args map\n");
397-
goto write_cleanup;
398-
}
399-
400401
printf("%-8s %-8s %-8s %-8s %-8s\n","ds","inode_number","pid","real_count","count");
401402
POLL_RING_BUFFER(rb, 1000, err);
402403

0 commit comments

Comments
 (0)