[libvirt PATCH v4 13/31] qemu: Extract qemuDomainLogContext into a new file

Jonathon Jongsma jjongsma at redhat.com
Fri Jan 20 22:03:07 UTC 2023


This will allow us to use it for nbdkit logging in upcoming commits.

Signed-off-by: Jonathon Jongsma <jjongsma at redhat.com>
---
 po/POTFILES                |   1 +
 src/qemu/meson.build       |   1 +
 src/qemu/qemu_domain.c     | 247 ++--------------------------------
 src/qemu/qemu_domain.h     |  29 +---
 src/qemu/qemu_logcontext.c | 264 +++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_logcontext.h |  38 ++++++
 src/qemu/qemu_process.c    |  44 +++----
 7 files changed, 347 insertions(+), 277 deletions(-)
 create mode 100644 src/qemu/qemu_logcontext.c
 create mode 100644 src/qemu/qemu_logcontext.h

diff --git a/po/POTFILES b/po/POTFILES
index a45259c0d8..024575a0d9 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -172,6 +172,7 @@ src/qemu/qemu_hostdev.c
 src/qemu/qemu_hotplug.c
 src/qemu/qemu_interface.c
 src/qemu/qemu_interop_config.c
+src/qemu/qemu_logcontext.c
 src/qemu/qemu_migration.c
 src/qemu/qemu_migration_cookie.c
 src/qemu/qemu_migration_params.c
diff --git a/src/qemu/meson.build b/src/qemu/meson.build
index 9be6996195..6d7a1bfbb0 100644
--- a/src/qemu/meson.build
+++ b/src/qemu/meson.build
@@ -21,6 +21,7 @@ qemu_driver_sources = [
   'qemu_hotplug.c',
   'qemu_interface.c',
   'qemu_interop_config.c',
+  'qemu_logcontext.c',
   'qemu_migration.c',
   'qemu_migration_cookie.c',
   'qemu_migration_params.c',
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 8961efa804..63c2c602ec 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -454,21 +454,8 @@ qemuDomainObjFromDomain(virDomainPtr domain)
 }
 
 
-struct _qemuDomainLogContext {
-    GObject parent;
-
-    int writefd;
-    int readfd; /* Only used if manager == NULL */
-    off_t pos;
-    ino_t inode; /* Only used if manager != NULL */
-    char *path;
-    virLogManager *manager;
-};
-
-G_DEFINE_TYPE(qemuDomainLogContext, qemu_domain_log_context, G_TYPE_OBJECT);
 static virClass *qemuDomainSaveCookieClass;
 
-static void qemuDomainLogContextFinalize(GObject *obj);
 static void qemuDomainSaveCookieDispose(void *obj);
 
 
@@ -481,32 +468,8 @@ qemuDomainOnceInit(void)
     return 0;
 }
 
-static void qemu_domain_log_context_init(qemuDomainLogContext *logctxt G_GNUC_UNUSED)
-{
-}
-
-static void qemu_domain_log_context_class_init(qemuDomainLogContextClass *klass)
-{
-    GObjectClass *obj = G_OBJECT_CLASS(klass);
-
-    obj->finalize = qemuDomainLogContextFinalize;
-}
-
 VIR_ONCE_GLOBAL_INIT(qemuDomain);
 
