diff --git a/man/man8/syncsnoop.8 b/man/man8/syncsnoop.8 index eb641d66372f..3d4c8c4f434d 100644 --- a/man/man8/syncsnoop.8 +++ b/man/man8/syncsnoop.8 @@ -11,6 +11,10 @@ be useful to know if they are happening and how frequently. This works by tracing the kernel sys_sync() function using dynamic tracing, and will need updating to match any changes to this function. +This makes use of a Linux 4.5 feature (bpf_perf_event_output()); +for kernels older than 4.5, see the version under tools/old, +which uses an older mechanism. + This program is also a basic example of eBPF/bcc. Since this uses BPF, only the root user can use this tool. diff --git a/tools/old/syncsnoop.py b/tools/old/syncsnoop.py new file mode 100755 index 000000000000..cae57ea8ad33 --- /dev/null +++ b/tools/old/syncsnoop.py @@ -0,0 +1,31 @@ +#!/usr/bin/python +# @lint-avoid-python-3-compatibility-imports +# +# syncsnoop Trace sync() syscall. +# For Linux, uses BCC, eBPF. Embedded C. +# +# Written as a basic example of BCC trace & reformat. See +# examples/hello_world.py for a BCC trace with default output example. +# +# Copyright (c) 2015 Brendan Gregg. +# Licensed under the Apache License, Version 2.0 (the "License") +# +# 13-Aug-2015 Brendan Gregg Created this. + +from __future__ import print_function +from bcc import BPF + +# load BPF program +b = BPF(text=""" +void kprobe__sys_sync(void *ctx) { + bpf_trace_printk("sync()\\n"); +}; +""") + +# header +print("%-18s %s" % ("TIME(s)", "CALL")) + +# format output +while 1: + (task, pid, cpu, flags, ts, msg) = b.trace_fields() + print("%-18.9f %s" % (ts, msg)) diff --git a/tools/syncsnoop.py b/tools/syncsnoop.py index cae57ea8ad33..90dcb2098fec 100755 --- a/tools/syncsnoop.py +++ b/tools/syncsnoop.py @@ -11,21 +11,41 @@ # 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 ctypes as ct # load BPF program b = BPF(text=""" +struct data_t { + u64 ts; +}; + +BPF_PERF_OUTPUT(events); + void kprobe__sys_sync(void *ctx) { - bpf_trace_printk("sync()\\n"); + struct data_t data = {}; + data.ts = bpf_ktime_get_ns() / 1000; + events.perf_submit(ctx, &data, sizeof(data)); }; """) +class Data(ct.Structure): + _fields_ = [ + ("ts", ct.c_ulonglong) + ] + # header print("%-18s %s" % ("TIME(s)", "CALL")) -# format output +# process event +def print_event(cpu, data, size): + event = ct.cast(data, ct.POINTER(Data)).contents + print("%-18.9f sync()" % (float(event.ts) / 1000000)) + +# loop with callback to print_event +b["events"].open_perf_buffer(print_event) while 1: - (task, pid, cpu, flags, ts, msg) = b.trace_fields() - print("%-18.9f %s" % (ts, msg)) + b.kprobe_poll()