1#!/usr/bin/env python 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 35from __future__ import print_function 36import sys 37import os 38 39tracing_dir = '/sys/kernel/debug/tracing' 40 41def trace_path(*args): 42 return os.path.join(tracing_dir, *args) 43 44def write_file(path, data): 45 open(path, 'wb').write(data) 46 47def enable_event(subsystem, event, enable): 48 write_file(trace_path('events', subsystem, event, 'enable'), '1' if enable else '0') 49 50def enable_subsystem(subsystem, enable): 51 write_file(trace_path('events', subsystem, 'enable'), '1' if enable else '0') 52 53def start_tracing(): 54 enable_subsystem('kvm', True) 55 write_file(trace_path('tracing_on'), '1') 56 57def stop_tracing(): 58 write_file(trace_path('tracing_on'), '0') 59 enable_subsystem('kvm', False) 60 write_file(trace_path('events', 'enable'), '0') 61 write_file(trace_path('current_tracer'), 'nop') 62 63def dump_trace(): 64 tracefile = open(trace_path('trace'), 'r') 65 try: 66 lines = True 67 while lines: 68 lines = tracefile.readlines(64 * 1024) 69 sys.stdout.writelines(lines) 70 except KeyboardInterrupt: 71 pass 72 73def tail_trace(): 74 try: 75 for line in open(trace_path('trace_pipe'), 'r'): 76 sys.stdout.write(line) 77 except KeyboardInterrupt: 78 pass 79 80def usage(): 81 print('Usage: %s start [buffer_size_kb] | stop | dump | tail' % sys.argv[0]) 82 print('Control the KVM flight recorder tracing.') 83 sys.exit(0) 84 85def main(): 86 if len(sys.argv) < 2: 87 usage() 88 89 cmd = sys.argv[1] 90 if cmd == '--version': 91 print('kvm_flightrecorder version 1.0') 92 sys.exit(0) 93 94 if not os.path.isdir(tracing_dir): 95 print('Unable to tracing debugfs directory, try:') 96 print('mount -t debugfs none /sys/kernel/debug') 97 sys.exit(1) 98 if not os.access(tracing_dir, os.W_OK): 99 print('Unable to write to tracing debugfs directory, please run as root') 100 sys.exit(1) 101 102 if cmd == 'start': 103 stop_tracing() # clean up first 104 105 if len(sys.argv) == 3: 106 try: 107 buffer_size_kb = int(sys.argv[2]) 108 except ValueError: 109 print('Invalid per-cpu trace buffer size in KB') 110 sys.exit(1) 111 write_file(trace_path('buffer_size_kb'), str(buffer_size_kb)) 112 print('Per-CPU ring buffer size set to %d KB' % buffer_size_kb) 113 114 start_tracing() 115 print('KVM flight recorder enabled') 116 elif cmd == 'stop': 117 stop_tracing() 118 print('KVM flight recorder disabled') 119 elif cmd == 'dump': 120 dump_trace() 121 elif cmd == 'tail': 122 tail_trace() 123 else: 124 usage() 125 126if __name__ == '__main__': 127 sys.exit(main()) 128