127 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			127 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | #!/usr/bin/env python | ||
|  | # | ||
|  | # 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()) |