[libvirt] [PATCH v2] Allow to dynamically set the size of the debug buffer

Daniel Veillard veillard at redhat.com
Wed Mar 9 09:08:40 UTC 2011


[ sending this by hand as git-send-email seems to have failed to send
  the patch ... weird
  Result: 250 2.0.0 p2979dJi005806 Message accepted for delivery

  (mbox) Adding cc: Daniel Veillard <veillard at redhat.com> from line
  'From: Daniel Veillard <veillard at redhat.com>'
  (mbox) Adding to: libvir-list at redhat.com from line 'To:
  libvir-list at redhat.com'
  (body) Adding cc: Daniel Veillard <veillard at redhat.com> from line
  'Signed-off-by: Daniel Veillard <veillard at redhat.com>'
  Enter mail, end with "." on a line by itself
  paphio:~/libvirt ->                                               ]


Allow to dynamically set the size of the debug buffer

This is the part allowing to dynamically resize the debug log
buffer from it's default 64kB size. The buffer is now dynamically
allocated.
It adds a new API virLogSetBufferSize() which resizes the buffer
If passed a zero size, the buffer is deallocated and we do the small
optimization of not formatting messages which are not output anymore.
On the daemon side, it just adds a new option log_buffer_size to
libvirtd.conf and call virLogSetBufferSize() if needed
* src/util/logging.h src/util/logging.c src/libvirt_private.syms:
  make buffer dynamic and add virLogSetBufferSize() internal API
* daemon/libvirtd.conf: document the new log_buffer_size option
* daemon/libvirtd.c: read and use the new log_buffer_size option

diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index 452566c..ad3274f 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -2713,18 +2713,22 @@ remoteReadSaslAllowedUsernameList (virConfPtr conf ATTRIBUTE_UNUSED,
  * Set up the logging environment
  * By default if daemonized all errors go to the logfile libvirtd.log,
  * but if verbose or error debugging is asked for then also output
- * informations or debug.
+ * informations or debug. Default size if 64 kB.
  */
 static int
 qemudSetLogging(struct qemud_server *server, virConfPtr conf,
                 const char *filename)
 {
     int log_level = 0;
+    int log_buffer_size = 64;
     char *log_filters = NULL;
     char *log_outputs = NULL;
     char *log_file = NULL;
     int ret = -1;
 
+    GET_CONF_INT (conf, filename, log_buffer_size);
+    virLogSetBufferSize(log_buffer_size);
+
     virLogReset();
 
     /*
diff --git a/daemon/libvirtd.conf b/daemon/libvirtd.conf
index 163a80f..3a071b0 100644
--- a/daemon/libvirtd.conf
+++ b/daemon/libvirtd.conf
@@ -313,6 +313,13 @@
 # log_outputs="3:syslog:libvirtd"
 # to log all warnings and errors to syslog under the libvirtd ident
 
+# Log debug buffer size: default 64
+# The daemon keeps an internal debug log buffer which will be dumped in case
+# of crash or upon receiving a SIGUSR2 signal. This setting allows to override
+# the default buffer size in kilobytes.
+# If value is 0 or less the debug log buffer is deactivated
+#log_buffer_size = 64
+
 
 ##################################################################
 #
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index efcf3c5..7567c78 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -558,6 +558,7 @@ virLogParseDefaultPriority;
 virLogParseFilters;
 virLogParseOutputs;
 virLogReset;
+virLogSetBufferSize;
 virLogSetDefaultPriority;
 virLogSetFromEnv;
 virLogShutdown;
diff --git a/src/util/logging.c b/src/util/logging.c
index 6490376..12e2829 100644
--- a/src/util/logging.c
+++ b/src/util/logging.c
@@ -36,6 +36,7 @@
 #endif
 
 #include "ignore-value.h"
+#include "virterror_internal.h"
 #include "logging.h"
 #include "memory.h"
 #include "util.h"
@@ -43,6 +44,8 @@
 #include "threads.h"
 #include "files.h"
 
+#define VIR_FROM_THIS VIR_FROM_NONE
+
 /*
  * Macro used to format the message as a string in virLogMessage
  * and borrowed from libxml2 (also used in virRaiseError)
@@ -83,9 +86,9 @@
 /*
  * A logging buffer to keep some history over logs
  */
-#define LOG_BUFFER_SIZE 64000
 
-static char virLogBuffer[LOG_BUFFER_SIZE + 1];
+static int virLogSize = 64 * 1024;
+static char *virLogBuffer = NULL;
 static int virLogLen = 0;
 static int virLogStart = 0;
 static int virLogEnd = 0;
@@ -184,6 +187,8 @@ static int virLogInitialized = 0;
  * Returns 0 if successful, and -1 in case or error
  */
 int virLogStartup(void) {
+    const char *pbm = NULL;
+
     if (virLogInitialized)
         return -1;
 
@@ -192,15 +197,85 @@ int virLogStartup(void) {
 
     virLogInitialized = 1;
     virLogLock();
+    if (VIR_ALLOC_N(virLogBuffer, virLogSize) < 0) {
+        /*
+         * The debug buffer is not a critical component, allow startup
+         * even in case of failure to allocate it in case of a
+         * configuration mistake.
+         */
+        virLogSize = 64000;
+        if (VIR_ALLOC_N(virLogBuffer, virLogSize) < 0) {
+            pbm = "Failed to allocate debug buffer: desactivating debug log\n";
+            virLogSize = 0;
+        } else {
+            pbm = "Failed to allocate debug buffer: reduced to 64 kB\n";
+        }
+    }
     virLogLen = 0;
     virLogStart = 0;
     virLogEnd = 0;
     virLogDefaultPriority = VIR_LOG_DEFAULT;
     virLogUnlock();
+    if (pbm)
+        VIR_WARN0(pbm);
     return 0;
 }
 
 /**
+ * virLogSetBufferSize:
+ * @size: size of the buffer in kilobytes or <= 0 to deactivate
+ *
+ * Dynamically set the size or deactivate the logging buffer used to keep
+ * a trace of all recent debug output. Note that the content of the buffer
+ * is lost if it gets reallocated.
+ *
+ * Return -1 in case of failure or 0 in case of success
+ */
+extern int
+virLogSetBufferSize(int size) {
+    int ret = 0;
+    int oldsize;
+    char *oldLogBuffer;
+    const char *pbm = NULL;
+
+    if (size < 0)
+        size = 0;
+
+    if ((virLogInitialized == 0) || (size * 1024 == virLogSize))
+        return ret;
+
+    virLogLock();
+
+    oldsize = virLogSize;
+    oldLogBuffer = virLogBuffer;
+
+    if (INT_MAX / 1024 < size) {
+        pbm = "Requested log size of %d kB too large\n";
+        ret = -1;
+        goto error;
+    }
+
+    virLogSize = size * 1024;
+    if (VIR_ALLOC_N(virLogBuffer, virLogSize) < 0) {
+        pbm = "Failed to allocate debug buffer of %d kB\n";
+        virLogBuffer = oldLogBuffer;
+        virLogSize = oldsize;
+        ret = -1;
+        goto error;
+    }
+    VIR_FREE(oldLogBuffer);
+    virLogLen = 0;
+    virLogStart = 0;
+    virLogEnd = 0;
+
+error:
+    virLogUnlock();
+    if (pbm)
+        VIR_ERROR(pbm, size);
+    return ret;
+}
+
+/**
  * virLogReset:
  *
  * Reset the logging module to its default initial state
@@ -235,6 +310,7 @@ void virLogShutdown(void) {
     virLogLen = 0;
     virLogStart = 0;
     virLogEnd = 0;
+    VIR_FREE(virLogBuffer);
     virLogUnlock();
     virMutexDestroy(&virLogMutex);
     virLogInitialized = 0;
@@ -246,21 +322,21 @@ void virLogShutdown(void) {
 static void virLogStr(const char *str, int len) {
     int tmp;
 
-    if (str == NULL)
+    if ((str == NULL) || (virLogBuffer == NULL) || (virLogSize <= 0))
         return;
     if (len <= 0)
         len = strlen(str);
-    if (len > LOG_BUFFER_SIZE)
+    if (len > virLogSize)
         return;
     virLogLock();
 
     /*
      * copy the data and reset the end, we cycle over the end of the buffer
      */
-    if (virLogEnd + len >= LOG_BUFFER_SIZE) {
-        tmp = LOG_BUFFER_SIZE - virLogEnd;
+    if (virLogEnd + len >= virLogSize) {
+        tmp = virLogSize - virLogEnd;
         memcpy(&virLogBuffer[virLogEnd], str, tmp);
-        virLogBuffer[LOG_BUFFER_SIZE] = 0;
+        virLogBuffer[virLogSize] = 0;
         memcpy(&virLogBuffer[0], &str[tmp], len - tmp);
         virLogEnd = len - tmp;
     } else {
@@ -271,12 +347,12 @@ static void virLogStr(const char *str, int len) {
      * Update the log length, and if full move the start index
      */
     virLogLen += len;
-    if (virLogLen > LOG_BUFFER_SIZE) {
-        tmp = virLogLen - LOG_BUFFER_SIZE;
-        virLogLen = LOG_BUFFER_SIZE;
+    if (virLogLen > virLogSize) {
+        tmp = virLogLen - virLogSize;
+        virLogLen = virLogSize;
         virLogStart += tmp;
-        if (virLogStart >= LOG_BUFFER_SIZE)
-            virLogStart -= LOG_BUFFER_SIZE;
+        if (virLogStart >= virLogSize)
+            virLogStart -= virLogSize;
     }
     virLogUnlock();
 }
@@ -350,23 +426,28 @@ virLogEmergencyDumpAll(int signum) {
             virLogDumpAllFD( "Caught unexpected signal", -1);
             break;
     }
+    if ((virLogBuffer == NULL) || (virLogSize <= 0)) {
+        virLogDumpAllFD(" internal log buffer deactivated\n", -1);
+        goto done;
+    }
     virLogDumpAllFD(" dumping internal log buffer:\n", -1);
     virLogDumpAllFD("\n\n    ====== start of log =====\n\n", -1);
     while (virLogLen > 0) {
-        if (virLogStart + virLogLen < LOG_BUFFER_SIZE) {
+        if (virLogStart + virLogLen < virLogSize) {
             virLogBuffer[virLogStart + virLogLen] = 0;
             virLogDumpAllFD(&virLogBuffer[virLogStart], virLogLen);
             virLogStart += virLogLen;
             virLogLen = 0;
         } else {
-            len = LOG_BUFFER_SIZE - virLogStart;
-            virLogBuffer[LOG_BUFFER_SIZE] = 0;
+            len = virLogSize - virLogStart;
+            virLogBuffer[virLogSize] = 0;
             virLogDumpAllFD(&virLogBuffer[virLogStart], len);
             virLogLen -= len;
             virLogStart = 0;
         }
     }
     virLogDumpAllFD("\n\n     ====== end of log =====\n\n", -1);
+done:
     virLogUnlock();
 }
 
@@ -643,6 +724,9 @@ void virLogMessage(const char *category, int priority, const char *funcname,
         emit = 0;
     }
 
+    if ((emit == 0) && ((virLogBuffer == NULL) || (virLogSize <= 0)))
+        goto cleanup;
+
     /*
      * serialize the error message, add level and timestamp
      */
diff --git a/src/util/logging.h b/src/util/logging.h
index c168dff..0dba78c 100644
--- a/src/util/logging.h
+++ b/src/util/logging.h
@@ -133,5 +133,6 @@ extern int virLogParseOutputs(const char *output);
 extern void virLogMessage(const char *category, int priority,
                           const char *funcname, long long linenr, int flags,
                           const char *fmt, ...) ATTRIBUTE_FMT_PRINTF(6, 7);
+extern int virLogSetBufferSize(int size);
 extern void virLogEmergencyDumpAll(int signum);
 #endif

-- 
Daniel Veillard      | libxml Gnome XML XSLT toolkit  http://xmlsoft.org/
daniel at veillard.com  | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library  http://libvirt.org/




More information about the libvir-list mailing list