From b4154f389e688beafc9cbfae7e868fa406c8448d Mon Sep 17 00:00:00 2001 Message-ID: From: Peter Krempa Date: Mon, 27 Jan 2025 19:13:43 +0100 Subject: [PATCH] virDomainGetMessages: Introduce VIR_DOMAIN_MESSAGE_IOERRORS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Daniel P. Berrangé (cherry picked from commit 666219f5f166ac3cebe4854bcefddd449a98ad04) https://issues.redhat.com/browse/RHEL-77884 --- 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 | 16 +++++++++- src/test/test_driver.c | 3 +- 7 files changed, 78 insertions(+), 3 deletions(-) diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index d4f1573954..92a32f1cde 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -6490,6 +6490,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 8cd0fb83b6..d83f1ba240 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -31643,6 +31643,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 @@ -31671,6 +31712,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 7058203e67..5237046196 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -4576,6 +4576,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 43e2dfb9cd..7d404fdbf5 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -590,6 +590,7 @@ virDomainObjEndAPI; virDomainObjFormat; virDomainObjGetDefs; virDomainObjGetMessages; +virDomainObjGetMessagesIOErrorsChain; virDomainObjGetMetadata; virDomainObjGetOneDef; virDomainObjGetOneDefState; diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 545d67de52..29dcee3cfc 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -6577,7 +6577,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 276a7caded..9a69574f31 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -19814,9 +19814,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; @@ -19824,8 +19826,20 @@ qemuDomainGetMessages(virDomainPtr dom, if (virDomainGetMessagesEnsureACL(dom->conn, vm->def) < 0) goto cleanup; + priv = vm->privateData; + virDomainObjGetMessages(vm, m, flags); + if (priv->backup && + (!flags || (flags & VIR_DOMAIN_MESSAGE_IOERRORS))) { + 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