qemuMonitorJSONGetBlockInfo: Don't fail if 'io-status' field gets new values

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>
This commit is contained in:
Peter Krempa committed 2026-02-12 16:45:34 +01:00
1 parent 4666d19617
commit a94d2b9871
3 files changed
+43 -49

No files matched your search

-42
View 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)
{
-3
View File
@@ -783,9 +783,6 @@ qemuMonitorSetMemoryStatsPeriod(qemuMonitor *mon,
virDomainMemballoonDef *balloon,
int period);
int
qemuMonitorBlockIOStatusToError(const char *status);
GHashTable *
qemuMonitorGetBlockInfo(qemuMonitor *mon);
+43 -4
View 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 &&