[libvirt] [PATCH 2/2] Add some DTrace/SystemTAP probes to the RPC code

Daniel P. Berrange berrange at redhat.com
Fri Sep 30 13:54:36 UTC 2011


From: "Daniel P. Berrange" <berrange at 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




More information about the libvir-list mailing list