| #!/usr/bin/env python3 | 
 | # | 
 | # KVM Flight Recorder - ring buffer tracing script | 
 | # | 
 | # Copyright (C) 2012 IBM Corp | 
 | # | 
 | # Author: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> | 
 | # | 
 | # This script provides a command-line interface to kvm ftrace and is designed | 
 | # to be used as a flight recorder that is always running.  To start in-memory | 
 | # recording: | 
 | # | 
 | # sudo kvm_flightrecorder start 8192  # 8 MB per-cpu ring buffers | 
 | # | 
 | # The per-cpu ring buffer size can be given in KB as an optional argument to | 
 | # the 'start' subcommand. | 
 | # | 
 | # To stop the flight recorder: | 
 | # | 
 | # sudo kvm_flightrecorder stop | 
 | # | 
 | # To dump the contents of the flight recorder (this can be done when the | 
 | # recorder is stopped or while it is running): | 
 | # | 
 | # sudo kvm_flightrecorder dump >/path/to/dump.txt | 
 | # | 
 | # To observe the trace while it is running, use the 'tail' subcommand: | 
 | # | 
 | # sudo kvm_flightrecorder tail | 
 | # | 
 | # Note that the flight recorder may impact overall system performance by | 
 | # consuming CPU cycles.  No disk I/O is performed since the ring buffer holds a | 
 | # fixed-size in-memory trace. | 
 |  | 
 | import sys | 
 | import os | 
 |  | 
 | tracing_dir = '/sys/kernel/debug/tracing' | 
 |  | 
 | def trace_path(*args): | 
 |     return os.path.join(tracing_dir, *args) | 
 |  | 
 | def write_file(path, data): | 
 |     open(path, 'wb').write(data) | 
 |  | 
 | def enable_event(subsystem, event, enable): | 
 |     write_file(trace_path('events', subsystem, event, 'enable'), '1' if enable else '0') | 
 |  | 
 | def enable_subsystem(subsystem, enable): | 
 |     write_file(trace_path('events', subsystem, 'enable'), '1' if enable else '0') | 
 |  | 
 | def start_tracing(): | 
 |     enable_subsystem('kvm', True) | 
 |     write_file(trace_path('tracing_on'), '1') | 
 |  | 
 | def stop_tracing(): | 
 |     write_file(trace_path('tracing_on'), '0') | 
 |     enable_subsystem('kvm', False) | 
 |     write_file(trace_path('events', 'enable'), '0') | 
 |     write_file(trace_path('current_tracer'), 'nop') | 
 |  | 
 | def dump_trace(): | 
 |     tracefile = open(trace_path('trace'), 'r') | 
 |     try: | 
 |         lines = True | 
 |         while lines: | 
 |             lines = tracefile.readlines(64 * 1024) | 
 |             sys.stdout.writelines(lines) | 
 |     except KeyboardInterrupt: | 
 |         pass | 
 |  | 
 | def tail_trace(): | 
 |     try: | 
 |         for line in open(trace_path('trace_pipe'), 'r'): | 
 |             sys.stdout.write(line) | 
 |     except KeyboardInterrupt: | 
 |         pass | 
 |  | 
 | def usage(): | 
 |     print('Usage: %s start [buffer_size_kb] | stop | dump | tail' % sys.argv[0]) | 
 |     print('Control the KVM flight recorder tracing.') | 
 |     sys.exit(0) | 
 |  | 
 | def main(): | 
 |     if len(sys.argv) < 2: | 
 |         usage() | 
 |  | 
 |     cmd = sys.argv[1] | 
 |     if cmd == '--version': | 
 |         print('kvm_flightrecorder version 1.0') | 
 |         sys.exit(0) | 
 |  | 
 |     if not os.path.isdir(tracing_dir): | 
 |         print('Unable to tracing debugfs directory, try:') | 
 |         print('mount -t debugfs none /sys/kernel/debug') | 
 |         sys.exit(1) | 
 |     if not os.access(tracing_dir, os.W_OK): | 
 |         print('Unable to write to tracing debugfs directory, please run as root') | 
 |         sys.exit(1) | 
 |  | 
 |     if cmd == 'start': | 
 |         stop_tracing() # clean up first | 
 |  | 
 |         if len(sys.argv) == 3: | 
 |             try: | 
 |                 buffer_size_kb = int(sys.argv[2]) | 
 |             except ValueError: | 
 |                 print('Invalid per-cpu trace buffer size in KB') | 
 |                 sys.exit(1) | 
 |             write_file(trace_path('buffer_size_kb'), str(buffer_size_kb)) | 
 |             print('Per-CPU ring buffer size set to %d KB' % buffer_size_kb) | 
 |  | 
 |         start_tracing() | 
 |         print('KVM flight recorder enabled') | 
 |     elif cmd == 'stop': | 
 |         stop_tracing() | 
 |         print('KVM flight recorder disabled') | 
 |     elif cmd == 'dump': | 
 |         dump_trace() | 
 |     elif cmd == 'tail': | 
 |         tail_trace() | 
 |     else: | 
 |         usage() | 
 |  | 
 | if __name__ == '__main__': | 
 |     sys.exit(main()) |