Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 00f1762d authored by Ingo Molnar's avatar Ingo Molnar
Browse files

Merge tag 'perf-core-for-mingo' of...

Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux

 into perf/core

Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:

  * Backport libtraceevent plugin support from trace-cmd repository, with
    plugins for jbd2, hrtimer, kmem, kvm, mac80211, sched_switch, function,
    xen, scsi, cfg80211. From Jiri Olsa.

  * Retain bfd reference to lookup source line numbers, greatly optimizing, among
    other use cases, 'perf report -s srcline', from Adrian Hunter.

  * Do not disable source line lookup just because of one failure, from Adrian Hunter.

  * Fix random fd closing with no libelf, from Adrian Hunter.

  * Do not call perf_event__preprocess_sample() twice in 'perf script',
    from Adrian Hunter.

  * Several 'perf kvm' man page corrections, from Dongsheng Yang.

Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents 89e3bbd5 6d65894b
Loading
Loading
Loading
Loading
+64 −7
Original line number Diff line number Diff line
@@ -43,6 +43,30 @@ man_dir_SQ = '$(subst ','\'',$(man_dir))'
export man_dir man_dir_SQ INSTALL
export DESTDIR DESTDIR_SQ

set_plugin_dir := 1

# Set plugin_dir to preffered global plugin location
# If we install under $HOME directory we go under
# $(HOME)/.traceevent/plugins
#
# We dont set PLUGIN_DIR in case we install under $HOME
# directory, because by default the code looks under:
# $(HOME)/.traceevent/plugins by default.
#
ifeq ($(plugin_dir),)
ifeq ($(prefix),$(HOME))
override plugin_dir = $(HOME)/.traceevent/plugins
set_plugin_dir := 0
else
override plugin_dir = $(prefix)/lib/traceevent/plugins
endif
endif

ifeq ($(set_plugin_dir),1)
PLUGIN_DIR = -DPLUGIN_DIR="$(DESTDIR)/$(plugin_dir)"
PLUGIN_DIR_SQ = '$(subst ','\'',$(PLUGIN_DIR))'
endif

# copy a bit from Linux kbuild

ifeq ("$(origin V)", "command line")
@@ -96,6 +120,7 @@ export prefix bindir src obj
# Shell quotes
bindir_SQ = $(subst ','\'',$(bindir))
bindir_relative_SQ = $(subst ','\'',$(bindir_relative))
plugin_dir_SQ = $(subst ','\'',$(plugin_dir))

LIB_FILE = libtraceevent.a libtraceevent.so

@@ -138,10 +163,10 @@ else
  print_app_build =		echo '  BUILD    '$(OBJ);
  print_fpic_compile =		echo '  CC FPIC  '$(OBJ);
  print_shared_lib_compile =	echo '  BUILD    SHARED LIB '$(OBJ);
  print_plugin_obj_compile =	echo '  BUILD    PLUGIN OBJ '$(OBJ);
  print_plugin_obj_compile =	echo '  CC FPIC  '$(OBJ);
  print_plugin_build =		echo '  BUILD    PLUGIN '$(OBJ);
  print_static_lib_build =	echo '  BUILD    STATIC LIB '$(OBJ);
  print_install =		echo '  INSTALL  '$1'	to	$(DESTDIR_SQ)$2';
  print_install =		echo '  INSTALL  '$1;
endif

do_fpic_compile =					\
@@ -180,12 +205,29 @@ $(obj)/%.o: $(src)/%.c
%.o: $(src)/%.c
	$(Q)$(call do_compile)

PEVENT_LIB_OBJS = event-parse.o trace-seq.o parse-filter.o parse-utils.o
PEVENT_LIB_OBJS  = event-parse.o
PEVENT_LIB_OBJS += event-plugin.o
PEVENT_LIB_OBJS += trace-seq.o
PEVENT_LIB_OBJS += parse-filter.o
PEVENT_LIB_OBJS += parse-utils.o
PEVENT_LIB_OBJS += kbuffer-parse.o

