• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Lint as: python2, python3
2"""
3Trace kernel events with Linux Tracing Toolkit (lttng).
4You need to install the lttng patched kernel in order to use the profiler.
5
6Examples:
7    job.profilers.add('lttng', tracepoints = None): enable all trace points.
8    job.profilers.add('lttng', tracepoints = []): disable all trace points.
9    job.profilers.add('lttng', tracepoints = ['kernel_arch_syscall_entry',
10                                              'kernel_arch_syscall_exit'])
11                               will only trace syscall events.
12Take a look at /proc/ltt for the list of the tracing events currently
13supported by lttng and their output formats.
14
15To view the collected traces, copy results/your-test/profiler/lttng
16to a machine that has Linux Tracing Toolkit Viewer (lttv) installed:
17    test$ scp -r results/your-test/profiler/lttng user@localmachine:/home/tmp/
18Then you can examine the traces either in text mode or in GUI:
19    localmachine$ lttv -m textDump -t /home/tmp/lttng
20or
21    localmachine$ lttv-gui -t /home/tmp/lttng &
22"""
23
24from __future__ import absolute_import
25from __future__ import division
26from __future__ import print_function
27
28import os, shutil, time
29
30from autotest_lib.client.bin import utils, profiler
31from autotest_lib.client.common_lib import error
32
33class lttng(profiler.profiler):
34    version = 1
35
36    # http://ltt.polymtl.ca/lttng/ltt-control-0.51-12082008.tar.gz
37    def setup(self, tarball='ltt-control-0.51-12082008.tar.gz', **dargs):
38        self.tarball = utils.unmap_url(self.bindir, tarball, self.tmpdir)
39        utils.extract_tarball_to_dir(self.tarball, self.srcdir)
40        os.chdir(self.srcdir)
41
42        utils.configure()
43        utils.make()
44
45
46    # tracepoints: list of trace points to enable
47    # outputsize: size limit for lttng output file. -1: no limit.
48    def initialize(self, outputsize=1048576, tracepoints=None, **dargs):
49        self.job.require_gcc()
50
51        self.tracepoints = tracepoints
52        self.ltt_bindir = os.path.join(self.srcdir, 'lttctl')
53        self.lttctl = os.path.join(self.ltt_bindir, 'lttctl')
54        self.lttd = os.path.join(self.srcdir, 'lttd', 'lttd')
55        self.armall = os.path.join(self.ltt_bindir, 'ltt-armall')
56        self.disarmall = os.path.join(self.ltt_bindir, 'ltt-disarmall')
57        self.mountpoint = '/mnt/debugfs'
58        self.outputsize = outputsize
59
60        os.putenv('LTT_DAEMON', self.lttd)
61
62        if not os.path.exists(self.mountpoint):
63            os.mkdir(self.mountpoint)
64
65        utils.system('mount -t debugfs debugfs ' + self.mountpoint,
66                                                            ignore_status=True)
67        utils.system('modprobe ltt-control')
68        utils.system('modprobe ltt-statedump')
69        # clean up from any tracing we left running
70        utils.system(self.lttctl + ' -n test -R', ignore_status=True)
71        utils.system(self.disarmall, ignore_status=True)
72
73        if tracepoints is None:
74            utils.system(self.armall, ignore_status=True)
75        else:
76            for tracepoint in self.tracepoints:
77                if tracepoint in ('list_process_state',
78                                  'user_generic_thread_brand', 'fs_exec',
79                                  'kernel_process_fork', 'kernel_process_free',
80                                  'kernel_process_exit',
81                                  'kernel_arch_kthread_create',
82                                  'list_statedump_end', 'list_vm_map'):
83                    channel = 'processes'
84                elif tracepoint in ('list_interrupt',
85                                    'statedump_idt_table',
86                                    'statedump_sys_call_table'):
87                    channel = 'interrupts'
88                elif tracepoint in ('list_network_ipv4_interface',
89                                    'list_network_ip_interface'):
90                    channel = 'network'
91                elif tracepoint in ('kernel_module_load', 'kernel_module_free'):
92                    channel = 'modules'
93                else:
94                    channel = ''
95                print('Connecting ' + tracepoint)
96                utils.write_one_line('/proc/ltt', 'connect ' + tracepoint
97                                     + ' default dynamic ' + channel)
98
99    def start(self, test):
100        self.output = os.path.join(test.profdir, 'lttng')
101        utils.system('%s -n test -d -l %s/ltt -t %s' %
102                                  (self.lttctl, self.mountpoint, self.output))
103
104
105    def stop(self, test):
106        utils.system(self.lttctl + ' -n test -R')
107        time.sleep(10)
108        if self.outputsize != -1:
109            # truncate lttng output file to the specified limit
110            for filename in os.listdir(self.output):
111                file_path = os.path.join(self.output, filename)
112                if os.path.isdir(file_path):
113                    continue
114                size = os.stat(file_path)[6] # grab file size
115                if size > self.outputsize:
116                    f = open(file_path, 'r+')
117                    f.truncate(self.outputsize)
118                    f.close()
119        tarball = os.path.join(test.profdir, 'lttng.tar.bz2')
120        utils.system("tar -cvjf %s -C %s %s" % (tarball, test.profdir, 'lttng'))
121        utils.system('rm -rf ' + self.output)
122