[PATCH 00/20] qemu: Optimize calls to 'query-block'
We call query-block on each start of a VM but as it turns out there isn't much information that we actually probe from it. This series: - refactors 'query-block' use - removes unneeded calls - adds support for upcoming more optimal mode (RFC) Patches 19 and 20 are RFC as the qemu patches weren't accepted yet. I'll post them also separately with a capability dump update once that hits upstream. Peter Krempa (20): qemuDomainDiskInfo: Drop 'nodename' field qemu: Remove 'removable' field from 'qemuDomainDiskPrivate' qemuProcessRefreshDiskProps: Drop code to remove disk source qemu: Drop 'empty' filed from 'qemuDomainDiskInfo' qemuMigrationSrcBegin: Drop disk refresh step qemu: process: Unexport 'qemuProcessRefreshDisks' qemu: Drop 'removable' field from 'qemuDomainDiskInfo' qemuMonitorJSONHandleMigrationStatus: Simplify error case qemu: monitor: Add test validating that 'eventHandlers' are properly sorted qemuMonitorJSONHandleMemoryFailure: Simplify error case and value extraction qemuMonitorJSONGetBlockInfo: Don't fail if 'io-status' field gets new values qemuDomainDiskInfo: Use proper type for 'io_status' conf: domain: Add VIR_DOMAIN_DISK_TRAY_NONE state for devices without tray qemuDomainDiskPrivate: Remove unused 'tray' field qemuDomainAttachDiskGeneric: Avoid unneeded disk property refresh after hotplug qemu: Refactor tray_status handling qemuProcessUpdateVideoRamSize: Remove 'driver' argument and adjust callers qemuProcessRefreshDisks: Don't bother to refresh disks on cold boot qemu: capabilities: Introduce QEMU_CAPS_QUERY_BLOCK_FLAT qemu: monitor: Use 'flat' mode of 'query-block' src/conf/domain_conf.c | 17 +++- src/conf/domain_conf.h | 3 +- src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_domain.h | 12 +-- src/qemu/qemu_driver.c | 10 +-- src/qemu/qemu_hotplug.c | 18 ++-- src/qemu/qemu_migration.c | 12 +-- src/qemu/qemu_monitor.c | 44 +-------- src/qemu/qemu_monitor.h | 3 - src/qemu/qemu_monitor_json.c | 149 ++++++++++++++++++++----------- src/qemu/qemu_monitor_json.h | 3 + src/qemu/qemu_monitor_priv.h | 3 + src/qemu/qemu_process.c | 167 +++++++++++++++++------------------ src/qemu/qemu_process.h | 9 +- src/qemu/qemu_saveimage.c | 2 +- tests/qemuhotplugtest.c | 38 +++----- tests/qemumonitorjsontest.c | 31 +++++-- 18 files changed, 254 insertions(+), 270 deletions(-) -- 2.53.0
From: Peter Krempa <pkrempa@redhat.com> The field is only read in tests. Other code using it no longer exists. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_domain.h | 1 - src/qemu/qemu_monitor.c | 1 - src/qemu/qemu_monitor_json.c | 5 +---- tests/qemumonitorjsontest.c | 4 ++-- 4 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 3361e97315..095c36b8ac 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -364,7 +364,6 @@ struct qemuDomainDiskInfo { bool tray_open; bool empty; int io_status; - char *nodename; }; #define QEMU_DOMAIN_CHR_SOURCE_PRIVATE(dev) \ diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 504500c864..6acc80832c 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -1947,7 +1947,6 @@ qemuDomainDiskInfoFree(void *value) { struct qemuDomainDiskInfo *info = value; - g_free(info->nodename); g_free(info); } diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index f345741207..a7e095a648 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2304,7 +2304,6 @@ qemuMonitorJSONBlockInfoAdd(GHashTable *table, tmp = g_new0(struct qemuDomainDiskInfo, 1); *tmp = *info; - tmp->nodename = g_strdup(info->nodename); g_hash_table_insert(table, g_strdup(entryname), tmp); @@ -2360,9 +2359,7 @@ qemuMonitorJSONGetBlockInfo(qemuMonitor *mon, info.tray = true; /* presence of 'inserted' notifies that a medium is in the device */ - if ((image = virJSONValueObjectGetObject(dev, "inserted"))) { - info.nodename = (char *) virJSONValueObjectGetString(image, "node-name"); - } else { + if (!(image = virJSONValueObjectGetObject(dev, "inserted"))) { info.empty = true; } diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index bfe81739a7..efa2400750 100644 --- a/tests/qemumonitorjsontest.c +++ b/tests/qemumonitorjsontest.c @@ -1354,9 +1354,9 @@ static void testQemuMonitorJSONGetBlockInfoPrint(const struct qemuDomainDiskInfo *d) { VIR_TEST_VERBOSE("removable: %d, tray: %d, tray_open: %d, empty: %d, " - "io_status: %d, nodename: '%s'", + "io_status: %d", d->removable, d->tray, d->tray_open, d->empty, - d->io_status, NULLSTR(d->nodename)); + d->io_status); } -- 2.53.0
On a Thursday in 2026, Peter Krempa via Devel wrote:
From: Peter Krempa <pkrempa@redhat.com>
The field is only read in tests. Other code using it no longer exists.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_domain.h | 1 - src/qemu/qemu_monitor.c | 1 - src/qemu/qemu_monitor_json.c | 5 +---- tests/qemumonitorjsontest.c | 4 ++-- 4 files changed, 3 insertions(+), 8 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano
From: Peter Krempa <pkrempa@redhat.com> The field is only set, but never read. Drop it. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_domain.h | 2 -- src/qemu/qemu_process.c | 1 - 2 files changed, 3 deletions(-) diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 095c36b8ac..20d6bd316c 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -288,9 +288,7 @@ struct _qemuDomainDiskPrivate { virStorageSource *migrSource; /* disk source object used for NBD migration */ bool migrationslice; /* storage slice was added for migration purposes */ - /* information about the device */ bool tray; /* device has tray */ - bool removable; /* device media can be removed/changed */ char *qomName; /* QOM path of the disk (also refers to the block backend) */ char *nodeCopyOnRead; /* nodename of the disk-wide copy-on-read blockdev layer */ diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index c5b2a5fda8..fba1dbe844 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -9555,7 +9555,6 @@ qemuProcessRefreshDiskProps(virDomainDiskDef *disk, } } - diskpriv->removable = info->removable; diskpriv->tray = info->tray; } -- 2.53.0
On a Thursday in 2026, Peter Krempa via Devel wrote:
From: Peter Krempa <pkrempa@redhat.com>
The field is only set, but never read. Drop it.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_domain.h | 2 -- src/qemu/qemu_process.c | 1 - 2 files changed, 3 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano
From: Peter Krempa <pkrempa@redhat.com> In blockdev mode, the guest OS can't force the drive to become empty (opening cdrom tray doesn't remove media; floppies can't be ejected from guest OS), so the check if a drive is empty is dead code at this point. Remove it. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_process.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index fba1dbe844..c130483659 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -9544,9 +9544,6 @@ qemuProcessRefreshDiskProps(virDomainDiskDef *disk, qemuDomainDiskPrivate *diskpriv = QEMU_DOMAIN_DISK_PRIVATE(disk); if (info->removable) { - if (info->empty) - virDomainDiskEmptySource(disk); - if (info->tray) { if (info->tray_open) disk->tray_status = VIR_DOMAIN_DISK_TRAY_OPEN; -- 2.53.0
From: Peter Krempa <pkrempa@redhat.com> The value is no longer used so drop the field and also the code which fetches it from the QMP command reply. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_domain.h | 1 - src/qemu/qemu_monitor_json.c | 6 ------ tests/qemumonitorjsontest.c | 7 ++----- 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 20d6bd316c..0f975a22fc 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -360,7 +360,6 @@ struct qemuDomainDiskInfo { bool removable; bool tray; bool tray_open; - bool empty; int io_status; }; diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index a7e095a648..bf9e59c0b6 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2323,7 +2323,6 @@ qemuMonitorJSONGetBlockInfo(qemuMonitor *mon, for (i = 0; i < virJSONValueArraySize(devices); i++) { virJSONValue *dev; - virJSONValue *image; struct qemuDomainDiskInfo info = { false }; const char *thisdev; const char *status; @@ -2358,11 +2357,6 @@ qemuMonitorJSONGetBlockInfo(qemuMonitor *mon, if (virJSONValueObjectGetBoolean(dev, "tray_open", &info.tray_open) == 0) info.tray = true; - /* presence of 'inserted' notifies that a medium is in the device */ - if (!(image = virJSONValueObjectGetObject(dev, "inserted"))) { - info.empty = true; - } - /* Missing io-status indicates no error */ if ((status = virJSONValueObjectGetString(dev, "io-status"))) { info.io_status = qemuMonitorBlockIOStatusToError(status); diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index efa2400750..699b75ce2d 100644 --- a/tests/qemumonitorjsontest.c +++ b/tests/qemumonitorjsontest.c @@ -1353,10 +1353,8 @@ testQemuMonitorJSONqemuMonitorJSONGetBalloonInfo(const void *opaque) static void testQemuMonitorJSONGetBlockInfoPrint(const struct qemuDomainDiskInfo *d) { - VIR_TEST_VERBOSE("removable: %d, tray: %d, tray_open: %d, empty: %d, " - "io_status: %d", - d->removable, d->tray, d->tray_open, d->empty, - d->io_status); + VIR_TEST_VERBOSE("removable: %d, tray: %d, tray_open: %d, io_status: %d", + d->removable, d->tray, d->tray_open, d->io_status); } @@ -1418,7 +1416,6 @@ testQemuMonitorJSONqemuMonitorJSONGetBlockInfo(const void *opaque) info->removable = true; info->tray = true; - info->empty = true; if (virHashAddEntry(expectedBlockDevices, "ide0-1-1", info) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", -- 2.53.0
From: Peter Krempa <pkrempa@redhat.com> Since 'qemuProcessRefreshDiskProps' doesn't remove the source since we switched to blockdev mode, we don't need to update disk state at the beginning of migration. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_migration.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index b4d2e27370..88db5e93fa 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -3016,7 +3016,6 @@ qemuMigrationSrcBegin(virConnectPtr conn, g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); g_autofree char *xml = NULL; char *ret = NULL; - virDomainAsyncJob asyncJob; if (cfg->migrateTLSForce && !(flags & VIR_MIGRATE_TUNNELLED) && @@ -3035,14 +3034,12 @@ qemuMigrationSrcBegin(virConnectPtr conn, if ((flags & VIR_MIGRATE_CHANGE_PROTECTION)) { if (qemuMigrationJobStart(vm, VIR_ASYNC_JOB_MIGRATION_OUT, flags) < 0) goto cleanup; - asyncJob = VIR_ASYNC_JOB_MIGRATION_OUT; } else { if (!qemuMigrationJobIsAllowed(vm)) goto cleanup; if (virDomainObjBeginJob(vm, VIR_JOB_MODIFY) < 0) goto cleanup; - asyncJob = VIR_ASYNC_JOB_NONE; } qemuMigrationSrcStoreDomainState(vm); @@ -3050,13 +3047,6 @@ qemuMigrationSrcBegin(virConnectPtr conn, if (!(flags & VIR_MIGRATE_OFFLINE) && virDomainObjCheckActive(vm) < 0) goto endjob; - /* Check if there is any ejected media. - * We don't want to require them on the destination. - */ - if (!(flags & VIR_MIGRATE_OFFLINE) && - qemuProcessRefreshDisks(vm, asyncJob) < 0) - goto endjob; - if (!(xml = qemuMigrationSrcBeginPhase(driver, vm, xmlin, dname, cookieout, cookieoutlen, migrate_disks, -- 2.53.0
From: Peter Krempa <pkrempa@redhat.com> Since it's currently called above the place where it is defined we also need to move it within qemu_process.c. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_process.c | 98 ++++++++++++++++++++--------------------- src/qemu/qemu_process.h | 3 -- 2 files changed, 49 insertions(+), 52 deletions(-) diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index c130483659..ba8bda0f99 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -8639,6 +8639,55 @@ qemuProcessRefreshRxFilters(virDomainObj *vm, } +static int +qemuProcessRefreshDisks(virDomainObj *vm, + virDomainAsyncJob asyncJob) +{ + qemuDomainObjPrivate *priv = vm->privateData; + virQEMUDriver *driver = priv->driver; + g_autoptr(GHashTable) table = NULL; + size_t i; + + if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) == 0) { + table = qemuMonitorGetBlockInfo(priv->mon); + qemuDomainObjExitMonitor(vm); + } + + if (!table) + return -1; + + for (i = 0; i < vm->def->ndisks; i++) { + virDomainDiskDef *disk = vm->def->disks[i]; + qemuDomainDiskPrivate *diskpriv = QEMU_DOMAIN_DISK_PRIVATE(disk); + struct qemuDomainDiskInfo *info; + const char *entryname = disk->info.alias; + virDomainDiskTray old_tray_status = disk->tray_status; + + if (diskpriv->qomName) + entryname = diskpriv->qomName; + + if (!(info = virHashLookup(table, entryname))) + continue; + + qemuProcessRefreshDiskProps(disk, info); + + if (diskpriv->tray && + old_tray_status != disk->tray_status) { + virDomainEventTrayChangeReason reason = VIR_DOMAIN_EVENT_TRAY_CHANGE_OPEN; + virObjectEvent *event; + + if (disk->tray_status == VIR_DOMAIN_DISK_TRAY_CLOSED) + reason = VIR_DOMAIN_EVENT_TRAY_CHANGE_CLOSE; + + event = virDomainEventTrayChangeNewFromObj(vm, disk->info.alias, reason); + virObjectEventStateQueue(driver->domainEventState, event); + } + } + + return 0; +} + + /** * qemuProcessRefreshState: * @driver: qemu driver data @@ -9556,55 +9605,6 @@ qemuProcessRefreshDiskProps(virDomainDiskDef *disk, } -int -qemuProcessRefreshDisks(virDomainObj *vm, - virDomainAsyncJob asyncJob) -{ - qemuDomainObjPrivate *priv = vm->privateData; - virQEMUDriver *driver = priv->driver; - g_autoptr(GHashTable) table = NULL; - size_t i; - - if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) == 0) { - table = qemuMonitorGetBlockInfo(priv->mon); - qemuDomainObjExitMonitor(vm); - } - - if (!table) - return -1; - - for (i = 0; i < vm->def->ndisks; i++) { - virDomainDiskDef *disk = vm->def->disks[i]; - qemuDomainDiskPrivate *diskpriv = QEMU_DOMAIN_DISK_PRIVATE(disk); - struct qemuDomainDiskInfo *info; - const char *entryname = disk->info.alias; - virDomainDiskTray old_tray_status = disk->tray_status; - - if (diskpriv->qomName) - entryname = diskpriv->qomName; - - if (!(info = virHashLookup(table, entryname))) - continue; - - qemuProcessRefreshDiskProps(disk, info); - - if (diskpriv->tray && - old_tray_status != disk->tray_status) { - virDomainEventTrayChangeReason reason = VIR_DOMAIN_EVENT_TRAY_CHANGE_OPEN; - virObjectEvent *event; - - if (disk->tray_status == VIR_DOMAIN_DISK_TRAY_CLOSED) - reason = VIR_DOMAIN_EVENT_TRAY_CHANGE_CLOSE; - - event = virDomainEventTrayChangeNewFromObj(vm, disk->info.alias, reason); - virObjectEventStateQueue(driver->domainEventState, event); - } - } - - return 0; -} - - static int qemuProcessRefreshCPUMigratability(virDomainObj *vm, virDomainAsyncJob asyncJob) diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h index 426e11d79e..201b3ebb63 100644 --- a/src/qemu/qemu_process.h +++ b/src/qemu/qemu_process.h @@ -218,9 +218,6 @@ int qemuRefreshVirtioChannelState(virQEMUDriver *driver, int qemuProcessRefreshBalloonState(virDomainObj *vm, int asyncJob); -int qemuProcessRefreshDisks(virDomainObj *vm, - virDomainAsyncJob asyncJob); - int qemuProcessStartManagedPRDaemon(virDomainObj *vm) ATTRIBUTE_MOCKABLE; void qemuProcessKillManagedPRDaemon(virDomainObj *vm) ATTRIBUTE_MOCKABLE; -- 2.53.0
From: Peter Krempa <pkrempa@redhat.com> The only real use was in 'qemuProcessRefreshDiskProps' where it guarded assignment of 'tray' status. Since qemu doesn't actually report any tray status for devices which don't have a tray there's no need for the extra guard. Remove the field completely. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_domain.h | 1 - src/qemu/qemu_monitor_json.c | 7 ------- src/qemu/qemu_process.c | 12 +++++------- tests/qemumonitorjsontest.c | 6 ++---- 4 files changed, 7 insertions(+), 19 deletions(-) diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 0f975a22fc..06e2f92ac3 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -357,7 +357,6 @@ struct _qemuDomainVcpuPrivate { struct qemuDomainDiskInfo { - bool removable; bool tray; bool tray_open; int io_status; diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index bf9e59c0b6..1b05c713ea 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2346,13 +2346,6 @@ qemuMonitorJSONGetBlockInfo(qemuMonitor *mon, return -1; } - if (virJSONValueObjectGetBoolean(dev, "removable", &info.removable) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot read %1$s value"), - "removable"); - return -1; - } - /* 'tray_open' is present only if the device has a tray */ if (virJSONValueObjectGetBoolean(dev, "tray_open", &info.tray_open) == 0) info.tray = true; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index ba8bda0f99..d6ff9c96fc 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -9592,13 +9592,11 @@ qemuProcessRefreshDiskProps(virDomainDiskDef *disk, { qemuDomainDiskPrivate *diskpriv = QEMU_DOMAIN_DISK_PRIVATE(disk); - if (info->removable) { - if (info->tray) { - if (info->tray_open) - disk->tray_status = VIR_DOMAIN_DISK_TRAY_OPEN; - else - disk->tray_status = VIR_DOMAIN_DISK_TRAY_CLOSED; - } + if (info->tray) { + if (info->tray_open) + disk->tray_status = VIR_DOMAIN_DISK_TRAY_OPEN; + else + disk->tray_status = VIR_DOMAIN_DISK_TRAY_CLOSED; } diskpriv->tray = info->tray; diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index 699b75ce2d..b3aca6a6c3 100644 --- a/tests/qemumonitorjsontest.c +++ b/tests/qemumonitorjsontest.c @@ -1353,8 +1353,8 @@ testQemuMonitorJSONqemuMonitorJSONGetBalloonInfo(const void *opaque) static void testQemuMonitorJSONGetBlockInfoPrint(const struct qemuDomainDiskInfo *d) { - VIR_TEST_VERBOSE("removable: %d, tray: %d, tray_open: %d, io_status: %d", - d->removable, d->tray, d->tray_open, d->io_status); + VIR_TEST_VERBOSE("tray: %d, tray_open: %d, io_status: %d", + d->tray, d->tray_open, d->io_status); } @@ -1403,7 +1403,6 @@ testQemuMonitorJSONqemuMonitorJSONGetBlockInfo(const void *opaque) info = g_new0(struct qemuDomainDiskInfo, 1); - info->removable = true; info->tray = true; if (virHashAddEntry(expectedBlockDevices, "ide0-1-0", info) < 0) { @@ -1414,7 +1413,6 @@ testQemuMonitorJSONqemuMonitorJSONGetBlockInfo(const void *opaque) info = g_new0(struct qemuDomainDiskInfo, 1); - info->removable = true; info->tray = true; if (virHashAddEntry(expectedBlockDevices, "ide0-1-1", info) < 0) { -- 2.53.0
From: Peter Krempa <pkrempa@redhat.com> Report both missing 'status' and invalid value in a single error message. Also use the proper spelling of the event name (all caps). Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_monitor_json.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 1b05c713ea..021995f5cc 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -1268,13 +1268,10 @@ qemuMonitorJSONHandleMigrationStatus(qemuMonitor *mon, const char *str; int status; - if (!(str = virJSONValueObjectGetString(data, "status"))) { - VIR_WARN("missing status in migration event"); - return; - } - - if ((status = qemuMonitorMigrationStatusTypeFromString(str)) == -1) { - VIR_WARN("unknown status '%s' in migration event", str); + if (!(str = virJSONValueObjectGetString(data, "status")) || + (status = qemuMonitorMigrationStatusTypeFromString(str)) == -1) { + VIR_WARN("Missing or unknown value '%s' of 'status' in 'MIGRATION' event", + NULLSTR(str)); return; } -- 2.53.0
From: Peter Krempa <pkrempa@redhat.com> The monitor code uses 'bsearch' to look up the event handler so the event names must be properly listed. Until now only an comment reminded us to do it. Add a test to verify that it is actually sorted properly. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_monitor_json.c | 21 +++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 3 +++ tests/qemumonitorjsontest.c | 18 ++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 021995f5cc..825508e8f5 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -143,6 +143,27 @@ qemuMonitorEventCompare(const void *key, const void *elt) } +/** + * qemuMonitorJSONValidateEventHandlers: + * + * Used by 'qemumonitorjsontest' to validate that the 'eventHandlers' array + * is properly sorted to use 'bsearch'. + */ +char * +qemuMonitorJSONValidateEventHandlers(void) +{ + size_t i; + + for (i = 1; i < G_N_ELEMENTS(eventHandlers); i++) { + if (strcmp(eventHandlers[i-1].type, eventHandlers[i].type) > -1) + return g_strdup_printf("mis-ordered 'eventHandlers': '%s', '%s'", + eventHandlers[i-1].type, eventHandlers[i].type); + } + + return NULL; +} + + static int qemuMonitorJSONIOProcessEvent(qemuMonitor *mon, virJSONValue *obj) diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index db9160eb68..8f5434d0df 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -27,6 +27,9 @@ #include "cpu/cpu.h" #include "util/virgic.h" +char * +qemuMonitorJSONValidateEventHandlers(void); + int qemuMonitorJSONIOProcessLine(qemuMonitor *mon, const char *line, diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index b3aca6a6c3..9c9b3397ad 100644 --- a/tests/qemumonitorjsontest.c +++ b/tests/qemumonitorjsontest.c @@ -2825,6 +2825,20 @@ testQemuMonitorJSONGetGuestCPU(const void *opaque) } +static int +testEventHandlersOrdering(const void *opaque G_GNUC_UNUSED) +{ + g_autofree char *errmsg = NULL; + + if ((errmsg = qemuMonitorJSONValidateEventHandlers())) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", errmsg); + return -1; + } + + return 0; +} + + static int mymain(void) { @@ -2848,6 +2862,10 @@ mymain(void) qapiData.schema = qapischema_x86_64; + if (virTestRun("'eventHandlers' ordering check", testEventHandlersOrdering, + NULL) < 0) + ret = -1; + #define DO_TEST(name) \ do { \ testGenericData data = { driver.xmlopt, qapiData.schema }; \ -- 2.53.0
From: Peter Krempa <pkrempa@redhat.com> Report missing 'recipient' and 'action' together with the warning about unknown value. Use the actual name of the event. Additional booleans can be extracted without extra variables. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_monitor_json.c | 32 ++++++++++---------------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 825508e8f5..328e32533d 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -1243,41 +1243,29 @@ qemuMonitorJSONHandleMemoryFailure(qemuMonitor *mon, const char *str; int recipient; int action; - bool ar = false; - bool recursive = false; qemuMonitorEventMemoryFailure mf = {0}; - if (!(str = virJSONValueObjectGetString(data, "recipient"))) { - VIR_WARN("missing recipient in memory failure event"); - return; - } - - recipient = qemuMonitorMemoryFailureRecipientTypeFromString(str); - if (recipient < 0) { - VIR_WARN("unknown recipient '%s' in memory_failure event", str); - return; - } - - if (!(str = virJSONValueObjectGetString(data, "action"))) { - VIR_WARN("missing action in memory failure event"); + if (!(str = virJSONValueObjectGetString(data, "recipient")) || + (recipient = qemuMonitorMemoryFailureRecipientTypeFromString(str)) < 0) { + VIR_WARN("missing or unknown value '%s' of 'recipient' field in 'MEMORY_FAILURE' event", + NULLSTR(str)); return; } - action = qemuMonitorMemoryFailureActionTypeFromString(str); - if (action < 0) { - VIR_WARN("unknown action '%s' in memory_failure event", str); + if (!(str = virJSONValueObjectGetString(data, "action")) || + (action = qemuMonitorMemoryFailureActionTypeFromString(str)) < 0) { + VIR_WARN("missing or unknown value '%s' of 'action' field in 'MEMORY_FAILURE' event", + NULLSTR(str)); return; } if (flagsjson) { - virJSONValueObjectGetBoolean(flagsjson, "action-required", &ar); - virJSONValueObjectGetBoolean(flagsjson, "recursive", &recursive); + virJSONValueObjectGetBoolean(flagsjson, "action-required", &mf.action_required); + virJSONValueObjectGetBoolean(flagsjson, "recursive", &mf.recursive); } mf.recipient = recipient; mf.action = action; - mf.action_required = ar; - mf.recursive = recursive; qemuMonitorEmitMemoryFailure(mon, &mf); } -- 2.53.0
From: Peter Krempa <pkrempa@redhat.com> 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> --- src/qemu/qemu_monitor.c | 42 -------------------------------- src/qemu/qemu_monitor.h | 3 --- src/qemu/qemu_monitor_json.c | 47 +++++++++++++++++++++++++++++++++--- 3 files changed, 43 insertions(+), 49 deletions(-) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 6acc80832c..1434da7f70 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -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) { diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 041aa7bc12..a35dbe560f 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -783,9 +783,6 @@ qemuMonitorSetMemoryStatsPeriod(qemuMonitor *mon, virDomainMemballoonDef *balloon, int period); -int -qemuMonitorBlockIOStatusToError(const char *status); - GHashTable * qemuMonitorGetBlockInfo(qemuMonitor *mon); diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 328e32533d..50e0497385 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -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 && -- 2.53.0
From: Peter Krempa <pkrempa@redhat.com> Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_domain.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 06e2f92ac3..393f9c9c96 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -359,7 +359,7 @@ struct _qemuDomainVcpuPrivate { struct qemuDomainDiskInfo { bool tray; bool tray_open; - int io_status; + virDomainDiskErrorCode io_status; }; #define QEMU_DOMAIN_CHR_SOURCE_PRIVATE(dev) \ -- 2.53.0
From: Peter Krempa <pkrempa@redhat.com> Currently the default state was VIR_DOMAIN_DISK_TRAY_CLOSED. Not all disks have a tray so add another state as the default and adjust code which was based on the assumption that the tray is always present. This change also removes the need for the 'tray' field in the disk private data which was used inconsistently. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/conf/domain_conf.c | 17 +++++++++++++---- src/conf/domain_conf.h | 3 ++- src/qemu/qemu_hotplug.c | 6 ++++-- src/qemu/qemu_process.c | 3 ++- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 02e23f7866..fe61284789 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1286,6 +1286,7 @@ VIR_ENUM_IMPL(virDomainCpuPlacementMode, VIR_ENUM_IMPL(virDomainDiskTray, VIR_DOMAIN_DISK_TRAY_LAST, + "", "closed", "open", ); @@ -8600,7 +8601,7 @@ virDomainDiskDefParseXML(virDomainXMLOption *xmlopt, return NULL; if (virXMLPropEnum(targetNode, "tray", virDomainDiskTrayTypeFromString, - VIR_XML_PROP_NONE, &def->tray_status) < 0) + VIR_XML_PROP_NONZERO, &def->tray_status) < 0) return NULL; if (virXMLPropTristateSwitch(targetNode, "removable", VIR_XML_PROP_NONE, @@ -24247,11 +24248,19 @@ virDomainDiskDefFormat(virBuffer *buf, virBufferAsprintf(&childBuf, "<target dev='%s' bus='%s'", def->dst, bus); - if ((def->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY || - def->device == VIR_DOMAIN_DISK_DEVICE_CDROM) && - def->tray_status != VIR_DOMAIN_DISK_TRAY_CLOSED) + + switch (def->tray_status) { + case VIR_DOMAIN_DISK_TRAY_NONE: + case VIR_DOMAIN_DISK_TRAY_CLOSED: + case VIR_DOMAIN_DISK_TRAY_LAST: + break; + + case VIR_DOMAIN_DISK_TRAY_OPEN: virBufferAsprintf(&childBuf, " tray='%s'", virDomainDiskTrayTypeToString(def->tray_status)); + break; + } + if (def->bus == VIR_DOMAIN_DISK_BUS_USB && def->removable != VIR_TRISTATE_SWITCH_ABSENT) { virBufferAsprintf(&childBuf, " removable='%s'", diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 66dc4e3417..9e3735da73 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -421,7 +421,8 @@ typedef enum { typedef enum { - VIR_DOMAIN_DISK_TRAY_CLOSED = 0, + VIR_DOMAIN_DISK_TRAY_NONE = 0, + VIR_DOMAIN_DISK_TRAY_CLOSED, VIR_DOMAIN_DISK_TRAY_OPEN, VIR_DOMAIN_DISK_TRAY_LAST diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index f786248e70..0d5da456c5 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -539,7 +539,7 @@ qemuDomainChangeMediaBlockdev(virDomainObj *vm, return -1; } - if (diskPriv->tray && disk->tray_status != VIR_DOMAIN_DISK_TRAY_OPEN) { + if (disk->tray_status == VIR_DOMAIN_DISK_TRAY_CLOSED) { qemuDomainObjEnterMonitor(vm); rc = qemuMonitorBlockdevTrayOpen(priv->mon, diskPriv->qomName, force); qemuDomainObjExitMonitor(vm); @@ -575,7 +575,9 @@ qemuDomainChangeMediaBlockdev(virDomainObj *vm, &disk->blkdeviotune); } - if (rc == 0) + /* Close any device with a tray since we've opened it before (regardless + * of the current state if it e.g. wasn't updated) */ + if (rc == 0 && disk->tray_status != VIR_DOMAIN_DISK_TRAY_NONE) rc = qemuMonitorBlockdevTrayClose(priv->mon, diskPriv->qomName); if (rc < 0 && newbackend) diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index d6ff9c96fc..e627d2121e 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -8671,7 +8671,8 @@ qemuProcessRefreshDisks(virDomainObj *vm, qemuProcessRefreshDiskProps(disk, info); - if (diskpriv->tray && + if (old_tray_status != VIR_DOMAIN_DISK_TRAY_NONE && + disk->tray_status != VIR_DOMAIN_DISK_TRAY_NONE && old_tray_status != disk->tray_status) { virDomainEventTrayChangeReason reason = VIR_DOMAIN_EVENT_TRAY_CHANGE_OPEN; virObjectEvent *event; -- 2.53.0
From: Peter Krempa <pkrempa@redhat.com> Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_domain.h | 2 -- src/qemu/qemu_process.c | 4 ---- 2 files changed, 6 deletions(-) diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 393f9c9c96..2a881a8285 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -288,8 +288,6 @@ struct _qemuDomainDiskPrivate { virStorageSource *migrSource; /* disk source object used for NBD migration */ bool migrationslice; /* storage slice was added for migration purposes */ - bool tray; /* device has tray */ - char *qomName; /* QOM path of the disk (also refers to the block backend) */ char *nodeCopyOnRead; /* nodename of the disk-wide copy-on-read blockdev layer */ diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index e627d2121e..2142198589 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -9591,16 +9591,12 @@ void qemuProcessRefreshDiskProps(virDomainDiskDef *disk, struct qemuDomainDiskInfo *info) { - qemuDomainDiskPrivate *diskpriv = QEMU_DOMAIN_DISK_PRIVATE(disk); - if (info->tray) { if (info->tray_open) disk->tray_status = VIR_DOMAIN_DISK_TRAY_OPEN; else disk->tray_status = VIR_DOMAIN_DISK_TRAY_CLOSED; } - - diskpriv->tray = info->tray; } -- 2.53.0
From: Peter Krempa <pkrempa@redhat.com> The only thing the call to 'qemuProcessRefreshDiskProps' would update from data gathered from a 'query-block' QMP call would be the state of the tray of the device. We know that only CDROM devices have a tray and after hotplug it's closed. Remove the unneeded code and adjust tests. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_hotplug.c | 12 +++--------- tests/qemuhotplugtest.c | 38 ++++++++++++-------------------------- 2 files changed, 15 insertions(+), 35 deletions(-) diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 0d5da456c5..e1e5688942 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -711,6 +711,9 @@ qemuDomainAttachDiskGeneric(virDomainObj *vm, g_autoptr(qemuSnapshotDiskContext) transientDiskSnapshotCtxt = NULL; bool origReadonly = disk->src->readonly; + if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) + disk->tray_status = VIR_DOMAIN_DISK_TRAY_CLOSED; + if (!virStorageSourceIsEmpty(disk->src)) { if (disk->transient) disk->src->readonly = true; @@ -803,21 +806,12 @@ qemuDomainAttachDiskGeneric(virDomainObj *vm, */ if (rc == 0) { qemuDomainDiskPrivate *diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); - g_autoptr(GHashTable) blockinfo = NULL; if (qemuDiskConfigBlkdeviotuneEnabled(disk)) { if (qemuMonitorSetBlockIoThrottle(priv->mon, diskPriv->qomName, &disk->blkdeviotune) < 0) VIR_WARN("failed to set blkdeviotune for '%s' of '%s'", disk->dst, vm->def->name); } - - if ((blockinfo = qemuMonitorGetBlockInfo(priv->mon))) { - struct qemuDomainDiskInfo *diskinfo; - - if ((diskinfo = virHashLookup(blockinfo, diskPriv->qomName))) { - qemuProcessRefreshDiskProps(disk, diskinfo); - } - } } if (rc == 0 && diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c index 7881ccf327..58413b6e0d 100644 --- a/tests/qemuhotplugtest.c +++ b/tests/qemuhotplugtest.c @@ -541,7 +541,6 @@ mymain(void) #define QMP_OK "{\"return\": {}}" -#define QMP_EMPTY_ARRAY "{\"return\": []}" #define QMP_DEVICE_DELETED(dev) \ "{" \ @@ -579,8 +578,7 @@ mymain(void) DO_TEST_ATTACH("x86_64", "base-live", "disk-virtio", false, true, "blockdev-add", QMP_OK, - "device_add", QMP_OK, - "query-block", QMP_EMPTY_ARRAY); + "device_add", QMP_OK); DO_TEST_DETACH("x86_64", "base-live", "disk-virtio", true, true, "device_del", QMP_OK); DO_TEST_DETACH("x86_64", "base-live", "disk-virtio", false, false, @@ -589,8 +587,7 @@ mymain(void) DO_TEST_ATTACH("x86_64", "base-live", "disk-usb", false, true, "blockdev-add", QMP_OK, - "device_add", QMP_OK, - "query-block", QMP_EMPTY_ARRAY); + "device_add", QMP_OK); DO_TEST_DETACH("x86_64", "base-live", "disk-usb", true, true, "device_del", QMP_OK); DO_TEST_DETACH("x86_64", "base-live", "disk-usb", false, false, @@ -599,8 +596,7 @@ mymain(void) DO_TEST_ATTACH("x86_64", "base-live", "disk-scsi", false, true, "blockdev-add", QMP_OK, - "device_add", QMP_OK, - "query-block", QMP_EMPTY_ARRAY); + "device_add", QMP_OK); DO_TEST_DETACH("x86_64", "base-live", "disk-scsi", true, true, "device_del", QMP_OK); DO_TEST_DETACH("x86_64", "base-live", "disk-scsi", false, false, @@ -614,8 +610,7 @@ mymain(void) "device_add", QMP_OK, "device_add", QMP_OK, "blockdev-add", QMP_OK, - "device_add", QMP_OK, - "query-block", QMP_EMPTY_ARRAY); + "device_add", QMP_OK); DO_TEST_DETACH("x86_64", "base-with-scsi-controller-live", "disk-scsi-2", true, true, "device_del", QMP_OK); DO_TEST_DETACH("x86_64", "base-with-scsi-controller-live", "disk-scsi-2", false, false, @@ -625,8 +620,7 @@ mymain(void) DO_TEST_ATTACH("x86_64", "base-live", "disk-scsi-multipath", false, true, "object-add", QMP_OK, "blockdev-add", QMP_OK, - "device_add", QMP_OK, - "query-block", QMP_EMPTY_ARRAY); + "device_add", QMP_OK); DO_TEST_DETACH("x86_64", "base-live", "disk-scsi-multipath", true, true, "device_del", QMP_OK); DO_TEST_DETACH("x86_64", "base-live", "disk-scsi-multipath", false, false, @@ -644,16 +638,14 @@ mymain(void) DO_TEST_ATTACH("s390x", "base-ccw-live", "ccw-virtio", false, true, "blockdev-add", QMP_OK, - "device_add", QMP_OK, - "query-block", QMP_EMPTY_ARRAY); + "device_add", QMP_OK); DO_TEST_DETACH("s390x", "base-ccw-live", "ccw-virtio", false, false, "device_del", QMP_DEVICE_DELETED("virtio-disk4") QMP_OK, "blockdev-del", QMP_OK); DO_TEST_ATTACH("s390x", "base-ccw-live-with-ccw-virtio", "ccw-virtio-2", false, true, "blockdev-add", QMP_OK, - "device_add", QMP_OK, - "query-block", QMP_EMPTY_ARRAY); + "device_add", QMP_OK); DO_TEST_DETACH("s390x", "base-ccw-live-with-ccw-virtio", "ccw-virtio-2", false, false, "device_del", QMP_DEVICE_DELETED("virtio-disk0") QMP_OK, @@ -661,8 +653,7 @@ mymain(void) DO_TEST_ATTACH("s390x", "base-ccw-live-with-ccw-virtio", "ccw-virtio-2-explicit", false, true, "blockdev-add", QMP_OK, - "device_add", QMP_OK, - "query-block", QMP_EMPTY_ARRAY); + "device_add", QMP_OK); DO_TEST_DETACH("s390x", "base-ccw-live-with-ccw-virtio", "ccw-virtio-2-explicit", false, false, "device_del", QMP_DEVICE_DELETED("virtio-disk0") QMP_OK, @@ -671,16 +662,14 @@ mymain(void) /* Attach a second device, then detach the first one. Then attach the first one again. */ DO_TEST_ATTACH("s390x", "base-ccw-live-with-ccw-virtio", "ccw-virtio-2-explicit", false, true, "blockdev-add", QMP_OK, - "device_add", QMP_OK, - "query-block", QMP_EMPTY_ARRAY); + "device_add", QMP_OK); DO_TEST_DETACH("s390x", "base-ccw-live-with-2-ccw-virtio", "ccw-virtio-1-explicit", false, true, "device_del", QMP_DEVICE_DELETED("virtio-disk4") QMP_OK); DO_TEST_ATTACH("s390x", "base-ccw-live-with-2-ccw-virtio", "ccw-virtio-1-reverse", false, false, "blockdev-add", QMP_OK, - "device_add", QMP_OK, - "query-block", QMP_EMPTY_ARRAY); + "device_add", QMP_OK); DO_TEST_ATTACH("x86_64", "base-live", "ivshmem-plain", false, true, "object-add", QMP_OK, @@ -697,8 +686,7 @@ mymain(void) DO_TEST_ATTACH("x86_64", "base-live+disk-scsi-wwn", "disk-scsi-duplicate-wwn", false, false, "blockdev-add", QMP_OK, - "device_add", QMP_OK, - "query-block", QMP_EMPTY_ARRAY); + "device_add", QMP_OK); DO_TEST_ATTACH("x86_64", "base-live", "hostdev-pci", false, true, "device_add", QMP_OK); @@ -747,7 +735,6 @@ mymain(void) "blockdev-add", QMP_OK, "device_add", QMP_OK, "device_add", QMP_OK, - "query-block", QMP_EMPTY_ARRAY, "qom-set", QMP_OK); DO_TEST_DETACH("x86_64", "base-live", "cdrom-usb", true, true, "device_del", QMP_OK); @@ -757,8 +744,7 @@ mymain(void) DO_TEST_ATTACH("x86_64", "base-live", "cdrom-scsi", false, true, "blockdev-add", QMP_OK, - "device_add", QMP_OK, - "query-block", QMP_EMPTY_ARRAY); + "device_add", QMP_OK); DO_TEST_DETACH("x86_64", "base-live", "cdrom-scsi", true, true, "device_del", QMP_OK); DO_TEST_DETACH("x86_64", "base-live", "cdrom-scsi", false, false, -- 2.53.0
From: Peter Krempa <pkrempa@redhat.com> Modify the monitor code to directly return values from 'virDomainDiskTray' enum instead of two bools. This allows simplification of the other code: - qemuProcessRefreshDiskProps just assigns the value, thus can be deleted - old_tray_status is no longer needed as we can directly access the disk status instead and assign later Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_domain.h | 3 +-- src/qemu/qemu_monitor_json.c | 14 +++++++++++--- src/qemu/qemu_process.c | 26 ++++++-------------------- src/qemu/qemu_process.h | 3 --- tests/qemumonitorjsontest.c | 8 ++++---- 5 files changed, 22 insertions(+), 32 deletions(-) diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 2a881a8285..d4f6c256cd 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -355,8 +355,7 @@ struct _qemuDomainVcpuPrivate { struct qemuDomainDiskInfo { - bool tray; - bool tray_open; + virDomainDiskTray tray_status; virDomainDiskErrorCode io_status; }; diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 50e0497385..971e8dd63f 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2347,10 +2347,14 @@ qemuMonitorJSONGetBlockInfo(qemuMonitor *mon, for (i = 0; i < virJSONValueArraySize(devices); i++) { virJSONValue *dev; - struct qemuDomainDiskInfo info = { .io_status = VIR_DOMAIN_DISK_ERROR_NONE }; + struct qemuDomainDiskInfo info = { + .tray_status = VIR_DOMAIN_DISK_TRAY_NONE, + .io_status = VIR_DOMAIN_DISK_ERROR_NONE + }; const char *thisdev; const char *status; const char *qdev; + bool tray_open; if (!(dev = qemuMonitorJSONGetBlockDev(devices, i))) return -1; @@ -2371,8 +2375,12 @@ qemuMonitorJSONGetBlockInfo(qemuMonitor *mon, } /* 'tray_open' is present only if the device has a tray */ - if (virJSONValueObjectGetBoolean(dev, "tray_open", &info.tray_open) == 0) - info.tray = true; + if (virJSONValueObjectGetBoolean(dev, "tray_open", &tray_open) == 0) { + if (tray_open) + info.tray_status = VIR_DOMAIN_DISK_TRAY_OPEN; + else + info.tray_status = VIR_DOMAIN_DISK_TRAY_CLOSED; + } /* Missing io-status indicates no error */ if ((status = virJSONValueObjectGetString(dev, "io-status"))) { diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 2142198589..0b78d45ef6 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -8661,7 +8661,6 @@ qemuProcessRefreshDisks(virDomainObj *vm, qemuDomainDiskPrivate *diskpriv = QEMU_DOMAIN_DISK_PRIVATE(disk); struct qemuDomainDiskInfo *info; const char *entryname = disk->info.alias; - virDomainDiskTray old_tray_status = disk->tray_status; if (diskpriv->qomName) entryname = diskpriv->qomName; @@ -8669,20 +8668,20 @@ qemuProcessRefreshDisks(virDomainObj *vm, if (!(info = virHashLookup(table, entryname))) continue; - qemuProcessRefreshDiskProps(disk, info); - - if (old_tray_status != VIR_DOMAIN_DISK_TRAY_NONE && - disk->tray_status != VIR_DOMAIN_DISK_TRAY_NONE && - old_tray_status != disk->tray_status) { + if (disk->tray_status != VIR_DOMAIN_DISK_TRAY_NONE && + info->tray_status != VIR_DOMAIN_DISK_TRAY_NONE && + disk->tray_status != info->tray_status) { virDomainEventTrayChangeReason reason = VIR_DOMAIN_EVENT_TRAY_CHANGE_OPEN; virObjectEvent *event; - if (disk->tray_status == VIR_DOMAIN_DISK_TRAY_CLOSED) + if (info->tray_status == VIR_DOMAIN_DISK_TRAY_CLOSED) reason = VIR_DOMAIN_EVENT_TRAY_CHANGE_CLOSE; event = virDomainEventTrayChangeNewFromObj(vm, disk->info.alias, reason); virObjectEventStateQueue(driver->domainEventState, event); } + + disk->tray_status = info->tray_status; } return 0; @@ -9587,19 +9586,6 @@ qemuProcessAutoDestroy(virDomainObj *dom, } -void -qemuProcessRefreshDiskProps(virDomainDiskDef *disk, - struct qemuDomainDiskInfo *info) -{ - if (info->tray) { - if (info->tray_open) - disk->tray_status = VIR_DOMAIN_DISK_TRAY_OPEN; - else - disk->tray_status = VIR_DOMAIN_DISK_TRAY_CLOSED; - } -} - - static int qemuProcessRefreshCPUMigratability(virDomainObj *vm, virDomainAsyncJob asyncJob) diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h index 201b3ebb63..df63cac9b8 100644 --- a/src/qemu/qemu_process.h +++ b/src/qemu/qemu_process.h @@ -257,9 +257,6 @@ bool qemuProcessRebootAllowed(const virDomainDef *def); void qemuProcessCleanupMigrationJob(virQEMUDriver *driver, virDomainObj *vm); -void qemuProcessRefreshDiskProps(virDomainDiskDef *disk, - struct qemuDomainDiskInfo *info); - int qemuProcessSetupEmulator(virDomainObj *vm); void qemuProcessHandleNbdkitExit(qemuNbdkitProcess *nbdkit, diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index 9c9b3397ad..c10faa6a6f 100644 --- a/tests/qemumonitorjsontest.c +++ b/tests/qemumonitorjsontest.c @@ -1353,8 +1353,8 @@ testQemuMonitorJSONqemuMonitorJSONGetBalloonInfo(const void *opaque) static void testQemuMonitorJSONGetBlockInfoPrint(const struct qemuDomainDiskInfo *d) { - VIR_TEST_VERBOSE("tray: %d, tray_open: %d, io_status: %d", - d->tray, d->tray_open, d->io_status); + VIR_TEST_VERBOSE("tray_status: %d, io_status: %d", + d->tray_status, d->io_status); } @@ -1403,7 +1403,7 @@ testQemuMonitorJSONqemuMonitorJSONGetBlockInfo(const void *opaque) info = g_new0(struct qemuDomainDiskInfo, 1); - info->tray = true; + info->tray_status = VIR_DOMAIN_DISK_TRAY_CLOSED; if (virHashAddEntry(expectedBlockDevices, "ide0-1-0", info) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", @@ -1413,7 +1413,7 @@ testQemuMonitorJSONqemuMonitorJSONGetBlockInfo(const void *opaque) info = g_new0(struct qemuDomainDiskInfo, 1); - info->tray = true; + info->tray_status = VIR_DOMAIN_DISK_TRAY_CLOSED; if (virHashAddEntry(expectedBlockDevices, "ide0-1-1", info) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", -- 2.53.0
From: Peter Krempa <pkrempa@redhat.com> 'driver' is part of domain's private data. Use it directly and adjust all callers recursively. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_driver.c | 10 ++++------ src/qemu/qemu_migration.c | 2 +- src/qemu/qemu_process.c | 15 ++++++--------- src/qemu/qemu_process.h | 3 +-- src/qemu/qemu_saveimage.c | 2 +- 5 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index cdd333c882..a81a4054d6 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1966,7 +1966,6 @@ qemuDomainReset(virDomainPtr dom, unsigned int flags) int ret = -1; qemuDomainObjPrivate *priv; virDomainState state; - virQEMUDriver *driver = dom->conn->privateData; virCheckFlags(0, -1); @@ -2001,7 +2000,7 @@ qemuDomainReset(virDomainPtr dom, unsigned int flags) if (state == VIR_DOMAIN_CRASHED) virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_CRASHED); - qemuProcessRefreshState(driver, vm, VIR_ASYNC_JOB_NONE); + qemuProcessRefreshState(vm, VIR_ASYNC_JOB_NONE); endjob: virDomainObjEndJob(vm); @@ -4035,13 +4034,12 @@ processMemoryDeviceSizeChange(virQEMUDriver *driver, static void -processResetEvent(virQEMUDriver *driver, - virDomainObj *vm) +processResetEvent(virDomainObj *vm) { if (virDomainObjBeginJob(vm, VIR_JOB_MODIFY) < 0) return; - qemuProcessRefreshState(driver, vm, VIR_ASYNC_JOB_NONE); + qemuProcessRefreshState(vm, VIR_ASYNC_JOB_NONE); virDomainObjEndJob(vm); } @@ -4133,7 +4131,7 @@ static void qemuProcessEventHandler(void *data, void *opaque) processEvent->status); break; case QEMU_PROCESS_EVENT_RESET: - processResetEvent(driver, vm); + processResetEvent(vm); break; case QEMU_PROCESS_EVENT_NBDKIT_EXITED: processNbdkitExitedEvent(vm, processEvent->data); diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 88db5e93fa..0e097f25b1 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -6805,7 +6805,7 @@ qemuMigrationDstFinishFresh(virQEMUDriver *driver, /* Now that the state data was transferred we can refresh the actual state * of the devices */ - if (qemuProcessRefreshState(driver, vm, VIR_ASYNC_JOB_MIGRATION_IN) < 0) { + if (qemuProcessRefreshState(vm, VIR_ASYNC_JOB_MIGRATION_IN) < 0) { /* Similarly to the case above v2 protocol will not be able to recover * from this. Let's ignore this and perhaps stuff will not break. */ if (v3proto) diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 0b78d45ef6..2628a89cbf 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -3225,8 +3225,7 @@ qemuProcessCleanupChardevDevice(virDomainDef *def G_GNUC_UNUSED, * migration. */ static int -qemuProcessUpdateVideoRamSize(virQEMUDriver *driver, - virDomainObj *vm, +qemuProcessUpdateVideoRamSize(virDomainObj *vm, int asyncJob) { int ret = -1; @@ -3296,8 +3295,8 @@ qemuProcessUpdateVideoRamSize(virQEMUDriver *driver, qemuDomainObjExitMonitor(vm); - cfg = virQEMUDriverGetConfig(driver); - ret = virDomainObjSave(vm, driver->xmlopt, cfg->stateDir); + cfg = virQEMUDriverGetConfig(priv->driver); + ret = virDomainObjSave(vm, priv->driver->xmlopt, cfg->stateDir); return ret; @@ -8690,7 +8689,6 @@ qemuProcessRefreshDisks(virDomainObj *vm, /** * qemuProcessRefreshState: - * @driver: qemu driver data * @vm: domain to refresh * @asyncJob: async job type * @@ -8699,8 +8697,7 @@ qemuProcessRefreshDisks(virDomainObj *vm, * state influenced by the migration stream. */ int -qemuProcessRefreshState(virQEMUDriver *driver, - virDomainObj *vm, +qemuProcessRefreshState(virDomainObj *vm, virDomainAsyncJob asyncJob) { VIR_DEBUG("Fetching list of active devices"); @@ -8712,7 +8709,7 @@ qemuProcessRefreshState(virQEMUDriver *driver, return -1; VIR_DEBUG("Detecting actual memory size for video device"); - if (qemuProcessUpdateVideoRamSize(driver, vm, asyncJob) < 0) + if (qemuProcessUpdateVideoRamSize(vm, asyncJob) < 0) return -1; VIR_DEBUG("Updating disk data"); @@ -8839,7 +8836,7 @@ qemuProcessStart(virConnectPtr conn, /* Refresh state of devices from QEMU. During migration this happens * in qemuMigrationDstFinish to ensure that state information is fully * transferred. */ - if (qemuProcessRefreshState(driver, vm, asyncJob) < 0) + if (qemuProcessRefreshState(vm, asyncJob) < 0) goto stop; } diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h index df63cac9b8..d96502b601 100644 --- a/src/qemu/qemu_process.h +++ b/src/qemu/qemu_process.h @@ -163,8 +163,7 @@ int qemuProcessFinishStartup(virQEMUDriver *driver, bool startCPUs, virDomainPausedReason pausedReason); -int qemuProcessRefreshState(virQEMUDriver *driver, - virDomainObj *vm, +int qemuProcessRefreshState(virDomainObj *vm, virDomainAsyncJob asyncJob); typedef enum { diff --git a/src/qemu/qemu_saveimage.c b/src/qemu/qemu_saveimage.c index cdfa9be09d..23922acd51 100644 --- a/src/qemu/qemu_saveimage.c +++ b/src/qemu/qemu_saveimage.c @@ -759,7 +759,7 @@ qemuSaveImageStartVM(virConnectPtr conn, VIR_DOMAIN_EVENT_STARTED_RESTORED); virObjectEventStateQueue(driver->domainEventState, event); - if (qemuProcessRefreshState(driver, vm, asyncJob) < 0) + if (qemuProcessRefreshState(vm, asyncJob) < 0) goto cleanup; /* If it was running before, resume it now unless caller requested pause. */ -- 2.53.0
From: Peter Krempa <pkrempa@redhat.com> The only thing that 'qemuProcessRefreshDisks' currently does is to update tray state for disks. This makes no sense on cold boot since only cdroms have tray and the tray is closed. Avoid the extra call to 'query-block' on cold boot and just assume CDROM has a closed tray. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_process.c | 47 ++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 2628a89cbf..51b91f2b98 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -8640,6 +8640,7 @@ qemuProcessRefreshRxFilters(virDomainObj *vm, static int qemuProcessRefreshDisks(virDomainObj *vm, + bool cold_start, virDomainAsyncJob asyncJob) { qemuDomainObjPrivate *priv = vm->privateData; @@ -8647,13 +8648,15 @@ qemuProcessRefreshDisks(virDomainObj *vm, g_autoptr(GHashTable) table = NULL; size_t i; - if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) == 0) { - table = qemuMonitorGetBlockInfo(priv->mon); - qemuDomainObjExitMonitor(vm); - } + if (!cold_start) { + if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) == 0) { + table = qemuMonitorGetBlockInfo(priv->mon); + qemuDomainObjExitMonitor(vm); + } - if (!table) - return -1; + if (!table) + return -1; + } for (i = 0; i < vm->def->ndisks; i++) { virDomainDiskDef *disk = vm->def->disks[i]; @@ -8661,6 +8664,14 @@ qemuProcessRefreshDisks(virDomainObj *vm, struct qemuDomainDiskInfo *info; const char *entryname = disk->info.alias; + /* At startup, when the rest of the detection will be skipped cdroms + * have empty trays */ + if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) + disk->tray_status = VIR_DOMAIN_DISK_TRAY_CLOSED; + + if (!table) + continue; + if (diskpriv->qomName) entryname = diskpriv->qomName; @@ -8690,15 +8701,17 @@ qemuProcessRefreshDisks(virDomainObj *vm, /** * qemuProcessRefreshState: * @vm: domain to refresh + * @cold_boot: starting a fresh VM * @asyncJob: async job type * * This function gathers calls to refresh qemu state after startup. This * function is called after a deferred migration finishes so that we can update * state influenced by the migration stream. */ -int -qemuProcessRefreshState(virDomainObj *vm, - virDomainAsyncJob asyncJob) +static int +qemuProcessRefreshStateInternal(virDomainObj *vm, + bool cold_boot, + virDomainAsyncJob asyncJob) { VIR_DEBUG("Fetching list of active devices"); if (qemuDomainUpdateDeviceList(vm, asyncJob) < 0) @@ -8713,7 +8726,7 @@ qemuProcessRefreshState(virDomainObj *vm, return -1; VIR_DEBUG("Updating disk data"); - if (qemuProcessRefreshDisks(vm, asyncJob) < 0) + if (qemuProcessRefreshDisks(vm, cold_boot, asyncJob) < 0) return -1; VIR_DEBUG("Updating rx-filter data"); @@ -8724,6 +8737,14 @@ qemuProcessRefreshState(virDomainObj *vm, } +int +qemuProcessRefreshState(virDomainObj *vm, + virDomainAsyncJob asyncJob) +{ + return qemuProcessRefreshStateInternal(vm, false, asyncJob); +} + + /** * qemuProcessFinishStartup: * @@ -8836,7 +8857,9 @@ qemuProcessStart(virConnectPtr conn, /* Refresh state of devices from QEMU. During migration this happens * in qemuMigrationDstFinish to ensure that state information is fully * transferred. */ - if (qemuProcessRefreshState(vm, asyncJob) < 0) + if (qemuProcessRefreshStateInternal(vm, + !!(flags & VIR_QEMU_PROCESS_START_COLD), + asyncJob) < 0) goto stop; } @@ -9930,7 +9953,7 @@ qemuProcessReconnect(void *opaque) qemuProcessFiltersInstantiate(obj->def); - if (qemuProcessRefreshDisks(obj, VIR_ASYNC_JOB_NONE) < 0) + if (qemuProcessRefreshDisks(obj, false, VIR_ASYNC_JOB_NONE) < 0) goto error; /* At this point we've already checked that the startup of the VM was -- 2.53.0
From: Peter Krempa <pkrempa@redhat.com> The 'flat' mode of 'query-block' allows ommiting information we don't actually read. Add a capability which will allow us to request the new mode. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + 2 files changed, 3 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index f456e8a378..69db20e5b0 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -755,6 +755,7 @@ VIR_ENUM_IMPL(virQEMUCaps, "disk-timed-stats", /* QEMU_CAPS_DISK_TIMED_STATS */ "query-accelerators", /* QEMU_CAPS_QUERY_ACCELERATORS */ "mshv", /* QEMU_CAPS_MSHV */ + "query-block-flat", /* QEMU_CAPS_QUERY_BLOCK_FLAT */ ); @@ -1647,6 +1648,7 @@ static struct virQEMUCapsStringFlags virQEMUCapsQMPSchemaQueries[] = { { "netdev_add/arg-type/+stream/reconnect-ms", QEMU_CAPS_NETDEV_STREAM_RECONNECT_MILISECONDS }, { "object-add/arg-type/+sev-guest/kernel-hashes", QEMU_CAPS_SEV_GUEST_KERNEL_HASHES }, { "object-add/arg-type/+iothread/thread-pool-max", QEMU_CAPS_IOTHREAD_THREAD_POOL_MAX }, + { "query-block/arg-type/flat", QEMU_CAPS_QUERY_BLOCK_FLAT }, { "query-display-options/ret-type/+egl-headless/rendernode", QEMU_CAPS_EGL_HEADLESS_RENDERNODE }, { "query-display-options/ret-type/+sdl", QEMU_CAPS_SDL }, { "query-display-options/ret-type/+egl-headless", QEMU_CAPS_EGL_HEADLESS }, diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index f180844e66..da9143f4da 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -730,6 +730,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_DISK_TIMED_STATS, /* timed stats support ('stats-intervals' property of disk frontends) */ QEMU_CAPS_QUERY_ACCELERATORS, /* query-accelerators command */ QEMU_CAPS_MSHV, /* -accel mshv */ + QEMU_CAPS_QUERY_BLOCK_FLAT, /* 'query-block' command supports 'flat' */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; -- 2.53.0
From: Peter Krempa <pkrempa@redhat.com> We don't actually look at any of the information in 'backing-image' field so we can ask qemu not to send it to us. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_monitor.c | 1 + src/qemu/qemu_monitor_json.c | 12 ++++++++++-- src/qemu/qemu_monitor_priv.h | 3 +++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 1434da7f70..ffd8a281b9 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -585,6 +585,7 @@ qemuMonitorOpenInternal(virDomainObj *vm, if (priv) { mon->blockjobMaskProtocol = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKJOB_BACKING_MASK_PROTOCOL); + mon->queryBlockFlat = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_QUERY_BLOCK_FLAT); } if (virSetCloseExec(mon->fd) < 0) { diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 971e8dd63f..6eff95f44a 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2243,7 +2243,9 @@ qemuMonitorJSONQueryNamedBlockNodes(qemuMonitor *mon) * @mon: Monitor pointer * * This helper will attempt to make a "query-block" call and check for - * errors before returning with the reply. + * errors before returning with the reply. If qemu supports 'flat' mode + * (which ommits 'backing-image' field in the reply objects) we will enable + * it as no callers need that information. * * Returns: NULL on error, reply on success */ @@ -2252,8 +2254,14 @@ qemuMonitorJSONQueryBlock(qemuMonitor *mon) { g_autoptr(virJSONValue) cmd = NULL; g_autoptr(virJSONValue) reply = NULL; + virTristateBool flat = VIR_TRISTATE_BOOL_ABSENT; + + if (mon->queryBlockFlat) + flat = VIR_TRISTATE_BOOL_YES; - if (!(cmd = qemuMonitorJSONMakeCommand("query-block", NULL))) + if (!(cmd = qemuMonitorJSONMakeCommand("query-block", + "T:flat", flat, + NULL))) return NULL; if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0 || diff --git a/src/qemu/qemu_monitor_priv.h b/src/qemu/qemu_monitor_priv.h index 198105007e..ee644123ca 100644 --- a/src/qemu/qemu_monitor_priv.h +++ b/src/qemu/qemu_monitor_priv.h @@ -90,6 +90,9 @@ struct _qemuMonitor { /* use the backing-mask-protocol flag of block-commit/stream */ bool blockjobMaskProtocol; + + /* 'query-block' supports flat mode */ + bool queryBlockFlat; }; -- 2.53.0
participants (2)
-
Ján Tomko -
Peter Krempa