2012-03-09 15:13:40 +01:00
|
|
|
#!/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.
|
|
|
|
|
2018-06-08 14:29:43 +02:00
|
|
|
from __future__ import print_function
|
2012-03-09 15:13:40 +01:00
|
|
|
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():
|
2018-06-08 14:29:43 +02:00
|
|
|
print('Usage: %s start [buffer_size_kb] | stop | dump | tail' % sys.argv[0])
|
|
|
|
print('Control the KVM flight recorder tracing.')
|
2012-03-09 15:13:40 +01:00
|
|
|
sys.exit(0)
|
|
|
|
|
|
|
|
def main():
|
|
|
|
if len(sys.argv) < 2:
|
|
|
|
usage()
|
|
|
|
|
|
|
|
cmd = sys.argv[1]
|
|
|
|
if cmd == '--version':
|
2018-06-08 14:29:43 +02:00
|
|
|
print('kvm_flightrecorder version 1.0')
|
2012-03-09 15:13:40 +01:00
|
|
|
sys.exit(0)
|
|
|
|
|
|
|
|
if not os.path.isdir(tracing_dir):
|
2018-06-08 14:29:43 +02:00
|
|
|
print('Unable to tracing debugfs directory, try:')
|
|
|
|
print('mount -t debugfs none /sys/kernel/debug')
|
2012-03-09 15:13:40 +01:00
|
|
|
sys.exit(1)
|
|
|
|
if not os.access(tracing_dir, os.W_OK):
|
2018-06-08 14:29:43 +02:00
|
|
|
print('Unable to write to tracing debugfs directory, please run as root')
|
2012-03-09 15:13:40 +01:00
|
|
|
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:
|
2018-06-08 14:29:43 +02:00
|
|
|
print('Invalid per-cpu trace buffer size in KB')
|
2012-03-09 15:13:40 +01:00
|
|
|
sys.exit(1)
|
|
|
|
write_file(trace_path('buffer_size_kb'), str(buffer_size_kb))
|
2018-06-08 14:29:43 +02:00
|
|
|
print('Per-CPU ring buffer size set to %d KB' % buffer_size_kb)
|
2012-03-09 15:13:40 +01:00
|
|
|
|
|
|
|
start_tracing()
|
2018-06-08 14:29:43 +02:00
|
|
|
print('KVM flight recorder enabled')
|
2012-03-09 15:13:40 +01:00
|
|
|
elif cmd == 'stop':
|
|
|
|
stop_tracing()
|
2018-06-08 14:29:43 +02:00
|
|
|
print('KVM flight recorder disabled')
|
2012-03-09 15:13:40 +01:00
|
|
|
elif cmd == 'dump':
|
|
|
|
dump_trace()
|
|
|
|
elif cmd == 'tail':
|
|
|
|
tail_trace()
|
|
|
|
else:
|
|
|
|
usage()
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
sys.exit(main())
|