-static void
-qemuDomainLogContextFinalize(GObject *object)
-{
-    qemuDomainLogContext *ctxt = QEMU_DOMAIN_LOG_CONTEXT(object);
-    VIR_DEBUG("ctxt=%p", ctxt);
-
-    virLogManagerFree(ctxt->manager);
-    VIR_FREE(ctxt->path);
-    VIR_FORCE_CLOSE(ctxt->writefd);
-    VIR_FORCE_CLOSE(ctxt->readfd);
-    G_OBJECT_CLASS(qemu_domain_log_context_parent_class)->finalize(object);
-}
-
 /* qemuDomainGetMasterKeyFilePath:
  * @libDir: Directory path to domain lib files
  *
@@ -6555,7 +6518,7 @@ qemuDomainDefFormatLive(virQEMUDriver *driver,
 void qemuDomainObjTaint(virQEMUDriver *driver,
                         virDomainObj *obj,
                         virDomainTaintFlags taint,
-                        qemuDomainLogContext *logCtxt)
+                        qemuLogContext *logCtxt)
 {
     qemuDomainObjTaintMsg(driver, obj, taint, logCtxt, NULL);
     qemuDomainSaveStatus(obj);
@@ -6564,7 +6527,7 @@ void qemuDomainObjTaint(virQEMUDriver *driver,
 void qemuDomainObjTaintMsg(virQEMUDriver *driver,
                            virDomainObj *obj,
                            virDomainTaintFlags taint,
-                           qemuDomainLogContext *logCtxt,
+                           qemuLogContext *logCtxt,
                            const char *fmt, ...)
 {
     virErrorPtr orig_err = NULL;
@@ -6617,12 +6580,12 @@ void qemuDomainObjTaintMsg(virQEMUDriver *driver,
         goto cleanup;
 
     if (logCtxt) {
-        rc = qemuDomainLogContextWrite(logCtxt,
-                                       "%s: Domain id=%d is tainted: %s%s%s%s\n",
-                                       timestamp,
-                                       obj->def->id,
-                                       virDomainTaintTypeToString(taint),
-                                       extraprefix, extramsg, extrasuffix);
+        rc = qemuLogContextWrite(logCtxt,
+                                 "%s: Domain id=%d is tainted: %s%s%s%s\n",
+                                 timestamp,
+                                 obj->def->id,
+                                 virDomainTaintTypeToString(taint),
+                                 extraprefix, extramsg, extrasuffix);
     } else {
         rc = qemuDomainLogAppendMessage(driver, obj,
                                         "%s: Domain id=%d is tainted: %s%s%s%s\n",
@@ -6642,7 +6605,7 @@ void qemuDomainObjTaintMsg(virQEMUDriver *driver,
 static void
 qemuDomainObjCheckMachineTaint(virQEMUDriver *driver,
                                virDomainObj *obj,
-                               qemuDomainLogContext *logCtxt)
+                               qemuLogContext *logCtxt)
 {
     qemuDomainObjPrivate *priv = obj->privateData;
     virQEMUCaps *qemuCaps = priv->qemuCaps;
@@ -6660,7 +6623,7 @@ qemuDomainObjCheckMachineTaint(virQEMUDriver *driver,
 static void
 qemuDomainObjCheckCPUTaint(virQEMUDriver *driver,
                            virDomainObj *obj,
-                           qemuDomainLogContext *logCtxt,
+                           qemuLogContext *logCtxt,
                            bool incomingMigration)
 {
     qemuDomainObjPrivate *priv = obj->privateData;
@@ -6692,7 +6655,7 @@ qemuDomainObjCheckCPUTaint(virQEMUDriver *driver,
 
 void qemuDomainObjCheckTaint(virQEMUDriver *driver,
                              virDomainObj *obj,
-                             qemuDomainLogContext *logCtxt,
+                             qemuLogContext *logCtxt,
                              bool incomingMigration)
 {
     size_t i;
@@ -6748,7 +6711,7 @@ void qemuDomainObjCheckTaint(virQEMUDriver *driver,
 void qemuDomainObjCheckDiskTaint(virQEMUDriver *driver,
                                  virDomainObj *obj,
                                  virDomainDiskDef *disk,
-                                 qemuDomainLogContext *logCtxt)
+                                 qemuLogContext *logCtxt)
 {
     if (disk->rawio == VIR_TRISTATE_BOOL_YES)
         qemuDomainObjTaint(driver, obj, VIR_DOMAIN_TAINT_HIGH_PRIVILEGES,
@@ -6765,7 +6728,7 @@ void qemuDomainObjCheckDiskTaint(virQEMUDriver *driver,
 void qemuDomainObjCheckHostdevTaint(virQEMUDriver *driver,
                                     virDomainObj *obj,
                                     virDomainHostdevDef *hostdev,
-                                    qemuDomainLogContext *logCtxt)
+                                    qemuLogContext *logCtxt)
 {
     if (!virHostdevIsSCSIDevice(hostdev))
         return;
@@ -6778,7 +6741,7 @@ void qemuDomainObjCheckHostdevTaint(virQEMUDriver *driver,
 void qemuDomainObjCheckNetTaint(virQEMUDriver *driver,
                                 virDomainObj *obj,
                                 virDomainNetDef *net,
-                                qemuDomainLogContext *logCtxt)
+                                qemuLogContext *logCtxt)
 {
     /* script is only useful for NET_TYPE_ETHERNET (qemu) and
      * NET_TYPE_BRIDGE (xen), but could be (incorrectly) specified for
@@ -6790,163 +6753,6 @@ void qemuDomainObjCheckNetTaint(virQEMUDriver *driver,
 }
 
 
-qemuDomainLogContext *qemuDomainLogContextNew(virQEMUDriver *driver,
-                                                virDomainObj *vm,
-                                                const char *basename)
-{
-    g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
-    qemuDomainLogContext *ctxt = QEMU_DOMAIN_LOG_CONTEXT(g_object_new(QEMU_TYPE_DOMAIN_LOG_CONTEXT, NULL));
-
-    VIR_DEBUG("Context new %p stdioLogD=%d", ctxt, cfg->stdioLogD);
-    ctxt->writefd = -1;
-    ctxt->readfd = -1;
-
-    ctxt->path = g_strdup_printf("%s/%s.log", cfg->logDir, basename);
-
-    if (cfg->stdioLogD) {
-        ctxt->manager = virLogManagerNew(driver->privileged);
-        if (!ctxt->manager)
-            goto error;
-
-        ctxt->writefd = virLogManagerDomainOpenLogFile(ctxt->manager,
-                                                       "qemu",
-                                                       vm->def->uuid,
-                                                       vm->def->name,
-                                                       ctxt->path,
-                                                       0,
-                                                       &ctxt->inode,
-                                                       &ctxt->pos);
-        if (ctxt->writefd < 0)
-            goto error;
-    } else {
-        if ((ctxt->writefd = open(ctxt->path, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR)) < 0) {
-            virReportSystemError(errno, _("failed to create logfile %s"),
-                                 ctxt->path);
-            goto error;
-        }
-        if (virSetCloseExec(ctxt->writefd) < 0) {
-            virReportSystemError(errno, _("failed to set close-on-exec flag on %s"),
-                                 ctxt->path);
-            goto error;
-        }
-
-        /* For unprivileged startup we must truncate the file since
-         * we can't rely on logrotate. We don't use O_TRUNC since
-         * it is better for SELinux policy if we truncate afterwards */
-        if (!driver->privileged &&
-            ftruncate(ctxt->writefd, 0) < 0) {
-            virReportSystemError(errno, _("failed to truncate %s"),
-                                 ctxt->path);
-            goto error;
-        }
-
-        if ((ctxt->readfd = open(ctxt->path, O_RDONLY)) < 0) {
-            virReportSystemError(errno, _("failed to open logfile %s"),
-                                 ctxt->path);
-            goto error;
-        }
-        if (virSetCloseExec(ctxt->readfd) < 0) {
-            virReportSystemError(errno, _("failed to set close-on-exec flag on %s"),
-                                 ctxt->path);
-            goto error;
-        }
-
-        if ((ctxt->pos = lseek(ctxt->writefd, 0, SEEK_END)) < 0) {
-            virReportSystemError(errno, _("failed to seek in log file %s"),
-                                 ctxt->path);
-            goto error;
-        }
-    }
-
-    return ctxt;
-
- error:
-    g_clear_object(&ctxt);
-    return NULL;
-}
-
-
-int qemuDomainLogContextWrite(qemuDomainLogContext *ctxt,
-                              const char *fmt, ...)
-{
-    va_list argptr;
-    g_autofree char *message = NULL;
-    int ret = -1;
-
-    va_start(argptr, fmt);
-
-    message = g_strdup_vprintf(fmt, argptr);
-    if (!ctxt->manager &&
-        lseek(ctxt->writefd, 0, SEEK_END) < 0) {
-        virReportSystemError(errno, "%s",
-                             _("Unable to seek to end of domain logfile"));
-        goto cleanup;
-    }
-    if (safewrite(ctxt->writefd, message, strlen(message)) < 0) {
-        virReportSystemError(errno, "%s",
-                             _("Unable to write to domain logfile"));
-        goto cleanup;
-    }
-
-    ret = 0;
-
- cleanup:
-    va_end(argptr);
-    return ret;
-}
-
-
-ssize_t qemuDomainLogContextRead(qemuDomainLogContext *ctxt,
-                                 char **msg)
-{
-    char *buf;
-    size_t buflen;
-
-    VIR_DEBUG("Context read %p manager=%p inode=%llu pos=%llu",
-              ctxt, ctxt->manager,
-              (unsigned long long)ctxt->inode,
-              (unsigned long long)ctxt->pos);
-
-    if (ctxt->manager) {
-        buf = virLogManagerDomainReadLogFile(ctxt->manager,
-                                             ctxt->path,
-                                             ctxt->inode,
-                                             ctxt->pos,
-                                             1024 * 128,
-                                             0);
-        if (!buf)
-            return -1;
-        buflen = strlen(buf);
-    } else {
-        ssize_t got;
-
-        buflen = 1024 * 128;
-
-        /* Best effort jump to start of messages */
-        ignore_value(lseek(ctxt->readfd, ctxt->pos, SEEK_SET));
-
-        buf = g_new0(char, buflen);
-
-        got = saferead(ctxt->readfd, buf, buflen - 1);
-        if (got < 0) {
-            VIR_FREE(buf);
-            virReportSystemError(errno, "%s",
-                                 _("Unable to read from log file"));
-            return -1;
-        }
-
-        buf[got] = '\0';
-
-        buf = g_renew(char, buf, got + 1);
-        buflen = got;
-    }
-
-    *msg = buf;
-
-    return buflen;
-}
-
-
 /**
  * qemuDomainLogAppendMessage:
  *
@@ -7004,31 +6810,6 @@ qemuDomainLogAppendMessage(virQEMUDriver *driver,
 }
 
 
-int qemuDomainLogContextGetWriteFD(qemuDomainLogContext *ctxt)
-{
-    return ctxt->writefd;
-}
-
-
-void qemuDomainLogContextMarkPosition(qemuDomainLogContext *ctxt)
-{
-    if (ctxt->manager)
-        virLogManagerDomainGetLogFilePosition(ctxt->manager,
-                                              ctxt->path,
-                                              0,
-                                              &ctxt->inode,
-                                              &ctxt->pos);
-    else
-        ctxt->pos = lseek(ctxt->writefd, 0, SEEK_END);
-}
-
-
-virLogManager *qemuDomainLogContextGetManager(qemuDomainLogContext *ctxt)
-{
-    return ctxt->manager;
-}
-
-
 /* Locate an appropriate 'qemu-img' binary.  */
 const char *
 qemuFindQemuImgBinary(virQEMUDriver *driver)
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 2a01c7e631..318865f920 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -32,13 +32,13 @@
 #include "qemu_domainjob.h"
 #include "qemu_conf.h"
 #include "qemu_capabilities.h"
