From: "Daniel P. Berrange" <berrange(a)redhat.com>
---
daemon/libvirtd.h | 28 +---------------
src/Makefile.am | 28 +++++++++++++++--
src/internal.h | 70 ++++++++++++++++++++++++++++++++++++++++++
src/libvirt.stp | 35 +++++++++++++++++++++
src/probes.d | 7 ++++
src/rpc/virnetclient.c | 13 +++++--
src/rpc/virnetserverclient.c | 9 +++++
7 files changed, 157 insertions(+), 33 deletions(-)
create mode 100644 src/libvirt.stp
create mode 100644 src/probes.d
diff --git a/daemon/libvirtd.h b/daemon/libvirtd.h
index 6d6460e..43f5921 100644
--- a/daemon/libvirtd.h
+++ b/daemon/libvirtd.h
@@ -45,32 +45,8 @@
# include "probes.h"
# endif /* LIBVIRTD_PROBES_H */
-/* Systemtap 1.2 headers have a bug where they cannot handle a
- * variable declared with array type. Work around this by casting all
- * arguments. This is some gross use of the preprocessor because
- * PROBE is a var-arg macro, but it is better than the alternative of
- * making all callers to PROBE have to be aware of the issues. And
- * hopefully, if we ever add a call to PROBE with other than 2 or 3
- * end arguments, you can figure out the pattern to extend this hack.
- */
-# define VIR_COUNT_ARGS(...) VIR_ARG5(__VA_ARGS__, 4, 3, 2, 1)
-# define VIR_ARG5(_1, _2, _3, _4, _5, ...) _5
-# define VIR_ADD_CAST_EXPAND(a, b, ...) VIR_ADD_CAST_PASTE(a, b, __VA_ARGS__)
-# define VIR_ADD_CAST_PASTE(a, b, ...) a##b(__VA_ARGS__)
-
-/* The double cast is necessary to silence gcc warnings; any pointer
- * can safely go to intptr_t and back to void *, which collapses
- * arrays into pointers; while any integer can be widened to intptr_t
- * then cast to void *. */
-# define VIR_ADD_CAST(a) ((void *)(intptr_t)(a))
-# define VIR_ADD_CAST2(a, b) \
- VIR_ADD_CAST(a), VIR_ADD_CAST(b)
-# define VIR_ADD_CAST3(a, b, c) \
- VIR_ADD_CAST(a), VIR_ADD_CAST(b), VIR_ADD_CAST(c)
-
-# define VIR_ADD_CASTS(...) \
- VIR_ADD_CAST_EXPAND(VIR_ADD_CAST, VIR_COUNT_ARGS(__VA_ARGS__), \
- __VA_ARGS__)
+# undef PROBE_EXPAND
+# undef PROBE
# define PROBE_EXPAND(NAME, ARGS) NAME(ARGS)
# define PROBE(NAME, FMT, ...) \
diff --git a/src/Makefile.am b/src/Makefile.am
index 7281802..d974904 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -25,6 +25,9 @@ AM_LDFLAGS = $(COVERAGE_LDFLAGS)
EXTRA_DIST = $(conf_DATA) util/keymaps.csv
BUILT_SOURCES =
+CLEANFILES =
+DISTCLEANFILES =
+MAINTAINERCLEANFILES =
if WITH_NETWORK
UUID=$(shell uuidgen 2>/dev/null)
@@ -1248,6 +1251,25 @@ libvirt_la_CFLAGS = -DIN_LIBVIRT $(AM_CFLAGS)
# picked out for us.
libvirt_la_DEPENDENCIES = $(libvirt_la_BUILT_LIBADD) $(LIBVIRT_SYMBOL_FILE)
+if WITH_DTRACE
+libvirt_la_LIBADD += probes.o
+nodist_libvirt_la_SOURCES = probes.h
+
+BUILT_SOURCES += probes.h
+
+tapsetdir = $(datadir)/systemtap/tapset
+tapset_DATA = libvirt.stp
+
+probes.h: probes.d
+ $(AM_V_GEN)$(DTRACE) -o $@ -h -s $<
+
+probes.o: probes.d
+ $(AM_V_GEN)$(DTRACE) -o $@ -G -s $<
+
+CLEANFILES += probes.h probes.o
+endif
+
+
# Create an automake "convenience library" version of libvirt_la,
# just for testing, since the test harness requires access to internal
# bits and pieces that we don't want to make publicly accessible.
@@ -1549,6 +1571,6 @@ if WITH_NETWORK
endif
rmdir "$(DESTDIR)$(localstatedir)/lib/libvirt" ||:
-CLEANFILES = *.gcov .libs/*.gcda .libs/*.gcno *.gcno *.gcda *.i *.s
-DISTCLEANFILES = $(GENERATED_SYM_FILES)
-MAINTAINERCLEANFILES = $(REMOTE_DRIVER_GENERATED) $(VIR_NET_RPC_GENERATED)
$(ESX_DRIVER_GENERATED)
+CLEANFILES += *.gcov .libs/*.gcda .libs/*.gcno *.gcno *.gcda *.i *.s
+DISTCLEANFILES += $(GENERATED_SYM_FILES)
+MAINTAINERCLEANFILES += $(REMOTE_DRIVER_GENERATED) $(VIR_NET_RPC_GENERATED)
$(ESX_DRIVER_GENERATED)
diff --git a/src/internal.h b/src/internal.h
index 1997031..18867fd 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -242,4 +242,74 @@
/* divide value by size, rounding up */
# define VIR_DIV_UP(value, size) (((value) + (size) - 1) / (size))
+
+# if WITH_DTRACE
+# ifndef LIBVIRT_PROBES_H
+# define LIBVIRT_PROBES_H
+# include "probes.h"
+# endif /* LIBVIRT_PROBES_H */
+
+/* Systemtap 1.2 headers have a bug where they cannot handle a
+ * variable declared with array type. Work around this by casting all
+ * arguments. This is some gross use of the preprocessor because
+ * PROBE is a var-arg macro, but it is better than the alternative of
+ * making all callers to PROBE have to be aware of the issues. And
+ * hopefully, if we ever add a call to PROBE with other than 2 or 3
+ * end arguments, you can figure out the pattern to extend this hack.
+ */
+# define VIR_COUNT_ARGS(...) VIR_ARG9(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1)
+# define VIR_ARG9(_1, _2, _3, _4, _5, _6, _7, _8, _9, ...) _9
+# define VIR_ADD_CAST_EXPAND(a, b, ...) VIR_ADD_CAST_PASTE(a, b, __VA_ARGS__)
+# define VIR_ADD_CAST_PASTE(a, b, ...) a##b(__VA_ARGS__)
+
+/* The double cast is necessary to silence gcc warnings; any pointer
+ * can safely go to intptr_t and back to void *, which collapses
+ * arrays into pointers; while any integer can be widened to intptr_t
+ * then cast to void *. */
+# define VIR_ADD_CAST(a) ((void *)(intptr_t)(a))
+# define VIR_ADD_CAST2(a, b) \
+ VIR_ADD_CAST(a), VIR_ADD_CAST(b)
+# define VIR_ADD_CAST3(a, b, c) \
+ VIR_ADD_CAST(a), VIR_ADD_CAST(b), VIR_ADD_CAST(c)
+# define VIR_ADD_CAST4(a, b, c, d) \
+ VIR_ADD_CAST(a), VIR_ADD_CAST(b), VIR_ADD_CAST(c), \
+ VIR_ADD_CAST(d)
+# define VIR_ADD_CAST5(a, b, c, d, e) \
+ VIR_ADD_CAST(a), VIR_ADD_CAST(b), VIR_ADD_CAST(c), \
+ VIR_ADD_CAST(d), VIR_ADD_CAST(e)
+# define VIR_ADD_CAST6(a, b, c, d, e, f) \
+ VIR_ADD_CAST(a), VIR_ADD_CAST(b), VIR_ADD_CAST(c), \
+ VIR_ADD_CAST(d), VIR_ADD_CAST(e), VIR_ADD_CAST(f)
+# define VIR_ADD_CAST7(a, b, c, d, e, f, g) \
+ VIR_ADD_CAST(a), VIR_ADD_CAST(b), VIR_ADD_CAST(c), \
+ VIR_ADD_CAST(d), VIR_ADD_CAST(e), VIR_ADD_CAST(f), \
+ VIR_ADD_CAST(g)
+# define VIR_ADD_CAST8(a, b, c, d, e, f, g, h) \
+ VIR_ADD_CAST(a), VIR_ADD_CAST(b), VIR_ADD_CAST(c), \
+ VIR_ADD_CAST(d), VIR_ADD_CAST(e), VIR_ADD_CAST(f), \
+ VIR_ADD_CAST(g), VIR_ADD_CAST(h)
+# define VIR_ADD_CAST9(a, b, c, d, e, f, g, h, i) \
+ VIR_ADD_CAST(a), VIR_ADD_CAST(b), VIR_ADD_CAST(c), \
+ VIR_ADD_CAST(d), VIR_ADD_CAST(e), VIR_ADD_CAST(f), \
+ VIR_ADD_CAST(g), VIR_ADD_CAST(h), VIR_ADD_CAST(i)
+
+# define VIR_ADD_CASTS(...) \
+ VIR_ADD_CAST_EXPAND(VIR_ADD_CAST, VIR_COUNT_ARGS(__VA_ARGS__), \
+ __VA_ARGS__)
+
+# define PROBE_EXPAND(NAME, ARGS) NAME(ARGS)
+# define PROBE(NAME, FMT, ...) \
+ VIR_DEBUG_INT("trace." __FILE__ , __func__, __LINE__, \
+ #NAME ": " FMT, __VA_ARGS__); \
+ if (LIBVIRT_ ## NAME ## _ENABLED()) { \
+ PROBE_EXPAND(LIBVIRT_ ## NAME, \
+ VIR_ADD_CASTS(__VA_ARGS__)); \
+ }
+# else
+# define PROBE(NAME, FMT, ...) \
+ VIR_DEBUG_INT("trace." __FILE__, __func__, __LINE__, \
+ #NAME ": " FMT, __VA_ARGS__);
+# endif
+
+
#endif /* __VIR_INTERNAL_H__ */
diff --git a/src/libvirt.stp b/src/libvirt.stp
new file mode 100644
index 0000000..0b8ad14
--- /dev/null
+++ b/src/libvirt.stp
@@ -0,0 +1,35 @@
+probe libvirt.rpc.server_msg_tx =
process("libvirt.so").mark("rpc_server_msg_tx") {
+ prog = $arg1;
+ vers = $arg2;
+ proc = $arg3;
+ type = $arg4;
+ status = $arg5;
+ serial = $arg6;
+}
+
+probe libvirt.rpc.server_msg_rx =
process("libvirt.so").mark("rpc_server_msg_rx") {
+ prog = $arg1;
+ vers = $arg2;
+ proc = $arg3;
+ type = $arg4;
+ status = $arg5;
+ serial = $arg6;
+}
+
+probe libvirt.rpc.client_msg_tx =
process("libvirt.so").mark("rpc_client_msg_tx") {
+ prog = $arg1;
+ vers = $arg2;
+ proc = $arg3;
+ type = $arg4;
+ status = $arg5;
+ serial = $arg6;
+}
+
+probe libvirt.rpc.client_msg_rx =
process("libvirt.so").mark("rpc_client_msg_rx") {
+ prog = $arg1;
+ vers = $arg2;
+ proc = $arg3;
+ type = $arg4;
+ status = $arg5;
+ serial = $arg6;
+}
diff --git a/src/probes.d b/src/probes.d
new file mode 100644
index 0000000..e1f4212
--- /dev/null
+++ b/src/probes.d
@@ -0,0 +1,7 @@
+provider libvirt {
+ probe rpc_server_msg_tx(int prog, int vers, int proc, int type, int status, int
serial);
+ probe rpc_server_msg_rx(int prog, int vers, int proc, int type, int status, int
serial);
+
+ probe rpc_client_msg_tx(int prog, int vers, int proc, int type, int status, int
serial);
+ probe rpc_client_msg_rx(int prog, int vers, int proc, int type, int status, int
serial);
+};
diff --git a/src/rpc/virnetclient.c b/src/rpc/virnetclient.c
index 64f1075..3d81f3c 100644
--- a/src/rpc/virnetclient.c
+++ b/src/rpc/virnetclient.c
@@ -834,10 +834,10 @@ virNetClientCallDispatch(virNetClientPtr client)
if (virNetMessageDecodeHeader(&client->msg) < 0)
return -1;
- VIR_DEBUG("Incoming message prog %d vers %d proc %d type %d status %d serial
%d",
- client->msg.header.prog, client->msg.header.vers,
- client->msg.header.proc, client->msg.header.type,
- client->msg.header.status, client->msg.header.serial);
+ PROBE(RPC_CLIENT_MSG_RX,
+ "prog=%u vers=%u proc=%u type=%u status=%u serial=%u",
+ client->msg.header.prog, client->msg.header.vers,
client->msg.header.proc,
+ client->msg.header.type, client->msg.header.status,
client->msg.header.serial);
if (virKeepAliveCheckMessage(client->keepalive, &client->msg))
return 0;
@@ -1406,6 +1406,11 @@ virNetClientSendInternal(virNetClientPtr client,
virNetClientCallPtr call;
int ret = -1;
+ PROBE(RPC_CLIENT_MSG_TX,
+ "prog=%u vers=%u proc=%u type=%u status=%u serial=%u",
+ msg->header.prog, msg->header.vers, msg->header.proc,
+ msg->header.type, msg->header.status, msg->header.serial);
+
if (expectReply &&
(msg->bufferLength != 0) &&
(msg->header.status == VIR_NET_CONTINUE || dontBlock)) {
diff --git a/src/rpc/virnetserverclient.c b/src/rpc/virnetserverclient.c
index 9bd8914..7474ea3 100644
--- a/src/rpc/virnetserverclient.c
+++ b/src/rpc/virnetserverclient.c
@@ -807,6 +807,11 @@ readmore:
return;
}
+ PROBE(RPC_SERVER_MSG_RX,
+ "prog=%u vers=%u proc=%u type=%u status=%u serial=%u",
+ msg->header.prog, msg->header.vers, msg->header.proc,
+ msg->header.type, msg->header.status, msg->header.serial);
+
/* Maybe send off for queue against a filter */
filter = client->filters;
while (filter) {
@@ -1015,6 +1020,10 @@ int virNetServerClientSendMessage(virNetServerClientPtr client,
virNetServerClientLock(client);
if (client->sock && !client->wantClose) {
+ PROBE(RPC_SERVER_MSG_TX,
+ "prog=%u vers=%u proc=%u type=%u status=%u serial=%u",
+ msg->header.prog, msg->header.vers, msg->header.proc,
+ msg->header.type, msg->header.status, msg->header.serial);
virNetMessageQueuePush(&client->tx, msg);
virNetServerClientUpdateEvent(client);
--
1.7.6.2