2121
2222// Default value set when file read/write latency timestamp rollback occurs.
2323#define TIME_ROLLBACK_DEFAULT_LATENCY_NS 50000
24-
24+
2525static __inline bool is_regular_file (int fd ,
2626 struct member_fields_offset * off_ptr )
2727{
@@ -35,12 +35,153 @@ static __inline bool is_regular_file(int fd,
3535 return S_ISREG (i_mode );
3636}
3737
38+ static __inline void * get_mount_ptr (void * file ,
39+ struct member_fields_offset * off_ptr )
40+ {
41+ void * vfsmount = NULL ;
42+
43+ /*
44+ * struct_file_f_path_offset: Starting from Linux 6.5, this offset has
45+ * undergone significant changes and automatic inference is not supported.
46+ */
47+
48+ // file -> path -> vfsmount
49+ bpf_probe_read_kernel (& vfsmount , sizeof (vfsmount ),
50+ file + off_ptr -> struct_file_f_path_offset +
51+ off_ptr -> struct_path_mnt_offset );
52+ if (vfsmount == NULL )
53+ return NULL ;
54+
55+ // `vfsmount` is embedded in `struct mount`
56+ return (vfsmount - off_ptr -> struct_mount_mnt_offset );
57+ }
58+
59+ static __inline void get_mount_ids (void * file ,
60+ struct __io_event_buffer * buffer ,
61+ struct member_fields_offset * off_ptr )
62+ {
63+ void * mount , * mnt_ns = NULL ;
64+ buffer -> mntns_id = 0 ;
65+ buffer -> mnt_id = -1 ;
66+ mount = get_mount_ptr (file , off_ptr );
67+ if (mount == NULL )
68+ return ;
69+
70+ //bpf_debug("mount_mnt_id_offset 0x%x\n", off_ptr->struct_mount_mnt_id_offset);
71+ if (off_ptr -> struct_mount_mnt_id_offset != INVALID_OFFSET ) {
72+ bpf_probe_read_kernel (& buffer -> mnt_id , sizeof (buffer -> mnt_id ),
73+ mount +
74+ off_ptr -> struct_mount_mnt_id_offset );
75+ }
76+
77+ if (off_ptr -> struct_mount_mnt_ns_offset == INVALID_OFFSET )
78+ return ;
79+
80+ bpf_probe_read_kernel (& mnt_ns , sizeof (mnt_ns ),
81+ mount + off_ptr -> struct_mount_mnt_ns_offset );
82+ if (mnt_ns == NULL )
83+ return ;
84+
85+ // mnt_namespace -> ns_common -> inum
86+ bpf_probe_read_kernel (& buffer -> mntns_id , sizeof (buffer -> mntns_id ),
87+ mnt_ns + off_ptr -> struct_mnt_namespace_ns_offset +
88+ off_ptr -> struct_ns_common_inum_offset );
89+ }
90+
91+ static __inline int infer_mount_offset (int fd ,
92+ struct member_fields_offset * off_ptr )
93+ {
94+ // The inference has been completed.
95+ if (off_ptr -> files_infer_done )
96+ return 0 ;
97+
98+ __u32 k0 = 0 ;
99+ struct adapt_kern_data * adapt_data ;
100+ adapt_data = adapt_kern_data_map__lookup (& k0 );
101+ if (!adapt_data )
102+ goto error ;
103+
104+ // The inference is limited to the threads we have designated.
105+ if (adapt_data -> id != bpf_get_current_pid_tgid ())
106+ return -1 ;
107+
108+ void * file = fd_to_file (fd , off_ptr );
109+ if (file == NULL )
110+ goto error ;
111+
112+ void * mount = get_mount_ptr (file , off_ptr );
113+ if (mount == NULL )
114+ goto error ;
115+
116+ int i , mnt_id = 0 ;
117+ bool found = false;
118+ __u16 mnt_id_offsets [] = { 0x10c , 0x114 , 0x11c , 0x124 };
119+ #pragma unroll
120+ for (i = 0 ; i < ARRAY_SIZE (mnt_id_offsets ); i ++ ) {
121+ bpf_probe_read_kernel (& mnt_id , sizeof (mnt_id ),
122+ mount + mnt_id_offsets [i ]);
123+ if (mnt_id == adapt_data -> mnt_id ) {
124+ found = true;
125+ break ;
126+ }
127+ }
128+
129+ if (found ) {
130+ off_ptr -> struct_mount_mnt_id_offset = mnt_id_offsets [i ];
131+ } else {
132+ off_ptr -> struct_mount_mnt_id_offset = INVALID_OFFSET ;
133+ }
134+
135+ __u32 mntns_id = 0 ;
136+ void * mnt_ns = NULL ;
137+ __u16 mnt_ns_offset [] = { 0xe0 , 0xe8 };
138+ off_ptr -> struct_mount_mnt_ns_offset = INVALID_OFFSET ;
139+ off_ptr -> struct_mnt_namespace_ns_offset = INVALID_OFFSET ;
140+ #pragma unroll
141+ for (i = 0 ; i < ARRAY_SIZE (mnt_ns_offset ); i ++ ) {
142+ bpf_probe_read_kernel (& mnt_ns , sizeof (mnt_ns ),
143+ mount + mnt_ns_offset [i ]);
144+ if (mnt_ns == NULL )
145+ continue ;
146+ // mnt_namespace -> ns_common -> inum
147+ bpf_probe_read_kernel (& mntns_id , sizeof (mntns_id ),
148+ mnt_ns +
149+ off_ptr -> struct_ns_common_inum_offset );
150+ if (mntns_id == adapt_data -> mntns_id ) {
151+ found = true;
152+ off_ptr -> struct_mount_mnt_ns_offset = mnt_ns_offset [i ];
153+ off_ptr -> struct_mnt_namespace_ns_offset = 0 ;
154+ off_ptr -> files_infer_done = 1 ;
155+ return 0 ;
156+ }
157+ bpf_probe_read_kernel (& mntns_id , sizeof (mntns_id ),
158+ mnt_ns + 0x8 +
159+ off_ptr -> struct_ns_common_inum_offset );
160+ if (mntns_id == adapt_data -> mntns_id ) {
161+ off_ptr -> struct_mount_mnt_ns_offset = mnt_ns_offset [i ];
162+ off_ptr -> struct_mnt_namespace_ns_offset = 0x8 ;
163+ off_ptr -> files_infer_done = 1 ;
164+ return 0 ;
165+ }
166+ }
167+
168+ off_ptr -> files_infer_done = 1 ;
169+ return -1 ;
170+
171+ error :
172+ off_ptr -> struct_mount_mnt_id_offset = INVALID_OFFSET ;
173+ off_ptr -> struct_mount_mnt_ns_offset = INVALID_OFFSET ;
174+ off_ptr -> struct_mnt_namespace_ns_offset = INVALID_OFFSET ;
175+ off_ptr -> files_infer_done = 1 ;
176+ return -1 ;
177+ }
178+
38179static __inline void set_file_metric_data (struct __io_event_buffer * buffer ,
39180 struct __socket_data * v ,
40181 int fd ,
41182 struct member_fields_offset * off_ptr )
42183{
43- #define MAX_DIRECTORY_DEPTH 19
184+ #define MAX_DIRECTORY_DEPTH 18
44185
45186 struct member_fields_offset * offset = off_ptr ;
46187 if (offset == NULL ) {
@@ -90,6 +231,8 @@ static __inline void set_file_metric_data(struct __io_event_buffer *buffer,
90231 void * dentry = NULL , * parent ;
91232 bpf_probe_read_kernel (& dentry , sizeof (dentry ),
92233 file + offset -> struct_file_dentry_offset );
234+ get_mount_ids (file , buffer , offset );
235+ //bpf_debug("buffer->mnt_id %d\n", buffer->mnt_id);
93236 buffer -> len = 0 ;
94237#pragma unroll
95238 for (int i = 0 ; i < MAX_DIRECTORY_DEPTH ; i ++ ) {
@@ -239,6 +382,9 @@ static __inline int do_sys_enter_pread(int fd, enum syscall_src_func fn)
239382 if (!offset )
240383 return 0 ;
241384
385+ // Attempt to infer file-related structure offsets.
386+ infer_mount_offset (fd , offset );
387+
242388 __u64 id = bpf_get_current_pid_tgid ();
243389 // Stash arguments.
244390 struct data_args_t read_args = {};
@@ -252,7 +398,7 @@ static __inline int do_sys_enter_pread(int fd, enum syscall_src_func fn)
252398#ifdef SUPPORTS_KPROBE_ONLY
253399//ssize_t ksys_pread64(unsigned int fd, char __user *buf, size_t count,
254400// loff_t pos)
255- KPROG (ksys_pread64 ) (struct pt_regs * ctx ) {
401+ KPROG (ksys_pread64 ) (struct pt_regs * ctx ) {
256402 int fd = (unsigned int )PT_REGS_PARM1 (ctx );
257403 return do_sys_enter_pread (fd , SYSCALL_FUNC_PREAD64 );
258404}
@@ -262,25 +408,25 @@ KPROG(ksys_pread64) (struct pt_regs *ctx) {
262408 * static ssize_t do_preadv(unsigned long fd, const struct iovec __user *vec,
263409 * unsigned long vlen, loff_t pos, rwf_t flags);
264410 */
265- KPROG (do_preadv ) (struct pt_regs * ctx ) {
411+ KPROG (do_preadv ) (struct pt_regs * ctx ) {
266412 int fd = (unsigned int )PT_REGS_PARM1 (ctx );
267413 return do_sys_enter_pread (fd , SYSCALL_FUNC_PREADV );
268414}
269415#else
270416// /sys/kernel/debug/tracing/events/syscalls/sys_enter_pread64/format
271- TP_SYSCALL_PROG (enter_pread64 ) (struct syscall_comm_enter_ctx * ctx ) {
417+ TP_SYSCALL_PROG (enter_pread64 ) (struct syscall_comm_enter_ctx * ctx ) {
272418 int fd = ctx -> fd ;
273419 return do_sys_enter_pread (fd , SYSCALL_FUNC_PREAD64 );
274420}
275421
276422// /sys/kernel/debug/tracing/events/syscalls/sys_enter_preadv/format
277- TP_SYSCALL_PROG (enter_preadv ) (struct syscall_comm_enter_ctx * ctx ) {
423+ TP_SYSCALL_PROG (enter_preadv ) (struct syscall_comm_enter_ctx * ctx ) {
278424 int fd = ctx -> fd ;
279425 return do_sys_enter_pread (fd , SYSCALL_FUNC_PREADV );
280426}
281427
282428// /sys/kernel/debug/tracing/events/syscalls/sys_enter_preadv2/format
283- TP_SYSCALL_PROG (enter_preadv2 ) (struct syscall_comm_enter_ctx * ctx ) {
429+ TP_SYSCALL_PROG (enter_preadv2 ) (struct syscall_comm_enter_ctx * ctx ) {
284430 int fd = ctx -> fd ;
285431 return do_sys_enter_pread (fd , SYSCALL_FUNC_PREADV2 );
286432}
@@ -306,28 +452,28 @@ static __inline int do_sys_exit_pread(void *ctx, ssize_t bytes_count)
306452}
307453
308454#ifdef SUPPORTS_KPROBE_ONLY
309- KRETPROG (ksys_pread64 ) (struct pt_regs * ctx ) {
455+ KRETPROG (ksys_pread64 ) (struct pt_regs * ctx ) {
310456 ssize_t bytes_count = PT_REGS_RC (ctx );
311457 return do_sys_exit_pread ((void * )ctx , bytes_count );
312458}
313459
314- KRETPROG (do_preadv ) (struct pt_regs * ctx ) {
460+ KRETPROG (do_preadv ) (struct pt_regs * ctx ) {
315461 ssize_t bytes_count = PT_REGS_RC (ctx );
316462 return do_sys_exit_pread ((void * )ctx , bytes_count );
317463}
318464#else
319465// /sys/kernel/debug/tracing/events/syscalls/sys_exit_pwrite64/format
320- TP_SYSCALL_PROG (exit_pread64 ) (struct syscall_comm_exit_ctx * ctx ) {
466+ TP_SYSCALL_PROG (exit_pread64 ) (struct syscall_comm_exit_ctx * ctx ) {
321467 return do_sys_exit_pread ((void * )ctx , (ssize_t ) ctx -> ret );
322468}
323469
324470// /sys/kernel/debug/tracing/events/syscalls/sys_exit_pwritev/format
325- TP_SYSCALL_PROG (exit_preadv ) (struct syscall_comm_exit_ctx * ctx ) {
471+ TP_SYSCALL_PROG (exit_preadv ) (struct syscall_comm_exit_ctx * ctx ) {
326472 return do_sys_exit_pread ((void * )ctx , (ssize_t ) ctx -> ret );
327473}
328474
329475// /sys/kernel/debug/tracing/events/syscalls/sys_exit_pwritev2/format
330- TP_SYSCALL_PROG (exit_preadv2 ) (struct syscall_comm_exit_ctx * ctx ) {
476+ TP_SYSCALL_PROG (exit_preadv2 ) (struct syscall_comm_exit_ctx * ctx ) {
331477 return do_sys_exit_pread ((void * )ctx , (ssize_t ) ctx -> ret );
332478}
333479#endif /* SUPPORTS_KPROBE_ONLY */
@@ -352,7 +498,7 @@ static __inline int do_sys_enter_pwrite(int fd, enum syscall_src_func fn)
352498//ssize_t ksys_pwrite64(unsigned int fd, const char __user *buf,
353499// size_t count, loff_t pos);
354500#ifdef SUPPORTS_KPROBE_ONLY
355- KPROG (ksys_pwrite64 ) (struct pt_regs * ctx ) {
501+ KPROG (ksys_pwrite64 ) (struct pt_regs * ctx ) {
356502 int fd = (int )PT_REGS_PARM1 (ctx );
357503 return do_sys_enter_pwrite (fd , SYSCALL_FUNC_PWRITE64 );
358504}
@@ -362,25 +508,25 @@ KPROG(ksys_pwrite64) (struct pt_regs *ctx) {
362508 * static ssize_t do_pwritev(unsigned long fd, const struct iovec __user *vec,
363509 * unsigned long vlen, loff_t pos, rwf_t flags);
364510 */
365- KPROG (do_pwritev ) (struct pt_regs * ctx ) {
511+ KPROG (do_pwritev ) (struct pt_regs * ctx ) {
366512 int fd = (int )PT_REGS_PARM1 (ctx );
367513 return do_sys_enter_pwrite (fd , SYSCALL_FUNC_PWRITEV );
368514}
369515#else
370516// /sys/kernel/debug/tracing/events/syscalls/sys_enter_pwrite64/format
371- TP_SYSCALL_PROG (enter_pwrite64 ) (struct syscall_comm_enter_ctx * ctx ) {
517+ TP_SYSCALL_PROG (enter_pwrite64 ) (struct syscall_comm_enter_ctx * ctx ) {
372518 int fd = ctx -> fd ;
373519 return do_sys_enter_pwrite (fd , SYSCALL_FUNC_PWRITE64 );
374520}
375521
376522// /sys/kernel/debug/tracing/events/syscalls/sys_enter_pwritev/format
377- TP_SYSCALL_PROG (enter_pwritev ) (struct syscall_comm_enter_ctx * ctx ) {
523+ TP_SYSCALL_PROG (enter_pwritev ) (struct syscall_comm_enter_ctx * ctx ) {
378524 int fd = ctx -> fd ;
379525 return do_sys_enter_pwrite (fd , SYSCALL_FUNC_PWRITEV );
380526}
381527
382528// /sys/kernel/debug/tracing/events/syscalls/sys_enter_pwritev2/format
383- TP_SYSCALL_PROG (enter_pwritev2 ) (struct syscall_comm_enter_ctx * ctx ) {
529+ TP_SYSCALL_PROG (enter_pwritev2 ) (struct syscall_comm_enter_ctx * ctx ) {
384530 int fd = ctx -> fd ;
385531 return do_sys_enter_pwrite (fd , SYSCALL_FUNC_PWRITEV2 );
386532}
@@ -407,28 +553,28 @@ static __inline int do_sys_exit_pwrite(void *ctx, ssize_t bytes_count)
407553}
408554
409555#ifdef SUPPORTS_KPROBE_ONLY
410- KRETPROG (ksys_pwrite64 ) (struct pt_regs * ctx ) {
556+ KRETPROG (ksys_pwrite64 ) (struct pt_regs * ctx ) {
411557 ssize_t bytes_count = PT_REGS_RC (ctx );
412558 return do_sys_exit_pwrite ((void * )ctx , bytes_count );
413559}
414560
415- KRETPROG (do_pwritev ) (struct pt_regs * ctx ) {
561+ KRETPROG (do_pwritev ) (struct pt_regs * ctx ) {
416562 ssize_t bytes_count = PT_REGS_RC (ctx );
417563 return do_sys_exit_pwrite ((void * )ctx , bytes_count );
418564}
419565#else
420566// /sys/kernel/debug/tracing/events/syscalls/sys_exit_pwrite64/format
421- TP_SYSCALL_PROG (exit_pwrite64 ) (struct syscall_comm_exit_ctx * ctx ) {
567+ TP_SYSCALL_PROG (exit_pwrite64 ) (struct syscall_comm_exit_ctx * ctx ) {
422568 return do_sys_exit_pwrite ((void * )ctx , (ssize_t ) ctx -> ret );
423569}
424570
425571// /sys/kernel/debug/tracing/events/syscalls/sys_exit_pwritev/format
426- TP_SYSCALL_PROG (exit_pwritev ) (struct syscall_comm_exit_ctx * ctx ) {
572+ TP_SYSCALL_PROG (exit_pwritev ) (struct syscall_comm_exit_ctx * ctx ) {
427573 return do_sys_exit_pwrite ((void * )ctx , (ssize_t ) ctx -> ret );
428574}
429575
430576// /sys/kernel/debug/tracing/events/syscalls/sys_exit_pwritev2/format
431- TP_SYSCALL_PROG (exit_pwritev2 ) (struct syscall_comm_exit_ctx * ctx ) {
577+ TP_SYSCALL_PROG (exit_pwritev2 ) (struct syscall_comm_exit_ctx * ctx ) {
432578 return do_sys_exit_pwrite ((void * )ctx , (ssize_t ) ctx -> ret );
433579}
434580#endif /* SUPPORTS_KPROBE_ONLY */
0 commit comments