kvm_flightrecorder 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #!/usr/bin/env python
  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. from __future__ import print_function
  35. import sys
  36. import os
  37. tracing_dir = '/sys/kernel/debug/tracing'
  38. def trace_path(*args):
  39. return os.path.join(tracing_dir, *args)
  40. def write_file(path, data):
  41. open(path, 'wb').write(data)
  42. def enable_event(subsystem, event, enable):
  43. write_file(trace_path('events', subsystem, event, 'enable'), '1' if enable else '0')
  44. def enable_subsystem(subsystem, enable):
  45. write_file(trace_path('events', subsystem, 'enable'), '1' if enable else '0')
  46. def start_tracing():
  47. enable_subsystem('kvm', True)
  48. write_file(trace_path('tracing_on'), '1')
  49. def stop_tracing():
  50. write_file(trace_path('tracing_on'), '0')
  51. enable_subsystem('kvm', False)
  52. write_file(trace_path('events', 'enable'), '0')
  53. write_file(trace_path('current_tracer'), 'nop')
  54. def dump_trace():
  55. tracefile = open(trace_path('trace'), 'r')
  56. try:
  57. lines = True
  58. while lines:
  59. lines = tracefile.readlines(64 * 1024)
  60. sys.stdout.writelines(lines)
  61. except KeyboardInterrupt:
  62. pass
  63. def tail_trace():
  64. try:
  65. for line in open(trace_path('trace_pipe'), 'r'):
  66. sys.stdout.write(line)
  67. except KeyboardInterrupt:
  68. pass
  69. def usage():
  70. print('Usage: %s start [buffer_size_kb] | stop | dump | tail' % sys.argv[0])
  71. print('Control the KVM flight recorder tracing.')
  72. sys.exit(0)
  73. def main():
  74. if len(sys.argv) < 2:
  75. usage()
  76. cmd = sys.argv[1]
  77. if cmd == '--version':
  78. print('kvm_flightrecorder version 1.0')
  79. sys.exit(0)
  80. if not os.path.isdir(tracing_dir):
  81. print('Unable to tracing debugfs directory, try:')
  82. print('mount -t debugfs none /sys/kernel/debug')
  83. sys.exit(1)
  84. if not os.access(tracing_dir, os.W_OK):
  85. print('Unable to write to tracing debugfs directory, please run as root')
  86. sys.exit(1)
  87. if cmd == 'start':
  88. stop_tracing() # clean up first
  89. if len(sys.argv) == 3:
  90. try:
  91. buffer_size_kb = int(sys.argv[2])
  92. except ValueError:
  93. print('Invalid per-cpu trace buffer size in KB')
  94. sys.exit(1)
  95. write_file(trace_path('buffer_size_kb'), str(buffer_size_kb))
  96. print('Per-CPU ring buffer size set to %d KB' % buffer_size_kb)
  97. start_tracing()
  98. print('KVM flight recorder enabled')
  99. elif cmd == 'stop':
  100. stop_tracing()
  101. print('KVM flight recorder disabled')
  102. elif cmd == 'dump':
  103. dump_trace()
  104. elif cmd == 'tail':
  105. tail_trace()
  106. else:
  107. usage()
  108. if __name__ == '__main__':
  109. sys.exit(main())