ALL_OBJS = $(PEVENT_LIB_OBJS)
PLUGIN_OBJS  = plugin_jbd2.o
PLUGIN_OBJS += plugin_hrtimer.o
PLUGIN_OBJS += plugin_kmem.o
PLUGIN_OBJS += plugin_kvm.o
PLUGIN_OBJS += plugin_mac80211.o
PLUGIN_OBJS += plugin_sched_switch.o
PLUGIN_OBJS += plugin_function.o
PLUGIN_OBJS += plugin_xen.o
PLUGIN_OBJS += plugin_scsi.o
PLUGIN_OBJS += plugin_cfg80211.o

PLUGINS := $(PLUGIN_OBJS:.o=.so)

CMD_TARGETS = $(LIB_FILE)
ALL_OBJS = $(PEVENT_LIB_OBJS) $(PLUGIN_OBJS)

CMD_TARGETS = $(LIB_FILE) $(PLUGINS)

TARGETS = $(CMD_TARGETS)

@@ -200,9 +242,17 @@ libtraceevent.so: $(PEVENT_LIB_OBJS)
libtraceevent.a: $(PEVENT_LIB_OBJS)
	$(Q)$(do_build_static_lib)

plugins: $(PLUGINS)

$(PEVENT_LIB_OBJS): %.o: $(src)/%.c TRACEEVENT-CFLAGS
	$(Q)$(do_fpic_compile)

$(PLUGIN_OBJS): %.o : $(src)/%.c
	$(Q)$(do_compile_plugin_obj)

$(PLUGINS): %.so: %.o
	$(Q)$(do_plugin_build)

