From 5760a75d15de43abb1b5bfa86892106d310480f0 Mon Sep 17 00:00:00 2001 From: Jiping Yin Date: Wed, 31 Dec 2025 11:41:54 +0800 Subject: [PATCH 1/2] feat: eBPF Add a virtual file collection switch for IO events --- agent/src/config/config.rs | 2 + agent/src/config/handler.rs | 8 ++ agent/src/ebpf/kernel/files_rw.bpf.c | 43 ++++++- .../ebpf/kernel/include/socket_trace_common.h | 5 +- .../ebpf/kernel/include/task_struct_utils.h | 6 +- agent/src/ebpf/mod.rs | 1 + .../samples/rust/socket-tracer/src/main.rs | 1 + agent/src/ebpf/user/socket.c | 105 +++++++++++++++--- agent/src/ebpf/user/socket.h | 13 +++ agent/src/ebpf_dispatcher.rs | 9 ++ server/agent_config/README-CH.md | 30 +++++ server/agent_config/README.md | 32 ++++++ server/agent_config/template.yaml | 21 ++++ 13 files changed, 254 insertions(+), 22 deletions(-) diff --git a/agent/src/config/config.rs b/agent/src/config/config.rs index f4cd99e04df..f3e99b1182b 100644 --- a/agent/src/config/config.rs +++ b/agent/src/config/config.rs @@ -1033,6 +1033,7 @@ pub struct EbpfFileIoEvent { pub collect_mode: usize, #[serde(with = "humantime_serde")] pub minimal_duration: Duration, + pub enable_virtual_file_collect: bool, } impl Default for EbpfFileIoEvent { @@ -1040,6 +1041,7 @@ impl Default for EbpfFileIoEvent { Self { collect_mode: 1, minimal_duration: Duration::from_millis(1), + enable_virtual_file_collect: false, } } } diff --git a/agent/src/config/handler.rs b/agent/src/config/handler.rs index 4ea3e8f5a4a..19be291303d 100755 --- a/agent/src/config/handler.rs +++ b/agent/src/config/handler.rs @@ -3313,6 +3313,14 @@ impl ConfigHandler { io_event.minimal_duration = new_io_event.minimal_duration; restart_agent = !first_run; } + if io_event.enable_virtual_file_collect != new_io_event.enable_virtual_file_collect { + info!( + "Update inputs.ebpf.file.io_event.enable_virtual_file_collect from {:?} to {:?}.", + io_event.enable_virtual_file_collect, new_io_event.enable_virtual_file_collect + ); + io_event.enable_virtual_file_collect = new_io_event.enable_virtual_file_collect; + restart_agent = !first_run; + } if ebpf.java_symbol_file_refresh_defer_interval != new_ebpf.java_symbol_file_refresh_defer_interval { diff --git a/agent/src/ebpf/kernel/files_rw.bpf.c b/agent/src/ebpf/kernel/files_rw.bpf.c index 656dffa4770..e0080342b96 100644 --- a/agent/src/ebpf/kernel/files_rw.bpf.c +++ b/agent/src/ebpf/kernel/files_rw.bpf.c @@ -23,6 +23,7 @@ #define TIME_ROLLBACK_DEFAULT_LATENCY_NS 50000 static __inline bool is_regular_file(int fd, + bool disable_vfile_collect, struct member_fields_offset *off_ptr) { struct member_fields_offset *offset = off_ptr; @@ -31,6 +32,44 @@ static __inline bool is_regular_file(int fd, offset = members_offset__lookup(&k0); } void *file = fd_to_file(fd, offset); + if (file == NULL) + return false; + + /* + * Determine whether a file belongs to a regular VFS filesystem + * based on the existence of file->f_op->read_iter. + * + * file->f_op->read_iter != NULL: + * Regular VFS-backed files, including: + * - ext4 / xfs / btrfs + * - NFS / CIFS / CephFS + * - tmpfs / ramfs + * - overlayfs + * - fuse + * + * file->f_op->read_iter == NULL: + * Non-VFS or special kernel objects, including: + * - IPC objects (pipe / fifo) + * - socket-related objects + * - anon_inode derived objects + * - some procfs / sysfs entries + * - certain character devices or special driver files + * - kernel objects without regular VFS file semantics + */ + if (disable_vfile_collect) { + void *f_op, *read_iter; + bpf_probe_read_kernel(&f_op, sizeof(f_op), + file + offset->struct_file_f_op_offset); + if (f_op == NULL) + return false; + + bpf_probe_read_kernel(&read_iter, sizeof(read_iter), + f_op + + offset->struct_file_operations_read_iter_offset); + if (read_iter == NULL) + return false; + } + __u32 i_mode = file_to_i_mode(file, offset); return S_ISREG(i_mode); } @@ -295,7 +334,9 @@ static __inline int trace_io_event_common(void *ctx, int data_max_sz = tracer_ctx->data_limit_max; - if (!is_regular_file(data_args->fd, offset)) { + if (!is_regular_file(data_args->fd, + !tracer_ctx->virtual_file_collect_enabled, + offset)) { return -1; } diff --git a/agent/src/ebpf/kernel/include/socket_trace_common.h b/agent/src/ebpf/kernel/include/socket_trace_common.h index 7c9deeb9cd3..2e06955e3ae 100644 --- a/agent/src/ebpf/kernel/include/socket_trace_common.h +++ b/agent/src/ebpf/kernel/include/socket_trace_common.h @@ -200,6 +200,7 @@ struct tracer_ctx_s { __u32 go_tracing_timeout; /**< Go tracing timeout */ __u32 io_event_collect_mode; /**< IO event collection mode */ __u64 io_event_minimal_duration; /**< Minimum duration for IO events */ + bool virtual_file_collect_enabled; /**< Enable virtual file collection */ int push_buffer_refcnt; /**< Reference count of the data push buffer */ __u64 last_period_timestamp; /**< Record the timestamp of the last periodic check of the push buffer. */ __u64 period_timestamp; /**< Record the timestamp of the periodic check of the push buffer. */ @@ -372,7 +373,9 @@ struct member_fields_offset { __u16 struct_files_struct_fdt_offset; // offsetof(struct files_struct, fdt) __u16 struct_file_f_pos_offset; // offsetof(struct file, f_pos) - __u32 struct_files_private_data_offset; // offsetof(struct file, private_data) + __u32 struct_file_private_data_offset; // offsetof(struct file, private_data) + __u32 struct_file_f_op_offset; // offsetof(struct file, f_op) + __u32 struct_file_operations_read_iter_offset; // offsetof(struct file_operations, read_iter) __u32 struct_file_f_inode_offset; // offsetof(struct file, f_inode) __u32 struct_inode_i_mode_offset; // offsetof(struct inode, i_mode) __u32 struct_inode_i_sb_offset; // offsetof(struct inode, i_sb) diff --git a/agent/src/ebpf/kernel/include/task_struct_utils.h b/agent/src/ebpf/kernel/include/task_struct_utils.h index 395005a4943..4f901bedcb1 100644 --- a/agent/src/ebpf/kernel/include/task_struct_utils.h +++ b/agent/src/ebpf/kernel/include/task_struct_utils.h @@ -137,7 +137,7 @@ static __inline void *infer_and_get_socket_from_fd(int fd_num, struct member_fie sizeof(private_data), file + offset-> - struct_files_private_data_offset); + struct_file_private_data_offset); if (private_data != NULL) { socket = private_data; bpf_probe_read_kernel(&__socket, @@ -165,7 +165,7 @@ static __inline void *infer_and_get_socket_from_fd(int fd_num, struct member_fie } bpf_probe_read_kernel(&private_data, sizeof(private_data), - file + offset->struct_files_private_data_offset); + file + offset->struct_file_private_data_offset); if (private_data == NULL) { return NULL; @@ -225,7 +225,7 @@ static __inline void *get_socket_from_fd(int fd_num, file + data_off); #else bpf_probe_read_kernel(&private_data, sizeof(private_data), - file + offset->struct_files_private_data_offset); + file + offset->struct_file_private_data_offset); #endif if (private_data == NULL) { return NULL; diff --git a/agent/src/ebpf/mod.rs b/agent/src/ebpf/mod.rs index f70df95393a..bb3088e3571 100644 --- a/agent/src/ebpf/mod.rs +++ b/agent/src/ebpf/mod.rs @@ -782,6 +782,7 @@ extern "C" { pub fn enable_unix_socket_feature(); pub fn disable_fentry(); pub fn enable_fentry(); + pub fn set_virtual_file_collect(enabled: bool) -> c_int; cfg_if::cfg_if! { if #[cfg(feature = "extended_observability")] { pub fn enable_offcpu_profiler() -> c_int; diff --git a/agent/src/ebpf/samples/rust/socket-tracer/src/main.rs b/agent/src/ebpf/samples/rust/socket-tracer/src/main.rs index 70d7370cc8b..3d08d4b3f3d 100644 --- a/agent/src/ebpf/samples/rust/socket-tracer/src/main.rs +++ b/agent/src/ebpf/samples/rust/socket-tracer/src/main.rs @@ -653,6 +653,7 @@ fn main() { // dpdk enable // set_dpdk_trace_enabled(true); // disable_kprobe_feature(); + // set_virtual_file_collect(true); if running_socket_tracer( socket_trace_callback, /* Callback interface rust -> C */ 1, /* Number of worker threads, indicating how many user-space threads participate in data processing */ diff --git a/agent/src/ebpf/user/socket.c b/agent/src/ebpf/user/socket.c index 03f4a342ab6..de09f5322f0 100644 --- a/agent/src/ebpf/user/socket.c +++ b/agent/src/ebpf/user/socket.c @@ -56,8 +56,9 @@ static enum linux_kernel_type g_k_type; static bool use_kfunc_bin; // Whether to use fentry/fexit binary eBPF bytecode static struct list_head events_list; // Use for extra register events static pthread_t proc_events_pthread; // Process exec/exit thread -static bool kprobe_feature_disable; // Whether to disable the kprobe feature. -static bool unix_socket_feature_enable; // Whether to enable the kprobe feature. +static bool kprobe_feature_disable; // Whether to disable the kprobe feature? +static bool unix_socket_feature_enable; // Whether to enable the kprobe feature? +static bool virtual_file_collect_enable; // Whether to enable virtual file collect? /* * Control whether to disable the tracing feature. * 'true' disables the tracing feature, and 'false' enables it. @@ -1711,37 +1712,45 @@ static int update_offset_map_default(struct bpf_tracer *t, switch (kern_type) { case K_TYPE_VER_3_10: offset.struct_files_struct_fdt_offset = 0x8; - offset.struct_files_private_data_offset = 0xa8; + offset.struct_file_private_data_offset = 0xa8; offset.struct_file_f_pos_offset = 0x68; offset.struct_ns_common_inum_offset = 0x4; break; case K_TYPE_KYLIN: offset.struct_files_struct_fdt_offset = 0x20; - offset.struct_files_private_data_offset = 0xc0; + offset.struct_file_private_data_offset = 0xc0; offset.struct_file_f_pos_offset = 0x60; offset.struct_ns_common_inum_offset = 0x10; break; default: offset.struct_files_struct_fdt_offset = 0x20; - offset.struct_files_private_data_offset = 0xc8; + offset.struct_file_private_data_offset = 0xc8; offset.struct_file_f_pos_offset = 0x68; offset.struct_ns_common_inum_offset = 0x10; }; /* * In Tencent Linux (4.14.105-1-tlinux3-0023.1), there is a difference in - * `struct_files_private_data_offset`. If the offset value of the generic + * `struct_file_private_data_offset`. If the offset value of the generic * eBPF program is used, it will result in the kernel being unable to adapt. * A separate correction is made here. */ if (strstr(linux_release, "tlinux3")) - offset.struct_files_private_data_offset = 0xc0; + offset.struct_file_private_data_offset = 0xc0; // For 4.19.90-2211.5.0.0178.22.uel20.x86_64 if (strstr(linux_release, "uel20")) - offset.struct_files_private_data_offset = 0xc0; + offset.struct_file_private_data_offset = 0xc0; - offset.struct_file_f_inode_offset = 0x20; + /* + * The corresponding offset is used to access `file->f_op->read_iter`, which + * is then used to determine whether the file belongs to a standard VFS + * filesystem or is a virtual file. + */ + offset.struct_file_f_op_offset = 0x28; + offset.struct_file_operations_read_iter_offset = 0x20; + + offset.struct_file_f_inode_offset = 0x20; offset.struct_inode_i_mode_offset = 0x0; offset.struct_inode_i_sb_offset = 0x28; offset.struct_super_block_s_dev_offset = 0x10; @@ -1817,8 +1826,12 @@ static int update_offset_map_from_btf_vmlinux(struct bpf_tracer *t) int struct_files_struct_fdt_offset = kernel_struct_field_offset(obj, "files_struct", "fdt"); - int struct_files_private_data_offset = + int struct_file_private_data_offset = kernel_struct_field_offset(obj, "file", "private_data"); + int struct_file_f_op_offset = + kernel_struct_field_offset(obj, "file", "f_op"); + int struct_file_operations_read_iter_offset = + kernel_struct_field_offset(obj, "file_operations", "read_iter"); int struct_file_f_inode_offset = kernel_struct_field_offset(obj, "file", "f_inode"); int struct_file_f_pos_offset = @@ -1885,7 +1898,9 @@ static int update_offset_map_from_btf_vmlinux(struct bpf_tracer *t) kernel_struct_field_offset(obj, "mount", "mnt_id"); if (copied_seq_offs < 0 || write_seq_offs < 0 || files_offs < 0 || sk_flags_offs < 0 || struct_files_struct_fdt_offset < 0 || - struct_files_private_data_offset < 0 || + struct_file_private_data_offset < 0 || + struct_file_f_op_offset < 0 || + struct_file_operations_read_iter_offset < 0 || struct_file_f_inode_offset < 0 || struct_inode_i_mode_offset < 0 || struct_inode_i_sb_offset < 0 || struct_super_block_s_dev_offset < 0 || struct_file_dentry_offset < 0 || @@ -1910,8 +1925,12 @@ static int update_offset_map_from_btf_vmlinux(struct bpf_tracer *t) ebpf_info(" sk_flags_offs: 0x%x\n", sk_flags_offs); ebpf_info(" struct_files_struct_fdt_offset: 0x%x\n", struct_files_struct_fdt_offset); - ebpf_info(" struct_files_private_data_offset: 0x%x\n", - struct_files_private_data_offset); + ebpf_info(" struct_file_private_data_offset: 0x%x\n", + struct_file_private_data_offset); + ebpf_info(" struct_file_f_op_offset: 0x%x\n", + struct_file_f_op_offset); + ebpf_info(" struct_file_operations_read_iter_offset: 0x%x\n", + struct_file_operations_read_iter_offset); ebpf_info(" struct_file_f_inode_offset: 0x%x\n", struct_file_f_inode_offset); ebpf_info(" struct_file_f_pos_offset: 0x%x\n", @@ -1978,8 +1997,11 @@ static int update_offset_map_from_btf_vmlinux(struct bpf_tracer *t) offset.tcp_sock__copied_seq_offset = copied_seq_offs; offset.tcp_sock__write_seq_offset = write_seq_offs; offset.struct_files_struct_fdt_offset = struct_files_struct_fdt_offset; - offset.struct_files_private_data_offset = - struct_files_private_data_offset; + offset.struct_file_private_data_offset = + struct_file_private_data_offset; + offset.struct_file_f_op_offset = struct_file_f_op_offset; + offset.struct_file_operations_read_iter_offset = + struct_file_operations_read_iter_offset; offset.struct_file_f_inode_offset = struct_file_f_inode_offset; offset.struct_file_f_pos_offset = struct_file_f_pos_offset; offset.struct_inode_i_mode_offset = struct_inode_i_mode_offset; @@ -2040,8 +2062,12 @@ static void display_kern_offsets(bpf_offset_param_t * offset) offset->struct_files_struct_fdt_offset); ebpf_info("\tstruct_file_f_pos_offset: 0x%x\n", offset->struct_file_f_pos_offset); - ebpf_info("\tstruct_files_private_data_offset: 0x%x\n", - offset->struct_files_private_data_offset); + ebpf_info("\tstruct_file_private_data_offset: 0x%x\n", + offset->struct_file_private_data_offset); + ebpf_info("\tstruct_file_f_op_offset: 0x%x\n", + offset->struct_file_f_op_offset); + ebpf_info("\tstruct_file_operations_read_iter_offset: 0x%x\n", + offset->struct_file_operations_read_iter_offset); ebpf_info("\tstruct_file_f_inode_offset: 0x%x\n", offset->struct_file_f_inode_offset); ebpf_info("\tstruct_inode_i_mode_offset: 0x%x\n", @@ -2354,6 +2380,7 @@ int set_io_event_collect_mode(uint32_t mode) return ETR_UPDATE_MAP_FAILD; } + ebpf_info("Set io_event_collect_mode %d\n", io_event_collect_mode); return 0; } @@ -2387,6 +2414,42 @@ int set_io_event_minimal_duration(uint64_t duration) return ETR_UPDATE_MAP_FAILD; } + ebpf_info("Set io_event_minimal_duration %llu ns\n", io_event_minimal_duration); + return 0; +} + +int set_virtual_file_collect(bool enabled) +{ + virtual_file_collect_enable = enabled; + + struct bpf_tracer *tracer = find_bpf_tracer(SK_TRACER_NAME); + if (tracer == NULL) { + return 0; + } + + int cpu; + int nr_cpus = get_num_possible_cpus(); + struct tracer_ctx_s values[nr_cpus]; + memset(values, 0, sizeof(values)); + + if (!bpf_table_get_value(tracer, MAP_TRACER_CTX_NAME, 0, values)) { + ebpf_warning("Get map '%s' failed.\n", MAP_TRACER_CTX_NAME); + return ETR_NOTEXIST; + } + + for (cpu = 0; cpu < nr_cpus; cpu++) { + values[cpu].virtual_file_collect_enabled = + virtual_file_collect_enable; + } + + if (!bpf_table_set_value + (tracer, MAP_TRACER_CTX_NAME, 0, (void *)&values)) { + ebpf_warning("Set '%s' failed\n", MAP_TRACER_CTX_NAME); + return ETR_UPDATE_MAP_FAILD; + } + + ebpf_info("IO event virtual_file_collect_enable set to %s\n", + virtual_file_collect_enable ? "true" : "false"); return 0; } @@ -2921,6 +2984,7 @@ int running_socket_tracer(tracer_callback_t handle, t_conf[cpu].io_event_collect_mode = io_event_collect_mode; t_conf[cpu].io_event_minimal_duration = io_event_minimal_duration; + t_conf[cpu].virtual_file_collect_enabled = virtual_file_collect_enable; t_conf[cpu].disable_tracing = g_disable_syscall_tracing; if (!g_disable_syscall_tracing) t_conf[cpu].go_tracing_timeout = go_tracing_timeout; @@ -2930,6 +2994,13 @@ int running_socket_tracer(tracer_callback_t handle, (tracer, MAP_TRACER_CTX_NAME, 0, (void *)&t_conf)) return -EINVAL; + ebpf_info("Config socket_data_limit_max: %d\n", socket_data_limit_max); + ebpf_info("Config io_event_collect_mode: %d\n", io_event_collect_mode); + ebpf_info("Config io_event_minimal_duration: %llu ns\n", io_event_minimal_duration); + ebpf_info("Config virtual_file_collect_enable: %d\n", virtual_file_collect_enable); + ebpf_info("Config g_disable_syscall_tracing: %d\n", g_disable_syscall_tracing); + ebpf_info("Config go_tracing_timeout: %d\n", go_tracing_timeout); + tracer->data_limit_max = socket_data_limit_max; // Insert prog of output data into map for using BPF Tail Calls. diff --git a/agent/src/ebpf/user/socket.h b/agent/src/ebpf/user/socket.h index af788e83c08..29ffed07038 100644 --- a/agent/src/ebpf/user/socket.h +++ b/agent/src/ebpf/user/socket.h @@ -482,5 +482,18 @@ void enable_kprobe_feature(void); */ void insert_adapt_kern_data_to_map(struct bpf_tracer *tracer, int mnt_id, u32 mntns_id); + +/** + * Enable or disable virtual file collection. + * + * This function sets the global flag controlling whether + * virtual file collection is enabled. + * + * @param enabled Boolean flag to enable (true) or disable (false) + * the virtual file collection feature. + * + * @return 0 on success, or a negative error code on failure. + */ +int set_virtual_file_collect(bool enabled); bool is_pure_kprobe_ebpf(void); #endif /* DF_USER_SOCKET_H */ diff --git a/agent/src/ebpf_dispatcher.rs b/agent/src/ebpf_dispatcher.rs index 382cd5f06b3..7c2f590e4a5 100644 --- a/agent/src/ebpf_dispatcher.rs +++ b/agent/src/ebpf_dispatcher.rs @@ -947,6 +947,15 @@ impl EbpfCollector { return Err(Error::EbpfInitError); } + if ebpf::set_virtual_file_collect(config.ebpf.file.io_event.enable_virtual_file_collect) + != 0 + { + info!( + "ebpf set_virtual_file_collect error: {}", + config.ebpf.file.io_event.enable_virtual_file_collect + ); + } + if ebpf::set_io_event_minimal_duration( config.ebpf.file.io_event.minimal_duration.as_nanos() as c_ulonglong, ) != 0 diff --git a/server/agent_config/README-CH.md b/server/agent_config/README-CH.md index e7369403bc2..4c629a45644 100644 --- a/server/agent_config/README-CH.md +++ b/server/agent_config/README-CH.md @@ -4371,6 +4371,36 @@ inputs: deepflow-agent 所采集的文件 IO 事件的时延下限阈值,操作系统中时延低于此阈值 的文件 IO 事件将被忽略。 +##### 启用虚拟文件采集 {#inputs.ebpf.file.io_event.enable_virtual_file_collect} + +**标签**: + +agent_restart + +**FQCN**: + +`inputs.ebpf.file.io_event.enable_virtual_file_collect` + +**默认值**: +```yaml +inputs: + ebpf: + file: + io_event: + enable_virtual_file_collect: false +``` + +**模式**: +| Key | Value | +| ---- | ---------------------------- | +| Type | bool | + +**详细描述**: + +当设置为 true 时,deepflow-agent 将采集发生在虚拟文件系统上的文件 +I/O 事件(例如 /proc、/sys、/run 等由内核动态生成的伪文件系统)。 +当设置为 false 时,将不会采集虚拟文件系统上的文件 I/O 事件。 + ### Profile {#inputs.ebpf.profile} #### 栈回溯 {#inputs.ebpf.profile.unwinding} diff --git a/server/agent_config/README.md b/server/agent_config/README.md index 4bfd3a2e85e..744c212b91b 100644 --- a/server/agent_config/README.md +++ b/server/agent_config/README.md @@ -4476,6 +4476,38 @@ inputs: Only collect IO events with delay exceeding this threshold. +##### Virtual File Collection Enabled {#inputs.ebpf.file.io_event.enable_virtual_file_collect} + +**Tags**: + +agent_restart + +**FQCN**: + +`inputs.ebpf.file.io_event.enable_virtual_file_collect` + +**Default value**: +```yaml +inputs: + ebpf: + file: + io_event: + enable_virtual_file_collect: false +``` + +**Schema**: +| Key | Value | +| ---- | ---------------------------- | +| Type | bool | + +**Description**: + +When set to true, the agent will collect file I/O events generated on +virtual file systems (such as /proc, /sys, /run, and other kernel +pseudo file systems). +When set to false, the agent will not collect file I/O events from +virtual file systems. + ### Profile {#inputs.ebpf.profile} #### Unwinding {#inputs.ebpf.profile.unwinding} diff --git a/server/agent_config/template.yaml b/server/agent_config/template.yaml index 2f54f218b10..53730ada664 100644 --- a/server/agent_config/template.yaml +++ b/server/agent_config/template.yaml @@ -3307,6 +3307,27 @@ inputs: # 的文件 IO 事件将被忽略。 # upgrade_from: static_config.ebpf.io-event-minimal-duration minimal_duration: 1ms + # type: bool + # name: + # en: Virtual File Collection Enabled + # ch: 启用虚拟文件采集 + # unit: + # range: [] + # enum_options: [] + # modification: agent_restart + # ee_feature: false + # description: + # en: |- + # When set to true, the agent will collect file I/O events generated on + # virtual file systems (such as /proc, /sys, /run, and other kernel + # pseudo file systems). + # When set to false, the agent will not collect file I/O events from + # virtual file systems. + # ch: |- + # 当设置为 true 时,deepflow-agent 将采集发生在虚拟文件系统上的文件 + # I/O 事件(例如 /proc、/sys、/run 等由内核动态生成的伪文件系统)。 + # 当设置为 false 时,将不会采集虚拟文件系统上的文件 I/O 事件。 + enable_virtual_file_collect: false # type: section # name: Profile # description: From 9ba702f6a0ede8f7a075d36598d41eb6999b6ee8 Mon Sep 17 00:00:00 2001 From: Jiping Yin Date: Wed, 31 Dec 2025 17:21:30 +0800 Subject: [PATCH 2/2] Adjust interface names --- agent/src/ebpf/kernel/files_rw.bpf.c | 63 +++++++++++++++++----------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/agent/src/ebpf/kernel/files_rw.bpf.c b/agent/src/ebpf/kernel/files_rw.bpf.c index e0080342b96..b79ecea2edf 100644 --- a/agent/src/ebpf/kernel/files_rw.bpf.c +++ b/agent/src/ebpf/kernel/files_rw.bpf.c @@ -21,19 +21,14 @@ // Default value set when file read/write latency timestamp rollback occurs. #define TIME_ROLLBACK_DEFAULT_LATENCY_NS 50000 +#define FILE_CHECK_ERROR (-1) /* Error or exceptional condition */ +#define FILE_TYPE_REGULAR 0 /* Regular (non-virtual) file */ +#define FILE_TYPE_VIRTUAL 1 /* Virtual file */ -static __inline bool is_regular_file(int fd, - bool disable_vfile_collect, - struct member_fields_offset *off_ptr) +static __inline int check_virtual_file(void *file, struct member_fields_offset *offset) { - struct member_fields_offset *offset = off_ptr; - if (offset == NULL) { - __u32 k0 = 0; - offset = members_offset__lookup(&k0); - } - void *file = fd_to_file(fd, offset); - if (file == NULL) - return false; + if (!file || !offset) + return FILE_CHECK_ERROR; /* * Determine whether a file belongs to a regular VFS filesystem @@ -56,19 +51,37 @@ static __inline bool is_regular_file(int fd, * - certain character devices or special driver files * - kernel objects without regular VFS file semantics */ - if (disable_vfile_collect) { - void *f_op, *read_iter; - bpf_probe_read_kernel(&f_op, sizeof(f_op), - file + offset->struct_file_f_op_offset); - if (f_op == NULL) - return false; + void *f_op, *read_iter; + bpf_probe_read_kernel(&f_op, sizeof(f_op), + file + offset->struct_file_f_op_offset); + if (f_op == NULL) + return FILE_CHECK_ERROR; + + bpf_probe_read_kernel(&read_iter, sizeof(read_iter), + f_op + + offset->struct_file_operations_read_iter_offset); + if (read_iter == NULL) + return FILE_TYPE_VIRTUAL; + + return FILE_TYPE_REGULAR; +} - bpf_probe_read_kernel(&read_iter, sizeof(read_iter), - f_op + - offset->struct_file_operations_read_iter_offset); - if (read_iter == NULL) - return false; +static __inline bool is_readable_file(int fd, + bool disable_vfile_collect, + struct member_fields_offset *off_ptr) +{ + struct member_fields_offset *offset = off_ptr; + if (offset == NULL) { + __u32 k0 = 0; + offset = members_offset__lookup(&k0); } + void *file = fd_to_file(fd, offset); + if (file == NULL) + return false; + + if (disable_vfile_collect && + check_virtual_file(file, offset) != FILE_TYPE_REGULAR) + return false; __u32 i_mode = file_to_i_mode(file, offset); return S_ISREG(i_mode); @@ -334,9 +347,9 @@ static __inline int trace_io_event_common(void *ctx, int data_max_sz = tracer_ctx->data_limit_max; - if (!is_regular_file(data_args->fd, - !tracer_ctx->virtual_file_collect_enabled, - offset)) { + if (!is_readable_file(data_args->fd, + !tracer_ctx->virtual_file_collect_enabled, + offset)) { return -1; }