Skip to content

Instantly share code, notes, and snippets.

@giuseppe
Created May 8, 2020 15:37
Show Gist options
  • Save giuseppe/7bd343b0c629f5f90c73b99187b5edbb to your computer and use it in GitHub Desktop.
Save giuseppe/7bd343b0c629f5f90c73b99187b5edbb to your computer and use it in GitHub Desktop.
#!/usr/bin/python3
#
# profile *sync* syscalls.
#
# Based on existing programs that have these copyrights:
# Copyright (c) 2015 Brendan Gregg.
# Licensed under the Apache License, Version 2.0 (the "License")
#
# 13-Aug-2015 Brendan Gregg Created this.
# 19-Feb-2016 Allan McAleavy migrated to BPF_PERF_OUTPUT
from __future__ import print_function
from bcc import BPF
import os
syscalls = {
1: "fdatasync",
2: "fsync",
3: "msync",
4: "sync",
5: "syncfs",
6: "sync_file_range",
7: "sync_file_range2",
}
code = """
struct data_t {
u32 syscall;
u64 ts;
u32 pid;
};
BPF_HASH(start, u32);
BPF_PERF_OUTPUT(events);
int trace_func_entry(struct pt_regs *ctx)
{
u64 pid_tgid = bpf_get_current_pid_tgid();
u32 pid = pid_tgid;
u32 tgid = pid_tgid >> 32;
u64 sc;
u64 ts = bpf_ktime_get_ns();
start.update(&pid, &ts);
return 0;
}
"""
for k, v in syscalls.items():
code = code + \
"""
int trace_func_return_SYSCALL(struct pt_regs *ctx)
{
struct data_t data = {};
u64 *tsp;
u64 pid_tgid = bpf_get_current_pid_tgid();
u32 pid = pid_tgid;
u32 tgid = pid_tgid >> 32;
// calculate delta time
tsp = start.lookup(&pid);
if (tsp == 0) {
return 0; // missed start
}
start.delete(&pid);
data.ts = (bpf_ktime_get_ns() - *tsp) / 1000;
data.syscall = SYSCALL;
data.pid = pid;
events.perf_submit(ctx, &data, sizeof(data));
return 0;
}
""".replace("SYSCALL", str(k))
# load BPF program
b = BPF(text=code)
for k, v in syscalls.items():
b.attach_kprobe(event=b.get_syscall_fnname(v),
fn_name="trace_func_entry")
b.attach_kretprobe(event=b.get_syscall_fnname(v),
fn_name="trace_func_return_%d" % k)
# header
print("%-18s %-18s %-12s %-12s %s" % ("TIME(s)", "TOTAL SO FAR(s)", "CALL", "PID", "EXE"))
total_so_far = 0.0
# process event
def print_event(cpu, data, size):
global total_so_far
event = b["events"].event(data)
delta = float(event.ts) / 1000000
total_so_far = total_so_far + delta
link = ""
try:
link = os.readlink("/proc/%d/exe" % event.pid)
except:
pass
print("%-18.9f %-18.9f %-12s %-12s %s" % (delta, total_so_far, syscalls[event.syscall], event.pid, link))
# loop with callback to print_event
b["events"].open_perf_buffer(print_event)
while 1:
try:
b.perf_buffer_poll()
except KeyboardInterrupt:
exit()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment