Blame SOURCES/kvm-tools-kvm_stat-move-functions-to-corresponding-class.patch

4a2fec
From 1dbc0659acce676594060b331eb4d854d26eed0c Mon Sep 17 00:00:00 2001
4a2fec
From: David Hildenbrand <david@redhat.com>
4a2fec
Date: Tue, 17 Oct 2017 19:15:52 +0200
4a2fec
Subject: [PATCH 47/69] tools/kvm_stat: move functions to corresponding classes
4a2fec
4a2fec
RH-Author: David Hildenbrand <david@redhat.com>
4a2fec
Message-id: <20171017191605.2378-27-david@redhat.com>
4a2fec
Patchwork-id: 77334
4a2fec
O-Subject: [RHEL-7.5 qemu-kvm-rhev PATCH 26/39] tools/kvm_stat: move functions to corresponding classes
4a2fec
Bugzilla: 1497137
4a2fec
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
4a2fec
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
4a2fec
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
4a2fec
RH-Acked-by: Thomas Huth <thuth@redhat.com>
4a2fec
4a2fec
Upstream-status: linux.git 099a2dfc674e3333bd4ff5e5b106ccd788aa46d7
4a2fec
4a2fec
commit 099a2dfc674e3333bd4ff5e5b106ccd788aa46d7
4a2fec
Author: Stefan Raspl <raspl@linux.vnet.ibm.com>
4a2fec
Date:   Wed Jun 7 21:08:33 2017 +0200
4a2fec
4a2fec
    tools/kvm_stat: move functions to corresponding classes
4a2fec
4a2fec
    Quite a few of the functions are used only in a single class. Moving
4a2fec
    functions accordingly to improve the overall structure.
4a2fec
    Furthermore, introduce a base class for the providers, which might also
4a2fec
    come handy for future extensions.
4a2fec
4a2fec
    Signed-off-by: Stefan Raspl <raspl@linux.vnet.ibm.com>
4a2fec
    Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
4a2fec
4a2fec
Signed-off-by: David Hildenbrand <david@redhat.com>
4a2fec
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
4a2fec
---
4a2fec
 scripts/kvm/kvm_stat | 327 ++++++++++++++++++++++++++-------------------------
4a2fec
 1 file changed, 165 insertions(+), 162 deletions(-)
4a2fec
4a2fec
diff --git a/scripts/kvm/kvm_stat b/scripts/kvm/kvm_stat
4a2fec
index b8522d2..f81ed20 100755
4a2fec
--- a/scripts/kvm/kvm_stat
4a2fec
+++ b/scripts/kvm/kvm_stat
4a2fec
@@ -295,121 +295,6 @@ class ArchS390(Arch):
4a2fec
 ARCH = Arch.get_arch()
4a2fec
 
4a2fec
 
4a2fec
-def is_field_wanted(fields_filter, field):
4a2fec
-    """Indicate whether field is valid according to fields_filter."""
4a2fec
-    if not fields_filter:
4a2fec
-        return True
4a2fec
-    return re.match(fields_filter, field) is not None
4a2fec
-
4a2fec
-
4a2fec
-def walkdir(path):
4a2fec
-    """Returns os.walk() data for specified directory.
4a2fec
-
4a2fec
-    As it is only a wrapper it returns the same 3-tuple of (dirpath,
4a2fec
-    dirnames, filenames).
4a2fec
-    """
4a2fec
-    return next(os.walk(path))
4a2fec
-
4a2fec
-
4a2fec
-def parse_int_list(list_string):
4a2fec
-    """Returns an int list from a string of comma separated integers and
4a2fec
-    integer ranges."""
4a2fec
-    integers = []
4a2fec
-    members = list_string.split(',')
4a2fec
-
4a2fec
-    for member in members:
4a2fec
-        if '-' not in member:
4a2fec
-            integers.append(int(member))
4a2fec
-        else:
4a2fec
-            int_range = member.split('-')
4a2fec
-            integers.extend(range(int(int_range[0]),
4a2fec
-                                  int(int_range[1]) + 1))
4a2fec
-
4a2fec
-    return integers
4a2fec
-
4a2fec
-
4a2fec
-def get_pid_from_gname(gname):
4a2fec
-    """Fuzzy function to convert guest name to QEMU process pid.
4a2fec
-
4a2fec
-    Returns a list of potential pids, can be empty if no match found.
4a2fec
-    Throws an exception on processing errors.
4a2fec
-
4a2fec
-    """
4a2fec
-    pids = []
4a2fec
-    try:
4a2fec
-        child = subprocess.Popen(['ps', '-A', '--format', 'pid,args'],
4a2fec
-                                 stdout=subprocess.PIPE)
4a2fec
-    except:
4a2fec
-        raise Exception
4a2fec
-    for line in child.stdout:
4a2fec
-        line = line.lstrip().split(' ', 1)
4a2fec
-        # perform a sanity check before calling the more expensive
4a2fec
-        # function to possibly extract the guest name
4a2fec
-        if ' -name ' in line[1] and gname == get_gname_from_pid(line[0]):
4a2fec
-            pids.append(int(line[0]))
4a2fec
-    child.stdout.close()
4a2fec
-
4a2fec
-    return pids
4a2fec
-
4a2fec
-
4a2fec
-def get_gname_from_pid(pid):
4a2fec
-    """Returns the guest name for a QEMU process pid.
4a2fec
-
4a2fec
-    Extracts the guest name from the QEMU comma line by processing the '-name'
4a2fec
-    option. Will also handle names specified out of sequence.
4a2fec
-
4a2fec
-    """
4a2fec
-    name = ''
4a2fec
-    try:
4a2fec
-        line = open('/proc/{}/cmdline'.format(pid), 'rb').read().split('\0')
4a2fec
-        parms = line[line.index('-name') + 1].split(',')
4a2fec
-        while '' in parms:
4a2fec
-            # commas are escaped (i.e. ',,'), hence e.g. 'foo,bar' results in
4a2fec
-            # ['foo', '', 'bar'], which we revert here
4a2fec
-            idx = parms.index('')
4a2fec
-            parms[idx - 1] += ',' + parms[idx + 1]
4a2fec
-            del parms[idx:idx+2]
4a2fec
-        # the '-name' switch allows for two ways to specify the guest name,
4a2fec
-        # where the plain name overrides the name specified via 'guest='
4a2fec
-        for arg in parms:
4a2fec
-            if '=' not in arg:
4a2fec
-                name = arg
4a2fec
-                break
4a2fec
-            if arg[:6] == 'guest=':
4a2fec
-                name = arg[6:]
4a2fec
-    except (ValueError, IOError, IndexError):
4a2fec
-        pass
4a2fec
-
4a2fec
-    return name
4a2fec
-
4a2fec
-
4a2fec
-def get_online_cpus():
4a2fec
-    """Returns a list of cpu id integers."""
4a2fec
-    with open('/sys/devices/system/cpu/online') as cpu_list:
4a2fec
-        cpu_string = cpu_list.readline()
4a2fec
-        return parse_int_list(cpu_string)
4a2fec
-
4a2fec
-
4a2fec
-def get_filters():
4a2fec
-    """Returns a dict of trace events, their filter ids and
4a2fec
-    the values that can be filtered.
4a2fec
-
4a2fec
-    Trace events can be filtered for special values by setting a
4a2fec
-    filter string via an ioctl. The string normally has the format
4a2fec
-    identifier==value. For each filter a new event will be created, to
4a2fec
-    be able to distinguish the events.
4a2fec
-
4a2fec
-    """
4a2fec
-    filters = {}
4a2fec
-    filters['kvm_userspace_exit'] = ('reason', USERSPACE_EXIT_REASONS)
4a2fec
-    if ARCH.exit_reasons:
4a2fec
-        filters['kvm_exit'] = ('exit_reason', ARCH.exit_reasons)
4a2fec
-    return filters
4a2fec
-
4a2fec
-libc = ctypes.CDLL('libc.so.6', use_errno=True)
4a2fec
-syscall = libc.syscall
4a2fec
-
4a2fec
-
4a2fec
 class perf_event_attr(ctypes.Structure):
4a2fec
     """Struct that holds the necessary data to set up a trace event.
4a2fec
 
4a2fec
@@ -439,25 +324,6 @@ class perf_event_attr(ctypes.Structure):
4a2fec
         self.read_format = PERF_FORMAT_GROUP
4a2fec
 
4a2fec
 
4a2fec
-def perf_event_open(attr, pid, cpu, group_fd, flags):
4a2fec
-    """Wrapper for the sys_perf_evt_open() syscall.
4a2fec
-
4a2fec
-    Used to set up performance events, returns a file descriptor or -1
4a2fec
-    on error.
4a2fec
-
4a2fec
-    Attributes are:
4a2fec
-    - syscall number
4a2fec
-    - struct perf_event_attr *
4a2fec
-    - pid or -1 to monitor all pids
4a2fec
-    - cpu number or -1 to monitor all cpus
4a2fec
-    - The file descriptor of the group leader or -1 to create a group.
4a2fec
-    - flags
4a2fec
-
4a2fec
-    """
4a2fec
-    return syscall(ARCH.sc_perf_evt_open, ctypes.pointer(attr),
4a2fec
-                   ctypes.c_int(pid), ctypes.c_int(cpu),
4a2fec
-                   ctypes.c_int(group_fd), ctypes.c_long(flags))
4a2fec
-
4a2fec
 PERF_TYPE_TRACEPOINT = 2
4a2fec
 PERF_FORMAT_GROUP = 1 << 3
4a2fec
 
4a2fec
@@ -502,6 +368,8 @@ class Event(object):
4a2fec
     """Represents a performance event and manages its life cycle."""
4a2fec
     def __init__(self, name, group, trace_cpu, trace_pid, trace_point,
4a2fec
                  trace_filter, trace_set='kvm'):
4a2fec
+        self.libc = ctypes.CDLL('libc.so.6', use_errno=True)
4a2fec
+        self.syscall = self.libc.syscall
4a2fec
         self.name = name
4a2fec
         self.fd = None
4a2fec
         self.setup_event(group, trace_cpu, trace_pid, trace_point,
4a2fec
@@ -518,6 +386,25 @@ class Event(object):
4a2fec
         if self.fd:
4a2fec
             os.close(self.fd)
4a2fec
 
4a2fec
+    def perf_event_open(self, attr, pid, cpu, group_fd, flags):
4a2fec
+        """Wrapper for the sys_perf_evt_open() syscall.
4a2fec
+
4a2fec
+        Used to set up performance events, returns a file descriptor or -1
4a2fec
+        on error.
4a2fec
+
4a2fec
+        Attributes are:
4a2fec
+        - syscall number
4a2fec
+        - struct perf_event_attr *
4a2fec
+        - pid or -1 to monitor all pids
4a2fec
+        - cpu number or -1 to monitor all cpus
4a2fec
+        - The file descriptor of the group leader or -1 to create a group.
4a2fec
+        - flags
4a2fec
+
4a2fec
+        """
4a2fec
+        return self.syscall(ARCH.sc_perf_evt_open, ctypes.pointer(attr),
4a2fec
+                            ctypes.c_int(pid), ctypes.c_int(cpu),
4a2fec
+                            ctypes.c_int(group_fd), ctypes.c_long(flags))
4a2fec
+
4a2fec
     def setup_event_attribute(self, trace_set, trace_point):
4a2fec
         """Returns an initialized ctype perf_event_attr struct."""
4a2fec
 
4a2fec
@@ -546,8 +433,8 @@ class Event(object):
4a2fec
         if group.events:
4a2fec
             group_leader = group.events[0].fd
4a2fec
 
4a2fec
-        fd = perf_event_open(event_attr, trace_pid,
4a2fec
-                             trace_cpu, group_leader, 0)
4a2fec
+        fd = self.perf_event_open(event_attr, trace_pid,
4a2fec
+                                  trace_cpu, group_leader, 0)
4a2fec
         if fd == -1:
4a2fec
             err = ctypes.get_errno()
4a2fec
             raise OSError(err, os.strerror(err),
4a2fec
@@ -582,7 +469,26 @@ class Event(object):
4a2fec
         fcntl.ioctl(self.fd, ARCH.ioctl_numbers['RESET'], 0)
4a2fec
 
4a2fec
 
4a2fec
-class TracepointProvider(object):
4a2fec
+class Provider(object):
4a2fec
+    """Encapsulates functionalities used by all providers."""
4a2fec
+    @staticmethod
4a2fec
+    def is_field_wanted(fields_filter, field):
4a2fec
+        """Indicate whether field is valid according to fields_filter."""
4a2fec
+        if not fields_filter:
4a2fec
+            return True
4a2fec
+        return re.match(fields_filter, field) is not None
4a2fec
+
4a2fec
+    @staticmethod
4a2fec
+    def walkdir(path):
4a2fec
+        """Returns os.walk() data for specified directory.
4a2fec
+
4a2fec
+        As it is only a wrapper it returns the same 3-tuple of (dirpath,
4a2fec
+        dirnames, filenames).
4a2fec
+        """
4a2fec
+        return next(os.walk(path))
4a2fec
+
4a2fec
+
4a2fec
+class TracepointProvider(Provider):
4a2fec
     """Data provider for the stats class.
4a2fec
 
4a2fec
     Manages the events/groups from which it acquires its data.
4a2fec
@@ -590,10 +496,27 @@ class TracepointProvider(object):
4a2fec
     """
4a2fec
     def __init__(self, pid, fields_filter):
4a2fec
         self.group_leaders = []
4a2fec
-        self.filters = get_filters()
4a2fec
+        self.filters = self.get_filters()
4a2fec
         self.update_fields(fields_filter)
4a2fec
         self.pid = pid
4a2fec
 
4a2fec
+    @staticmethod
4a2fec
+    def get_filters():
4a2fec
+        """Returns a dict of trace events, their filter ids and
4a2fec
+        the values that can be filtered.
4a2fec
+
4a2fec
+        Trace events can be filtered for special values by setting a
4a2fec
+        filter string via an ioctl. The string normally has the format
4a2fec
+        identifier==value. For each filter a new event will be created, to
4a2fec
+        be able to distinguish the events.
4a2fec
+
4a2fec
+        """
4a2fec
+        filters = {}
4a2fec
+        filters['kvm_userspace_exit'] = ('reason', USERSPACE_EXIT_REASONS)
4a2fec
+        if ARCH.exit_reasons:
4a2fec
+            filters['kvm_exit'] = ('exit_reason', ARCH.exit_reasons)
4a2fec
+        return filters
4a2fec
+
4a2fec
     def get_available_fields(self):
4a2fec
         """Returns a list of available event's of format 'event name(filter
4a2fec
         name)'.
4a2fec
@@ -610,7 +533,7 @@ class TracepointProvider(object):
4a2fec
 
4a2fec
         """
4a2fec
         path = os.path.join(PATH_DEBUGFS_TRACING, 'events', 'kvm')
4a2fec
-        fields = walkdir(path)[1]
4a2fec
+        fields = self.walkdir(path)[1]
4a2fec
         extra = []
4a2fec
         for field in fields:
4a2fec
             if field in self.filters:
4a2fec
@@ -623,7 +546,30 @@ class TracepointProvider(object):
4a2fec
     def update_fields(self, fields_filter):
4a2fec
         """Refresh fields, applying fields_filter"""
4a2fec
         self._fields = [field for field in self.get_available_fields()
4a2fec
-                        if is_field_wanted(fields_filter, field)]
4a2fec
+                        if self.is_field_wanted(fields_filter, field)]
4a2fec
+
4a2fec
+    @staticmethod
4a2fec
+    def get_online_cpus():
4a2fec
+        """Returns a list of cpu id integers."""
4a2fec
+        def parse_int_list(list_string):
4a2fec
+            """Returns an int list from a string of comma separated integers and
4a2fec
+            integer ranges."""
4a2fec
+            integers = []
4a2fec
+            members = list_string.split(',')
4a2fec
+
4a2fec
+            for member in members:
4a2fec
+                if '-' not in member:
4a2fec
+                    integers.append(int(member))
4a2fec
+                else:
4a2fec
+                    int_range = member.split('-')
4a2fec
+                    integers.extend(range(int(int_range[0]),
4a2fec
+                                          int(int_range[1]) + 1))
4a2fec
+
4a2fec
+            return integers
4a2fec
+
4a2fec
+        with open('/sys/devices/system/cpu/online') as cpu_list:
4a2fec
+            cpu_string = cpu_list.readline()
4a2fec
+            return parse_int_list(cpu_string)
4a2fec
 
4a2fec
     def setup_traces(self):
4a2fec
         """Creates all event and group objects needed to be able to retrieve
4a2fec
@@ -633,9 +579,9 @@ class TracepointProvider(object):
4a2fec
             # Fetch list of all threads of the monitored pid, as qemu
4a2fec
             # starts a thread for each vcpu.
4a2fec
             path = os.path.join('/proc', str(self._pid), 'task')
4a2fec
-            groupids = walkdir(path)[1]
4a2fec
+            groupids = self.walkdir(path)[1]
4a2fec
         else:
