debug: add "ringbuf" backend logging to a ringbuffer
authorRalph Boehme <slow@samba.org>
Sat, 7 Jan 2017 13:36:24 +0000 (14:36 +0100)
committerVolker Lendecke <vl@samba.org>
Fri, 20 Jan 2017 17:48:25 +0000 (18:48 +0100)
This is useful for debugging bugs that involve timing effects and are
not reproducible when logging at higher debug levels with the file
backend.

The log can be dumped to a file with gdb:

(gdb) dump binary memory samba.log debug_ringbuf debug_ringbuf+SIZE

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
docs-xml/smbdotconf/logging/logging.xml
lib/util/debug.c
lib/util/debug.h

index 8524884bbffd1c26542573b3e93ddc2bb1f27faf..b152d0c469e83f682418595992353f9d861a6cca 100644 (file)
     <listitem><para><parameter moreinfo="none">systemd</parameter></para></listitem>
     <listitem><para><parameter moreinfo="none">lttng</parameter></para></listitem>
     <listitem><para><parameter moreinfo="none">gpfs</parameter></para></listitem>
+    <listitem><para><parameter moreinfo="none">ringbuf</parameter></para></listitem>
   </itemizedlist>
 
+  <para>The <parameter moreinfo="none">ringbuf</parameter> backend supports an
+  optional size argument to change the buffer size used, the default is 1 MB:
+  <parameter moreinfo="none">ringbuf:size=NBYTES</parameter></para>
+
 </description>
 <value type="default"></value>
 <value type="example">syslog@1 file</value>
index 12a9b1bcaaaf8fad17830ba8a15857b74e1e46a8..08954c30fdeaee200a672403af4898ab2eb275a4 100644 (file)
@@ -236,6 +236,84 @@ static void debug_gpfs_log(int msg_level,
 }
 #endif /* HAVE_GPFS */
 
+#define DEBUG_RINGBUF_SIZE (1024 * 1024)
+#define DEBUG_RINGBUF_SIZE_OPT "size="
+
+static char *debug_ringbuf;
+static size_t debug_ringbuf_size;
+static size_t debug_ringbuf_ofs;
+
+/* We ensure in debug_ringbuf_log() that this is always \0 terminated */
+char *debug_get_ringbuf(void)
+{
+       return debug_ringbuf;
+}
+
+/* Return the size of the ringbuf (including a \0 terminator) */
+size_t debug_get_ringbuf_size(void)
+{
+       return debug_ringbuf_size;
+}
+
+static void debug_ringbuf_reload(bool enabled, bool previously_enabled,
+                                const char *prog_name, char *option)
+{
+       bool cmp;
+       size_t optlen = strlen(DEBUG_RINGBUF_SIZE_OPT);
+
+       debug_ringbuf_size = DEBUG_RINGBUF_SIZE;
+       debug_ringbuf_ofs = 0;
+
+       SAFE_FREE(debug_ringbuf);
+
+       if (!enabled) {
+               return;
+       }
+
+       if (option != NULL) {
+               cmp = strncmp(option, DEBUG_RINGBUF_SIZE_OPT, optlen);
+               if (cmp == 0) {
+                       debug_ringbuf_size = (size_t)strtoull(
+                               option + optlen, NULL, 10);
+               }
+       }
+
+       debug_ringbuf = calloc(debug_ringbuf_size, sizeof(char));
+       if (debug_ringbuf == NULL) {
+               return;
+       }
+}
+
+static void debug_ringbuf_log(int msg_level,
+                             const char *msg,
+                             const char *msg_no_nl)
+{
+       size_t msglen = strlen(msg);
+       size_t allowed_size;
+
+       if (debug_ringbuf == NULL) {
+               return;
+       }
+
+       /* Ensure the buffer is always \0 terminated */
+       allowed_size = debug_ringbuf_size - 1;
+
+       if (msglen > allowed_size) {
+               return;
+       }
+
+       if ((debug_ringbuf_ofs + msglen) < debug_ringbuf_ofs) {
+               return;
+       }
+
+       if ((debug_ringbuf_ofs + msglen) > allowed_size) {
+               debug_ringbuf_ofs = 0;
+       }
+
+       memcpy(debug_ringbuf + debug_ringbuf_ofs, msg, msglen);
+       debug_ringbuf_ofs += msglen;
+}
+
 static struct debug_backend {
        const char *name;
        int log_level;
@@ -278,6 +356,11 @@ static struct debug_backend {
                .log = debug_gpfs_log,
        },
 #endif
+       {
+               .name = "ringbuf",
+               .log = debug_ringbuf_log,
+               .reload = debug_ringbuf_reload,
+       },
 };
 
 static struct debug_backend *debug_find_backend(const char *name)
index b50bf50266238742cdf70575b4255c293d9022df..43c6aa08c7669ae1216ff9851e928a1b0e1694a8 100644 (file)
@@ -287,4 +287,7 @@ typedef void (*debug_callback_fn)(void *private_ptr, int level, const char *msg)
  */
 void debug_set_callback(void *private_ptr, debug_callback_fn fn);
 
+char *debug_get_ringbuf(void);
+size_t debug_get_ringbuf_size(void);
+
 #endif /* _SAMBA_DEBUG_H */