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