4a2fec
-            groupids = get_online_cpus()
4a2fec
+            groupids = self.get_online_cpus()
4a2fec
 
4a2fec
         # The constant is needed as a buffer for python libs, std
4a2fec
         # streams and other files that the script opens.
4a2fec
@@ -732,7 +678,7 @@ class TracepointProvider(object):
4a2fec
                 event.reset()
4a2fec
 
4a2fec
 
4a2fec
-class DebugfsProvider(object):
4a2fec
+class DebugfsProvider(Provider):
4a2fec
     """Provides data from the files that KVM creates in the kvm debugfs
4a2fec
     folder."""
4a2fec
     def __init__(self, pid, fields_filter):
4a2fec
@@ -748,12 +694,12 @@ class DebugfsProvider(object):
4a2fec
         The fields are all available KVM debugfs files
4a2fec
 
4a2fec
         """
4a2fec
-        return walkdir(PATH_DEBUGFS_KVM)[2]
4a2fec
+        return self.walkdir(PATH_DEBUGFS_KVM)[2]
4a2fec
 
4a2fec
     def update_fields(self, fields_filter):
4a2fec
         """Refresh fields, applying fields_filter"""
4a2fec
         self._fields = [field for field in self.get_available_fields()
4a2fec
-                        if is_field_wanted(fields_filter, field)]
4a2fec
+                        if self.is_field_wanted(fields_filter, field)]
4a2fec
 
4a2fec
     @property
4a2fec
     def fields(self):
4a2fec
@@ -772,7 +718,7 @@ class DebugfsProvider(object):
4a2fec
     def pid(self, pid):
4a2fec
         self._pid = pid
4a2fec
         if pid != 0:
4a2fec
-            vms = walkdir(PATH_DEBUGFS_KVM)[1]
4a2fec
+            vms = self.walkdir(PATH_DEBUGFS_KVM)[1]
4a2fec
             if len(vms) == 0:
4a2fec
                 self.do_read = False
4a2fec
 
4a2fec
@@ -834,11 +780,23 @@ class Stats(object):
4a2fec
 
4a2fec
     """
4a2fec
     def __init__(self, options):
4a2fec
-        self.providers = get_providers(options)
4a2fec
+        self.providers = self.get_providers(options)
4a2fec
         self._pid_filter = options.pid
4a2fec
         self._fields_filter = options.fields
4a2fec
         self.values = {}
4a2fec
 
4a2fec
+    @staticmethod
4a2fec
+    def get_providers(options):
4a2fec
+        """Returns a list of data providers depending on the passed options."""
4a2fec
+        providers = []
4a2fec
+
4a2fec
+        if options.debugfs:
4a2fec
+            providers.append(DebugfsProvider(options.pid, options.fields))
4a2fec
+        if options.tracepoints or not providers:
4a2fec
+            providers.append(TracepointProvider(options.pid, options.fields))
4a2fec
+
4a2fec
+        return providers
4a2fec
+
4a2fec
     def update_provider_filters(self):
4a2fec
         """Propagates fields filters to providers."""
4a2fec
         # As we reset the counters when updating the fields we can
4a2fec
@@ -933,6 +891,63 @@ class Tui(object):
4a2fec
             curses.nocbreak()
4a2fec
             curses.endwin()
4a2fec
 
