kvm_flightrecorder (3642B)
1 #!/usr/bin/env python3 2 # 3 # KVM Flight Recorder - ring buffer tracing script 4 # 5 # Copyright (C) 2012 IBM Corp 6 # 7 # Author: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> 8 # 9 # This script provides a command-line interface to kvm ftrace and is designed 10 # to be used as a flight recorder that is always running. To start in-memory 11 # recording: 12 # 13 # sudo kvm_flightrecorder start 8192 # 8 MB per-cpu ring buffers 14 # 15 # The per-cpu ring buffer size can be given in KB as an optional argument to 16 # the 'start' subcommand. 17 # 18 # To stop the flight recorder: 19 # 20 # sudo kvm_flightrecorder stop 21 # 22 # To dump the contents of the flight recorder (this can be done when the 23 # recorder is stopped or while it is running): 24 # 25 # sudo kvm_flightrecorder dump >/path/to/dump.txt 26 # 27 # To observe the trace while it is running, use the 'tail' subcommand: 28 # 29 # sudo kvm_flightrecorder tail 30 # 31 # Note that the flight recorder may impact overall system performance by 32 # consuming CPU cycles. No disk I/O is performed since the ring buffer holds a 33 # fixed-size in-memory trace. 34 35 import sys 36 import os 37 38 tracing_dir = '/sys/kernel/debug/tracing' 39 40 def trace_path(*args): 41 return os.path.join(tracing_dir, *args) 42 43 def write_file(path, data): 44 open(path, 'wb').write(data) 45 46 def enable_event(subsystem, event, enable): 47 write_file(trace_path('events', subsystem, event, 'enable'), '1' if enable else '0') 48 49 def enable_subsystem(subsystem, enable): 50 write_file(trace_path('events', subsystem, 'enable'), '1' if enable else '0') 51 52 def start_tracing(): 53 enable_subsystem('kvm', True) 54 write_file(trace_path('tracing_on'), '1') 55 56 def stop_tracing(): 57 write_file(trace_path('tracing_on'), '0') 58 enable_subsystem('kvm', False) 59 write_file(trace_path('events', 'enable'), '0') 60 write_file(trace_path('current_tracer'), 'nop') 61 62 def dump_trace(): 63 tracefile = open(trace_path('trace'), 'r') 64 try: 65 lines = True 66 while lines: 67 lines = tracefile.readlines(64 * 1024) 68 sys.stdout.writelines(lines) 69 except KeyboardInterrupt: 70 pass 71 72 def tail_trace(): 73 try: 74 for line in open(trace_path('trace_pipe'), 'r'): 75 sys.stdout.write(line) 76 except KeyboardInterrupt: 77 pass 78 79 def usage(): 80 print('Usage: %s start [buffer_size_kb] | stop | dump | tail' % sys.argv[0]) 81 print('Control the KVM flight recorder tracing.') 82 sys.exit(0) 83 84 def main(): 85 if len(sys.argv) < 2: 86 usage() 87 88 cmd = sys.argv[1] 89 if cmd == '--version': 90 print('kvm_flightrecorder version 1.0') 91 sys.exit(0) 92 93 if not os.path.isdir(tracing_dir): 94 print('Unable to tracing debugfs directory, try:') 95 print('mount -t debugfs none /sys/kernel/debug') 96 sys.exit(1) 97 if not os.access(tracing_dir, os.W_OK): 98 print('Unable to write to tracing debugfs directory, please run as root') 99 sys.exit(1) 100 101 if cmd == 'start': 102 stop_tracing() # clean up first 103 104 if len(sys.argv) == 3: 105 try: 106 buffer_size_kb = int(sys.argv[2]) 107 except ValueError: 108 print('Invalid per-cpu trace buffer size in KB') 109 sys.exit(1) 110 write_file(trace_path('buffer_size_kb'), str(buffer_size_kb)) 111 print('Per-CPU ring buffer size set to %d KB' % buffer_size_kb) 112 113 start_tracing() 114 print('KVM flight recorder enabled') 115 elif cmd == 'stop': 116 stop_tracing() 117 print('KVM flight recorder disabled') 118 elif cmd == 'dump': 119 dump_trace() 120 elif cmd == 'tail': 121 tail_trace() 122 else: 123 usage() 124 125 if __name__ == '__main__': 126 sys.exit(main())