define make_version.h
	(echo '/* This file is automatically generated. Do not modify. */';		\
	echo \#define VERSION_CODE $(shell						\
@@ -290,9 +340,16 @@ define do_install
	$(INSTALL) $1 '$(DESTDIR_SQ)$2'
endef

install_lib: all_cmd
install_lib: all_cmd install_plugins
	$(Q)$(call do_install,$(LIB_FILE),$(bindir_SQ))

PLUGINS_INSTALL = $(subst .so,.install,$(PLUGINS))

$(PLUGINS_INSTALL): %.install : %.so force
	$(Q)$(call do_install,$<,$(plugin_dir_SQ))

install_plugins: $(PLUGINS_INSTALL)

install: install_lib

clean:
+35 −21
Original line number Diff line number Diff line
@@ -5121,8 +5121,38 @@ enum pevent_errno __pevent_parse_format(struct event_format **eventp,
	return ret;
}

static enum pevent_errno
__pevent_parse_event(struct pevent *pevent,
		     struct event_format **eventp,
		     const char *buf, unsigned long size,
		     const char *sys)
{
	int ret = __pevent_parse_format(eventp, pevent, buf, size, sys);
	struct event_format *event = *eventp;

	if (event == NULL)
		return ret;

	if (pevent && add_event(pevent, event)) {
		ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
		goto event_add_failed;
	}

#define PRINT_ARGS 0
	if (PRINT_ARGS && event->print_fmt.args)
		print_args(event->print_fmt.args);

	return 0;

event_add_failed:
	pevent_free_format(event);
	return ret;
}

/**
 * pevent_parse_format - parse the event format
 * @pevent: the handle to the pevent
 * @eventp: returned format
 * @buf: the buffer storing the event format string
 * @size: the size of @buf
 * @sys: the system the event belongs to
@@ -5134,10 +5164,12 @@ enum pevent_errno __pevent_parse_format(struct event_format **eventp,
 *
 * /sys/kernel/debug/tracing/events/.../.../format
 */
enum pevent_errno pevent_parse_format(struct event_format **eventp, const char *buf,
enum pevent_errno pevent_parse_format(struct pevent *pevent,
				      struct event_format **eventp,
				      const char *buf,
				      unsigned long size, const char *sys)
{
	return __pevent_parse_format(eventp, NULL, buf, size, sys);
	return __pevent_parse_event(pevent, eventp, buf, size, sys);
}

/**
@@ -5158,25 +5190,7 @@ enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf,
				     unsigned long size, const char *sys)
{
	struct event_format *event = NULL;
	int ret = __pevent_parse_format(&event, pevent, buf, size, sys);

	if (event == NULL)
		return ret;

	if (add_event(pevent, event)) {
		ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
		goto event_add_failed;
	}

#define PRINT_ARGS 0
	if (PRINT_ARGS && event->print_fmt.args)
		print_args(event->print_fmt.args);

	return 0;

event_add_failed:
	pevent_free_format(event);
	return ret;
	return __pevent_parse_event(pevent, &event, buf, size, sys);
}

#undef _PE
+18 −1
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <stdbool.h>
#include <stdarg.h>
#include <regex.h>
#include <string.h>

#ifndef __maybe_unused
#define __maybe_unused __attribute__((unused))
@@ -377,6 +378,11 @@ enum pevent_errno {
};
#undef _PE

struct plugin_list;

struct plugin_list *traceevent_load_plugins(struct pevent *pevent);
void traceevent_unload_plugins(struct plugin_list *plugin_list);

struct cmdline;
struct cmdline_list;
struct func_map;
@@ -522,6 +528,15 @@ __data2host8(struct pevent *pevent, unsigned long long data)
	__data2host8(pevent, __val);				\
})

static inline int traceevent_host_bigendian(void)
{
	unsigned char str[] = { 0x1, 0x2, 0x3, 0x4 };
	unsigned int val;

	memcpy(&val, str, 4);
	return val == 0x01020304;
}

/* taken from kernel/trace/trace.h */
enum trace_flag_type {
	TRACE_FLAG_IRQS_OFF		= 0x01,
@@ -547,7 +562,9 @@ int pevent_parse_header_page(struct pevent *pevent, char *buf, unsigned long siz

enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf,
				     unsigned long size, const char *sys);
enum pevent_errno pevent_parse_format(struct event_format **eventp, const char *buf,
enum pevent_errno pevent_parse_format(struct pevent *pevent,
				      struct event_format **eventp,
				      const char *buf,
				      unsigned long size, const char *sys);
void pevent_free_format(struct event_format *event);

+215 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License (not later!)
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not,  see <http://www.gnu.org/licenses>
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */

#include <string.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include "event-parse.h"
#include "event-utils.h"

#define LOCAL_PLUGIN_DIR ".traceevent/plugins"

struct plugin_list {
	struct plugin_list	*next;
	char			*name;
	void			*handle;
};

static void
load_plugin(struct pevent *pevent, const char *path,
	    const char *file, void *data)
{
	struct plugin_list **plugin_list = data;
	pevent_plugin_load_func func;
	struct plugin_list *list;
	const char *alias;
	char *plugin;
	void *handle;

	plugin = malloc(strlen(path) + strlen(file) + 2);
	if (!plugin) {
		warning("could not allocate plugin memory\n");
		return;
	}

	strcpy(plugin, path);
	strcat(plugin, "/");
	strcat(plugin, file);

	handle = dlopen(plugin, RTLD_NOW | RTLD_GLOBAL);
	if (!handle) {
		warning("could not load plugin '%s'\n%s\n",
			plugin, dlerror());
		goto out_free;
	}

	alias = dlsym(handle, PEVENT_PLUGIN_ALIAS_NAME);
	if (!alias)
		alias = file;

	func = dlsym(handle, PEVENT_PLUGIN_LOADER_NAME);
	if (!func) {
		warning("could not find func '%s' in plugin '%s'\n%s\n",
			PEVENT_PLUGIN_LOADER_NAME, plugin, dlerror());
		goto out_free;
	}

	list = malloc(sizeof(*list));
	if (!list) {
		warning("could not allocate plugin memory\n");
		goto out_free;
	}

	list->next = *plugin_list;
	list->handle = handle;
	list->name = plugin;
	*plugin_list = list;

	pr_stat("registering plugin: %s", plugin);
	func(pevent);
	return;

 out_free:
	free(plugin);
}

static void
load_plugins_dir(struct pevent *pevent, const char *suffix,
		 const char *path,
		 void (*load_plugin)(struct pevent *pevent,
				     const char *path,
				     const char *name,
				     void *data),
		 void *data)
{
	struct dirent *dent;
	struct stat st;
	DIR *dir;
	int ret;

	ret = stat(path, &st);
	if (ret < 0)
		return;

	if (!S_ISDIR(st.st_mode))
		return;

	dir = opendir(path);
	if (!dir)
		return;

	while ((dent = readdir(dir))) {
		const char *name = dent->d_name;

		if (strcmp(name, ".") == 0 ||
		    strcmp(name, "..") == 0)
			continue;

		/* Only load plugins that end in suffix */
		if (strcmp(name + (strlen(name) - strlen(suffix)), suffix) != 0)
			continue;

		load_plugin(pevent, path, name, data);
	}

	closedir(dir);
}

static void
load_plugins(struct pevent *pevent, const char *suffix,
	     void (*load_plugin)(struct pevent *pevent,
				 const char *path,
				 const char *name,
				 void *data),
	     void *data)
{
	char *home;
	char *path;
	char *envdir;

	/*
	 * If a system plugin directory was defined,
	 * check that first.
	 */
#ifdef PLUGIN_DIR
	load_plugins_dir(pevent, suffix, PLUGIN_DIR, load_plugin, data);
#endif

	/*
	 * Next let the environment-set plugin directory
	 * override the system defaults.
	 */
	envdir = getenv("TRACEEVENT_PLUGIN_DIR");
	if (envdir)
		load_plugins_dir(pevent, suffix, envdir, load_plugin, data);

	/*
	 * Now let the home directory override the environment
	 * or system defaults.
	 */
	home = getenv("HOME");
	if (!home)
		return;

	path = malloc(strlen(home) + strlen(LOCAL_PLUGIN_DIR) + 2);
	if (!path) {
		warning("could not allocate plugin memory\n");
		return;
	}

	strcpy(path, home);
	strcat(path, "/");
	strcat(path, LOCAL_PLUGIN_DIR);

	load_plugins_dir(pevent, suffix, path, load_plugin, data);

	free(path);
}

struct plugin_list*
traceevent_load_plugins(struct pevent *pevent)
{
	struct plugin_list *list = NULL;

	load_plugins(pevent, ".so", load_plugin, &list);
	return list;
}

void
traceevent_unload_plugins(struct plugin_list *plugin_list)
{
	pevent_plugin_unload_func func;
	struct plugin_list *list;

	while (plugin_list) {
		list = plugin_list;
		plugin_list = list->next;
		func = dlsym(list->handle, PEVENT_PLUGIN_UNLOADER_NAME);
		if (func)
			func();
		dlclose(list->handle);
		free(list->name);
		free(list);
	}
}
+24 −0
Original line number Diff line number Diff line
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <endian.h>
#include "event-parse.h"

static unsigned long long
process___le16_to_cpup(struct trace_seq *s,
		       unsigned long long *args)
{
	uint16_t *val = (uint16_t *) args[0];
	return val ? (long long) le16toh(*val) : 0;
}

int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
{
	pevent_register_print_function(pevent,
				       process___le16_to_cpup,
				       PEVENT_FUNC_ARG_INT,
				       "__le16_to_cpup",
				       PEVENT_FUNC_ARG_PTR,
				       PEVENT_FUNC_ARG_VOID);
	return 0;
}
Loading