diff --git a/libvirt-build-Bump-minimum-glib2-version-to-2.66.0.patch b/libvirt-build-Bump-minimum-glib2-version-to-2.66.0.patch new file mode 100644 index 0000000..b4cb8ad --- /dev/null +++ b/libvirt-build-Bump-minimum-glib2-version-to-2.66.0.patch @@ -0,0 +1,286 @@ +From 9a27bfdfb50f42b27acf6998f95721461fc0706a Mon Sep 17 00:00:00 2001 +Message-ID: <9a27bfdfb50f42b27acf6998f95721461fc0706a.1738937224.git.jdenemar@redhat.com> +From: Peter Krempa +Date: Mon, 27 Jan 2025 17:42:34 +0100 +Subject: [PATCH] build: Bump minimum glib2 version to 2.66.0 + +Per our supported platforms the minimum available versions are: + + CentOS Stream 9: 2.68.4 + Debian 11: 2.66.8 + Fedora 39: 2.78.6 + openSUSE Leap 15.6: 2.78.6 + Ubuntu 22.04: 2.72.4 + FreeBSD ports: 2.80.5 + macOS homebrew: 2.82.4 + macOS macports: 2.78.4 + +Bump to 2.66 which is limited by Debian 11. While ideally we'd bump to +2.68 which would give us 'g_strv_builder' and friends 2.66 is enough for +g_ptr_array_steal() which can be used to emulate the former with almost +no extra code. + +Signed-off-by: Peter Krempa +Reviewed-by: Pavel Hrdina +(cherry picked from commit 420c39d6bd66ccf4841878882f5a3e9e47103ebb) + +https://issues.redhat.com/browse/RHEL-76802 +--- + libvirt.spec.in | 2 +- + meson.build | 2 +- + src/libvirt_private.syms | 4 -- + src/qemu/qemu_agent.c | 2 +- + src/qemu/qemu_monitor.c | 2 +- + src/util/glibcompat.c | 94 ---------------------------------------- + src/util/glibcompat.h | 18 -------- + src/util/vireventglib.c | 12 ++--- + 8 files changed, 10 insertions(+), 126 deletions(-) + +diff --git a/meson.build b/meson.build +index 89ac1594cb..d3e2c939ea 100644 +--- a/meson.build ++++ b/meson.build +@@ -998,7 +998,7 @@ else + endif + endif + +-glib_version = '2.58.0' ++glib_version = '2.66.0' + glib_dep = dependency('glib-2.0', version: '>=' + glib_version) + gobject_dep = dependency('gobject-2.0', version: '>=' + glib_version) + if host_machine.system() == 'windows' +diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms +index c931003fad..43e2dfb9cd 100644 +--- a/src/libvirt_private.syms ++++ b/src/libvirt_private.syms +@@ -1871,10 +1871,6 @@ virStorageSourceUpdatePhysicalSize; + + + # util/glibcompat.h +-vir_g_fsync; +-vir_g_source_unref; +-vir_g_strdup_printf; +-vir_g_strdup_vprintf; + vir_g_string_replace; + + +diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c +index 22359f8518..43fca86f10 100644 +--- a/src/qemu/qemu_agent.c ++++ b/src/qemu/qemu_agent.c +@@ -448,7 +448,7 @@ qemuAgentUnregister(qemuAgent *agent) + { + if (agent->watch) { + g_source_destroy(agent->watch); +- vir_g_source_unref(agent->watch, agent->context); ++ g_source_unref(agent->watch); + agent->watch = NULL; + } + } +diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c +index 73f37d26eb..79bd91b539 100644 +--- a/src/qemu/qemu_monitor.c ++++ b/src/qemu/qemu_monitor.c +@@ -745,7 +745,7 @@ qemuMonitorUnregister(qemuMonitor *mon) + { + if (mon->watch) { + g_source_destroy(mon->watch); +- vir_g_source_unref(mon->watch, mon->context); ++ g_source_unref(mon->watch); + mon->watch = NULL; + } + } +diff --git a/src/util/glibcompat.c b/src/util/glibcompat.c +index 98dcfab389..bcb666992a 100644 +--- a/src/util/glibcompat.c ++++ b/src/util/glibcompat.c +@@ -63,100 +63,6 @@ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + +-#undef g_fsync +-#undef g_strdup_printf +-#undef g_strdup_vprintf +- +- +-/* Drop when min glib >= 2.63.0 */ +-gint +-vir_g_fsync(gint fd) +-{ +-#ifdef G_OS_WIN32 +- return _commit(fd); +-#else +- return fsync(fd); +-#endif +-} +- +- +-/* Due to a bug in glib, g_strdup_printf() nor g_strdup_vprintf() +- * abort on OOM. It's fixed in glib's upstream. Provide our own +- * implementation until the fix gets distributed. */ +-char * +-vir_g_strdup_printf(const char *msg, ...) +-{ +- va_list args; +- char *ret; +- va_start(args, msg); +- ret = g_strdup_vprintf(msg, args); +- if (!ret) +- abort(); +- va_end(args); +- return ret; +-} +- +- +-char * +-vir_g_strdup_vprintf(const char *msg, va_list args) +-{ +- char *ret; +- ret = g_strdup_vprintf(msg, args); +- if (!ret) +- abort(); +- return ret; +-} +- +- +-/* +- * If the last reference to a GSource is released in a non-main +- * thread we're exposed to a race condition that causes a +- * crash: +- * +- * https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1358 +- * +- * Thus we're using an idle func to release our ref... +- * +- * ...but this imposes a significant performance penalty on +- * I/O intensive workloads which are sensitive to the iterations +- * of the event loop, so avoid the workaround if we know we have +- * new enough glib. +- * +- * The function below is used from a header file definition. +- * +- * Drop when min glib >= 2.64.0 +- */ +-#if GLIB_CHECK_VERSION(2, 64, 0) +-void vir_g_source_unref(GSource *src, GMainContext *ctx G_GNUC_UNUSED) +-{ +- g_source_unref(src); +-} +-#else +- +-static gboolean +-virEventGLibSourceUnrefIdle(gpointer data) +-{ +- GSource *src = data; +- +- g_source_unref(src); +- +- return FALSE; +-} +- +-void vir_g_source_unref(GSource *src, GMainContext *ctx) +-{ +- GSource *idle = g_idle_source_new(); +- +- g_source_set_callback(idle, virEventGLibSourceUnrefIdle, src, NULL); +- +- g_source_attach(idle, ctx); +- +- g_source_unref(idle); +-} +- +-#endif +- +- + /** + * Adapted (to pass syntax check) from 'g_string_replace' from + * glib-2.81.1. Drop once minimum glib is bumped to 2.68. +diff --git a/src/util/glibcompat.h b/src/util/glibcompat.h +index 474ff95bc5..a3d01089e6 100644 +--- a/src/util/glibcompat.h ++++ b/src/util/glibcompat.h +@@ -42,24 +42,6 @@ + + #endif /* GLib < 2.67.0 */ + +- +-gint vir_g_fsync(gint fd); +-char *vir_g_strdup_printf(const char *msg, ...) +- G_GNUC_PRINTF(1, 2); +-char *vir_g_strdup_vprintf(const char *msg, va_list args) +- G_GNUC_PRINTF(1, 0); +- +-#if !GLIB_CHECK_VERSION(2, 64, 0) +-# define g_strdup_printf vir_g_strdup_printf +-# define g_strdup_vprintf vir_g_strdup_vprintf +-#endif +- +-#undef g_fsync +-#define g_fsync vir_g_fsync +- +-void vir_g_source_unref(GSource *src, GMainContext *ctx); +- +- + /* Drop once we require glib-2.68 at minimum */ + guint + vir_g_string_replace(GString *string, +diff --git a/src/util/vireventglib.c b/src/util/vireventglib.c +index 023dc37445..6c54f62123 100644 +--- a/src/util/vireventglib.c ++++ b/src/util/vireventglib.c +@@ -213,7 +213,7 @@ virEventGLibHandleUpdate(int watch, + if (data->source != NULL) { + VIR_DEBUG("Removed old handle source=%p", data->source); + g_source_destroy(data->source); +- vir_g_source_unref(data->source, NULL); ++ g_source_unref(data->source); + } + + data->source = virEventGLibAddSocketWatch( +@@ -227,7 +227,7 @@ virEventGLibHandleUpdate(int watch, + + VIR_DEBUG("Removed old handle source=%p", data->source); + g_source_destroy(data->source); +- vir_g_source_unref(data->source, NULL); ++ g_source_unref(data->source); + data->source = NULL; + data->events = 0; + } +@@ -276,7 +276,7 @@ virEventGLibHandleRemove(int watch) + + if (data->source != NULL) { + g_source_destroy(data->source); +- vir_g_source_unref(data->source, NULL); ++ g_source_unref(data->source); + data->source = NULL; + data->events = 0; + } +@@ -409,7 +409,7 @@ virEventGLibTimeoutUpdate(int timer, + if (interval >= 0) { + if (data->source != NULL) { + g_source_destroy(data->source); +- vir_g_source_unref(data->source, NULL); ++ g_source_unref(data->source); + } + + data->interval = interval; +@@ -419,7 +419,7 @@ virEventGLibTimeoutUpdate(int timer, + goto cleanup; + + g_source_destroy(data->source); +- vir_g_source_unref(data->source, NULL); ++ g_source_unref(data->source); + data->source = NULL; + } + +@@ -468,7 +468,7 @@ virEventGLibTimeoutRemove(int timer) + + if (data->source != NULL) { + g_source_destroy(data->source); +- vir_g_source_unref(data->source, NULL); ++ g_source_unref(data->source); + data->source = NULL; + } + +-- +2.48.1 diff --git a/libvirt-include-libvirt-domain-Add-message-reason-of-VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON.patch b/libvirt-include-libvirt-domain-Add-message-reason-of-VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON.patch new file mode 100644 index 0000000..77d580f --- /dev/null +++ b/libvirt-include-libvirt-domain-Add-message-reason-of-VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON.patch @@ -0,0 +1,69 @@ +From 1b184bd766a04506a7a4f115dd46afbbb8ce07c5 Mon Sep 17 00:00:00 2001 +Message-ID: <1b184bd766a04506a7a4f115dd46afbbb8ce07c5.1738937224.git.jdenemar@redhat.com> +From: Peter Krempa +Date: Fri, 24 Jan 2025 16:26:54 +0100 +Subject: [PATCH] include: libvirt-domain: Add 'message' @reason of + VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In case when the hypervisor does report the reason for the I/O error as +an unstable string to display to users we can add a @reason possibility +for the I/O error event noting that the error is available. + +Add 'message' as a reason enumeration value and document it +to instruct users to look at the logs or virDomainGetMessages(). + +The resulting event looks like: + + event 'io-error' for domain 'cd': /dev/mapper/errdev0 (virtio-disk0) report due to message + +Users then can look at the virDomainGetMessages() API: + + I/O error: disk='vda', index='1', path='/dev/mapper/errdev0', timestamp='2025-01-28 15:47:52.776+0000', message='Input/output error' + +Or in the VM log file: + + 2025-01-28 15:47:52.776+0000: IO error device='virtio-disk0' node-name='libvirt-1-storage' reason='Input/output error' + +Signed-off-by: Peter Krempa +Reviewed-by: Daniel P. Berrangé +(cherry picked from commit 97c47333cbdc2531260f7b11b1fa9ba828878343) + +https://issues.redhat.com/browse/RHEL-76802 +--- + include/libvirt/libvirt-domain.h | 4 ++++ + src/qemu/qemu_process.c | 2 ++ + 2 files changed, 6 insertions(+) + +diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h +index 1dc7b417c9..f026ce197c 100644 +--- a/include/libvirt/libvirt-domain.h ++++ b/include/libvirt/libvirt-domain.h +@@ -4782,6 +4782,10 @@ typedef void (*virConnectDomainEventIOErrorCallback)(virConnectPtr conn, + * - "enospc": The I/O error is known to be caused by an ENOSPC condition in + * the host. Resizing the disk source to be larger will allow the + * guest to be resumed as if nothing happened. ++ * - "message": The hypervisor reported a string description of the ++ * I/O error. The errors are usually logged into the ++ * domain log file or the last instance of the error ++ * string can be queried via virDomainGetMessages(). + * + * Since: 0.8.1 + */ +diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c +index 409734d948..b9d69649ca 100644 +--- a/src/qemu/qemu_process.c ++++ b/src/qemu/qemu_process.c +@@ -862,6 +862,8 @@ qemuProcessHandleIOError(qemuMonitor *mon G_GNUC_UNUSED, + + if (nospace) + eventReason = "enospc"; ++ else if (reason) ++ eventReason = "message"; + + ioErrorEvent = virDomainEventIOErrorNewFromObj(vm, eventPath, eventAlias, action); + ioErrorEvent2 = virDomainEventIOErrorReasonNewFromObj(vm, eventPath, eventAlias, action, eventReason); +-- +2.48.1 diff --git a/libvirt-include-libvirt-domain-Reword-documentation-for-reason-of-VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON.patch b/libvirt-include-libvirt-domain-Reword-documentation-for-reason-of-VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON.patch new file mode 100644 index 0000000..f1f0c63 --- /dev/null +++ b/libvirt-include-libvirt-domain-Reword-documentation-for-reason-of-VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON.patch @@ -0,0 +1,47 @@ +From 5ce72113702e5b48bde5234c0d6b9c951d998a1d Mon Sep 17 00:00:00 2001 +Message-ID: <5ce72113702e5b48bde5234c0d6b9c951d998a1d.1738937224.git.jdenemar@redhat.com> +From: Peter Krempa +Date: Mon, 27 Jan 2025 15:50:34 +0100 +Subject: [PATCH] include: libvirt-domain: Reword documentation for @reason of + VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Emphasise that it's an enumeration and convert the possibilities to a +list of values with explanation. + +Signed-off-by: Peter Krempa +Reviewed-by: Daniel P. Berrangé +(cherry picked from commit 3a3c5616eb2c50a58896f99f30d887937dab297a) + +https://issues.redhat.com/browse/RHEL-76802 +--- + include/libvirt/libvirt-domain.h | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h +index 92a32f1cde..1dc7b417c9 100644 +--- a/include/libvirt/libvirt-domain.h ++++ b/include/libvirt/libvirt-domain.h +@@ -4775,11 +4775,13 @@ typedef void (*virConnectDomainEventIOErrorCallback)(virConnectPtr conn, + * The callback signature to use when registering for an event of type + * VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON with virConnectDomainEventRegisterAny() + * +- * If the I/O error is known to be caused by an ENOSPC condition in +- * the host (where resizing the disk to be larger will allow the guest +- * to be resumed as if nothing happened), @reason will be "enospc". +- * Otherwise, @reason will be "", although future strings may be added +- * if determination of other error types becomes possible. ++ * Although @reason is a string, it is considered to be an enumeration of the ++ * following values: ++ * ++ * - "" (empty string): unknown I/O error reason ++ * - "enospc": The I/O error is known to be caused by an ENOSPC condition in ++ * the host. Resizing the disk source to be larger will allow the ++ * guest to be resumed as if nothing happened. + * + * Since: 0.8.1 + */ +-- +2.48.1 diff --git a/libvirt-libxlDomainGetMessages-Add-existing-flags-to-virCheckFlags.patch b/libvirt-libxlDomainGetMessages-Add-existing-flags-to-virCheckFlags.patch new file mode 100644 index 0000000..5235975 --- /dev/null +++ b/libvirt-libxlDomainGetMessages-Add-existing-flags-to-virCheckFlags.patch @@ -0,0 +1,37 @@ +From 8f734969bbaf0e68fb67f7106c037fee274bef9f Mon Sep 17 00:00:00 2001 +Message-ID: <8f734969bbaf0e68fb67f7106c037fee274bef9f.1738937224.git.jdenemar@redhat.com> +From: Peter Krempa +Date: Tue, 28 Jan 2025 14:06:16 +0100 +Subject: [PATCH] libxlDomainGetMessages: Add existing flags to 'virCheckFlags' +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The two VIR_DOMAIN_MESSAGE_* flags were not listed in the virCheckFlags +check in 'libxl' but were present in 'test' and 'qemu' driver impls. + +Signed-off-by: Peter Krempa +Reviewed-by: Daniel P. Berrangé +(cherry picked from commit 042ea8630b1b35ce6d325df52fefa84bad94d027) + +https://issues.redhat.com/browse/RHEL-76802 +--- + src/libxl/libxl_driver.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c +index e72553603d..26d22550ae 100644 +--- a/src/libxl/libxl_driver.c ++++ b/src/libxl/libxl_driver.c +@@ -6575,7 +6575,8 @@ libxlDomainGetMessages(virDomainPtr dom, + virDomainObj *vm = NULL; + int ret = -1; + +- virCheckFlags(0, -1); ++ virCheckFlags(VIR_DOMAIN_MESSAGE_DEPRECATION | ++ VIR_DOMAIN_MESSAGE_TAINTING, -1); + + if (!(vm = libxlDomObjFromDomain(dom))) + return -1; +-- +2.48.1 diff --git a/libvirt-qemu-Handle-quirks-of-device-field-of-BLOCK_IO_ERROR-event-in-monitor-code.patch b/libvirt-qemu-Handle-quirks-of-device-field-of-BLOCK_IO_ERROR-event-in-monitor-code.patch new file mode 100644 index 0000000..7f63304 --- /dev/null +++ b/libvirt-qemu-Handle-quirks-of-device-field-of-BLOCK_IO_ERROR-event-in-monitor-code.patch @@ -0,0 +1,66 @@ +From 53a7b2cc3a550791f69d6b78d12cadb02a43d247 Mon Sep 17 00:00:00 2001 +Message-ID: <53a7b2cc3a550791f69d6b78d12cadb02a43d247.1738937224.git.jdenemar@redhat.com> +From: Peter Krempa +Date: Mon, 27 Jan 2025 13:03:58 +0100 +Subject: [PATCH] qemu: Handle quirks of 'device' field of BLOCK_IO_ERROR event + in monitor code +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +BLOCK_IO_ERROR's 'device' field is an empty string in case when it isn't +applicable as it was originally mandatory in the qemu API docs. + +Move the logic that convert's empty string back to NULL from +'qemuProcessHandleIOError()' to 'qemuMonitorJSONHandleIOError()' + +This also fixes a hypothetical NULL-dereference if qemu would indeed +report an IO error without the 'device' field present. + +Signed-off-by: Peter Krempa +Reviewed-by: Daniel P. Berrangé +(cherry picked from commit 2f8359f827ce92e0b454eca55640a928367131fd) + +https://issues.redhat.com/browse/RHEL-76802 +--- + src/qemu/qemu_monitor_json.c | 9 ++++++++- + src/qemu/qemu_process.c | 3 --- + 2 files changed, 8 insertions(+), 4 deletions(-) + +diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c +index 1b4288b744..345e9383e3 100644 +--- a/src/qemu/qemu_monitor_json.c ++++ b/src/qemu/qemu_monitor_json.c +@@ -708,8 +708,15 @@ qemuMonitorJSONHandleIOError(qemuMonitor *mon, virJSONValue *data) + action = "ignore"; + } + +- if ((device = virJSONValueObjectGetString(data, "device")) == NULL) ++ if ((device = virJSONValueObjectGetString(data, "device")) == NULL) { + VIR_WARN("missing device in disk io error event"); ++ } else { ++ /* 'device' was documented as mandatory in the qemu event, but later became ++ * optional, in which case an empty string is sent by qemu. Convert it back ++ * to NULL */ ++ if (*device == '\0') ++ device = NULL; ++ } + + nodename = virJSONValueObjectGetString(data, "node-name"); + +diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c +index c618fbf69c..b4f6d358f3 100644 +--- a/src/qemu/qemu_process.c ++++ b/src/qemu/qemu_process.c +@@ -840,9 +840,6 @@ qemuProcessHandleIOError(qemuMonitor *mon G_GNUC_UNUSED, + virObjectLock(vm); + priv = QEMU_DOMAIN_PRIVATE(vm); + +- if (*diskAlias == '\0') +- diskAlias = NULL; +- + if (diskAlias) + disk = qemuProcessFindDomainDiskByAliasOrQOM(vm, diskAlias, NULL); + else if (nodename) +-- +2.48.1 diff --git a/libvirt-qemu-Rename-diskAlias-to-device-in-qemu-IO-error-event-handling.patch b/libvirt-qemu-Rename-diskAlias-to-device-in-qemu-IO-error-event-handling.patch new file mode 100644 index 0000000..1b57844 --- /dev/null +++ b/libvirt-qemu-Rename-diskAlias-to-device-in-qemu-IO-error-event-handling.patch @@ -0,0 +1,93 @@ +From de943558accd1623655f121fe9864b8b7ffc44e2 Mon Sep 17 00:00:00 2001 +Message-ID: +From: Peter Krempa +Date: Mon, 27 Jan 2025 13:42:36 +0100 +Subject: [PATCH] qemu: Rename 'diskAlias' to 'device' in qemu IO error event + handling +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The field is named 'device' in the event so unify our naming. + +Signed-off-by: Peter Krempa +Reviewed-by: Daniel P. Berrangé +(cherry picked from commit 2d6bd6f05fc57839093850ebfc06c9b4e02b4f67) + +https://issues.redhat.com/browse/RHEL-76802 +--- + src/qemu/qemu_monitor.c | 4 ++-- + src/qemu/qemu_monitor.h | 4 ++-- + src/qemu/qemu_process.c | 6 +++--- + 3 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c +index 79bd91b539..e98da5fbff 100644 +--- a/src/qemu/qemu_monitor.c ++++ b/src/qemu/qemu_monitor.c +@@ -1127,7 +1127,7 @@ qemuMonitorEmitWatchdog(qemuMonitor *mon, int action) + + void + qemuMonitorEmitIOError(qemuMonitor *mon, +- const char *diskAlias, ++ const char *device, + const char *nodename, + int action, + const char *reason) +@@ -1135,7 +1135,7 @@ qemuMonitorEmitIOError(qemuMonitor *mon, + VIR_DEBUG("mon=%p", mon); + + QEMU_MONITOR_CALLBACK(mon, domainIOError, mon->vm, +- diskAlias, nodename, action, reason); ++ device, nodename, action, reason); + } + + +diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h +index 89a59dfd27..0ab60f286d 100644 +--- a/src/qemu/qemu_monitor.h ++++ b/src/qemu/qemu_monitor.h +@@ -206,7 +206,7 @@ typedef void (*qemuMonitorDomainWatchdogCallback)(qemuMonitor *mon, + int action); + typedef void (*qemuMonitorDomainIOErrorCallback)(qemuMonitor *mon, + virDomainObj *vm, +- const char *diskAlias, ++ const char *device, + const char *nodename, + int action, + const char *reason); +@@ -450,7 +450,7 @@ void qemuMonitorEmitResume(qemuMonitor *mon); + void qemuMonitorEmitRTCChange(qemuMonitor *mon, long long offset); + void qemuMonitorEmitWatchdog(qemuMonitor *mon, int action); + void qemuMonitorEmitIOError(qemuMonitor *mon, +- const char *diskAlias, ++ const char *device, + const char *nodename, + int action, + const char *reason); +diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c +index b4f6d358f3..3861d91228 100644 +--- a/src/qemu/qemu_process.c ++++ b/src/qemu/qemu_process.c +@@ -824,7 +824,7 @@ qemuProcessHandleWatchdog(qemuMonitor *mon G_GNUC_UNUSED, + static void + qemuProcessHandleIOError(qemuMonitor *mon G_GNUC_UNUSED, + virDomainObj *vm, +- const char *diskAlias, ++ const char *device, + const char *nodename, + int action, + const char *reason) +@@ -840,8 +840,8 @@ qemuProcessHandleIOError(qemuMonitor *mon G_GNUC_UNUSED, + virObjectLock(vm); + priv = QEMU_DOMAIN_PRIVATE(vm); + +- if (diskAlias) +- disk = qemuProcessFindDomainDiskByAliasOrQOM(vm, diskAlias, NULL); ++ if (device) ++ disk = qemuProcessFindDomainDiskByAliasOrQOM(vm, device, NULL); + else if (nodename) + disk = qemuDomainDiskLookupByNodename(vm->def, NULL, nodename, NULL); + else +-- +2.48.1 diff --git a/libvirt-qemu-domain-Initialize-FD-passthrough-for-a-virStorageSource-before-using-it.patch b/libvirt-qemu-domain-Initialize-FD-passthrough-for-a-virStorageSource-before-using-it.patch new file mode 100644 index 0000000..da9be2b --- /dev/null +++ b/libvirt-qemu-domain-Initialize-FD-passthrough-for-a-virStorageSource-before-using-it.patch @@ -0,0 +1,85 @@ +From 76ca496fe71d36346389f6e3e8959f360c4eead2 Mon Sep 17 00:00:00 2001 +Message-ID: <76ca496fe71d36346389f6e3e8959f360c4eead2.1738937224.git.jdenemar@redhat.com> +From: Peter Krempa +Date: Thu, 6 Feb 2025 16:20:45 +0100 +Subject: [PATCH] qemu: domain: Initialize FD passthrough for a + virStorageSource before using it + +The call to 'qemuBlockStorageSourceNeedsFormatLayer()' bases the +decision also on the state of the passed FD, so we must initialize the +passthrough data via 'qemuDomainPrepareStorageSourceFDs()' before the +aforementioned call. + +In the test change it's visible that we didn't add the necessary 'raw' +driver which allows the 'protocol' blockdev to be opened in 'rw' mode so +that qemu picks the proper file descriptior while keeping the device +read-only. + +Resolves: https://issues.redhat.com/browse/RHEL-37519 +Signed-off-by: Peter Krempa +Reviewed-by: Jiri Denemark +(cherry picked from commit 5830e564bbeb798cccce2988094d1218f6dc5a60) + +https://issues.redhat.com/browse/RHEL-78353 +--- + src/qemu/qemu_domain.c | 6 +++--- + .../qemuxmlconfdata/disk-source-fd.x86_64-latest.args | 10 ++++++---- + 2 files changed, 9 insertions(+), 7 deletions(-) + +diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c +index 1fc4e2f33f..92035dd281 100644 +--- a/src/qemu/qemu_domain.c ++++ b/src/qemu/qemu_domain.c +@@ -9677,6 +9677,9 @@ qemuDomainPrepareStorageSourceBlockdevNodename(virDomainDiskDef *disk, + /* qemuBlockStorageSourceSetStorageNodename steals 'nodestorage' */ + qemuBlockStorageSourceSetStorageNodename(src, nodestorage); + ++ if (qemuDomainPrepareStorageSourceFDs(src, priv) < 0) ++ return -1; ++ + if (qemuBlockStorageSourceNeedsFormatLayer(src, priv->qemuCaps)) { + char *nodeformat = g_strdup_printf("%s-format", nodenameprefix); + +@@ -9717,9 +9720,6 @@ qemuDomainPrepareStorageSourceBlockdevNodename(virDomainDiskDef *disk, + if (qemuDomainPrepareStorageSourceNFS(src) < 0) + return -1; + +- if (qemuDomainPrepareStorageSourceFDs(src, priv) < 0) +- return -1; +- + return 0; + } + +diff --git a/tests/qemuxmlconfdata/disk-source-fd.x86_64-latest.args b/tests/qemuxmlconfdata/disk-source-fd.x86_64-latest.args +index d77b3ca505..27d852cf32 100644 +--- a/tests/qemuxmlconfdata/disk-source-fd.x86_64-latest.args ++++ b/tests/qemuxmlconfdata/disk-source-fd.x86_64-latest.args +@@ -33,11 +33,12 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ + -blockdev '{"node-name":"libvirt-6-format","read-only":false,"driver":"qcow2","file":"libvirt-6-storage"}' \ + -device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x2","drive":"libvirt-6-format","id":"virtio-disk4","bootindex":1}' \ + -add-fd set=4,fd=209,opaque=libvirt-5-storage0 \ +--blockdev '{"driver":"file","filename":"/dev/fdset/4","node-name":"libvirt-5-storage","read-only":true}' \ ++-blockdev '{"driver":"file","filename":"/dev/fdset/4","node-name":"libvirt-5-storage","read-only":false,"discard":"unmap"}' \ ++-blockdev '{"node-name":"libvirt-5-format","read-only":true,"driver":"raw","file":"libvirt-5-storage"}' \ + -add-fd set=3,fd=247,opaque=libvirt-4-storage0 \ + -add-fd set=3,fd=248,opaque=libvirt-4-storage1 \ + -blockdev '{"driver":"file","filename":"/dev/fdset/3","node-name":"libvirt-4-storage","auto-read-only":true,"discard":"unmap"}' \ +--blockdev '{"node-name":"libvirt-4-format","read-only":true,"driver":"qcow2","file":"libvirt-4-storage","backing":"libvirt-5-storage"}' \ ++-blockdev '{"node-name":"libvirt-4-format","read-only":true,"driver":"qcow2","file":"libvirt-4-storage","backing":"libvirt-5-format"}' \ + -add-fd set=2,fd=204,opaque=libvirt-3-storage0 \ + -blockdev '{"driver":"file","filename":"/dev/fdset/2","node-name":"libvirt-3-storage","read-only":false,"discard":"unmap"}' \ + -blockdev '{"node-name":"libvirt-3-format","read-only":false,"driver":"qcow2","file":"libvirt-3-storage","backing":"libvirt-4-format"}' \ +@@ -46,8 +47,9 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ + -blockdev '{"driver":"file","filename":"/dev/fdset/1","node-name":"libvirt-2-storage","read-only":true}' \ + -device '{"driver":"ide-cd","bus":"ide.0","unit":0,"drive":"libvirt-2-storage","id":"ide0-0-0"}' \ + -add-fd set=0,fd=208,opaque=libvirt-1-storage0 \ +--blockdev '{"driver":"file","filename":"/dev/fdset/0","node-name":"libvirt-1-storage","read-only":true}' \ +--device '{"driver":"ide-cd","bus":"ide.0","unit":1,"drive":"libvirt-1-storage","id":"ide0-0-1"}' \ ++-blockdev '{"driver":"file","filename":"/dev/fdset/0","node-name":"libvirt-1-storage","read-only":false,"discard":"unmap"}' \ ++-blockdev '{"node-name":"libvirt-1-format","read-only":true,"driver":"raw","file":"libvirt-1-storage"}' \ ++-device '{"driver":"ide-cd","bus":"ide.0","unit":1,"drive":"libvirt-1-format","id":"ide0-0-1"}' \ + -audiodev '{"id":"audio1","driver":"none"}' \ + -device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x4"}' \ + -sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-- +2.48.1 diff --git a/libvirt-qemu-process-Export-qemuPrepareNVRAM-for-use-in-snapshot-code.patch b/libvirt-qemu-process-Export-qemuPrepareNVRAM-for-use-in-snapshot-code.patch new file mode 100644 index 0000000..0cd41da --- /dev/null +++ b/libvirt-qemu-process-Export-qemuPrepareNVRAM-for-use-in-snapshot-code.patch @@ -0,0 +1,109 @@ +From c85ea17d124a3dd2d25818758e963612c803474c Mon Sep 17 00:00:00 2001 +Message-ID: +From: Peter Krempa +Date: Mon, 3 Feb 2025 17:48:05 +0100 +Subject: [PATCH] qemu: process: Export qemuPrepareNVRAM for use in snapshot + code + +Export qemuPrepareNVRAM so that it doesn't require the VM object. The +snapshot code needs in the corner case of creating a snapshot of a +freshly defined VM ensure that the nvram image exists in order to +snapshot it. + +Signed-off-by: Peter Krempa +Reviewed-by: Pavel Hrdina +(cherry picked from commit a377404ed912e8d17e88ef3eb8e71143eff88f7d) + +https://issues.redhat.com/browse/RHEL-78186 +--- + src/qemu/qemu_process.c | 26 ++++++++++++++------------ + src/qemu/qemu_process.h | 4 ++++ + 2 files changed, 18 insertions(+), 12 deletions(-) + +diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c +index b9d69649ca..1866c8f4e1 100644 +--- a/src/qemu/qemu_process.c ++++ b/src/qemu/qemu_process.c +@@ -4627,10 +4627,9 @@ qemuPrepareNVRAMHelper(int dstFD, + + + static int +-qemuPrepareNVRAMBlock(virDomainObj *vm, ++qemuPrepareNVRAMBlock(virDomainLoaderDef *loader, + bool reset_nvram) + { +- virDomainLoaderDef *loader = vm->def->os.loader; + g_autoptr(virCommand) qemuimg = NULL; + const char *templateFormatStr = "raw"; + +@@ -4691,13 +4690,12 @@ qemuPrepareNVRAMBlock(virDomainObj *vm, + + + static int +-qemuPrepareNVRAMFile(virDomainObj *vm, ++qemuPrepareNVRAMFile(virQEMUDriver *driver, ++ virDomainLoaderDef *loader, + bool reset_nvram) + { +- qemuDomainObjPrivate *priv = vm->privateData; +- g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(priv->driver); ++ g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); + VIR_AUTOCLOSE srcFD = -1; +- virDomainLoaderDef *loader = vm->def->os.loader; + struct qemuPrepareNVRAMHelperData data; + + if (virFileExists(loader->nvram->path) && !reset_nvram) +@@ -4739,21 +4737,24 @@ qemuPrepareNVRAMFile(virDomainObj *vm, + } + + +-static int +-qemuPrepareNVRAM(virDomainObj *vm, ++int ++qemuPrepareNVRAM(virQEMUDriver *driver, ++ virDomainDef *def, + bool reset_nvram) + { +- virDomainLoaderDef *loader = vm->def->os.loader; ++ virDomainLoaderDef *loader = def->os.loader; + + if (!loader || !loader->nvram) + return 0; + ++ VIR_DEBUG("nvram='%s'", NULLSTR(loader->nvram->path)); ++ + switch (virStorageSourceGetActualType(loader->nvram)) { + case VIR_STORAGE_TYPE_FILE: +- return qemuPrepareNVRAMFile(vm, reset_nvram); ++ return qemuPrepareNVRAMFile(driver, loader, reset_nvram); + + case VIR_STORAGE_TYPE_BLOCK: +- return qemuPrepareNVRAMBlock(vm, reset_nvram); ++ return qemuPrepareNVRAMBlock(loader, reset_nvram); + + case VIR_STORAGE_TYPE_DIR: + case VIR_STORAGE_TYPE_NETWORK: +@@ -7408,7 +7409,8 @@ qemuProcessPrepareHost(virQEMUDriver *driver, + qemuProcessMakeDir(driver, vm, priv->channelTargetDir) < 0) + return -1; + +- if (qemuPrepareNVRAM(vm, !!(flags & VIR_QEMU_PROCESS_START_RESET_NVRAM)) < 0) ++ if (qemuPrepareNVRAM(driver, vm->def, ++ !!(flags & VIR_QEMU_PROCESS_START_RESET_NVRAM)) < 0) + return -1; + + if (vm->def->vsock) { +diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h +index 12781673c5..fee00ce53b 100644 +--- a/src/qemu/qemu_process.h ++++ b/src/qemu/qemu_process.h +@@ -258,3 +258,7 @@ int qemuProcessSetupEmulator(virDomainObj *vm); + + void qemuProcessHandleNbdkitExit(qemuNbdkitProcess *nbdkit, + virDomainObj *vm); ++ ++int qemuPrepareNVRAM(virQEMUDriver *driver, ++ virDomainDef *def, ++ bool reset_nvram); +-- +2.48.1 diff --git a/libvirt-qemu-snapshot-Ensure-that-NVRAM-image-exists-when-taking-inactive-internal-snapshot.patch b/libvirt-qemu-snapshot-Ensure-that-NVRAM-image-exists-when-taking-inactive-internal-snapshot.patch new file mode 100644 index 0000000..a8bd87e --- /dev/null +++ b/libvirt-qemu-snapshot-Ensure-that-NVRAM-image-exists-when-taking-inactive-internal-snapshot.patch @@ -0,0 +1,94 @@ +From 82076c65791dbe33aa61c8523f2786cc2fc8c02e Mon Sep 17 00:00:00 2001 +Message-ID: <82076c65791dbe33aa61c8523f2786cc2fc8c02e.1738937224.git.jdenemar@redhat.com> +From: Peter Krempa +Date: Mon, 3 Feb 2025 17:52:50 +0100 +Subject: [PATCH] qemu: snapshot: Ensure that NVRAM image exists when taking + inactive internal snapshot + +Attempting to take an internal snapshot of a freshly defined VM with +qcow2 backed NVRAM results in failure as the NVRAM image doesn't get +populated until the VM is started for the first time. + +Fix this by invoking qemuPrepareNVRAM() when qcow2 nvram is defined. + +Resolves: https://issues.redhat.com/browse/RHEL-73315 +Signed-off-by: Peter Krempa +Reviewed-by: Pavel Hrdina +(cherry picked from commit 650e6fb7ebf905fe7dc992610ef9e932328460b7) + +https://issues.redhat.com/browse/RHEL-78186 +--- + src/qemu/qemu_snapshot.c | 23 +++++++++++++++++++---- + 1 file changed, 19 insertions(+), 4 deletions(-) + +diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c +index 7c998afe6f..b1f4ebb995 100644 +--- a/src/qemu/qemu_snapshot.c ++++ b/src/qemu/qemu_snapshot.c +@@ -269,6 +269,7 @@ qemuSnapshotForEachQcow2One(virStorageSource *src, + /** + * qemuSnapshotForEachQcow2: + * ++ * @driver: qemu driver configuration + * @def: domain definition + * @snap: snapshot object + * @op: 'qemu-img snapshot' operation flag, one of "-c", "-d", "-a" +@@ -282,7 +283,8 @@ qemuSnapshotForEachQcow2One(virStorageSource *src, + * permissive modes. + */ + static int +-qemuSnapshotForEachQcow2(virDomainDef *def, ++qemuSnapshotForEachQcow2(virQEMUDriver *driver, ++ virDomainDef *def, + virDomainMomentObj *snap, + const char *op) + { +@@ -352,6 +354,16 @@ qemuSnapshotForEachQcow2(virDomainDef *def, + + if (virStorageSourceIsLocalStorage(nvram) && + nvram->format == VIR_STORAGE_FILE_QCOW2) { ++ if (create) { ++ /* Ensure that the NVRAM image exists; e.g. when snapshotting ++ * a VM directly after defining it */ ++ if (qemuPrepareNVRAM(driver, def, false) < 0) { ++ nrollback = def->ndisks; ++ virErrorPreserveLast(&orig_err); ++ goto rollback; ++ } ++ } ++ + if (qemuSnapshotForEachQcow2One(nvram, op, snap->def->name) < 0) { + if (create) { + nrollback = def->ndisks; +@@ -392,7 +404,8 @@ static int + qemuSnapshotCreateInactiveInternal(virDomainObj *vm, + virDomainMomentObj *snap) + { +- return qemuSnapshotForEachQcow2(vm->def, snap, "-c"); ++ return qemuSnapshotForEachQcow2(QEMU_DOMAIN_PRIVATE(vm)->driver, ++ vm->def, snap, "-c"); + } + + +@@ -2696,7 +2709,8 @@ qemuSnapshotInternalRevertInactive(virDomainObj *vm, + } + + /* Try all disks, but report failure if we skipped any. */ +- if (qemuSnapshotForEachQcow2(def, snap, "-a") != 0) ++ if (qemuSnapshotForEachQcow2(QEMU_DOMAIN_PRIVATE(vm)->driver, ++ def, snap, "-a") != 0) + return -1; + + return 0; +@@ -4064,7 +4078,8 @@ qemuSnapshotDiscardImpl(virDomainObj *vm, + if (qemuSnapshotDiscardExternal(vm, snap, externalData) < 0) + return -1; + } else { +- if (qemuSnapshotForEachQcow2(def, snap, "-d") < 0) ++ if (qemuSnapshotForEachQcow2(QEMU_DOMAIN_PRIVATE(vm)->driver, ++ def, snap, "-d") < 0) + return -1; + } + } else { +-- +2.48.1 diff --git a/libvirt-qemuMonitorJSONHandleIOError-Do-not-munge-reason-field-of-IO-error-event.patch b/libvirt-qemuMonitorJSONHandleIOError-Do-not-munge-reason-field-of-IO-error-event.patch new file mode 100644 index 0000000..5b25013 --- /dev/null +++ b/libvirt-qemuMonitorJSONHandleIOError-Do-not-munge-reason-field-of-IO-error-event.patch @@ -0,0 +1,139 @@ +From 00ec6644dfd6ffc7ca51e45f69c4b3cdd3c868d7 Mon Sep 17 00:00:00 2001 +Message-ID: <00ec6644dfd6ffc7ca51e45f69c4b3cdd3c868d7.1738937224.git.jdenemar@redhat.com> +From: Peter Krempa +Date: Mon, 27 Jan 2025 13:53:36 +0100 +Subject: [PATCH] qemuMonitorJSONHandleIOError: Do not munge 'reason' field of + IO error event +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Leave the interpretation of the event to 'qemuProcessHandleIOError()' +which will create it's own variant of the messages for the user-facing +libvirt events. qemuMonitorJSONHandleIOError() will pass through the raw +data it got from qemu. + +Signed-off-by: Peter Krempa +Reviewed-by: Daniel P. Berrangé +(cherry picked from commit f8f8d5a253633aaae93b04d92bdcbed5b954149f) + +https://issues.redhat.com/browse/RHEL-76802 +--- + src/qemu/qemu_monitor.c | 3 ++- + src/qemu/qemu_monitor.h | 2 ++ + src/qemu/qemu_monitor_json.c | 12 ++++++------ + src/qemu/qemu_process.c | 9 +++++++-- + 4 files changed, 17 insertions(+), 9 deletions(-) + +diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c +index e98da5fbff..e0161b8e23 100644 +--- a/src/qemu/qemu_monitor.c ++++ b/src/qemu/qemu_monitor.c +@@ -1130,12 +1130,13 @@ qemuMonitorEmitIOError(qemuMonitor *mon, + const char *device, + const char *nodename, + int action, ++ bool nospace, + const char *reason) + { + VIR_DEBUG("mon=%p", mon); + + QEMU_MONITOR_CALLBACK(mon, domainIOError, mon->vm, +- device, nodename, action, reason); ++ device, nodename, action, nospace, reason); + } + + +diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h +index 0ab60f286d..0655802dcc 100644 +--- a/src/qemu/qemu_monitor.h ++++ b/src/qemu/qemu_monitor.h +@@ -209,6 +209,7 @@ typedef void (*qemuMonitorDomainIOErrorCallback)(qemuMonitor *mon, + const char *device, + const char *nodename, + int action, ++ bool nospace, + const char *reason); + typedef void (*qemuMonitorDomainGraphicsCallback)(qemuMonitor *mon, + virDomainObj *vm, +@@ -453,6 +454,7 @@ void qemuMonitorEmitIOError(qemuMonitor *mon, + const char *device, + const char *nodename, + int action, ++ bool nospace, + const char *reason); + void qemuMonitorEmitGraphics(qemuMonitor *mon, + int phase, +diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c +index 345e9383e3..7d202133f7 100644 +--- a/src/qemu/qemu_monitor_json.c ++++ b/src/qemu/qemu_monitor_json.c +@@ -695,8 +695,8 @@ qemuMonitorJSONHandleIOError(qemuMonitor *mon, virJSONValue *data) + const char *device; + const char *nodename; + const char *action; +- const char *reason = ""; +- bool nospc = false; ++ const char *reason; ++ bool nospace = false; + int actionID; + + /* Throughout here we try our best to carry on upon errors, +@@ -719,16 +719,16 @@ qemuMonitorJSONHandleIOError(qemuMonitor *mon, virJSONValue *data) + } + + nodename = virJSONValueObjectGetString(data, "node-name"); +- +- if (virJSONValueObjectGetBoolean(data, "nospace", &nospc) == 0 && nospc) +- reason = "enospc"; ++ reason = virJSONValueObjectGetString(data, "reason"); ++ /* 'nospace' flag is relevant only when true */ ++ ignore_value(virJSONValueObjectGetBoolean(data, "nospace", &nospace)); + + if ((actionID = qemuMonitorIOErrorActionTypeFromString(action)) < 0) { + VIR_WARN("unknown disk io error action '%s'", action); + actionID = VIR_DOMAIN_EVENT_IO_ERROR_NONE; + } + +- qemuMonitorEmitIOError(mon, device, nodename, actionID, reason); ++ qemuMonitorEmitIOError(mon, device, nodename, actionID, nospace, reason); + } + + +diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c +index 4083188af4..9ae39c0379 100644 +--- a/src/qemu/qemu_process.c ++++ b/src/qemu/qemu_process.c +@@ -827,7 +827,8 @@ qemuProcessHandleIOError(qemuMonitor *mon G_GNUC_UNUSED, + const char *device, + const char *nodename, + int action, +- const char *reason) ++ bool nospace, ++ const char *reason G_GNUC_UNUSED) + { + qemuDomainObjPrivate *priv; + virObjectEvent *ioErrorEvent = NULL; +@@ -835,6 +836,7 @@ qemuProcessHandleIOError(qemuMonitor *mon G_GNUC_UNUSED, + virObjectEvent *lifecycleEvent = NULL; + const char *eventPath = ""; + const char *eventAlias = ""; ++ const char *eventReason = ""; + virDomainDiskDef *disk; + + virObjectLock(vm); +@@ -852,8 +854,11 @@ qemuProcessHandleIOError(qemuMonitor *mon G_GNUC_UNUSED, + eventAlias = disk->info.alias; + } + ++ if (nospace) ++ eventReason = "enospc"; ++ + ioErrorEvent = virDomainEventIOErrorNewFromObj(vm, eventPath, eventAlias, action); +- ioErrorEvent2 = virDomainEventIOErrorReasonNewFromObj(vm, eventPath, eventAlias, action, reason); ++ ioErrorEvent2 = virDomainEventIOErrorReasonNewFromObj(vm, eventPath, eventAlias, action, eventReason); + + if (action == VIR_DOMAIN_EVENT_IO_ERROR_PAUSE && + virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) { +-- +2.48.1 diff --git a/libvirt-qemuMonitorJSONHandleIOError-Propagate-new-qom-path-field.patch b/libvirt-qemuMonitorJSONHandleIOError-Propagate-new-qom-path-field.patch new file mode 100644 index 0000000..1a8ad97 --- /dev/null +++ b/libvirt-qemuMonitorJSONHandleIOError-Propagate-new-qom-path-field.patch @@ -0,0 +1,118 @@ +From 1193fb140a38e202d5acdcec188f06b90af92f9a Mon Sep 17 00:00:00 2001 +Message-ID: <1193fb140a38e202d5acdcec188f06b90af92f9a.1738937224.git.jdenemar@redhat.com> +From: Peter Krempa +Date: Tue, 28 Jan 2025 10:39:52 +0100 +Subject: [PATCH] qemuMonitorJSONHandleIOError: Propagate new 'qom-path' field +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +QEMU commit v9.1.0-1065-ge67b7aef7c added 'qom-path' as an optional +field for the BLOCK_IO_ERROR event. Extract and propagate it as an +alternative to lookup via 'node-name' and 'device' (alias). + +Signed-off-by: Peter Krempa +Reviewed-by: Daniel P. Berrangé +(cherry picked from commit 0525323175253b1fe1a161181e58bd348d9c605b) + +https://issues.redhat.com/browse/RHEL-76802 +--- + src/qemu/qemu_monitor.c | 3 ++- + src/qemu/qemu_monitor.h | 2 ++ + src/qemu/qemu_monitor_json.c | 4 +++- + src/qemu/qemu_process.c | 3 ++- + 4 files changed, 9 insertions(+), 3 deletions(-) + +diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c +index e0161b8e23..79ff4e2e87 100644 +--- a/src/qemu/qemu_monitor.c ++++ b/src/qemu/qemu_monitor.c +@@ -1128,6 +1128,7 @@ qemuMonitorEmitWatchdog(qemuMonitor *mon, int action) + void + qemuMonitorEmitIOError(qemuMonitor *mon, + const char *device, ++ const char *qompath, + const char *nodename, + int action, + bool nospace, +@@ -1136,7 +1137,7 @@ qemuMonitorEmitIOError(qemuMonitor *mon, + VIR_DEBUG("mon=%p", mon); + + QEMU_MONITOR_CALLBACK(mon, domainIOError, mon->vm, +- device, nodename, action, nospace, reason); ++ device, qompath, nodename, action, nospace, reason); + } + + +diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h +index 0655802dcc..a4818a6aa1 100644 +--- a/src/qemu/qemu_monitor.h ++++ b/src/qemu/qemu_monitor.h +@@ -207,6 +207,7 @@ typedef void (*qemuMonitorDomainWatchdogCallback)(qemuMonitor *mon, + typedef void (*qemuMonitorDomainIOErrorCallback)(qemuMonitor *mon, + virDomainObj *vm, + const char *device, ++ const char *qompath, + const char *nodename, + int action, + bool nospace, +@@ -452,6 +453,7 @@ void qemuMonitorEmitRTCChange(qemuMonitor *mon, long long offset); + void qemuMonitorEmitWatchdog(qemuMonitor *mon, int action); + void qemuMonitorEmitIOError(qemuMonitor *mon, + const char *device, ++ const char *qompath, + const char *nodename, + int action, + bool nospace, +diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c +index 7d202133f7..53648dea8b 100644 +--- a/src/qemu/qemu_monitor_json.c ++++ b/src/qemu/qemu_monitor_json.c +@@ -693,6 +693,7 @@ static void + qemuMonitorJSONHandleIOError(qemuMonitor *mon, virJSONValue *data) + { + const char *device; ++ const char *qompath; + const char *nodename; + const char *action; + const char *reason; +@@ -718,6 +719,7 @@ qemuMonitorJSONHandleIOError(qemuMonitor *mon, virJSONValue *data) + device = NULL; + } + ++ qompath = virJSONValueObjectGetString(data, "qom-path"); + nodename = virJSONValueObjectGetString(data, "node-name"); + reason = virJSONValueObjectGetString(data, "reason"); + /* 'nospace' flag is relevant only when true */ +@@ -728,7 +730,7 @@ qemuMonitorJSONHandleIOError(qemuMonitor *mon, virJSONValue *data) + actionID = VIR_DOMAIN_EVENT_IO_ERROR_NONE; + } + +- qemuMonitorEmitIOError(mon, device, nodename, actionID, nospace, reason); ++ qemuMonitorEmitIOError(mon, device, qompath, nodename, actionID, nospace, reason); + } + + +diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c +index b0a20328d4..c95b1ecd82 100644 +--- a/src/qemu/qemu_process.c ++++ b/src/qemu/qemu_process.c +@@ -825,6 +825,7 @@ static void + qemuProcessHandleIOError(qemuMonitor *mon G_GNUC_UNUSED, + virDomainObj *vm, + const char *device, ++ const char *qompath, + const char *nodename, + int action, + bool nospace, +@@ -847,7 +848,7 @@ qemuProcessHandleIOError(qemuMonitor *mon G_GNUC_UNUSED, + disk = qemuDomainDiskLookupByNodename(vm->def, priv->backup, nodename, &src); + + if (!disk) +- disk = qemuProcessFindDomainDiskByAliasOrQOM(vm, device, NULL); ++ disk = qemuProcessFindDomainDiskByAliasOrQOM(vm, device, qompath); + + if (!src && disk) + src = disk->src; +-- +2.48.1 diff --git a/libvirt-qemuProcessHandleIOError-Log-IO-errors-in-the-VM-log-file.patch b/libvirt-qemuProcessHandleIOError-Log-IO-errors-in-the-VM-log-file.patch new file mode 100644 index 0000000..b5a134c --- /dev/null +++ b/libvirt-qemuProcessHandleIOError-Log-IO-errors-in-the-VM-log-file.patch @@ -0,0 +1,48 @@ +From c192df0a82c97d04b58de428836a7221fc11f7f2 Mon Sep 17 00:00:00 2001 +Message-ID: +From: Peter Krempa +Date: Fri, 24 Jan 2025 17:01:34 +0100 +Subject: [PATCH] qemuProcessHandleIOError: Log IO errors in the VM log file +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add a log entry to the VM log file for every time we receive an IO error +event from qemu. The log entry is as follows: + + 2025-01-24 16:03:28.928+0000: IO error device='virtio-disk0' node-name='libvirt-1-storage' reason='other: Input/output error' + +Signed-off-by: Peter Krempa +Reviewed-by: Daniel P. Berrangé +(cherry picked from commit 18f8d572be4caaa0c55a8d68a4048ef2360a03c5) + +https://issues.redhat.com/browse/RHEL-76802 +--- + src/qemu/qemu_process.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c +index 6b8a2af4ed..409734d948 100644 +--- a/src/qemu/qemu_process.c ++++ b/src/qemu/qemu_process.c +@@ -829,7 +829,7 @@ qemuProcessHandleIOError(qemuMonitor *mon G_GNUC_UNUSED, + const char *nodename, + int action, + bool nospace, +- const char *reason G_GNUC_UNUSED) ++ const char *reason) + { + qemuDomainObjPrivate *priv; + virObjectEvent *ioErrorEvent = NULL; +@@ -867,6 +867,9 @@ qemuProcessHandleIOError(qemuMonitor *mon G_GNUC_UNUSED, + ioErrorEvent2 = virDomainEventIOErrorReasonNewFromObj(vm, eventPath, eventAlias, action, eventReason); + + if ((timestamp = virTimeStringNow()) != NULL) { ++ qemuDomainLogAppendMessage(priv->driver, vm, "%s: IO error device='%s' node-name='%s' reason='%s'\n", ++ timestamp, NULLSTR(eventAlias), NULLSTR(nodename), NULLSTR(reason)); ++ + if (src) { + g_free(src->ioerror_timestamp); + g_free(src->ioerror_message); +-- +2.48.1 diff --git a/libvirt-qemuProcessHandleIOError-Populate-I-O-error-reason-to-virStorageSource.patch b/libvirt-qemuProcessHandleIOError-Populate-I-O-error-reason-to-virStorageSource.patch new file mode 100644 index 0000000..833f3e4 --- /dev/null +++ b/libvirt-qemuProcessHandleIOError-Populate-I-O-error-reason-to-virStorageSource.patch @@ -0,0 +1,55 @@ +From 61829441be56a5d24f727056cde31907ef3cfdeb Mon Sep 17 00:00:00 2001 +Message-ID: <61829441be56a5d24f727056cde31907ef3cfdeb.1738937224.git.jdenemar@redhat.com> +From: Peter Krempa +Date: Mon, 27 Jan 2025 19:17:16 +0100 +Subject: [PATCH] qemuProcessHandleIOError: Populate I/O error reason to + virStorageSource +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Record the last I/O error reason and timestamp which happened with the +corresponding virStorageSource struct. + +This will later allow querying the last error e.g. via the +virDomainGetMessages() API. + +Signed-off-by: Peter Krempa +Reviewed-by: Daniel P. Berrangé +(cherry picked from commit 300f7e9bd4ee4e043cac1a84059fe4a60b101cf1) + +https://issues.redhat.com/browse/RHEL-76802 +--- + src/qemu/qemu_process.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c +index c95b1ecd82..6b8a2af4ed 100644 +--- a/src/qemu/qemu_process.c ++++ b/src/qemu/qemu_process.c +@@ -840,6 +840,7 @@ qemuProcessHandleIOError(qemuMonitor *mon G_GNUC_UNUSED, + const char *eventReason = ""; + virDomainDiskDef *disk = NULL; + virStorageSource *src = NULL; ++ g_autofree char *timestamp = NULL; + + virObjectLock(vm); + priv = QEMU_DOMAIN_PRIVATE(vm); +@@ -865,6 +866,15 @@ qemuProcessHandleIOError(qemuMonitor *mon G_GNUC_UNUSED, + ioErrorEvent = virDomainEventIOErrorNewFromObj(vm, eventPath, eventAlias, action); + ioErrorEvent2 = virDomainEventIOErrorReasonNewFromObj(vm, eventPath, eventAlias, action, eventReason); + ++ if ((timestamp = virTimeStringNow()) != NULL) { ++ if (src) { ++ g_free(src->ioerror_timestamp); ++ g_free(src->ioerror_message); ++ src->ioerror_timestamp = g_steal_pointer(×tamp); ++ src->ioerror_message = g_strdup(reason); ++ } ++ } ++ + if (action == VIR_DOMAIN_EVENT_IO_ERROR_PAUSE && + virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) { + VIR_WARN("Transitioned guest %s to paused state due to IO error", vm->def->name); +-- +2.48.1 diff --git a/libvirt-qemuProcessHandleIOError-Prefer-lookup-by-node-name.patch b/libvirt-qemuProcessHandleIOError-Prefer-lookup-by-node-name.patch new file mode 100644 index 0000000..554dcdb --- /dev/null +++ b/libvirt-qemuProcessHandleIOError-Prefer-lookup-by-node-name.patch @@ -0,0 +1,64 @@ +From 036c41c36b59f7ac41228701097c2b0ae6b03053 Mon Sep 17 00:00:00 2001 +Message-ID: <036c41c36b59f7ac41228701097c2b0ae6b03053.1738937224.git.jdenemar@redhat.com> +From: Peter Krempa +Date: Fri, 24 Jan 2025 17:17:51 +0100 +Subject: [PATCH] qemuProcessHandleIOError: Prefer lookup by node name +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When qemu reports a node name for an I/O error we should prefer the +lookup by node name instead as it gives us the path to the specific +image which caused the error instead of the top level image path. + +Signed-off-by: Peter Krempa +Reviewed-by: Daniel P. Berrangé +(cherry picked from commit 784538a470fe346cb1ab85786b8ece85cbe7ff9f) + +https://issues.redhat.com/browse/RHEL-76802 +--- + src/qemu/qemu_process.c | 22 +++++++++++++--------- + 1 file changed, 13 insertions(+), 9 deletions(-) + +diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c +index 9ae39c0379..b0a20328d4 100644 +--- a/src/qemu/qemu_process.c ++++ b/src/qemu/qemu_process.c +@@ -837,22 +837,26 @@ qemuProcessHandleIOError(qemuMonitor *mon G_GNUC_UNUSED, + const char *eventPath = ""; + const char *eventAlias = ""; + const char *eventReason = ""; +- virDomainDiskDef *disk; ++ virDomainDiskDef *disk = NULL; ++ virStorageSource *src = NULL; + + virObjectLock(vm); + priv = QEMU_DOMAIN_PRIVATE(vm); + +- if (device) ++ if (nodename) ++ disk = qemuDomainDiskLookupByNodename(vm->def, priv->backup, nodename, &src); ++ ++ if (!disk) + disk = qemuProcessFindDomainDiskByAliasOrQOM(vm, device, NULL); +- else if (nodename) +- disk = qemuDomainDiskLookupByNodename(vm->def, NULL, nodename, NULL); +- else +- disk = NULL; + +- if (disk) { +- eventPath = virDomainDiskGetSource(disk); ++ if (!src && disk) ++ src = disk->src; ++ ++ if (disk) + eventAlias = disk->info.alias; +- } ++ ++ if (src && src->path) ++ eventPath = src->path; + + if (nospace) + eventReason = "enospc"; +-- +2.48.1 diff --git a/libvirt-qemuProcessHandleIOError-Refactor-to-extract-priv-instead-of-driver.patch b/libvirt-qemuProcessHandleIOError-Refactor-to-extract-priv-instead-of-driver.patch new file mode 100644 index 0000000..8f54d98 --- /dev/null +++ b/libvirt-qemuProcessHandleIOError-Refactor-to-extract-priv-instead-of-driver.patch @@ -0,0 +1,76 @@ +From 2edd047dcd0b7544ea6f49248686c22e1b6cb868 Mon Sep 17 00:00:00 2001 +Message-ID: <2edd047dcd0b7544ea6f49248686c22e1b6cb868.1738937224.git.jdenemar@redhat.com> +From: Peter Krempa +Date: Fri, 24 Jan 2025 17:16:35 +0100 +Subject: [PATCH] qemuProcessHandleIOError: Refactor to extract 'priv' instead + of 'driver' +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The VM private data will be used in a sub-sequent patch. To minimize +churn, refactor the function before changing the logic. + +Signed-off-by: Peter Krempa +Reviewed-by: Daniel P. Berrangé +(cherry picked from commit 72142dcde34dd7e1dfb3ea0d841f567badd80539) + +https://issues.redhat.com/browse/RHEL-76802 +--- + src/qemu/qemu_process.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c +index 7297263d33..c618fbf69c 100644 +--- a/src/qemu/qemu_process.c ++++ b/src/qemu/qemu_process.c +@@ -829,7 +829,7 @@ qemuProcessHandleIOError(qemuMonitor *mon G_GNUC_UNUSED, + int action, + const char *reason) + { +- virQEMUDriver *driver; ++ qemuDomainObjPrivate *priv; + virObjectEvent *ioErrorEvent = NULL; + virObjectEvent *ioErrorEvent2 = NULL; + virObjectEvent *lifecycleEvent = NULL; +@@ -838,7 +838,7 @@ qemuProcessHandleIOError(qemuMonitor *mon G_GNUC_UNUSED, + virDomainDiskDef *disk; + + virObjectLock(vm); +- driver = QEMU_DOMAIN_PRIVATE(vm)->driver; ++ priv = QEMU_DOMAIN_PRIVATE(vm); + + if (*diskAlias == '\0') + diskAlias = NULL; +@@ -863,7 +863,6 @@ qemuProcessHandleIOError(qemuMonitor *mon G_GNUC_UNUSED, + + if (action == VIR_DOMAIN_EVENT_IO_ERROR_PAUSE && + virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) { +- qemuDomainObjPrivate *priv = vm->privateData; + VIR_WARN("Transitioned guest %s to paused state due to IO error", vm->def->name); + + if (priv->signalIOError) +@@ -875,7 +874,7 @@ qemuProcessHandleIOError(qemuMonitor *mon G_GNUC_UNUSED, + VIR_DOMAIN_EVENT_SUSPENDED_IOERROR); + + VIR_FREE(priv->lockState); +- if (virDomainLockProcessPause(driver->lockManager, vm, &priv->lockState) < 0) ++ if (virDomainLockProcessPause(priv->driver->lockManager, vm, &priv->lockState) < 0) + VIR_WARN("Unable to release lease on %s", vm->def->name); + VIR_DEBUG("Preserving lock state '%s'", NULLSTR(priv->lockState)); + +@@ -883,9 +882,9 @@ qemuProcessHandleIOError(qemuMonitor *mon G_GNUC_UNUSED, + } + virObjectUnlock(vm); + +- virObjectEventStateQueue(driver->domainEventState, ioErrorEvent); +- virObjectEventStateQueue(driver->domainEventState, ioErrorEvent2); +- virObjectEventStateQueue(driver->domainEventState, lifecycleEvent); ++ virObjectEventStateQueue(priv->driver->domainEventState, ioErrorEvent); ++ virObjectEventStateQueue(priv->driver->domainEventState, ioErrorEvent2); ++ virObjectEventStateQueue(priv->driver->domainEventState, lifecycleEvent); + } + + +-- +2.48.1 diff --git a/libvirt-qemuProcessHandleIOError-Rename-local-variables.patch b/libvirt-qemuProcessHandleIOError-Rename-local-variables.patch new file mode 100644 index 0000000..205a5c9 --- /dev/null +++ b/libvirt-qemuProcessHandleIOError-Rename-local-variables.patch @@ -0,0 +1,59 @@ +From eaf365d8e054543ff33489a93f5fe25cc41939d7 Mon Sep 17 00:00:00 2001 +Message-ID: +From: Peter Krempa +Date: Mon, 27 Jan 2025 13:07:24 +0100 +Subject: [PATCH] qemuProcessHandleIOError: Rename local variables +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Prefix the helper variables used to supply data to the event by +'event'. Declare them with the default value of an empty string rather +than doing it later. + +Signed-off-by: Peter Krempa +Reviewed-by: Daniel P. Berrangé +(cherry picked from commit 590a5765c190230ab3df87e7eda42f621766347b) + +https://issues.redhat.com/browse/RHEL-76802 +--- + src/qemu/qemu_process.c | 15 ++++++--------- + 1 file changed, 6 insertions(+), 9 deletions(-) + +diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c +index 3861d91228..4083188af4 100644 +--- a/src/qemu/qemu_process.c ++++ b/src/qemu/qemu_process.c +@@ -833,8 +833,8 @@ qemuProcessHandleIOError(qemuMonitor *mon G_GNUC_UNUSED, + virObjectEvent *ioErrorEvent = NULL; + virObjectEvent *ioErrorEvent2 = NULL; + virObjectEvent *lifecycleEvent = NULL; +- const char *srcPath; +- const char *devAlias; ++ const char *eventPath = ""; ++ const char *eventAlias = ""; + virDomainDiskDef *disk; + + virObjectLock(vm); +@@ -848,15 +848,12 @@ qemuProcessHandleIOError(qemuMonitor *mon G_GNUC_UNUSED, + disk = NULL; + + if (disk) { +- srcPath = virDomainDiskGetSource(disk); +- devAlias = disk->info.alias; +- } else { +- srcPath = ""; +- devAlias = ""; ++ eventPath = virDomainDiskGetSource(disk); ++ eventAlias = disk->info.alias; + } + +- ioErrorEvent = virDomainEventIOErrorNewFromObj(vm, srcPath, devAlias, action); +- ioErrorEvent2 = virDomainEventIOErrorReasonNewFromObj(vm, srcPath, devAlias, action, reason); ++ ioErrorEvent = virDomainEventIOErrorNewFromObj(vm, eventPath, eventAlias, action); ++ ioErrorEvent2 = virDomainEventIOErrorReasonNewFromObj(vm, eventPath, eventAlias, action, reason); + + if (action == VIR_DOMAIN_EVENT_IO_ERROR_PAUSE && + virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) { +-- +2.48.1 diff --git a/libvirt-qemuSnapshotForEachQcow2-Don-t-initialize-nrollback.patch b/libvirt-qemuSnapshotForEachQcow2-Don-t-initialize-nrollback.patch new file mode 100644 index 0000000..4af6ae7 --- /dev/null +++ b/libvirt-qemuSnapshotForEachQcow2-Don-t-initialize-nrollback.patch @@ -0,0 +1,36 @@ +From e24b0d16ed1876fbb0ac07ede669c928cd486107 Mon Sep 17 00:00:00 2001 +Message-ID: +From: Peter Krempa +Date: Mon, 3 Feb 2025 18:23:29 +0100 +Subject: [PATCH] qemuSnapshotForEachQcow2: Don't initialize 'nrollback' + +The variable holds the amount of disks to roll back the snapshot for. +The value must be set before the code jumps to the 'rollback:' label so +the best situation is to not initialize it and let the compiler catch +errors rather than initialize the unsigned variable to -1 and let it +crash. + +Signed-off-by: Peter Krempa +Reviewed-by: Pavel Hrdina +(cherry picked from commit d15eff63041ace067fa0ea9687c482a0f1dd140f) + +https://issues.redhat.com/browse/RHEL-78186 +--- + src/qemu/qemu_snapshot.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c +index 80cd54bf33..7c998afe6f 100644 +--- a/src/qemu/qemu_snapshot.c ++++ b/src/qemu/qemu_snapshot.c +@@ -290,7 +290,7 @@ qemuSnapshotForEachQcow2(virDomainDef *def, + size_t i; + bool skipped = false; + bool create = STREQ(op, "-c"); +- size_t nrollback = -1; ++ size_t nrollback; + virErrorPtr orig_err; + + /* pre-checks */ +-- +2.48.1 diff --git a/libvirt-qemuxmlconftest-Add-testing-of-FDs-with-writable-flag-in-disk-source-fd.patch b/libvirt-qemuxmlconftest-Add-testing-of-FDs-with-writable-flag-in-disk-source-fd.patch new file mode 100644 index 0000000..e043774 --- /dev/null +++ b/libvirt-qemuxmlconftest-Add-testing-of-FDs-with-writable-flag-in-disk-source-fd.patch @@ -0,0 +1,164 @@ +From aebbd45d109383d1c79fc19b35c5f294d92d7d92 Mon Sep 17 00:00:00 2001 +Message-ID: +From: Peter Krempa +Date: Thu, 6 Feb 2025 15:55:37 +0100 +Subject: [PATCH] qemuxmlconftest: Add testing of FDs with 'writable' flag in + 'disk-source-fd' + +Add few examples of fd groups with the 'writable' flag set, when passing +a single FD. Notably as a top level image of a readonly disk (even when +that doesn't make much sense) and also as a base image of a chain. + +Note that this documents a status quo of a bug fixed in upcoming patch. + +Signed-off-by: Peter Krempa +Reviewed-by: Jiri Denemark +(cherry picked from commit 7a119483a361a3ab814e4e07ccac7b13b0cbfbf7) + +https://issues.redhat.com/browse/RHEL-78353 +--- + .../disk-source-fd.x86_64-latest.args | 36 +++++++++++-------- + .../disk-source-fd.x86_64-latest.xml | 21 +++++++++-- + tests/qemuxmlconfdata/disk-source-fd.xml | 16 +++++++-- + tests/qemuxmlconftest.c | 3 ++ + 4 files changed, 57 insertions(+), 19 deletions(-) + +diff --git a/tests/qemuxmlconfdata/disk-source-fd.x86_64-latest.args b/tests/qemuxmlconfdata/disk-source-fd.x86_64-latest.args +index 1341b7d032..d77b3ca505 100644 +--- a/tests/qemuxmlconfdata/disk-source-fd.x86_64-latest.args ++++ b/tests/qemuxmlconfdata/disk-source-fd.x86_64-latest.args +@@ -27,21 +27,27 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ + -no-shutdown \ + -boot strict=on \ + -device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \ +--add-fd set=2,fd=200,opaque=libvirt-4-storage0 \ +--add-fd set=2,fd=205,opaque=libvirt-4-storage1 \ +--blockdev '{"driver":"file","filename":"/dev/fdset/2","node-name":"libvirt-4-storage","auto-read-only":true,"discard":"unmap"}' \ +--blockdev '{"node-name":"libvirt-4-format","read-only":false,"driver":"qcow2","file":"libvirt-4-storage"}' \ +--device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x2","drive":"libvirt-4-format","id":"virtio-disk4","bootindex":1}' \ +--blockdev '{"driver":"file","filename":"/var/lib/libvirt/images/rhel7.1484071876","node-name":"libvirt-3-storage","auto-read-only":true,"discard":"unmap"}' \ +--blockdev '{"node-name":"libvirt-3-format","read-only":true,"driver":"qcow2","file":"libvirt-3-storage","backing":null}' \ +--add-fd set=1,fd=247,opaque=libvirt-2-storage0 \ +--add-fd set=1,fd=248,opaque=libvirt-2-storage1 \ +--blockdev '{"driver":"file","filename":"/dev/fdset/1","node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"}' \ +--blockdev '{"node-name":"libvirt-2-format","read-only":true,"driver":"qcow2","file":"libvirt-2-storage","backing":"libvirt-3-format"}' \ +--add-fd set=0,fd=204,opaque=libvirt-1-storage0 \ +--blockdev '{"driver":"file","filename":"/dev/fdset/0","node-name":"libvirt-1-storage","read-only":false,"discard":"unmap"}' \ +--blockdev '{"node-name":"libvirt-1-format","read-only":false,"driver":"qcow2","file":"libvirt-1-storage","backing":"libvirt-2-format"}' \ +--device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x3","drive":"libvirt-1-format","id":"virtio-disk5"}' \ ++-add-fd set=5,fd=200,opaque=libvirt-6-storage0 \ ++-add-fd set=5,fd=205,opaque=libvirt-6-storage1 \ ++-blockdev '{"driver":"file","filename":"/dev/fdset/5","node-name":"libvirt-6-storage","auto-read-only":true,"discard":"unmap"}' \ ++-blockdev '{"node-name":"libvirt-6-format","read-only":false,"driver":"qcow2","file":"libvirt-6-storage"}' \ ++-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x2","drive":"libvirt-6-format","id":"virtio-disk4","bootindex":1}' \ ++-add-fd set=4,fd=209,opaque=libvirt-5-storage0 \ ++-blockdev '{"driver":"file","filename":"/dev/fdset/4","node-name":"libvirt-5-storage","read-only":true}' \ ++-add-fd set=3,fd=247,opaque=libvirt-4-storage0 \ ++-add-fd set=3,fd=248,opaque=libvirt-4-storage1 \ ++-blockdev '{"driver":"file","filename":"/dev/fdset/3","node-name":"libvirt-4-storage","auto-read-only":true,"discard":"unmap"}' \ ++-blockdev '{"node-name":"libvirt-4-format","read-only":true,"driver":"qcow2","file":"libvirt-4-storage","backing":"libvirt-5-storage"}' \ ++-add-fd set=2,fd=204,opaque=libvirt-3-storage0 \ ++-blockdev '{"driver":"file","filename":"/dev/fdset/2","node-name":"libvirt-3-storage","read-only":false,"discard":"unmap"}' \ ++-blockdev '{"node-name":"libvirt-3-format","read-only":false,"driver":"qcow2","file":"libvirt-3-storage","backing":"libvirt-4-format"}' \ ++-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x3","drive":"libvirt-3-format","id":"virtio-disk5"}' \ ++-add-fd set=1,fd=207,opaque=libvirt-2-storage0 \ ++-blockdev '{"driver":"file","filename":"/dev/fdset/1","node-name":"libvirt-2-storage","read-only":true}' \ ++-device '{"driver":"ide-cd","bus":"ide.0","unit":0,"drive":"libvirt-2-storage","id":"ide0-0-0"}' \ ++-add-fd set=0,fd=208,opaque=libvirt-1-storage0 \ ++-blockdev '{"driver":"file","filename":"/dev/fdset/0","node-name":"libvirt-1-storage","read-only":true}' \ ++-device '{"driver":"ide-cd","bus":"ide.0","unit":1,"drive":"libvirt-1-storage","id":"ide0-0-1"}' \ + -audiodev '{"id":"audio1","driver":"none"}' \ + -device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x4"}' \ + -sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +diff --git a/tests/qemuxmlconfdata/disk-source-fd.x86_64-latest.xml b/tests/qemuxmlconfdata/disk-source-fd.x86_64-latest.xml +index 9ab5e9443f..d9917c7d53 100644 +--- a/tests/qemuxmlconfdata/disk-source-fd.x86_64-latest.xml ++++ b/tests/qemuxmlconfdata/disk-source-fd.x86_64-latest.xml +@@ -30,18 +30,35 @@ + + + +- +- ++ ++ + + + + +
+ ++ ++ ++ ++ ++ ++
++ ++ ++ ++ ++ ++ ++
++ + +
+ + ++ ++
++ + + +