Support kfunc in opensnoop.py
Adding kfunc return trampoline probe if available instead of
kprobe/kretprobe probes.
The return trampoline has access to function entry arguments,
so we are good with just single eBPF program.
The kfunc trampolines are also faster - less intrusive.
Below are stats for compiling linux kernel while running
opensnoop.py on the background for kprobes and kfuncs.
Without opensnoop.py:
Performance counter stats for 'system wide':
849,741,782,765 cycles:k
162.235646336 seconds time elapsed
With opensnoop.py using kprobes:
Performance counter stats for 'system wide':
941,615,199,769 cycles:k
164.355032879 seconds time elapsed
With opensnoop.py using trampolines:
Performance counter stats for 'system wide':
913,437,005,488 cycles:k
163.742914795 seconds time elapsed
Signed-off-by: Jiri Olsa <[email protected]>
diff --git a/tools/opensnoop.py b/tools/opensnoop.py
index 6d1388b..4f94d01 100755
--- a/tools/opensnoop.py
+++ b/tools/opensnoop.py
@@ -105,8 +105,11 @@
#if CGROUPSET
BPF_TABLE_PINNED("hash", u64, u64, cgroupset, 1024, "CGROUPPATH");
#endif
-BPF_HASH(infotmp, u64, struct val_t);
BPF_PERF_OUTPUT(events);
+"""
+
+bpf_text_kprobe = """
+BPF_HASH(infotmp, u64, struct val_t);
int trace_entry(struct pt_regs *ctx, int dfd, const char __user *filename, int flags)
{
@@ -162,6 +165,41 @@
return 0;
}
"""
+
+bpf_text_kfunc= """
+KRETFUNC_PROBE(do_sys_open, int dfd, const char *filename, int flags, int mode, int ret)
+{
+ u64 id = bpf_get_current_pid_tgid();
+ u32 pid = id >> 32; // PID is higher part
+ u32 tid = id; // Cast and get the lower part
+ u32 uid = bpf_get_current_uid_gid();
+
+ PID_TID_FILTER
+ UID_FILTER
+ FLAGS_FILTER
+
+ struct data_t data = {};
+ bpf_get_current_comm(&data.comm, sizeof(data.comm));
+
+ u64 tsp = bpf_ktime_get_ns();
+
+ bpf_probe_read(&data.fname, sizeof(data.fname), (void *)filename);
+ data.id = id;
+ data.ts = tsp / 1000;
+ data.uid = bpf_get_current_uid_gid();
+ data.flags = flags; // EXTENDED_STRUCT_MEMBER
+ data.ret = ret;
+
+ events.perf_submit(ctx, &data, sizeof(data));
+}
+"""
+
+is_support_kfunc = BPF.support_kfunc()
+if is_support_kfunc:
+ bpf_text += bpf_text_kfunc
+else:
+ bpf_text += bpf_text_kprobe
+
if args.tid: # TID trumps PID
bpf_text = bpf_text.replace('PID_TID_FILTER',
'if (tid != %s) { return 0; }' % args.tid)
@@ -195,8 +233,9 @@
# initialize BPF
b = BPF(text=bpf_text)
-b.attach_kprobe(event="do_sys_open", fn_name="trace_entry")
-b.attach_kretprobe(event="do_sys_open", fn_name="trace_return")
+if not is_support_kfunc:
+ b.attach_kprobe(event="do_sys_open", fn_name="trace_entry")
+ b.attach_kretprobe(event="do_sys_open", fn_name="trace_return")
initial_ts = 0