From: Xinghai Yu <yuxinghai(a)cn.fujitsu.com>
Using the macro exported by configure.ac to decide which trace backend
to build for libvirt.
We got 3 trace macros now:
WITH_TRACE_PROBES, if --with-ftrace or --with-dtrace option was set, this
macro would be true and it tell the codes that we will use trace function,
dtrace or ftrace will be supported in libvirt.
WITH_DTRACE_PROBES, if --with-dtrace was set this macro would be true and
the ftrace will be supported in libvirt.
The ftrace backend code turn on the tracing function of deugfs and
store fd of the ftrace buffer '/sys/kernel/debug/tracing/trace_marker'.
Then let the 'trace_backend_init()' function be called in the initial
process of other programs so that the trace info of them can be transfered
to the ftrace's buffer.
The user can get trace info in interface '/sys/kernel/debug/tracing/trace'.
Signed-off-by: Xinghai Yu <yuxinghai(a)cn.fujitsu.com>
Cc: Eiichi Tsukata <eiichi.tsukata.xh(a)hitachi.com>
---
configure.ac | 24 ++++++++++++--
daemon/Makefile.am | 3 ++
src/Makefile.am | 66 ++++++++++++++++++++++++++++++---------
src/ftrace.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/ftrace.h | 14 +++++++++
tests/Makefile.am | 3 ++
tools/virsh.c | 3 ++
7 files changed, 188 insertions(+), 16 deletions(-)
create mode 100644 src/ftrace.c
create mode 100644 src/ftrace.h
diff --git a/configure.ac b/configure.ac
index 63744ee..6f0992f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1476,6 +1476,25 @@ if test "$with_apparmor" = "no"; then
fi
AM_CONDITIONAL([WITH_APPARMOR_PROFILES], [test "$with_apparmor_profiles" !=
"no"])
+dnl FTrace trace
+AC_ARG_WITH([ftrace],
+ [AS_HELP_STRING([--with-ftrace],
+ [use ftrace for tracing @<:@default=check@:>@])],
+ [],
+ [with_ftrace=check])
+
+if test "$with_ftrace" != "no" ; then
+ if test "$with_linux" = "yes"; then
+ with_ftrace=yes
+ else
+ with_ftrace=no
+ fi
+ if test "$with_ftrace" = "yes"; then
+ AC_DEFINE_UNQUOTED([WITH_FTRACE_PROBES], 1, [whether FTrace are available])
+ fi
+fi
+AM_CONDITIONAL([WITH_FTRACE_PROBES], [test "$with_ftrace" != "no"])
+
dnl DTrace static probes
AC_ARG_WITH([dtrace],
[AS_HELP_STRING([--with-dtrace],
@@ -1500,10 +1519,10 @@ if test "$with_dtrace" != "no" ; then
fi
AM_CONDITIONAL([WITH_DTRACE_PROBES], [test "$with_dtrace" != "no"])
-if test "$with_dtrace" = "yes"; then
+if test "$with_dtrace" = "yes" || test "$with_ftrace" =
"yes"; then
AC_DEFINE_UNQUOTED([WITH_TRACE_PROBES], 1, [whether Trace function are available])
fi
-AM_CONDITIONAL([WITH_TRACE_PROBES], [test "$with_dtrace" != "no"])
+AM_CONDITIONAL([WITH_TRACE_PROBES], [test "$with_dtrace" != "no" ||
test "$with_ftrace" != "no"])
dnl numad
AC_ARG_WITH([numad],
@@ -2856,6 +2875,7 @@ AC_MSG_NOTICE([ Debug: $enable_debug])
AC_MSG_NOTICE([ Use -Werror: $set_werror])
AC_MSG_NOTICE([ Warning Flags: $WARN_CFLAGS])
AC_MSG_NOTICE([ DTrace: $with_dtrace])
+AC_MSG_NOTICE([ FTrace: $with_ftrace])
AC_MSG_NOTICE([ numad: $with_numad])
AC_MSG_NOTICE([ XML Catalog: $XML_CATALOG_FILE])
AC_MSG_NOTICE([ Init script: $with_init_script])
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index bd77623..8637978 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -166,6 +166,9 @@ endif WITH_TRACE_PROBES
if WITH_DTRACE_PROBES
libvirtd_LDADD += ../src/libvirt_probes_dtrace.lo
endif WITH_DTRACE_PROBES
+if WITH_FTRACE_PROBES
+libvirtd_LDADD += ../src/libvirt_ftrace.la
+endif WITH_FTRACE_PROBES
libvirtd_LDADD += \
libvirtd_conf.la \
diff --git a/src/Makefile.am b/src/Makefile.am
index 0e50ebc..6325864 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1979,6 +1979,18 @@ CLEANFILES += libvirt_probes.c libvirt_probes.h libvirt_probes.o
libvirt_probes.
libvirt_qemu_probes.lo
endif
+if WITH_FTRACE_PROBES
+noinst_LTLIBRARIES += libvirt_ftrace.la
+libvirt_la_BUILT_LIBADD += libvirt_ftrace.la
+libvirt_ftrace_la_SOURCES = ftrace.c ftrace.h
+libvirt_ftrace_la_LDFLAGS = $(AM_LDFLAGS)
+libvirt_ftrace_la_CFLAGS = $(AM_CFLAGS)
+BUILT_SOURCES += ftrace.c ftrace.h
+if WITH_QEMU
+libvirt_driver_qemu_impl_la_LIBADD += libvirt_ftrace.la
+endif WITH_QEMU
+endif WITH_FTRACE_PROBES
+
if WITH_DTRACE_PROBES
libvirt_la_BUILT_LIBADD += libvirt_probes_dtrace.lo
libvirt_la_DEPENDENCIES += libvirt_probes_dtrace.o libvirt_probes_dtrace.lo
@@ -2171,6 +2183,9 @@ endif WITH_TRACE_PROBES
if WITH_DTRACE_PROBES
lockd_la_LIBADD += libvirt_probes_dtrace.lo
endif WITH_DTRACE_PROBES
+if WITH_FTRACE_PROBES
+lockd_la_LIBADD += libvirt_ftrace.la
+endif WITH_FTRACE_PROBES
if WITH_QEMU
nodist_conf_DATA += locking/qemu-lockd.conf
BUILT_SOURCES += locking/qemu-lockd.conf
@@ -2203,16 +2218,21 @@ virtlockd_LDFLAGS = \
virtlockd_LDADD = \
libvirt-net-rpc-server.la \
libvirt-net-rpc.la \
- libvirt_util.la \
- ../gnulib/lib/libgnu.la \
- $(CYGWIN_EXTRA_LIBADD) \
- $(NULL)
+ libvirt_util.la
if WITH_TRACE_PROBES
virtlockd_LDADD += libvirt_probes.lo
endif WITH_TRACE_PROBES
if WITH_DTRACE_PROBES
virtlockd_LDADD += libvirt_probes_dtrace.lo
endif WITH_DTRACE_PROBES
+if WITH_FTRACE_PROBES
+virtlockd_LDADD += libvirt_ftrace.la
+endif WITH_FTRACE_PROBES
+# Library 'libgnu.la' must be added last, since functions it provides/replaces
+# are used by 'libvirt_ftrace.la' library.
+virtlockd_LDADD += ../gnulib/lib/libgnu.la \
+ $(CYGWIN_EXTRA_LIBADD) \
+ $(NULL)
else ! WITH_LIBVIRTD
EXTRA_DIST += $(LOCK_DAEMON_SOURCES) \
@@ -2489,15 +2509,19 @@ libvirt_iohelper_LDFLAGS = \
$(AM_LDFLAGS) \
$(PIE_LDFLAGS) \
$(NULL)
-libvirt_iohelper_LDADD = \
- libvirt_util.la \
- ../gnulib/lib/libgnu.la
+libvirt_iohelper_LDADD = libvirt_util.la
if WITH_TRACE_PROBES
libvirt_iohelper_LDADD += libvirt_probes.lo
endif WITH_TRACE_PROBES
if WITH_DTRACE_PROBES
libvirt_iohelper_LDADD += libvirt_probes_dtrace.lo
endif WITH_DTRACE_PROBES
+if WITH_FTRACE_PROBES
+libvirt_iohelper_LDADD += libvirt_ftrace.la
+endif WITH_FTRACE_PROBES
+# Library 'libgnu.la' must be added last, since functions it provides/replaces
+# are used by 'libvirt_ftrace.la' library.
+libvirt_iohelper_LDADD += ../gnulib/lib/libgnu.la
libvirt_iohelper_CFLAGS = \
$(AM_CFLAGS) \
@@ -2516,14 +2540,19 @@ libvirt_parthelper_LDFLAGS = \
$(NULL)
libvirt_parthelper_LDADD = \
$(LIBPARTED_LIBS) \
- libvirt_util.la \
- ../gnulib/lib/libgnu.la
+ libvirt_util.la
if WITH_TRACE_PROBES
libvirt_parthelper_LDADD += libvirt_probes.lo
endif WITH_TRACE_PROBES
if WITH_DTRACE_PROBES
libvirt_parthelper_LDADD += libvirt_probes_dtrace.lo
endif WITH_DTRACE_PROBES
+if WITH_FTRACE_PROBES
+libvirt_parthelper_LDADD += libvirt_ftrace.la
+endif WITH_FTRACE_PROBES
+# Library 'libgnu.la' must be added last, since functions it provides/replaces
+# are used by 'libvirt_ftrace.la' library.
+libvirt_parthelper_LDADD += ../gnulib/lib/libgnu.la
libvirt_parthelper_CFLAGS = \
$(LIBPARTED_CFLAGS) \
@@ -2569,15 +2598,19 @@ libvirt_lxc_LDADD = \
libvirt-net-rpc.la \
libvirt_security_manager.la \
libvirt_conf.la \
- libvirt_util.la \
- ../gnulib/lib/libgnu.la
+ libvirt_util.la
if WITH_TRACE_PROBES
libvirt_lxc_LDADD += libvirt_probes.lo
endif WITH_TRACE_PROBES
if WITH_DTRACE_PROBES
libvirt_lxc_LDADD += libvirt_probes_dtrace.lo
endif WITH_DTRACE_PROBES
-libvirt_lxc_LDADD += $(SECDRIVER_LIBS)
+if WITH_FTRACE_PROBES
+libvirt_lxc_LDADD += libvirt_ftrace.la
+endif WITH_FTRACE_PROBES
+# Library 'libgnu.la' must be added last, since functions it provides/replaces
+# are used by 'libvirt_ftrace.la' library.
+libvirt_lxc_LDADD += ../gnulib/lib/libgnu.la $(SECDRIVER_LIBS)
libvirt_lxc_CFLAGS = \
-I$(top_srcdir)/src/conf \
$(AM_CFLAGS) \
@@ -2607,14 +2640,19 @@ virt_aa_helper_LDFLAGS = \
$(NULL)
virt_aa_helper_LDADD = \
libvirt_conf.la \
- libvirt_util.la \
- ../gnulib/lib/libgnu.la
+ libvirt_util.la
if WITH_TRACE_PROBES
virt_aa_helper_LDADD += libvirt_probes.lo
endif WITH_TRACE_PROBES
if WITH_DTRACE_PROBES
virt_aa_helper_LDADD += libvirt_probes_dtrace.lo
endif WITH_DTRACE_PROBES
+if WITH_FTRACE_PROBES
+virt_aa_helper_LDADD += libvirt_ftrace.la
+endif WITH_FTRACE_PROBES
+# Library 'libgnu.la' must be added last, since functions it provides/replaces
+# are used by 'libvirt_ftrace.la' library.
+virt_aa_helper_LDADD += ../gnulib/lib/libgnu.la
virt_aa_helper_CFLAGS = \
-I$(top_srcdir)/src/conf \
-I$(top_srcdir)/src/security \
diff --git a/src/ftrace.c b/src/ftrace.c
new file mode 100644
index 0000000..a46593f
--- /dev/null
+++ b/src/ftrace.c
@@ -0,0 +1,91 @@
+/*
+ * Ftrace trace backend
+ *
+ * Copyright (C) 2013 Hitachi, Ltd.
+ * Created by Eiichi Tsukata <eiichi.tsukata.xh(a)hitachi.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <sys/unistd.h>
+
+#define _STR(x) #x
+#define STR(x) _STR(x)
+
+int trace_marker_fd;
+bool trace_backend_init(void);
+
+static int find_debugfs(char *debugfs)
+{
+ char type[100];
+ FILE *fp;
+
+ fp = fopen("/proc/mounts", "r");
+ if (fp == NULL) {
+ return 0;
+ }
+
+ while (fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
+ debugfs, type) == 2) {
+ if (strcmp(type, "debugfs") == 0) {
+ break;
+ }
+ }
+ fclose(fp);
+
+ if (strcmp(type, "debugfs") != 0) {
+ return 0;
+ }
+ return 1;
+}
+
+bool trace_backend_init(void)
+{
+ int debugfs_found;
+ int trace_fd = -1;
+ bool ret = true;
+ char *debugfs = malloc(PATH_MAX);
+ char *path = malloc(PATH_MAX);
+
+ debugfs_found = find_debugfs(debugfs);
+ if (debugfs_found) {
+ snprintf(path, PATH_MAX, "%s/tracing/tracing_on", debugfs);
+ trace_fd = open(path, O_WRONLY);
+ if (trace_fd < 0) {
+ perror("Could not open ftrace 'tracing_on' file");
+ ret = false;
+ goto out;
+ } else {
+ if (write(trace_fd, "1", 1) < 0) {
+ perror("Could not write to 'tracing_on' file");
+ close(trace_fd);
+ ret = false;
+ goto out;
+ }
+ close(trace_fd);
+ }
+ snprintf(path, PATH_MAX, "%s/tracing/trace_marker", debugfs);
+ trace_marker_fd = open(path, O_WRONLY);
+ if (trace_marker_fd < 0) {
+ perror("Could not open ftrace 'trace_marker' file");
+ ret = false;
+ goto out;
+ }
+ } else {
+ fprintf(stderr, "debugfs is not mounted\n");
+ ret = false;
+ goto out;
+ }
+out:
+ free(path);
+ free(debugfs);
+ return ret;
+}
diff --git a/src/ftrace.h b/src/ftrace.h
new file mode 100644
index 0000000..0fd88d1
--- /dev/null
+++ b/src/ftrace.h
@@ -0,0 +1,14 @@
+#ifndef TRACE_FTRACE_H
+#define TRACE_FTRACE_H
+
+#include <stdbool.h>
+#include <unistd.h>
+
+/* the buffer size of qemu_monitor is 1024 */
+#define MAX_TRACE_STRLEN 1024
+
+bool trace_backend_init(void);
+
+extern int trace_marker_fd;
+
+#endif
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 8d24cd9..2aa26f5 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -51,6 +51,9 @@ endif WITH_TRACE_PROBES
if WITH_DTRACE_PROBES
PROBES_O += ../src/libvirt_probes_dtrace.lo
endif WITH_DTRACE_PROBES
+if WITH_FTRACE_PROBES
+PROBES_O += ../src/libvirt_ftrace.la
+endif WITH_FTRACE_PROBES
GNULIB_LIBS = \
../gnulib/lib/libgnu.la
diff --git a/tools/virsh.c b/tools/virsh.c
index 2d4aaff..edd41aa 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -3276,6 +3276,9 @@ vshShowVersion(vshControl *ctl ATTRIBUTE_UNUSED)
#ifdef WITH_DTRACE_PROBES
vshPrint(ctl, " DTrace");
#endif
+#ifdef WITH_FTRACE_PROBES
+ vshPrint(ctl, " FTrace");
+#endif
#if WITH_READLINE
vshPrint(ctl, " Readline");
#endif
--
1.8.3.1