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