Add systemtap/DTrace probes.
authorRichard W.M. Jones <rjones@redhat.com>
Mon, 10 Oct 2011 12:26:15 +0000 (13:26 +0100)
committerRichard W.M. Jones <rjones@redhat.com>
Mon, 10 Oct 2011 12:26:15 +0000 (13:26 +0100)
Mainly this is a documentation change.  However a sample of
DTrace-compatible userspace probes are also added.

README
configure.ac
src/guestfs-internal.h
src/guestfs.pod
src/launch.c

diff --git a/README b/README
index 6b2078e..396c8bb 100644 (file)
--- a/README
+++ b/README
@@ -77,6 +77,9 @@ For basic functionality and the C tools:
 - Berkeley DB 'db_dump' and 'db_load' utilities
   (db4-utils or db4.X-util or similar) (optional)
 
+- systemtap/DTrace userspace probes (optional)
+  http://sourceware.org/systemtap/wiki/AddingUserSpaceProbingToApps
+
 - perldoc (pod2man, pod2text, pod2html) to generate the manual pages
   and other documentation.
 
index 2bd98c6..e0fd7de 100644 (file)
@@ -346,6 +346,11 @@ if test "x$have_libselinux" = "xyes"; then
 fi
 AC_SUBST([SELINUX_LIB])
 
+dnl Check for systemtap/DTrace userspace probes (optional).
+dnl http://sourceware.org/systemtap/wiki/AddingUserSpaceProbingToApps
+AC_CHECK_HEADERS([sys/sdt.h])
+dnl AC_CHECK_PROG([DTRACE],[dtrace],[dtrace],[no])
+
 dnl Check for cpio which isn't in the default Pardus install amazingly.
 AC_CHECK_PROG([CPIO],[cpio],[cpio],[no])
 test "x$CPIO" = "xno" &&
index 494003e..64cf696 100644 (file)
 #define N_(str) str
 #endif
 
+#ifdef HAVE_SYS_SDT_H
+#include <sys/sdt.h>
+/* NB: The 'name' parameter is a literal identifier, NOT a string! */
+#define TRACE0(name) DTRACE_PROBE(guestfs, name)
+#define TRACE1(name, arg1) \
+  DTRACE_PROBE(guestfs, name, (arg1))
+#define TRACE2(name, arg1, arg2) \
+  DTRACE_PROBE(guestfs, name, (arg1), (arg2))
+#define TRACE3(name, arg1, arg2, arg3) \
+  DTRACE_PROBE(guestfs, name, (arg1), (arg2), (arg3))
+#define TRACE4(name, arg1, arg2, arg3, arg4) \
+  DTRACE_PROBE(guestfs, name, (arg1), (arg2), (arg3), (arg4))
+#else
+#define TRACE0(name)
+#define TRACE1(name, arg1)
+#define TRACE2(name, arg1, arg2)
+#define TRACE3(name, arg1, arg2, arg3)
+#define TRACE4(name, arg1, arg2, arg3, arg4)
+#endif
+
 #define TMP_TEMPLATE_ON_STACK(var)                        \
   const char *ttos_tmpdir = guestfs_tmpdir ();            \
   char var[strlen (ttos_tmpdir) + 32];                    \
index 1a5abc6..ada9f1e 100644 (file)
@@ -2165,6 +2165,77 @@ are being deleted, but other manipulations of keys within the loop
 might not terminate unless you also maintain an indication of which
 keys have been visited.
 
+=head1 SYSTEMTAP
+
+The libguestfs C library can be probed using systemtap or DTrace.
+This is true of any library, not just libguestfs.  However libguestfs
+also contains static markers to help in probing internal operations.
+
+You can list all the static markers by doing:
+
+ stap -l 'process("/usr/lib*/libguestfs.so.0")
+              .provider("guestfs").mark("*")'
+
+B<Note:> These static markers are I<not> part of the stable API and
+may change in future versions.
+
+=head2 SYSTEMTAP SCRIPT EXAMPLE
+
+This script contains examples of displaying both the static markers
+and some ordinary C entry points:
+
+ global last;
+ function display_time () {
+       now = gettimeofday_us ();
+       delta = 0;
+       if (last > 0)
+             delta = now - last;
+       last = now;
+       printf ("%d (+%d):", now, delta);
+ }
+ probe begin {
+       last = 0;
+       printf ("ready\n");
+ }
+ /* Display all calls to static markers. */
+ probe process("/usr/lib*/libguestfs.so.0")
+           .provider("guestfs").mark("*") ? {
+       display_time();
+       printf ("\t%s %s\n", $$name, $$parms);
+ }
+ /* Display all calls to guestfs_mkfs* functions. */
+ probe process("/usr/lib*/libguestfs.so.0")
+           .function("guestfs_mkfs*") ? {
+       display_time();
+       printf ("\t%s %s\n", probefunc(), $$parms);
+ }
+
+The script above can be saved to C<test.stap> and run using the
+L<stap(1)> program.  Note that you either have to be root, or you have
+to add yourself to several special stap groups.  Consult the systemtap
+documentation for more information.
+
+ # stap /tmp/test.stap
+ ready
+
+In another terminal, run a guestfish command such as this:
+
+ guestfish -N fs
+
+In the first terminal, stap trace output similar to this is shown:
+
+ 1318248056692655 (+0):        launch_start
+ 1318248056692850 (+195):       launch_build_appliance_start
+ 1318248056818285 (+125435):    launch_build_appliance_end
+ 1318248056838059 (+19774):     launch_run_qemu
+ 1318248061071167 (+4233108):   launch_end
+ 1318248061280324 (+209157):    guestfs_mkfs g=0x1024ab0 fstype=0x46116f device=0x1024e60
+
 =begin html
 
 <!-- old anchor for the next section -->
@@ -3216,6 +3287,7 @@ L<qemu(1)>,
 L<febootstrap(1)>,
 L<febootstrap-supermin-helper(8)>,
 L<hivex(3)>,
+L<stap(1)>,
 L<http://libguestfs.org/>.
 
 Tools with a similar purpose:
index b0f5b39..8e171f7 100644 (file)
@@ -389,6 +389,8 @@ guestfs__launch (guestfs_h *g)
     return -1;
   }
 
+  TRACE0 (launch_start);
+
   /* Make the temporary directory. */
   if (!g->tmpdir) {
     TMP_TEMPLATE_ON_STACK (dir_template);
@@ -439,11 +441,15 @@ launch_appliance (guestfs_h *g)
   gettimeofday (&g->launch_t, NULL);
   guestfs___launch_send_progress (g, 0);
 
+  TRACE0 (launch_build_appliance_start);
+
   /* Locate and/or build the appliance. */
   char *kernel = NULL, *initrd = NULL, *appliance = NULL;
   if (guestfs___build_appliance (g, &kernel, &initrd, &appliance) == -1)
     return -1;
 
+  TRACE0 (launch_build_appliance_end);
+
   guestfs___launch_send_progress (g, 3);
 
   if (g->verbose)
@@ -696,6 +702,8 @@ launch_appliance (guestfs_h *g)
 
     setenv ("LC_ALL", "C", 1);
 
+    TRACE0 (launch_run_qemu);
+
     execv (g->qemu, g->cmdline); /* Run qemu. */
     perror (g->qemu);
     _exit (EXIT_FAILURE);
@@ -825,6 +833,8 @@ launch_appliance (guestfs_h *g)
     goto cleanup1;
   }
 
+  TRACE0 (launch_end);
+
   guestfs___launch_send_progress (g, 12);
 
   return 0;