4a2fec
+    @staticmethod
4a2fec
+    def get_pid_from_gname(gname):
4a2fec
+        """Fuzzy function to convert guest name to QEMU process pid.
4a2fec
+
4a2fec
+        Returns a list of potential pids, can be empty if no match found.
4a2fec
+        Throws an exception on processing errors.
4a2fec
+
4a2fec
+        """
4a2fec
+        pids = []
4a2fec
+        try:
4a2fec
+            child = subprocess.Popen(['ps', '-A', '--format', 'pid,args'],
4a2fec
+                                     stdout=subprocess.PIPE)
4a2fec
+        except:
4a2fec
+            raise Exception
4a2fec
+        for line in child.stdout:
4a2fec
+            line = line.lstrip().split(' ', 1)
4a2fec
+            # perform a sanity check before calling the more expensive
4a2fec
+            # function to possibly extract the guest name
4a2fec
+            if (' -name ' in line[1] and
4a2fec
+                    gname == self.get_gname_from_pid(line[0])):
4a2fec
+                pids.append(int(line[0]))
4a2fec
+        child.stdout.close()
4a2fec
+
4a2fec
+        return pids
4a2fec
+
4a2fec
+    @staticmethod
4a2fec
+    def get_gname_from_pid(pid):
4a2fec
+        """Returns the guest name for a QEMU process pid.
4a2fec
+
4a2fec
+        Extracts the guest name from the QEMU comma line by processing the
4a2fec
+        '-name' option. Will also handle names specified out of sequence.
4a2fec
+
4a2fec
+        """
4a2fec
+        name = ''
4a2fec
+        try:
4a2fec
+            line = open('/proc/{}/cmdline'
4a2fec
+                        .format(pid), 'rb').read().split('\0')
4a2fec
+            parms = line[line.index('-name') + 1].split(',')
4a2fec
+            while '' in parms:
4a2fec
+                # commas are escaped (i.e. ',,'), hence e.g. 'foo,bar' results
4a2fec
+                # in # ['foo', '', 'bar'], which we revert here
4a2fec
+                idx = parms.index('')
4a2fec
+                parms[idx - 1] += ',' + parms[idx + 1]
4a2fec
+                del parms[idx:idx+2]
4a2fec
+            # the '-name' switch allows for two ways to specify the guest name,
4a2fec
+            # where the plain name overrides the name specified via 'guest='
4a2fec
+            for arg in parms:
4a2fec
+                if '=' not in arg:
4a2fec
+                    name = arg
4a2fec
+                    break
4a2fec
+                if arg[:6] == 'guest=':
4a2fec
+                    name = arg[6:]
4a2fec
+        except (ValueError, IOError, IndexError):
4a2fec
+            pass
4a2fec
+
4a2fec
+        return name
4a2fec
+
4a2fec
     def update_drilldown(self):
4a2fec
         """Sets or removes a filter that only allows fields without braces."""
4a2fec
         if not self.stats.fields_filter:
4a2fec
@@ -950,7 +965,7 @@ class Tui(object):
4a2fec
         if pid is None:
4a2fec
             pid = self.stats.pid_filter
4a2fec
         self.screen.erase()
4a2fec
-        gname = get_gname_from_pid(pid)
4a2fec
+        gname = self.get_gname_from_pid(pid)
4a2fec
         if gname:
4a2fec
             gname = ('({})'.format(gname[:MAX_GUEST_NAME_LEN] + '...'
4a2fec
                                    if len(gname) > MAX_GUEST_NAME_LEN
4a2fec
@@ -1096,7 +1111,7 @@ class Tui(object):
4a2fec
             else:
4a2fec
                 pids = []
4a2fec
                 try:
4a2fec
-                    pids = get_pid_from_gname(gname)
4a2fec
+                    pids = self.get_pid_from_gname(gname)
4a2fec
                 except:
4a2fec
                     msg = '"' + gname + '": Internal error while searching, ' \
4a2fec
                           'use pid filter instead'
4a2fec
@@ -1229,7 +1244,7 @@ Press any other key to refresh statistics immediately.
4a2fec
 
4a2fec
     def cb_guest_to_pid(option, opt, val, parser):
4a2fec
         try:
4a2fec
-            pids = get_pid_from_gname(val)
4a2fec
+            pids = Tui.get_pid_from_gname(val)
4a2fec
         except:
4a2fec
             raise optparse.OptionValueError('Error while searching for guest '
4a2fec
                                             '"{}", use "-p" to specify a pid '
4a2fec
@@ -1294,18 +1309,6 @@ Press any other key to refresh statistics immediately.
4a2fec
     return options
4a2fec
 
4a2fec
 
4a2fec
-def get_providers(options):
4a2fec
-    """Returns a list of data providers depending on the passed options."""
4a2fec
-    providers = []
4a2fec
-
4a2fec
-    if options.debugfs:
4a2fec
-        providers.append(DebugfsProvider(options.pid, options.fields))
4a2fec
-    if options.tracepoints or not providers:
4a2fec
-        providers.append(TracepointProvider(options.pid, options.fields))
4a2fec
-
4a2fec
-    return providers
4a2fec
-
4a2fec
-
4a2fec
 def check_access(options):
4a2fec
     """Exits if the current user can't access all needed directories."""
4a2fec
     if not os.path.exists('/sys/kernel/debug'):
4a2fec
-- 
4a2fec
1.8.3.1
4a2fec