+#include "qemu_logcontext.h"
 #include "qemu_migration_params.h"
 #include "qemu_nbdkit.h"
 #include "qemu_slirp.h"
 #include "qemu_fd.h"
 #include "virchrdev.h"
 #include "virobject.h"
-#include "logging/log_manager.h"
 #include "virdomainmomentobjlist.h"
 #include "virenum.h"
 #include "vireventthread.h"
@@ -473,9 +473,6 @@ struct qemuProcessEvent {
 
 void qemuProcessEventFree(struct qemuProcessEvent *event);
 
-#define QEMU_TYPE_DOMAIN_LOG_CONTEXT qemu_domain_log_context_get_type()
-G_DECLARE_FINAL_TYPE(qemuDomainLogContext, qemu_domain_log_context, QEMU, DOMAIN_LOG_CONTEXT, GObject);
-
 typedef struct _qemuDomainSaveCookie qemuDomainSaveCookie;
 struct _qemuDomainSaveCookie {
     virObject parent;
@@ -628,12 +625,12 @@ char *qemuDomainDefFormatLive(virQEMUDriver *driver,
 void qemuDomainObjTaint(virQEMUDriver *driver,
                         virDomainObj *obj,
                         virDomainTaintFlags taint,
-                        qemuDomainLogContext *logCtxt);
+                        qemuLogContext *logCtxt);
 
 void qemuDomainObjTaintMsg(virQEMUDriver *driver,
                            virDomainObj *obj,
                            virDomainTaintFlags taint,
-                           qemuDomainLogContext *logCtxt,
+                           qemuLogContext *logCtxt,
                            const char *msg,
                            ...) G_GNUC_PRINTF(5, 6);
 
@@ -642,32 +639,20 @@ char **qemuDomainObjGetTainting(virQEMUDriver *driver,
 
 void qemuDomainObjCheckTaint(virQEMUDriver *driver,
                              virDomainObj *obj,
-                             qemuDomainLogContext *logCtxt,
+                             qemuLogContext *logCtxt,
                              bool incomingMigration);
 void qemuDomainObjCheckDiskTaint(virQEMUDriver *driver,
                                  virDomainObj *obj,
                                  virDomainDiskDef *disk,
-                                 qemuDomainLogContext *logCtxt);
+                                 qemuLogContext *logCtxt);
 void qemuDomainObjCheckHostdevTaint(virQEMUDriver *driver,
                                     virDomainObj *obj,
                                     virDomainHostdevDef *disk,
-                                    qemuDomainLogContext *logCtxt);
+                                    qemuLogContext *logCtxt);
 void qemuDomainObjCheckNetTaint(virQEMUDriver *driver,
                                 virDomainObj *obj,
                                 virDomainNetDef *net,
-                                qemuDomainLogContext *logCtxt);
-
-qemuDomainLogContext *qemuDomainLogContextNew(virQEMUDriver *driver,
-                                                virDomainObj *vm,
-                                                const char *basename);
-int qemuDomainLogContextWrite(qemuDomainLogContext *ctxt,
-                              const char *fmt, ...) G_GNUC_PRINTF(2, 3);
-ssize_t qemuDomainLogContextRead(qemuDomainLogContext *ctxt,
-                                 char **msg);
-int qemuDomainLogContextGetWriteFD(qemuDomainLogContext *ctxt);
-void qemuDomainLogContextMarkPosition(qemuDomainLogContext *ctxt);
-
-virLogManager *qemuDomainLogContextGetManager(qemuDomainLogContext *ctxt);
+                                qemuLogContext *logCtxt);
 
 int qemuDomainLogAppendMessage(virQEMUDriver *driver,
                                virDomainObj *vm,
diff --git a/src/qemu/qemu_logcontext.c b/src/qemu/qemu_logcontext.c
new file mode 100644
index 0000000000..6ad0beeeae
--- /dev/null
+++ b/src/qemu/qemu_logcontext.c
@@ -0,0 +1,264 @@
+/*
+ * qemu_logcontext.c: QEMU log context
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "qemu_logcontext.h"
+#include "viralloc.h"
+#include "virlog.h"
+#include "virutil.h"
+
+#include <fcntl.h>
+
+#define VIR_FROM_THIS VIR_FROM_QEMU
+
+VIR_LOG_INIT("qemu.qemu_logcontext");
+
+
+struct _qemuLogContext {
+    GObject parent;
+
+    int writefd;
+    int readfd; /* Only used if manager == NULL */
+    off_t pos;
+    ino_t inode; /* Only used if manager != NULL */
+    char *path;
+    virLogManager *manager;
+};
+
+G_DEFINE_TYPE(qemuLogContext, qemu_log_context, G_TYPE_OBJECT);
+
+static void
+qemuLogContextFinalize(GObject *obj);
+
+
+static void
+qemu_log_context_init(qemuLogContext *logctxt G_GNUC_UNUSED)
+{
+}
+
+
+static void
+qemu_log_context_class_init(qemuLogContextClass *klass)
+{
+    GObjectClass *obj = G_OBJECT_CLASS(klass);
+
+    obj->finalize = qemuLogContextFinalize;
+}
+
+
+static void
+qemuLogContextFinalize(GObject *object)
+{
+    qemuLogContext *ctxt = QEMU_LOG_CONTEXT(object);
+    VIR_DEBUG("ctxt=%p", ctxt);
+
+    virLogManagerFree(ctxt->manager);
+    VIR_FREE(ctxt->path);
+    VIR_FORCE_CLOSE(ctxt->writefd);
+    VIR_FORCE_CLOSE(ctxt->readfd);
+    G_OBJECT_CLASS(qemu_log_context_parent_class)->finalize(object);
+}
+
+
+qemuLogContext *
+qemuLogContextNew(virQEMUDriver *driver,
+                  virDomainObj *vm,
+                  const char *basename)
+{
+    g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
+    qemuLogContext *ctxt = QEMU_LOG_CONTEXT(g_object_new(QEMU_TYPE_LOG_CONTEXT, NULL));
+
+    VIR_DEBUG("Context new %p stdioLogD=%d", ctxt, cfg->stdioLogD);
+    ctxt->writefd = -1;
+    ctxt->readfd = -1;
+
+    ctxt->path = g_strdup_printf("%s/%s.log", cfg->logDir, basename);
+
+    if (cfg->stdioLogD) {
+        ctxt->manager = virLogManagerNew(driver->privileged);
+        if (!ctxt->manager)
+            goto error;
+
+        ctxt->writefd = virLogManagerDomainOpenLogFile(ctxt->manager,
+                                                       "qemu",
+                                                       vm->def->uuid,
+                                                       vm->def->name,
+                                                       ctxt->path,
+                                                       0,
+                                                       &ctxt->inode,
+                                                       &ctxt->pos);
+        if (ctxt->writefd < 0)
+            goto error;
+    } else {
+        if ((ctxt->writefd = open(ctxt->path, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR)) < 0) {
+            virReportSystemError(errno, _("failed to create logfile %s"),
+                                 ctxt->path);
+            goto error;
+        }
+        if (virSetCloseExec(ctxt->writefd) < 0) {
+            virReportSystemError(errno, _("failed to set close-on-exec flag on %s"),
+                                 ctxt->path);
+            goto error;
+        }
+
+        /* For unprivileged startup we must truncate the file since
+         * we can't rely on logrotate. We don't use O_TRUNC since
+         * it is better for SELinux policy if we truncate afterwards */
+        if (!driver->privileged &&
+            ftruncate(ctxt->writefd, 0) < 0) {
+            virReportSystemError(errno, _("failed to truncate %s"),
+                                 ctxt->path);
+            goto error;
+        }
+
+        if ((ctxt->readfd = open(ctxt->path, O_RDONLY)) < 0) {
+            virReportSystemError(errno, _("failed to open logfile %s"),
+                                 ctxt->path);
+            goto error;
+        }
+        if (virSetCloseExec(ctxt->readfd) < 0) {
+            virReportSystemError(errno, _("failed to set close-on-exec flag on %s"),
+                                 ctxt->path);
+            goto error;
+        }
+
+        if ((ctxt->pos = lseek(ctxt->writefd, 0, SEEK_END)) < 0) {
+            virReportSystemError(errno, _("failed to seek in log file %s"),
+                                 ctxt->path);
+            goto error;
+        }
+    }
+
+    return ctxt;
+
+ error:
+    g_clear_object(&ctxt);
+    return NULL;
+}
+
+
+int
+qemuLogContextWrite(qemuLogContext *ctxt,
+                    const char *fmt, ...)
+{
+    va_list argptr;
+    g_autofree char *message = NULL;
+    int ret = -1;
+
+    va_start(argptr, fmt);
+
+    message = g_strdup_vprintf(fmt, argptr);
+    if (!ctxt->manager &&
+        lseek(ctxt->writefd, 0, SEEK_END) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("Unable to seek to end of domain logfile"));
+        goto cleanup;
+    }
+    if (safewrite(ctxt->writefd, message, strlen(message)) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("Unable to write to domain logfile"));
+        goto cleanup;
+    }
+
+    ret = 0;
+
+ cleanup:
+    va_end(argptr);
+    return ret;
+}
+
+
+ssize_t
+qemuLogContextRead(qemuLogContext *ctxt,
+                   char **msg)
+{
+    char *buf;
+    size_t buflen;
+
+    VIR_DEBUG("Context read %p manager=%p inode=%llu pos=%llu",
+              ctxt, ctxt->manager,
+              (unsigned long long)ctxt->inode,
+              (unsigned long long)ctxt->pos);
+
+    if (ctxt->manager) {
+        buf = virLogManagerDomainReadLogFile(ctxt->manager,
+                                             ctxt->path,
+                                             ctxt->inode,
+                                             ctxt->pos,
+                                             1024 * 128,
+                                             0);
+        if (!buf)
+            return -1;
+        buflen = strlen(buf);
+    } else {
+        ssize_t got;
+
+        buflen = 1024 * 128;
+
+        /* Best effort jump to start of messages */
+        ignore_value(lseek(ctxt->readfd, ctxt->pos, SEEK_SET));
+
+        buf = g_new0(char, buflen);
+
+        got = saferead(ctxt->readfd, buf, buflen - 1);
+        if (got < 0) {
+            VIR_FREE(buf);
+            virReportSystemError(errno, "%s",
+                                 _("Unable to read from log file"));
+            return -1;
+        }
+
+        buf[got] = '\0';
+
+        buf = g_renew(char, buf, got + 1);
+        buflen = got;
+    }
+
+    *msg = buf;
+
+    return buflen;
+}
+
+
+int
+qemuLogContextGetWriteFD(qemuLogContext *ctxt)
+{
+    return ctxt->writefd;
+}
+
+
+void
+qemuLogContextMarkPosition(qemuLogContext *ctxt)
+{
+    if (ctxt->manager)
+        virLogManagerDomainGetLogFilePosition(ctxt->manager,
+                                              ctxt->path,
+                                              0,
+                                              &ctxt->inode,
+                                              &ctxt->pos);
+    else
+        ctxt->pos = lseek(ctxt->writefd, 0, SEEK_END);
+}
+
+
+virLogManager *
+qemuLogContextGetManager(qemuLogContext *ctxt)
+{
+    return ctxt->manager;
+}
diff --git a/src/qemu/qemu_logcontext.h b/src/qemu/qemu_logcontext.h
new file mode 100644
index 0000000000..c6dbf3cb84
--- /dev/null
+++ b/src/qemu/qemu_logcontext.h
@@ -0,0 +1,38 @@
+/*
+ * qemu_logcontext.h: QEMU log context
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <glib-object.h>
+#include "qemu_conf.h"
+#include "logging/log_manager.h"
+
+#define QEMU_TYPE_LOG_CONTEXT qemu_log_context_get_type()
+G_DECLARE_FINAL_TYPE(qemuLogContext, qemu_log_context, QEMU, LOG_CONTEXT, GObject);
+
+qemuLogContext *qemuLogContextNew(virQEMUDriver *driver,
+                                  virDomainObj *vm,
+                                  const char *basename);
+int qemuLogContextWrite(qemuLogContext *ctxt,
+                        const char *fmt, ...) G_GNUC_PRINTF(2, 3);
+ssize_t qemuLogContextRead(qemuLogContext *ctxt,
+                                 char **msg);
+int qemuLogContextGetWriteFD(qemuLogContext *ctxt);
+void qemuLogContextMarkPosition(qemuLogContext *ctxt);
+
+virLogManager *qemuLogContextGetManager(qemuLogContext *ctxt);
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index a2118c4f09..db25f26057 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -1812,7 +1812,7 @@ qemuProcessMonitorReportLogError(qemuMonitor *mon,
 static void
 qemuProcessMonitorLogFree(void *opaque)
 {
-    qemuDomainLogContext *logCtxt = opaque;
+    qemuLogContext *logCtxt = opaque;
     g_clear_object(&logCtxt);
 }
 
@@ -1838,7 +1838,7 @@ static int
 qemuConnectMonitor(virQEMUDriver *driver,
                    virDomainObj *vm,
                    int asyncJob,
-                   qemuDomainLogContext *logCtxt,
+                   qemuLogContext *logCtxt,
                    bool reconnect)
 {
     qemuDomainObjPrivate *priv = vm->privateData;
@@ -1902,7 +1902,7 @@ qemuConnectMonitor(virQEMUDriver *driver,
  * Returns 0 on success or -1 on error
  */
 static int
