]>
Commit | Line | Data |
---|---|---|
b3c09bde SH |
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 <[email protected]> | |
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 | ||
35 | import sys | |
36 | import os | |
37 | ||
38 | tracing_dir = '/sys/kernel/debug/tracing' | |
39 | ||
40 | def trace_path(*args): | |
41 | return os.path.join(tracing_dir, *args) | |
42 | ||
43 | def write_file(path, data): | |
44 | open(path, 'wb').write(data) | |
45 | ||
46 | def enable_event(subsystem, event, enable): | |
47 | write_file(trace_path('events', subsystem, event, 'enable'), '1' if enable else '0') | |
48 | ||
49 | def enable_subsystem(subsystem, enable): | |
50 | write_file(trace_path('events', subsystem, 'enable'), '1' if enable else '0') | |
51 | ||
52 | def start_tracing(): | |
53 | enable_subsystem('kvm', True) | |
54 | write_file(trace_path('tracing_on'), '1') | |
55 | ||
56 | def 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 | ||
62 | def 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 | ||
72 | def 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 | ||
79 | def 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 | ||
84 | def 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 | ||
125 | if __name__ == '__main__': | |
126 | sys.exit(main()) |