]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemuMonitorJSONGetBlockInfo: Don't fail if 'io-status' field gets new values
authorPeter Krempa <pkrempa@redhat.com>
Thu, 5 Feb 2026 10:47:46 +0000 (11:47 +0100)
committerPeter Krempa <pkrempa@redhat.com>
Thu, 12 Feb 2026 15:45:34 +0000 (16:45 +0100)
Strictly validating qemu replies and rejecting unknown values can have
bad consequences in case qemu adds a new value.

Refactor the code parsing 'io-status' field from 'query-block' to be
tolerant to new values to avoid failure.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
src/qemu/qemu_monitor.c
src/qemu/qemu_monitor.h
src/qemu/qemu_monitor_json.c

index 6acc80832c9c6daa159490a94017e1fb79c1d8c4..1434da7f70f39847f24330c881b2ad2a62035690 100644 (file)
@@ -177,21 +177,6 @@ VIR_ENUM_IMPL(qemuMonitorVMStatus,
               "guest-panicked",
 );
 
-typedef enum {
-    QEMU_MONITOR_BLOCK_IO_STATUS_OK,
-    QEMU_MONITOR_BLOCK_IO_STATUS_FAILED,
-    QEMU_MONITOR_BLOCK_IO_STATUS_NOSPACE,
-
-    QEMU_MONITOR_BLOCK_IO_STATUS_LAST
-} qemuMonitorBlockIOStatus;
-
-VIR_ENUM_DECL(qemuMonitorBlockIOStatus);
-
-VIR_ENUM_IMPL(qemuMonitorBlockIOStatus,
-              QEMU_MONITOR_BLOCK_IO_STATUS_LAST,
-              "ok", "failed", "nospace",
-);
-
 VIR_ENUM_IMPL(qemuMonitorDumpStatus,
               QEMU_MONITOR_DUMP_STATUS_LAST,
               "none", "active", "completed", "failed",
@@ -1915,33 +1900,6 @@ qemuMonitorSetMemoryStatsPeriod(qemuMonitor *mon,
 }
 
 
-int
-qemuMonitorBlockIOStatusToError(const char *status)
-{
-    int st = qemuMonitorBlockIOStatusTypeFromString(status);
-
-    if (st < 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("unknown block IO status: %1$s"), status);
-        return -1;
-    }
-
-    switch ((qemuMonitorBlockIOStatus) st) {
-    case QEMU_MONITOR_BLOCK_IO_STATUS_OK:
-        return VIR_DOMAIN_DISK_ERROR_NONE;
-    case QEMU_MONITOR_BLOCK_IO_STATUS_FAILED:
-        return VIR_DOMAIN_DISK_ERROR_UNSPEC;
-    case QEMU_MONITOR_BLOCK_IO_STATUS_NOSPACE:
-        return VIR_DOMAIN_DISK_ERROR_NO_SPACE;
-
-    /* unreachable */
-    case QEMU_MONITOR_BLOCK_IO_STATUS_LAST:
-        break;
-    }
-    return -1;
-}
-
-
 static void
 qemuDomainDiskInfoFree(void *value)
 {
index 041aa7bc1243f21b6fcf02775a574d85a35792a7..a35dbe560f45875d7dc95931540a816923ee3b9b 100644 (file)
@@ -783,9 +783,6 @@ qemuMonitorSetMemoryStatsPeriod(qemuMonitor *mon,
                                 virDomainMemballoonDef *balloon,
                                 int period);
 
-int
-qemuMonitorBlockIOStatusToError(const char *status);
-
 GHashTable *
 qemuMonitorGetBlockInfo(qemuMonitor *mon);
 
index 328e32533ded710c4ccc037fba94c2cb363d5038..50e0497385f3b0728cc906ef5425e8e21fb9c313 100644 (file)
@@ -2317,6 +2317,24 @@ qemuMonitorJSONBlockInfoAdd(GHashTable *table,
 }
 
 
+typedef enum {
+    QEMU_MONITOR_BLOCK_IO_STATUS_OK,
+    QEMU_MONITOR_BLOCK_IO_STATUS_FAILED,
+    QEMU_MONITOR_BLOCK_IO_STATUS_NOSPACE,
+
+    QEMU_MONITOR_BLOCK_IO_STATUS_LAST
+} qemuMonitorBlockIOStatus;
+
+VIR_ENUM_DECL(qemuMonitorBlockIOStatus);
+
+VIR_ENUM_IMPL(qemuMonitorBlockIOStatus,
+              QEMU_MONITOR_BLOCK_IO_STATUS_LAST,
+              "ok",
+              "failed",
+              "nospace",
+);
+
+
 int
 qemuMonitorJSONGetBlockInfo(qemuMonitor *mon,
                             GHashTable *table)
@@ -2329,7 +2347,7 @@ qemuMonitorJSONGetBlockInfo(qemuMonitor *mon,
 
     for (i = 0; i < virJSONValueArraySize(devices); i++) {
         virJSONValue *dev;
-        struct qemuDomainDiskInfo info = { false };
+        struct qemuDomainDiskInfo info = { .io_status = VIR_DOMAIN_DISK_ERROR_NONE };
         const char *thisdev;
         const char *status;
         const char *qdev;
@@ -2358,9 +2376,30 @@ qemuMonitorJSONGetBlockInfo(qemuMonitor *mon,
 
         /* Missing io-status indicates no error */
         if ((status = virJSONValueObjectGetString(dev, "io-status"))) {
-            info.io_status = qemuMonitorBlockIOStatusToError(status);
-            if (info.io_status < 0)
-                return -1;
+            int st = qemuMonitorBlockIOStatusTypeFromString(status);
+
+            if (st < 0) {
+                VIR_WARN("Unhandled value '%s' of 'io-status' field in 'query-block' reply",
+                         status);
+                info.io_status = VIR_DOMAIN_DISK_ERROR_UNSPEC;
+            } else {
+                switch ((qemuMonitorBlockIOStatus) st) {
+                case QEMU_MONITOR_BLOCK_IO_STATUS_OK:
+                    info.io_status = VIR_DOMAIN_DISK_ERROR_NONE;
+                    break;
+
+                case QEMU_MONITOR_BLOCK_IO_STATUS_FAILED:
+                    info.io_status = VIR_DOMAIN_DISK_ERROR_UNSPEC;
+                    break;
+
+                case QEMU_MONITOR_BLOCK_IO_STATUS_NOSPACE:
+                    info.io_status = VIR_DOMAIN_DISK_ERROR_NO_SPACE;
+                    break;
+
+                case QEMU_MONITOR_BLOCK_IO_STATUS_LAST:
+                    break;
+                }
+            }
         }
 
         if (thisdev &&