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