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())
							 |