c1c534
From 0b0135f00c4e17cb902ec6885648b5a4e667d56b Mon Sep 17 00:00:00 2001
c1c534
Message-Id: <0b0135f00c4e17cb902ec6885648b5a4e667d56b@dist-git>
c1c534
From: Jiri Denemark <jdenemar@redhat.com>
c1c534
Date: Wed, 22 Nov 2017 13:12:00 +0100
c1c534
Subject: [PATCH] qemu: Use the end of QEMU log for reporting errors
c1c534
c1c534
When QEMU dies, we read its output stored in a log file and use it for
c1c534
reporting a hopefully useful error. However, virReportError will trim
c1c534
the message to (VIR_ERROR_MAX_LENGTH - 1) characters, which means the
c1c534
end of the log (which likely contains the error message we want to
c1c534
report) may get lost. We should trim the beginning of the log instead.
c1c534
c1c534
https://bugzilla.redhat.com/show_bug.cgi?id=1335534
c1c534
c1c534
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
c1c534
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
c1c534
(cherry picked from commit 96f7a045e93ad08eb4130be97dd6d8a8c963a952)
c1c534
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
c1c534
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
c1c534
---
c1c534
 src/qemu/qemu_process.c | 34 ++++++++++++++++++++++++++++++----
c1c534
 1 file changed, 30 insertions(+), 4 deletions(-)
c1c534
c1c534
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
c1c534
index c5fa8cb4b2..f7808227a8 100644
c1c534
--- a/src/qemu/qemu_process.c
c1c534
+++ b/src/qemu/qemu_process.c
c1c534
@@ -1827,17 +1827,24 @@ qemuConnectMonitor(virQEMUDriverPtr driver, virDomainObjPtr vm, int asyncJob,
c1c534
  * qemuProcessReadLog: Read log file of a qemu VM
c1c534
  * @logCtxt: the domain log context
c1c534
  * @msg: pointer to buffer to store the read messages in
c1c534
+ * @max: maximum length of the message returned in @msg
c1c534
  *
c1c534
  * Reads log of a qemu VM. Skips messages not produced by qemu or irrelevant
c1c534
- * messages. Returns returns 0 on success or -1 on error
c1c534
+ * messages. If @max is not zero, @msg will contain at most @max characters
c1c534
+ * from the end of the log and @msg will start after a new line if possible.
c1c534
+ *
c1c534
+ * Returns 0 on success or -1 on error
c1c534
  */
c1c534
 static int
c1c534
-qemuProcessReadLog(qemuDomainLogContextPtr logCtxt, char **msg)
c1c534
+qemuProcessReadLog(qemuDomainLogContextPtr logCtxt,
c1c534
+                   char **msg,
c1c534
+                   size_t max)
c1c534
 {
c1c534
     char *buf;
c1c534
     ssize_t got;
c1c534
     char *eol;
c1c534
     char *filter_next;
c1c534
+    size_t skip;
c1c534
 
c1c534
     if ((got = qemuDomainLogContextRead(logCtxt, &buf)) < 0)
c1c534
         return -1;
c1c534
@@ -1848,7 +1855,7 @@ qemuProcessReadLog(qemuDomainLogContextPtr logCtxt, char **msg)
c1c534
         *eol = '\0';
c1c534
         if (virLogProbablyLogMessage(filter_next) ||
c1c534
             strstr(filter_next, "char device redirected to")) {
c1c534
-            size_t skip = (eol + 1) - filter_next;
c1c534
+            skip = (eol + 1) - filter_next;
c1c534
             memmove(filter_next, eol + 1, buf + got - eol);
c1c534
             got -= skip;
c1c534
         } else {
c1c534
@@ -1863,6 +1870,19 @@ qemuProcessReadLog(qemuDomainLogContextPtr logCtxt, char **msg)
c1c534
         buf[got - 1] = '\0';
c1c534
         got--;
c1c534
     }
c1c534
+
c1c534
+    if (max > 0 && got > max) {
c1c534
+        skip = got - max;
c1c534
+
c1c534
+        if (buf[skip - 1] != '\n' &&
c1c534
+            (eol = strchr(buf + skip, '\n')) &&
c1c534
+            !virStringIsEmpty(eol + 1))
c1c534
+            skip = eol + 1 - buf;
c1c534
+
c1c534
+        memmove(buf, buf + skip, got - skip + 1);
c1c534
+        got -= skip;
c1c534
+    }
c1c534
+
c1c534
     ignore_value(VIR_REALLOC_N_QUIET(buf, got + 1));
c1c534
     *msg = buf;
c1c534
     return 0;
c1c534
@@ -1874,8 +1894,14 @@ qemuProcessReportLogError(qemuDomainLogContextPtr logCtxt,
c1c534
                           const char *msgprefix)
c1c534
 {
c1c534
     char *logmsg = NULL;
c1c534
+    size_t max;
c1c534
 
c1c534
-    if (qemuProcessReadLog(logCtxt, &logmsg) < 0)
c1c534
+    max = VIR_ERROR_MAX_LENGTH - 1;
c1c534
+    max -= strlen(msgprefix);
c1c534
+    /* The length of the formatting string minus two '%s' */
c1c534
+    max -= strlen(_("%s: %s")) - 4;
c1c534
+
c1c534
+    if (qemuProcessReadLog(logCtxt, &logmsg, max) < 0)
c1c534
         return -1;
c1c534
 
c1c534
     virResetLastError();
c1c534
-- 
c1c534
2.15.0
c1c534