-qemuProcessReadLog(qemuDomainLogContext *logCtxt,
+qemuProcessReadLog(qemuLogContext *logCtxt,
                    char **msg,
                    size_t max)
 {
@@ -1912,7 +1912,7 @@ qemuProcessReadLog(qemuDomainLogContext *logCtxt,
     char *filter_next;
     size_t skip;
 
-    if ((got = qemuDomainLogContextRead(logCtxt, &buf)) < 0)
+    if ((got = qemuLogContextRead(logCtxt, &buf)) < 0)
         return -1;
 
     /* Filter out debug messages from intermediate libvirt process */
@@ -1955,7 +1955,7 @@ qemuProcessReadLog(qemuDomainLogContext *logCtxt,
 
 
 static int
-qemuProcessReportLogError(qemuDomainLogContext *logCtxt,
+qemuProcessReportLogError(qemuLogContext *logCtxt,
                           const char *msgprefix)
 {
     g_autofree char *logmsg = NULL;
@@ -1980,7 +1980,7 @@ qemuProcessMonitorReportLogError(qemuMonitor *mon G_GNUC_UNUSED,
                                  const char *msg,
                                  void *opaque)
 {
-    qemuDomainLogContext *logCtxt = opaque;
+    qemuLogContext *logCtxt = opaque;
     qemuProcessReportLogError(logCtxt, msg);
 }
 
@@ -2282,7 +2282,7 @@ static int
 qemuProcessWaitForMonitor(virQEMUDriver *driver,
                           virDomainObj *vm,
                           int asyncJob,
-                          qemuDomainLogContext *logCtxt)
+                          qemuLogContext *logCtxt)
 {
     int ret = -1;
     g_autoptr(GHashTable) info = NULL;
@@ -4657,7 +4657,7 @@ static void
 qemuLogOperation(virDomainObj *vm,
                  const char *msg,
                  virCommand *cmd,
-                 qemuDomainLogContext *logCtxt)
+                 qemuLogContext *logCtxt)
 {
     g_autofree char *timestamp = NULL;
     qemuDomainObjPrivate *priv = vm->privateData;
@@ -4671,20 +4671,20 @@ qemuLogOperation(virDomainObj *vm,
     if ((timestamp = virTimeStringNow()) == NULL)
         return;
 
-    if (qemuDomainLogContextWrite(logCtxt,
-                                  "%s: %s %s, qemu version: %d.%d.%d%s, kernel: %s, hostname: %s\n",
-                                  timestamp, msg, VIR_LOG_VERSION_STRING,
-                                  (qemuVersion / 1000000) % 1000,
-                                  (qemuVersion / 1000) % 1000,
-                                  qemuVersion % 1000,
-                                  NULLSTR_EMPTY(package),
-                                  uts.release,
-                                  NULLSTR_EMPTY(hostname)) < 0)
+    if (qemuLogContextWrite(logCtxt,
+                            "%s: %s %s, qemu version: %d.%d.%d%s, kernel: %s, hostname: %s\n",
+                            timestamp, msg, VIR_LOG_VERSION_STRING,
+                            (qemuVersion / 1000000) % 1000,
+                            (qemuVersion / 1000) % 1000,
+                            qemuVersion % 1000,
+                            NULLSTR_EMPTY(package),
+                            uts.release,
+                            NULLSTR_EMPTY(hostname)) < 0)
         return;
 
     if (cmd) {
         g_autofree char *args = virCommandToString(cmd, true);
-        qemuDomainLogContextWrite(logCtxt, "%s\n", args);
+        qemuLogContextWrite(logCtxt, "%s\n", args);
     }
 }
 
@@ -7634,7 +7634,7 @@ qemuProcessLaunch(virConnectPtr conn,
     int ret = -1;
     int rv;
     int logfile = -1;
-    g_autoptr(qemuDomainLogContext) logCtxt = NULL;
+    g_autoptr(qemuLogContext) logCtxt = NULL;
     qemuDomainObjPrivate *priv = vm->privateData;
     g_autoptr(virCommand) cmd = NULL;
     struct qemuProcessHookData hookData;
@@ -7683,11 +7683,11 @@ qemuProcessLaunch(virConnectPtr conn,
     hookData.cfg = cfg;
 
     VIR_DEBUG("Creating domain log file");
-    if (!(logCtxt = qemuDomainLogContextNew(driver, vm, vm->def->name))) {
+    if (!(logCtxt = qemuLogContextNew(driver, vm, vm->def->name))) {
         virLastErrorPrefixMessage("%s", _("can't connect to virtlogd"));
         goto cleanup;
     }
-    logfile = qemuDomainLogContextGetWriteFD(logCtxt);
+    logfile = qemuLogContextGetWriteFD(logCtxt);
 
     if (qemuProcessGenID(vm, flags) < 0)
         goto cleanup;
@@ -7717,7 +7717,7 @@ qemuProcessLaunch(virConnectPtr conn,
 
     qemuDomainObjCheckTaint(driver, vm, logCtxt, incoming != NULL);
 
-    qemuDomainLogContextMarkPosition(logCtxt);
+    qemuLogContextMarkPosition(logCtxt);
 
     VIR_DEBUG("Building mount namespace");
 
-- 
2.39.0



More information about the libvir-list mailing list