[PATCH v2 12/15] virDomainGetMessages: Introduce VIR_DOMAIN_MESSAGE_IOERRORS

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Report any stored I/O error messages reported by the hypervisor when
reporting messages of a domain. As the I/O error may be already stale we
report also the timestamp when it was recorded.

Example message:

 I/O error: disk='vda', index='1', path='/dev/mapper/errdev0', timestamp='2025-01-28 15:47:52.776+0000', message'Input/output error'

Signed-off-by: Peter Krempa <pkrempa@xxxxxxxxxx>
---
 include/libvirt/libvirt-domain.h |  3 ++
 src/conf/domain_conf.c           | 50 ++++++++++++++++++++++++++++++++
 src/conf/domain_conf.h           |  5 ++++
 src/libvirt_private.syms         |  1 +
 src/libxl/libxl_driver.c         |  3 +-
 src/qemu/qemu_driver.c           | 15 +++++++++-
 src/test/test_driver.c           |  3 +-
 7 files changed, 77 insertions(+), 3 deletions(-)

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 74016c6c46..9e9016cfe7 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -6520,6 +6520,9 @@ int virDomainAuthorizedSSHKeysSet(virDomainPtr domain,
 typedef enum {
     VIR_DOMAIN_MESSAGE_DEPRECATION = (1 << 0), /* (Since: 7.1.0) */
     VIR_DOMAIN_MESSAGE_TAINTING = (1 << 1), /* (Since: 7.1.0) */
+    VIR_DOMAIN_MESSAGE_IOERRORS = (1 << 2), /* Report available stored I/O
+                                               errors messages for disk images
+                                               (Since: 11.1.0) */
 } virDomainMessageType;

 int virDomainGetMessages(virDomainPtr domain,
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 00d486e774..548bc82308 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -31682,6 +31682,47 @@ virHostdevIsPCIDevice(const virDomainHostdevDef *hostdev)
 }


+static void
+virDomainObjGetMessagesIOErrorsSrc(virStorageSource *src,
+                                   const char *diskdst,
+                                   GPtrArray *m)
+{
+    if (!src ||
+        !src->ioerror_message)
+        return;
+
+    g_ptr_array_add(m, g_strdup_printf(_("I/O error: disk='%1$s', index='%2$d', path='%3$s', timestamp='%4$s', message'%5$s'"),
+                                       NULLSTR_MINUS(diskdst),
+                                       src->id,
+                                       NULLSTR_MINUS(src->path),
+                                       src->ioerror_timestamp,
+                                       src->ioerror_message));
+}
+
+
+void
+virDomainObjGetMessagesIOErrorsChain(virStorageSource *src,
+                                     const char *diskdst,
+                                     GPtrArray *m)
+{
+    virStorageSource *n;
+
+    for (n = src; n; n = n->backingStore) {
+        virDomainObjGetMessagesIOErrorsSrc(n, diskdst, m);
+        virDomainObjGetMessagesIOErrorsSrc(n->dataFileStore, diskdst, m);
+    }
+}
+
+
+static void
+virDomainObjGetMessagesIOErrorsDisk(virDomainDiskDef *disk,
+                                    GPtrArray *m)
+{
+    virDomainObjGetMessagesIOErrorsChain(disk->src, disk->dst, m);
+    virDomainObjGetMessagesIOErrorsChain(disk->mirror, disk->dst, m);
+}
+
+
 /**
  * virDomainObjGetMessages:
  * @vm: domain object
@@ -31710,6 +31751,15 @@ virDomainObjGetMessages(virDomainObj *vm,
                                                vm->deprecations[i]));
         }
     }
+
+    if (!flags || (flags & VIR_DOMAIN_MESSAGE_IOERRORS)) {
+        if (vm->def->os.loader)
+            virDomainObjGetMessagesIOErrorsChain(vm->def->os.loader->nvram, NULL, m);
+
+        for (i = 0; i < vm->def->ndisks; i++)
+            virDomainObjGetMessagesIOErrorsDisk(vm->def->disks[i], m);
+    }
+
 }

 bool
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index e996d3c0de..e51c74b6d1 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -4588,6 +4588,11 @@ bool
 virHostdevIsPCIDevice(const virDomainHostdevDef *hostdev)
     ATTRIBUTE_NONNULL(1);

+void
+virDomainObjGetMessagesIOErrorsChain(virStorageSource *src,
+                                     const char *diskdst,
+                                     GPtrArray *m);
+
 void
 virDomainObjGetMessages(virDomainObj *vm,
                         GPtrArray *m,
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 2fe0a07944..406e6583a3 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -592,6 +592,7 @@ virDomainObjEndAPI;
 virDomainObjFormat;
 virDomainObjGetDefs;
 virDomainObjGetMessages;
+virDomainObjGetMessagesIOErrorsChain;
 virDomainObjGetMetadata;
 virDomainObjGetOneDef;
 virDomainObjGetOneDefState;
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index 426c2b4278..a76545c9ff 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -6580,7 +6580,8 @@ libxlDomainGetMessages(virDomainPtr dom,
     int ret = -1;

     virCheckFlags(VIR_DOMAIN_MESSAGE_DEPRECATION |
-                  VIR_DOMAIN_MESSAGE_TAINTING, -1);
+                  VIR_DOMAIN_MESSAGE_TAINTING |
+                  VIR_DOMAIN_MESSAGE_IOERRORS, -1);

     if (!(vm = libxlDomObjFromDomain(dom)))
         return -1;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 8327e7079c..50733a5b3a 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -19821,9 +19821,11 @@ qemuDomainGetMessages(virDomainPtr dom,
     g_autoptr(GPtrArray) m = g_ptr_array_new_with_free_func(g_free);
     virDomainObj *vm = NULL;
     int rv = -1;
+    qemuDomainObjPrivate *priv;

     virCheckFlags(VIR_DOMAIN_MESSAGE_DEPRECATION |
-                  VIR_DOMAIN_MESSAGE_TAINTING, -1);
+                  VIR_DOMAIN_MESSAGE_TAINTING |
+                  VIR_DOMAIN_MESSAGE_IOERRORS, -1);

     if (!(vm = qemuDomainObjFromDomain(dom)))
         return -1;
@@ -19831,8 +19833,19 @@ qemuDomainGetMessages(virDomainPtr dom,
     if (virDomainGetMessagesEnsureACL(dom->conn, vm->def) < 0)
         goto cleanup;

+    priv = vm->privateData;
+
     virDomainObjGetMessages(vm, m, flags);

+    if (priv->backup) {
+        size_t i;
+
+        for (i = 0; i < priv->backup->ndisks; i++)
+            virDomainObjGetMessagesIOErrorsChain(priv->backup->disks[i].store,
+                                                 priv->backup->disks[i].name,
+                                                 m);
+    }
+
     rv = m->len;
     if (m->len > 0) {
         g_ptr_array_add(m, NULL);
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index a10ec3bc41..6f18b2b2c8 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -9527,7 +9527,8 @@ testDomainGetMessages(virDomainPtr dom,
     int rv = -1;

     virCheckFlags(VIR_DOMAIN_MESSAGE_DEPRECATION |
-                  VIR_DOMAIN_MESSAGE_TAINTING, -1);
+                  VIR_DOMAIN_MESSAGE_TAINTING |
+                  VIR_DOMAIN_MESSAGE_IOERRORS, -1);

     if (!(vm = testDomObjFromDomain(dom)))
         return -1;
-- 
2.48.1




[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]

  Powered by Linux