* [PATCH 00/40] Make HMP optional (and later standalone)
@ 2026-05-20 21:49 Marc-André Lureau
2026-05-20 21:49 ` [PATCH 01/40] vl: fix -monitor none prefix matching Marc-André Lureau
` (40 more replies)
0 siblings, 41 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Hi,
This series makes HMP compile-time optional via --disable-hmp. The
resulting binary speaks only QMP - reducing the attack surface, binary
size and enforcing a separation between machine-readable interface and
interactive debugging console.
QMP offers almost all the functionality HMP could provide, so a separate
standalone "HMP-like" console could be implemented on top of it. The
rough list of missing commands (+complexity estimation) after this
series:
Debugging / introspection:
- info registers (medium) - plus $reg expression handling
- x/xp read memory (medium)
- gpa2hpa/gpa2hva/gva2gpa address translation (medium)
- info lapic (high) - deep x86 APIC state, lots of registers
- info mem (high) - virtual memory mappings, different per arch
- info tlb (high) - virt-to-phys mappings, also per arch
- info mtree (high) - memory region tree, multiple view modes
- info skeys (medium) - s390x storage keys
- info cmma (medium) - s390x CMMA values
- info qdm (easy) - could probably be folded into QOM introspection
- info qtree (medium) - same, maybe QOM introspection is enough
- info snapshots (medium)
- info usbhost (medium)
- info via (medium) -- VIA south bridge state
Simple actions / settings:
- gdbserver (trivial)
- boot_set (easy)
- mce (easy) - x86 MCE injection
- sum (easy) - memory checksum
- sync-profile (easy) - enable/disable/reset
- info sync-profile (medium)
- one-insn-per-tb (easy) - could be a QOM property on the accelerator
- pcie_aer_inject_error (easy)
- migration_mode (medium?)
- i/o ioport read/write (easy)
- hostfwd-add/hostfwd-remove (medium) - slirp port forwarding
- log/logfile (medium)
- trace-file (medium)
Also, to let clients do disassembly on their side, it'd be useful to
have something like "query-disassemble-info" that gives the client what
architecture and endianness is used etc.
In the meantime, being able to build without HMP is valuable and helps
identifying the missing pieces. The series does so by steps:
- preparatory cleanups and bug fixes
- add commands without QMP equivalent and needed for tests
- convert most iotests and qtests from HMP to QMP
- guard HMP-only code paths
- make HMP source files conditional in the build system
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
Marc-André Lureau (40):
vl: fix -monitor none prefix matching
hmp: remove 'vcpu' argument from trace-event help
hmp: fix snapshot_blkdev argument type
target/i386: decouple cpu_x86_inject_mce() from Monitor
system: move gpa2hva() to system memory unit
s390x: prevent crash if given invalid CPU#
system: decouple qmp_inject_nmi() from Monitor
hmp: correct the nmi documentation
monitor: move HMP-only fields from Monitor to MonitorHMP
tests/functional: use query-version QMP command instead of HMP
net/qapi: add x-query-usernet
tests: use x-query-usernet
RFC: qtest: add -qtest-no-ts option
qemu-io: propagate errors through Error API instead of printf
block: add x-qemu-io QMP command
tests/qemu-iotests/N: use x-qemu-io QMP command
tests/qemu-iotests/181, 192, 249: convert to QMP
tests/qemu-iotests/186: convert from HMP to QMP
tests/qemu-iotests/copy-before-write: convert to QMP
tests/qemu-iotests: skip some 172 & 267 that require HMP
RFC: qtest: add qemu-io command to the qtest protocol
RFC: qtest/ide-test: convert to use qtest qemu-io command
tests/qtest/numa-test: replace HMP "info numa" with QMP query-cpus-fast
tests/qtest/pnv: drop unnecessary -serial mon:stdio
net: add x-query-network QMP command
tests/qtest/netdev-socket: replace HMP with x-query-network QMP
tests/qtest/cdrom-test: replace HMP "info block" with QMP query-block
tests/qtest/qmp-test: don't depend on human-monitor-command
build-sys: add 'hmp' option
tests/qtest/device-introspect-test: fix test without HMP
tests/qtest/drive_del-test: guard HMP-dependent tests with CONFIG_HMP
qapi: make HMP-specific schema entries conditional on CONFIG_HMP
monitor: guard HMP-specific code with CONFIG_HMP
util: guard monitor_vprintf callers with CONFIG_HMP
system: guard HMP initialization paths with CONFIG_HMP
hw: guard BusClass::print_dev with CONFIG_HMP
target: guard MonitorDef tables with CONFIG_HMP
Guard HMP command implementations with CONFIG_HMP
build-sys: make HMP source files conditional on have_hmp
gitlab-ci: add --disable-hmp to build-without-defaults
meson.build | 6 +-
qapi/block.json | 34 ++
qapi/control.json | 4 +-
qapi/machine.json | 5 +-
qapi/misc.json | 3 +-
qapi/net.json | 166 ++++++++++
qapi/qom.json | 5 +-
include/hw/core/qdev.h | 2 +
include/hw/core/sysemu-cpu-ops.h | 2 +
include/monitor/hmp.h | 2 +
include/monitor/monitor.h | 11 +-
include/net/net.h | 3 +-
include/qemu-io.h | 4 +-
include/system/memory.h | 2 +
include/system/qtest.h | 3 +-
monitor/monitor-internal.h | 4 +-
net/hub.h | 4 +-
target/i386/cpu.h | 4 +-
tests/qtest/libqtest.h | 11 +
accel/accel-system.c | 2 +
accel/tcg/monitor.c | 2 +
block/monitor/block-hmp-cmds.c | 60 +---
block/monitor/qmp-cmds.c | 79 +++++
chardev/char.c | 7 +
gdbstub/system.c | 8 +
hw/char/virtio-serial-bus.c | 6 +
hw/core/sysbus.c | 6 +
hw/i386/kvm/xen-stubs.c | 2 +
hw/i386/kvm/xen_evtchn.c | 3 +-
hw/i386/sgx.c | 2 +
hw/misc/auxbus.c | 16 +-
hw/misc/mos6522-stub.c | 2 +
hw/misc/mos6522.c | 2 +
hw/pci/pci-hmp-cmds.c | 2 +
hw/pci/pci-stub.c | 2 +
hw/pci/pci.c | 2 +
hw/s390x/s390-skeys.c | 2 +
hw/s390x/s390-stattrib.c | 4 +
hw/s390x/s390-virtio-ccw.c | 5 +
hw/uefi/ovmf-log.c | 2 +
hw/usb/bus.c | 6 +
hw/usb/host-libusb.c | 6 +
hw/xen/xen-bus.c | 4 +
migration/dirtyrate.c | 2 +
monitor/hmp-cmds.c | 48 +--
monitor/hmp.c | 5 +-
monitor/monitor.c | 47 ++-
monitor/qmp-cmds.c | 2 +
net/hub.c | 29 +-
net/net-hmp-cmds.c | 59 +++-
net/net.c | 70 +++-
net/slirp.c | 41 ++-
qemu-io-cmds.c | 426 +++++++++++++------------
qemu-io.c | 17 +-
replay/replay-debugging.c | 8 +
replay/stubs-system.c | 6 +
stubs/monitor-core.c | 2 +
stubs/monitor-internal.c | 2 +
system/cpus.c | 7 +-
system/dirtylimit.c | 6 +
system/physmem.c | 31 ++
system/qdev-monitor.c | 4 +
system/qtest.c | 75 ++++-
system/vl.c | 13 +-
target/i386/cpu-apic.c | 2 +
target/i386/cpu.c | 4 +
target/i386/helper.c | 49 +--
target/i386/kvm/kvm.c | 4 +-
target/i386/monitor.c | 9 +-
target/i386/sev.c | 2 +
target/m68k/cpu.c | 4 +
target/m68k/monitor.c | 2 +
target/ppc/monitor.c | 2 +
target/riscv/monitor.c | 3 +
target/sh4/monitor.c | 2 +
target/sparc/cpu.c | 5 +-
target/sparc/monitor.c | 2 +
target/xtensa/monitor.c | 2 +
tests/qtest/cdrom-test.c | 29 +-
tests/qtest/device-introspect-test.c | 111 +++++--
tests/qtest/drive_del-test.c | 14 +
tests/qtest/ide-test.c | 4 +-
tests/qtest/libqtest.c | 14 +
tests/qtest/netdev-socket.c | 143 +++++----
tests/qtest/numa-test.c | 63 +++-
tests/qtest/pnv-host-i2c-test.c | 2 +-
tests/qtest/pnv-xive2-test.c | 2 +-
tests/qtest/qmp-test.c | 9 +-
tests/unit/test-util-sockets.c | 4 +-
tools/qemu-vnc/stubs.c | 2 +
util/error-report.c | 8 +-
util/qemu-print.c | 6 +
.gitlab-ci.d/buildtest.yml | 1 +
audio/meson.build | 4 +-
backends/meson.build | 5 +-
block/monitor/meson.build | 5 +-
chardev/meson.build | 5 +-
disas/meson.build | 4 +-
dump/meson.build | 5 +-
hmp-commands-info.hx | 6 +-
hmp-commands.hx | 14 +-
hw/core/meson.build | 5 +-
hw/i386/meson.build | 4 +-
hw/net/meson.build | 4 +-
hw/pci/meson.build | 4 +-
hw/virtio/meson.build | 4 +-
meson_options.txt | 2 +
migration/meson.build | 4 +-
monitor/meson.build | 9 +-
net/meson.build | 4 +-
python/qemu/utils/__init__.py | 5 +-
qemu-options.hx | 7 +-
qom/meson.build | 4 +-
scripts/meson-buildoptions.sh | 3 +
stats/meson.build | 5 +-
stubs/meson.build | 12 +-
system/meson.build | 9 +-
tests/functional/generic/test_version.py | 10 +-
tests/functional/qemu_test/utils.py | 8 +-
tests/qemu-iotests/004.out | 20 +-
tests/qemu-iotests/021.out | 60 ++--
tests/qemu-iotests/060 | 8 +-
tests/qemu-iotests/060.out | 44 ++-
tests/qemu-iotests/071 | 30 +-
tests/qemu-iotests/071.out | 14 +-
tests/qemu-iotests/072.out | 2 +-
tests/qemu-iotests/080.out | 4 +-
tests/qemu-iotests/089.out | 4 +-
tests/qemu-iotests/114.out | 2 +-
tests/qemu-iotests/117 | 5 +-
tests/qemu-iotests/117.out | 7 +-
tests/qemu-iotests/120 | 4 +-
tests/qemu-iotests/120.out | 2 +-
tests/qemu-iotests/134.out | 2 +-
tests/qemu-iotests/137.out | 2 +-
tests/qemu-iotests/156 | 36 +--
tests/qemu-iotests/156.out | 48 +--
tests/qemu-iotests/161 | 18 +-
tests/qemu-iotests/161.out | 24 +-
tests/qemu-iotests/171 | 2 +-
tests/qemu-iotests/171.out | 68 ++--
tests/qemu-iotests/172 | 5 +
tests/qemu-iotests/181 | 99 ++++--
tests/qemu-iotests/181.out | 36 ++-
tests/qemu-iotests/186 | 20 +-
tests/qemu-iotests/186.out | 440 ++++++--------------------
tests/qemu-iotests/192 | 22 +-
tests/qemu-iotests/192.out | 17 +-
tests/qemu-iotests/214.out | 2 +-
tests/qemu-iotests/220.out | 2 +-
tests/qemu-iotests/244.out | 12 +-
tests/qemu-iotests/249 | 18 +-
tests/qemu-iotests/249.out | 18 +-
tests/qemu-iotests/267 | 4 +
tests/qemu-iotests/271.out | 14 +-
tests/qemu-iotests/283 | 4 +-
tests/qemu-iotests/283.out | 4 +-
tests/qemu-iotests/common.rc | 7 +
tests/qemu-iotests/iotests.py | 4 +-
tests/qemu-iotests/tests/copy-before-write | 98 +++---
tests/qemu-iotests/tests/image-fleecing | 4 +-
tests/qemu-iotests/tests/image-fleecing.out | 52 +--
tests/qemu-iotests/tests/migrate-bitmaps-test | 4 +-
tests/qtest/meson.build | 8 +-
tests/vm/basevm.py | 13 +-
trace/meson.build | 5 +-
ui/meson.build | 4 +-
167 files changed, 2092 insertions(+), 1292 deletions(-)
---
base-commit: e89049b3ba5f1f0468bc0d294173345597514a1b
change-id: 20260521-qemu-no-hmp-ead3f0bf79c0
Best regards,
--
Marc-André Lureau <marcandre.lureau@redhat.com>
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 01/40] vl: fix -monitor none prefix matching
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 02/40] hmp: remove 'vcpu' argument from trace-event help Marc-André Lureau
` (39 subsequent siblings)
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Use g_strcmp0() for exact match instead of strncmp() which would
incorrectly treat any string starting with "none" as disabling
the monitor.
Fixes: 70e098af88f ("monitor: allow to disable the default monitor")
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
system/vl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/system/vl.c b/system/vl.c
index e690aa3ed8c..f4d55f0addd 100644
--- a/system/vl.c
+++ b/system/vl.c
@@ -3216,7 +3216,7 @@ void qemu_init(int argc, char **argv)
}
case QEMU_OPTION_monitor:
default_monitor = 0;
- if (strncmp(optarg, "none", 4)) {
+ if (g_strcmp0(optarg, "none")) {
monitor_parse(optarg, "readline", false);
}
break;
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 02/40] hmp: remove 'vcpu' argument from trace-event help
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
2026-05-20 21:49 ` [PATCH 01/40] vl: fix -monitor none prefix matching Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-21 5:50 ` Philippe Mathieu-Daudé
2026-05-20 21:49 ` [PATCH 03/40] hmp: fix snapshot_blkdev argument type Marc-André Lureau
` (38 subsequent siblings)
40 siblings, 1 reply; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Fixes: 89aafcf2a793 ("trace: remove code that depends on setting vcpu")
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
hmp-commands-info.hx | 6 +++---
hmp-commands.hx | 7 +++----
2 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
index 82134eb6c21..2695ff04ffc 100644
--- a/hmp-commands-info.hx
+++ b/hmp-commands-info.hx
@@ -587,10 +587,10 @@ ERST
{
.name = "trace-events",
- .args_type = "name:s?,vcpu:i?",
- .params = "[name] [vcpu]",
+ .args_type = "name:s?",
+ .params = "[name]",
.help = "show available trace-events & their state "
- "(name: event name pattern; vcpu: vCPU to query, default is any)",
+ "(name: event name pattern)",
.cmd = hmp_info_trace_events,
.command_completion = info_trace_events_completion,
},
diff --git a/hmp-commands.hx b/hmp-commands.hx
index c3a1a95c5fb..750a2f42a80 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -299,10 +299,9 @@ ERST
{
.name = "trace-event",
- .args_type = "name:s,option:b,vcpu:i?",
- .params = "name on|off [vcpu]",
- .help = "changes status of a specific trace event "
- "(vcpu: vCPU to set, default is all)",
+ .args_type = "name:s,option:b",
+ .params = "name on|off",
+ .help = "changes status of a specific trace event",
.cmd = hmp_trace_event,
.command_completion = trace_event_completion,
},
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 03/40] hmp: fix snapshot_blkdev argument type
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
2026-05-20 21:49 ` [PATCH 01/40] vl: fix -monitor none prefix matching Marc-André Lureau
2026-05-20 21:49 ` [PATCH 02/40] hmp: remove 'vcpu' argument from trace-event help Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 04/40] target/i386: decouple cpu_x86_inject_mce() from Monitor Marc-André Lureau
` (37 subsequent siblings)
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
The `snapshot-file` argument for `snapshot_blkdev` is mandatory. Correct
the `args_type` definition to reflect this.
Fixes: 6106e2492fe ("qapi: Convert blockdev_snapshot_sync")
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
hmp-commands.hx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 750a2f42a80..705c8662f4b 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1168,7 +1168,7 @@ ERST
{
.name = "snapshot_blkdev",
- .args_type = "reuse:-n,device:B,snapshot-file:s?,format:s?",
+ .args_type = "reuse:-n,device:B,snapshot-file:s,format:s?",
.params = "[-n] device [new-image-file] [format]",
.help = "initiates a live snapshot\n\t\t\t"
"of device. If a new image file is specified, the\n\t\t\t"
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 04/40] target/i386: decouple cpu_x86_inject_mce() from Monitor
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (2 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 03/40] hmp: fix snapshot_blkdev argument type Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-21 5:49 ` Philippe Mathieu-Daudé
2026-05-20 21:49 ` [PATCH 05/40] system: move gpa2hva() to system memory unit Marc-André Lureau
` (36 subsequent siblings)
40 siblings, 1 reply; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Replace monitor_printf() error reporting with the standard **errp
pattern. Drop the Monitor *mon parameter and return bool to indicate
success, improving the function usage from non-HMP contexts. Update the
KVM MCE injection path and hmp_mce() accordingly.
Notes:
- we may want to print the error in KVM path too
- multiple error prints are now accumulated with error hints
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
target/i386/cpu.h | 4 ++--
target/i386/helper.c | 49 ++++++++++++++++++++++++++++---------------------
target/i386/kvm/kvm.c | 4 ++--
target/i386/monitor.c | 6 ++++--
4 files changed, 36 insertions(+), 27 deletions(-)
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index bdd4fff89d6..da9f51b85b7 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -2842,9 +2842,9 @@ void do_cpu_init(X86CPU *cpu);
#define MCE_INJECT_BROADCAST 1
#define MCE_INJECT_UNCOND_AO 2
-void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank,
+bool cpu_x86_inject_mce(X86CPU *cpu, int bank,
uint64_t status, uint64_t mcg_status, uint64_t addr,
- uint64_t misc, int flags);
+ uint64_t misc, int flags, Error **errp);
uint32_t cpu_cc_compute_all(CPUX86State *env1);
diff --git a/target/i386/helper.c b/target/i386/helper.c
index 8cc73f619a9..03265c80b0a 100644
--- a/target/i386/helper.c
+++ b/target/i386/helper.c
@@ -18,6 +18,7 @@
*/
#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "qapi/qapi-events-run-state.h"
#include "cpu.h"
#include "exec/cputlb.h"
@@ -27,7 +28,6 @@
#ifndef CONFIG_USER_ONLY
#include "system/hw_accel.h"
#include "system/memory.h"
-#include "monitor/monitor.h"
#include "kvm/kvm_i386.h"
#endif
#include "qemu/log.h"
@@ -377,7 +377,7 @@ out:
}
typedef struct MCEInjectionParams {
- Monitor *mon;
+ GString *err;
int bank;
uint64_t status;
uint64_t mcg_status;
@@ -424,9 +424,9 @@ static void do_inject_x86_mce(CPUState *cs, run_on_cpu_data data)
* reporting is disabled
*/
if ((cenv->mcg_cap & MCG_CTL_P) && cenv->mcg_ctl != ~(uint64_t)0) {
- monitor_printf(params->mon,
- "CPU %d: Uncorrected error reporting disabled\n",
- cs->cpu_index);
+ g_string_append_printf(params->err,
+ "CPU %d: Uncorrected error reporting disabled\n",
+ cs->cpu_index);
return;
}
@@ -435,10 +435,9 @@ static void do_inject_x86_mce(CPUState *cs, run_on_cpu_data data)
* reporting is disabled for the bank
*/
if (banks[0] != ~(uint64_t)0) {
- monitor_printf(params->mon,
- "CPU %d: Uncorrected error reporting disabled for"
- " bank %d\n",
- cs->cpu_index, params->bank);
+ g_string_append_printf(params->err,
+ "CPU %d: Uncorrected error reporting disabled for bank %d\n",
+ cs->cpu_index, params->bank);
return;
}
@@ -455,7 +454,7 @@ static void do_inject_x86_mce(CPUState *cs, run_on_cpu_data data)
if (need_reset) {
emit_guest_memory_failure(MEMORY_FAILURE_ACTION_RESET, ar,
recursive);
- monitor_printf(params->mon, "%s", msg);
+ g_string_append_printf(params->err, "%s\n", msg);
qemu_log_mask(CPU_LOG_RESET, "%s\n", msg);
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
return;
@@ -484,14 +483,16 @@ static void do_inject_x86_mce(CPUState *cs, run_on_cpu_data data)
emit_guest_memory_failure(MEMORY_FAILURE_ACTION_INJECT, ar, recursive);
}
-void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank,
+bool cpu_x86_inject_mce(X86CPU *cpu, int bank,
uint64_t status, uint64_t mcg_status, uint64_t addr,
- uint64_t misc, int flags)
+ uint64_t misc, int flags, Error **errp)
{
+ ERRP_GUARD();
CPUState *cs = CPU(cpu);
CPUX86State *cenv = &cpu->env;
+ g_autoptr(GString) err = g_string_new(NULL);
MCEInjectionParams params = {
- .mon = mon,
+ .err = err,
.bank = bank,
.status = status,
.mcg_status = mcg_status,
@@ -502,21 +503,21 @@ void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank,
unsigned bank_num = cenv->mcg_cap & 0xff;
if (!cenv->mcg_cap) {
- monitor_printf(mon, "MCE injection not supported\n");
- return;
+ error_setg(errp, "MCE injection not supported");
+ return false;
}
if (bank >= bank_num) {
- monitor_printf(mon, "Invalid MCE bank number\n");
- return;
+ error_setg(errp, "Invalid MCE bank number");
+ return false;
}
if (!(status & MCI_STATUS_VAL)) {
- monitor_printf(mon, "Invalid MCE status code\n");
- return;
+ error_setg(errp, "Invalid MCE status code");
+ return false;
}
if ((flags & MCE_INJECT_BROADCAST)
&& !cpu_x86_support_mca_broadcast(cenv)) {
- monitor_printf(mon, "Guest CPU does not support MCA broadcast\n");
- return;
+ error_setg(errp, "Guest CPU does not support MCA broadcast");
+ return false;
}
run_on_cpu(cs, do_inject_x86_mce, RUN_ON_CPU_HOST_PTR(¶ms));
@@ -535,6 +536,12 @@ void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank,
run_on_cpu(other_cs, do_inject_x86_mce, RUN_ON_CPU_HOST_PTR(¶ms));
}
}
+ if (params.err->len) {
+ error_setg(errp, "Failed to inject MCE");
+ error_append_hint(errp, "%s", params.err->str);
+ return false;
+ }
+ return true;
}
static inline target_ulong get_memio_eip(CPUX86State *env)
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 9e352882c8c..d01519ef2f3 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -747,8 +747,8 @@ static void kvm_mce_inject(X86CPU *cpu, hwaddr paddr, int code)
flags = 0;
}
- cpu_x86_inject_mce(NULL, cpu, 9, status, mcg_status, paddr,
- (MCM_ADDR_PHYS << 6) | 0xc, flags);
+ cpu_x86_inject_mce(cpu, 9, status, mcg_status, paddr,
+ (MCM_ADDR_PHYS << 6) | 0xc, flags, NULL);
}
static void emit_hypervisor_memory_failure(MemoryFailureAction action, bool ar)
diff --git a/target/i386/monitor.c b/target/i386/monitor.c
index a536712c755..785a13dd710 100644
--- a/target/i386/monitor.c
+++ b/target/i386/monitor.c
@@ -580,6 +580,7 @@ void hmp_mce(Monitor *mon, const QDict *qdict)
uint64_t addr = qdict_get_int(qdict, "addr");
uint64_t misc = qdict_get_int(qdict, "misc");
int flags = MCE_INJECT_UNCOND_AO;
+ Error *err = NULL;
if (qdict_get_try_bool(qdict, "broadcast", false)) {
flags |= MCE_INJECT_BROADCAST;
@@ -587,7 +588,8 @@ void hmp_mce(Monitor *mon, const QDict *qdict)
cs = qemu_get_cpu(cpu_index);
if (cs != NULL) {
cpu = X86_CPU(cs);
- cpu_x86_inject_mce(mon, cpu, bank, status, mcg_status, addr, misc,
- flags);
+ cpu_x86_inject_mce(cpu, bank, status, mcg_status, addr, misc,
+ flags, &err);
+ hmp_handle_error(mon, err);
}
}
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 05/40] system: move gpa2hva() to system memory unit
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (3 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 04/40] target/i386: decouple cpu_x86_inject_mce() from Monitor Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-21 5:50 ` Philippe Mathieu-Daudé
2026-05-20 21:49 ` [PATCH 06/40] s390x: prevent crash if given invalid CPU# Marc-André Lureau
` (35 subsequent siblings)
40 siblings, 1 reply; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
The function is now used by SEV code path. Move it to physmem.c rather
than hmp-cmds.c.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
include/monitor/monitor.h | 2 --
include/system/memory.h | 2 ++
monitor/hmp-cmds.c | 31 -------------------------------
system/physmem.c | 31 +++++++++++++++++++++++++++++++
4 files changed, 33 insertions(+), 33 deletions(-)
diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
index 55649a86641..17182e626a7 100644
--- a/include/monitor/monitor.h
+++ b/include/monitor/monitor.h
@@ -42,8 +42,6 @@ int monitor_get_cpu_index(Monitor *mon);
int monitor_puts_locked(Monitor *mon, const char *str);
void monitor_flush_locked(Monitor *mon);
-void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, uint64_t size, Error **errp);
-
void monitor_read_command(MonitorHMP *mon, int show_prompt);
int monitor_read_password(MonitorHMP *mon, ReadLineFunc *readline_func,
void *opaque);
diff --git a/include/system/memory.h b/include/system/memory.h
index 1417132f6d9..e2724e38532 100644
--- a/include/system/memory.h
+++ b/include/system/memory.h
@@ -3063,4 +3063,6 @@ bool ram_block_discard_is_required(void);
void ram_block_add_cpr_blocker(RAMBlock *rb, Error **errp);
void ram_block_del_cpr_blocker(RAMBlock *rb);
+void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, uint64_t size, Error **errp);
+
#endif
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
index 443b8c785dc..521ab8a641c 100644
--- a/monitor/hmp-cmds.c
+++ b/monitor/hmp-cmds.c
@@ -709,37 +709,6 @@ void hmp_physical_memory_dump(Monitor *mon, const QDict *qdict)
memory_dump(mon, count, format, size, addr, true);
}
-void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, uint64_t size, Error **errp)
-{
- Int128 gpa_region_size;
- MemoryRegionSection mrs = memory_region_find(get_system_memory(),
- addr, size);
-
- if (!mrs.mr) {
- error_setg(errp,
- "No memory is mapped at address 0x%" HWADDR_PRIx, addr);
- return NULL;
- }
-
- if (!memory_region_is_ram(mrs.mr) && !memory_region_is_romd(mrs.mr)) {
- error_setg(errp,
- "Memory at address 0x%" HWADDR_PRIx " is not RAM", addr);
- memory_region_unref(mrs.mr);
- return NULL;
- }
-
- gpa_region_size = int128_make64(size);
- if (int128_lt(mrs.size, gpa_region_size)) {
- error_setg(errp, "Size of memory region at 0x%" HWADDR_PRIx
- " exceeded.", addr);
- memory_region_unref(mrs.mr);
- return NULL;
- }
-
- *p_mr = mrs.mr;
- return qemu_map_ram_ptr(mrs.mr->ram_block, mrs.offset_within_region);
-}
-
void hmp_gpa2hva(Monitor *mon, const QDict *qdict)
{
hwaddr addr = qdict_get_int(qdict, "addr");
diff --git a/system/physmem.c b/system/physmem.c
index 7bcbf875736..90bf857c9df 100644
--- a/system/physmem.c
+++ b/system/physmem.c
@@ -4477,3 +4477,34 @@ void ram_block_del_cpr_blocker(RAMBlock *rb)
{
migrate_del_blocker(&rb->cpr_blocker);
}
+
+void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, uint64_t size, Error **errp)
+{
+ Int128 gpa_region_size;
+ MemoryRegionSection mrs = memory_region_find(get_system_memory(),
+ addr, size);
+
+ if (!mrs.mr) {
+ error_setg(errp,
+ "No memory is mapped at address 0x%" HWADDR_PRIx, addr);
+ return NULL;
+ }
+
+ if (!memory_region_is_ram(mrs.mr) && !memory_region_is_romd(mrs.mr)) {
+ error_setg(errp,
+ "Memory at address 0x%" HWADDR_PRIx " is not RAM", addr);
+ memory_region_unref(mrs.mr);
+ return NULL;
+ }
+
+ gpa_region_size = int128_make64(size);
+ if (int128_lt(mrs.size, gpa_region_size)) {
+ error_setg(errp, "Size of memory region at 0x%" HWADDR_PRIx
+ " exceeded.", addr);
+ memory_region_unref(mrs.mr);
+ return NULL;
+ }
+
+ *p_mr = mrs.mr;
+ return qemu_map_ram_ptr(mrs.mr->ram_block, mrs.offset_within_region);
+}
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 06/40] s390x: prevent crash if given invalid CPU#
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (4 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 05/40] system: move gpa2hva() to system memory unit Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-21 0:47 ` Eric Farman
2026-05-20 21:49 ` [PATCH 07/40] system: decouple qmp_inject_nmi() from Monitor Marc-André Lureau
` (34 subsequent siblings)
40 siblings, 1 reply; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
hw/s390x/s390-virtio-ccw.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 4d35f9b10bc..d27d82a378a 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -729,6 +729,11 @@ static void s390_nmi(NMIState *n, int cpu_index, Error **errp)
{
CPUState *cs = qemu_get_cpu(cpu_index);
+ if (!cs) {
+ error_setg(errp, "CPU %d does not exist", cpu_index);
+ return;
+ }
+
s390_cpu_restart(S390_CPU(cs));
}
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 07/40] system: decouple qmp_inject_nmi() from Monitor
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (5 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 06/40] s390x: prevent crash if given invalid CPU# Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 08/40] hmp: correct the nmi documentation Marc-André Lureau
` (33 subsequent siblings)
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Use first_cpu directly instead of going through monitor_get_cpu_index(),
as this is HMP-territory. QMP doesn't have a `cpu` command, we should
add arguments instead when needed.
Update the inject-nmi doc to accurately describe per-architecture NMI
delivery.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
qapi/machine.json | 5 +++--
system/cpus.c | 7 +++++--
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/qapi/machine.json b/qapi/machine.json
index 685e4e29b87..03461f5f723 100644
--- a/qapi/machine.json
+++ b/qapi/machine.json
@@ -432,8 +432,9 @@
##
# @inject-nmi:
#
-# Injects a Non-Maskable Interrupt into the default CPU (x86/s390) or
-# all CPUs (ppc64). The command fails when the guest doesn't support
+# Injects a Non-Maskable Interrupt into the virtual machine. The NMI
+# is delivered to all vCPUs (x86, hppa, ppc64) or to the first vCPU
+# (s390). The command fails when the guest doesn't support
# injecting.
#
# Since: 0.14
diff --git a/system/cpus.c b/system/cpus.c
index bded87feb1c..0089eef9b1c 100644
--- a/system/cpus.c
+++ b/system/cpus.c
@@ -913,6 +913,9 @@ exit:
void qmp_inject_nmi(Error **errp)
{
- nmi_monitor_handle(monitor_get_cpu_index(monitor_cur()), errp);
+ int cpu_index = UNASSIGNED_CPU_INDEX;
+ if (first_cpu) {
+ cpu_index = first_cpu->cpu_index;
+ }
+ nmi_monitor_handle(cpu_index, errp);
}
-
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 08/40] hmp: correct the nmi documentation
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (6 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 07/40] system: decouple qmp_inject_nmi() from Monitor Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 09/40] monitor: move HMP-only fields from Monitor to MonitorHMP Marc-André Lureau
` (32 subsequent siblings)
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
hmp-commands.hx | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 705c8662f4b..146fb05dc64 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -868,8 +868,9 @@ ERST
.cmd = hmp_nmi,
},
SRST
-``nmi`` *cpu*
- Inject an NMI on the default CPU (x86/s390) or all CPUs (ppc64).
+``nmi``
+ Inject an NMI on the associated monitor vCPU (``cpu`` command, on s390x) or
+ all vCPUs (on other architectures).
ERST
{
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 09/40] monitor: move HMP-only fields from Monitor to MonitorHMP
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (7 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 08/40] hmp: correct the nmi documentation Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-21 5:53 ` Philippe Mathieu-Daudé
2026-05-20 21:49 ` [PATCH 10/40] tests/functional: use query-version QMP command instead of HMP Marc-André Lureau
` (31 subsequent siblings)
40 siblings, 1 reply; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
mon_cpu_path and reset_seen are only used by HMP monitors; move them
from the base Monitor struct into MonitorHMP to properly encapsulate
HMP-specific state.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
monitor/monitor-internal.h | 4 ++--
monitor/hmp-cmds.c | 17 ++++++++++-------
monitor/hmp.c | 5 +++--
monitor/monitor.c | 16 +++++++++++-----
4 files changed, 26 insertions(+), 16 deletions(-)
diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h
index a5c4aba306e..e071ad3e2e8 100644
--- a/monitor/monitor-internal.h
+++ b/monitor/monitor-internal.h
@@ -108,7 +108,6 @@ struct Monitor {
bool skip_flush;
bool use_io_thread;
- char *mon_cpu_path;
QTAILQ_ENTRY(Monitor) entry;
/*
@@ -124,7 +123,6 @@ struct Monitor {
GString *outbuf;
guint out_watch;
int mux_out;
- int reset_seen;
};
struct MonitorHMP {
@@ -138,6 +136,8 @@ struct MonitorHMP {
* These members can be safely accessed without locks.
*/
ReadLineState *rs;
+ char *mon_cpu_path;
+ int reset_seen;
};
typedef struct {
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
index 521ab8a641c..e7a02b1fddb 100644
--- a/monitor/hmp-cmds.c
+++ b/monitor/hmp-cmds.c
@@ -496,31 +496,34 @@ void hmp_dumpdtb(Monitor *mon, const QDict *qdict)
/* Set the current CPU defined by the user. Callers must hold BQL. */
int monitor_set_cpu(Monitor *mon, int cpu_index)
{
+ assert(!monitor_is_qmp(mon));
+ MonitorHMP *hmp_mon = container_of(mon, MonitorHMP, common);
CPUState *cpu;
cpu = qemu_get_cpu(cpu_index);
if (cpu == NULL) {
return -1;
}
- g_free(mon->mon_cpu_path);
- mon->mon_cpu_path = object_get_canonical_path(OBJECT(cpu));
+ g_free(hmp_mon->mon_cpu_path);
+ hmp_mon->mon_cpu_path = object_get_canonical_path(OBJECT(cpu));
return 0;
}
/* Callers must hold BQL. */
static CPUState *mon_get_cpu_sync(Monitor *mon, bool synchronize)
{
+ MonitorHMP *hmp_mon = container_of(mon, MonitorHMP, common);
CPUState *cpu = NULL;
- if (mon->mon_cpu_path) {
- cpu = (CPUState *) object_resolve_path_type(mon->mon_cpu_path,
+ if (hmp_mon->mon_cpu_path) {
+ cpu = (CPUState *) object_resolve_path_type(hmp_mon->mon_cpu_path,
TYPE_CPU, NULL);
if (!cpu) {
- g_free(mon->mon_cpu_path);
- mon->mon_cpu_path = NULL;
+ g_free(hmp_mon->mon_cpu_path);
+ hmp_mon->mon_cpu_path = NULL;
}
}
- if (!mon->mon_cpu_path) {
+ if (!hmp_mon->mon_cpu_path) {
if (!first_cpu) {
return NULL;
}
diff --git a/monitor/hmp.c b/monitor/hmp.c
index cc4390486e1..de8804af51a 100644
--- a/monitor/hmp.c
+++ b/monitor/hmp.c
@@ -1453,6 +1453,7 @@ static void monitor_read(void *opaque, const uint8_t *buf, int size)
static void monitor_event(void *opaque, QEMUChrEvent event)
{
Monitor *mon = opaque;
+ MonitorHMP *hmp_mon = container_of(mon, MonitorHMP, common);
switch (event) {
case CHR_EVENT_MUX_IN:
@@ -1467,7 +1468,7 @@ static void monitor_event(void *opaque, QEMUChrEvent event)
case CHR_EVENT_MUX_OUT:
qemu_mutex_lock(&mon->mon_lock);
if (!mon->mux_out) {
- if (mon->reset_seen && !mon->suspend_cnt) {
+ if (hmp_mon->reset_seen && !mon->suspend_cnt) {
monitor_puts_locked(mon, "\n");
} else {
monitor_flush_locked(mon);
@@ -1482,7 +1483,7 @@ static void monitor_event(void *opaque, QEMUChrEvent event)
monitor_printf(mon, "QEMU %s monitor - type 'help' for more "
"information\n", QEMU_VERSION);
qemu_mutex_lock(&mon->mon_lock);
- mon->reset_seen = 1;
+ hmp_mon->reset_seen = 1;
if (!mon->mux_out) {
/* Suspend-resume forces the prompt to be printed. */
monitor_suspend(mon);
diff --git a/monitor/monitor.c b/monitor/monitor.c
index 00b93ed6124..2dec0e299af 100644
--- a/monitor/monitor.c
+++ b/monitor/monitor.c
@@ -541,12 +541,17 @@ static void monitor_accept_input(void *opaque)
Monitor *mon = opaque;
qemu_mutex_lock(&mon->mon_lock);
- if (!monitor_is_qmp(mon) && mon->reset_seen) {
+ if (!monitor_is_qmp(mon)) {
MonitorHMP *hmp_mon = container_of(mon, MonitorHMP, common);
assert(hmp_mon->rs);
- readline_restart(hmp_mon->rs);
+ bool reset_seen = hmp_mon->reset_seen;
+ if (reset_seen) {
+ readline_restart(hmp_mon->rs);
+ }
qemu_mutex_unlock(&mon->mon_lock);
- readline_show_prompt(hmp_mon->rs);
+ if (reset_seen) {
+ readline_show_prompt(hmp_mon->rs);
+ }
} else {
qemu_mutex_unlock(&mon->mon_lock);
}
@@ -622,12 +627,13 @@ void monitor_data_init(Monitor *mon, bool is_qmp, bool skip_flush,
void monitor_data_destroy(Monitor *mon)
{
- g_free(mon->mon_cpu_path);
qemu_chr_fe_deinit(&mon->chr, false);
if (monitor_is_qmp(mon)) {
monitor_data_destroy_qmp(container_of(mon, MonitorQMP, common));
} else {
- readline_free(container_of(mon, MonitorHMP, common)->rs);
+ MonitorHMP *hmp_mon = container_of(mon, MonitorHMP, common);
+ readline_free(hmp_mon->rs);
+ g_free(hmp_mon->mon_cpu_path);
}
g_string_free(mon->outbuf, true);
qemu_mutex_destroy(&mon->mon_lock);
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 10/40] tests/functional: use query-version QMP command instead of HMP
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (8 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 09/40] monitor: move HMP-only fields from Monitor to MonitorHMP Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-21 5:54 ` Philippe Mathieu-Daudé
2026-05-20 21:49 ` [PATCH 11/40] net/qapi: add x-query-usernet Marc-André Lureau
` (30 subsequent siblings)
40 siblings, 1 reply; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Replace the human-monitor-command based version test with the native
QMP query-version command, which returns structured version data.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
tests/functional/generic/test_version.py | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/tests/functional/generic/test_version.py b/tests/functional/generic/test_version.py
index 3ab3b67f7e3..7764424826e 100755
--- a/tests/functional/generic/test_version.py
+++ b/tests/functional/generic/test_version.py
@@ -16,13 +16,15 @@
class Version(QemuSystemTest):
- def test_qmp_human_info_version(self):
+ def test_qmp_query_version(self):
self.set_machine('none')
self.vm.add_args('-nodefaults')
self.vm.launch()
- res = self.vm.cmd('human-monitor-command',
- command_line='info version')
- self.assertRegex(res, r'^(\d+\.\d+\.\d)')
+ res = self.vm.cmd('query-version')
+ version = res['qemu']
+ self.assertIsInstance(version['major'], int)
+ self.assertIsInstance(version['minor'], int)
+ self.assertIsInstance(version['micro'], int)
if __name__ == '__main__':
QemuSystemTest.main()
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 11/40] net/qapi: add x-query-usernet
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (9 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 10/40] tests/functional: use query-version QMP command instead of HMP Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 12/40] tests: use x-query-usernet Marc-André Lureau
` (29 subsequent siblings)
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Add a QMP equivalent to hmp "info usernet", so we can disable HMP.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
qapi/net.json | 44 ++++++++++++++++++++++++++++++++++++++++++++
net/slirp.c | 34 ++++++++++++++++++++++++++++------
2 files changed, 72 insertions(+), 6 deletions(-)
diff --git a/qapi/net.json b/qapi/net.json
index 118bd349651..dd56215fd15 100644
--- a/qapi/net.json
+++ b/qapi/net.json
@@ -1191,3 +1191,47 @@
##
{ 'event': 'NETDEV_VHOST_USER_DISCONNECTED',
'data': { 'netdev-id': 'str' } }
+
+##
+# @UsernetInfo:
+#
+# Information about a user-mode network stack (slirp).
+#
+# @hub-id: The hub id, if available.
+#
+# @hub-name: The name of the hub.
+#
+# @info: Network information from slirp.
+#
+# Since: 11.1
+##
+{ 'struct': 'UsernetInfo',
+ 'data': {
+ '*hub-id': 'int',
+ 'hub-name': 'str',
+ 'info': 'str' },
+ 'if': 'CONFIG_SLIRP' }
+
+##
+# @x-query-usernet:
+#
+# Query user-mode network stack connection states.
+#
+# Features:
+#
+# @unstable: This command is meant for debugging.
+#
+# Returns: list of user-mode network stack information.
+#
+# Since: 11.1
+#
+# .. qmp-example::
+#
+# -> { "execute": "x-query-usernet" }
+# <- { "return": [ { "hub-id": 0, "hub-name": "vnet",
+# "info": "..." } ] }
+##
+{ 'command': 'x-query-usernet',
+ 'returns': ['UsernetInfo'],
+ 'if': 'CONFIG_SLIRP',
+ 'features': [ 'unstable' ] }
diff --git a/net/slirp.c b/net/slirp.c
index 04925f33187..d3ed5ec9cb8 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -43,6 +43,7 @@
#include "system/system.h"
#include "qemu/cutils.h"
#include "qapi/error.h"
+#include "qapi/qapi-commands-net.h"
#include "qobject/qdict.h"
#include "util.h"
#include "migration/register.h"
@@ -1199,18 +1200,39 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str, Error **errp)
return -1;
}
-void hmp_info_usernet(Monitor *mon, const QDict *qdict)
+UsernetInfoList *qmp_x_query_usernet(Error **errp)
{
+ UsernetInfoList *head = NULL, **tail = &head;
SlirpState *s;
QTAILQ_FOREACH(s, &slirp_stacks, entry) {
+ UsernetInfo *ui = g_new0(UsernetInfo, 1);
int id;
- bool got_hub_id = net_hub_id_for_client(&s->nc, &id) == 0;
- char *info = slirp_connection_info(s->slirp);
+
+ if (net_hub_id_for_client(&s->nc, &id) == 0) {
+ ui->has_hub_id = true;
+ ui->hub_id = id;
+ }
+ ui->hub_name = g_strdup(s->nc.name);
+ ui->info = slirp_connection_info(s->slirp);
+
+ QAPI_LIST_APPEND(tail, ui);
+ }
+
+ return head;
+}
+
+void hmp_info_usernet(Monitor *mon, const QDict *qdict)
+{
+ g_autoptr(UsernetInfoList) list = NULL;
+ UsernetInfoList *entry;
+
+ list = qmp_x_query_usernet(&error_abort);
+ for (entry = list; entry; entry = entry->next) {
+ UsernetInfo *ui = entry->value;
monitor_printf(mon, "Hub %d (%s):\n%s",
- got_hub_id ? id : -1,
- s->nc.name, info);
- g_free(info);
+ ui->has_hub_id ? (int)ui->hub_id : -1,
+ ui->hub_name, ui->info);
}
}
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 12/40] tests: use x-query-usernet
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (10 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 11/40] net/qapi: add x-query-usernet Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 13/40] RFC: qtest: add -qtest-no-ts option Marc-André Lureau
` (28 subsequent siblings)
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
python/qemu/utils/__init__.py | 5 +++--
tests/functional/qemu_test/utils.py | 8 ++++++--
tests/vm/basevm.py | 13 ++++++++-----
3 files changed, 17 insertions(+), 9 deletions(-)
diff --git a/python/qemu/utils/__init__.py b/python/qemu/utils/__init__.py
index be5daa83634..e32911d4c6d 100644
--- a/python/qemu/utils/__init__.py
+++ b/python/qemu/utils/__init__.py
@@ -46,10 +46,11 @@ def get_info_usernet_hostfwd_port(info_usernet_output: str) -> Optional[int]:
"""
Returns the port given to the hostfwd parameter via info usernet
- :param info_usernet_output: output generated by hmp command "info usernet"
+ :param info_usernet_output: output generated by "info usernet" or
+ the "info" field from x-query-usernet
:return: the port number allocated by the hostfwd option
"""
- for line in info_usernet_output.split('\r\n'):
+ for line in info_usernet_output.splitlines():
regex = r'TCP.HOST_FORWARD.*127\.0\.0\.1\s+(\d+)\s+10\.'
match = re.search(regex, line)
if match is not None:
diff --git a/tests/functional/qemu_test/utils.py b/tests/functional/qemu_test/utils.py
index 826c267785b..0992db49ab2 100644
--- a/tests/functional/qemu_test/utils.py
+++ b/tests/functional/qemu_test/utils.py
@@ -14,8 +14,12 @@
def get_usernet_hostfwd_port(vm):
- res = vm.cmd('human-monitor-command', command_line='info usernet')
- return get_info_usernet_hostfwd_port(res)
+ res = vm.cmd('x-query-usernet')
+ for entry in res:
+ port = get_info_usernet_hostfwd_port(entry['info'])
+ if port is not None:
+ return port
+ return None
def pow2ceil(x):
"""
diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py
index 9e879e966a3..198b04e8c37 100644
--- a/tests/vm/basevm.py
+++ b/tests/vm/basevm.py
@@ -312,12 +312,15 @@ def boot(self, img, extra_args=[]):
self._guest = guest
# Init console so we can start consuming the chars.
self.console_init()
- usernet_info = guest.cmd("human-monitor-command",
- command_line="info usernet")
- self.ssh_port = get_info_usernet_hostfwd_port(usernet_info)
+ res = guest.cmd("x-query-usernet")
+ for entry in res:
+ port = get_info_usernet_hostfwd_port(entry['info'])
+ if port is not None:
+ self.ssh_port = port
+ break
if not self.ssh_port:
- raise Exception("Cannot find ssh port from 'info usernet':\n%s" % \
- usernet_info)
+ raise Exception("Cannot find ssh port from"
+ " 'x-query-usernet': %s" % res)
def console_init(self, timeout = None):
if timeout == None:
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 13/40] RFC: qtest: add -qtest-no-ts option
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (11 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 12/40] tests: use x-query-usernet Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 14/40] qemu-io: propagate errors through Error API instead of printf Marc-André Lureau
` (27 subsequent siblings)
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Add an option to disable printing the timestamp in the reply.
This may help tests that want to compare the output between runs.
It's not use by this series after all, it could be excluded.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
qapi/qom.json | 5 ++-
include/system/qtest.h | 3 +-
system/qtest.c | 61 ++++++++++++++++++++++-----
system/vl.c | 7 ++-
qemu-options.hx | 1 +
tests/qemu-iotests/iotests.py | 4 +-
tests/qemu-iotests/tests/copy-before-write | 4 +-
tests/qemu-iotests/tests/migrate-bitmaps-test | 4 +-
8 files changed, 70 insertions(+), 19 deletions(-)
diff --git a/qapi/qom.json b/qapi/qom.json
index dd45ac1087c..c7b6c64d157 100644
--- a/qapi/qom.json
+++ b/qapi/qom.json
@@ -834,11 +834,14 @@
#
# @log: the path to a log file
#
+# @ts: if true, print timestamps in the log. Default true.
+#
# Since: 6.0
##
{ 'struct': 'QtestProperties',
'data': { 'chardev': 'str',
- '*log': 'str' } }
+ '*log': 'str',
+ '*ts': 'bool' } }
##
# @RemoteObjectProperties:
diff --git a/include/system/qtest.h b/include/system/qtest.h
index 7f6dc01d147..2fa06409a84 100644
--- a/include/system/qtest.h
+++ b/include/system/qtest.h
@@ -27,7 +27,8 @@ void G_GNUC_PRINTF(2, 3) qtest_sendf(CharFrontend *chr, const char *fmt, ...);
void qtest_set_command_cb(bool (*pc_cb)(CharFrontend *chr, gchar **words));
bool qtest_driver(void);
-void qtest_server_init(const char *qtest_chrdev, const char *qtest_log, Error **errp);
+void qtest_server_init(const char *qtest_chrdev, const char *qtest_log,
+ bool qtest_no_ts, Error **errp);
void qtest_server_set_send_handler(void (*send)(void *, const char *),
void *opaque);
diff --git a/system/qtest.c b/system/qtest.c
index a79d10d1361..1fb35ae36bc 100644
--- a/system/qtest.c
+++ b/system/qtest.c
@@ -42,6 +42,7 @@ struct QTest {
Object parent;
bool has_machine_link;
+ bool ts;
char *chr_name;
Chardev *chr;
CharFrontend qtest_chr;
@@ -57,6 +58,7 @@ static GString *inbuf;
static int irq_levels[MAX_IRQ];
static GTimer *timer;
static bool qtest_opened;
+static bool qtest_ts = true;
static void (*qtest_server_send)(void*, const char*);
static void *qtest_server_send_opaque;
@@ -270,13 +272,17 @@ static int hex2nib(char ch)
}
}
-static void qtest_log_timestamp(void)
+static void qtest_log_timestamp(const char c)
{
if (!qtest_log_fp || !qtest_opened) {
return;
}
- fprintf(qtest_log_fp, "[S +" FMT_timeval "] ", g_timer_elapsed(timer, NULL));
+ fprintf(qtest_log_fp, "[%c", c);
+ if (qtest_ts) {
+ fprintf(qtest_log_fp, " +" FMT_timeval, g_timer_elapsed(timer, NULL));
+ }
+ fprintf(qtest_log_fp, "]");
}
static void G_GNUC_PRINTF(1, 2) qtest_log_send(const char *fmt, ...)
@@ -287,8 +293,8 @@ static void G_GNUC_PRINTF(1, 2) qtest_log_send(const char *fmt, ...)
return;
}
- qtest_log_timestamp();
-
+ qtest_log_timestamp('S');
+ fprintf(qtest_log_fp, " ");
va_start(ap, fmt);
vfprintf(qtest_log_fp, fmt, ap);
va_end(ap);
@@ -306,7 +312,10 @@ static void qtest_server_char_be_send(void *opaque, const char *str)
static void qtest_send(CharFrontend *chr, const char *str)
{
- qtest_log_timestamp();
+ if (qtest_log_fp) {
+ qtest_log_timestamp('S');
+ fprintf(qtest_log_fp, " ");
+ }
qtest_server_send(qtest_server_send_opaque, str);
}
@@ -364,7 +373,7 @@ static void qtest_process_command(CharFrontend *chr, gchar **words)
if (qtest_log_fp) {
int i;
- fprintf(qtest_log_fp, "[R +" FMT_timeval "]", g_timer_elapsed(timer, NULL));
+ qtest_log_timestamp('R');
for (i = 0; words[i]; i++) {
fprintf(qtest_log_fp, " %s", words[i]);
}
@@ -812,7 +821,8 @@ static void qtest_event(void *opaque, QEMUChrEvent event)
timer = g_timer_new();
qtest_opened = true;
if (qtest_log_fp) {
- fprintf(qtest_log_fp, "[I " FMT_timeval "] OPENED\n", g_timer_elapsed(timer, NULL));
+ qtest_log_timestamp('I');
+ fprintf(qtest_log_fp, " OPENED\n");
}
break;
case CHR_EVENT_CLOSED:
@@ -820,10 +830,11 @@ static void qtest_event(void *opaque, QEMUChrEvent event)
/* Ignore CLOSED events if we have already closed the log */
break;
}
- qtest_opened = false;
if (qtest_log_fp) {
- fprintf(qtest_log_fp, "[I +" FMT_timeval "] CLOSED\n", g_timer_elapsed(timer, NULL));
+ qtest_log_timestamp('I');
+ fprintf(qtest_log_fp, " CLOSED\n");
}
+ qtest_opened = false;
g_clear_pointer(&timer, g_timer_destroy);
break;
default:
@@ -831,7 +842,8 @@ static void qtest_event(void *opaque, QEMUChrEvent event)
}
}
-void qtest_server_init(const char *qtest_chrdev, const char *qtest_log, Error **errp)
+void qtest_server_init(const char *qtest_chrdev, const char *qtest_log,
+ bool no_ts, Error **errp)
{
ERRP_GUARD();
Chardev *chr;
@@ -849,6 +861,9 @@ void qtest_server_init(const char *qtest_chrdev, const char *qtest_log, Error **
if (qtest_log) {
object_property_set_str(qobj, "log", qtest_log, &error_abort);
}
+ if (no_ts) {
+ object_property_set_bool(qobj, "ts", false, &error_abort);
+ }
object_property_add_child(qdev_get_machine(), "qtest", qobj);
user_creatable_complete(USER_CREATABLE(qobj), errp);
if (*errp) {
@@ -871,6 +886,8 @@ static bool qtest_server_start(QTest *q, Error **errp)
qtest_log_fp = stderr;
}
+ qtest_ts = q->ts;
+
if (!qemu_chr_fe_init(&q->qtest_chr, chr, errp)) {
return false;
}
@@ -974,6 +991,20 @@ static char *qtest_get_log(Object *obj, Error **errp)
return g_strdup(q->log);
}
+static bool qtest_get_ts(Object *obj, Error **errp)
+{
+ QTest *q = QTEST(obj);
+
+ return q->ts;
+}
+
+static void qtest_set_ts(Object *obj, bool value, Error **errp)
+{
+ QTest *q = QTEST(obj);
+
+ q->ts = value;
+}
+
static void qtest_set_chardev(Object *obj, const char *value, Error **errp)
{
QTest *q = QTEST(obj);
@@ -1018,6 +1049,8 @@ static void qtest_class_init(ObjectClass *oc, const void *data)
qtest_get_chardev, qtest_set_chardev);
object_class_property_add_str(oc, "log",
qtest_get_log, qtest_set_log);
+ object_class_property_add_bool(oc, "ts",
+ qtest_get_ts, qtest_set_ts);
}
static void qtest_finalize(Object *obj)
@@ -1029,10 +1062,18 @@ static void qtest_finalize(Object *obj)
object_unref(q->chr);
}
+static void qtest_init(Object *obj)
+{
+ QTest *q = QTEST(obj);
+
+ q->ts = true;
+}
+
static const TypeInfo qtest_info = {
.name = TYPE_QTEST,
.parent = TYPE_OBJECT,
.class_init = qtest_class_init,
+ .instance_init = qtest_init,
.instance_finalize = qtest_finalize,
.instance_size = sizeof(QTest),
.interfaces = (const InterfaceInfo[]) {
diff --git a/system/vl.c b/system/vl.c
index f4d55f0addd..4797700abd5 100644
--- a/system/vl.c
+++ b/system/vl.c
@@ -193,6 +193,7 @@ static const char *log_file;
static bool list_data_dirs;
static const char *qtest_chrdev;
static const char *qtest_log;
+static bool qtest_no_ts;
static int has_defaults = 1;
static int default_audio = 1;
@@ -2092,7 +2093,8 @@ static bool object_create_late(const char *type)
static void qemu_create_late_backends(void)
{
if (qtest_chrdev) {
- qtest_server_init(qtest_chrdev, qtest_log, &error_fatal);
+ qtest_server_init(qtest_chrdev, qtest_log, qtest_no_ts,
+ &error_fatal);
}
net_init_clients();
@@ -3596,6 +3598,9 @@ void qemu_init(int argc, char **argv)
case QEMU_OPTION_qtest_log:
qtest_log = optarg;
break;
+ case QEMU_OPTION_qtest_no_ts:
+ qtest_no_ts = true;
+ break;
case QEMU_OPTION_sandbox:
olist = qemu_find_opts("sandbox");
if (!olist) {
diff --git a/qemu-options.hx b/qemu-options.hx
index 96ae41f787b..4c1b32713e0 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -5584,6 +5584,7 @@ ERST
HXCOMM Internal use
DEF("qtest", HAS_ARG, QEMU_OPTION_qtest, "", QEMU_ARCH_ALL)
DEF("qtest-log", HAS_ARG, QEMU_OPTION_qtest_log, "", QEMU_ARCH_ALL)
+DEF("qtest-no-ts", 0, QEMU_OPTION_qtest_no_ts, "", QEMU_ARCH_ALL)
#if defined(CONFIG_POSIX) && !defined(EMSCRIPTEN)
DEF("run-with", HAS_ARG, QEMU_OPTION_run_with,
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 05274772ce4..5a4d843886d 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -712,8 +712,8 @@ def filter_nbd_exports(output: str) -> str:
return re.sub(r'((min|opt|max) block): [0-9]+', r'\1: XXX', output)
def filter_qtest(output: str) -> str:
- output = re.sub(r'^\[I \d+\.\d+\] OPENED\n', '', output)
- output = re.sub(r'\n?\[I \+\d+\.\d+\] CLOSED\n?$', '', output)
+ output = re.sub(r'^\[I \+?\d+\.\d+\] OPENED\n', '', output)
+ output = re.sub(r'\n?\[I \+?\d+\.\d+\] CLOSED\n?$', '', output)
return output
Msg = TypeVar('Msg', Dict[str, Any], List[Any], str)
diff --git a/tests/qemu-iotests/tests/copy-before-write b/tests/qemu-iotests/tests/copy-before-write
index 236cb8ac374..f86032b1167 100755
--- a/tests/qemu-iotests/tests/copy-before-write
+++ b/tests/qemu-iotests/tests/copy-before-write
@@ -273,8 +273,8 @@ read 1048576/1048576 bytes at offset 0
self.vm.shutdown()
log = self.vm.get_log()
- log = re.sub(r'^\[I \d+\.\d+\] OPENED\n', '', log)
- log = re.sub(r'\[I \+\d+\.\d+\] CLOSED\n?$', '', log)
+ log = re.sub(r'^\[I \+?\d+\.\d+\] OPENED\n', '', log)
+ log = re.sub(r'\[I \+?\d+\.\d+\] CLOSED\n?$', '', log)
log = iotests.filter_qemu_io(log)
return log
diff --git a/tests/qemu-iotests/tests/migrate-bitmaps-test b/tests/qemu-iotests/tests/migrate-bitmaps-test
index 8fb4099201d..eec110757a6 100755
--- a/tests/qemu-iotests/tests/migrate-bitmaps-test
+++ b/tests/qemu-iotests/tests/migrate-bitmaps-test
@@ -195,8 +195,8 @@ class TestDirtyBitmapMigration(iotests.QMPTestCase):
# catch 'Could not reopen qcow2 layer: Bitmap already exists'
# possible error
log = self.vm_b.get_log()
- log = re.sub(r'^\[I \d+\.\d+\] OPENED\n', '', log)
- log = re.sub(r'\[I \+\d+\.\d+\] CLOSED\n?$', '', log)
+ log = re.sub(r'^\[I \+?\d+\.\d+\] OPENED\n', '', log)
+ log = re.sub(r'\[I \+?\d+\.\d+\] CLOSED\n?$', '', log)
self.assertEqual(log, '')
# recreate vm_b, as we don't want -incoming option (this will lead
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 14/40] qemu-io: propagate errors through Error API instead of printf
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (12 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 13/40] RFC: qtest: add -qtest-no-ts option Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-21 6:02 ` Philippe Mathieu-Daudé
2026-05-20 21:49 ` [PATCH 15/40] block: add x-qemu-io QMP command Marc-André Lureau
` (26 subsequent siblings)
40 siblings, 1 reply; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Convert the qemu-io command infrastructure to use QEMU's Error API
(Error **errp) for error propagation instead of printing directly to
stdout/stderr via printf/fprintf.
The cfunc_t typedef, all ~35 command functions, the dispatcher chain
(command/init_check_command/qemuio_command), and helper functions
(parse_pattern, create_iovec, qemu_io_alloc_from_file) all gain an
Error **errp parameter. Async completion callbacks (aio_read_done,
aio_write_done, aio_discard_done) use error_report() since they have
no Error path back to the caller.
Update tests:
- error_report_err() prepends qemu-io: prefix
- copy-before-write: check the HMP return value, rather than stdio
- other tests: update to check JSON {"return": "Error: error text"}
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
include/qemu-io.h | 4 +-
block/monitor/block-hmp-cmds.c | 2 +-
qemu-io-cmds.c | 426 +++++++++++++++--------------
qemu-io.c | 17 +-
tests/qemu-iotests/004.out | 20 +-
tests/qemu-iotests/021.out | 60 ++--
tests/qemu-iotests/060.out | 44 ++-
tests/qemu-iotests/071.out | 10 +-
tests/qemu-iotests/072.out | 2 +-
tests/qemu-iotests/080.out | 4 +-
tests/qemu-iotests/089.out | 4 +-
tests/qemu-iotests/114.out | 2 +-
tests/qemu-iotests/134.out | 2 +-
tests/qemu-iotests/137.out | 2 +-
tests/qemu-iotests/171 | 2 +-
tests/qemu-iotests/171.out | 68 ++---
tests/qemu-iotests/214.out | 2 +-
tests/qemu-iotests/220.out | 2 +-
tests/qemu-iotests/244.out | 12 +-
tests/qemu-iotests/249.out | 6 +-
tests/qemu-iotests/271.out | 14 +-
tests/qemu-iotests/tests/copy-before-write | 66 +++--
22 files changed, 404 insertions(+), 367 deletions(-)
diff --git a/include/qemu-io.h b/include/qemu-io.h
index 3af513004a6..240764bb35c 100644
--- a/include/qemu-io.h
+++ b/include/qemu-io.h
@@ -25,7 +25,7 @@
* Operate on @blk using @argc/@argv as the command's arguments, and
* return 0 on success or negative errno on failure.
*/
-typedef int (*cfunc_t)(BlockBackend *blk, int argc, char **argv);
+typedef int (*cfunc_t)(BlockBackend *blk, int argc, char **argv, Error **errp);
typedef void (*helpfunc_t)(void);
@@ -45,7 +45,7 @@ typedef struct cmdinfo {
extern bool qemuio_misalign;
-int qemuio_command(BlockBackend *blk, const char *cmd);
+int qemuio_command(BlockBackend *blk, const char *cmd, Error **errp);
void qemuio_add_command(const cmdinfo_t *ci);
void qemuio_command_usage(const cmdinfo_t *ci);
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
index 69ade0534f1..c7113b8ea5e 100644
--- a/block/monitor/block-hmp-cmds.c
+++ b/block/monitor/block-hmp-cmds.c
@@ -608,7 +608,7 @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict)
* extended, possibly resulting in a read-only guest device keeping write
* permissions. Ugly, but it appears to be the lesser evil.
*/
- qemuio_command(blk, command);
+ qemuio_command(blk, command, &err);
fail:
blk_unref(local_blk);
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index de4c1966fea..5093aa4169a 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -55,40 +55,43 @@ void qemuio_command_usage(const cmdinfo_t *ci)
printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
}
-static int init_check_command(BlockBackend *blk, const cmdinfo_t *ct)
+static int init_check_command(BlockBackend *blk, const cmdinfo_t *ct,
+ Error **errp)
{
if (ct->flags & CMD_FLAG_GLOBAL) {
return 1;
}
if (!(ct->flags & CMD_NOFILE_OK) && !blk) {
- fprintf(stderr, "no file open, try 'help open'\n");
+ error_setg(errp, "no file open, try 'help open'");
return 0;
}
return 1;
}
static int command(BlockBackend *blk, const cmdinfo_t *ct, int argc,
- char **argv)
+ char **argv, Error **errp)
{
char *cmd = argv[0];
- if (!init_check_command(blk, ct)) {
+ if (!init_check_command(blk, ct, errp)) {
return -EINVAL;
}
if (argc - 1 < ct->argmin || (ct->argmax != -1 && argc - 1 > ct->argmax)) {
if (ct->argmax == -1) {
- fprintf(stderr,
- "bad argument count %d to %s, expected at least %d arguments\n",
- argc-1, cmd, ct->argmin);
+ error_setg(errp,
+ "bad argument count %d to %s,"
+ " expected at least %d arguments",
+ argc - 1, cmd, ct->argmin);
} else if (ct->argmin == ct->argmax) {
- fprintf(stderr,
- "bad argument count %d to %s, expected %d arguments\n",
- argc-1, cmd, ct->argmin);
+ error_setg(errp,
+ "bad argument count %d to %s, expected %d arguments",
+ argc - 1, cmd, ct->argmin);
} else {
- fprintf(stderr,
- "bad argument count %d to %s, expected between %d and %d arguments\n",
- argc-1, cmd, ct->argmin, ct->argmax);
+ error_setg(errp,
+ "bad argument count %d to %s,"
+ " expected between %d and %d arguments",
+ argc - 1, cmd, ct->argmin, ct->argmax);
}
return -EINVAL;
}
@@ -112,21 +115,19 @@ static int command(BlockBackend *blk, const cmdinfo_t *ct, int argc,
if (ct->perm & ~orig_perm) {
uint64_t new_perm;
- Error *local_err = NULL;
int ret;
new_perm = orig_perm | ct->perm;
- ret = blk_set_perm(blk, new_perm, orig_shared_perm, &local_err);
+ ret = blk_set_perm(blk, new_perm, orig_shared_perm, errp);
if (ret < 0) {
- error_report_err(local_err);
return ret;
}
}
}
qemu_reset_optind();
- return ct->cfunc(blk, argc, argv);
+ return ct->cfunc(blk, argc, argv, errp);
}
static const cmdinfo_t *find_command(const char *cmd)
@@ -192,18 +193,18 @@ static int64_t cvtnum(const char *s)
return value;
}
-static void print_cvtnum_err(int64_t rc, const char *arg)
+static void set_cvtnum_err(int64_t rc, const char *arg, Error **errp)
{
switch (rc) {
case -EINVAL:
- printf("Parsing error: non-numeric argument,"
- " or extraneous/unrecognized suffix -- %s\n", arg);
+ error_setg(errp, "Parsing error: non-numeric argument,"
+ " or extraneous/unrecognized suffix -- %s", arg);
break;
case -ERANGE:
- printf("Parsing error: argument too large -- %s\n", arg);
+ error_setg(errp, "Parsing error: argument too large -- %s", arg);
break;
default:
- printf("Parsing error: %s\n", arg);
+ error_setg(errp, "Parsing error: %s", arg);
}
}
@@ -316,14 +317,14 @@ static void timestr(struct timespec *tv, char *ts, size_t size, int format)
* Because the pattern is used as an argument to memset it must evaluate
* to an unsigned integer that fits into a single byte.
*/
-static int parse_pattern(const char *arg)
+static int parse_pattern(const char *arg, Error **errp)
{
char *endptr = NULL;
long pattern;
pattern = strtol(arg, &endptr, 0);
if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
- printf("%s is not a valid pattern byte\n", arg);
+ error_setg(errp, "%s is not a valid pattern byte", arg);
return -1;
}
@@ -386,7 +387,8 @@ static void qemu_io_free(BlockBackend *blk, void *p, size_t len,
* NULL on error
*/
static void *qemu_io_alloc_from_file(BlockBackend *blk, size_t len,
- const char *file_name, bool register_buf)
+ const char *file_name, bool register_buf,
+ Error **errp)
{
size_t alloc_len = len + (qemuio_misalign ? MISALIGN_OFFSET : 0);
char *alloc_buf, *buf, *end;
@@ -394,7 +396,7 @@ static void *qemu_io_alloc_from_file(BlockBackend *blk, size_t len,
int pattern_len;
if (!f) {
- perror(file_name);
+ error_setg_errno(errp, errno, "%s", file_name);
return NULL;
}
@@ -407,12 +409,12 @@ static void *qemu_io_alloc_from_file(BlockBackend *blk, size_t len,
pattern_len = fread(buf, 1, len, f);
if (ferror(f)) {
- perror(file_name);
+ error_setg_errno(errp, errno, "%s", file_name);
goto error;
}
if (pattern_len == 0) {
- fprintf(stderr, "%s: file is empty\n", file_name);
+ error_setg(errp, "%s: file is empty", file_name);
goto error;
}
@@ -494,7 +496,7 @@ static void print_report(const char *op, struct timespec *t, int64_t offset,
*/
static void *
create_iovec(BlockBackend *blk, QEMUIOVector *qiov, char **argv, int nr_iov,
- int pattern, bool register_buf)
+ int pattern, bool register_buf, Error **errp)
{
size_t *sizes = g_new0(size_t, nr_iov);
size_t count = 0;
@@ -508,19 +510,20 @@ create_iovec(BlockBackend *blk, QEMUIOVector *qiov, char **argv, int nr_iov,
len = cvtnum(arg);
if (len < 0) {
- print_cvtnum_err(len, arg);
+ set_cvtnum_err(len, arg, errp);
goto fail;
}
if (len > BDRV_REQUEST_MAX_BYTES) {
- printf("Argument '%s' exceeds maximum size %" PRIu64 "\n", arg,
- (uint64_t)BDRV_REQUEST_MAX_BYTES);
+ error_setg(errp, "Argument '%s' exceeds maximum size %" PRIu64,
+ arg, (uint64_t)BDRV_REQUEST_MAX_BYTES);
goto fail;
}
if (count > BDRV_REQUEST_MAX_BYTES - len) {
- printf("The total number of bytes exceed the maximum size %" PRIu64
- "\n", (uint64_t)BDRV_REQUEST_MAX_BYTES);
+ error_setg(errp,
+ "The total number of bytes exceed the maximum size %"
+ PRIu64, (uint64_t)BDRV_REQUEST_MAX_BYTES);
goto fail;
}
@@ -692,7 +695,7 @@ static void read_help(void)
"\n");
}
-static int read_f(BlockBackend *blk, int argc, char **argv);
+static int read_f(BlockBackend *blk, int argc, char **argv, Error **errp);
static const cmdinfo_t read_cmd = {
.name = "read",
@@ -705,7 +708,7 @@ static const cmdinfo_t read_cmd = {
.help = read_help,
};
-static int read_f(BlockBackend *blk, int argc, char **argv)
+static int read_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
struct timespec t1, t2;
bool Cflag = false, qflag = false, vflag = false;
@@ -732,7 +735,7 @@ static int read_f(BlockBackend *blk, int argc, char **argv)
lflag = true;
pattern_count = cvtnum(optarg);
if (pattern_count < 0) {
- print_cvtnum_err(pattern_count, optarg);
+ set_cvtnum_err(pattern_count, optarg, errp);
return pattern_count;
}
break;
@@ -741,7 +744,7 @@ static int read_f(BlockBackend *blk, int argc, char **argv)
break;
case 'P':
Pflag = true;
- pattern = parse_pattern(optarg);
+ pattern = parse_pattern(optarg, errp);
if (pattern < 0) {
return -EINVAL;
}
@@ -756,7 +759,7 @@ static int read_f(BlockBackend *blk, int argc, char **argv)
sflag = true;
pattern_offset = cvtnum(optarg);
if (pattern_offset < 0) {
- print_cvtnum_err(pattern_offset, optarg);
+ set_cvtnum_err(pattern_offset, optarg, errp);
return pattern_offset;
}
break;
@@ -776,18 +779,18 @@ static int read_f(BlockBackend *blk, int argc, char **argv)
offset = cvtnum(argv[optind]);
if (offset < 0) {
- print_cvtnum_err(offset, argv[optind]);
+ set_cvtnum_err(offset, argv[optind], errp);
return offset;
}
optind++;
count = cvtnum(argv[optind]);
if (count < 0) {
- print_cvtnum_err(count, argv[optind]);
+ set_cvtnum_err(count, argv[optind], errp);
return count;
} else if (count > BDRV_REQUEST_MAX_BYTES) {
- printf("length cannot exceed %" PRIu64 ", given %s\n",
- (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
+ error_setg(errp, "length cannot exceed %" PRIu64 ", given %s",
+ (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
return -EINVAL;
}
@@ -801,24 +804,26 @@ static int read_f(BlockBackend *blk, int argc, char **argv)
}
if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) {
- printf("pattern verification range exceeds end of read data\n");
+ error_setg(errp, "pattern verification range exceeds end of read data");
return -EINVAL;
}
if (bflag) {
if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) {
- printf("%" PRId64 " is not a sector-aligned value for 'offset'\n",
- offset);
+ error_setg(errp,
+ "%" PRId64 " is not a sector-aligned value for 'offset'",
+ offset);
return -EINVAL;
}
if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) {
- printf("%"PRId64" is not a sector-aligned value for 'count'\n",
- count);
+ error_setg(errp,
+ "%" PRId64 " is not a sector-aligned value for 'count'",
+ count);
return -EINVAL;
}
if (flags & BDRV_REQ_REGISTERED_BUF) {
- printf("I/O buffer registration is not supported when reading "
- "from vmstate\n");
+ error_setg(errp, "I/O buffer registration is not supported when"
+ " reading from vmstate");
return -EINVAL;
}
}
@@ -834,7 +839,7 @@ static int read_f(BlockBackend *blk, int argc, char **argv)
clock_gettime(CLOCK_MONOTONIC, &t2);
if (ret < 0) {
- printf("read failed: %s\n", strerror(-ret));
+ error_setg(errp, "read failed: %s", strerror(-ret));
goto out;
}
cnt = ret;
@@ -845,9 +850,9 @@ static int read_f(BlockBackend *blk, int argc, char **argv)
void *cmp_buf = g_malloc(pattern_count);
memset(cmp_buf, pattern, pattern_count);
if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
- printf("Pattern verification failed at offset %"
- PRId64 ", %"PRId64" bytes\n",
- offset + pattern_offset, pattern_count);
+ error_setg(errp, "Pattern verification failed at offset %"
+ PRId64 ", %" PRId64 " bytes",
+ offset + pattern_offset, pattern_count);
ret = -EINVAL;
}
g_free(cmp_buf);
@@ -890,7 +895,7 @@ static void readv_help(void)
"\n");
}
-static int readv_f(BlockBackend *blk, int argc, char **argv);
+static int readv_f(BlockBackend *blk, int argc, char **argv, Error **errp);
static const cmdinfo_t readv_cmd = {
.name = "readv",
@@ -902,7 +907,7 @@ static const cmdinfo_t readv_cmd = {
.help = readv_help,
};
-static int readv_f(BlockBackend *blk, int argc, char **argv)
+static int readv_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
struct timespec t1, t2;
bool Cflag = false, qflag = false, vflag = false;
@@ -924,7 +929,7 @@ static int readv_f(BlockBackend *blk, int argc, char **argv)
break;
case 'P':
Pflag = true;
- pattern = parse_pattern(optarg);
+ pattern = parse_pattern(optarg, errp);
if (pattern < 0) {
return -EINVAL;
}
@@ -952,14 +957,14 @@ static int readv_f(BlockBackend *blk, int argc, char **argv)
offset = cvtnum(argv[optind]);
if (offset < 0) {
- print_cvtnum_err(offset, argv[optind]);
+ set_cvtnum_err(offset, argv[optind], errp);
return offset;
}
optind++;
nr_iov = argc - optind;
buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, 0xab,
- flags & BDRV_REQ_REGISTERED_BUF);
+ flags & BDRV_REQ_REGISTERED_BUF, errp);
if (buf == NULL) {
return -EINVAL;
}
@@ -969,7 +974,7 @@ static int readv_f(BlockBackend *blk, int argc, char **argv)
clock_gettime(CLOCK_MONOTONIC, &t2);
if (ret < 0) {
- printf("readv failed: %s\n", strerror(-ret));
+ error_setg(errp, "readv failed: %s", strerror(-ret));
goto out;
}
cnt = ret;
@@ -980,8 +985,8 @@ static int readv_f(BlockBackend *blk, int argc, char **argv)
void *cmp_buf = g_malloc(qiov.size);
memset(cmp_buf, pattern, qiov.size);
if (memcmp(buf, cmp_buf, qiov.size)) {
- printf("Pattern verification failed at offset %"
- PRId64 ", %zu bytes\n", offset, qiov.size);
+ error_setg(errp, "Pattern verification failed at offset %"
+ PRId64 ", %zu bytes", offset, qiov.size);
ret = -EINVAL;
}
g_free(cmp_buf);
@@ -1031,7 +1036,7 @@ static void write_help(void)
"\n");
}
-static int write_f(BlockBackend *blk, int argc, char **argv);
+static int write_f(BlockBackend *blk, int argc, char **argv, Error **errp);
static const cmdinfo_t write_cmd = {
.name = "write",
@@ -1045,7 +1050,7 @@ static const cmdinfo_t write_cmd = {
.help = write_help,
};
-static int write_f(BlockBackend *blk, int argc, char **argv)
+static int write_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
struct timespec t1, t2;
bool Cflag = false, qflag = false, bflag = false;
@@ -1082,7 +1087,7 @@ static int write_f(BlockBackend *blk, int argc, char **argv)
break;
case 'P':
Pflag = true;
- pattern = parse_pattern(optarg);
+ pattern = parse_pattern(optarg, errp);
if (pattern < 0) {
return -EINVAL;
}
@@ -1115,72 +1120,78 @@ static int write_f(BlockBackend *blk, int argc, char **argv)
}
if (bflag && zflag) {
- printf("-b and -z cannot be specified at the same time\n");
+ error_setg(errp, "-b and -z cannot be specified at the same time");
return -EINVAL;
}
if ((flags & BDRV_REQ_FUA) && (bflag || cflag)) {
- printf("-f and -b or -c cannot be specified at the same time\n");
+ error_setg(errp,
+ "-f and -b or -c cannot be specified at the same time");
return -EINVAL;
}
if ((flags & BDRV_REQ_NO_FALLBACK) && !zflag) {
- printf("-n requires -z to be specified\n");
+ error_setg(errp, "-n requires -z to be specified");
return -EINVAL;
}
if ((flags & BDRV_REQ_MAY_UNMAP) && !zflag) {
- printf("-u requires -z to be specified\n");
+ error_setg(errp, "-u requires -z to be specified");
return -EINVAL;
}
if (zflag + Pflag + sflag > 1) {
- printf("Only one of -z, -P, and -s "
- "can be specified at the same time\n");
+ error_setg(errp, "Only one of -z, -P, and -s "
+ "can be specified at the same time");
return -EINVAL;
}
offset = cvtnum(argv[optind]);
if (offset < 0) {
- print_cvtnum_err(offset, argv[optind]);
+ set_cvtnum_err(offset, argv[optind], errp);
return offset;
}
optind++;
count = cvtnum(argv[optind]);
if (count < 0) {
- print_cvtnum_err(count, argv[optind]);
+ set_cvtnum_err(count, argv[optind], errp);
return count;
} else if (count > BDRV_REQUEST_MAX_BYTES &&
!(flags & BDRV_REQ_NO_FALLBACK)) {
- printf("length cannot exceed %" PRIu64 " without -n, given %s\n",
- (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
+ error_setg(errp,
+ "length cannot exceed %" PRIu64 " without -n, given %s",
+ (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
return -EINVAL;
}
if (bflag || cflag) {
if (!QEMU_IS_ALIGNED(offset, BDRV_SECTOR_SIZE)) {
- printf("%" PRId64 " is not a sector-aligned value for 'offset'\n",
- offset);
+ error_setg(errp,
+ "%" PRId64 " is not a sector-aligned value for 'offset'",
+ offset);
return -EINVAL;
}
if (!QEMU_IS_ALIGNED(count, BDRV_SECTOR_SIZE)) {
- printf("%"PRId64" is not a sector-aligned value for 'count'\n",
- count);
+ error_setg(errp,
+ "%" PRId64 " is not a sector-aligned value for 'count'",
+ count);
return -EINVAL;
}
}
if (zflag) {
if (flags & BDRV_REQ_REGISTERED_BUF) {
- printf("cannot combine zero write with registered I/O buffer\n");
+ error_setg(errp,
+ "cannot combine zero write with registered I/O buffer");
return -EINVAL;
}
} else {
if (sflag) {
buf = qemu_io_alloc_from_file(blk, count, file_name,
- flags & BDRV_REQ_REGISTERED_BUF);
+ flags & BDRV_REQ_REGISTERED_BUF,
+ errp);
if (!buf) {
return -EINVAL;
}
@@ -1203,7 +1214,7 @@ static int write_f(BlockBackend *blk, int argc, char **argv)
clock_gettime(CLOCK_MONOTONIC, &t2);
if (ret < 0) {
- printf("write failed: %s\n", strerror(-ret));
+ error_setg(errp, "write failed: %s", strerror(-ret));
goto out;
}
cnt = ret;
@@ -1245,7 +1256,7 @@ writev_help(void)
"\n");
}
-static int writev_f(BlockBackend *blk, int argc, char **argv);
+static int writev_f(BlockBackend *blk, int argc, char **argv, Error **errp);
static const cmdinfo_t writev_cmd = {
.name = "writev",
@@ -1258,7 +1269,7 @@ static const cmdinfo_t writev_cmd = {
.help = writev_help,
};
-static int writev_f(BlockBackend *blk, int argc, char **argv)
+static int writev_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
struct timespec t1, t2;
bool Cflag = false, qflag = false;
@@ -1287,7 +1298,7 @@ static int writev_f(BlockBackend *blk, int argc, char **argv)
flags |= BDRV_REQ_REGISTERED_BUF;
break;
case 'P':
- pattern = parse_pattern(optarg);
+ pattern = parse_pattern(optarg, errp);
if (pattern < 0) {
return -EINVAL;
}
@@ -1305,14 +1316,14 @@ static int writev_f(BlockBackend *blk, int argc, char **argv)
offset = cvtnum(argv[optind]);
if (offset < 0) {
- print_cvtnum_err(offset, argv[optind]);
+ set_cvtnum_err(offset, argv[optind], errp);
return offset;
}
optind++;
nr_iov = argc - optind;
buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, pattern,
- flags & BDRV_REQ_REGISTERED_BUF);
+ flags & BDRV_REQ_REGISTERED_BUF, errp);
if (buf == NULL) {
return -EINVAL;
}
@@ -1322,7 +1333,7 @@ static int writev_f(BlockBackend *blk, int argc, char **argv)
clock_gettime(CLOCK_MONOTONIC, &t2);
if (ret < 0) {
- printf("writev failed: %s\n", strerror(-ret));
+ error_setg(errp, "writev failed: %s", strerror(-ret));
goto out;
}
cnt = ret;
@@ -1367,7 +1378,7 @@ static void aio_write_done(void *opaque, int ret)
if (ret < 0) {
- printf("aio_write failed: %s\n", strerror(-ret));
+ error_report("aio_write failed: %s", strerror(-ret));
block_acct_failed(blk_get_stats(ctx->blk), &ctx->acct);
goto out;
}
@@ -1399,7 +1410,7 @@ static void aio_read_done(void *opaque, int ret)
clock_gettime(CLOCK_MONOTONIC, &t2);
if (ret < 0) {
- printf("readv failed: %s\n", strerror(-ret));
+ error_report("readv failed: %s", strerror(-ret));
block_acct_failed(blk_get_stats(ctx->blk), &ctx->acct);
goto out;
}
@@ -1409,8 +1420,8 @@ static void aio_read_done(void *opaque, int ret)
memset(cmp_buf, ctx->pattern, ctx->qiov.size);
if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
- printf("Pattern verification failed at offset %"
- PRId64 ", %zu bytes\n", ctx->offset, ctx->qiov.size);
+ error_report("Pattern verification failed at offset %"
+ PRId64 ", %zu bytes", ctx->offset, ctx->qiov.size);
}
g_free(cmp_buf);
}
@@ -1461,7 +1472,7 @@ static void aio_read_help(void)
"\n");
}
-static int aio_read_f(BlockBackend *blk, int argc, char **argv);
+static int aio_read_f(BlockBackend *blk, int argc, char **argv, Error **errp);
static const cmdinfo_t aio_read_cmd = {
.name = "aio_read",
@@ -1473,7 +1484,7 @@ static const cmdinfo_t aio_read_cmd = {
.help = aio_read_help,
};
-static int aio_read_f(BlockBackend *blk, int argc, char **argv)
+static int aio_read_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
int nr_iov, c;
struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
@@ -1486,7 +1497,7 @@ static int aio_read_f(BlockBackend *blk, int argc, char **argv)
break;
case 'P':
ctx->Pflag = true;
- ctx->pattern = parse_pattern(optarg);
+ ctx->pattern = parse_pattern(optarg, errp);
if (ctx->pattern < 0) {
g_free(ctx);
return -EINVAL;
@@ -1522,7 +1533,7 @@ static int aio_read_f(BlockBackend *blk, int argc, char **argv)
ctx->offset = cvtnum(argv[optind]);
if (ctx->offset < 0) {
int ret = ctx->offset;
- print_cvtnum_err(ret, argv[optind]);
+ set_cvtnum_err(ret, argv[optind], errp);
g_free(ctx);
return ret;
}
@@ -1530,7 +1541,7 @@ static int aio_read_f(BlockBackend *blk, int argc, char **argv)
nr_iov = argc - optind;
ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov, 0xab,
- ctx->flags & BDRV_REQ_REGISTERED_BUF);
+ ctx->flags & BDRV_REQ_REGISTERED_BUF, errp);
if (ctx->buf == NULL) {
block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_READ);
g_free(ctx);
@@ -1573,7 +1584,7 @@ static void aio_write_help(void)
"\n");
}
-static int aio_write_f(BlockBackend *blk, int argc, char **argv);
+static int aio_write_f(BlockBackend *blk, int argc, char **argv, Error **errp);
static const cmdinfo_t aio_write_cmd = {
.name = "aio_write",
@@ -1586,7 +1597,7 @@ static const cmdinfo_t aio_write_cmd = {
.help = aio_write_help,
};
-static int aio_write_f(BlockBackend *blk, int argc, char **argv)
+static int aio_write_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
int nr_iov, c;
int pattern = 0xcd;
@@ -1611,7 +1622,7 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv)
ctx->flags |= BDRV_REQ_MAY_UNMAP;
break;
case 'P':
- pattern = parse_pattern(optarg);
+ pattern = parse_pattern(optarg, errp);
if (pattern < 0) {
g_free(ctx);
return -EINVAL;
@@ -1639,25 +1650,26 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv)
}
if (ctx->zflag && optind != argc - 2) {
- printf("-z supports only a single length parameter\n");
+ error_setg(errp, "-z supports only a single length parameter");
g_free(ctx);
return -EINVAL;
}
if ((ctx->flags & BDRV_REQ_MAY_UNMAP) && !ctx->zflag) {
- printf("-u requires -z to be specified\n");
+ error_setg(errp, "-u requires -z to be specified");
g_free(ctx);
return -EINVAL;
}
if (ctx->zflag && ctx->Pflag) {
- printf("-z and -P cannot be specified at the same time\n");
+ error_setg(errp, "-z and -P cannot be specified at the same time");
g_free(ctx);
return -EINVAL;
}
if (ctx->zflag && (ctx->flags & BDRV_REQ_REGISTERED_BUF)) {
- printf("cannot combine zero write with registered I/O buffer\n");
+ error_setg(errp,
+ "cannot combine zero write with registered I/O buffer");
g_free(ctx);
return -EINVAL;
}
@@ -1665,7 +1677,7 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv)
ctx->offset = cvtnum(argv[optind]);
if (ctx->offset < 0) {
int ret = ctx->offset;
- print_cvtnum_err(ret, argv[optind]);
+ set_cvtnum_err(ret, argv[optind], errp);
g_free(ctx);
return ret;
}
@@ -1674,7 +1686,7 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv)
if (ctx->zflag) {
int64_t count = cvtnum(argv[optind]);
if (count < 0) {
- print_cvtnum_err(count, argv[optind]);
+ set_cvtnum_err(count, argv[optind], errp);
g_free(ctx);
return count;
}
@@ -1685,7 +1697,8 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv)
} else {
nr_iov = argc - optind;
ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov,
- pattern, ctx->flags & BDRV_REQ_REGISTERED_BUF);
+ pattern,
+ ctx->flags & BDRV_REQ_REGISTERED_BUF, errp);
if (ctx->buf == NULL) {
block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_WRITE);
g_free(ctx);
@@ -1703,7 +1716,7 @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv)
return 0;
}
-static int aio_flush_f(BlockBackend *blk, int argc, char **argv)
+static int aio_flush_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
BlockAcctCookie cookie;
block_acct_start(blk_get_stats(blk), &cookie, 0, BLOCK_ACCT_FLUSH);
@@ -1718,7 +1731,7 @@ static const cmdinfo_t aio_flush_cmd = {
.oneline = "completes all outstanding aio requests"
};
-static int flush_f(BlockBackend *blk, int argc, char **argv)
+static int flush_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
return blk_flush(blk);
}
@@ -1735,7 +1748,7 @@ static inline int64_t tosector(int64_t bytes)
return bytes >> BDRV_SECTOR_BITS;
}
-static int zone_report_f(BlockBackend *blk, int argc, char **argv)
+static int zone_report_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
int ret;
int64_t offset;
@@ -1745,17 +1758,17 @@ static int zone_report_f(BlockBackend *blk, int argc, char **argv)
++optind;
offset = cvtnum(argv[optind]);
if (offset < 0) {
- print_cvtnum_err(offset, argv[optind]);
+ set_cvtnum_err(offset, argv[optind], errp);
return offset;
}
++optind;
val = cvtnum(argv[optind]);
if (val < 0) {
- print_cvtnum_err(val, argv[optind]);
+ set_cvtnum_err(val, argv[optind], errp);
return val;
}
if (val > UINT_MAX) {
- printf("Number of zones must be less than 2^32\n");
+ error_setg(errp, "Number of zones must be less than 2^32");
return -ERANGE;
}
nr_zones = val;
@@ -1764,7 +1777,7 @@ static int zone_report_f(BlockBackend *blk, int argc, char **argv)
zones = g_new(BlockZoneDescriptor, nr_zones);
ret = blk_zone_report(blk, offset, &nr_zones, zones);
if (ret < 0) {
- printf("zone report failed: %s\n", strerror(-ret));
+ error_setg(errp, "zone report failed: %s", strerror(-ret));
} else {
for (int i = 0; i < nr_zones; ++i) {
printf("start: 0x%" PRIx64 ", len 0x%" PRIx64 ", "
@@ -1788,25 +1801,25 @@ static const cmdinfo_t zone_report_cmd = {
.oneline = "report zone information",
};
-static int zone_open_f(BlockBackend *blk, int argc, char **argv)
+static int zone_open_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
int ret;
int64_t offset, len;
++optind;
offset = cvtnum(argv[optind]);
if (offset < 0) {
- print_cvtnum_err(offset, argv[optind]);
+ set_cvtnum_err(offset, argv[optind], errp);
return offset;
}
++optind;
len = cvtnum(argv[optind]);
if (len < 0) {
- print_cvtnum_err(len, argv[optind]);
+ set_cvtnum_err(len, argv[optind], errp);
return len;
}
ret = blk_zone_mgmt(blk, BLK_ZO_OPEN, offset, len);
if (ret < 0) {
- printf("zone open failed: %s\n", strerror(-ret));
+ error_setg(errp, "zone open failed: %s", strerror(-ret));
}
return ret;
}
@@ -1821,25 +1834,25 @@ static const cmdinfo_t zone_open_cmd = {
.oneline = "explicit open a range of zones in zone block device",
};
-static int zone_close_f(BlockBackend *blk, int argc, char **argv)
+static int zone_close_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
int ret;
int64_t offset, len;
++optind;
offset = cvtnum(argv[optind]);
if (offset < 0) {
- print_cvtnum_err(offset, argv[optind]);
+ set_cvtnum_err(offset, argv[optind], errp);
return offset;
}
++optind;
len = cvtnum(argv[optind]);
if (len < 0) {
- print_cvtnum_err(len, argv[optind]);
+ set_cvtnum_err(len, argv[optind], errp);
return len;
}
ret = blk_zone_mgmt(blk, BLK_ZO_CLOSE, offset, len);
if (ret < 0) {
- printf("zone close failed: %s\n", strerror(-ret));
+ error_setg(errp, "zone close failed: %s", strerror(-ret));
}
return ret;
}
@@ -1854,25 +1867,25 @@ static const cmdinfo_t zone_close_cmd = {
.oneline = "close a range of zones in zone block device",
};
-static int zone_finish_f(BlockBackend *blk, int argc, char **argv)
+static int zone_finish_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
int ret;
int64_t offset, len;
++optind;
offset = cvtnum(argv[optind]);
if (offset < 0) {
- print_cvtnum_err(offset, argv[optind]);
+ set_cvtnum_err(offset, argv[optind], errp);
return offset;
}
++optind;
len = cvtnum(argv[optind]);
if (len < 0) {
- print_cvtnum_err(len, argv[optind]);
+ set_cvtnum_err(len, argv[optind], errp);
return len;
}
ret = blk_zone_mgmt(blk, BLK_ZO_FINISH, offset, len);
if (ret < 0) {
- printf("zone finish failed: %s\n", strerror(-ret));
+ error_setg(errp, "zone finish failed: %s", strerror(-ret));
}
return ret;
}
@@ -1887,25 +1900,25 @@ static const cmdinfo_t zone_finish_cmd = {
.oneline = "finish a range of zones in zone block device",
};
-static int zone_reset_f(BlockBackend *blk, int argc, char **argv)
+static int zone_reset_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
int ret;
int64_t offset, len;
++optind;
offset = cvtnum(argv[optind]);
if (offset < 0) {
- print_cvtnum_err(offset, argv[optind]);
+ set_cvtnum_err(offset, argv[optind], errp);
return offset;
}
++optind;
len = cvtnum(argv[optind]);
if (len < 0) {
- print_cvtnum_err(len, argv[optind]);
+ set_cvtnum_err(len, argv[optind], errp);
return len;
}
ret = blk_zone_mgmt(blk, BLK_ZO_RESET, offset, len);
if (ret < 0) {
- printf("zone reset failed: %s\n", strerror(-ret));
+ error_setg(errp, "zone reset failed: %s", strerror(-ret));
}
return ret;
}
@@ -1934,7 +1947,7 @@ static int do_aio_zone_append(BlockBackend *blk, QEMUIOVector *qiov,
return async_ret < 0 ? async_ret : 1;
}
-static int zone_append_f(BlockBackend *blk, int argc, char **argv)
+static int zone_append_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
int ret;
bool pflag = false;
@@ -1956,19 +1969,19 @@ static int zone_append_f(BlockBackend *blk, int argc, char **argv)
offset = cvtnum(argv[optind]);
if (offset < 0) {
- print_cvtnum_err(offset, argv[optind]);
+ set_cvtnum_err(offset, argv[optind], errp);
return offset;
}
optind++;
nr_iov = argc - optind;
buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, pattern,
- flags & BDRV_REQ_REGISTERED_BUF);
+ flags & BDRV_REQ_REGISTERED_BUF, errp);
if (buf == NULL) {
return -EINVAL;
}
ret = do_aio_zone_append(blk, &qiov, &offset, flags, &total);
if (ret < 0) {
- printf("zone append failed: %s\n", strerror(-ret));
+ error_setg(errp, "zone append failed: %s", strerror(-ret));
goto out;
}
@@ -1994,7 +2007,7 @@ static const cmdinfo_t zone_append_cmd = {
.oneline = "append write a number of bytes at a specified offset",
};
-static int truncate_f(BlockBackend *blk, int argc, char **argv);
+static int truncate_f(BlockBackend *blk, int argc, char **argv, Error **errp);
static const cmdinfo_t truncate_cmd = {
.name = "truncate",
.altname = "t",
@@ -2006,9 +2019,8 @@ static const cmdinfo_t truncate_cmd = {
.oneline = "truncates the current file at the given offset",
};
-static int truncate_f(BlockBackend *blk, int argc, char **argv)
+static int truncate_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
- Error *local_err = NULL;
int64_t offset;
int c, ret;
PreallocMode prealloc = PREALLOC_MODE_OFF;
@@ -2019,7 +2031,7 @@ static int truncate_f(BlockBackend *blk, int argc, char **argv)
prealloc = qapi_enum_parse(&PreallocMode_lookup, optarg,
PREALLOC_MODE__MAX, NULL);
if (prealloc == PREALLOC_MODE__MAX) {
- error_report("Invalid preallocation mode '%s'", optarg);
+ error_setg(errp, "Invalid preallocation mode '%s'", optarg);
return -EINVAL;
}
break;
@@ -2031,7 +2043,7 @@ static int truncate_f(BlockBackend *blk, int argc, char **argv)
offset = cvtnum(argv[optind]);
if (offset < 0) {
- print_cvtnum_err(offset, argv[1]);
+ set_cvtnum_err(offset, argv[1], errp);
return offset;
}
@@ -2040,23 +2052,22 @@ static int truncate_f(BlockBackend *blk, int argc, char **argv)
* exact=true. It is better to err on the "emit more errors" side
* than to be overly permissive.
*/
- ret = blk_truncate(blk, offset, false, prealloc, 0, &local_err);
+ ret = blk_truncate(blk, offset, false, prealloc, 0, errp);
if (ret < 0) {
- error_report_err(local_err);
return ret;
}
return 0;
}
-static int length_f(BlockBackend *blk, int argc, char **argv)
+static int length_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
int64_t size;
char s1[64];
size = blk_getlength(blk);
if (size < 0) {
- printf("getlength: %s\n", strerror(-size));
+ error_setg(errp, "getlength: %s", strerror(-size));
return size;
}
@@ -2074,12 +2085,11 @@ static const cmdinfo_t length_cmd = {
};
-static int info_f(BlockBackend *blk, int argc, char **argv)
+static int info_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
BlockDriverState *bs = blk_bs(blk);
BlockDriverInfo bdi;
ImageInfoSpecific *spec_info;
- Error *local_err = NULL;
char s1[64], s2[64];
int ret;
@@ -2104,10 +2114,13 @@ static int info_f(BlockBackend *blk, int argc, char **argv)
printf("cluster size: %s\n", s1);
printf("vm state offset: %s\n", s2);
- spec_info = bdrv_get_specific_info(bs, &local_err);
- if (local_err) {
- error_report_err(local_err);
- return -EIO;
+ {
+ Error *local_err = NULL;
+ spec_info = bdrv_get_specific_info(bs, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return -EIO;
+ }
}
if (spec_info) {
bdrv_image_info_specific_dump(spec_info,
@@ -2143,7 +2156,7 @@ static void discard_help(void)
"\n");
}
-static int discard_f(BlockBackend *blk, int argc, char **argv);
+static int discard_f(BlockBackend *blk, int argc, char **argv, Error **errp);
static const cmdinfo_t discard_cmd = {
.name = "discard",
@@ -2157,7 +2170,7 @@ static const cmdinfo_t discard_cmd = {
.help = discard_help,
};
-static int discard_f(BlockBackend *blk, int argc, char **argv)
+static int discard_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
struct timespec t1, t2;
bool Cflag = false, qflag = false;
@@ -2185,18 +2198,18 @@ static int discard_f(BlockBackend *blk, int argc, char **argv)
offset = cvtnum(argv[optind]);
if (offset < 0) {
- print_cvtnum_err(offset, argv[optind]);
+ set_cvtnum_err(offset, argv[optind], errp);
return offset;
}
optind++;
bytes = cvtnum(argv[optind]);
if (bytes < 0) {
- print_cvtnum_err(bytes, argv[optind]);
+ set_cvtnum_err(bytes, argv[optind], errp);
return bytes;
} else if (bytes > BDRV_REQUEST_MAX_BYTES) {
- printf("length cannot exceed %"PRIu64", given %s\n",
- (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
+ error_setg(errp, "length cannot exceed %" PRIu64 ", given %s",
+ (uint64_t)BDRV_REQUEST_MAX_BYTES, argv[optind]);
return -EINVAL;
}
@@ -2205,7 +2218,7 @@ static int discard_f(BlockBackend *blk, int argc, char **argv)
clock_gettime(CLOCK_MONOTONIC, &t2);
if (ret < 0) {
- printf("discard failed: %s\n", strerror(-ret));
+ error_setg(errp, "discard failed: %s", strerror(-ret));
return ret;
}
@@ -2238,7 +2251,8 @@ static void aio_discard_help(void)
"\n");
}
-static int aio_discard_f(BlockBackend *blk, int argc, char **argv);
+static int aio_discard_f(BlockBackend *blk, int argc, char **argv,
+ Error **errp);
static const cmdinfo_t aio_discard_cmd = {
.name = "aio_discard",
@@ -2259,7 +2273,7 @@ static void aio_discard_done(void *opaque, int ret)
clock_gettime(CLOCK_MONOTONIC, &t2);
if (ret < 0) {
- printf("aio_discard failed: %s\n", strerror(-ret));
+ error_report("aio_discard failed: %s", strerror(-ret));
block_acct_failed(blk_get_stats(ctx->blk), &ctx->acct);
goto out;
}
@@ -2278,7 +2292,7 @@ out:
g_free(ctx);
}
-static int aio_discard_f(BlockBackend *blk, int argc, char **argv)
+static int aio_discard_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
int c, ret;
int64_t count;
@@ -2310,7 +2324,7 @@ static int aio_discard_f(BlockBackend *blk, int argc, char **argv)
ctx->offset = cvtnum(argv[optind]);
if (ctx->offset < 0) {
ret = ctx->offset;
- print_cvtnum_err(ret, argv[optind]);
+ set_cvtnum_err(ret, argv[optind], errp);
g_free(ctx);
return ret;
}
@@ -2318,7 +2332,7 @@ static int aio_discard_f(BlockBackend *blk, int argc, char **argv)
count = cvtnum(argv[optind]);
if (count < 0) {
- print_cvtnum_err(count, argv[optind]);
+ set_cvtnum_err(count, argv[optind], errp);
g_free(ctx);
return count;
}
@@ -2332,7 +2346,7 @@ static int aio_discard_f(BlockBackend *blk, int argc, char **argv)
return 0;
}
-static int alloc_f(BlockBackend *blk, int argc, char **argv)
+static int alloc_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
BlockDriverState *bs = blk_bs(blk);
int64_t offset, start, remaining, count;
@@ -2342,14 +2356,14 @@ static int alloc_f(BlockBackend *blk, int argc, char **argv)
start = offset = cvtnum(argv[1]);
if (offset < 0) {
- print_cvtnum_err(offset, argv[1]);
+ set_cvtnum_err(offset, argv[1], errp);
return offset;
}
if (argc == 3) {
count = cvtnum(argv[2]);
if (count < 0) {
- print_cvtnum_err(count, argv[2]);
+ set_cvtnum_err(count, argv[2], errp);
return count;
}
} else {
@@ -2361,7 +2375,7 @@ static int alloc_f(BlockBackend *blk, int argc, char **argv)
while (remaining) {
ret = bdrv_is_allocated(bs, offset, remaining, &num);
if (ret < 0) {
- printf("is_allocated failed: %s\n", strerror(-ret));
+ error_setg(errp, "is_allocated failed: %s", strerror(-ret));
return ret;
}
offset += num;
@@ -2422,7 +2436,7 @@ static int map_is_allocated(BlockDriverState *bs, int64_t offset,
return firstret;
}
-static int map_f(BlockBackend *blk, int argc, char **argv)
+static int map_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
int64_t offset, bytes;
char s1[64], s2[64];
@@ -2433,17 +2447,18 @@ static int map_f(BlockBackend *blk, int argc, char **argv)
offset = 0;
bytes = blk_getlength(blk);
if (bytes < 0) {
- error_report("Failed to query image length: %s", strerror(-bytes));
+ error_setg(errp, "Failed to query image length: %s", strerror(-bytes));
return bytes;
}
while (bytes) {
ret = map_is_allocated(blk_bs(blk), offset, bytes, &num);
if (ret < 0) {
- error_report("Failed to get allocation status: %s", strerror(-ret));
+ error_setg(errp, "Failed to get allocation status: %s",
+ strerror(-ret));
return ret;
} else if (!num) {
- error_report("Unexpected end of image");
+ error_setg(errp, "Unexpected end of image");
return -EIO;
}
@@ -2485,7 +2500,7 @@ static void reopen_help(void)
"\n");
}
-static int reopen_f(BlockBackend *blk, int argc, char **argv);
+static int reopen_f(BlockBackend *blk, int argc, char **argv, Error **errp);
static QemuOptsList reopen_opts = {
.name = "reopen",
@@ -2507,7 +2522,7 @@ static const cmdinfo_t reopen_cmd = {
.help = reopen_help,
};
-static int reopen_f(BlockBackend *blk, int argc, char **argv)
+static int reopen_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
BlockDriverState *bs = blk_bs(blk);
QemuOpts *qopts;
@@ -2517,13 +2532,12 @@ static int reopen_f(BlockBackend *blk, int argc, char **argv)
bool writethrough = !blk_enable_write_cache(blk);
bool has_rw_option = false;
bool has_cache_option = false;
- Error *local_err = NULL;
while ((c = getopt(argc, argv, "c:o:rw")) != -1) {
switch (c) {
case 'c':
if (bdrv_parse_cache_mode(optarg, &flags, &writethrough) < 0) {
- error_report("Invalid cache option: %s", optarg);
+ error_setg(errp, "Invalid cache option: %s", optarg);
return -EINVAL;
}
has_cache_option = true;
@@ -2536,7 +2550,7 @@ static int reopen_f(BlockBackend *blk, int argc, char **argv)
break;
case 'r':
if (has_rw_option) {
- error_report("Only one -r/-w option may be given");
+ error_setg(errp, "Only one -r/-w option may be given");
return -EINVAL;
}
flags &= ~BDRV_O_RDWR;
@@ -2544,7 +2558,7 @@ static int reopen_f(BlockBackend *blk, int argc, char **argv)
break;
case 'w':
if (has_rw_option) {
- error_report("Only one -r/-w option may be given");
+ error_setg(errp, "Only one -r/-w option may be given");
return -EINVAL;
}
flags |= BDRV_O_RDWR;
@@ -2566,7 +2580,7 @@ static int reopen_f(BlockBackend *blk, int argc, char **argv)
if (!writethrough != blk_enable_write_cache(blk) &&
blk_get_attached_dev(blk))
{
- error_report("Cannot change cache.writeback: Device attached");
+ error_setg(errp, "Cannot change cache.writeback: Device attached");
qemu_opts_reset(&reopen_opts);
return -EBUSY;
}
@@ -2589,7 +2603,8 @@ static int reopen_f(BlockBackend *blk, int argc, char **argv)
if (qdict_haskey(opts, BDRV_OPT_READ_ONLY)) {
if (has_rw_option) {
- error_report("Cannot set both -r/-w and '" BDRV_OPT_READ_ONLY "'");
+ error_setg(errp,
+ "Cannot set both -r/-w and '" BDRV_OPT_READ_ONLY "'");
qobject_unref(opts);
return -EINVAL;
}
@@ -2600,7 +2615,7 @@ static int reopen_f(BlockBackend *blk, int argc, char **argv)
if (qdict_haskey(opts, BDRV_OPT_CACHE_DIRECT) ||
qdict_haskey(opts, BDRV_OPT_CACHE_NO_FLUSH)) {
if (has_cache_option) {
- error_report("Cannot set both -c and the cache options");
+ error_setg(errp, "Cannot set both -c and the cache options");
qobject_unref(opts);
return -EINVAL;
}
@@ -2609,37 +2624,41 @@ static int reopen_f(BlockBackend *blk, int argc, char **argv)
qdict_put_bool(opts, BDRV_OPT_CACHE_NO_FLUSH, flags & BDRV_O_NO_FLUSH);
}
- bdrv_reopen(bs, opts, true, &local_err);
-
- if (local_err) {
- error_report_err(local_err);
- return -EINVAL;
+ {
+ Error *local_err = NULL;
+ bdrv_reopen(bs, opts, true, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return -EINVAL;
+ }
}
blk_set_enable_write_cache(blk, !writethrough);
return 0;
}
-static int break_f(BlockBackend *blk, int argc, char **argv)
+static int break_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
int ret;
ret = bdrv_debug_breakpoint(blk_bs(blk), argv[1], argv[2]);
if (ret < 0) {
- printf("Could not set breakpoint: %s\n", strerror(-ret));
+ error_setg(errp, "Could not set breakpoint: %s", strerror(-ret));
return ret;
}
return 0;
}
-static int remove_break_f(BlockBackend *blk, int argc, char **argv)
+static int remove_break_f(BlockBackend *blk, int argc, char **argv,
+ Error **errp)
{
int ret;
ret = bdrv_debug_remove_breakpoint(blk_bs(blk), argv[1]);
if (ret < 0) {
- printf("Could not remove breakpoint %s: %s\n", argv[1], strerror(-ret));
+ error_setg(errp, "Could not remove breakpoint %s: %s",
+ argv[1], strerror(-ret));
return ret;
}
@@ -2665,13 +2684,13 @@ static const cmdinfo_t remove_break_cmd = {
.oneline = "remove a breakpoint by tag",
};
-static int resume_f(BlockBackend *blk, int argc, char **argv)
+static int resume_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
int ret;
ret = bdrv_debug_resume(blk_bs(blk), argv[1]);
if (ret < 0) {
- printf("Could not resume request: %s\n", strerror(-ret));
+ error_setg(errp, "Could not resume request: %s", strerror(-ret));
return ret;
}
@@ -2687,7 +2706,7 @@ static const cmdinfo_t resume_cmd = {
.oneline = "resumes the request tagged as tag",
};
-static int wait_break_f(BlockBackend *blk, int argc, char **argv)
+static int wait_break_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
while (!bdrv_debug_is_suspended(blk_bs(blk), argv[1])) {
aio_poll(blk_get_aio_context(blk), true);
@@ -2704,7 +2723,7 @@ static const cmdinfo_t wait_break_cmd = {
.oneline = "waits for the suspension of a request",
};
-static int abort_f(BlockBackend *blk, int argc, char **argv)
+static int abort_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
abort();
}
@@ -2730,7 +2749,7 @@ static void sigraise_help(void)
"\n", SIGTERM);
}
-static int sigraise_f(BlockBackend *blk, int argc, char **argv);
+static int sigraise_f(BlockBackend *blk, int argc, char **argv, Error **errp);
static const cmdinfo_t sigraise_cmd = {
.name = "sigraise",
@@ -2743,15 +2762,16 @@ static const cmdinfo_t sigraise_cmd = {
.help = sigraise_help,
};
-static int sigraise_f(BlockBackend *blk, int argc, char **argv)
+static int sigraise_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
int64_t sig = cvtnum(argv[1]);
if (sig < 0) {
- print_cvtnum_err(sig, argv[1]);
+ set_cvtnum_err(sig, argv[1], errp);
return sig;
} else if (sig > NSIG) {
- printf("signal argument '%s' is too large to be a valid signal\n",
- argv[1]);
+ error_setg(errp,
+ "signal argument '%s' is too large to be a valid signal",
+ argv[1]);
return -EINVAL;
}
@@ -2772,7 +2792,7 @@ static void sleep_cb(void *opaque)
*expired = true;
}
-static int sleep_f(BlockBackend *blk, int argc, char **argv)
+static int sleep_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
char *endptr;
long ms;
@@ -2781,7 +2801,7 @@ static int sleep_f(BlockBackend *blk, int argc, char **argv)
ms = strtol(argv[1], &endptr, 0);
if (ms < 0 || *endptr != '\0') {
- printf("%s is not a valid number\n", argv[1]);
+ error_setg(errp, "%s is not a valid number", argv[1]);
return -EINVAL;
}
@@ -2833,7 +2853,7 @@ static void help_all(void)
printf("\nUse 'help commandname' for extended help.\n");
}
-static int help_f(BlockBackend *blk, int argc, char **argv)
+static int help_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
const cmdinfo_t *ct;
@@ -2844,7 +2864,7 @@ static int help_f(BlockBackend *blk, int argc, char **argv)
ct = find_command(argv[1]);
if (ct == NULL) {
- printf("command %s not found\n", argv[1]);
+ error_setg(errp, "command %s not found", argv[1]);
return -EINVAL;
}
@@ -2867,7 +2887,7 @@ static const cmdinfo_t help_cmd = {
* Called with aio context of blk acquired. Or with qemu_get_aio_context()
* context acquired if blk is NULL.
*/
-int qemuio_command(BlockBackend *blk, const char *cmd)
+int qemuio_command(BlockBackend *blk, const char *cmd, Error **errp)
{
char *input;
const cmdinfo_t *ct;
@@ -2880,9 +2900,9 @@ int qemuio_command(BlockBackend *blk, const char *cmd)
if (c) {
ct = find_command(v[0]);
if (ct) {
- ret = command(blk, ct, c, v);
+ ret = command(blk, ct, c, v, errp);
} else {
- fprintf(stderr, "command \"%s\" not found\n", v[0]);
+ error_setg(errp, "command \"%s\" not found", v[0]);
ret = -EINVAL;
}
}
diff --git a/qemu-io.c b/qemu-io.c
index 8f2de83f3c8..598d5b1c9ca 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -68,7 +68,7 @@ static int get_eof_char(void)
#endif
}
-static int close_f(BlockBackend *blk, int argc, char **argv)
+static int close_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
blk_unref(qemuio_blk);
qemuio_blk = NULL;
@@ -140,7 +140,7 @@ static void open_help(void)
"\n");
}
-static int open_f(BlockBackend *blk, int argc, char **argv);
+static int open_f(BlockBackend *blk, int argc, char **argv, Error **errp);
static const cmdinfo_t open_cmd = {
.name = "open",
@@ -164,7 +164,7 @@ static QemuOptsList empty_opts = {
},
};
-static int open_f(BlockBackend *blk, int argc, char **argv)
+static int open_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
int flags = BDRV_O_UNMAP;
int readonly = 0;
@@ -268,7 +268,7 @@ static int open_f(BlockBackend *blk, int argc, char **argv)
return 0;
}
-static int quit_f(BlockBackend *blk, int argc, char **argv)
+static int quit_f(BlockBackend *blk, int argc, char **argv, Error **errp)
{
quit_qemu_io = true;
return 0;
@@ -414,7 +414,14 @@ static void prep_fetchline(void *opaque)
static int do_qemuio_command(const char *cmd)
{
- return qemuio_command(qemuio_blk, cmd);
+ Error *local_err = NULL;
+ int ret;
+
+ ret = qemuio_command(qemuio_blk, cmd, &local_err);
+ if (local_err) {
+ error_report_err(local_err);
+ }
+ return ret;
}
static int command_loop(void)
diff --git a/tests/qemu-iotests/004.out b/tests/qemu-iotests/004.out
index fb8593289f5..37da6024809 100644
--- a/tests/qemu-iotests/004.out
+++ b/tests/qemu-iotests/004.out
@@ -6,36 +6,36 @@ wrote 1048576/1048576 bytes at offset 133169152
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
write into image boundary
-write failed: Input/output error
+qemu-io: write failed: Input/output error
write at image boundary
-write failed: Input/output error
+qemu-io: write failed: Input/output error
write past image boundary
-write failed: Input/output error
+qemu-io: write failed: Input/output error
pwrite past image boundary
-write failed: Input/output error
+qemu-io: write failed: Input/output error
writev past image boundary
-writev failed: Input/output error
+qemu-io: writev failed: Input/output error
read before image boundary
read 1048576/1048576 bytes at offset 133169152
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read into image boundary
-read failed: Input/output error
+qemu-io: read failed: Input/output error
read at image boundary
-read failed: Input/output error
+qemu-io: read failed: Input/output error
read past image boundary
-read failed: Input/output error
+qemu-io: read failed: Input/output error
pread past image boundary
-read failed: Input/output error
+qemu-io: read failed: Input/output error
readv past image boundary
-readv failed: Input/output error
+qemu-io: readv failed: Input/output error
*** done
diff --git a/tests/qemu-iotests/021.out b/tests/qemu-iotests/021.out
index 8533f8e58ae..dfdfeb50378 100644
--- a/tests/qemu-iotests/021.out
+++ b/tests/qemu-iotests/021.out
@@ -2,92 +2,92 @@ QA output created by 021
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
== testing writev -P -1 ==
--1 is not a valid pattern byte
+qemu-io: -1 is not a valid pattern byte
== testing read -P -1 ==
--1 is not a valid pattern byte
+qemu-io: -1 is not a valid pattern byte
== testing write -P -1 ==
--1 is not a valid pattern byte
+qemu-io: -1 is not a valid pattern byte
== testing readv -P -1 ==
--1 is not a valid pattern byte
+qemu-io: -1 is not a valid pattern byte
== testing aio_read -P -1 ==
--1 is not a valid pattern byte
+qemu-io: -1 is not a valid pattern byte
== testing aio_write -P -1 ==
--1 is not a valid pattern byte
+qemu-io: -1 is not a valid pattern byte
== testing writev -P 300 ==
-300 is not a valid pattern byte
+qemu-io: 300 is not a valid pattern byte
== testing read -P 300 ==
-300 is not a valid pattern byte
+qemu-io: 300 is not a valid pattern byte
== testing write -P 300 ==
-300 is not a valid pattern byte
+qemu-io: 300 is not a valid pattern byte
== testing readv -P 300 ==
-300 is not a valid pattern byte
+qemu-io: 300 is not a valid pattern byte
== testing aio_read -P 300 ==
-300 is not a valid pattern byte
+qemu-io: 300 is not a valid pattern byte
== testing aio_write -P 300 ==
-300 is not a valid pattern byte
+qemu-io: 300 is not a valid pattern byte
== testing writev -P 12m ==
-12m is not a valid pattern byte
+qemu-io: 12m is not a valid pattern byte
== testing read -P 12m ==
-12m is not a valid pattern byte
+qemu-io: 12m is not a valid pattern byte
== testing write -P 12m ==
-12m is not a valid pattern byte
+qemu-io: 12m is not a valid pattern byte
== testing readv -P 12m ==
-12m is not a valid pattern byte
+qemu-io: 12m is not a valid pattern byte
== testing aio_read -P 12m ==
-12m is not a valid pattern byte
+qemu-io: 12m is not a valid pattern byte
== testing aio_write -P 12m ==
-12m is not a valid pattern byte
+qemu-io: 12m is not a valid pattern byte
== testing writev -P 4k ==
-4k is not a valid pattern byte
+qemu-io: 4k is not a valid pattern byte
== testing read -P 4k ==
-4k is not a valid pattern byte
+qemu-io: 4k is not a valid pattern byte
== testing write -P 4k ==
-4k is not a valid pattern byte
+qemu-io: 4k is not a valid pattern byte
== testing readv -P 4k ==
-4k is not a valid pattern byte
+qemu-io: 4k is not a valid pattern byte
== testing aio_read -P 4k ==
-4k is not a valid pattern byte
+qemu-io: 4k is not a valid pattern byte
== testing aio_write -P 4k ==
-4k is not a valid pattern byte
+qemu-io: 4k is not a valid pattern byte
== testing writev -P route66 ==
-route66 is not a valid pattern byte
+qemu-io: route66 is not a valid pattern byte
== testing read -P route66 ==
-route66 is not a valid pattern byte
+qemu-io: route66 is not a valid pattern byte
== testing write -P route66 ==
-route66 is not a valid pattern byte
+qemu-io: route66 is not a valid pattern byte
== testing readv -P route66 ==
-route66 is not a valid pattern byte
+qemu-io: route66 is not a valid pattern byte
== testing aio_read -P route66 ==
-route66 is not a valid pattern byte
+qemu-io: route66 is not a valid pattern byte
== testing aio_write -P route66 ==
-route66 is not a valid pattern byte
+qemu-io: route66 is not a valid pattern byte
*** done
diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out
index a37bf446e94..27275fd6b70 100644
--- a/tests/qemu-iotests/060.out
+++ b/tests/qemu-iotests/060.out
@@ -9,7 +9,7 @@ ERROR cluster 3 refcount=1 reference=3
Data may be corrupted, or further writes to the image may corrupt it.
incompatible_features []
qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with active L1 table); further corruption events will be suppressed
-write failed: Input/output error
+qemu-io: write failed: Input/output error
incompatible_features [1]
image: TEST_DIR/t.IMGFMT
file format: IMGFMT
@@ -23,7 +23,7 @@ Format specific information:
corrupt: true
extended l2: false
qemu-io: can't open device TEST_DIR/t.IMGFMT: IMGFMT: Image is corrupt; cannot be opened read/write
-no file open, try 'help open'
+qemu-io: no file open, try 'help open'
read 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -37,7 +37,7 @@ ERROR cluster 2 refcount=1 reference=2
Data may be corrupted, or further writes to the image may corrupt it.
incompatible_features []
qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with refcount block); further corruption events will be suppressed
-write failed: Input/output error
+qemu-io: write failed: Input/output error
incompatible_features [1]
ERROR refcount block 0 refcount=2
ERROR cluster 2 refcount=1 reference=2
@@ -73,7 +73,7 @@ Data may be corrupted, or further writes to the image may corrupt it.
This means waste of disk space, but no harm to data.
incompatible_features []
qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with inactive L2 table); further corruption events will be suppressed
-write failed: Input/output error
+qemu-io: write failed: Input/output error
incompatible_features [1]
ERROR cluster 4 refcount=1 reference=2
Leaked cluster 9 refcount=1 reference=0
@@ -108,10 +108,10 @@ wrote 65536/65536 bytes at offset 0
wrote 65536/65536 bytes at offset 536870912
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with active L2 table); further corruption events will be suppressed
+qemu-io: write failed: Input/output error
+qemu-io: aio_write failed: No medium found
blkdebug: Suspended request '0'
-write failed: Input/output error
blkdebug: Resuming request '0'
-aio_write failed: No medium found
=== Testing unallocated image header ===
@@ -119,7 +119,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with qcow2_header); further corruption events will be suppressed
-write failed: Input/output error
+qemu-io: write failed: Input/output error
=== Testing unaligned L1 entry ===
@@ -127,7 +127,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
qcow2: Marking image as corrupt: L2 table offset 0x42a00 unaligned (L1 index: 0); further corruption events will be suppressed
-read failed: Input/output error
+qemu-io: read failed: Input/output error
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -140,7 +140,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
qcow2: Marking image as corrupt: Cluster allocation offset 0x52a00 unaligned (L2 offset: 0x40000, L2 index: 0); further corruption events will be suppressed
-read failed: Input/output error
+qemu-io: read failed: Input/output error
=== Testing unaligned pre-allocated zero cluster ===
@@ -154,7 +154,7 @@ qemu-img: Failed to turn zero into data clusters: Input/output error
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
qcow2: Marking image as corrupt: Refblock offset 0x22a00 unaligned (reftable index: 0); further corruption events will be suppressed
-write failed: Input/output error
+qemu-io: write failed: Input/output error
=== Testing non-fatal corruption on freeing ===
@@ -171,8 +171,8 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
qcow2: Image is corrupt: Cluster allocation offset 0x52a00 unaligned (L2 offset: 0x40000, L2 index: 0); further non-fatal corruption events will be suppressed
-read failed: Input/output error
-read failed: Input/output error
+qemu-io: read failed: Input/output error
+qemu-io: read failed: Input/output error
=== Testing non-fatal and then fatal corruption report ===
@@ -181,15 +181,15 @@ wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
qcow2: Image is corrupt: Cannot free unaligned cluster 0x52a00; further non-fatal corruption events will be suppressed
qcow2: Marking image as corrupt: Cluster allocation offset 0x62a00 unaligned (L2 offset: 0x40000, L2 index: 0x1); further corruption events will be suppressed
+qemu-io: read failed: Input/output error
discard 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read failed: Input/output error
=== Testing empty refcount table ===
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with refcount table); further corruption events will be suppressed
-write failed: Input/output error
+qemu-io: write failed: Input/output error
ERROR cluster 0 refcount=0 reference=1
ERROR cluster 1 refcount=0 reference=1
ERROR cluster 3 refcount=0 reference=1
@@ -209,7 +209,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
qcow2: Marking image as corrupt: Preventing invalid allocation of refcount block at offset 0; further corruption events will be suppressed
-write failed: Input/output error
+qemu-io: write failed: Input/output error
ERROR cluster 0 refcount=0 reference=1
ERROR cluster 1 refcount=0 reference=1
ERROR cluster 3 refcount=0 reference=1
@@ -229,7 +229,7 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
qcow2: Marking image as corrupt: Preventing invalid allocation of L2 table at offset 0; further corruption events will be suppressed
-write failed: Input/output error
+qemu-io: write failed: Input/output error
ERROR cluster 0 refcount=0 reference=1
ERROR cluster 1 refcount=0 reference=1
ERROR cluster 2 refcount=0 reference=1
@@ -251,7 +251,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
wrote 65536/65536 bytes at offset 65536
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
qcow2: Marking image as corrupt: Preventing invalid allocation of compressed cluster at offset 0; further corruption events will be suppressed
-write failed: Input/output error
+qemu-io: write failed: Input/output error
ERROR cluster 0 refcount=0 reference=1
ERROR cluster 1 refcount=0 reference=1
ERROR cluster 2 refcount=0 reference=1
@@ -286,7 +286,7 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
qcow2: Marking image as corrupt: Preventing invalid allocation of L2 table at offset 0; further corruption events will be suppressed
-write failed: Input/output error
+qemu-io: write failed: Input/output error
=== Testing dirty corrupt image ===
@@ -319,7 +319,7 @@ wrote 65536/65536 bytes at offset 0
discard 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
qcow2: Marking image as corrupt: Preallocated zero cluster offset 0x2a00 unaligned (guest offset: 0); further corruption events will be suppressed
-write failed: Input/output error
+qemu-io: write failed: Input/output error
--- Repairing ---
Repairing offset=2a00: Preallocated cluster is not properly aligned; L2 entry corrupted.
The following inconsistencies were found and repaired:
@@ -337,7 +337,7 @@ wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
qcow2: Marking image as corrupt: Refblock offset 0x2a00 unaligned (reftable index: 0); further corruption events will be suppressed
qcow2_free_clusters failed: Input/output error
-discard failed: No medium found
+qemu-io: discard failed: No medium found
--- Repairing ---
ERROR refcount block 0 is not cluster aligned; refcount table entry corrupted
qcow2: Marking image as corrupt: Refblock offset 0x2a00 unaligned (reftable index: 0); further corruption events will be suppressed
@@ -419,8 +419,7 @@ qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps
QMP_VERSION
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_IMAGE_CORRUPTED", "data": {"device": "none0", "msg": "Preventing invalid write on metadata (overlaps with refcount table)", "offset": 65536, "node-name": "drive", "fatal": true, "size": 65536}}
-write failed: Input/output error
-{"return": ""}
+{"return": "Error: write failed: Input/output error\r\n"}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
{"return": {}}
@@ -431,7 +430,6 @@ QMP_VERSION
{"return": {}}
qcow2: Image is corrupt: L2 table offset 0x2a2a2a00 unaligned (L1 index: 0); further non-fatal corruption events will be suppressed
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_IMAGE_CORRUPTED", "data": {"device": "", "msg": "L2 table offset 0x2a2a2a00 unaligned (L1 index: 0)", "node-name": "drive", "fatal": false}}
-{"return": ""}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
{"return": {}}
diff --git a/tests/qemu-iotests/071.out b/tests/qemu-iotests/071.out
index a2923b05c29..f2d015d8cca 100644
--- a/tests/qemu-iotests/071.out
+++ b/tests/qemu-iotests/071.out
@@ -30,11 +30,11 @@ blkverify: read offset=0 bytes=512 contents mismatch at offset 0
=== Testing blkdebug through filename ===
-read failed: Input/output error
+qemu-io: read failed: Input/output error
=== Testing blkdebug through file blockref ===
-read failed: Input/output error
+qemu-io: read failed: Input/output error
=== Testing blkdebug on existing block device ===
@@ -43,8 +43,7 @@ QMP_VERSION
{"return": {}}
{"return": {}}
{"return": {}}
-read failed: Input/output error
-{"return": ""}
+{"return": "Error: read failed: Input/output error\r\n"}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
{"return": {}}
@@ -82,8 +81,7 @@ read 512/512 bytes at offset 0
wrote 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
-read failed: Input/output error
-{"return": ""}
+{"return": "Error: read failed: Input/output error\r\n"}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
QEMU_PROG: Failed to flush the L2 table cache: Input/output error
QEMU_PROG: Failed to flush the refcount block cache: Input/output error
diff --git a/tests/qemu-iotests/072.out b/tests/qemu-iotests/072.out
index fe949d47817..d7ce24da1f7 100644
--- a/tests/qemu-iotests/072.out
+++ b/tests/qemu-iotests/072.out
@@ -15,7 +15,7 @@ read 512/512 bytes at offset 512
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 512/512 bytes at offset 1024
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-Pattern verification failed at offset 0, 512 bytes
+qemu-io: Pattern verification failed at offset 0, 512 bytes
read 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
*** done
diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out
index d8acb3e7235..b20c21faf6a 100644
--- a/tests/qemu-iotests/080.out
+++ b/tests/qemu-iotests/080.out
@@ -66,8 +66,8 @@ wrote 512/512 bytes at offset 0
qemu-img: Failed to load snapshot: Snapshot L1 table offset invalid
qemu-img: Snapshot L1 table offset invalid
qemu-img: Failed to turn zero into data clusters: Invalid argument
+qemu-io: write failed: Invalid argument
qemu-io: Failed to flush the refcount block cache: Invalid argument
-write failed: Invalid argument
qemu-img: Snapshot L1 table offset invalid
qemu-img: Could not apply snapshot 'test': Failed to load snapshot: Invalid argument
qemu-img: Could not delete snapshot 'test': Snapshot L1 table offset invalid
@@ -89,8 +89,8 @@ wrote 512/512 bytes at offset 0
qemu-img: Failed to load snapshot: Snapshot L1 table too large
qemu-img: Snapshot L1 table too large
qemu-img: Failed to turn zero into data clusters: File too large
+qemu-io: write failed: File too large
qemu-io: Failed to flush the refcount block cache: File too large
-write failed: File too large
qemu-img: Snapshot L1 table too large
qemu-img: Could not apply snapshot 'test': Failed to load snapshot: File too large
qemu-img: Could not delete snapshot 'test': Snapshot L1 table too large
diff --git a/tests/qemu-iotests/089.out b/tests/qemu-iotests/089.out
index c53fc4823a1..a29e19b12d7 100644
--- a/tests/qemu-iotests/089.out
+++ b/tests/qemu-iotests/089.out
@@ -16,7 +16,7 @@ read 512/512 bytes at offset 512
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 512/512 bytes at offset 1024
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-Pattern verification failed at offset 0, 512 bytes
+qemu-io: Pattern verification failed at offset 0, 512 bytes
read 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -33,7 +33,7 @@ read 512/512 bytes at offset 0
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
wrote 512/512 bytes at offset 229376
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read failed: Input/output error
+qemu-io: read failed: Input/output error
=== Testing qemu-img info output ===
diff --git a/tests/qemu-iotests/114.out b/tests/qemu-iotests/114.out
index f51dd9d20a1..80220e440ec 100644
--- a/tests/qemu-iotests/114.out
+++ b/tests/qemu-iotests/114.out
@@ -11,7 +11,7 @@ cluster_size: 65536
backing file: TEST_DIR/t.IMGFMT.base
backing file format: foo
qemu-io: can't open device TEST_DIR/t.qcow2: Could not open backing file: Unknown driver 'foo'
-no file open, try 'help open'
+qemu-io: no file open, try 'help open'
read 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
qemu-img: Could not change the backing file to 'TEST_DIR/t.qcow2.base': backing format must be specified
diff --git a/tests/qemu-iotests/134.out b/tests/qemu-iotests/134.out
index 4abc5b5f7da..ce2a0df166e 100644
--- a/tests/qemu-iotests/134.out
+++ b/tests/qemu-iotests/134.out
@@ -24,7 +24,7 @@ read 134217728/134217728 bytes at offset 0
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== verify pattern failure with wrong password ==
-Pattern verification failed at offset 0, 134217728 bytes
+qemu-io: Pattern verification failed at offset 0, 134217728 bytes
read 134217728/134217728 bytes at offset 0
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
*** done
diff --git a/tests/qemu-iotests/137.out b/tests/qemu-iotests/137.out
index e19df5b6ba8..1947c1a1bd7 100644
--- a/tests/qemu-iotests/137.out
+++ b/tests/qemu-iotests/137.out
@@ -40,5 +40,5 @@ OK: Dirty bit not set
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
qemu-io: Parameter 'lazy-refcounts' expects 'on' or 'off'
qcow2: Marking image as corrupt: Preventing invalid allocation of L2 table at offset 0; further corruption events will be suppressed
-write failed: Input/output error
+qemu-io: write failed: Input/output error
*** done
diff --git a/tests/qemu-iotests/171 b/tests/qemu-iotests/171
index d1d77f70130..87a8aa24d96 100755
--- a/tests/qemu-iotests/171
+++ b/tests/qemu-iotests/171
@@ -188,7 +188,7 @@ img_offset=512
img_size=512
_make_test_img $size
(
-$QEMU_IO "$(img_json)" <<EOT
+$QEMU_IO "$(img_json)" 2>&1 <<EOT
write -P 0x0a 0 512
write -P 0x0a 511 1
write -P 0x0a 512 1
diff --git a/tests/qemu-iotests/171.out b/tests/qemu-iotests/171.out
index ec3363b4f44..67ef9b88415 100644
--- a/tests/qemu-iotests/171.out
+++ b/tests/qemu-iotests/171.out
@@ -21,32 +21,32 @@ wrote 1/1 bytes at offset 3583
1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
write across image boundary
-write failed: Input/output error
+qemu-io: write failed: Input/output error
write at image boundary
-write failed: Input/output error
+qemu-io: write failed: Input/output error
write after image boundary
-write failed: Input/output error
+qemu-io: write failed: Input/output error
writev before/after image boundary
-writev failed: Input/output error
+qemu-io: writev failed: Input/output error
read before image boundary
read 1/1 bytes at offset 3583
1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read across image boundary
-read failed: Input/output error
+qemu-io: read failed: Input/output error
read at image boundary
-read failed: Input/output error
+qemu-io: read failed: Input/output error
read after image boundary
-read failed: Input/output error
+qemu-io: read failed: Input/output error
readv before/after image boundary
-readv failed: Input/output error
+qemu-io: readv failed: Input/output error
fill image with pattern
wrote 4096/4096 bytes at offset 0
@@ -60,7 +60,7 @@ read 4/4 bytes at offset 510
4 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
write zeroes across image boundary
-write failed: Input/output error
+qemu-io: write failed: Input/output error
write zeroes at image boundary and check
wrote 2/2 bytes at offset 3582
@@ -68,7 +68,7 @@ wrote 2/2 bytes at offset 3582
00000ffe: 00 00 ..
read 2/2 bytes at offset 4094
2 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read failed: Input/output error
+qemu-io: read failed: Input/output error
fill image with pattern
wrote 4096/4096 bytes at offset 0
@@ -82,7 +82,7 @@ read 4/4 bytes at offset 510
4 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
discard across image boundary
-discard failed: Input/output error
+qemu-io: discard failed: Input/output error
discard at image boundary and check
discard 2/2 bytes at offset 3582
@@ -90,7 +90,7 @@ discard 2/2 bytes at offset 3582
00000ffe: 00 00 ..
read 2/2 bytes at offset 4094
2 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read failed: Input/output error
+qemu-io: read failed: Input/output error
== test 'offset' and 'size' options ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4096
@@ -113,32 +113,32 @@ wrote 1/1 bytes at offset 2047
1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
write across image boundary
-write failed: Input/output error
+qemu-io: write failed: Input/output error
write at image boundary
-write failed: Input/output error
+qemu-io: write failed: Input/output error
write after image boundary
-write failed: Input/output error
+qemu-io: write failed: Input/output error
writev before/after image boundary
-writev failed: Input/output error
+qemu-io: writev failed: Input/output error
read before image boundary
read 1/1 bytes at offset 2047
1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read across image boundary
-read failed: Input/output error
+qemu-io: read failed: Input/output error
read at image boundary
-read failed: Input/output error
+qemu-io: read failed: Input/output error
read after image boundary
-read failed: Input/output error
+qemu-io: read failed: Input/output error
readv before/after image boundary
-readv failed: Input/output error
+qemu-io: readv failed: Input/output error
fill image with pattern
wrote 4096/4096 bytes at offset 0
@@ -152,7 +152,7 @@ read 4/4 bytes at offset 510
4 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
write zeroes across image boundary
-write failed: Input/output error
+qemu-io: write failed: Input/output error
write zeroes at image boundary and check
wrote 2/2 bytes at offset 2046
@@ -176,7 +176,7 @@ read 4/4 bytes at offset 510
4 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
discard across image boundary
-discard failed: Input/output error
+qemu-io: discard failed: Input/output error
discard at image boundary and check
discard 2/2 bytes at offset 2046
@@ -209,32 +209,32 @@ wrote 1/1 bytes at offset 2047
1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
write across image boundary
-write failed: Input/output error
+qemu-io: write failed: Input/output error
write at image boundary
-write failed: Input/output error
+qemu-io: write failed: Input/output error
write after image boundary
-write failed: Input/output error
+qemu-io: write failed: Input/output error
writev before/after image boundary
-writev failed: Input/output error
+qemu-io: writev failed: Input/output error
read before image boundary
read 1/1 bytes at offset 2047
1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read across image boundary
-read failed: Input/output error
+qemu-io: read failed: Input/output error
read at image boundary
-read failed: Input/output error
+qemu-io: read failed: Input/output error
read after image boundary
-read failed: Input/output error
+qemu-io: read failed: Input/output error
readv before/after image boundary
-readv failed: Input/output error
+qemu-io: readv failed: Input/output error
fill image with pattern
wrote 4096/4096 bytes at offset 0
@@ -248,7 +248,7 @@ read 4/4 bytes at offset 8
4 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
write zeroes across image boundary
-write failed: Input/output error
+qemu-io: write failed: Input/output error
write zeroes at image boundary and check
wrote 2/2 bytes at offset 2046
@@ -272,7 +272,7 @@ read 4/4 bytes at offset 8
4 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
discard across image boundary
-discard failed: Input/output error
+qemu-io: discard failed: Input/output error
discard at image boundary and check
discard 2/2 bytes at offset 2046
@@ -290,12 +290,12 @@ wrote 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 1/1 bytes at offset 511
1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-write failed: Input/output error
+qemu-io: write failed: Input/output error
wrote 1024/1024 bytes at offset 0
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 1/1 bytes at offset 1023
1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-write failed: Input/output error
+qemu-io: write failed: Input/output error
checking boundaries
000001fe: 00 00 0a 0a ....
read 4/4 bytes at offset 510
diff --git a/tests/qemu-iotests/214.out b/tests/qemu-iotests/214.out
index 9fc67287f8e..26056938ee9 100644
--- a/tests/qemu-iotests/214.out
+++ b/tests/qemu-iotests/214.out
@@ -7,7 +7,7 @@ wrote 2097152/2097152 bytes at offset 0
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 2097152/2097152 bytes at offset 2097152
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read failed: Input/output error
+qemu-io: read failed: Input/output error
No errors were found on the image.
read 4194304/4194304 bytes at offset 0
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
diff --git a/tests/qemu-iotests/220.out b/tests/qemu-iotests/220.out
index 33b994b8a14..6f200ec8947 100644
--- a/tests/qemu-iotests/220.out
+++ b/tests/qemu-iotests/220.out
@@ -38,7 +38,7 @@ wrote 2097152/2097152 bytes at offset 37748736
No errors were found on the image.
image size 39845888
== Trying to write compressed cluster ==
-write failed: File too large
+qemu-io: write failed: File too large
image size 562949957615616
== Writing normal cluster ==
wrote 2097152/2097152 bytes at offset 0
diff --git a/tests/qemu-iotests/244.out b/tests/qemu-iotests/244.out
index c62f5aec25b..c5e62146c93 100644
--- a/tests/qemu-iotests/244.out
+++ b/tests/qemu-iotests/244.out
@@ -10,22 +10,22 @@ read 65536/65536 bytes at offset 0
read 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
qemu-io: can't open device TEST_DIR/t.qcow2: Could not open 'inexistent': No such file or directory
-no file open, try 'help open'
+qemu-io: no file open, try 'help open'
Data file required, but without data file name in the image:
qemu-io: can't open device TEST_DIR/t.qcow2: 'data-file' is required for this image
-no file open, try 'help open'
+qemu-io: no file open, try 'help open'
read 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
qemu-io: can't open device TEST_DIR/t.qcow2: Could not open 'inexistent': No such file or directory
-no file open, try 'help open'
+qemu-io: no file open, try 'help open'
Setting data-file for an image with internal data:
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
qemu-io: can't open device TEST_DIR/t.qcow2: 'data-file' can only be set for images with an external data file
-no file open, try 'help open'
+qemu-io: no file open, try 'help open'
qemu-io: can't open device TEST_DIR/t.qcow2: Could not open 'inexistent': No such file or directory
-no file open, try 'help open'
+qemu-io: no file open, try 'help open'
=== Conflicting features ===
@@ -37,7 +37,7 @@ qemu-img: error while writing at byte 0: Operation not supported
Convert uncompressed, then write compressed data manually:
Images are identical.
-write failed: Operation not supported
+qemu-io: write failed: Operation not supported
No errors were found on the image.
Take an internal snapshot:
diff --git a/tests/qemu-iotests/249.out b/tests/qemu-iotests/249.out
index d2bf9be85ea..3d37709a9ef 100644
--- a/tests/qemu-iotests/249.out
+++ b/tests/qemu-iotests/249.out
@@ -9,7 +9,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.
{ 'execute': 'human-monitor-command',
'arguments': {'command-line': 'qemu-io none0 "aio_write 0 2k"'}}
-{"return": "Block node is read-onlyrn"}
+{"return": "Error: Block node is read-onlyrn"}
=== Run block-commit on base using an invalid filter node name
@@ -24,7 +24,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.
{ 'execute': 'human-monitor-command',
'arguments': {'command-line': 'qemu-io none0 "aio_write 0 2k"'}}
-{"return": "Block node is read-onlyrn"}
+{"return": "Error: Block node is read-onlyrn"}
=== Run block-commit on base using the default filter node name
@@ -43,5 +43,5 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.
{ 'execute': 'human-monitor-command',
'arguments': {'command-line': 'qemu-io none0 "aio_write 0 2k"'}}
-{"return": "Block node is read-onlyrn"}
+{"return": "Error: Block node is read-onlyrn"}
*** done
diff --git a/tests/qemu-iotests/271.out b/tests/qemu-iotests/271.out
index 0b24d501595..da92d4b5b1a 100644
--- a/tests/qemu-iotests/271.out
+++ b/tests/qemu-iotests/271.out
@@ -456,7 +456,7 @@ L2 entry #0: 0x8000000000050001 0000000000000001
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
L2 entry #1: 0x8000000000060000 00000001ffffffff
qcow2: Marking image as corrupt: Invalid cluster entry found (L2 offset: 0x40000, L2 index: 0x1); further corruption events will be suppressed
-read failed: Input/output error
+qemu-io: read failed: Input/output error
### Corrupted L2 entries - read test (unallocated) ###
@@ -471,14 +471,14 @@ L2 entry #0: 0x0000000000000001 0000000000000000
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
L2 entry #0: 0x0000000000000000 0000000000000001
qcow2: Marking image as corrupt: Invalid cluster entry found (L2 offset: 0x40000, L2 index: 0); further corruption events will be suppressed
-read failed: Input/output error
+qemu-io: read failed: Input/output error
# Both 'subcluster is zero' and 'subcluster is allocated' bits set
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
L2 entry #1: 0x0000000000000000 0000000100000001
qcow2: Marking image as corrupt: Invalid cluster entry found (L2 offset: 0x40000, L2 index: 0x1); further corruption events will be suppressed
-read failed: Input/output error
+qemu-io: read failed: Input/output error
### Compressed cluster with subcluster bitmap != 0 - read test ###
@@ -501,7 +501,7 @@ L2 entry #0: 0x8000000000050001 0000000000000001
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
L2 entry #1: 0x8000000000060000 00000001ffffffff
qcow2: Marking image as corrupt: Invalid cluster entry found (L2 offset: 0x40000, L2 index: 0x1); further corruption events will be suppressed
-write failed: Input/output error
+qemu-io: write failed: Input/output error
### Corrupted L2 entries - write test (unallocated) ###
@@ -516,14 +516,14 @@ L2 entry #0: 0x8000000000060000 0000000000000001
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
L2 entry #0: 0x0000000000000000 0000000000000001
qcow2: Marking image as corrupt: Invalid cluster entry found (L2 offset: 0x40000, L2 index: 0); further corruption events will be suppressed
-write failed: Input/output error
+qemu-io: write failed: Input/output error
# Both 'subcluster is zero' and 'subcluster is allocated' bits set
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
L2 entry #1: 0x0000000000000000 0000000100000001
qcow2: Marking image as corrupt: Invalid cluster entry found (L2 offset: 0x40000, L2 index: 0x1); further corruption events will be suppressed
-write failed: Input/output error
+qemu-io: write failed: Input/output error
### Compressed cluster with subcluster bitmap != 0 - write test ###
@@ -555,7 +555,7 @@ Double checking the fixed image now...
1 errors were found on the image.
Data may be corrupted, or further writes to the image may corrupt it.
qcow2: Marking image as corrupt: Cluster allocation offset 0x50200 unaligned (L2 offset: 0x40000, L2 index: 0); further corruption events will be suppressed
-read failed: Input/output error
+qemu-io: read failed: Input/output error
# Corrupted L2 entry, no allocated subclusters #
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw
Repairing offset=50200: Preallocated cluster is not properly aligned; L2 entry corrupted.
diff --git a/tests/qemu-iotests/tests/copy-before-write b/tests/qemu-iotests/tests/copy-before-write
index f86032b1167..11a9562067b 100755
--- a/tests/qemu-iotests/tests/copy-before-write
+++ b/tests/qemu-iotests/tests/copy-before-write
@@ -87,17 +87,17 @@ class TestCbwError(iotests.QMPTestCase):
result = self.vm.qmp('human-monitor-command',
command_line='qemu-io cbw "write 0 1M"')
- self.assert_qmp(result, 'return', '')
+ write_res = result['return']
result = self.vm.qmp('human-monitor-command',
command_line='qemu-io access "read 0 1M"')
- self.assert_qmp(result, 'return', '')
+ read_res = result['return']
self.vm.shutdown()
log = self.vm.get_log()
log = iotests.filter_qtest(log)
log = iotests.filter_qemu_io(log)
- return log
+ return log, write_res, read_res
def do_cbw_error_via_blockdev_backup(self, on_cbw_error=None):
self.vm.cmd('blockdev-add', {
@@ -150,28 +150,29 @@ class TestCbwError(iotests.QMPTestCase):
result = self.vm.qmp('human-monitor-command',
command_line='qemu-io cbw "write 0 1M"')
- self.assert_qmp(result, 'return', '')
+ write_res = result['return']
result = self.vm.qmp('human-monitor-command',
command_line='qemu-io access "read 0 1M"')
- self.assert_qmp(result, 'return', '')
+ read_res = result['return']
self.vm.shutdown()
log = self.vm.get_log()
log = iotests.filter_qemu_io(log)
- return log
+ return log, write_res, read_res
def test_break_snapshot_on_cbw_error(self):
"""break-snapshot behavior:
Guest write succeed, but further snapshot-read fails, as snapshot is
broken.
"""
- log = self.do_cbw_error('break-snapshot')
+ log, write_res, read_res = self.do_cbw_error('break-snapshot')
+ self.assertEqual(write_res, '')
+ self.assertIn('read failed: Permission denied', read_res)
self.assertEqual(log, """\
wrote 1048576/1048576 bytes at offset 0
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read failed: Permission denied
""")
def test_break_guest_write_on_cbw_error(self):
@@ -179,10 +180,11 @@ read failed: Permission denied
Guest write fails, but snapshot-access continues working and further
snapshot-read succeeds.
"""
- log = self.do_cbw_error('break-guest-write')
+ log, write_res, read_res = self.do_cbw_error('break-guest-write')
+ self.assertIn('write failed: Input/output error', write_res)
+ self.assertEqual(read_res, '')
self.assertEqual(log, """\
-write failed: Input/output error
read 1048576/1048576 bytes at offset 0
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
""")
@@ -191,20 +193,24 @@ read 1048576/1048576 bytes at offset 0
"""Ensure CBW filter accepts break-snapshot policy
specified in blockdev-backup QMP command.
"""
- log = self.do_cbw_error_via_blockdev_backup('break-snapshot')
+ log, write_res, read_res = \
+ self.do_cbw_error_via_blockdev_backup('break-snapshot')
+ self.assertEqual(write_res, '')
+ self.assertIn('read failed: Permission denied', read_res)
self.assertEqual(log, """\
wrote 1048576/1048576 bytes at offset 0
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read failed: Permission denied
""")
def test_break_guest_write_policy_forwarding(self):
"""Ensure CBW filter accepts break-guest-write policy
specified in blockdev-backup QMP command.
"""
- log = self.do_cbw_error_via_blockdev_backup('break-guest-write')
+ log, write_res, read_res = \
+ self.do_cbw_error_via_blockdev_backup('break-guest-write')
+ self.assertIn('write failed: Input/output error', write_res)
+ self.assertEqual(read_res, '')
self.assertEqual(log, """\
-write failed: Input/output error
read 1048576/1048576 bytes at offset 0
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
""")
@@ -213,9 +219,11 @@ read 1048576/1048576 bytes at offset 0
"""Ensure break-guest-write policy is used by default when
on-cbw-error is not explicitly specified.
"""
- log = self.do_cbw_error_via_blockdev_backup()
+ log, write_res, read_res = \
+ self.do_cbw_error_via_blockdev_backup()
+ self.assertIn('write failed: Input/output error', write_res)
+ self.assertEqual(read_res, '')
self.assertEqual(log, """\
-write failed: Input/output error
read 1048576/1048576 bytes at offset 0
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
""")
@@ -260,47 +268,53 @@ read 1048576/1048576 bytes at offset 0
result = self.vm.qmp('human-monitor-command',
command_line='qemu-io cbw "write 0 512K"')
- self.assert_qmp(result, 'return', '')
+ write1_res = result['return']
# We need second write to trigger throttling
result = self.vm.qmp('human-monitor-command',
command_line='qemu-io cbw "write 512K 512K"')
- self.assert_qmp(result, 'return', '')
+ write2_res = result['return']
result = self.vm.qmp('human-monitor-command',
command_line='qemu-io access "read 0 1M"')
- self.assert_qmp(result, 'return', '')
+ read_res = result['return']
self.vm.shutdown()
log = self.vm.get_log()
log = re.sub(r'^\[I \+?\d+\.\d+\] OPENED\n', '', log)
log = re.sub(r'\[I \+?\d+\.\d+\] CLOSED\n?$', '', log)
log = iotests.filter_qemu_io(log)
- return log
+ return log, write1_res, write2_res, read_res
def test_timeout_break_guest(self):
- log = self.do_cbw_timeout('break-guest-write')
+ log, write1_res, write2_res, read_res = \
+ self.do_cbw_timeout('break-guest-write')
+ self.assertEqual(write1_res, '')
# macOS and FreeBSD tend to represent ETIMEDOUT as
# "Operation timed out", when Linux prefer
# "Connection timed out"
- log = log.replace('Operation timed out',
- 'Connection timed out')
+ write2_res = write2_res.replace('Operation timed out',
+ 'Connection timed out')
+ self.assertIn('write failed: Connection timed out', write2_res)
+ self.assertEqual(read_res, '')
self.assertEqual(log, """\
wrote 524288/524288 bytes at offset 0
512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-write failed: Connection timed out
read 1048576/1048576 bytes at offset 0
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
""")
def test_timeout_break_snapshot(self):
- log = self.do_cbw_timeout('break-snapshot')
+ log, write1_res, write2_res, read_res = \
+ self.do_cbw_timeout('break-snapshot')
+ self.assertEqual(write1_res, '')
+ self.assertEqual(write2_res, '')
+ self.assertIn('read failed: Permission denied', read_res)
self.assertEqual(log, """\
wrote 524288/524288 bytes at offset 0
512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 524288/524288 bytes at offset 524288
512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-read failed: Permission denied
""")
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 15/40] block: add x-qemu-io QMP command
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (13 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 14/40] qemu-io: propagate errors through Error API instead of printf Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 16/40] tests/qemu-iotests/N: use " Marc-André Lureau
` (25 subsequent siblings)
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Add an x-qemu-io QMP command that runs qemu-io commands on block
devices. The command accepts a device name (block backend name,
node-name, or qdev ID) and a qemu-io command string.
Refactor hmp_qemu_io() to be a thin wrapper around the new QMP
command, following the standard HMP-over-QMP pattern used by other
block commands.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
qapi/block.json | 34 +++++++++++++
block/monitor/block-hmp-cmds.c | 60 ++--------------------
block/monitor/qmp-cmds.c | 79 +++++++++++++++++++++++++++++
block/monitor/meson.build | 1 +
tests/qemu-iotests/tests/image-fleecing | 4 +-
tests/qemu-iotests/tests/image-fleecing.out | 52 +++++++++----------
6 files changed, 145 insertions(+), 85 deletions(-)
diff --git a/qapi/block.json b/qapi/block.json
index 46955bbb3e3..0a588714ea9 100644
--- a/qapi/block.json
+++ b/qapi/block.json
@@ -603,3 +603,37 @@
'*boundaries-zap': ['uint64'],
'*boundaries-flush': ['uint64'] },
'allow-preconfig': true }
+
+##
+# @x-qemu-io:
+#
+# Run a qemu-io command on a block device. Take either a block
+# backend name or a qdev ID to identify the device.
+#
+# @device: the block backend name, node-name to run the
+# command on.
+#
+# @qdev: the qdev ID of the block device to run the
+# command on.
+#
+# @command: the qemu-io command string to execute.
+#
+# Features:
+#
+# @unstable: This command is for testing only.
+#
+# Since: 11.1
+#
+# .. qmp-example::
+#
+# -> { "execute": "x-qemu-io",
+# "arguments": { "device": "virtio0",
+# "command": "read 0 512" } }
+# <- { "return": {} }
+##
+{ 'command': 'x-qemu-io',
+ 'data': { '*device': 'str',
+ '*qdev': 'str',
+ 'command': 'str' },
+ 'features': [ 'unstable' ],
+ 'allow-preconfig': true }
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
index c7113b8ea5e..254a79ce855 100644
--- a/block/monitor/block-hmp-cmds.c
+++ b/block/monitor/block-hmp-cmds.c
@@ -56,7 +56,6 @@
#include "block/qapi.h"
#include "block/block_int.h"
#include "block/block-hmp-cmds.h"
-#include "qemu-io.h"
static void hmp_drive_add_node(Monitor *mon, const char *optstr)
{
@@ -551,67 +550,14 @@ void hmp_eject(Monitor *mon, const QDict *qdict)
void hmp_qemu_io(Monitor *mon, const QDict *qdict)
{
- BlockBackend *blk = NULL;
- BlockDriverState *bs = NULL;
- BlockBackend *local_blk = NULL;
bool qdev = qdict_get_try_bool(qdict, "qdev", false);
const char *device = qdict_get_str(qdict, "device");
const char *command = qdict_get_str(qdict, "command");
Error *err = NULL;
- int ret;
-
- if (qdev) {
- blk = blk_by_qdev_id(device, &err);
- if (!blk) {
- goto fail;
- }
- } else {
- blk = blk_by_name(device);
- if (!blk) {
- bs = bdrv_lookup_bs(NULL, device, &err);
- if (!bs) {
- goto fail;
- }
- }
- }
-
- if (bs) {
- blk = local_blk = blk_new(bdrv_get_aio_context(bs), 0, BLK_PERM_ALL);
- ret = blk_insert_bs(blk, bs, &err);
- if (ret < 0) {
- goto fail;
- }
- }
-
- /*
- * Notably absent: Proper permission management. This is sad, but it seems
- * almost impossible to achieve without changing the semantics and thereby
- * limiting the use cases of the qemu-io HMP command.
- *
- * In an ideal world we would unconditionally create a new BlockBackend for
- * qemuio_command(), but we have commands like 'reopen' and want them to
- * take effect on the exact BlockBackend whose name the user passed instead
- * of just on a temporary copy of it.
- *
- * Another problem is that deleting the temporary BlockBackend involves
- * draining all requests on it first, but some qemu-iotests cases want to
- * issue multiple aio_read/write requests and expect them to complete in
- * the background while the monitor has already returned.
- *
- * This is also what prevents us from saving the original permissions and
- * restoring them later: We can't revoke permissions until all requests
- * have completed, and we don't know when that is nor can we really let
- * anything else run before we have revoken them to avoid race conditions.
- *
- * What happens now is that command() in qemu-io-cmds.c can extend the
- * permissions if necessary for the qemu-io command. And they simply stay
- * extended, possibly resulting in a read-only guest device keeping write
- * permissions. Ugly, but it appears to be the lesser evil.
- */
- qemuio_command(blk, command, &err);
-fail:
- blk_unref(local_blk);
+ qmp_x_qemu_io(qdev ? NULL : device,
+ qdev ? device : NULL,
+ command, &err);
hmp_handle_error(mon, err);
}
diff --git a/block/monitor/qmp-cmds.c b/block/monitor/qmp-cmds.c
new file mode 100644
index 00000000000..e5759d824f1
--- /dev/null
+++ b/block/monitor/qmp-cmds.c
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#include "qemu/osdep.h"
+
+#include "system/block-backend.h"
+#include "block/block_int.h"
+#include "qapi/qapi-commands-block.h"
+#include "qapi/error.h"
+#include "qemu-io.h"
+
+void qmp_x_qemu_io(const char *device, const char *qdev,
+ const char *command, Error **errp)
+{
+ BlockBackend *blk = NULL;
+ BlockBackend *local_blk = NULL;
+ BlockDriverState *bs = NULL;
+ int ret;
+
+ if (!device && !qdev) {
+ error_setg(errp, "Must specify either device or qdev");
+ return;
+ }
+ if (qdev && device) {
+ error_setg(errp, "Cannot specify both qdev and device");
+ return;
+ }
+
+ if (qdev) {
+ blk = blk_by_qdev_id(qdev, errp);
+ if (!blk) {
+ return;
+ }
+ } else {
+ blk = blk_by_name(device);
+ if (!blk) {
+ bs = bdrv_lookup_bs(NULL, device, errp);
+ if (!bs) {
+ return;
+ }
+ }
+ }
+
+ if (bs) {
+ blk = local_blk = blk_new(bdrv_get_aio_context(bs), 0, BLK_PERM_ALL);
+ ret = blk_insert_bs(blk, bs, errp);
+ if (ret < 0) {
+ goto fail;
+ }
+ }
+
+ /*
+ * Notably absent: Proper permission management. This is sad, but it seems
+ * almost impossible to achieve without changing the semantics and thereby
+ * limiting the use cases of the qemu-io command.
+ *
+ * In an ideal world we would unconditionally create a new BlockBackend for
+ * qemuio_command(), but we have commands like 'reopen' and want them to
+ * take effect on the exact BlockBackend whose name the user passed instead
+ * of just on a temporary copy of it.
+ *
+ * Another problem is that deleting the temporary BlockBackend involves
+ * draining all requests on it first, but some qemu-iotests cases want to
+ * issue multiple aio_read/write requests and expect them to complete in
+ * the background while the monitor has already returned.
+ *
+ * This is also what prevents us from saving the original permissions and
+ * restoring them later: We can't revoke permissions until all requests
+ * have completed, and we don't know when that is nor can we really let
+ * anything else run before we have revoken them to avoid race conditions.
+ *
+ * What happens now is that command() in qemu-io-cmds.c can extend the
+ * permissions if necessary for the qemu-io command. And they simply stay
+ * extended, possibly resulting in a read-only guest device keeping write
+ * permissions. Ugly, but it appears to be the lesser evil.
+ */
+ qemuio_command(blk, command, errp);
+
+fail:
+ blk_unref(local_blk);
+}
diff --git a/block/monitor/meson.build b/block/monitor/meson.build
index 1022516e93c..74faced9e17 100644
--- a/block/monitor/meson.build
+++ b/block/monitor/meson.build
@@ -1,2 +1,3 @@
system_ss.add(files('block-hmp-cmds.c'))
block_ss.add(files('bitmap-qmp-cmds.c'))
+system_ss.add(files('qmp-cmds.c'))
diff --git a/tests/qemu-iotests/tests/image-fleecing b/tests/qemu-iotests/tests/image-fleecing
index 5e3b2c7e46a..62ef15ff046 100755
--- a/tests/qemu-iotests/tests/image-fleecing
+++ b/tests/qemu-iotests/tests/image-fleecing
@@ -202,12 +202,12 @@ def do_test(vm, use_cbw, use_snapshot_access_filter, base_img_path,
for p in overwrite:
cmd = 'write -P%s %s %s' % p
log(cmd)
- log(vm.hmp_qemu_io(qom_path, cmd, qdev=True))
+ log(vm.qmp('x-qemu-io', qdev='sda', command=cmd))
if push_backup:
# Check that previous operations were done during backup, not after
# If backup is already finished, it's possible that it was finished
- # even before hmp qemu_io write, and we didn't actually test
+ # even before qemu_io write, and we didn't actually test
# copy-before-write operation. This should not happen, as we use
# speed=1. But worth checking.
result = vm.qmp('query-block-jobs')
diff --git a/tests/qemu-iotests/tests/image-fleecing.out b/tests/qemu-iotests/tests/image-fleecing.out
index acfc89ff0e9..0a819539130 100644
--- a/tests/qemu-iotests/tests/image-fleecing.out
+++ b/tests/qemu-iotests/tests/image-fleecing.out
@@ -31,13 +31,13 @@ read -P0 0x3fe0000 64k
--- Testing COW ---
write -P0xab 0 64k
-{"return": ""}
+{"return": {}}
write -P0xad 0x00f8000 64k
-{"return": ""}
+{"return": {}}
write -P0x1d 0x2008000 64k
-{"return": ""}
+{"return": {}}
write -P0xea 0x3fe0000 64k
-{"return": ""}
+{"return": {}}
--- Verifying Data ---
@@ -101,13 +101,13 @@ read -P0 0x3fe0000 64k
--- Testing COW ---
write -P0xab 0 64k
-{"return": ""}
+{"return": {}}
write -P0xad 0x00f8000 64k
-{"return": ""}
+{"return": {}}
write -P0x1d 0x2008000 64k
-{"return": ""}
+{"return": {}}
write -P0xea 0x3fe0000 64k
-{"return": ""}
+{"return": {}}
--- Verifying Data ---
@@ -172,13 +172,13 @@ read -P0 0x3fe0000 64k
--- Testing COW ---
write -P0xab 0 64k
-{"return": ""}
+{"return": {}}
write -P0xad 0x00f8000 64k
-{"return": ""}
+{"return": {}}
write -P0x1d 0x2008000 64k
-{"return": ""}
+{"return": {}}
write -P0xea 0x3fe0000 64k
-{"return": ""}
+{"return": {}}
--- Verifying Data ---
@@ -238,25 +238,25 @@ read -P0xd5 1M 64k
read -P0xdc 32M 64k
read -P0xcd 0x3ff0000 64k
read -P0 0x00f8000 32k
-read failed: Invalid argument
+qemu-io: read failed: Invalid argument
read -P0 0x2010000 32k
-read failed: Invalid argument
+qemu-io: read failed: Invalid argument
read -P0 0x3fe0000 64k
-read failed: Invalid argument
+qemu-io: read failed: Invalid argument
--- Testing COW ---
write -P0xab 0 64k
-{"return": ""}
+{"return": {}}
write -P0xad 0x00f8000 64k
-{"return": ""}
+{"return": {}}
write -P0x1d 0x2008000 64k
-{"return": ""}
+{"return": {}}
write -P0xea 0x3fe0000 64k
-{"return": ""}
+{"return": {}}
--- Verifying Data ---
@@ -265,13 +265,13 @@ read -P0xd5 1M 64k
read -P0xdc 32M 64k
read -P0xcd 0x3ff0000 64k
read -P0 0x00f8000 32k
-read failed: Invalid argument
+qemu-io: read failed: Invalid argument
read -P0 0x2010000 32k
-read failed: Invalid argument
+qemu-io: read failed: Invalid argument
read -P0 0x3fe0000 64k
-read failed: Invalid argument
+qemu-io: read failed: Invalid argument
--- Cleanup ---
@@ -318,13 +318,13 @@ Done
--- Testing COW ---
write -P0xab 0 64k
-{"return": ""}
+{"return": {}}
write -P0xad 0x00f8000 64k
-{"return": ""}
+{"return": {}}
write -P0x1d 0x2008000 64k
-{"return": ""}
+{"return": {}}
write -P0xea 0x3fe0000 64k
-{"return": ""}
+{"return": {}}
{"data": {"device": "push-backup", "len": 67108864, "offset": 67108864, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
{"return": {}}
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 16/40] tests/qemu-iotests/N: use x-qemu-io QMP command
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (14 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 15/40] block: add x-qemu-io QMP command Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 17/40] tests/qemu-iotests/181, 192, 249: convert to QMP Marc-André Lureau
` (24 subsequent siblings)
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Replace human-monitor-command wrapping of the HMP qemu-io command with
direct x-qemu-io QMP calls in the two test cases that exercised
corrupted image behavior through the monitor.
The only output change is the QMP response: {"return": {}} (void)
instead of {"return": ""} (empty HMP string).
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
tests/qemu-iotests/060 | 8 ++++----
tests/qemu-iotests/060.out | 2 +-
tests/qemu-iotests/071 | 30 +++++++++++++++++------------
tests/qemu-iotests/071.out | 8 ++++----
tests/qemu-iotests/117 | 5 +++--
tests/qemu-iotests/117.out | 7 ++++---
tests/qemu-iotests/120 | 4 ++--
tests/qemu-iotests/120.out | 2 +-
tests/qemu-iotests/156 | 36 +++++++++++++++++-----------------
tests/qemu-iotests/156.out | 48 +++++++++++++++++++++++-----------------------
tests/qemu-iotests/161 | 18 ++++++++---------
tests/qemu-iotests/161.out | 24 +++++++++++------------
tests/qemu-iotests/249 | 12 ++++++------
tests/qemu-iotests/249.out | 18 ++++++++---------
tests/qemu-iotests/283 | 4 ++--
tests/qemu-iotests/283.out | 4 ++--
16 files changed, 119 insertions(+), 111 deletions(-)
diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060
index 5cd21a6f686..c2c1cd815f0 100755
--- a/tests/qemu-iotests/060
+++ b/tests/qemu-iotests/060
@@ -449,8 +449,8 @@ echo
_make_test_img 64M
poke_file "$TEST_IMG" "$rt_offset" "\x00\x00\x00\x00\x00\x00\x00\x00"
echo "{'execute': 'qmp_capabilities'}
- {'execute': 'human-monitor-command',
- 'arguments': {'command-line': 'qemu-io drive \"write 0 512\"'}}
+ {'execute': 'x-qemu-io',
+ 'arguments': {'device': 'drive', 'command': 'write 0 512'}}
{'execute': 'quit'}" \
| $QEMU -qmp stdio -nographic -nodefaults \
-drive if=none,node-name=drive,file="$TEST_IMG",driver=qcow2 \
@@ -468,8 +468,8 @@ poke_file "$TEST_IMG" "$l1_offset" "\x00\x00\x00\x00\x2a\x2a\x2a\x2a"
# Inactive images are effectively read-only images, so this should be a
# non-fatal corruption (which does not modify the image)
echo "{'execute': 'qmp_capabilities'}
- {'execute': 'human-monitor-command',
- 'arguments': {'command-line': 'qemu-io drive \"read 0 512\"'}}
+ {'execute': 'x-qemu-io',
+ 'arguments': {'device': 'drive', 'command': 'read 0 512'}}
{'execute': 'quit'}" \
| $QEMU -qmp stdio -nographic -nodefaults \
-blockdev "{'node-name': 'drive',
diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out
index 27275fd6b70..7d3bfc97450 100644
--- a/tests/qemu-iotests/060.out
+++ b/tests/qemu-iotests/060.out
@@ -419,7 +419,7 @@ qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps
QMP_VERSION
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_IMAGE_CORRUPTED", "data": {"device": "none0", "msg": "Preventing invalid write on metadata (overlaps with refcount table)", "offset": 65536, "node-name": "drive", "fatal": true, "size": 65536}}
-{"return": "Error: write failed: Input/output error\r\n"}
+{"error": {"class": "GenericError", "desc": "write failed: Input/output error"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
{"return": {}}
diff --git a/tests/qemu-iotests/071 b/tests/qemu-iotests/071
index 331f8cfddcf..463f5c02349 100755
--- a/tests/qemu-iotests/071
+++ b/tests/qemu-iotests/071
@@ -139,9 +139,10 @@ run_qemu <<EOF
}
}
}
-{ "execute": "human-monitor-command",
+{ "execute": "x-qemu-io",
"arguments": {
- "command-line": 'qemu-io drive0-debug "read 0 512"'
+ "device": "drive0-debug",
+ "command": "read 0 512"
}
}
{ "execute": "quit" }
@@ -174,9 +175,10 @@ run_qemu <<EOF
}
}
}
-{ "execute": "human-monitor-command",
+{ "execute": "x-qemu-io",
"arguments": {
- "command-line": 'qemu-io drive0-verify "read 0 512"'
+ "device": "drive0-verify",
+ "command": "read 0 512"
}
}
{ "execute": "quit" }
@@ -209,9 +211,10 @@ run_qemu <<EOF
"raw": "drive0"
}
}
-{ "execute": "human-monitor-command",
+{ "execute": "x-qemu-io",
"arguments": {
- "command-line": 'qemu-io drive0-verify "read 0 512"'
+ "device": "drive0-verify",
+ "command": "read 0 512"
}
}
{ "execute": "quit" }
@@ -248,19 +251,22 @@ run_qemu <<EOF
}
}
}
-{ "execute": "human-monitor-command",
+{ "execute": "x-qemu-io",
"arguments": {
- "command-line": 'qemu-io drive0-debug "read 0 512"'
+ "device": "drive0-debug",
+ "command": "read 0 512"
}
}
-{ "execute": "human-monitor-command",
+{ "execute": "x-qemu-io",
"arguments": {
- "command-line": 'qemu-io drive0-debug "write 0 512"'
+ "device": "drive0-debug",
+ "command": "write 0 512"
}
}
-{ "execute": "human-monitor-command",
+{ "execute": "x-qemu-io",
"arguments": {
- "command-line": 'qemu-io drive0-debug "read 0 512"'
+ "device": "drive0-debug",
+ "command": "read 0 512"
}
}
{ "execute": "quit" }
diff --git a/tests/qemu-iotests/071.out b/tests/qemu-iotests/071.out
index f2d015d8cca..7fcdbed943f 100644
--- a/tests/qemu-iotests/071.out
+++ b/tests/qemu-iotests/071.out
@@ -43,7 +43,7 @@ QMP_VERSION
{"return": {}}
{"return": {}}
{"return": {}}
-{"return": "Error: read failed: Input/output error\r\n"}
+{"error": {"class": "GenericError", "desc": "read failed: Input/output error"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
{"return": {}}
@@ -77,11 +77,11 @@ QMP_VERSION
{"return": {}}
read 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-{"return": ""}
+{"return": {}}
wrote 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-{"return": ""}
-{"return": "Error: read failed: Input/output error\r\n"}
+{"return": {}}
+{"error": {"class": "GenericError", "desc": "read failed: Input/output error"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
QEMU_PROG: Failed to flush the L2 table cache: Input/output error
QEMU_PROG: Failed to flush the refcount block cache: Input/output error
diff --git a/tests/qemu-iotests/117 b/tests/qemu-iotests/117
index 6081473584f..bbd9d431502 100755
--- a/tests/qemu-iotests/117
+++ b/tests/qemu-iotests/117
@@ -65,8 +65,9 @@ _send_qemu_cmd $QEMU_HANDLE \
'return'
_send_qemu_cmd $QEMU_HANDLE \
- "{ 'execute': 'human-monitor-command',
- 'arguments': { 'command-line': 'qemu-io format \"write -P 42 0 64k\"' } }" \
+ "{ 'execute': 'x-qemu-io',
+ 'arguments': { 'device': 'format',
+ 'command': 'write -P 42 0 64k' } }" \
'return'
_send_qemu_cmd $QEMU_HANDLE \
diff --git a/tests/qemu-iotests/117.out b/tests/qemu-iotests/117.out
index 1cea9e02173..ed260e8215b 100644
--- a/tests/qemu-iotests/117.out
+++ b/tests/qemu-iotests/117.out
@@ -12,11 +12,12 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536
'driver': 'IMGFMT',
'file': 'protocol' } }
{"return": {}}
-{ 'execute': 'human-monitor-command',
- 'arguments': { 'command-line': 'qemu-io format "write -P 42 0 64k"' } }
+{ 'execute': 'x-qemu-io',
+ 'arguments': { 'device': 'format',
+ 'command': 'write -P 42 0 64k' } }
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-{"return": ""}
+{"return": {}}
{ 'execute': 'quit' }
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
{"return": {}}
diff --git a/tests/qemu-iotests/120 b/tests/qemu-iotests/120
index ac7bd8c4e3c..fb9ac5a165e 100755
--- a/tests/qemu-iotests/120
+++ b/tests/qemu-iotests/120
@@ -46,8 +46,8 @@ _require_drivers raw
_make_test_img 64M
echo "{'execute': 'qmp_capabilities'}
- {'execute': 'human-monitor-command',
- 'arguments': {'command-line': 'qemu-io drv \"write -P 42 0 64k\"'}}
+ {'execute': 'x-qemu-io',
+ 'arguments': {'device': 'drv', 'command': 'write -P 42 0 64k'}}
{'execute': 'quit'}" \
| $QEMU -qmp stdio -nographic -nodefaults \
-drive id=drv,if=none,file="$TEST_IMG",driver=raw,file.driver=$IMGFMT \
diff --git a/tests/qemu-iotests/120.out b/tests/qemu-iotests/120.out
index 35d84a5bc5a..e5b8848207d 100644
--- a/tests/qemu-iotests/120.out
+++ b/tests/qemu-iotests/120.out
@@ -4,7 +4,7 @@ QMP_VERSION
{"return": {}}
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-{"return": ""}
+{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
{"return": {}}
read 65536/65536 bytes at offset 0
diff --git a/tests/qemu-iotests/156 b/tests/qemu-iotests/156
index 97c2d86ce57..1b0c955c422 100755
--- a/tests/qemu-iotests/156
+++ b/tests/qemu-iotests/156
@@ -79,9 +79,9 @@ _send_qemu_cmd $QEMU_HANDLE \
# Write something to the snapshot
_send_qemu_cmd $QEMU_HANDLE \
- "{ 'execute': 'human-monitor-command',
- 'arguments': { 'command-line':
- 'qemu-io source \"write -P 3 128k 128k\"' } }" \
+ "{ 'execute': 'x-qemu-io',
+ 'arguments': { 'device': 'source',
+ 'command': 'write -P 3 128k 128k' } }" \
'return'
# Create target image
@@ -104,9 +104,9 @@ _send_qemu_cmd $QEMU_HANDLE \
# Write some more
_send_qemu_cmd $QEMU_HANDLE \
- "{ 'execute': 'human-monitor-command',
- 'arguments': { 'command-line':
- 'qemu-io source \"write -P 4 192k 64k\"' } }" \
+ "{ 'execute': 'x-qemu-io',
+ 'arguments': { 'device': 'source',
+ 'command': 'write -P 4 192k 64k' } }" \
'return'
# Copy source backing chain to the target before completing the job
@@ -133,27 +133,27 @@ echo
# Check online disk contents
_send_qemu_cmd $QEMU_HANDLE \
- "{ 'execute': 'human-monitor-command',
- 'arguments': { 'command-line':
- 'qemu-io source \"read -P 1 0k 64k\"' } }" \
+ "{ 'execute': 'x-qemu-io',
+ 'arguments': { 'device': 'source',
+ 'command': 'read -P 1 0k 64k' } }" \
'return'
_send_qemu_cmd $QEMU_HANDLE \
- "{ 'execute': 'human-monitor-command',
- 'arguments': { 'command-line':
- 'qemu-io source \"read -P 2 64k 64k\"' } }" \
+ "{ 'execute': 'x-qemu-io',
+ 'arguments': { 'device': 'source',
+ 'command': 'read -P 2 64k 64k' } }" \
'return'
_send_qemu_cmd $QEMU_HANDLE \
- "{ 'execute': 'human-monitor-command',
- 'arguments': { 'command-line':
- 'qemu-io source \"read -P 3 128k 64k\"' } }" \
+ "{ 'execute': 'x-qemu-io',
+ 'arguments': { 'device': 'source',
+ 'command': 'read -P 3 128k 64k' } }" \
'return'
_send_qemu_cmd $QEMU_HANDLE \
- "{ 'execute': 'human-monitor-command',
- 'arguments': { 'command-line':
- 'qemu-io source \"read -P 4 192k 64k\"' } }" \
+ "{ 'execute': 'x-qemu-io',
+ 'arguments': { 'device': 'source',
+ 'command': 'read -P 4 192k 64k' } }" \
'return'
echo
diff --git a/tests/qemu-iotests/156.out b/tests/qemu-iotests/156.out
index 07e5e83f5d4..5a3805746a7 100644
--- a/tests/qemu-iotests/156.out
+++ b/tests/qemu-iotests/156.out
@@ -14,12 +14,12 @@ Formatting 'TEST_DIR/t.IMGFMT.overlay', fmt=IMGFMT size=1048576 backing_file=TES
'format': 'IMGFMT',
'mode': 'existing' } }
{"return": {}}
-{ 'execute': 'human-monitor-command',
- 'arguments': { 'command-line':
- 'qemu-io source "write -P 3 128k 128k"' } }
+{ 'execute': 'x-qemu-io',
+ 'arguments': { 'device': 'source',
+ 'command': 'write -P 3 128k 128k' } }
wrote 131072/131072 bytes at offset 131072
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-{"return": ""}
+{"return": {}}
Formatting 'TEST_DIR/t.IMGFMT.target.overlay', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.target backing_fmt=IMGFMT
{ 'execute': 'drive-mirror',
'arguments': { 'device': 'source',
@@ -31,12 +31,12 @@ Formatting 'TEST_DIR/t.IMGFMT.target.overlay', fmt=IMGFMT size=1048576 backing_f
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "source"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "source", "len": 131072, "offset": 131072, "speed": 0, "type": "mirror"}}
-{ 'execute': 'human-monitor-command',
- 'arguments': { 'command-line':
- 'qemu-io source "write -P 4 192k 64k"' } }
+{ 'execute': 'x-qemu-io',
+ 'arguments': { 'device': 'source',
+ 'command': 'write -P 4 192k 64k' } }
wrote 65536/65536 bytes at offset 196608
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-{"return": ""}
+{"return": {}}
{ 'execute': 'block-job-complete',
'arguments': { 'device': 'source' } }
{"return": {}}
@@ -46,30 +46,30 @@ wrote 65536/65536 bytes at offset 196608
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "source"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "source"}}
-{ 'execute': 'human-monitor-command',
- 'arguments': { 'command-line':
- 'qemu-io source "read -P 1 0k 64k"' } }
+{ 'execute': 'x-qemu-io',
+ 'arguments': { 'device': 'source',
+ 'command': 'read -P 1 0k 64k' } }
read 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-{"return": ""}
-{ 'execute': 'human-monitor-command',
- 'arguments': { 'command-line':
- 'qemu-io source "read -P 2 64k 64k"' } }
+{"return": {}}
+{ 'execute': 'x-qemu-io',
+ 'arguments': { 'device': 'source',
+ 'command': 'read -P 2 64k 64k' } }
read 65536/65536 bytes at offset 65536
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-{"return": ""}
-{ 'execute': 'human-monitor-command',
- 'arguments': { 'command-line':
- 'qemu-io source "read -P 3 128k 64k"' } }
+{"return": {}}
+{ 'execute': 'x-qemu-io',
+ 'arguments': { 'device': 'source',
+ 'command': 'read -P 3 128k 64k' } }
read 65536/65536 bytes at offset 131072
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-{"return": ""}
-{ 'execute': 'human-monitor-command',
- 'arguments': { 'command-line':
- 'qemu-io source "read -P 4 192k 64k"' } }
+{"return": {}}
+{ 'execute': 'x-qemu-io',
+ 'arguments': { 'device': 'source',
+ 'command': 'read -P 4 192k 64k' } }
read 65536/65536 bytes at offset 196608
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-{"return": ""}
+{"return": {}}
{ 'execute': 'quit' }
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
diff --git a/tests/qemu-iotests/161 b/tests/qemu-iotests/161
index f25effab936..0f4d59b97d2 100755
--- a/tests/qemu-iotests/161
+++ b/tests/qemu-iotests/161
@@ -64,9 +64,9 @@ _send_qemu_cmd $QEMU_HANDLE \
'return'
_send_qemu_cmd $QEMU_HANDLE \
- "{ 'execute': 'human-monitor-command',
- 'arguments': { 'command-line':
- 'qemu-io none0 \"reopen -o backing.detect-zeroes=on\"' } }" \
+ "{ 'execute': 'x-qemu-io',
+ 'arguments': { 'device': 'none0',
+ 'command': 'reopen -o backing.detect-zeroes=on' } }" \
"return"
_cleanup_qemu
@@ -92,9 +92,9 @@ _send_qemu_cmd $QEMU_HANDLE \
sleep 0.5
_send_qemu_cmd $QEMU_HANDLE \
- "{ 'execute': 'human-monitor-command',
- 'arguments': { 'command-line':
- 'qemu-io none0 \"reopen -o backing.detect-zeroes=on\"' } }" \
+ "{ 'execute': 'x-qemu-io',
+ 'arguments': { 'device': 'none0',
+ 'command': 'reopen -o backing.detect-zeroes=on' } }" \
"return"
_cleanup_qemu
@@ -125,9 +125,9 @@ _send_qemu_cmd $QEMU_HANDLE \
sleep 0.5
_send_qemu_cmd $QEMU_HANDLE \
- "{ 'execute': 'human-monitor-command',
- 'arguments': { 'command-line':
- 'qemu-io none0 \"reopen -o backing.detect-zeroes=on\"' } }" \
+ "{ 'execute': 'x-qemu-io',
+ 'arguments': { 'device': 'none0',
+ 'command': 'reopen -o backing.detect-zeroes=on' } }" \
"return"
_cleanup_qemu
diff --git a/tests/qemu-iotests/161.out b/tests/qemu-iotests/161.out
index 6cc285afcfd..0975bc288bf 100644
--- a/tests/qemu-iotests/161.out
+++ b/tests/qemu-iotests/161.out
@@ -7,10 +7,10 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.
{ 'execute': 'qmp_capabilities' }
{"return": {}}
-{ 'execute': 'human-monitor-command',
- 'arguments': { 'command-line':
- 'qemu-io none0 "reopen -o backing.detect-zeroes=on"' } }
-{"return": ""}
+{ 'execute': 'x-qemu-io',
+ 'arguments': { 'device': 'none0',
+ 'command': 'reopen -o backing.detect-zeroes=on' } }
+{"return": {}}
*** Stream and then change an option on the backing file
@@ -21,15 +21,15 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "none0"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "none0"}}
{"return": {}}
-{ 'execute': 'human-monitor-command',
- 'arguments': { 'command-line':
- 'qemu-io none0 "reopen -o backing.detect-zeroes=on"' } }
+{ 'execute': 'x-qemu-io',
+ 'arguments': { 'device': 'none0',
+ 'command': 'reopen -o backing.detect-zeroes=on' } }
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "none0"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "none0"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "none0", "len": 1048576, "offset": 1048576, "speed": 0, "type": "stream"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "none0"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "none0"}}
-{"return": ""}
+{"return": {}}
*** Commit and then change an option on the backing file
@@ -43,13 +43,13 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "none0"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "none0"}}
{"return": {}}
-{ 'execute': 'human-monitor-command',
- 'arguments': { 'command-line':
- 'qemu-io none0 "reopen -o backing.detect-zeroes=on"' } }
+{ 'execute': 'x-qemu-io',
+ 'arguments': { 'device': 'none0',
+ 'command': 'reopen -o backing.detect-zeroes=on' } }
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "none0"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "none0"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "none0", "len": 1048576, "offset": 1048576, "speed": 0, "type": "commit"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "none0"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "none0"}}
-{"return": ""}
+{"return": {}}
*** done
diff --git a/tests/qemu-iotests/249 b/tests/qemu-iotests/249
index 28bffd4d571..16cf6c2d8c4 100755
--- a/tests/qemu-iotests/249
+++ b/tests/qemu-iotests/249
@@ -67,8 +67,8 @@ echo
echo '=== Send a write command to a drive opened in read-only mode (1)'
echo
_send_qemu_cmd $QEMU_HANDLE \
- "{ 'execute': 'human-monitor-command',
- 'arguments': {'command-line': 'qemu-io none0 \"aio_write 0 2k\"'}}" \
+ "{ 'execute': 'x-qemu-io',
+ 'arguments': {'device': 'none0', 'command': 'aio_write 0 2k'}}" \
'return'
echo
@@ -84,8 +84,8 @@ echo
echo '=== Send a write command to a drive opened in read-only mode (2)'
echo
_send_qemu_cmd $QEMU_HANDLE \
- "{ 'execute': 'human-monitor-command',
- 'arguments': {'command-line': 'qemu-io none0 \"aio_write 0 2k\"'}}" \
+ "{ 'execute': 'x-qemu-io',
+ 'arguments': {'device': 'none0', 'command': 'aio_write 0 2k'}}" \
'return'
echo
@@ -104,8 +104,8 @@ echo
echo '=== Send a write command to a drive opened in read-only mode (3)'
echo
_send_qemu_cmd $QEMU_HANDLE \
- "{ 'execute': 'human-monitor-command',
- 'arguments': {'command-line': 'qemu-io none0 \"aio_write 0 2k\"'}}" \
+ "{ 'execute': 'x-qemu-io',
+ 'arguments': {'device': 'none0', 'command': 'aio_write 0 2k'}}" \
'return'
_cleanup_qemu
diff --git a/tests/qemu-iotests/249.out b/tests/qemu-iotests/249.out
index 3d37709a9ef..79f69cd2651 100644
--- a/tests/qemu-iotests/249.out
+++ b/tests/qemu-iotests/249.out
@@ -7,9 +7,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.
=== Send a write command to a drive opened in read-only mode (1)
-{ 'execute': 'human-monitor-command',
- 'arguments': {'command-line': 'qemu-io none0 "aio_write 0 2k"'}}
-{"return": "Error: Block node is read-onlyrn"}
+{ 'execute': 'x-qemu-io',
+ 'arguments': {'device': 'none0', 'command': 'aio_write 0 2k'}}
+{"error": {"class": "GenericError", "desc": "Block node is read-only"}}
=== Run block-commit on base using an invalid filter node name
@@ -22,9 +22,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.
=== Send a write command to a drive opened in read-only mode (2)
-{ 'execute': 'human-monitor-command',
- 'arguments': {'command-line': 'qemu-io none0 "aio_write 0 2k"'}}
-{"return": "Error: Block node is read-onlyrn"}
+{ 'execute': 'x-qemu-io',
+ 'arguments': {'device': 'none0', 'command': 'aio_write 0 2k'}}
+{"error": {"class": "GenericError", "desc": "Block node is read-only"}}
=== Run block-commit on base using the default filter node name
@@ -41,7 +41,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.
=== Send a write command to a drive opened in read-only mode (3)
-{ 'execute': 'human-monitor-command',
- 'arguments': {'command-line': 'qemu-io none0 "aio_write 0 2k"'}}
-{"return": "Error: Block node is read-onlyrn"}
+{ 'execute': 'x-qemu-io',
+ 'arguments': {'device': 'none0', 'command': 'aio_write 0 2k'}}
+{"error": {"class": "GenericError", "desc": "Block node is read-only"}}
*** done
diff --git a/tests/qemu-iotests/283 b/tests/qemu-iotests/283
index 5defe48e97d..655a2113341 100755
--- a/tests/qemu-iotests/283
+++ b/tests/qemu-iotests/283
@@ -136,8 +136,8 @@ vm.event_wait('BLOCK_JOB_COMPLETED', 5.0)
# The filter should be gone now. Check that by trying to access it
# with qemu-io (which will most likely crash qemu if it is still
# there.).
-vm.qmp_log('human-monitor-command',
- command_line='qemu-io backup-filter "write 0 1M"')
+vm.qmp_log('x-qemu-io',
+ device='backup-filter', command='write 0 1M')
# (Also, do an explicit check.)
assert vm.node_info('backup-filter') is None
diff --git a/tests/qemu-iotests/283.out b/tests/qemu-iotests/283.out
index 5e4f456db55..1c12c8fad7d 100644
--- a/tests/qemu-iotests/283.out
+++ b/tests/qemu-iotests/283.out
@@ -17,7 +17,7 @@
{"return": {}}
{"execute": "job-finalize", "arguments": {"id": "backup"}}
{"return": {}}
-{"execute": "human-monitor-command", "arguments": {"command-line": "qemu-io backup-filter \"write 0 1M\""}}
-{"return": "Error: Cannot find device='' nor node-name='backup-filter'\r\n"}
+{"execute": "x-qemu-io", "arguments": {"command": "write 0 1M", "device": "backup-filter"}}
+{"error": {"class": "GenericError", "desc": "Cannot find device='' nor node-name='backup-filter'"}}
{"execute": "job-dismiss", "arguments": {"id": "backup"}}
{"return": {}}
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 17/40] tests/qemu-iotests/181, 192, 249: convert to QMP
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (15 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 16/40] tests/qemu-iotests/N: use " Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 18/40] tests/qemu-iotests/186: convert from HMP " Marc-André Lureau
` (23 subsequent siblings)
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Convert tests 181 and 192 from HMP monitor commands to QMP:
- Remove qemu_comm_method="monitor" and add qmp_capabilities
negotiation.
- Replace HMP commands (qemu-io, migrate_set_capability,
migrate_set_parameter, migrate, info migrate, nbd_server_start,
nbd_server_add, quit) with their QMP equivalents (x-qemu-io,
migrate-set-capabilities, migrate-set-parameters, migrate,
query-migrate, nbd-server-start, nbd-server-add, quit).
Unlike human-monitor-command which wraps errors inside
{"return": "Error: ..."}, x-qemu-io returns errors as a proper QMP
{"error": ...} response. Match 'return\|error' on x-qemu-io calls so
the test terminates on both success and failure, rather than hanging
until timeout. Apply the same fix to test 249.
Remove the HMP output drain idiom (send empty command, wait for
prompt) after query-migrate polling in test 181. In QMP, an empty line
produces no response, so this would hang.
Capture the RESUME event delivered on the destination QMP channel after
postcopy migration completes. This event was not visible in HMP mode.
Update expected output for all three tests.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
tests/qemu-iotests/181 | 99 ++++++++++++++++++++++++++++++++++------------
tests/qemu-iotests/181.out | 36 ++++++++++++-----
tests/qemu-iotests/192 | 22 +++++++++--
tests/qemu-iotests/192.out | 17 ++++++--
tests/qemu-iotests/249 | 6 +--
5 files changed, 134 insertions(+), 46 deletions(-)
diff --git a/tests/qemu-iotests/181 b/tests/qemu-iotests/181
index dc90a10757f..3de24090c68 100755
--- a/tests/qemu-iotests/181
+++ b/tests/qemu-iotests/181
@@ -55,8 +55,6 @@ echo
echo === Starting VMs ===
echo
-qemu_comm_method="monitor"
-
if [ "$IMGOPTSSYNTAX" = "true" ]; then
_launch_qemu \
-drive "${TEST_IMG}",cache=${CACHEMODE},aio=$AIOMODE,id=disk
@@ -77,15 +75,30 @@ else
fi
dest=$QEMU_HANDLE
+_send_qemu_cmd $src \
+ "{ 'execute': 'qmp_capabilities' }" \
+ 'return'
+
+_send_qemu_cmd $dest \
+ "{ 'execute': 'qmp_capabilities' }" \
+ 'return'
+
echo
echo === Write something on the source ===
echo
silent=
-_send_qemu_cmd $src 'qemu-io disk "write -P 0x55 0 64k"' "(qemu)"
-_send_qemu_cmd $src "" "ops/sec"
-_send_qemu_cmd $src 'qemu-io disk "read -P 0x55 0 64k"' "(qemu)"
-_send_qemu_cmd $src "" "ops/sec"
+_send_qemu_cmd $src \
+ "{ 'execute': 'x-qemu-io',
+ 'arguments': { 'device': 'disk',
+ 'command': 'write -P 0x55 0 64k' } }" \
+ 'return\|error'
+
+_send_qemu_cmd $src \
+ "{ 'execute': 'x-qemu-io',
+ 'arguments': { 'device': 'disk',
+ 'command': 'read -P 0x55 0 64k' } }" \
+ 'return\|error'
echo
echo === Do postcopy migration to destination ===
@@ -95,28 +108,49 @@ echo
# switch to postcopy
# Enable postcopy-ram capability both on source and destination
silent=yes
-_send_qemu_cmd $dest 'migrate_set_capability postcopy-ram on' "(qemu)"
-
qemu_error_no_exit=yes success_or_failure=yes \
- _send_qemu_cmd $dest '' "(qemu)" "Postcopy is not supported"
-if [ ${QEMU_STATUS[$dest]} -lt 0 ]; then
- _send_qemu_cmd $dest '' "(qemu)"
+ _send_qemu_cmd $dest \
+ "{ 'execute': 'migrate-set-capabilities',
+ 'arguments': { 'capabilities': [
+ { 'capability': 'postcopy-ram', 'state': true } ] } }" \
+ 'return' 'error'
- _send_qemu_cmd $src 'quit' ""
- _send_qemu_cmd $dest 'quit' ""
+if [ ${QEMU_STATUS[$dest]} -lt 0 ]; then
+ _send_qemu_cmd $src \
+ "{ 'execute': 'quit' }" \
+ 'return'
+ _send_qemu_cmd $dest \
+ "{ 'execute': 'quit' }" \
+ 'return'
wait=1 _cleanup_qemu
_notrun 'Postcopy is not supported'
fi
-_send_qemu_cmd $src 'migrate_set_parameter max-bandwidth 4k' "(qemu)"
-_send_qemu_cmd $src 'migrate_set_capability postcopy-ram on' "(qemu)"
-_send_qemu_cmd $src "migrate -d unix:${MIG_SOCKET}" "(qemu)"
-_send_qemu_cmd $src 'migrate_start_postcopy' "(qemu)"
+_send_qemu_cmd $src \
+ "{ 'execute': 'migrate-set-parameters',
+ 'arguments': { 'max-bandwidth': 4096 } }" \
+ 'return'
+
+_send_qemu_cmd $src \
+ "{ 'execute': 'migrate-set-capabilities',
+ 'arguments': { 'capabilities': [
+ { 'capability': 'postcopy-ram', 'state': true } ] } }" \
+ 'return'
+
+_send_qemu_cmd $src \
+ "{ 'execute': 'migrate',
+ 'arguments': { 'uri': 'unix:${MIG_SOCKET}' } }" \
+ 'return'
+
+_send_qemu_cmd $src \
+ "{ 'execute': 'migrate-start-postcopy' }" \
+ 'return'
QEMU_COMM_TIMEOUT=1 qemu_cmd_repeat=10 silent=yes \
- _send_qemu_cmd $src "info migrate" "completed\|failed"
-silent=yes _send_qemu_cmd $src "" "(qemu)"
+ _send_qemu_cmd $src \
+ "{ 'execute': 'query-migrate' }" \
+ "completed\|failed"
echo
echo === Do some I/O on the destination ===
@@ -126,17 +160,32 @@ echo
# of the node name, which would create a new BlockBackend and not test whether
# the guest has the necessary permissions to access the image now
silent=
-_send_qemu_cmd $dest 'qemu-io disk "read -P 0x55 0 64k"' "(qemu)"
-_send_qemu_cmd $dest "" "ops/sec"
-_send_qemu_cmd $dest 'qemu-io disk "write -P 0x66 1M 64k"' "(qemu)"
-_send_qemu_cmd $dest "" "ops/sec"
+capture_events="RESUME"
+_send_qemu_cmd $dest \
+ "{ 'execute': 'x-qemu-io',
+ 'arguments': { 'device': 'disk',
+ 'command': 'read -P 0x55 0 64k' } }" \
+ 'return\|error'
+capture_events=
+
+_send_qemu_cmd $dest \
+ "{ 'execute': 'x-qemu-io',
+ 'arguments': { 'device': 'disk',
+ 'command': 'write -P 0x66 1M 64k' } }" \
+ 'return\|error'
echo
echo === Shut down and check image ===
echo
-_send_qemu_cmd $src 'quit' ""
-_send_qemu_cmd $dest 'quit' ""
+_send_qemu_cmd $src \
+ "{ 'execute': 'quit' }" \
+ 'return'
+
+_send_qemu_cmd $dest \
+ "{ 'execute': 'quit' }" \
+ 'return'
+
wait=1 _cleanup_qemu
_check_test_img
diff --git a/tests/qemu-iotests/181.out b/tests/qemu-iotests/181.out
index d58c6a9dabb..ddcce564699 100644
--- a/tests/qemu-iotests/181.out
+++ b/tests/qemu-iotests/181.out
@@ -3,35 +3,51 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
=== Starting VMs ===
+{ 'execute': 'qmp_capabilities' }
+{"return": {}}
+{ 'execute': 'qmp_capabilities' }
+{"return": {}}
=== Write something on the source ===
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) qemu-io disk "write -P 0x55 0 64k"
+{ 'execute': 'x-qemu-io',
+ 'arguments': { 'device': 'disk',
+ 'command': 'write -P 0x55 0 64k' } }
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-(qemu)
-(qemu) qemu-io disk "read -P 0x55 0 64k"
+{"return": {}}
+{ 'execute': 'x-qemu-io',
+ 'arguments': { 'device': 'disk',
+ 'command': 'read -P 0x55 0 64k' } }
read 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+{"return": {}}
=== Do postcopy migration to destination ===
=== Do some I/O on the destination ===
-(qemu) qemu-io disk "read -P 0x55 0 64k"
+{ 'execute': 'x-qemu-io',
+ 'arguments': { 'device': 'disk',
+ 'command': 'read -P 0x55 0 64k' } }
read 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-(qemu)
-(qemu) qemu-io disk "write -P 0x66 1M 64k"
+{"return": {}}
+{ 'execute': 'x-qemu-io',
+ 'arguments': { 'device': 'disk',
+ 'command': 'write -P 0x66 1M 64k' } }
wrote 65536/65536 bytes at offset 1048576
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+{"return": {}}
=== Shut down and check image ===
-(qemu) quit
-(qemu)
-(qemu) quit
+{ 'execute': 'quit' }
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
+{ 'execute': 'quit' }
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"return": {}}
No errors were found on the image.
*** done
diff --git a/tests/qemu-iotests/192 b/tests/qemu-iotests/192
index e66e1a4f06a..ea89cffe107 100755
--- a/tests/qemu-iotests/192
+++ b/tests/qemu-iotests/192
@@ -58,7 +58,6 @@ else
DRIVE_ARG=if=ide,id=drive0,format=$IMGFMT,file=$TEST_IMG
fi
-qemu_comm_method="monitor"
_launch_qemu -drive $DRIVE_ARG -incoming defer
h=$QEMU_HANDLE
if [ "${VALGRIND_QEMU}" == "y" ]; then
@@ -67,9 +66,24 @@ else
QEMU_COMM_TIMEOUT=1
fi
-_send_qemu_cmd $h "nbd_server_start unix:$SOCK_DIR/nbd" "(qemu)"
-_send_qemu_cmd $h "nbd_server_add -w drive0" "(qemu)"
-_send_qemu_cmd $h "q" "(qemu)"
+_send_qemu_cmd $h \
+ "{ 'execute': 'qmp_capabilities' }" \
+ 'return'
+
+_send_qemu_cmd $h \
+ "{ 'execute': 'nbd-server-start',
+ 'arguments': { 'addr': { 'type': 'unix',
+ 'data': { 'path': '$SOCK_DIR/nbd' } } } }" \
+ 'return'
+
+_send_qemu_cmd $h \
+ "{ 'execute': 'nbd-server-add',
+ 'arguments': { 'device': 'drive0', 'writable': true } }" \
+ 'return'
+
+_send_qemu_cmd $h \
+ "{ 'execute': 'quit' }" \
+ 'return'
# success, all done
echo "*** done"
diff --git a/tests/qemu-iotests/192.out b/tests/qemu-iotests/192.out
index b9429dbe367..88185a2e8ff 100644
--- a/tests/qemu-iotests/192.out
+++ b/tests/qemu-iotests/192.out
@@ -1,7 +1,16 @@
QA output created by 192
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) nbd_server_start unix:SOCK_DIR/nbd
-(qemu) nbd_server_add -w drive0
-(qemu) q
+{ 'execute': 'qmp_capabilities' }
+{"return": {}}
+{ 'execute': 'nbd-server-start',
+ 'arguments': { 'addr': { 'type': 'unix',
+ 'data': { 'path': 'SOCK_DIR/nbd' } } } }
+{"return": {}}
+{ 'execute': 'nbd-server-add',
+ 'arguments': { 'device': 'drive0', 'writable': true } }
+{"return": {}}
+{ 'execute': 'quit' }
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "drive0"}}
+{"return": {}}
*** done
diff --git a/tests/qemu-iotests/249 b/tests/qemu-iotests/249
index 16cf6c2d8c4..d30a2ac6bc8 100755
--- a/tests/qemu-iotests/249
+++ b/tests/qemu-iotests/249
@@ -69,7 +69,7 @@ echo
_send_qemu_cmd $QEMU_HANDLE \
"{ 'execute': 'x-qemu-io',
'arguments': {'device': 'none0', 'command': 'aio_write 0 2k'}}" \
- 'return'
+ 'return\|error'
echo
echo '=== Run block-commit on base using an invalid filter node name'
@@ -86,7 +86,7 @@ echo
_send_qemu_cmd $QEMU_HANDLE \
"{ 'execute': 'x-qemu-io',
'arguments': {'device': 'none0', 'command': 'aio_write 0 2k'}}" \
- 'return'
+ 'return\|error'
echo
echo '=== Run block-commit on base using the default filter node name'
@@ -106,7 +106,7 @@ echo
_send_qemu_cmd $QEMU_HANDLE \
"{ 'execute': 'x-qemu-io',
'arguments': {'device': 'none0', 'command': 'aio_write 0 2k'}}" \
- 'return'
+ 'return\|error'
_cleanup_qemu
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 18/40] tests/qemu-iotests/186: convert from HMP to QMP
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (16 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 17/40] tests/qemu-iotests/181, 192, 249: convert to QMP Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 19/40] tests/qemu-iotests/copy-before-write: convert " Marc-André Lureau
` (22 subsequent siblings)
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Replace HMP 'info block' with QMP 'query-block' so the test works
with --disable-hmp builds. Use -qmp stdio instead of -monitor stdio,
send JSON commands via printf, and filter with _filter_qmp and
_filter_qmp_empty_return instead of _filter_hmp.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
tests/qemu-iotests/186 | 20 +--
tests/qemu-iotests/186.out | 440 +++++++++++----------------------------------
2 files changed, 108 insertions(+), 352 deletions(-)
diff --git a/tests/qemu-iotests/186 b/tests/qemu-iotests/186
index eaf13c7a334..fa77319614b 100755
--- a/tests/qemu-iotests/186
+++ b/tests/qemu-iotests/186
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
# group: rw auto
#
-# Test 'info block' with all kinds of configurations
+# Test 'query-block' with all kinds of configurations
#
# Copyright (C) 2017 Red Hat, Inc.
#
@@ -50,22 +50,18 @@ do_run_qemu()
{
echo Testing: "$@"
- (
- if ! test -t 0; then
- while read cmd; do
- echo $cmd
- done
- fi
- echo quit
- ) | $QEMU -S -display none -device virtio-scsi-pci -monitor stdio "$@" 2>&1
+ printf '{"execute":"qmp_capabilities"}\n{"execute":"query-block"}\n{"execute":"quit"}\n' |
+ $QEMU -S -display none -device virtio-scsi-pci -monitor none -qmp stdio "$@" 2>&1
echo
}
check_info_block()
{
- echo "info block" |
- do_run_qemu "$@" | _filter_win32 | _filter_hmp | _filter_qemu |
- _filter_generated_node_ids | _filter_qom_path
+ do_run_qemu "$@" | _filter_win32 | _filter_qemu | _filter_qmp |
+ _filter_qmp_empty_return |
+ grep -v '"event"' |
+ _filter_generated_node_ids |
+ sed 's/device\[[0-9]\+\]/device[N]/g'
}
diff --git a/tests/qemu-iotests/186.out b/tests/qemu-iotests/186.out
index 01530040e5f..952b0c7a0a0 100644
--- a/tests/qemu-iotests/186.out
+++ b/tests/qemu-iotests/186.out
@@ -4,458 +4,218 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
=== Empty drives ===
Testing: -device floppy
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-/machine/peripheral-anon/device[1]: [not inserted]
- Attached to: /machine/peripheral-anon/device[N]
- Removable device: not locked, tray closed
-(qemu) quit
+QMP_VERSION
+{"return": [{"device": "", "locked": false, "removable": true, "qdev": "/machine/peripheral-anon/device[N]", "type": "unknown"}]}
Testing: -device floppy,id=qdev_id
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-qdev_id: [not inserted]
- Attached to: qdev_id
- Removable device: not locked, tray closed
-(qemu) quit
+QMP_VERSION
+{"return": [{"device": "", "locked": false, "removable": true, "qdev": "qdev_id", "type": "unknown"}]}
Testing: -device ide-cd
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-/machine/peripheral-anon/device[1]: [not inserted]
- Attached to: /machine/peripheral-anon/device[N]
- Removable device: not locked, tray closed
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "", "locked": false, "removable": true, "qdev": "/machine/peripheral-anon/device[N]", "tray_open": false, "type": "unknown"}]}
Testing: -device ide-cd,id=qdev_id
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-qdev_id: [not inserted]
- Attached to: qdev_id
- Removable device: not locked, tray closed
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "", "locked": false, "removable": true, "qdev": "qdev_id", "tray_open": false, "type": "unknown"}]}
Testing: -device scsi-cd
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-/machine/peripheral-anon/device[1]: [not inserted]
- Attached to: /machine/peripheral-anon/device[N]
- Removable device: not locked, tray closed
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "", "locked": false, "removable": true, "qdev": "/machine/peripheral-anon/device[N]", "tray_open": false, "type": "unknown"}]}
Testing: -device scsi-cd,id=qdev_id
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-qdev_id: [not inserted]
- Attached to: qdev_id
- Removable device: not locked, tray closed
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "", "locked": false, "removable": true, "qdev": "qdev_id", "tray_open": false, "type": "unknown"}]}
=== -blockdev/-device=<node-name> ===
Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device ide-hd,drive=null
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-null: json:{"read-zeroes": true, "driver": "null-co"} (null-co)
- Attached to: /machine/peripheral-anon/device[N]
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "", "locked": false, "removable": false, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": true, \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": true, \"driver\": \"null-co\"}"}, "qdev": "/machine/peripheral-anon/device[N]", "type": "unknown"}]}
Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device ide-hd,drive=null,id=qdev_id
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-null: json:{"read-zeroes": true, "driver": "null-co"} (null-co)
- Attached to: qdev_id
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "", "locked": false, "removable": false, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": true, \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": true, \"driver\": \"null-co\"}"}, "qdev": "qdev_id", "type": "unknown"}]}
Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device scsi-hd,drive=null
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-null: json:{"read-zeroes": true, "driver": "null-co"} (null-co)
- Attached to: /machine/peripheral-anon/device[N]
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "", "locked": false, "removable": false, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": true, \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": true, \"driver\": \"null-co\"}"}, "qdev": "/machine/peripheral-anon/device[N]", "type": "unknown"}]}
Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device scsi-hd,drive=null,id=qdev_id
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-null: json:{"read-zeroes": true, "driver": "null-co"} (null-co)
- Attached to: qdev_id
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "", "locked": false, "removable": false, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": true, \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": true, \"driver\": \"null-co\"}"}, "qdev": "qdev_id", "type": "unknown"}]}
Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device virtio-blk-pci,drive=null
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-null: json:{"read-zeroes": true, "driver": "null-co"} (null-co)
- Attached to: /machine/peripheral-anon/device[N]/virtio-backend
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "", "locked": false, "removable": false, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": true, \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": true, \"driver\": \"null-co\"}"}, "qdev": "/machine/peripheral-anon/device[N]/virtio-backend", "type": "unknown"}]}
Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device virtio-blk-pci,drive=null,id=qdev_id
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-null: json:{"read-zeroes": true, "driver": "null-co"} (null-co)
- Attached to: /machine/peripheral/qdev_id/virtio-backend
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "", "locked": false, "removable": false, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": true, \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": true, \"driver\": \"null-co\"}"}, "qdev": "/machine/peripheral/qdev_id/virtio-backend", "type": "unknown"}]}
Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device floppy,drive=null
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-null: json:{"read-zeroes": true, "driver": "null-co"} (null-co)
- Attached to: /machine/peripheral-anon/device[N]
- Removable device: not locked, tray closed
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"device": "", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": true, \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": true, \"driver\": \"null-co\"}"}, "qdev": "/machine/peripheral-anon/device[N]", "type": "unknown"}]}
Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device floppy,drive=null,id=qdev_id
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-null: json:{"read-zeroes": true, "driver": "null-co"} (null-co)
- Attached to: qdev_id
- Removable device: not locked, tray closed
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"device": "", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": true, \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": true, \"driver\": \"null-co\"}"}, "qdev": "qdev_id", "type": "unknown"}]}
Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device ide-cd,drive=null
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-null: json:{"read-zeroes": true, "driver": "null-co"} (null-co)
- Attached to: /machine/peripheral-anon/device[N]
- Removable device: not locked, tray closed
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": true, \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": true, \"driver\": \"null-co\"}"}, "qdev": "/machine/peripheral-anon/device[N]", "tray_open": false, "type": "unknown"}]}
Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device ide-cd,drive=null,id=qdev_id
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-null: json:{"read-zeroes": true, "driver": "null-co"} (null-co)
- Attached to: qdev_id
- Removable device: not locked, tray closed
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": true, \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": true, \"driver\": \"null-co\"}"}, "qdev": "qdev_id", "tray_open": false, "type": "unknown"}]}
Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device scsi-cd,drive=null
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-null: json:{"read-zeroes": true, "driver": "null-co"} (null-co)
- Attached to: /machine/peripheral-anon/device[N]
- Removable device: not locked, tray closed
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": true, \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": true, \"driver\": \"null-co\"}"}, "qdev": "/machine/peripheral-anon/device[N]", "tray_open": false, "type": "unknown"}]}
Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device scsi-cd,drive=null,id=qdev_id
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-null: json:{"read-zeroes": true, "driver": "null-co"} (null-co)
- Attached to: qdev_id
- Removable device: not locked, tray closed
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": true, \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": true, \"driver\": \"null-co\"}"}, "qdev": "qdev_id", "tray_open": false, "type": "unknown"}]}
=== -drive if=none/-device=<node-name> ===
Testing: -drive if=none,driver=null-co,read-zeroes=on,node-name=null -device ide-hd,drive=null,id=qdev_id
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-none0 (null): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Removable device: not locked, tray closed
- Cache mode: writeback
-
-null: json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: qdev_id
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"device": "none0", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}"}, "type": "unknown"}, {"io-status": "ok", "device": "", "locked": false, "removable": false, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "vi
rtual-size": 1073741824, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}"}, "qdev": "qdev_id", "type": "unknown"}]}
Testing: -drive if=none,driver=null-co,read-zeroes=on,node-name=null -device scsi-hd,drive=null,id=qdev_id
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-none0 (null): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Removable device: not locked, tray closed
- Cache mode: writeback
-
-null: json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: qdev_id
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"device": "none0", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}"}, "type": "unknown"}, {"io-status": "ok", "device": "", "locked": false, "removable": false, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "vi
rtual-size": 1073741824, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}"}, "qdev": "qdev_id", "type": "unknown"}]}
Testing: -drive if=none,driver=null-co,read-zeroes=on,node-name=null -device virtio-blk-pci,drive=null,id=qdev_id
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-none0 (null): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Removable device: not locked, tray closed
- Cache mode: writeback
-
-null: json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: /machine/peripheral/qdev_id/virtio-backend
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"device": "none0", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}"}, "type": "unknown"}, {"io-status": "ok", "device": "", "locked": false, "removable": false, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "vi
rtual-size": 1073741824, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}"}, "qdev": "/machine/peripheral/qdev_id/virtio-backend", "type": "unknown"}]}
Testing: -drive if=none,driver=null-co,read-zeroes=on,node-name=null -device floppy,drive=null,id=qdev_id
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-none0 (null): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Removable device: not locked, tray closed
- Cache mode: writeback
-
-null: json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: qdev_id
- Removable device: not locked, tray closed
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"device": "none0", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}"}, "type": "unknown"}, {"device": "", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741
824, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}"}, "qdev": "qdev_id", "type": "unknown"}]}
Testing: -drive if=none,driver=null-co,read-zeroes=on,node-name=null -device ide-cd,drive=null,id=qdev_id
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-none0 (null): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Removable device: not locked, tray closed
- Cache mode: writeback
-
-null: json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: qdev_id
- Removable device: not locked, tray closed
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"device": "none0", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}"}, "type": "unknown"}, {"io-status": "ok", "device": "", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "vir
tual-size": 1073741824, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}"}, "qdev": "qdev_id", "tray_open": false, "type": "unknown"}]}
Testing: -drive if=none,driver=null-co,read-zeroes=on,node-name=null -device scsi-cd,drive=null,id=qdev_id
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-none0 (null): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Removable device: not locked, tray closed
- Cache mode: writeback
-
-null: json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: qdev_id
- Removable device: not locked, tray closed
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"device": "none0", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}"}, "type": "unknown"}, {"io-status": "ok", "device": "", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "vir
tual-size": 1073741824, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}"}, "qdev": "qdev_id", "tray_open": false, "type": "unknown"}]}
=== -drive if=none/-device=<bb-name> (with medium) ===
Testing: -drive if=none,driver=null-co,read-zeroes=on,node-name=null -device ide-hd,drive=none0
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-none0 (null): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: /machine/peripheral-anon/device[N]
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "none0", "locked": false, "removable": false, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}"}, "qdev": "/machine/peripheral-anon/device[N]", "type": "unknown"}]}
Testing: -drive if=none,driver=null-co,read-zeroes=on,node-name=null -device ide-hd,drive=none0,id=qdev_id
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-none0 (null): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: qdev_id
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "none0", "locked": false, "removable": false, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}"}, "qdev": "qdev_id", "type": "unknown"}]}
Testing: -drive if=none,driver=null-co,read-zeroes=on,node-name=null -device scsi-hd,drive=none0
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-none0 (null): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: /machine/peripheral-anon/device[N]
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "none0", "locked": false, "removable": false, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}"}, "qdev": "/machine/peripheral-anon/device[N]", "type": "unknown"}]}
Testing: -drive if=none,driver=null-co,read-zeroes=on,node-name=null -device scsi-hd,drive=none0,id=qdev_id
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-none0 (null): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: qdev_id
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "none0", "locked": false, "removable": false, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}"}, "qdev": "qdev_id", "type": "unknown"}]}
Testing: -drive if=none,driver=null-co,read-zeroes=on,node-name=null -device virtio-blk-pci,drive=none0
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-none0 (null): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: /machine/peripheral-anon/device[N]/virtio-backend
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "none0", "locked": false, "removable": false, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}"}, "qdev": "/machine/peripheral-anon/device[N]/virtio-backend", "type": "unknown"}]}
Testing: -drive if=none,driver=null-co,read-zeroes=on,node-name=null -device virtio-blk-pci,drive=none0,id=qdev_id
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-none0 (null): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: /machine/peripheral/qdev_id/virtio-backend
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "none0", "locked": false, "removable": false, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}"}, "qdev": "/machine/peripheral/qdev_id/virtio-backend", "type": "unknown"}]}
Testing: -drive if=none,driver=null-co,read-zeroes=on,node-name=null -device floppy,drive=none0
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-none0 (null): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: /machine/peripheral-anon/device[N]
- Removable device: not locked, tray closed
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"device": "none0", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}"}, "qdev": "/machine/peripheral-anon/device[N]", "type": "unknown"}]}
Testing: -drive if=none,driver=null-co,read-zeroes=on,node-name=null -device floppy,drive=none0,id=qdev_id
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-none0 (null): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: qdev_id
- Removable device: not locked, tray closed
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"device": "none0", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}"}, "qdev": "qdev_id", "type": "unknown"}]}
Testing: -drive if=none,driver=null-co,read-zeroes=on,node-name=null -device ide-cd,drive=none0
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-none0 (null): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: /machine/peripheral-anon/device[N]
- Removable device: not locked, tray closed
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "none0", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}"}, "qdev": "/machine/peripheral-anon/device[N]", "tray_open": false, "type": "unknown"}]}
Testing: -drive if=none,driver=null-co,read-zeroes=on,node-name=null -device ide-cd,drive=none0,id=qdev_id
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-none0 (null): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: qdev_id
- Removable device: not locked, tray closed
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "none0", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}"}, "qdev": "qdev_id", "tray_open": false, "type": "unknown"}]}
Testing: -drive if=none,driver=null-co,read-zeroes=on,node-name=null -device scsi-cd,drive=none0
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-none0 (null): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: /machine/peripheral-anon/device[N]
- Removable device: not locked, tray closed
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "none0", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}"}, "qdev": "/machine/peripheral-anon/device[N]", "tray_open": false, "type": "unknown"}]}
Testing: -drive if=none,driver=null-co,read-zeroes=on,node-name=null -device scsi-cd,drive=none0,id=qdev_id
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-none0 (null): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: qdev_id
- Removable device: not locked, tray closed
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "none0", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "null", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}"}, "qdev": "qdev_id", "tray_open": false, "type": "unknown"}]}
=== -drive if=none/-device=<bb-name> (without medium) ===
Testing: -drive if=none
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-none0: [not inserted]
- Removable device: not locked, tray closed
-(qemu) quit
+QMP_VERSION
+{"return": [{"device": "none0", "locked": false, "removable": true, "type": "unknown"}]}
Testing: -drive if=none -device floppy,drive=none0
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-none0: [not inserted]
- Attached to: /machine/peripheral-anon/device[N]
- Removable device: not locked, tray closed
-(qemu) quit
+QMP_VERSION
+{"return": [{"device": "none0", "locked": false, "removable": true, "qdev": "/machine/peripheral-anon/device[N]", "type": "unknown"}]}
Testing: -drive if=none -device floppy,drive=none0,id=qdev_id
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-none0: [not inserted]
- Attached to: qdev_id
- Removable device: not locked, tray closed
-(qemu) quit
+QMP_VERSION
+{"return": [{"device": "none0", "locked": false, "removable": true, "qdev": "qdev_id", "type": "unknown"}]}
Testing: -drive if=none -device ide-cd,drive=none0
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-none0: [not inserted]
- Attached to: /machine/peripheral-anon/device[N]
- Removable device: not locked, tray closed
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "none0", "locked": false, "removable": true, "qdev": "/machine/peripheral-anon/device[N]", "tray_open": false, "type": "unknown"}]}
Testing: -drive if=none -device ide-cd,drive=none0,id=qdev_id
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-none0: [not inserted]
- Attached to: qdev_id
- Removable device: not locked, tray closed
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "none0", "locked": false, "removable": true, "qdev": "qdev_id", "tray_open": false, "type": "unknown"}]}
Testing: -drive if=none -device scsi-cd,drive=none0
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-none0: [not inserted]
- Attached to: /machine/peripheral-anon/device[N]
- Removable device: not locked, tray closed
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "none0", "locked": false, "removable": true, "qdev": "/machine/peripheral-anon/device[N]", "tray_open": false, "type": "unknown"}]}
Testing: -drive if=none -device scsi-cd,drive=none0,id=qdev_id
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-none0: [not inserted]
- Attached to: qdev_id
- Removable device: not locked, tray closed
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "none0", "locked": false, "removable": true, "qdev": "qdev_id", "tray_open": false, "type": "unknown"}]}
=== -drive if=... ===
Testing: -drive if=floppy
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-floppy0: [not inserted]
- Attached to: /machine/unattached/device[N]
- Removable device: not locked, tray closed
-(qemu) quit
+QMP_VERSION
+{"return": [{"device": "floppy0", "locked": false, "removable": true, "qdev": "/machine/unattached/device[N]", "type": "unknown"}]}
Testing: -drive if=floppy,driver=null-co,read-zeroes=on
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-floppy0 (NODE_NAME): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: /machine/unattached/device[N]
- Removable device: not locked, tray closed
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"device": "floppy0", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "NODE_NAME", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}"}, "qdev": "/machine/unattached/device[N]", "type": "unknown"}]}
Testing: -drive if=ide,driver=null-co,read-zeroes=on
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-ide0-hd0 (NODE_NAME): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: /machine/unattached/device[N]
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "ide0-hd0", "locked": false, "removable": false, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "NODE_NAME", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}"}, "qdev": "/machine/unattached/device[N]", "type": "unknown"}]}
Testing: -drive if=ide,media=cdrom
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-ide0-cd0: [not inserted]
- Attached to: /machine/unattached/device[N]
- Removable device: not locked, tray closed
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "ide0-cd0", "locked": false, "removable": true, "qdev": "/machine/unattached/device[N]", "tray_open": false, "type": "unknown"}]}
Testing: -drive if=ide,driver=null-co,read-zeroes=on,media=cdrom
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-ide0-cd0 (NODE_NAME): json:{"read-zeroes": "on", "driver": "null-co"} (null-co, read-only)
- Attached to: /machine/unattached/device[N]
- Removable device: not locked, tray closed
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "ide0-cd0", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": true, "children": [], "node-name": "NODE_NAME", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}"}, "qdev": "/machine/unattached/device[N]", "tray_open": false, "type": "unknown"}]}
Testing: -drive if=virtio,driver=null-co,read-zeroes=on
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-virtio0 (NODE_NAME): json:{"read-zeroes": "on", "driver": "null-co"} (null-co)
- Attached to: /machine/peripheral-anon/device[N]/virtio-backend
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"io-status": "ok", "device": "virtio0", "locked": false, "removable": false, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1073741824, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "NODE_NAME", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\"}"}, "qdev": "/machine/peripheral-anon/device[N]/virtio-backend", "type": "unknown"}]}
Testing: -drive if=pflash,driver=null-co,read-zeroes=on,size=1M
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) info block
-pflash0 (NODE_NAME): json:{"read-zeroes": "on", "driver": "null-co", "size": "1M"} (null-co)
- Attached to: /machine/system.flash0
- Cache mode: writeback
-(qemu) quit
+QMP_VERSION
+{"return": [{"device": "pflash0", "locked": false, "removable": false, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "active": true, "image": {"limits": {"request-alignment": 1, "min-mem-alignment": 512, "opt-mem-alignment": 4096, "max-iov": 1024}, "virtual-size": 1048576, "filename": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\", \"size\": \"1M\"}", "format": "null-co", "actual-size": 0}, "iops_wr": 0, "ro": false, "children": [], "node-name": "NODE_NAME", "backing_file_depth": 0, "drv": "null-co", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": {"no-flush": false, "direct": false, "writeback": true}, "file": "json:{\"read-zeroes\": \"on\", \"driver\": \"null-co\", \"size\": \"1M\"}"}, "qdev": "/machine/system.flash0", "type": "unknown"}]}
*** done
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 19/40] tests/qemu-iotests/copy-before-write: convert to QMP
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (17 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 18/40] tests/qemu-iotests/186: convert from HMP " Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 20/40] tests/qemu-iotests: skip some 172 & 267 that require HMP Marc-André Lureau
` (21 subsequent siblings)
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
tests/qemu-iotests/tests/copy-before-write | 42 +++++++++++++++---------------
1 file changed, 21 insertions(+), 21 deletions(-)
diff --git a/tests/qemu-iotests/tests/copy-before-write b/tests/qemu-iotests/tests/copy-before-write
index 11a9562067b..339bd0de644 100755
--- a/tests/qemu-iotests/tests/copy-before-write
+++ b/tests/qemu-iotests/tests/copy-before-write
@@ -85,13 +85,13 @@ class TestCbwError(iotests.QMPTestCase):
'file': 'cbw'
})
- result = self.vm.qmp('human-monitor-command',
- command_line='qemu-io cbw "write 0 1M"')
- write_res = result['return']
+ result = self.vm.qmp('x-qemu-io',
+ device='cbw', command='write 0 1M')
+ write_res = result.get('error', {}).get('desc', '')
- result = self.vm.qmp('human-monitor-command',
- command_line='qemu-io access "read 0 1M"')
- read_res = result['return']
+ result = self.vm.qmp('x-qemu-io',
+ device='access', command='read 0 1M')
+ read_res = result.get('error', {}).get('desc', '')
self.vm.shutdown()
log = self.vm.get_log()
@@ -148,13 +148,13 @@ class TestCbwError(iotests.QMPTestCase):
'file': 'cbw'
})
- result = self.vm.qmp('human-monitor-command',
- command_line='qemu-io cbw "write 0 1M"')
- write_res = result['return']
+ result = self.vm.qmp('x-qemu-io',
+ device='cbw', command='write 0 1M')
+ write_res = result.get('error', {}).get('desc', '')
- result = self.vm.qmp('human-monitor-command',
- command_line='qemu-io access "read 0 1M"')
- read_res = result['return']
+ result = self.vm.qmp('x-qemu-io',
+ device='access', command='read 0 1M')
+ read_res = result.get('error', {}).get('desc', '')
self.vm.shutdown()
log = self.vm.get_log()
@@ -266,18 +266,18 @@ read 1048576/1048576 bytes at offset 0
'file': 'cbw'
})
- result = self.vm.qmp('human-monitor-command',
- command_line='qemu-io cbw "write 0 512K"')
- write1_res = result['return']
+ result = self.vm.qmp('x-qemu-io',
+ device='cbw', command='write 0 512K')
+ write1_res = result.get('error', {}).get('desc', '')
# We need second write to trigger throttling
- result = self.vm.qmp('human-monitor-command',
- command_line='qemu-io cbw "write 512K 512K"')
- write2_res = result['return']
+ result = self.vm.qmp('x-qemu-io',
+ device='cbw', command='write 512K 512K')
+ write2_res = result.get('error', {}).get('desc', '')
- result = self.vm.qmp('human-monitor-command',
- command_line='qemu-io access "read 0 1M"')
- read_res = result['return']
+ result = self.vm.qmp('x-qemu-io',
+ device='access', command='read 0 1M')
+ read_res = result.get('error', {}).get('desc', '')
self.vm.shutdown()
log = self.vm.get_log()
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 20/40] tests/qemu-iotests: skip some 172 & 267 that require HMP
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (18 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 19/40] tests/qemu-iotests/copy-before-write: convert " Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 21/40] RFC: qtest: add qemu-io command to the qtest protocol Marc-André Lureau
` (20 subsequent siblings)
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
tests/qemu-iotests/172 | 5 +++++
tests/qemu-iotests/267 | 4 ++++
tests/qemu-iotests/common.rc | 7 +++++++
3 files changed, 16 insertions(+)
diff --git a/tests/qemu-iotests/172 b/tests/qemu-iotests/172
index 4da0e0f2e29..40298c0d7c3 100755
--- a/tests/qemu-iotests/172
+++ b/tests/qemu-iotests/172
@@ -39,6 +39,11 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
. ./common.rc
. ./common.filter
+# HMP: info block & info qtree
+# rewrite with qom-list/get + query-block is possible,
+# but hardly in bash
+_require_hmp
+
_supported_fmt qcow2
_supported_proto file
_supported_os Linux
diff --git a/tests/qemu-iotests/267 b/tests/qemu-iotests/267
index 2e2afdad9c5..ff8eed0a44b 100755
--- a/tests/qemu-iotests/267
+++ b/tests/qemu-iotests/267
@@ -38,6 +38,10 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
. ./common.rc
. ./common.filter
+# HMP: savevm/loadvm, info snapshots
+# TODO: rewrite with QMP snapshot-save/load
+_require_hmp
+
_supported_fmt qcow2
_supported_proto file
_supported_os Linux
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
index 731e4b2b998..4f51a22f8df 100644
--- a/tests/qemu-iotests/common.rc
+++ b/tests/qemu-iotests/common.rc
@@ -1067,6 +1067,13 @@ _require_secret()
rm -f "$TEST_IMG"
}
+_require_hmp()
+{
+ if ! echo quit | $QEMU -M none -monitor stdio > /dev/null 2>&1; then
+ _notrun "HMP monitor not available"
+ fi
+}
+
_qcow2_dump_header()
{
if [[ "$1" == "--no-filter-compression" ]]; then
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 21/40] RFC: qtest: add qemu-io command to the qtest protocol
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (19 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 20/40] tests/qemu-iotests: skip some 172 & 267 that require HMP Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 22/40] RFC: qtest/ide-test: convert to use qtest qemu-io command Marc-André Lureau
` (19 subsequent siblings)
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Add a "qemu-io" command to the qtest protocol so that tests can issue
block layer I/O commands without going through the HMP monitor's
"human-monitor-command" QMP, or use QMP at all.
Unfortunately, many tests will prefer to use QMP as they also monitor
and log other events. It's easier if it is pipelined in the same stream.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
tests/qtest/libqtest.h | 11 +++++++++++
system/qtest.c | 14 ++++++++++++++
tests/qtest/libqtest.c | 14 ++++++++++++++
3 files changed, 39 insertions(+)
diff --git a/tests/qtest/libqtest.h b/tests/qtest/libqtest.h
index 950ea2baafa..647a8a095a1 100644
--- a/tests/qtest/libqtest.h
+++ b/tests/qtest/libqtest.h
@@ -424,6 +424,17 @@ char *qtest_hmp(QTestState *s, const char *fmt, ...) G_GNUC_PRINTF(2, 3);
char *qtest_vhmp(QTestState *s, const char *fmt, va_list ap)
G_GNUC_PRINTF(2, 0);
+/**
+ * qtest_qemu_io:
+ * @s: #QTestState instance to operate on.
+ * @device: block device node-name or BlockBackend name.
+ * @fmt: qemu-io command to send, formats arguments like sprintf().
+ *
+ * Send a qemu-io command via the qtest protocol.
+ */
+void qtest_qemu_io(QTestState *s, const char *device,
+ const char *fmt, ...) G_GNUC_PRINTF(3, 4);
+
void qtest_module_load(QTestState *s, const char *prefix, const char *libname);
/**
diff --git a/system/qtest.c b/system/qtest.c
index 1fb35ae36bc..1b7a7b6b8b8 100644
--- a/system/qtest.c
+++ b/system/qtest.c
@@ -31,6 +31,7 @@
#include "qemu/cutils.h"
#include "qemu/target-info.h"
#include "qom/object_interfaces.h"
+#include "qapi-commands-block.h"
#define MAX_IRQ 256
@@ -763,6 +764,19 @@ static void qtest_process_command(CharFrontend *chr, gchar **words)
new_ns = qemu_clock_advance_virtual_time(ns);
qtest_sendf(chr, "%s %"PRIi64"\n",
new_ns == ns ? "OK" : "FAIL", new_ns);
+ } else if (strcmp(words[0], "qemu-io") == 0) {
+ const char *io_dev;
+ g_autofree char *io_cmd = NULL;
+ Error *err = NULL;
+
+ g_assert(words[1] && words[2]);
+ io_dev = words[1];
+ io_cmd = g_strjoinv(" ", &words[2]);
+
+ qmp_x_qemu_io(io_dev, NULL, io_cmd, &err);
+ qtest_sendf(chr, err ? "FAIL %s\n" : "OK\n",
+ err ? error_get_pretty(err) : NULL);
+ error_free(err);
} else if (process_command_cb && process_command_cb(chr, words)) {
/* Command got consumed by the callback handler */
} else {
diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c
index b1e06ea364e..363fc3028d3 100644
--- a/tests/qtest/libqtest.c
+++ b/tests/qtest/libqtest.c
@@ -1012,6 +1012,20 @@ char *qtest_hmp(QTestState *s, const char *fmt, ...)
return ret;
}
+void qtest_qemu_io(QTestState *s, const char *device,
+ const char *fmt, ...)
+{
+ va_list ap;
+ g_autofree char *cmd = NULL;
+
+ va_start(ap, fmt);
+ cmd = g_strdup_vprintf(fmt, ap);
+ va_end(ap);
+
+ qtest_sendf(s, "qemu-io %s %s\n", device, cmd);
+ qtest_rsp(s);
+}
+
const char *qtest_get_arch(void)
{
/*
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 22/40] RFC: qtest/ide-test: convert to use qtest qemu-io command
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (20 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 21/40] RFC: qtest: add qemu-io command to the qtest protocol Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 23/40] tests/qtest/numa-test: replace HMP "info numa" with QMP query-cpus-fast Marc-André Lureau
` (18 subsequent siblings)
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Depend on the previous commit to be accepted.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
tests/qtest/ide-test.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/qtest/ide-test.c b/tests/qtest/ide-test.c
index 721e78170bc..3a00c5ff8eb 100644
--- a/tests/qtest/ide-test.c
+++ b/tests/qtest/ide-test.c
@@ -832,7 +832,7 @@ static void test_flush(void)
make_dirty(qts, 0);
/* Delay the completion of the flush request until we explicitly do it */
- g_free(qtest_hmp(qts, "qemu-io ide0-hd0 \"break flush_to_os A\""));
+ qtest_qemu_io(qts, "ide0-hd0", "break flush_to_os A");
/* FLUSH CACHE command on device 0*/
qpci_io_writeb(dev, ide_bar, reg_device, 0);
@@ -844,7 +844,7 @@ static void test_flush(void)
assert_bit_clear(data, DF | ERR | DRQ);
/* Complete the command */
- g_free(qtest_hmp(qts, "qemu-io ide0-hd0 \"resume A\""));
+ qtest_qemu_io(qts, "ide0-hd0", "resume A");
/* Check registers */
data = qpci_io_readb(dev, ide_bar, reg_device);
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 23/40] tests/qtest/numa-test: replace HMP "info numa" with QMP query-cpus-fast
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (21 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 22/40] RFC: qtest/ide-test: convert to use qtest qemu-io command Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 24/40] tests/qtest/pnv: drop unnecessary -serial mon:stdio Marc-André Lureau
` (17 subsequent siblings)
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Convert the three test functions that relied on HMP "info numa" to use
QMP "query-cpus-fast" instead, verifying each CPU's node-id through the
structured response. Add a check_cpu_node() helper for the per-CPU
assertions.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
tests/qtest/numa-test.c | 63 +++++++++++++++++++++++++++++++++++++++----------
1 file changed, 51 insertions(+), 12 deletions(-)
diff --git a/tests/qtest/numa-test.c b/tests/qtest/numa-test.c
index d657f389474..8f563c079f6 100644
--- a/tests/qtest/numa-test.c
+++ b/tests/qtest/numa-test.c
@@ -19,19 +19,50 @@ static char *make_cli(const GString *generic_cli, const char *test_cli)
return g_strdup_printf("%s %s", generic_cli->str, test_cli);
}
+static void check_cpu_node(QTestState *qts, int cpu_idx, int expected_node)
+{
+ QDict *resp;
+ QList *cpus;
+ QListEntry *e;
+ bool found = false;
+
+ resp = qtest_qmp(qts, "{ 'execute': 'query-cpus-fast' }");
+ g_assert(resp);
+ g_assert(qdict_haskey(resp, "return"));
+ cpus = qdict_get_qlist(resp, "return");
+ g_assert(cpus);
+
+ QLIST_FOREACH_ENTRY(cpus, e) {
+ QDict *cpu = qobject_to(QDict, qlist_entry_obj(e));
+ int64_t idx = qdict_get_int(cpu, "cpu-index");
+ if (idx == cpu_idx) {
+ QDict *props = qdict_get_qdict(cpu, "props");
+ g_assert(qdict_haskey(props, "node-id"));
+ g_assert_cmpint(qdict_get_int(props, "node-id"), ==, expected_node);
+ found = true;
+ break;
+ }
+ }
+ g_assert(found);
+ qobject_unref(resp);
+}
+
static void test_mon_explicit(const void *data)
{
QTestState *qts;
- g_autofree char *s = NULL;
g_autofree char *cli = NULL;
+ int i;
cli = make_cli(data, "-machine smp.cpus=8 -numa node,nodeid=0,memdev=ram,cpus=0-3 "
"-numa node,nodeid=1,cpus=4-7");
qts = qtest_init(cli);
- s = qtest_hmp(qts, "info numa");
- g_assert(strstr(s, "node 0 cpus: 0 1 2 3"));
- g_assert(strstr(s, "node 1 cpus: 4 5 6 7"));
+ for (i = 0; i < 4; i++) {
+ check_cpu_node(qts, i, 0);
+ }
+ for (i = 4; i < 8; i++) {
+ check_cpu_node(qts, i, 1);
+ }
qtest_quit(qts);
}
@@ -39,16 +70,19 @@ static void test_mon_explicit(const void *data)
static void test_def_cpu_split(const void *data)
{
QTestState *qts;
- g_autofree char *s = NULL;
g_autofree char *cli = NULL;
+ int even_cpus[] = {0, 2, 4, 6};
+ int odd_cpus[] = {1, 3, 5, 7};
+ int i;
cli = make_cli(data, "-machine smp.cpus=8,smp.sockets=8 "
"-numa node,memdev=ram -numa node");
qts = qtest_init(cli);
- s = qtest_hmp(qts, "info numa");
- g_assert(strstr(s, "node 0 cpus: 0 2 4 6"));
- g_assert(strstr(s, "node 1 cpus: 1 3 5 7"));
+ for (i = 0; i < 4; i++) {
+ check_cpu_node(qts, even_cpus[i], 0);
+ check_cpu_node(qts, odd_cpus[i], 1);
+ }
qtest_quit(qts);
}
@@ -56,17 +90,22 @@ static void test_def_cpu_split(const void *data)
static void test_mon_partial(const void *data)
{
QTestState *qts;
- g_autofree char *s = NULL;
g_autofree char *cli = NULL;
+ int node0_cpus[] = {0, 1, 2, 3, 6, 7};
+ int node1_cpus[] = {4, 5};
+ int i;
cli = make_cli(data, "-machine smp.cpus=8 "
"-numa node,nodeid=0,memdev=ram,cpus=0-1 "
"-numa node,nodeid=1,cpus=4-5 ");
qts = qtest_init(cli);
- s = qtest_hmp(qts, "info numa");
- g_assert(strstr(s, "node 0 cpus: 0 1 2 3 6 7"));
- g_assert(strstr(s, "node 1 cpus: 4 5"));
+ for (i = 0; i < 6; i++) {
+ check_cpu_node(qts, node0_cpus[i], 0);
+ }
+ for (i = 0; i < 2; i++) {
+ check_cpu_node(qts, node1_cpus[i], 1);
+ }
qtest_quit(qts);
}
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 24/40] tests/qtest/pnv: drop unnecessary -serial mon:stdio
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (22 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 23/40] tests/qtest/numa-test: replace HMP "info numa" with QMP query-cpus-fast Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-21 6:02 ` Philippe Mathieu-Daudé
2026-05-20 21:49 ` [PATCH 25/40] net: add x-query-network QMP command Marc-André Lureau
` (16 subsequent siblings)
40 siblings, 1 reply; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
The pnv-xive2-test and pnv-host-i2c-test pass "-serial mon:stdio"
but never use HMP commands. The "mon:" chardev prefix creates an
HMP monitor mux, which fails when HMP is disabled. Other pnv tests
(e.g. pnv-spi-seeprom-test) don't specify -serial at all.
Drop the unnecessary -serial mon:stdio option.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
tests/qtest/pnv-host-i2c-test.c | 2 +-
tests/qtest/pnv-xive2-test.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/qtest/pnv-host-i2c-test.c b/tests/qtest/pnv-host-i2c-test.c
index 51e613ebdcb..368d1a91401 100644
--- a/tests/qtest/pnv-host-i2c-test.c
+++ b/tests/qtest/pnv-host-i2c-test.c
@@ -415,7 +415,7 @@ static void test_host_i2c(const void *data)
}
qts = qtest_initf("-M %s -smp %d,cores=1,threads=%d -nographic "
- "-nodefaults -serial mon:stdio -S "
+ "-nodefaults -S "
"-d guest_errors",
machine, SMT, SMT);
diff --git a/tests/qtest/pnv-xive2-test.c b/tests/qtest/pnv-xive2-test.c
index 5313d4ef18b..b4f4b601c2a 100644
--- a/tests/qtest/pnv-xive2-test.c
+++ b/tests/qtest/pnv-xive2-test.c
@@ -549,7 +549,7 @@ static void test_xive(void)
QTestState *qts;
qts = qtest_initf("-M powernv10 -smp %d,cores=1,threads=%d -nographic "
- "-nodefaults -serial mon:stdio -S "
+ "-nodefaults -S "
"-d guest_errors -trace '*xive*'",
SMT, SMT);
init_xive(qts);
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 25/40] net: add x-query-network QMP command
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (23 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 24/40] tests/qtest/pnv: drop unnecessary -serial mon:stdio Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 26/40] tests/qtest/netdev-socket: replace HMP with x-query-network QMP Marc-André Lureau
` (15 subsequent siblings)
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Add a structured x-query-network QMP command that returns network
configuration as a NetworkInfo struct with pre-grouped hub information
and a flat list of non-hub clients. Each hub includes its ports with
inlined peer client info, and each client includes attached netfilter
details.
Refactor hmp_info_network() to consume only the QMP result instead of
directly accessing internal net_clients state. This decouples HMP from
internal data structures, making it possible to remove HMP support
without losing programmatic network introspection.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
qapi/net.json | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++++
include/net/net.h | 3 +-
net/hub.h | 4 +-
net/hub.c | 29 +++++++------
net/net-hmp-cmds.c | 59 +++++++++++++++++++-------
net/net.c | 70 +++++++++++++++++++++++-------
6 files changed, 243 insertions(+), 44 deletions(-)
diff --git a/qapi/net.json b/qapi/net.json
index dd56215fd15..c329da9cec8 100644
--- a/qapi/net.json
+++ b/qapi/net.json
@@ -1235,3 +1235,125 @@
'returns': ['UsernetInfo'],
'if': 'CONFIG_SLIRP',
'features': [ 'unstable' ] }
+
+##
+# @NetFilterInfo:
+#
+# Information about a netfilter attached to a network client.
+#
+# @name: filter object name (QOM path component)
+#
+# @type: QOM type name (e.g. "filter-mirror")
+#
+# @info: filter properties as comma-separated key=value pairs
+# (excluding @type)
+#
+# Since: 11.1
+##
+{ 'struct': 'NetFilterInfo',
+ 'data': {
+ 'name': 'str',
+ 'type': 'str',
+ 'info': 'str' } }
+
+##
+# @NetworkClientInfo:
+#
+# Information about a network client.
+#
+# @name: unique network client identifier
+#
+# @queue-index: index of this queue (0 for single-queue clients)
+#
+# @type: network client driver type
+#
+# @info-str: driver-specific formatted information string (e.g.
+# "model=e1000,macaddr=52:54:00:12:34:56")
+#
+# @peer: the connected peer client (always a leaf; the peer's own
+# peer field is never populated)
+#
+# @filters: attached netfilters
+#
+# Since: 11.1
+##
+{ 'struct': 'NetworkClientInfo',
+ 'data': {
+ 'name': 'str',
+ 'queue-index': 'uint32',
+ 'type': 'NetClientDriver',
+ 'info-str': 'str',
+ '*peer': 'NetworkClientInfo',
+ 'filters': ['NetFilterInfo'] } }
+
+##
+# @NetHubPortInfo:
+#
+# Information about a hub port.
+#
+# @name: hub port identifier
+#
+# @peer: the network client connected through this port
+#
+# Since: 11.1
+##
+{ 'struct': 'NetHubPortInfo',
+ 'data': {
+ 'name': 'str',
+ '*peer': 'NetworkClientInfo' } }
+
+##
+# @NetHubInfo:
+#
+# Information about a network hub.
+#
+# @id: hub identifier
+#
+# @ports: list of ports on this hub
+#
+# Since: 11.1
+##
+{ 'struct': 'NetHubInfo',
+ 'data': {
+ 'id': 'int',
+ 'ports': ['NetHubPortInfo'] } }
+
+##
+# @NetworkInfo:
+#
+# Information about the network configuration.
+#
+# @hubs: network hubs and their ports
+#
+# @clients: network clients not associated with a hub
+#
+# Since: 11.1
+##
+{ 'struct': 'NetworkInfo',
+ 'data': {
+ 'hubs': ['NetHubInfo'],
+ 'clients': ['NetworkClientInfo'] } }
+
+##
+# @x-query-network:
+#
+# Query the network configuration including hubs and clients.
+#
+# Features:
+#
+# @unstable: This command is meant for debugging.
+#
+# Returns: @NetworkInfo describing hubs and clients.
+#
+# Since: 11.1
+#
+# .. qmp-example::
+#
+# -> { "execute": "x-query-network" }
+# <- { "return": { "clients": [ { "name": "st0",
+# "queue-index": 0, "type": "stream",
+# "info-str": "listening" } ] } }
+##
+{ 'command': 'x-query-network',
+ 'returns': 'NetworkInfo',
+ 'features': [ 'unstable' ] }
diff --git a/include/net/net.h b/include/net/net.h
index 45bc86fc86b..0f0b524df00 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -274,7 +274,6 @@ DeviceState *qemu_create_nic_device(const char *typename, bool match_default,
void qemu_create_nic_bus_devices(BusState *bus, const char *parent_type,
const char *default_model,
const char *alias, const char *alias_target);
-void print_net_client(Monitor *mon, NetClientState *nc);
void net_socket_rs_init(SocketReadState *rs,
SocketReadStateFinalize *finalize,
bool vnet_hdr);
@@ -325,6 +324,8 @@ void netdev_add(QemuOpts *opts, Error **errp);
int net_hub_id_for_client(NetClientState *nc, int *id);
+NetworkClientInfo *net_client_info(NetClientState *nc);
+
#define DEFAULT_NETWORK_SCRIPT CONFIG_SYSCONFDIR "/qemu-ifup"
#define DEFAULT_NETWORK_DOWN_SCRIPT CONFIG_SYSCONFDIR "/qemu-ifdown"
#define DEFAULT_BRIDGE_HELPER CONFIG_QEMU_HELPERDIR "/qemu-bridge-helper"
diff --git a/net/hub.h b/net/hub.h
index ce45f7b399d..cab6b1459b1 100644
--- a/net/hub.h
+++ b/net/hub.h
@@ -15,10 +15,12 @@
#ifndef NET_HUB_H
#define NET_HUB_H
+#include "qapi/qapi-types-net.h"
+
NetClientState *net_hub_add_port(int hub_id, const char *name,
NetClientState *hubpeer);
-void net_hub_info(Monitor *mon);
void net_hub_check_clients(void);
bool net_hub_flush(NetClientState *nc);
+NetHubInfoList *net_hub_query_info(void);
#endif /* NET_HUB_H */
diff --git a/net/hub.c b/net/hub.c
index ee5881f6d5c..b53a4cc872c 100644
--- a/net/hub.c
+++ b/net/hub.c
@@ -14,7 +14,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
-#include "monitor/monitor.h"
+#include "qapi/util.h"
#include "net/net.h"
#include "clients.h"
#include "hub.h"
@@ -199,26 +199,31 @@ NetClientState *net_hub_add_port(int hub_id, const char *name,
return &port->nc;
}
-/**
- * Print hub configuration
- */
-void net_hub_info(Monitor *mon)
+NetHubInfoList *net_hub_query_info(void)
{
+ NetHubInfoList *head = NULL, **tail = &head;
NetHub *hub;
- NetHubPort *port;
QLIST_FOREACH(hub, &hubs, next) {
- monitor_printf(mon, "hub %d\n", hub->id);
+ NetHubInfo *hi = g_new0(NetHubInfo, 1);
+ NetHubPortInfoList **ptail = &hi->ports;
+ NetHubPort *port;
+
+ hi->id = hub->id;
+
QLIST_FOREACH(port, &hub->ports, next) {
- monitor_printf(mon, " \\ %s", port->nc.name);
+ NetHubPortInfo *pi = g_new0(NetHubPortInfo, 1);
+ pi->name = g_strdup(port->nc.name);
if (port->nc.peer) {
- monitor_printf(mon, ": ");
- print_net_client(mon, port->nc.peer);
- } else {
- monitor_printf(mon, "\n");
+ pi->peer = net_client_info(port->nc.peer);
}
+ QAPI_LIST_APPEND(ptail, pi);
}
+
+ QAPI_LIST_APPEND(tail, hi);
}
+
+ return head;
}
/**
diff --git a/net/net-hmp-cmds.c b/net/net-hmp-cmds.c
index 2b24c9e6049..52ac8da770d 100644
--- a/net/net-hmp-cmds.c
+++ b/net/net-hmp-cmds.c
@@ -19,37 +19,66 @@
#include "monitor/hmp-completion.h"
#include "monitor/monitor.h"
#include "net/net.h"
-#include "net/hub.h"
#include "qapi/clone-visitor.h"
#include "qapi/qapi-commands-net.h"
#include "qapi/qapi-visit-net.h"
+#include "qapi/error.h"
#include "qobject/qdict.h"
#include "qemu/config-file.h"
#include "qemu/help_option.h"
#include "qemu/option.h"
-void hmp_info_network(Monitor *mon, const QDict *qdict)
+static void hmp_print_client_info(Monitor *mon, NetworkClientInfo *ci)
{
- NetClientState *nc, *peer;
- NetClientDriver type;
+ NetFilterInfoList *f;
+
+ monitor_printf(mon, "%s: index=%" PRIu32 ",type=%s,%s\n",
+ ci->name, ci->queue_index,
+ NetClientDriver_str(ci->type), ci->info_str);
+ if (ci->filters) {
+ monitor_printf(mon, "filters:\n");
+ for (f = ci->filters; f; f = f->next) {
+ monitor_printf(mon, " - %s: type=%s%s%s\n",
+ f->value->name, f->value->type,
+ f->value->info[0] ? "," : "", f->value->info);
+ }
+ }
+}
- net_hub_info(mon);
+void hmp_info_network(Monitor *mon, const QDict *qdict)
+{
+ Error *err = NULL;
+ g_autoptr(NetworkInfo) info = qmp_x_query_network(&err);
+ NetHubInfoList *h;
+ NetworkClientInfoList *entry;
- QTAILQ_FOREACH(nc, &net_clients, next) {
- peer = nc->peer;
- type = nc->info->type;
+ if (hmp_handle_error(mon, err)) {
+ return;
+ }
- /* Skip if already printed in hub info */
- if (net_hub_id_for_client(nc, NULL) == 0) {
- continue;
+ for (h = info->hubs; h; h = h->next) {
+ NetHubPortInfoList *p;
+
+ monitor_printf(mon, "hub %d\n", (int)h->value->id);
+ for (p = h->value->ports; p; p = p->next) {
+ if (p->value->peer) {
+ monitor_printf(mon, " \\ %s: ", p->value->name);
+ hmp_print_client_info(mon, p->value->peer);
+ } else {
+ monitor_printf(mon, " \\ %s\n", p->value->name);
+ }
}
+ }
+
+ for (entry = info->clients; entry; entry = entry->next) {
+ NetworkClientInfo *ci = entry->value;
- if (!peer || type == NET_CLIENT_DRIVER_NIC) {
- print_net_client(mon, nc);
+ if (!ci->peer || ci->type == NET_CLIENT_DRIVER_NIC) {
+ hmp_print_client_info(mon, ci);
} /* else it's a netdev connected to a NIC, printed with the NIC */
- if (peer && type == NET_CLIENT_DRIVER_NIC) {
+ if (ci->peer && ci->type == NET_CLIENT_DRIVER_NIC) {
monitor_printf(mon, " \\ ");
- print_net_client(mon, peer);
+ hmp_print_client_info(mon, ci->peer);
}
}
}
diff --git a/net/net.c b/net/net.c
index 2892f1730d1..2bcd229cd9d 100644
--- a/net/net.c
+++ b/net/net.c
@@ -1523,14 +1523,14 @@ void qmp_netdev_del(const char *id, Error **errp)
}
}
-static void netfilter_print_info(Monitor *mon, NetFilterState *nf)
+static char *netfilter_get_info_str(NetFilterState *nf)
{
char *str;
ObjectProperty *prop;
ObjectPropertyIterator iter;
Visitor *v;
+ GString *buf = g_string_new(NULL);
- /* generate info str */
object_property_iter_init(&iter, OBJECT(nf));
while ((prop = object_property_iter_next(&iter))) {
if (!strcmp(prop->name, "type")) {
@@ -1540,29 +1540,69 @@ static void netfilter_print_info(Monitor *mon, NetFilterState *nf)
object_property_get(OBJECT(nf), prop->name, v, NULL);
visit_complete(v, &str);
visit_free(v);
- monitor_printf(mon, ",%s=%s", prop->name, str);
+ if (buf->len > 0) {
+ g_string_append_c(buf, ',');
+ }
+ g_string_append_printf(buf, "%s=%s", prop->name, str);
g_free(str);
}
- monitor_printf(mon, "\n");
+
+ return g_string_free(buf, false);
}
-void print_net_client(Monitor *mon, NetClientState *nc)
+static NetworkClientInfo *net_client_info_no_peer(NetClientState *nc)
{
+ NetworkClientInfo *info = g_new0(NetworkClientInfo, 1);
NetFilterState *nf;
- monitor_printf(mon, "%s: index=%d,type=%s,%s\n", nc->name,
- nc->queue_index,
- NetClientDriver_str(nc->info->type),
- nc->info_str);
+ info->name = g_strdup(nc->name);
+ info->queue_index = nc->queue_index;
+ info->type = nc->info->type;
+ info->info_str = g_strdup(nc->info_str);
+
if (!QTAILQ_EMPTY(&nc->filters)) {
- monitor_printf(mon, "filters:\n");
+ NetFilterInfoList **ftail = &info->filters;
+ QTAILQ_FOREACH(nf, &nc->filters, next) {
+ NetFilterInfo *fi = g_new0(NetFilterInfo, 1);
+ fi->name = g_strdup(
+ object_get_canonical_path_component(OBJECT(nf)));
+ fi->type = g_strdup(object_get_typename(OBJECT(nf)));
+ fi->info = netfilter_get_info_str(nf);
+ QAPI_LIST_APPEND(ftail, fi);
+ }
}
- QTAILQ_FOREACH(nf, &nc->filters, next) {
- monitor_printf(mon, " - %s: type=%s",
- object_get_canonical_path_component(OBJECT(nf)),
- object_get_typename(OBJECT(nf)));
- netfilter_print_info(mon, nf);
+
+ return info;
+}
+
+NetworkClientInfo *net_client_info(NetClientState *nc)
+{
+ NetworkClientInfo *info = net_client_info_no_peer(nc);
+
+ if (nc->peer) {
+ info->peer = net_client_info_no_peer(nc->peer);
}
+
+ return info;
+}
+
+NetworkInfo *qmp_x_query_network(Error **errp)
+{
+ NetworkInfo *info = g_new0(NetworkInfo, 1);
+ NetworkClientInfoList **tail = &info->clients;
+ NetClientState *nc;
+
+ info->hubs = net_hub_query_info();
+
+ QTAILQ_FOREACH(nc, &net_clients, next) {
+ /* Skip if already gathered in hub info */
+ if (net_hub_id_for_client(nc, NULL) == 0) {
+ continue;
+ }
+ QAPI_LIST_APPEND(tail, net_client_info(nc));
+ }
+
+ return info;
}
RxFilterInfoList *qmp_query_rx_filter(const char *name, Error **errp)
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 26/40] tests/qtest/netdev-socket: replace HMP with x-query-network QMP
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (24 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 25/40] net: add x-query-network QMP command Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 27/40] tests/qtest/cdrom-test: replace HMP "info block" with QMP query-block Marc-André Lureau
` (14 subsequent siblings)
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Replace the HMP "info network" text parsing with the structured
x-query-network QMP command. This makes the test assertions more robust
by matching individual fields (info-str) instead of parsing the full HMP
line format.
The EXPECT_STATE macro now takes an explicit netdev id argument to look
up the client by name in the QMP response. The strrchr truncation is
made NULL-safe: if the truncation character is not found, the full
string is compared (and the final g_assert_cmpstr will catch
mismatches).
While at it, fix the pre-existing duplicate "qemu/sockets.h" include,
and reorder includes.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
tests/qtest/netdev-socket.c | 143 +++++++++++++++++++++++++-------------------
1 file changed, 82 insertions(+), 61 deletions(-)
diff --git a/tests/qtest/netdev-socket.c b/tests/qtest/netdev-socket.c
index b731af0ad95..30005c2e001 100644
--- a/tests/qtest/netdev-socket.c
+++ b/tests/qtest/netdev-socket.c
@@ -7,33 +7,62 @@
*/
#include "qemu/osdep.h"
-#include "qemu/sockets.h"
#include <glib/gstdio.h>
#include "../unit/socket-helpers.h"
#include "libqtest.h"
-#include "qobject/qstring.h"
-#include "qemu/sockets.h"
-#include "qapi/qobject-input-visitor.h"
#include "qapi/qapi-visit-sockets.h"
+#include "qapi/qobject-input-visitor.h"
+#include "qemu/sockets.h"
+#include "qobject/qdict.h"
+#include "qobject/qlist.h"
+#include "qobject/qstring.h"
#define CONNECTION_TIMEOUT 60
-#define EXPECT_STATE(q, e, t) \
-do { \
- char *resp = NULL; \
- g_test_timer_start(); \
- do { \
- g_free(resp); \
- resp = qtest_hmp(q, "info network"); \
- if (t) { \
- strrchr(resp, t)[0] = 0; \
- } \
- if (g_str_equal(resp, e)) { \
- break; \
- } \
- } while (g_test_timer_elapsed() < CONNECTION_TIMEOUT); \
- g_assert_cmpstr(resp, ==, e); \
- g_free(resp); \
+/*
+ * Only checks info-str; type is implicit from the netdev created by each test
+ */
+static char *query_net_info_str(QTestState *q, const char *name)
+{
+ QDict *ret;
+ QList *clients;
+ QListEntry *entry;
+
+ ret = qtest_qmp_assert_success_ref(q, "{'execute': 'x-query-network'}");
+ clients = qdict_get_qlist(ret, "clients");
+ g_assert_nonnull(clients);
+
+ QLIST_FOREACH_ENTRY(clients, entry) {
+ QDict *client = qobject_to(QDict, qlist_entry_obj(entry));
+ if (g_str_equal(qdict_get_str(client, "name"), name)) {
+ char *info = g_strdup(qdict_get_str(client, "info-str"));
+ qobject_unref(ret);
+ return info;
+ }
+ }
+
+ g_assert_not_reached();
+}
+
+#define EXPECT_STATE(q, id, e, t) \
+do { \
+ char *info = NULL; \
+ g_test_timer_start(); \
+ do { \
+ g_free(info); \
+ info = query_net_info_str(q, id); \
+ if (t) { \
+ char *p = strrchr(info, t); \
+ if (p) { \
+ p[0] = 0; \
+ } \
+ } \
+ if (g_str_equal(info, e)) { \
+ break; \
+ } \
+ } while (g_test_timer_elapsed() < CONNECTION_TIMEOUT); \
+ g_assert_cmpstr(info, ==, e); \
+ g_free(info); \
} while (0)
static gchar *tmpdir;
@@ -127,20 +156,19 @@ static void test_stream_inet_ipv4(void)
"addr.ipv4=on,addr.ipv6=off,"
"addr.host=127.0.0.1,addr.port=%d", port);
- EXPECT_STATE(qts0, "st0: index=0,type=stream,listening\r\n", 0);
+ EXPECT_STATE(qts0, "st0", "listening", 0);
qts1 = qtest_initf("-nodefaults -M none "
"-netdev stream,server=false,id=st0,addr.type=inet,"
"addr.ipv4=on,addr.ipv6=off,"
"addr.host=127.0.0.1,addr.port=%d", port);
- expect = g_strdup_printf("st0: index=0,type=stream,tcp:127.0.0.1:%d\r\n",
- port);
- EXPECT_STATE(qts1, expect, 0);
+ expect = g_strdup_printf("tcp:127.0.0.1:%d", port);
+ EXPECT_STATE(qts1, "st0", expect, 0);
g_free(expect);
/* the port is unknown, check only the address */
- EXPECT_STATE(qts0, "st0: index=0,type=stream,tcp:127.0.0.1", ':');
+ EXPECT_STATE(qts0, "st0", "tcp:127.0.0.1", ':');
qtest_quit(qts1);
qtest_quit(qts0);
@@ -200,7 +228,7 @@ static void test_stream_unix_reconnect(void)
"-netdev stream,id=st0,server=true,addr.type=unix,"
"addr.path=%s", path);
- EXPECT_STATE(qts0, "st0: index=0,type=stream,listening\r\n", 0);
+ EXPECT_STATE(qts0, "st0", "listening", 0);
qts1 = qtest_initf("-nodefaults -M none "
"-netdev stream,server=false,id=st0,addr.type=unix,"
@@ -250,20 +278,19 @@ static void test_stream_inet_ipv6(void)
"addr.ipv4=off,addr.ipv6=on,"
"addr.host=::1,addr.port=%d", port);
- EXPECT_STATE(qts0, "st0: index=0,type=stream,listening\r\n", 0);
+ EXPECT_STATE(qts0, "st0", "listening", 0);
qts1 = qtest_initf("-nodefaults -M none "
"-netdev stream,server=false,id=st0,addr.type=inet,"
"addr.ipv4=off,addr.ipv6=on,"
"addr.host=::1,addr.port=%d", port);
- expect = g_strdup_printf("st0: index=0,type=stream,tcp:::1:%d\r\n",
- port);
- EXPECT_STATE(qts1, expect, 0);
+ expect = g_strdup_printf("tcp:::1:%d", port);
+ EXPECT_STATE(qts1, "st0", expect, 0);
g_free(expect);
/* the port is unknown, check only the address */
- EXPECT_STATE(qts0, "st0: index=0,type=stream,tcp:::1", ':');
+ EXPECT_STATE(qts0, "st0", "tcp:::1", ':');
qtest_quit(qts1);
qtest_quit(qts0);
@@ -282,16 +309,16 @@ static void test_stream_unix(void)
"addr.type=unix,addr.path=%s,",
path);
- EXPECT_STATE(qts0, "st0: index=0,type=stream,listening\r\n", 0);
+ EXPECT_STATE(qts0, "st0", "listening", 0);
qts1 = qtest_initf("-nodefaults -M none "
"-netdev stream,id=st0,server=false,"
"addr.type=unix,addr.path=%s",
path);
- expect = g_strdup_printf("st0: index=0,type=stream,unix:%s\r\n", path);
- EXPECT_STATE(qts1, expect, 0);
- EXPECT_STATE(qts0, expect, 0);
+ expect = g_strdup_printf("unix:%s", path);
+ EXPECT_STATE(qts1, "st0", expect, 0);
+ EXPECT_STATE(qts0, "st0", expect, 0);
g_free(expect);
g_free(path);
@@ -314,16 +341,16 @@ static void test_stream_unix_abstract(void)
"addr.abstract=on",
path);
- EXPECT_STATE(qts0, "st0: index=0,type=stream,listening\r\n", 0);
+ EXPECT_STATE(qts0, "st0", "listening", 0);
qts1 = qtest_initf("-nodefaults -M none "
"-netdev stream,id=st0,server=false,"
"addr.type=unix,addr.path=%s,addr.abstract=on",
path);
- expect = g_strdup_printf("st0: index=0,type=stream,unix:%s\r\n", path);
- EXPECT_STATE(qts1, expect, 0);
- EXPECT_STATE(qts0, expect, 0);
+ expect = g_strdup_printf("unix:%s", path);
+ EXPECT_STATE(qts1, "st0", expect, 0);
+ EXPECT_STATE(qts0, "st0", expect, 0);
g_free(expect);
g_free(path);
@@ -346,14 +373,14 @@ static void test_stream_fd(void)
"-netdev stream,id=st0,addr.type=fd,addr.str=%d",
sock[0]);
- EXPECT_STATE(qts0, "st0: index=0,type=stream,unix:\r\n", 0);
+ EXPECT_STATE(qts0, "st0", "unix:", 0);
qts1 = qtest_initf("-nodefaults -M none "
"-netdev stream,id=st0,addr.type=fd,addr.str=%d",
sock[1]);
- EXPECT_STATE(qts1, "st0: index=0,type=stream,unix:\r\n", 0);
- EXPECT_STATE(qts0, "st0: index=0,type=stream,unix:\r\n", 0);
+ EXPECT_STATE(qts1, "st0", "unix:", 0);
+ EXPECT_STATE(qts0, "st0", "unix:", 0);
qtest_quit(qts1);
qtest_quit(qts0);
@@ -379,10 +406,9 @@ static void test_dgram_inet(void)
"remote.type=inet,remote.host=127.0.0.1,remote.port=%d",
port[0], port[1]);
- expect = g_strdup_printf("st0: index=0,type=dgram,"
- "udp=127.0.0.1:%d/127.0.0.1:%d\r\n",
+ expect = g_strdup_printf("udp=127.0.0.1:%d/127.0.0.1:%d",
port[0], port[1]);
- EXPECT_STATE(qts0, expect, 0);
+ EXPECT_STATE(qts0, "st0", expect, 0);
g_free(expect);
qts1 = qtest_initf("-nodefaults -M none "
@@ -391,10 +417,9 @@ static void test_dgram_inet(void)
"remote.type=inet,remote.host=127.0.0.1,remote.port=%d",
port[1], port[0]);
- expect = g_strdup_printf("st0: index=0,type=dgram,"
- "udp=127.0.0.1:%d/127.0.0.1:%d\r\n",
+ expect = g_strdup_printf("udp=127.0.0.1:%d/127.0.0.1:%d",
port[1], port[0]);
- EXPECT_STATE(qts1, expect, 0);
+ EXPECT_STATE(qts1, "st0", expect, 0);
g_free(expect);
qtest_quit(qts1);
@@ -410,7 +435,7 @@ static void test_dgram_mcast(void)
"-netdev dgram,id=st0,"
"remote.type=inet,remote.host=230.0.0.1,remote.port=1234");
- EXPECT_STATE(qts, "st0: index=0,type=dgram,mcast=230.0.0.1:1234\r\n", 0);
+ EXPECT_STATE(qts, "st0", "mcast=230.0.0.1:1234", 0);
qtest_quit(qts);
}
@@ -431,9 +456,8 @@ static void test_dgram_unix(void)
"remote.type=unix,remote.path=%s",
path0, path1);
- expect = g_strdup_printf("st0: index=0,type=dgram,udp=%s:%s\r\n",
- path0, path1);
- EXPECT_STATE(qts0, expect, 0);
+ expect = g_strdup_printf("udp=%s:%s", path0, path1);
+ EXPECT_STATE(qts0, "st0", expect, 0);
g_free(expect);
qts1 = qtest_initf("-nodefaults -M none "
@@ -441,10 +465,8 @@ static void test_dgram_unix(void)
"remote.type=unix,remote.path=%s",
path1, path0);
-
- expect = g_strdup_printf("st0: index=0,type=dgram,udp=%s:%s\r\n",
- path1, path0);
- EXPECT_STATE(qts1, expect, 0);
+ expect = g_strdup_printf("udp=%s:%s", path1, path0);
+ EXPECT_STATE(qts1, "st0", expect, 0);
g_free(expect);
unlink(path0);
@@ -470,17 +492,16 @@ static void test_dgram_fd(void)
"-netdev dgram,id=st0,local.type=fd,local.str=%d",
sv[0]);
- expect = g_strdup_printf("st0: index=0,type=dgram,fd=%d unix\r\n", sv[0]);
- EXPECT_STATE(qts0, expect, 0);
+ expect = g_strdup_printf("fd=%d unix", sv[0]);
+ EXPECT_STATE(qts0, "st0", expect, 0);
g_free(expect);
qts1 = qtest_initf("-nodefaults -M none "
"-netdev dgram,id=st0,local.type=fd,local.str=%d",
sv[1]);
-
- expect = g_strdup_printf("st0: index=0,type=dgram,fd=%d unix\r\n", sv[1]);
- EXPECT_STATE(qts1, expect, 0);
+ expect = g_strdup_printf("fd=%d unix", sv[1]);
+ EXPECT_STATE(qts1, "st0", expect, 0);
g_free(expect);
qtest_quit(qts1);
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 27/40] tests/qtest/cdrom-test: replace HMP "info block" with QMP query-block
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (25 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 26/40] tests/qtest/netdev-socket: replace HMP with x-query-network QMP Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-21 6:03 ` Philippe Mathieu-Daudé
2026-05-20 21:49 ` [PATCH 28/40] tests/qtest/qmp-test: don't depend on human-monitor-command Marc-André Lureau
` (13 subsequent siblings)
40 siblings, 1 reply; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
The test_cdrom_param() function uses qtest_hmp() to run "info block",
which depends on the human-monitor-command QMP endpoint. Replace it
with the QMP query-block command so the test works when HMP is
disabled (-Dhmp=disabled).
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
tests/qtest/cdrom-test.c | 29 ++++++++++++++++++++++++-----
1 file changed, 24 insertions(+), 5 deletions(-)
diff --git a/tests/qtest/cdrom-test.c b/tests/qtest/cdrom-test.c
index a65854d2bc5..bf997be6d69 100644
--- a/tests/qtest/cdrom-test.c
+++ b/tests/qtest/cdrom-test.c
@@ -14,6 +14,7 @@
#include "libqtest.h"
#include "boot-sector.h"
#include "qobject/qdict.h"
+#include "qobject/qlist.h"
static char isoimage[] = "cdrom-boot-iso-XXXXXX";
@@ -92,17 +93,35 @@ cleanup:
/**
* Check that at least the -cdrom parameter is basically working, i.e. we can
- * see the filename of the ISO image in the output of "info block" afterwards
+ * see the filename of the ISO image in the output of "query-block" afterwards
*/
static void test_cdrom_param(gconstpointer data)
{
QTestState *qts;
- char *resp;
+ QDict *response;
+ QList *ret;
+ QListEntry *entry;
+ bool found = false;
qts = qtest_initf("-M %s -cdrom %s", (const char *)data, isoimage);
- resp = qtest_hmp(qts, "info block");
- g_assert(strstr(resp, isoimage) != 0);
- g_free(resp);
+ response = qtest_qmp(qts, "{'execute': 'query-block'}");
+ g_assert(response && qdict_haskey(response, "return"));
+ ret = qdict_get_qlist(response, "return");
+
+ QLIST_FOREACH_ENTRY(ret, entry) {
+ QDict *entry_dict = qobject_to(QDict, entry->value);
+ QDict *inserted = qdict_get_qdict(entry_dict, "inserted");
+ if (inserted) {
+ const char *file = qdict_get_str(inserted, "file");
+ if (file && strstr(file, isoimage)) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ g_assert(found);
+ qobject_unref(response);
qtest_quit(qts);
}
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 28/40] tests/qtest/qmp-test: don't depend on human-monitor-command
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (26 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 27/40] tests/qtest/cdrom-test: replace HMP "info block" with QMP query-block Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 29/40] build-sys: add 'hmp' option Marc-André Lureau
` (12 subsequent siblings)
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
The test was using 'human-monitor-command' (which requires HMP) to
verify that an integer 'id' is echoed back on failure. Replace with
'query-name' for the success case and 'block_resize' (missing
required args) for the failure case, so the test works regardless of
HMP availability.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
tests/qtest/qmp-test.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/tests/qtest/qmp-test.c b/tests/qtest/qmp-test.c
index edf08867874..03637b9e2d2 100644
--- a/tests/qtest/qmp-test.c
+++ b/tests/qtest/qmp-test.c
@@ -151,9 +151,14 @@ static void test_qmp_protocol(void)
g_assert_cmpstr(qdict_get_try_str(resp, "id"), ==, "cookie#1");
qobject_unref(resp);
- /* Test command failure with 'id' */
- resp = qtest_qmp(qts, "{ 'execute': 'human-monitor-command', 'id': 2 }");
+ /* Test integer 'id' is echoed back on success */
+ resp = qtest_qmp(qts, "{ 'execute': 'query-name', 'id': 2 }");
g_assert_cmpint(qdict_get_int(resp, "id"), ==, 2);
+ qobject_unref(resp);
+
+ /* Test integer 'id' is echoed back on failure */
+ resp = qtest_qmp(qts, "{ 'execute': 'block_resize', 'id': 3 }");
+ g_assert_cmpint(qdict_get_int(resp, "id"), ==, 3);
qmp_expect_error_and_unref(resp, "GenericError");
qtest_quit(qts);
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 29/40] build-sys: add 'hmp' option
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (27 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 28/40] tests/qtest/qmp-test: don't depend on human-monitor-command Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 30/40] tests/qtest/device-introspect-test: fix test without HMP Marc-André Lureau
` (11 subsequent siblings)
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Add an option to enable/disable HMP support, default to true. The
following commits are going to make --disable-hmp gradually working.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
meson.build | 4 ++++
meson_options.txt | 2 ++
scripts/meson-buildoptions.sh | 3 +++
3 files changed, 9 insertions(+)
diff --git a/meson.build b/meson.build
index 70613bf4afc..e83cfe56cf3 100644
--- a/meson.build
+++ b/meson.build
@@ -247,6 +247,9 @@ have_vhost_net = have_vhost_net_kernel or have_vhost_net_user or have_vhost_net_
have_tcg = get_option('tcg').allowed() and (have_system or have_user)
+have_hmp = get_option('hmp') \
+ .disable_auto_if(not have_system) \
+ .allowed()
have_tools = get_option('tools') \
.disable_auto_if(not have_system) \
.allowed()
@@ -2256,6 +2259,7 @@ endif
config_host_data = configuration_data()
config_host_data.set('CONFIG_HAVE_RUST', have_rust)
+config_host_data.set('CONFIG_HMP', have_hmp)
audio_drivers_selected = []
if have_system
audio_drivers_available = {
diff --git a/meson_options.txt b/meson_options.txt
index a07cb47d35e..d8f59cf92ca 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -111,6 +111,8 @@ option('cfi', type: 'boolean', value: false,
description: 'Control-Flow Integrity (CFI)')
option('cfi_debug', type: 'boolean', value: false,
description: 'Verbose errors in case of CFI violation')
+option('hmp', type : 'feature', value : 'auto',
+ description: 'HMP monitor support')
option('multiprocess', type: 'feature', value: 'auto',
description: 'Out of process device emulation support')
option('relocatable', type : 'boolean', value : true,
diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh
index c003985047c..5a67e59a167 100644
--- a/scripts/meson-buildoptions.sh
+++ b/scripts/meson-buildoptions.sh
@@ -125,6 +125,7 @@ meson_options_help() {
printf "%s\n" ' gtk GTK+ user interface'
printf "%s\n" ' guest-agent Build QEMU Guest Agent'
printf "%s\n" ' guest-agent-msi Build MSI package for the QEMU Guest Agent'
+ printf "%s\n" ' hmp HMP monitor support'
printf "%s\n" ' hv-balloon hv-balloon driver (requires Glib 2.68+ GTree API)'
printf "%s\n" ' hvf HVF acceleration support'
printf "%s\n" ' iconv Font glyph conversion support'
@@ -339,6 +340,8 @@ _meson_option_parse() {
--disable-guest-agent-msi) printf "%s" -Dguest_agent_msi=disabled ;;
--enable-hexagon-idef-parser) printf "%s" -Dhexagon_idef_parser=true ;;
--disable-hexagon-idef-parser) printf "%s" -Dhexagon_idef_parser=false ;;
+ --enable-hmp) printf "%s" -Dhmp=enabled ;;
+ --disable-hmp) printf "%s" -Dhmp=disabled ;;
--enable-hv-balloon) printf "%s" -Dhv_balloon=enabled ;;
--disable-hv-balloon) printf "%s" -Dhv_balloon=disabled ;;
--enable-hvf) printf "%s" -Dhvf=enabled ;;
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 30/40] tests/qtest/device-introspect-test: fix test without HMP
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (28 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 29/40] build-sys: add 'hmp' option Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 31/40] tests/qtest/drive_del-test: guard HMP-dependent tests with CONFIG_HMP Marc-André Lureau
` (10 subsequent siblings)
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Replace "info qom-tree" with recursive qom-list walk.
Disable HMP-only code paths, info qtree, kinda duplicating the test.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
tests/qtest/device-introspect-test.c | 111 +++++++++++++++++++++++++++--------
1 file changed, 88 insertions(+), 23 deletions(-)
diff --git a/tests/qtest/device-introspect-test.c b/tests/qtest/device-introspect-test.c
index f84cec51dc2..f6eca2c8eb7 100644
--- a/tests/qtest/device-introspect-test.c
+++ b/tests/qtest/device-introspect-test.c
@@ -11,10 +11,10 @@
*/
/*
- * Covers QMP device-list-properties and HMP device_add help. We
- * currently don't check that their output makes sense, only that QEMU
- * survives. Useful since we've had an astounding number of crash
- * bugs around here.
+ * Covers QMP device-list-properties and HMP device_add help (if
+ * CONFIG_HMP). We currently don't check that the output makes sense,
+ * only that QEMU survives. Useful since we've had an astounding
+ * number of crash bugs around here.
*/
#include "qemu/osdep.h"
@@ -100,11 +100,60 @@ static QList *device_type_list(QTestState *qts, bool abstract)
return qom_list_types(qts, "device", abstract);
}
+/*
+ * Recursively walk the QOM composition tree via qom-list and build a
+ * string representation. This serves two purposes: detecting dangling
+ * pointers (qom-list would crash QEMU) and detecting leaked objects
+ * (by comparing the output before and after device introspection).
+ */
+static void qom_tree_walk(QTestState *qts, const char *path, GString *result)
+{
+ QDict *resp;
+ QList *list;
+ QListEntry *e;
+ GList *children = NULL;
+
+ resp = qtest_qmp(qts, "{'execute': 'qom-list',"
+ " 'arguments': {'path': %s}}", path);
+ g_assert(qdict_haskey(resp, "return"));
+ list = qdict_get_qlist(resp, "return");
+
+ QLIST_FOREACH_ENTRY(list, e) {
+ QDict *prop = qobject_to(QDict, qlist_entry_obj(e));
+ const char *type = qdict_get_str(prop, "type");
+ if (g_str_has_prefix(type, "child<")) {
+ const char *name = qdict_get_str(prop, "name");
+ children = g_list_prepend(children, g_strdup(name));
+ }
+ }
+
+ children = g_list_sort_with_data(children, (GCompareDataFunc)g_strcmp0,
+ NULL);
+
+ for (GList *l = children; l; l = l->next) {
+ const char *name = l->data;
+ g_autofree char *child_path = (!strcmp(path, "/"))
+ ? g_strdup_printf("/%s", name)
+ : g_strdup_printf("%s/%s", path, name);
+
+ g_string_append_printf(result, "%s\n", child_path);
+ qom_tree_walk(qts, child_path, result);
+ }
+
+ g_list_free_full(children, g_free);
+ qobject_unref(resp);
+}
+
+static char *qom_tree_str(QTestState *qts)
+{
+ GString *result = g_string_new("");
+ qom_tree_walk(qts, "/", result);
+ return g_string_free(result, FALSE);
+}
+
static void test_one_device(QTestState *qts, const char *type)
{
QDict *resp;
- char *help, *escaped;
- GRegex *comma;
g_test_message("Testing device '%s'", type);
@@ -113,19 +162,21 @@ static void test_one_device(QTestState *qts, const char *type)
type);
qobject_unref(resp);
- comma = g_regex_new(",", 0, 0, NULL);
- escaped = g_regex_replace_literal(comma, type, -1, 0, ",,", 0, NULL);
- g_regex_unref(comma);
+#ifdef CONFIG_HMP
+ {
+ g_autofree char *escaped = NULL;
+ g_autoptr(GRegex) comma = NULL;
- help = qtest_hmp(qts, "device_add \"%s,help\"", escaped);
- g_free(help);
- g_free(escaped);
+ comma = g_regex_new(",", 0, 0, NULL);
+ escaped = g_regex_replace_literal(comma, type, -1, 0, ",,", 0, NULL);
+ g_free(qtest_hmp(qts, "device_add \"%s,help\"", escaped));
+ }
+#endif
}
static void test_device_intro_list(void)
{
QList *types;
- char *help;
QTestState *qts;
qts = qtest_init(common_args);
@@ -133,8 +184,11 @@ static void test_device_intro_list(void)
types = device_type_list(qts, true);
qobject_unref(types);
- help = qtest_hmp(qts, "device_add help");
- g_free(help);
+#ifdef CONFIG_HMP
+ {
+ g_free(qtest_hmp(qts, "device_add help"));
+ }
+#endif
qtest_quit(qts);
}
@@ -198,18 +252,22 @@ static void test_qom_list_fields(void)
static void test_device_intro_none(void)
{
QTestState *qts = qtest_init(common_args);
- g_autofree char *qom_tree_start = qtest_hmp(qts, "info qom-tree");
+ g_autofree char *qom_tree_start = qom_tree_str(qts);
g_autofree char *qom_tree_end = NULL;
+#ifdef CONFIG_HMP
g_autofree char *qtree_start = qtest_hmp(qts, "info qtree");
g_autofree char *qtree_end = NULL;
+#endif
test_one_device(qts, "nonexistent");
/* Make sure that really nothing changed in the trees */
- qom_tree_end = qtest_hmp(qts, "info qom-tree");
+ qom_tree_end = qom_tree_str(qts);
g_assert_cmpstr(qom_tree_start, ==, qom_tree_end);
+#ifdef CONFIG_HMP
qtree_end = qtest_hmp(qts, "info qtree");
g_assert_cmpstr(qtree_start, ==, qtree_end);
+#endif
qtest_quit(qts);
}
@@ -217,18 +275,22 @@ static void test_device_intro_none(void)
static void test_device_intro_abstract(void)
{
QTestState *qts = qtest_init(common_args);
- g_autofree char *qom_tree_start = qtest_hmp(qts, "info qom-tree");
+ g_autofree char *qom_tree_start = qom_tree_str(qts);
g_autofree char *qom_tree_end = NULL;
+#ifdef CONFIG_HMP
g_autofree char *qtree_start = qtest_hmp(qts, "info qtree");
g_autofree char *qtree_end = NULL;
+#endif
test_one_device(qts, "device");
/* Make sure that really nothing changed in the trees */
- qom_tree_end = qtest_hmp(qts, "info qom-tree");
+ qom_tree_end = qom_tree_str(qts);
g_assert_cmpstr(qom_tree_start, ==, qom_tree_end);
+#ifdef CONFIG_HMP
qtree_end = qtest_hmp(qts, "info qtree");
g_assert_cmpstr(qtree_start, ==, qtree_end);
+#endif
qtest_quit(qts);
}
@@ -239,10 +301,12 @@ static void test_device_intro_concrete(const void *args)
QListEntry *entry;
const char *type;
QTestState *qts = qtest_init(args);
- g_autofree char *qom_tree_start = qtest_hmp(qts, "info qom-tree");
+ g_autofree char *qom_tree_start = qom_tree_str(qts);
g_autofree char *qom_tree_end = NULL;
+#ifdef CONFIG_HMP
g_autofree char *qtree_start = qtest_hmp(qts, "info qtree");
g_autofree char *qtree_end = NULL;
+#endif
types = device_type_list(qts, false);
@@ -255,14 +319,15 @@ static void test_device_intro_concrete(const void *args)
/*
* Some devices leave dangling pointers in QOM behind.
- * "info qom-tree" or "info qtree" have a good chance at crashing then.
+ * Walking the QOM tree via qom-list has a good chance at crashing then.
* Also make sure that the tree did not change.
*/
- qom_tree_end = qtest_hmp(qts, "info qom-tree");
+ qom_tree_end = qom_tree_str(qts);
g_assert_cmpstr(qom_tree_start, ==, qom_tree_end);
-
+#ifdef CONFIG_HMP
qtree_end = qtest_hmp(qts, "info qtree");
g_assert_cmpstr(qtree_start, ==, qtree_end);
+#endif
qobject_unref(types);
qtest_quit(qts);
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 31/40] tests/qtest/drive_del-test: guard HMP-dependent tests with CONFIG_HMP
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (29 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 30/40] tests/qtest/device-introspect-test: fix test without HMP Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 32/40] qapi: make HMP-specific schema entries conditional on CONFIG_HMP Marc-André Lureau
` (9 subsequent siblings)
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
These tests rely on HMP commands (drive_add, drive_del) that have no
direct QMP equivalent. QMP's blockdev-del operates on node-names and
rejects deletion of in-use nodes, whereas HMP's drive_del operates on
BlockBackend IDs and can detach a drive from a device. The equivalent
QMP-based tests already exist (test_blockdev_add_device_add_and_del*).
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
tests/qtest/drive_del-test.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/tests/qtest/drive_del-test.c b/tests/qtest/drive_del-test.c
index 30d9451ddda..d78816d44a7 100644
--- a/tests/qtest/drive_del-test.c
+++ b/tests/qtest/drive_del-test.c
@@ -87,6 +87,7 @@ static void blockdev_add_with_media(QTestState *qts)
g_assert(has_blockdev(qts));
}
+#ifdef CONFIG_HMP
static void drive_add(QTestState *qts)
{
char *resp = qtest_hmp(qts, "drive_add 0 if=none,id=drive0");
@@ -117,6 +118,7 @@ static void drive_del(QTestState *qts)
g_assert(!has_drive(qts));
g_free(resp);
}
+#endif
/*
* qvirtio_get_dev_type:
@@ -163,6 +165,7 @@ static void device_del(QTestState *qts, bool and_reset)
qtest_qmp_eventwait(qts, "DEVICE_DELETED");
}
+#ifdef CONFIG_HMP
static void test_drive_without_dev(void)
{
QTestState *qts;
@@ -245,6 +248,7 @@ static void test_drive_del_device_del(void)
qtest_quit(qts);
}
+#endif
static void test_cli_device_del(void)
{
@@ -391,6 +395,7 @@ static void test_device_add_and_del_q35(void)
qtest_quit(qts);
}
+#ifdef CONFIG_HMP
static void test_drive_add_device_add_and_del(void)
{
QTestState *qts;
@@ -443,6 +448,7 @@ static void test_drive_add_device_add_and_del_q35(void)
qtest_quit(qts);
}
+#endif
static void test_blockdev_add_device_add_and_del(void)
{
@@ -501,19 +507,25 @@ int main(int argc, char **argv)
{
g_test_init(&argc, &argv, NULL);
+#ifdef CONFIG_HMP
qtest_add_func("/drive_del/without-dev", test_drive_without_dev);
+#endif
if (qvirtio_get_dev_type() != NULL) {
+#ifdef CONFIG_HMP
qtest_add_func("/drive_del/after_failed_device_add",
test_after_failed_device_add);
qtest_add_func("/drive_del/drive_del_device_del",
test_drive_del_device_del);
+#endif
qtest_add_func("/device_del/drive/cli_device",
test_cli_device_del);
qtest_add_func("/device_del/drive/device_add",
test_device_add_and_del);
+#ifdef CONFIG_HMP
qtest_add_func("/device_del/drive/drive_add_device_add",
test_drive_add_device_add_and_del);
+#endif
qtest_add_func("/device_del/empty",
test_empty_device_del);
qtest_add_func("/device_del/blockdev",
@@ -524,8 +536,10 @@ int main(int argc, char **argv)
test_cli_device_del_q35);
qtest_add_func("/device_del/drive/device_add_q35",
test_device_add_and_del_q35);
+#ifdef CONFIG_HMP
qtest_add_func("/device_del/drive/drive_add_device_add_q35",
test_drive_add_device_add_and_del_q35);
+#endif
qtest_add_func("/device_del/blockdev_q35",
test_blockdev_add_device_add_and_del_q35);
}
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 32/40] qapi: make HMP-specific schema entries conditional on CONFIG_HMP
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (30 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 31/40] tests/qtest/drive_del-test: guard HMP-dependent tests with CONFIG_HMP Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 33/40] monitor: guard HMP-specific code with CONFIG_HMP Marc-André Lureau
` (8 subsequent siblings)
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Make the 'readline' value of MonitorMode and the
'human-monitor-command' command conditional on CONFIG_HMP, so
they are only available when HMP support is compiled in.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
qapi/control.json | 4 +++-
qapi/misc.json | 3 ++-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/qapi/control.json b/qapi/control.json
index 9a5302193d6..9898552814b 100644
--- a/qapi/control.json
+++ b/qapi/control.json
@@ -186,7 +186,9 @@
#
# Since: 5.0
##
-{ 'enum': 'MonitorMode', 'data': [ 'readline', 'control' ] }
+{ 'enum': 'MonitorMode', 'data': [
+ { 'name': 'readline', 'if': 'CONFIG_HMP' },
+ 'control' ] }
##
# @MonitorOptions:
diff --git a/qapi/misc.json b/qapi/misc.json
index 22b7afed9f6..a21ba61b96e 100644
--- a/qapi/misc.json
+++ b/qapi/misc.json
@@ -247,7 +247,8 @@
{ 'command': 'human-monitor-command',
'data': {'command-line': 'str', '*cpu-index': 'int'},
'returns': 'str',
- 'features': [ 'savevm-monitor-nodes' ] }
+ 'features': [ 'savevm-monitor-nodes' ],
+ 'if': 'CONFIG_HMP' }
##
# @getfd:
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 33/40] monitor: guard HMP-specific code with CONFIG_HMP
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (31 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 32/40] qapi: make HMP-specific schema entries conditional on CONFIG_HMP Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 34/40] util: guard monitor_vprintf callers " Marc-André Lureau
` (7 subsequent siblings)
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Add #ifdef CONFIG_HMP guards around HMP-specific declarations in
monitor headers and implementations:
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
include/monitor/hmp.h | 2 ++
include/monitor/monitor.h | 11 +++++++++++
monitor/monitor.c | 31 +++++++++++++++++++++++++++++++
monitor/qmp-cmds.c | 2 ++
stubs/monitor-core.c | 2 ++
stubs/monitor-internal.c | 2 ++
6 files changed, 50 insertions(+)
diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h
index 9258a049bff..7bc524cd4ff 100644
--- a/include/monitor/hmp.h
+++ b/include/monitor/hmp.h
@@ -14,6 +14,7 @@
#ifndef HMP_H
#define HMP_H
+#ifdef CONFIG_HMP
#include "qemu/readline.h"
#include "qapi/qapi-types-common.h"
#include "monitor/monitor.h"
@@ -195,3 +196,4 @@ void hmp_info_cmma(Monitor *mon, const QDict *qdict);
void hmp_migrationmode(Monitor *mon, const QDict *qdict);
#endif
+#endif
diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
index 17182e626a7..3457f4a7f88 100644
--- a/include/monitor/monitor.h
+++ b/include/monitor/monitor.h
@@ -20,7 +20,9 @@ bool monitor_cur_is_qmp(void);
void monitor_init_globals(void);
void monitor_init_globals_core(void);
void monitor_init_qmp(Chardev *chr, bool pretty, Error **errp);
+#ifdef CONFIG_HMP
void monitor_init_hmp(Chardev *chr, bool use_readline, Error **errp);
+#endif
int monitor_init(MonitorOptions *opts, bool allow_hmp, Error **errp);
int monitor_init_opts(QemuOpts *opts, Error **errp);
void monitor_cleanup(void);
@@ -32,28 +34,37 @@ int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp);
int monitor_fd_param(Monitor *mon, const char *fdname, Error **errp);
int monitor_puts(Monitor *mon, const char *str);
+
+#ifdef CONFIG_HMP
int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
G_GNUC_PRINTF(2, 0);
int monitor_printf(Monitor *mon, const char *fmt, ...) G_GNUC_PRINTF(2, 3);
void monitor_printc(Monitor *mon, int ch);
+#endif
+
void monitor_flush(Monitor *mon);
int monitor_get_cpu_index(Monitor *mon);
int monitor_puts_locked(Monitor *mon, const char *str);
void monitor_flush_locked(Monitor *mon);
+
+#ifdef CONFIG_HMP
void monitor_read_command(MonitorHMP *mon, int show_prompt);
int monitor_read_password(MonitorHMP *mon, ReadLineFunc *readline_func,
void *opaque);
+#endif
AddfdInfo *monitor_fdset_add_fd(int fd, bool has_fdset_id, int64_t fdset_id,
const char *opaque, Error **errp);
int monitor_fdset_dup_fd_add(int64_t fdset_id, int flags, Error **errp);
void monitor_fdset_dup_fd_remove(int dup_fd);
+#ifdef CONFIG_HMP
void monitor_register_hmp(const char *name, bool info,
void (*cmd)(Monitor *mon, const QDict *qdict));
void monitor_register_hmp_info_hrt(const char *name,
HumanReadableText *(*handler)(Error **errp));
+#endif
#endif /* MONITOR_H */
diff --git a/monitor/monitor.c b/monitor/monitor.c
index 2dec0e299af..096a5ee748d 100644
--- a/monitor/monitor.c
+++ b/monitor/monitor.c
@@ -116,6 +116,7 @@ bool monitor_cur_is_qmp(void)
return cur_mon && monitor_is_qmp(cur_mon);
}
+#ifdef CONFIG_HMP
/**
* Is @mon is using readline?
* Note: not all HMP monitors use readline, e.g., gdbserver has a
@@ -134,6 +135,12 @@ static inline bool monitor_is_hmp_non_interactive(const Monitor *mon)
return !monitor_uses_readline(container_of(mon, MonitorHMP, common));
}
+#else
+static inline bool monitor_is_hmp_non_interactive(const Monitor *mon)
+{
+ return false;
+}
+#endif
static gboolean monitor_unblocked(void *do_not_use, GIOCondition cond,
void *opaque)
@@ -211,6 +218,7 @@ int monitor_puts(Monitor *mon, const char *str)
return monitor_puts_locked(mon, str);
}
+#ifdef CONFIG_HMP
int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
{
char *buf;
@@ -267,6 +275,7 @@ void monitor_printc(Monitor *mon, int c)
}
monitor_printf(mon, "'");
}
+#endif
static MonitorQAPIEventConf monitor_qapi_event_conf[QAPI_EVENT__MAX] = {
/* Limit guest-triggerable events to 1 per second */
@@ -541,6 +550,7 @@ static void monitor_accept_input(void *opaque)
Monitor *mon = opaque;
qemu_mutex_lock(&mon->mon_lock);
+#ifdef CONFIG_HMP
if (!monitor_is_qmp(mon)) {
MonitorHMP *hmp_mon = container_of(mon, MonitorHMP, common);
assert(hmp_mon->rs);
@@ -555,6 +565,9 @@ static void monitor_accept_input(void *opaque)
} else {
qemu_mutex_unlock(&mon->mon_lock);
}
+#else
+ qemu_mutex_unlock(&mon->mon_lock);
+#endif
qemu_chr_fe_accept_input(&mon->chr);
}
@@ -631,9 +644,11 @@ void monitor_data_destroy(Monitor *mon)
if (monitor_is_qmp(mon)) {
monitor_data_destroy_qmp(container_of(mon, MonitorQMP, common));
} else {
+#ifdef CONFIG_HMP
MonitorHMP *hmp_mon = container_of(mon, MonitorHMP, common);
readline_free(hmp_mon->rs);
g_free(hmp_mon->mon_cpu_path);
+#endif
}
g_string_free(mon->outbuf, true);
qemu_mutex_destroy(&mon->mon_lock);
@@ -733,13 +748,18 @@ int monitor_init(MonitorOptions *opts, bool allow_hmp, Error **errp)
}
if (!opts->has_mode) {
+#ifdef CONFIG_HMP
opts->mode = allow_hmp ? MONITOR_MODE_READLINE : MONITOR_MODE_CONTROL;
+#else
+ opts->mode = MONITOR_MODE_CONTROL;
+#endif
}
switch (opts->mode) {
case MONITOR_MODE_CONTROL:
monitor_init_qmp(chr, opts->pretty, errp);
break;
+#ifdef CONFIG_HMP
case MONITOR_MODE_READLINE:
if (!allow_hmp) {
error_setg(errp, "Only QMP is supported");
@@ -751,6 +771,7 @@ int monitor_init(MonitorOptions *opts, bool allow_hmp, Error **errp)
}
monitor_init_hmp(chr, true, errp);
break;
+#endif
default:
g_assert_not_reached();
}
@@ -764,6 +785,16 @@ int monitor_init_opts(QemuOpts *opts, Error **errp)
MonitorOptions *options;
int ret;
+#ifndef CONFIG_HMP
+ const char *mode = qemu_opt_get(opts, "mode");
+ /* readline is HMP.. */
+ if (mode && g_str_equal(mode, "readline")) {
+ error_setg(errp, "HMP monitor is not available,"
+ " use '-qmp' instead of '-monitor'");
+ return -1;
+ }
+#endif
+
v = opts_visitor_new(opts);
visit_type_MonitorOptions(v, NULL, &options, errp);
visit_free(v);
diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c
index 0c409c27dc3..cca25c18a15 100644
--- a/monitor/qmp-cmds.c
+++ b/monitor/qmp-cmds.c
@@ -162,6 +162,7 @@ void qmp_add_client(const char *protocol, const char *fdname,
}
}
+#ifdef CONFIG_HMP
char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
int64_t cpu_index, Error **errp)
{
@@ -189,6 +190,7 @@ out:
monitor_data_destroy(&hmp.common);
return output;
}
+#endif
static void __attribute__((__constructor__)) monitor_init_qmp_commands(void)
{
diff --git a/stubs/monitor-core.c b/stubs/monitor-core.c
index 078a5012e9b..b4a4de41aa2 100644
--- a/stubs/monitor-core.c
+++ b/stubs/monitor-core.c
@@ -21,6 +21,7 @@ void qapi_event_emit(QAPIEvent event, QDict *qdict)
{
}
+#ifdef CONFIG_HMP
int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
{
/*
@@ -37,3 +38,4 @@ int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
}
return -1;
}
+#endif
diff --git a/stubs/monitor-internal.c b/stubs/monitor-internal.c
index 4fece49d531..29274bd2b4a 100644
--- a/stubs/monitor-internal.c
+++ b/stubs/monitor-internal.c
@@ -8,6 +8,8 @@ int monitor_get_fd(Monitor *mon, const char *name, Error **errp)
return -1;
}
+#ifdef CONFIG_HMP
void monitor_init_hmp(Chardev *chr, bool use_readline, Error **errp)
{
}
+#endif
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 34/40] util: guard monitor_vprintf callers with CONFIG_HMP
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (32 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 33/40] monitor: guard HMP-specific code with CONFIG_HMP Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 35/40] system: guard HMP initialization paths " Marc-André Lureau
` (6 subsequent siblings)
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Guard calls to monitor_vprintf in error-report and qemu-print so
they compile without HMP. When CONFIG_HMP is not set,
error_vprintf_mon falls back directly to stderr and qemu_vfprintf
returns -1 for NULL streams.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
tests/unit/test-util-sockets.c | 4 +++-
tools/qemu-vnc/stubs.c | 2 ++
util/error-report.c | 8 +++++---
util/qemu-print.c | 6 ++++++
4 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/tests/unit/test-util-sockets.c b/tests/unit/test-util-sockets.c
index b9f2453e299..23ebe1e26b5 100644
--- a/tests/unit/test-util-sockets.c
+++ b/tests/unit/test-util-sockets.c
@@ -73,8 +73,10 @@ int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp)
*/
Monitor *monitor_cur(void) { return cur_mon; }
Monitor *monitor_set_cur(Coroutine *co, Monitor *mon) { abort(); }
-int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) { abort(); }
bool monitor_cur_is_qmp(void) { abort(); };
+#ifdef CONFIG_HMP
+int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) { abort(); }
+#endif
#ifndef _WIN32
static void test_socket_fd_pass_name_good(void)
diff --git a/tools/qemu-vnc/stubs.c b/tools/qemu-vnc/stubs.c
index a865ce85f04..f476dd6d956 100644
--- a/tools/qemu-vnc/stubs.c
+++ b/tools/qemu-vnc/stubs.c
@@ -46,10 +46,12 @@ Monitor *monitor_set_cur(Coroutine *co, Monitor *mon)
return NULL;
}
+#ifdef CONFIG_HMP
int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
{
return -1;
}
+#endif
/*
* Link-time stubs for VMState symbols referenced by VNC code.
diff --git a/util/error-report.c b/util/error-report.c
index f832ad9b6b6..e2e46281455 100644
--- a/util/error-report.c
+++ b/util/error-report.c
@@ -40,11 +40,13 @@ error_vprintf_mon(Monitor *cur_mon, const char *fmt, va_list ap)
* IOW this will only print if in HMP, otherwise we
* fallback to stderr for QMP / no-monitor scenarios.
*/
+#ifdef CONFIG_HMP
int ret = monitor_vprintf(cur_mon, fmt, ap);
- if (ret == -1) {
- ret = vfprintf(stderr, fmt, ap);
+ if (ret != -1) {
+ return ret;
}
- return ret;
+#endif
+ return vfprintf(stderr, fmt, ap);
}
/*
diff --git a/util/qemu-print.c b/util/qemu-print.c
index 7b9591035e5..ee80000722b 100644
--- a/util/qemu-print.c
+++ b/util/qemu-print.c
@@ -20,10 +20,12 @@
*/
int qemu_vprintf(const char *fmt, va_list ap)
{
+#ifdef CONFIG_HMP
Monitor *cur_mon = monitor_cur();
if (cur_mon) {
return monitor_vprintf(cur_mon, fmt, ap);
}
+#endif
return vprintf(fmt, ap);
}
@@ -52,7 +54,11 @@ int qemu_printf(const char *fmt, ...)
int qemu_vfprintf(FILE *stream, const char *fmt, va_list ap)
{
if (!stream) {
+#ifdef CONFIG_HMP
return monitor_vprintf(monitor_cur(), fmt, ap);
+#else
+ return -1;
+#endif
}
return vfprintf(stream, fmt, ap);
}
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 35/40] system: guard HMP initialization paths with CONFIG_HMP
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (33 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 34/40] util: guard monitor_vprintf callers " Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 36/40] hw: guard BusClass::print_dev " Marc-André Lureau
` (5 subsequent siblings)
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
- disable default monitor when HMP is not available
- hide 'readline' from -mon help text
- error out on mux chardev monitor when no HMP
- skip HMP monitor terminal for gdb, return E01 for 'qRcmd' remote
commands
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
chardev/char.c | 7 +++++++
gdbstub/system.c | 8 ++++++++
system/vl.c | 4 ++++
qemu-options.hx | 6 +++++-
4 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/chardev/char.c b/chardev/char.c
index ca8b37ed8d7..5f2b9fbc4bf 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -805,6 +805,7 @@ static Chardev *qemu_chr_new_from_name(const char *label, const char *filename,
if (qemu_opt_get_bool(opts, "mux", 0)) {
assert(permit_mux_mon);
+#ifdef CONFIG_HMP
monitor_init_hmp(chr, true, &err);
if (err) {
error_report_err(err);
@@ -812,6 +813,12 @@ static Chardev *qemu_chr_new_from_name(const char *label, const char *filename,
chr = NULL;
goto out;
}
+#else
+ error_report("HMP monitor is disabled");
+ object_unparent(OBJECT(chr));
+ chr = NULL;
+ goto out;
+#endif
}
out:
diff --git a/gdbstub/system.c b/gdbstub/system.c
index e86c5870abc..0c282c9c491 100644
--- a/gdbstub/system.c
+++ b/gdbstub/system.c
@@ -385,10 +385,14 @@ bool gdbserver_start(const char *device, Error **errp)
qemu_add_vm_change_state_handler(gdb_vm_state_change, NULL);
+#ifdef CONFIG_HMP
/* Initialize a monitor terminal for gdb */
mon_chr = qemu_chardev_new(NULL, TYPE_CHARDEV_GDB,
NULL, NULL, &error_abort);
monitor_init_hmp(mon_chr, false, &error_abort);
+#else
+ mon_chr = NULL;
+#endif
} else {
qemu_chr_fe_deinit(&gdbserver_system_state.chr, true);
mon_chr = gdbserver_system_state.mon_chr;
@@ -529,10 +533,14 @@ void gdb_handle_query_rcmd(GArray *params, void *ctx)
len = len / 2;
gdb_hextomem(gdbserver_state.mem_buf, gdb_get_cmd_param(params, 0)->data, len);
g_byte_array_append(gdbserver_state.mem_buf, &zero, 1);
+#ifdef CONFIG_HMP
qemu_chr_be_write(gdbserver_system_state.mon_chr,
gdbserver_state.mem_buf->data,
gdbserver_state.mem_buf->len);
gdb_put_packet("OK");
+#else
+ gdb_put_packet("E01");
+#endif
}
/*
diff --git a/system/vl.c b/system/vl.c
index 4797700abd5..f9fa00de07b 100644
--- a/system/vl.c
+++ b/system/vl.c
@@ -199,7 +199,11 @@ static int has_defaults = 1;
static int default_audio = 1;
static int default_serial = 1;
static int default_parallel = 1;
+#ifdef CONFIG_HMP
static int default_monitor = 1;
+#else
+static int default_monitor; /* false */
+#endif
static int default_floppy = 1;
static int default_cdrom = 1;
static bool auto_create_sdcard = true;
diff --git a/qemu-options.hx b/qemu-options.hx
index 4c1b32713e0..d788467b83f 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -4941,7 +4941,11 @@ SRST
ERST
DEF("mon", HAS_ARG, QEMU_OPTION_mon, \
- "-mon [chardev=]name[,mode=readline|control][,pretty=on|off]\n", QEMU_ARCH_ALL)
+ "-mon [chardev=]name[,mode="
+#ifdef CONFIG_HMP
+ "readline|"
+#endif
+ "control][,pretty=on|off]\n", QEMU_ARCH_ALL)
SRST
``-mon [chardev=]name[,mode=readline|control][,pretty=on|off]``
Set up a monitor connected to the chardev ``name``.
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 36/40] hw: guard BusClass::print_dev with CONFIG_HMP
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (34 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 35/40] system: guard HMP initialization paths " Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-21 6:07 ` Philippe Mathieu-Daudé
2026-05-20 21:49 ` [PATCH 37/40] target: guard MonitorDef tables " Marc-André Lureau
` (4 subsequent siblings)
40 siblings, 1 reply; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
The print_dev callback is only used by HMP 'info qtree'. Guard the field
in BusClass, all implementations, and the caller with CONFIG_HMP.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
include/hw/core/qdev.h | 2 ++
hw/char/virtio-serial-bus.c | 6 ++++++
hw/core/sysbus.c | 6 ++++++
hw/misc/auxbus.c | 16 +++++++++++-----
hw/pci/pci-hmp-cmds.c | 2 ++
hw/pci/pci.c | 2 ++
hw/usb/bus.c | 6 ++++++
hw/xen/xen-bus.c | 4 ++++
system/qdev-monitor.c | 2 ++
9 files changed, 41 insertions(+), 5 deletions(-)
diff --git a/include/hw/core/qdev.h b/include/hw/core/qdev.h
index e1476223411..22dd143acf0 100644
--- a/include/hw/core/qdev.h
+++ b/include/hw/core/qdev.h
@@ -322,8 +322,10 @@ DECLARE_OBJ_CHECKERS(BusState, BusClass,
struct BusClass {
ObjectClass parent_class;
+#ifdef CONFIG_HMP
/* FIXME first arg should be BusState */
void (*print_dev)(Monitor *mon, DeviceState *dev, int indent);
+#endif
/*
* Return a newly allocated string containing the path of the
* device on this bus.
diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
index cd234dc6db1..34a723a8715 100644
--- a/hw/char/virtio-serial-bus.c
+++ b/hw/char/virtio-serial-bus.c
@@ -833,7 +833,9 @@ static int virtio_serial_load_device(VirtIODevice *vdev, QEMUFile *f,
return 0;
}
+#ifdef CONFIG_HMP
static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent);
+#endif
static const Property virtser_props[] = {
DEFINE_PROP_UINT32("nr", VirtIOSerialPort, id, VIRTIO_CONSOLE_BAD_ID),
@@ -842,8 +844,10 @@ static const Property virtser_props[] = {
static void virtser_bus_class_init(ObjectClass *klass, const void *data)
{
+#ifdef CONFIG_HMP
BusClass *k = BUS_CLASS(klass);
k->print_dev = virtser_bus_dev_print;
+#endif
}
static const TypeInfo virtser_bus_info = {
@@ -853,6 +857,7 @@ static const TypeInfo virtser_bus_info = {
.class_init = virtser_bus_class_init,
};
+#ifdef CONFIG_HMP
static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
{
VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(qdev);
@@ -863,6 +868,7 @@ static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
port->host_connected ? "on" : "off",
port->throttled ? "on" : "off");
}
+#endif
/* This function is only used if a port id is not provided by the user */
static uint32_t find_free_port_id(VirtIOSerial *vser)
diff --git a/hw/core/sysbus.c b/hw/core/sysbus.c
index 3e1160ee921..0b970d6b64f 100644
--- a/hw/core/sysbus.c
+++ b/hw/core/sysbus.c
@@ -23,7 +23,9 @@
#include "monitor/monitor.h"
#include "system/address-spaces.h"
+#ifdef CONFIG_HMP
static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent);
+#endif
static char *sysbus_get_fw_dev_path(DeviceState *dev);
typedef struct SysBusFind {
@@ -75,7 +77,9 @@ static void system_bus_class_init(ObjectClass *klass, const void *data)
{
BusClass *k = BUS_CLASS(klass);
+#ifdef CONFIG_HMP
k->print_dev = sysbus_dev_print;
+#endif
k->get_fw_dev_path = sysbus_get_fw_dev_path;
}
@@ -248,6 +252,7 @@ bool sysbus_realize_and_unref(SysBusDevice *dev, Error **errp)
return qdev_realize_and_unref(DEVICE(dev), sysbus_get_default(), errp);
}
+#ifdef CONFIG_HMP
static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent)
{
SysBusDevice *s = SYS_BUS_DEVICE(dev);
@@ -260,6 +265,7 @@ static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent)
indent, "", s->mmio[i].addr, size);
}
}
+#endif
static char *sysbus_get_fw_dev_path(DeviceState *dev)
{
diff --git a/hw/misc/auxbus.c b/hw/misc/auxbus.c
index 877f3456062..dd0629620ac 100644
--- a/hw/misc/auxbus.c
+++ b/hw/misc/auxbus.c
@@ -46,18 +46,22 @@
} while (0)
+#ifdef CONFIG_HMP
static void aux_slave_dev_print(Monitor *mon, DeviceState *dev, int indent);
+#endif
static inline I2CBus *aux_bridge_get_i2c_bus(AUXTOI2CState *bridge);
/* aux-bus implementation (internal not public) */
static void aux_bus_class_init(ObjectClass *klass, const void *data)
{
+#ifdef CONFIG_HMP
BusClass *k = BUS_CLASS(klass);
/* AUXSlave has an MMIO so we need to change the way we print information
* in monitor.
*/
k->print_dev = aux_slave_dev_print;
+#endif
}
AUXBus *aux_bus_init(DeviceState *parent, const char *name)
@@ -90,11 +94,6 @@ void aux_map_slave(AUXSlave *aux_dev, hwaddr addr)
memory_region_add_subregion(bus->aux_io, addr, aux_dev->mmio);
}
-static bool aux_bus_is_bridge(AUXBus *bus, DeviceState *dev)
-{
- return (dev == DEVICE(bus->bridge));
-}
-
I2CBus *aux_get_i2c_bus(AUXBus *bus)
{
return aux_bridge_get_i2c_bus(bus->bridge);
@@ -287,6 +286,12 @@ static const TypeInfo aux_to_i2c_type_info = {
};
/* aux-slave implementation */
+#ifdef CONFIG_HMP
+static bool aux_bus_is_bridge(AUXBus *bus, DeviceState *dev)
+{
+ return (dev == DEVICE(bus->bridge));
+}
+
static void aux_slave_dev_print(Monitor *mon, DeviceState *dev, int indent)
{
AUXBus *bus = AUX_BUS(qdev_get_parent_bus(dev));
@@ -304,6 +309,7 @@ static void aux_slave_dev_print(Monitor *mon, DeviceState *dev, int indent)
object_property_get_uint(OBJECT(s->mmio), "addr", NULL),
memory_region_size(s->mmio));
}
+#endif
void aux_init_mmio(AUXSlave *aux_slave, MemoryRegion *mmio)
{
diff --git a/hw/pci/pci-hmp-cmds.c b/hw/pci/pci-hmp-cmds.c
index a5f6483cc3d..3e378eadfaa 100644
--- a/hw/pci/pci-hmp-cmds.c
+++ b/hw/pci/pci-hmp-cmds.c
@@ -134,6 +134,7 @@ void hmp_info_pci(Monitor *mon, const QDict *qdict)
qapi_free_PciInfoList(info_list);
}
+#ifdef CONFIG_HMP
void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent)
{
PCIDevice *d = (PCIDevice *)dev;
@@ -169,6 +170,7 @@ void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent)
r->addr, r->addr + r->size - 1);
}
}
+#endif
void hmp_pcie_aer_inject_error(Monitor *mon, const QDict *qdict)
{
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 4298adf5a0a..c67aeb67f4c 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -283,7 +283,9 @@ static void pci_bus_class_init(ObjectClass *klass, const void *data)
ResettableClass *rc = RESETTABLE_CLASS(klass);
FWCfgDataGeneratorClass *fwgc = FW_CFG_DATA_GENERATOR_CLASS(klass);
+#ifdef CONFIG_HMP
k->print_dev = pcibus_dev_print;
+#endif
k->get_dev_path = pcibus_get_dev_path;
k->get_fw_dev_path = pcibus_get_fw_dev_path;
k->realize = pci_bus_realize;
diff --git a/hw/usb/bus.c b/hw/usb/bus.c
index 3b6fbd46ac3..753f2d9be56 100644
--- a/hw/usb/bus.c
+++ b/hw/usb/bus.c
@@ -12,7 +12,9 @@
#include "trace.h"
#include "qemu/cutils.h"
+#ifdef CONFIG_HMP
static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent);
+#endif
static char *usb_get_dev_path(DeviceState *dev);
static char *usb_get_fw_dev_path(DeviceState *qdev);
@@ -31,7 +33,9 @@ static void usb_bus_class_init(ObjectClass *klass, const void *data)
BusClass *k = BUS_CLASS(klass);
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
+#ifdef CONFIG_HMP
k->print_dev = usb_bus_dev_print;
+#endif
k->get_dev_path = usb_get_dev_path;
k->get_fw_dev_path = usb_get_fw_dev_path;
hc->unplug = qdev_simple_device_unplug_cb;
@@ -543,6 +547,7 @@ static const char *usb_speed(unsigned int speed)
return txt[speed];
}
+#ifdef CONFIG_HMP
static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
{
USBDevice *dev = USB_DEVICE(qdev);
@@ -554,6 +559,7 @@ static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
usb_speed(dev->speed), dev->product_desc,
dev->attached ? ", attached" : "");
}
+#endif
static char *usb_get_dev_path(DeviceState *qdev)
{
diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c
index dfad2bc5085..439cd47e849 100644
--- a/hw/xen/xen-bus.c
+++ b/hw/xen/xen-bus.c
@@ -100,6 +100,7 @@ abort:
qemu_xen_xs_transaction_end(xenbus->xsh, tid, true);
}
+#ifdef CONFIG_HMP
static void xen_bus_print_dev(Monitor *mon, DeviceState *dev, int indent)
{
XenDevice *xendev = XEN_DEVICE(dev);
@@ -107,6 +108,7 @@ static void xen_bus_print_dev(Monitor *mon, DeviceState *dev, int indent)
monitor_printf(mon, "%*sname = '%s' frontend_id = %u\n",
indent, "", xendev->name, xendev->frontend_id);
}
+#endif
static char *xen_bus_get_dev_path(DeviceState *dev)
{
@@ -385,7 +387,9 @@ static void xen_bus_class_init(ObjectClass *class, const void *data)
BusClass *bus_class = BUS_CLASS(class);
HotplugHandlerClass *hotplug_class = HOTPLUG_HANDLER_CLASS(class);
+#ifdef CONFIG_HMP
bus_class->print_dev = xen_bus_print_dev;
+#endif
bus_class->get_dev_path = xen_bus_get_dev_path;
bus_class->realize = xen_bus_realize;
bus_class->unrealize = xen_bus_unrealize;
diff --git a/system/qdev-monitor.c b/system/qdev-monitor.c
index e5b55e3004c..7ed2008d81f 100644
--- a/system/qdev-monitor.c
+++ b/system/qdev-monitor.c
@@ -763,6 +763,7 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp)
return ret;
}
+#ifdef CONFIG_HMP
#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
static void qdev_print_props(Monitor *mon, DeviceState *dev, DeviceClass *dc,
@@ -864,6 +865,7 @@ void hmp_info_qdm(Monitor *mon, const QDict *qdict)
{
qdev_print_devinfos(true);
}
+#endif
void qmp_device_add(QDict *qdict, QObject **ret_data, Error **errp)
{
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 37/40] target: guard MonitorDef tables with CONFIG_HMP
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (35 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 36/40] hw: guard BusClass::print_dev " Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 38/40] Guard HMP command implementations " Marc-André Lureau
` (3 subsequent siblings)
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Guard SysemuCPUOps::monitor_defs field and the per-target MonitorDef
arrays with CONFIG_HMP. These tables are only used by HMP 'print' and
'info registers' commands.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
include/hw/core/sysemu-cpu-ops.h | 2 ++
target/i386/cpu.c | 4 ++++
target/m68k/cpu.c | 4 ++++
target/sparc/cpu.c | 5 +++--
4 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/include/hw/core/sysemu-cpu-ops.h b/include/hw/core/sysemu-cpu-ops.h
index 441901fae8e..1d7d3700c93 100644
--- a/include/hw/core/sysemu-cpu-ops.h
+++ b/include/hw/core/sysemu-cpu-ops.h
@@ -120,11 +120,13 @@ typedef struct SysemuCPUOps {
*/
int (*monitor_get_register)(CPUState *cs, const char *name, int64_t *pval);
+#ifdef CONFIG_HMP
/**
* @monitor_defs: Array of MonitorDef entries. This field is legacy,
* use @gdb_core_xml_file to dump registers instead.
*/
const MonitorDef *monitor_defs;
+#endif
/**
* @legacy_vmsd: Legacy state for migration.
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 7248720a0eb..7efc223c787 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -10845,6 +10845,7 @@ static const Property x86_cpu_properties[] = {
#ifndef CONFIG_USER_ONLY
+#ifdef CONFIG_HMP
static int64_t monitor_get_pc(Monitor *mon, const struct MonitorDef *md,
int offset)
{
@@ -10870,6 +10871,7 @@ static const MonitorDef x86_monitor_defs[] = {
{ NULL },
#undef SEG
};
+#endif
#include "hw/core/sysemu-cpu-ops.h"
@@ -10884,7 +10886,9 @@ static const struct SysemuCPUOps i386_sysemu_ops = {
.write_elf64_note = x86_cpu_write_elf64_note,
.write_elf32_qemunote = x86_cpu_write_elf32_qemunote,
.write_elf64_qemunote = x86_cpu_write_elf64_qemunote,
+#ifdef CONFIG_HMP
.monitor_defs = x86_monitor_defs,
+#endif
.legacy_vmsd = &vmstate_x86_cpu,
};
#endif
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
index 9ad3057d91c..9955acb6c8d 100644
--- a/target/m68k/cpu.c
+++ b/target/m68k/cpu.c
@@ -603,6 +603,7 @@ static const VMStateDescription vmstate_m68k_cpu = {
},
};
+#ifdef CONFIG_HMP
static const MonitorDef m68k_monitor_defs[] = {
{ "ssp", offsetof(CPUM68KState, sp[0]) },
{ "usp", offsetof(CPUM68KState, sp[1]) },
@@ -618,13 +619,16 @@ static const MonitorDef m68k_monitor_defs[] = {
{ "mmusr", offsetof(CPUM68KState, mmu.mmusr) },
{ NULL },
};
+#endif
#include "hw/core/sysemu-cpu-ops.h"
static const struct SysemuCPUOps m68k_sysemu_ops = {
.has_work = m68k_cpu_has_work,
.get_phys_addr_debug = m68k_cpu_get_phys_addr_debug,
+#ifdef CONFIG_HMP
.monitor_defs = m68k_monitor_defs,
+#endif
};
#endif /* !CONFIG_USER_ONLY */
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
index 3df199ada7b..46af64c6a86 100644
--- a/target/sparc/cpu.c
+++ b/target/sparc/cpu.c
@@ -996,7 +996,7 @@ static const Property sparc_cpu_properties[] = {
#ifdef TARGET_SPARC64
#include "monitor/hmp.h"
-
+#ifdef CONFIG_HMP
static const MonitorDef sparc64_monitor_defs[] = {
{ "asi", offsetof(CPUSPARCState, asi) },
{ "pstate", offsetof(CPUSPARCState, pstate) },
@@ -1008,6 +1008,7 @@ static const MonitorDef sparc64_monitor_defs[] = {
{ NULL },
};
#endif
+#endif
#include "hw/core/sysemu-cpu-ops.h"
@@ -1015,7 +1016,7 @@ static const struct SysemuCPUOps sparc_sysemu_ops = {
.has_work = sparc_cpu_has_work,
.get_phys_addr_debug = sparc_cpu_get_phys_addr_debug,
.legacy_vmsd = &vmstate_sparc_cpu,
-#if defined(TARGET_SPARC64)
+#if defined(TARGET_SPARC64) && defined(CONFIG_HMP)
.monitor_defs = sparc64_monitor_defs,
#endif
};
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 38/40] Guard HMP command implementations with CONFIG_HMP
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (36 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 37/40] target: guard MonitorDef tables " Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 39/40] build-sys: make HMP source files conditional on have_hmp Marc-André Lureau
` (2 subsequent siblings)
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Add #ifdef CONFIG_HMP around all hmp_* function implementations
and their HMP-only helpers across subsystems.
This covers monitor_register_hmp* callers, hmp_info_* handlers,
and HMP-only helper functions like slirp_lookup.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
accel/accel-system.c | 2 ++
accel/tcg/monitor.c | 2 ++
hw/i386/kvm/xen-stubs.c | 2 ++
hw/i386/kvm/xen_evtchn.c | 3 ++-
hw/i386/sgx.c | 2 ++
hw/misc/mos6522-stub.c | 2 ++
hw/misc/mos6522.c | 2 ++
hw/pci/pci-stub.c | 2 ++
hw/s390x/s390-skeys.c | 2 ++
hw/s390x/s390-stattrib.c | 4 ++++
hw/uefi/ovmf-log.c | 2 ++
hw/usb/host-libusb.c | 6 ++++++
migration/dirtyrate.c | 2 ++
net/slirp.c | 7 ++++++-
replay/replay-debugging.c | 8 ++++++++
replay/stubs-system.c | 6 ++++++
system/dirtylimit.c | 6 ++++++
system/qdev-monitor.c | 2 ++
target/i386/cpu-apic.c | 2 ++
target/i386/monitor.c | 3 +++
target/i386/sev.c | 2 ++
target/m68k/monitor.c | 2 ++
target/ppc/monitor.c | 2 ++
target/riscv/monitor.c | 3 +++
target/sh4/monitor.c | 2 ++
target/sparc/monitor.c | 2 ++
target/xtensa/monitor.c | 2 ++
27 files changed, 80 insertions(+), 2 deletions(-)
diff --git a/accel/accel-system.c b/accel/accel-system.c
index 9176665202d..a8715924729 100644
--- a/accel/accel-system.c
+++ b/accel/accel-system.c
@@ -108,7 +108,9 @@ void accel_init_ops_interfaces(AccelClass *ac)
static void accel_ops_class_init(ObjectClass *oc, const void *data)
{
+#ifdef CONFIG_HMP
monitor_register_hmp_info_hrt("accel", qmp_x_accel_stats);
+#endif
}
static const TypeInfo accel_ops_type_info = {
diff --git a/accel/tcg/monitor.c b/accel/tcg/monitor.c
index be5c1950177..c860744536b 100644
--- a/accel/tcg/monitor.c
+++ b/accel/tcg/monitor.c
@@ -29,9 +29,11 @@ HumanReadableText *qmp_x_query_jit(Error **errp)
return human_readable_text_from_str(buf);
}
+#ifdef CONFIG_HMP
static void hmp_tcg_register(void)
{
monitor_register_hmp_info_hrt("jit", qmp_x_query_jit);
}
type_init(hmp_tcg_register);
+#endif
diff --git a/hw/i386/kvm/xen-stubs.c b/hw/i386/kvm/xen-stubs.c
index bf6ac28bef4..df36c84a4f4 100644
--- a/hw/i386/kvm/xen-stubs.c
+++ b/hw/i386/kvm/xen-stubs.c
@@ -40,6 +40,7 @@ void xen_primary_console_set_be_port(uint16_t port)
{
}
+#ifdef CONFIG_HMP
void hmp_xen_event_list(Monitor *mon, const QDict *qdict)
{
monitor_printf(mon, "XEN emulation is not available in this QEMU\n");
@@ -49,3 +50,4 @@ void hmp_xen_event_inject(Monitor *mon, const QDict *qdict)
{
monitor_printf(mon, "XEN emulation is not available in this QEMU\n");
}
+#endif
diff --git a/hw/i386/kvm/xen_evtchn.c b/hw/i386/kvm/xen_evtchn.c
index 8b243984e41..cb7b4c7a81b 100644
--- a/hw/i386/kvm/xen_evtchn.c
+++ b/hw/i386/kvm/xen_evtchn.c
@@ -2344,6 +2344,7 @@ void qmp_xen_event_inject(uint32_t port, Error **errp)
}
}
+#ifdef CONFIG_HMP
void hmp_xen_event_list(Monitor *mon, const QDict *qdict)
{
EvtchnInfoList *iter, *info_list;
@@ -2391,4 +2392,4 @@ void hmp_xen_event_inject(Monitor *mon, const QDict *qdict)
monitor_printf(mon, "Delivered port %d\n", port);
}
}
-
+#endif
diff --git a/hw/i386/sgx.c b/hw/i386/sgx.c
index 7e4c509f5a4..4ac8ea75aa7 100644
--- a/hw/i386/sgx.c
+++ b/hw/i386/sgx.c
@@ -234,6 +234,7 @@ SgxInfo *qmp_query_sgx(Error **errp)
return info;
}
+#ifdef CONFIG_HMP
void hmp_info_sgx(Monitor *mon, const QDict *qdict)
{
Error *err = NULL;
@@ -265,6 +266,7 @@ void hmp_info_sgx(Monitor *mon, const QDict *qdict)
monitor_printf(mon, "total size=%" PRIu64 "\n",
size);
}
+#endif
bool check_sgx_support(void)
{
diff --git a/hw/misc/mos6522-stub.c b/hw/misc/mos6522-stub.c
index 85eb0ee36ee..03fea6985a9 100644
--- a/hw/misc/mos6522-stub.c
+++ b/hw/misc/mos6522-stub.c
@@ -10,7 +10,9 @@
#include "monitor/monitor.h"
#include "monitor/hmp.h"
+#ifdef CONFIG_HMP
void hmp_info_via(Monitor *mon, const QDict *qdict)
{
monitor_printf(mon, "MOS6522 VIA is not available in this QEMU\n");
}
+#endif
diff --git a/hw/misc/mos6522.c b/hw/misc/mos6522.c
index bae766ef178..6be7ed3ff30 100644
--- a/hw/misc/mos6522.c
+++ b/hw/misc/mos6522.c
@@ -497,6 +497,7 @@ void mos6522_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
}
}
+#ifdef CONFIG_HMP
static int qmp_x_query_via_foreach(Object *obj, void *opaque)
{
GString *buf = opaque;
@@ -596,6 +597,7 @@ void hmp_info_via(Monitor *mon, const QDict *qdict)
}
monitor_puts(mon, info->human_readable_text);
}
+#endif /* CONFIG_HMP */
static const MemoryRegionOps mos6522_ops = {
.read = mos6522_read,
diff --git a/hw/pci/pci-stub.c b/hw/pci/pci-stub.c
index 3397d0c82ea..f217373ef03 100644
--- a/hw/pci/pci-stub.c
+++ b/hw/pci/pci-stub.c
@@ -34,6 +34,7 @@ PciInfoList *qmp_query_pci(Error **errp)
return NULL;
}
+#ifdef CONFIG_HMP
void hmp_info_pci(Monitor *mon, const QDict *qdict)
{
}
@@ -42,6 +43,7 @@ void hmp_pcie_aer_inject_error(Monitor *mon, const QDict *qdict)
{
monitor_printf(mon, "PCI devices not supported\n");
}
+#endif
/* kvm-all wants this */
MSIMessage pci_get_msi_message(PCIDevice *dev, int vector)
diff --git a/hw/s390x/s390-skeys.c b/hw/s390x/s390-skeys.c
index 7dca67d6618..81885a1640c 100644
--- a/hw/s390x/s390-skeys.c
+++ b/hw/s390x/s390-skeys.c
@@ -104,6 +104,7 @@ static void write_keys(FILE *f, uint8_t *keys, uint64_t startgfn,
}
}
+#ifdef CONFIG_HMP
void hmp_info_skeys(Monitor *mon, const QDict *qdict)
{
S390SKeysState *ss = s390_get_skeys_device();
@@ -144,6 +145,7 @@ void hmp_dump_skeys(Monitor *mon, const QDict *qdict)
error_report_err(err);
}
}
+#endif
void s390_qmp_dump_skeys(const char *filename, Error **errp)
{
diff --git a/hw/s390x/s390-stattrib.c b/hw/s390x/s390-stattrib.c
index c334714b31a..2fdf70bf2ed 100644
--- a/hw/s390x/s390-stattrib.c
+++ b/hw/s390x/s390-stattrib.c
@@ -32,6 +32,7 @@
#define STATTR_FLAG_ERROR 0x04ULL
#define STATTR_FLAG_DONE 0x08ULL
+#ifdef CONFIG_HMP
static S390StAttribState *s390_get_stattrib_device(void)
{
S390StAttribState *sas;
@@ -40,6 +41,7 @@ static S390StAttribState *s390_get_stattrib_device(void)
assert(sas);
return sas;
}
+#endif
void s390_stattrib_init(void)
{
@@ -59,6 +61,7 @@ void s390_stattrib_init(void)
/* Console commands: */
+#ifdef CONFIG_HMP
void hmp_migrationmode(Monitor *mon, const QDict *qdict)
{
S390StAttribState *sas = s390_get_stattrib_device();
@@ -110,6 +113,7 @@ void hmp_info_cmma(Monitor *mon, const QDict *qdict)
out:
g_free(vals);
}
+#endif
/* Migration support: */
diff --git a/hw/uefi/ovmf-log.c b/hw/uefi/ovmf-log.c
index 3a24afd9417..395a2d10a37 100644
--- a/hw/uefi/ovmf-log.c
+++ b/hw/uefi/ovmf-log.c
@@ -256,6 +256,7 @@ FirmwareLog *qmp_query_firmware_log(bool have_max_size, uint64_t max_size,
return ret;
}
+#ifdef CONFIG_HMP
void hmp_info_firmware_log(Monitor *mon, const QDict *qdict)
{
g_autofree gchar *log_esc = NULL;
@@ -284,3 +285,4 @@ void hmp_info_firmware_log(Monitor *mon, const QDict *qdict)
log_esc = g_strescape((gchar *)log_out, "\r\n");
monitor_printf(mon, "%s\n", log_esc);
}
+#endif
diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c
index b9f3ad3f66d..121fd817e82 100644
--- a/hw/usb/host-libusb.c
+++ b/hw/usb/host-libusb.c
@@ -183,6 +183,7 @@ static void usb_host_attach_kernel(USBHostDevice *s);
# define HAVE_SUPER_PLUS 1
#endif
+#ifdef CONFIG_HMP
static const char *speed_name[] = {
[LIBUSB_SPEED_UNKNOWN] = "?",
[LIBUSB_SPEED_LOW] = "1.5",
@@ -193,6 +194,7 @@ static const char *speed_name[] = {
[LIBUSB_SPEED_SUPER_PLUS] = "5000+",
#endif
};
+#endif
static const unsigned int speed_map[] = {
[LIBUSB_SPEED_LOW] = USB_SPEED_LOW,
@@ -1814,7 +1816,9 @@ module_kconfig(USB);
static void usb_host_register_types(void)
{
type_register_static(&usb_host_dev_info);
+#ifdef CONFIG_HMP
monitor_register_hmp("usbhost", true, hmp_info_usbhost);
+#endif
}
type_init(usb_host_register_types)
@@ -1919,6 +1923,7 @@ static void usb_host_auto_check(void *unused)
timer_mod(usb_auto_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 2000);
}
+#ifdef CONFIG_HMP
void hmp_info_usbhost(Monitor *mon, const QDict *qdict)
{
libusb_device **devs = NULL;
@@ -1962,3 +1967,4 @@ void hmp_info_usbhost(Monitor *mon, const QDict *qdict)
}
libusb_free_device_list(devs, 1);
}
+#endif
diff --git a/migration/dirtyrate.c b/migration/dirtyrate.c
index b360f49efea..8808f20f1b9 100644
--- a/migration/dirtyrate.c
+++ b/migration/dirtyrate.c
@@ -856,6 +856,7 @@ struct DirtyRateInfo *qmp_query_dirty_rate(bool has_calc_time_unit,
has_calc_time_unit ? calc_time_unit : TIME_UNIT_SECOND);
}
+#ifdef CONFIG_HMP
void hmp_info_dirty_rate(Monitor *mon, const QDict *qdict)
{
DirtyRateInfo *info = query_dirty_rate_info(TIME_UNIT_SECOND);
@@ -932,3 +933,4 @@ void hmp_calc_dirty_rate(Monitor *mon, const QDict *qdict)
" seconds\n", sec);
monitor_printf(mon, "[Please use 'info dirty_rate' to check results]\n");
}
+#endif
diff --git a/net/slirp.c b/net/slirp.c
index d3ed5ec9cb8..0d41370e345 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -709,6 +709,7 @@ error:
return -1;
}
+#ifdef CONFIG_HMP
static SlirpState *slirp_lookup(Monitor *mon, const char *id)
{
if (id) {
@@ -799,6 +800,7 @@ void hmp_hostfwd_remove(Monitor *mon, const QDict *qdict)
fail_syntax:
monitor_printf(mon, "invalid format\n");
}
+#endif
static int slirp_hostfwd(SlirpState *s, const char *redir_str, Error **errp)
{
@@ -955,6 +957,7 @@ static int slirp_hostfwd(SlirpState *s, const char *redir_str, Error **errp)
return -1;
}
+#ifdef CONFIG_HMP
void hmp_hostfwd_add(Monitor *mon, const QDict *qdict)
{
const char *redir_str;
@@ -975,8 +978,8 @@ void hmp_hostfwd_add(Monitor *mon, const QDict *qdict)
error_report_err(err);
}
}
-
}
+#endif
#if defined(CONFIG_SMBD_COMMAND)
@@ -1222,6 +1225,7 @@ UsernetInfoList *qmp_x_query_usernet(Error **errp)
return head;
}
+#ifdef CONFIG_HMP
void hmp_info_usernet(Monitor *mon, const QDict *qdict)
{
g_autoptr(UsernetInfoList) list = NULL;
@@ -1235,6 +1239,7 @@ void hmp_info_usernet(Monitor *mon, const QDict *qdict)
ui->hub_name, ui->info);
}
}
+#endif
static void
net_init_slirp_configs(const StringList *fwd, int flags)
diff --git a/replay/replay-debugging.c b/replay/replay-debugging.c
index 11053640021..1adf7422e36 100644
--- a/replay/replay-debugging.c
+++ b/replay/replay-debugging.c
@@ -31,6 +31,7 @@ bool replay_running_debug(void)
return replay_is_debugging;
}
+#ifdef CONFIG_HMP
void hmp_info_replay(Monitor *mon, const QDict *qdict)
{
if (replay_mode == REPLAY_MODE_NONE) {
@@ -42,6 +43,7 @@ void hmp_info_replay(Monitor *mon, const QDict *qdict)
replay_get_filename(), replay_get_current_icount());
}
}
+#endif
ReplayInfo *qmp_query_replay(Error **errp)
{
@@ -103,6 +105,7 @@ void qmp_replay_break(int64_t icount, Error **errp)
}
}
+#ifdef CONFIG_HMP
void hmp_replay_break(Monitor *mon, const QDict *qdict)
{
int64_t icount = qdict_get_try_int(qdict, "icount", -1LL);
@@ -114,6 +117,7 @@ void hmp_replay_break(Monitor *mon, const QDict *qdict)
return;
}
}
+#endif
void qmp_replay_delete_break(Error **errp)
{
@@ -124,6 +128,7 @@ void qmp_replay_delete_break(Error **errp)
}
}
+#ifdef CONFIG_HMP
void hmp_replay_delete_break(Monitor *mon, const QDict *qdict)
{
Error *err = NULL;
@@ -134,6 +139,7 @@ void hmp_replay_delete_break(Monitor *mon, const QDict *qdict)
return;
}
}
+#endif
static char *replay_find_nearest_snapshot(int64_t icount,
int64_t *snapshot_icount)
@@ -208,6 +214,7 @@ void qmp_replay_seek(int64_t icount, Error **errp)
replay_seek(icount, replay_stop_vm, errp);
}
+#ifdef CONFIG_HMP
void hmp_replay_seek(Monitor *mon, const QDict *qdict)
{
int64_t icount = qdict_get_try_int(qdict, "icount", -1LL);
@@ -219,6 +226,7 @@ void hmp_replay_seek(Monitor *mon, const QDict *qdict)
return;
}
}
+#endif
static void replay_stop_vm_debug(void *opaque)
{
diff --git a/replay/stubs-system.c b/replay/stubs-system.c
index b2c52bc4043..f253875bab4 100644
--- a/replay/stubs-system.c
+++ b/replay/stubs-system.c
@@ -63,22 +63,28 @@ void replay_vmstate_init(void)
#include "qapi/error.h"
#include "qemu/error-report.h"
+#ifdef CONFIG_HMP
void hmp_info_replay(Monitor *mon, const QDict *qdict)
{
error_report("replay support not available");
}
+
void hmp_replay_break(Monitor *mon, const QDict *qdict)
{
error_report("replay support not available");
}
+
void hmp_replay_delete_break(Monitor *mon, const QDict *qdict)
{
error_report("replay support not available");
}
+
void hmp_replay_seek(Monitor *mon, const QDict *qdict)
{
error_report("replay support not available");
}
+#endif
+
ReplayInfo *qmp_query_replay(Error **errp)
{
error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND,
diff --git a/system/dirtylimit.c b/system/dirtylimit.c
index 50fa67f3d6a..8992c45a509 100644
--- a/system/dirtylimit.c
+++ b/system/dirtylimit.c
@@ -491,6 +491,7 @@ void qmp_cancel_vcpu_dirty_limit(bool has_cpu_index,
dirtylimit_state_unlock();
}
+#ifdef CONFIG_HMP
void hmp_cancel_vcpu_dirty_limit(Monitor *mon, const QDict *qdict)
{
int64_t cpu_index = qdict_get_try_int(qdict, "cpu_index", -1);
@@ -505,6 +506,7 @@ void hmp_cancel_vcpu_dirty_limit(Monitor *mon, const QDict *qdict)
monitor_printf(mon, "[Please use 'info vcpu_dirty_limit' to query "
"dirty limit for virtual CPU]\n");
}
+#endif
void qmp_set_vcpu_dirty_limit(bool has_cpu_index,
int64_t cpu_index,
@@ -548,6 +550,7 @@ void qmp_set_vcpu_dirty_limit(bool has_cpu_index,
dirtylimit_state_unlock();
}
+#ifdef CONFIG_HMP
void hmp_set_vcpu_dirty_limit(Monitor *mon, const QDict *qdict)
{
int64_t dirty_rate = qdict_get_int(qdict, "dirty_rate");
@@ -564,6 +567,7 @@ void hmp_set_vcpu_dirty_limit(Monitor *mon, const QDict *qdict)
out:
hmp_handle_error(mon, err);
}
+#endif
/* Return the max throttle time of each virtual CPU */
uint64_t dirtylimit_throttle_time_per_round(void)
@@ -647,6 +651,7 @@ struct DirtyLimitInfoList *qmp_query_vcpu_dirty_limit(Error **errp)
return dirtylimit_query_all();
}
+#ifdef CONFIG_HMP
void hmp_info_vcpu_dirty_limit(Monitor *mon, const QDict *qdict)
{
DirtyLimitInfoList *info;
@@ -672,3 +677,4 @@ void hmp_info_vcpu_dirty_limit(Monitor *mon, const QDict *qdict)
info->value->current_rate);
}
}
+#endif
diff --git a/system/qdev-monitor.c b/system/qdev-monitor.c
index 7ed2008d81f..86afb14a6dd 100644
--- a/system/qdev-monitor.c
+++ b/system/qdev-monitor.c
@@ -1003,6 +1003,7 @@ void qmp_device_sync_config(const char *id, Error **errp)
qdev_sync_config(dev, errp);
}
+#ifdef CONFIG_HMP
void hmp_device_add(Monitor *mon, const QDict *qdict)
{
Error *err = NULL;
@@ -1045,6 +1046,7 @@ void hmp_device_del(Monitor *mon, const QDict *qdict)
qmp_device_del(id, &err);
hmp_handle_error(mon, err);
}
+#endif
void device_add_completion(ReadLineState *rs, int nb_args, const char *str)
{
diff --git a/target/i386/cpu-apic.c b/target/i386/cpu-apic.c
index 5599a4675c5..0ceb5536328 100644
--- a/target/i386/cpu-apic.c
+++ b/target/i386/cpu-apic.c
@@ -84,6 +84,7 @@ void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
}
}
+#ifdef CONFIG_HMP
void hmp_info_local_apic(Monitor *mon, const QDict *qdict)
{
CPUState *cs;
@@ -106,3 +107,4 @@ void hmp_info_local_apic(Monitor *mon, const QDict *qdict)
}
x86_cpu_dump_local_apic_state(cs, CPU_DUMP_FPU);
}
+#endif
diff --git a/target/i386/monitor.c b/target/i386/monitor.c
index 785a13dd710..c9d1e2b14f2 100644
--- a/target/i386/monitor.c
+++ b/target/i386/monitor.c
@@ -31,6 +31,8 @@
#include "qapi/qapi-commands-misc.h"
#include "system/memory.h"
+#ifdef CONFIG_HMP
+
/* Perform linear address sign extension */
static hwaddr addr_canonical(CPUArchState *env, hwaddr addr)
{
@@ -593,3 +595,4 @@ void hmp_mce(Monitor *mon, const QDict *qdict)
hmp_handle_error(mon, err);
}
}
+#endif
diff --git a/target/i386/sev.c b/target/i386/sev.c
index b44b5a1c2b9..4d636c90ee0 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -758,6 +758,7 @@ SevInfo *qmp_query_sev(Error **errp)
return info;
}
+#ifdef CONFIG_HMP
void hmp_info_sev(Monitor *mon, const QDict *qdict)
{
SevInfo *info = sev_get_info();
@@ -791,6 +792,7 @@ void hmp_info_sev(Monitor *mon, const QDict *qdict)
out:
qapi_free_SevInfo(info);
}
+#endif
static int
sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain,
diff --git a/target/m68k/monitor.c b/target/m68k/monitor.c
index 3e0df40a6b8..27f65d556e5 100644
--- a/target/m68k/monitor.c
+++ b/target/m68k/monitor.c
@@ -10,6 +10,7 @@
#include "monitor/hmp.h"
#include "monitor/monitor.h"
+#ifdef CONFIG_HMP
void hmp_info_tlb(Monitor *mon, const QDict *qdict)
{
CPUArchState *env1 = mon_get_cpu_env(mon);
@@ -21,3 +22,4 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict)
dump_mmu(env1);
}
+#endif
diff --git a/target/ppc/monitor.c b/target/ppc/monitor.c
index 7c88e0e2bda..2fa27105a34 100644
--- a/target/ppc/monitor.c
+++ b/target/ppc/monitor.c
@@ -11,6 +11,7 @@
#include "monitor/hmp.h"
#include "cpu.h"
+#ifdef CONFIG_HMP
void hmp_info_tlb(Monitor *mon, const QDict *qdict)
{
CPUArchState *env1 = mon_get_cpu_env(mon);
@@ -21,3 +22,4 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict)
}
dump_mmu(env1);
}
+#endif
diff --git a/target/riscv/monitor.c b/target/riscv/monitor.c
index 63806002417..bf4f9fdfc77 100644
--- a/target/riscv/monitor.c
+++ b/target/riscv/monitor.c
@@ -38,6 +38,8 @@
#define PTE_HEADER_DELIMITER "-------- ---------------- -------- -------\n"
#endif
+#ifdef CONFIG_HMP
+
/* Perform linear address sign extension */
static target_ulong addr_canonical(int va_bits, target_ulong addr)
{
@@ -243,6 +245,7 @@ void hmp_info_mem(Monitor *mon, const QDict *qdict)
mem_info_svxx(mon, env);
}
+#endif /* CONFIG_HMP */
static bool reg_is_ulong_integer(CPURISCVState *env, const char *name,
target_ulong *val, bool is_gprh)
diff --git a/target/sh4/monitor.c b/target/sh4/monitor.c
index 50324d3600c..619d2678d0a 100644
--- a/target/sh4/monitor.c
+++ b/target/sh4/monitor.c
@@ -26,6 +26,7 @@
#include "monitor/monitor.h"
#include "monitor/hmp.h"
+#ifdef CONFIG_HMP
static void print_tlb(Monitor *mon, int idx, tlb_t *tlb)
{
monitor_printf(mon, " tlb%i:\t"
@@ -55,3 +56,4 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict)
for (i = 0 ; i < UTLB_SIZE ; i++)
print_tlb (mon, i, &env->utlb[i]);
}
+#endif
diff --git a/target/sparc/monitor.c b/target/sparc/monitor.c
index 36f3d8d58e9..ed7e3b4b8b2 100644
--- a/target/sparc/monitor.c
+++ b/target/sparc/monitor.c
@@ -27,6 +27,7 @@
#include "monitor/hmp.h"
+#ifdef CONFIG_HMP
void hmp_info_tlb(Monitor *mon, const QDict *qdict)
{
CPUArchState *env1 = mon_get_cpu_env(mon);
@@ -37,3 +38,4 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict)
}
dump_mmu(env1);
}
+#endif
diff --git a/target/xtensa/monitor.c b/target/xtensa/monitor.c
index 2af84934f83..3f8a93ed724 100644
--- a/target/xtensa/monitor.c
+++ b/target/xtensa/monitor.c
@@ -26,6 +26,7 @@
#include "monitor/monitor.h"
#include "monitor/hmp.h"
+#ifdef CONFIG_HMP
void hmp_info_tlb(Monitor *mon, const QDict *qdict)
{
CPUArchState *env1 = mon_get_cpu_env(mon);
@@ -36,3 +37,4 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict)
}
dump_mmu(env1);
}
+#endif
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 39/40] build-sys: make HMP source files conditional on have_hmp
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (37 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 38/40] Guard HMP command implementations " Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-20 21:49 ` [PATCH 40/40] gitlab-ci: add --disable-hmp to build-without-defaults Marc-André Lureau
2026-05-21 7:55 ` [PATCH 00/40] Make HMP optional (and later standalone) Daniel P. Berrangé
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Exclude all *-hmp-cmds.c files and HMP-only source files from the
build when HMP is disabled.
Also conditionalise the hmp-commands.hx header generation and the
test-hmp qtest.
Together with the preceding CONFIG_HMP guards, this makes QEMU
buildable with -Dhmp=disabled.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
meson.build | 2 +-
audio/meson.build | 4 +++-
backends/meson.build | 5 ++++-
block/monitor/meson.build | 4 +++-
chardev/meson.build | 5 ++++-
disas/meson.build | 4 +++-
dump/meson.build | 5 ++++-
hw/core/meson.build | 5 +++--
hw/i386/meson.build | 4 +++-
hw/net/meson.build | 4 +++-
hw/pci/meson.build | 4 +++-
hw/virtio/meson.build | 4 +++-
migration/meson.build | 4 +++-
monitor/meson.build | 9 +++++++--
net/meson.build | 4 +++-
qom/meson.build | 4 +++-
stats/meson.build | 5 ++++-
stubs/meson.build | 12 +++++++-----
system/meson.build | 9 +++++++--
tests/qtest/meson.build | 8 +++++++-
trace/meson.build | 5 ++++-
ui/meson.build | 4 +++-
22 files changed, 85 insertions(+), 29 deletions(-)
diff --git a/meson.build b/meson.build
index e83cfe56cf3..63f2d687b69 100644
--- a/meson.build
+++ b/meson.build
@@ -3538,7 +3538,7 @@ hx_headers = [
['qemu-options.hx', 'qemu-options.def'],
['qemu-img-cmds.hx', 'qemu-img-cmds.h'],
]
-if have_system
+if have_system and have_hmp
hx_headers += [
['hmp-commands.hx', 'hmp-commands.h'],
['hmp-commands-info.hx', 'hmp-commands-info.h'],
diff --git a/audio/meson.build b/audio/meson.build
index 0e33b6f9836..6655f601b11 100644
--- a/audio/meson.build
+++ b/audio/meson.build
@@ -9,7 +9,9 @@ audio_ss.add(files(
))
# deprecated since v10.2, to be removed
-system_ss.add(files('audio-hmp-cmds.c', 'wavcapture.c'))
+if have_hmp
+ system_ss.add(files('audio-hmp-cmds.c', 'wavcapture.c'))
+endif
audio_modules = {}
foreach m : [
diff --git a/backends/meson.build b/backends/meson.build
index 60021f45d12..a59729f56fe 100644
--- a/backends/meson.build
+++ b/backends/meson.build
@@ -1,6 +1,5 @@
system_ss.add([files(
'cryptodev-builtin.c',
- 'cryptodev-hmp-cmds.c',
'cryptodev.c',
'hostmem-ram.c',
'hostmem.c',
@@ -10,6 +9,10 @@ system_ss.add([files(
'confidential-guest-support.c',
), numa])
+if have_hmp
+ system_ss.add(files('cryptodev-hmp-cmds.c'))
+endif
+
if host_os != 'windows'
system_ss.add(files('rng-random.c'))
if host_os != 'emscripten'
diff --git a/block/monitor/meson.build b/block/monitor/meson.build
index 74faced9e17..2d5c157a739 100644
--- a/block/monitor/meson.build
+++ b/block/monitor/meson.build
@@ -1,3 +1,5 @@
-system_ss.add(files('block-hmp-cmds.c'))
+if have_hmp
+ system_ss.add(files('block-hmp-cmds.c'))
+endif
block_ss.add(files('bitmap-qmp-cmds.c'))
system_ss.add(files('qmp-cmds.c'))
diff --git a/chardev/meson.build b/chardev/meson.build
index 56ee39ac0b0..031b6d7238c 100644
--- a/chardev/meson.build
+++ b/chardev/meson.build
@@ -30,11 +30,14 @@ endif
chardev_ss = chardev_ss.apply({})
system_ss.add(files(
- 'char-hmp-cmds.c',
'msmouse.c',
'wctablet.c',
'testdev.c'))
+if have_hmp
+ system_ss.add(files('char-hmp-cmds.c'))
+endif
+
chardev_modules = {}
if brlapi.found()
diff --git a/disas/meson.build b/disas/meson.build
index 42977a1f74d..b382550e41f 100644
--- a/disas/meson.build
+++ b/disas/meson.build
@@ -20,5 +20,7 @@ common_ss.add(when: 'CONFIG_TCG', if_true: files(
'objdump.c'
))
common_ss.add(files('disas-common.c'))
-system_ss.add(files('disas-mon.c'))
+if have_hmp
+ system_ss.add(files('disas-mon.c'))
+endif
specific_ss.add(capstone)
diff --git a/dump/meson.build b/dump/meson.build
index 26e1561ed48..bef8276aa5a 100644
--- a/dump/meson.build
+++ b/dump/meson.build
@@ -1,3 +1,6 @@
-system_ss.add([files('dump.c', 'dump-hmp-cmds.c'), snappy, lzo])
+system_ss.add([files('dump.c'), snappy, lzo])
+if have_hmp
+ system_ss.add(files('dump-hmp-cmds.c'))
+endif
specific_ss.add(when: 'CONFIG_WINDUMP', if_true: files('win_dump-x86.c'))
system_ss.add(when: 'CONFIG_WINDUMP', if_false: files('win_dump-stubs.c'))
diff --git a/hw/core/meson.build b/hw/core/meson.build
index 8a96567de8f..8fe776d2c86 100644
--- a/hw/core/meson.build
+++ b/hw/core/meson.build
@@ -26,13 +26,11 @@ system_ss.add(when: 'CONFIG_SPLIT_IRQ', if_true: files('split-irq.c'))
system_ss.add(when: 'CONFIG_XILINX_AXI', if_true: files('stream.c'))
system_ss.add(when: 'CONFIG_PLATFORM_BUS', if_true: files('sysbus-fdt.c'))
system_ss.add(when: 'CONFIG_EIF', if_true: [files('eif.c'), zlib, libcbor, gnutls])
-
system_ss.add(files(
'cpu-system.c',
'fw-path-provider.c',
'hotplug.c',
'loader.c',
- 'machine-hmp-cmds.c',
'machine-qmp-cmds.c',
'machine.c',
'nmi.c',
@@ -46,6 +44,9 @@ system_ss.add(files(
'vm-change-state-handler.c',
'clock-vmstate.c',
))
+if have_hmp
+ system_ss.add(files('machine-hmp-cmds.c'))
+endif
user_ss.add(files(
'cpu-user.c',
'qdev-user.c',
diff --git a/hw/i386/meson.build b/hw/i386/meson.build
index b611fbb5a7f..125f4ce894c 100644
--- a/hw/i386/meson.build
+++ b/hw/i386/meson.build
@@ -24,7 +24,9 @@ i386_ss.add(when: 'CONFIG_VTD', if_true: files('intel_iommu.c'))
i386_ss.add(when: 'CONFIG_VTD_ACCEL', if_true: files('intel_iommu_accel.c'))
i386_ss.add(when: 'CONFIG_SGX', if_true: files('sgx-epc.c','sgx.c'),
if_false: files('sgx-stub.c'))
-stub_ss.add(files('sgx-hmp-stub.c'))
+if have_hmp
+ stub_ss.add(files('sgx-hmp-stub.c'))
+endif
i386_ss.add(when: 'CONFIG_ACPI', if_true: files('acpi-common.c'))
i386_ss.add(when: 'CONFIG_PC', if_true: files(
diff --git a/hw/net/meson.build b/hw/net/meson.build
index 31025874699..76fe3d7dda6 100644
--- a/hw/net/meson.build
+++ b/hw/net/meson.build
@@ -68,6 +68,8 @@ system_ss.add(when: 'CONFIG_ROCKER', if_true: files(
'rocker/rocker_world.c',
))
stub_ss.add(files('rocker/rocker-stubs.c'))
-system_ss.add(files('rocker/rocker-hmp-cmds.c'))
+if have_hmp
+ system_ss.add(files('rocker/rocker-hmp-cmds.c'))
+endif
subdir('can')
diff --git a/hw/pci/meson.build b/hw/pci/meson.build
index a6cbd89c0a3..984c7327e5d 100644
--- a/hw/pci/meson.build
+++ b/hw/pci/meson.build
@@ -5,12 +5,14 @@ pci_ss.add(files(
'pci.c',
'pci_bridge.c',
'pci_host.c',
- 'pci-hmp-cmds.c',
'pci-qmp-cmds.c',
'pcie_sriov.c',
'shpc.c',
'slotid_cap.c'
))
+if have_hmp
+ pci_ss.add(files('pci-hmp-cmds.c'))
+endif
# The functions in these modules can be used by devices too. Since we
# allow plugging PCIe devices into PCI buses, include them even if
# CONFIG_PCI_EXPRESS=n.
diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build
index e0566a60de7..4b80e4e1c87 100644
--- a/hw/virtio/meson.build
+++ b/hw/virtio/meson.build
@@ -97,6 +97,8 @@ stub_ss.add(files('vhost-stub.c'))
stub_ss.add(files('virtio-stub.c'))
stub_ss.add(files('virtio-md-stubs.c'))
-system_ss.add(files('virtio-hmp-cmds.c'))
+if have_hmp
+ system_ss.add(files('virtio-hmp-cmds.c'))
+endif
system_ss.add(when: 'CONFIG_ACPI', if_true: files('virtio-acpi.c'))
diff --git a/migration/meson.build b/migration/meson.build
index e583822dec6..bb39d987110 100644
--- a/migration/meson.build
+++ b/migration/meson.build
@@ -36,7 +36,9 @@ system_ss.add(files(
'socket.c',
'tls.c',
), gnutls, zlib)
-system_ss.add([spice_headers, files('migration-hmp-cmds.c'), spice])
+if have_hmp
+ system_ss.add([spice_headers, files('migration-hmp-cmds.c'), spice])
+endif
if get_option('replication').allowed()
system_ss.add(files('colo-failover.c', 'colo.c', 'multifd-colo.c'))
diff --git a/monitor/meson.build b/monitor/meson.build
index 4c58dd148c0..f67e0291a42 100644
--- a/monitor/meson.build
+++ b/monitor/meson.build
@@ -2,8 +2,13 @@ qmp_ss.add(files('monitor.c', 'qmp.c', 'qmp-cmds-control.c'))
system_ss.add(files(
'fds.c',
- 'hmp-cmds.c',
- 'hmp.c',
'qemu-config-qmp.c',
'qmp-cmds.c',
))
+
+if have_hmp
+ system_ss.add(files(
+ 'hmp-cmds.c',
+ 'hmp.c',
+ ))
+endif
diff --git a/net/meson.build b/net/meson.build
index da6ea635e95..bb7d70c6c36 100644
--- a/net/meson.build
+++ b/net/meson.build
@@ -8,7 +8,6 @@ system_ss.add(files(
'filter-mirror.c',
'filter.c',
'hub.c',
- 'net-hmp-cmds.c',
'net.c',
'queue.c',
'socket.c',
@@ -16,6 +15,9 @@ system_ss.add(files(
'stream_data.c',
'util.c',
))
+if have_hmp
+ system_ss.add(files('net-hmp-cmds.c'))
+endif
if get_option('replication').allowed() or \
get_option('colo_proxy').allowed()
diff --git a/qom/meson.build b/qom/meson.build
index bd6f4aadd78..022d3ad5c8f 100644
--- a/qom/meson.build
+++ b/qom/meson.build
@@ -10,4 +10,6 @@ if have_system
endif
qmp_ss.add(files('qom-qmp-cmds.c'))
-system_ss.add(files('qom-hmp-cmds.c'))
+if have_hmp
+ system_ss.add(files('qom-hmp-cmds.c'))
+endif
diff --git a/stats/meson.build b/stats/meson.build
index 0728dafcd1c..b5f68a94052 100644
--- a/stats/meson.build
+++ b/stats/meson.build
@@ -1 +1,4 @@
-system_ss.add(files('stats-hmp-cmds.c', 'stats-qmp-cmds.c'))
+system_ss.add(files('stats-qmp-cmds.c'))
+if have_hmp
+ system_ss.add(files('stats-hmp-cmds.c'))
+endif
diff --git a/stubs/meson.build b/stubs/meson.build
index 3b2f2680b19..fe77107cc86 100644
--- a/stubs/meson.build
+++ b/stubs/meson.build
@@ -85,11 +85,13 @@ if have_system
stub_ss.add(files('qmp-cpu.c'))
stub_ss.add(files('qmp-cpu-s390x.c'))
stub_ss.add(files('qmp-cpu-s390x-kvm.c'))
- stub_ss.add(files('hmp-cmd-info_mem.c'))
- stub_ss.add(files('hmp-cmd-info_sev.c'))
- stub_ss.add(files('hmp-cmd-info_tlb.c'))
- stub_ss.add(files('hmp-cmds-hw-s390x.c'))
- stub_ss.add(files('hmp-cmds-target-i386.c'))
+ if have_hmp
+ stub_ss.add(files('hmp-cmd-info_mem.c'))
+ stub_ss.add(files('hmp-cmd-info_sev.c'))
+ stub_ss.add(files('hmp-cmd-info_tlb.c'))
+ stub_ss.add(files('hmp-cmds-hw-s390x.c'))
+ stub_ss.add(files('hmp-cmds-target-i386.c'))
+ endif
endif
if have_system or have_user
diff --git a/system/meson.build b/system/meson.build
index 9cdfe1b3e75..a1afc6fee5f 100644
--- a/system/meson.build
+++ b/system/meson.build
@@ -21,12 +21,17 @@ system_ss.add(files(
'qtest.c',
'rtc.c',
'runstate-action.c',
- 'runstate-hmp-cmds.c',
'runstate.c',
- 'tpm-hmp-cmds.c',
'watchpoint.c',
))
+if have_hmp
+ system_ss.add(files(
+ 'runstate-hmp-cmds.c',
+ 'tpm-hmp-cmds.c',
+ ))
+endif
+
if have_tpm
system_ss.add(files('tpm.c'))
endif
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 728dde54b3f..acd175a679c 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -26,7 +26,13 @@ qtests_generic = [
'qmp-test',
'qmp-cmd-test',
'qom-test',
- 'test-hmp',
+]
+if have_hmp
+ qtests_generic += [
+ 'test-hmp',
+ ]
+endif
+qtests_generic += [
'qos-test',
'readconfig-test',
'netdev-socket',
diff --git a/trace/meson.build b/trace/meson.build
index d89a0db82a1..4e5681c44ca 100644
--- a/trace/meson.build
+++ b/trace/meson.build
@@ -1,4 +1,7 @@
-system_ss.add(files('control-target.c', 'trace-hmp-cmds.c'))
+system_ss.add(files('control-target.c'))
+if have_hmp
+ system_ss.add(files('trace-hmp-cmds.c'))
+endif
trace_rs_targets = []
trace_events_files = []
foreach item : [ '.' ] + trace_events_subdirs + qapi_trace_events
diff --git a/ui/meson.build b/ui/meson.build
index 1b8f71796e4..66790c29f44 100644
--- a/ui/meson.build
+++ b/ui/meson.build
@@ -57,10 +57,12 @@ system_ss.add(files(
'input-legacy.c',
'input-barrier.c',
'input.c',
- 'ui-hmp-cmds.c',
'ui-qmp-cmds.c',
'util.c',
))
+if have_hmp
+ system_ss.add(files('ui-hmp-cmds.c'))
+endif
system_ss.add(ui)
system_ss.add(when: pixman, if_true: files('console-vc.c'), if_false: files('console-vc-stubs.c'))
if dbus_display
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 40/40] gitlab-ci: add --disable-hmp to build-without-defaults
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (38 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 39/40] build-sys: make HMP source files conditional on have_hmp Marc-André Lureau
@ 2026-05-20 21:49 ` Marc-André Lureau
2026-05-21 7:55 ` [PATCH 00/40] Make HMP optional (and later standalone) Daniel P. Berrangé
40 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-20 21:49 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
Test the HMP-disabled build configuration in CI to catch
regressions when HMP is compiled out.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
.gitlab-ci.d/buildtest.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml
index 4b1949a3a52..e10b68820d6 100644
--- a/.gitlab-ci.d/buildtest.yml
+++ b/.gitlab-ci.d/buildtest.yml
@@ -661,6 +661,7 @@ build-without-defaults:
--without-default-devices
--without-default-features
--disable-fdt
+ --disable-hmp
--disable-pie
--disable-qom-cast-debug
--disable-strip
--
2.54.0
^ permalink raw reply related [flat|nested] 55+ messages in thread
* Re: [PATCH 06/40] s390x: prevent crash if given invalid CPU#
2026-05-20 21:49 ` [PATCH 06/40] s390x: prevent crash if given invalid CPU# Marc-André Lureau
@ 2026-05-21 0:47 ` Eric Farman
0 siblings, 0 replies; 55+ messages in thread
From: Eric Farman @ 2026-05-21 0:47 UTC (permalink / raw)
To: Marc-André Lureau, qemu-devel
On Thu, 2026-05-21 at 01:49 +0400, Marc-André Lureau wrote:
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> hw/s390x/s390-virtio-ccw.c | 5 +++++
> 1 file changed, 5 insertions(+)
Straightforward defensive check.
Reviewed-by: Eric Farman <farman@linux.ibm.com>
^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [PATCH 04/40] target/i386: decouple cpu_x86_inject_mce() from Monitor
2026-05-20 21:49 ` [PATCH 04/40] target/i386: decouple cpu_x86_inject_mce() from Monitor Marc-André Lureau
@ 2026-05-21 5:49 ` Philippe Mathieu-Daudé
2026-05-29 21:28 ` marcandre.lureau
0 siblings, 1 reply; 55+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-21 5:49 UTC (permalink / raw)
To: Marc-André Lureau, qemu-devel
On 20/5/26 23:49, Marc-André Lureau wrote:
> Replace monitor_printf() error reporting with the standard **errp
> pattern. Drop the Monitor *mon parameter and return bool to indicate
> success, improving the function usage from non-HMP contexts. Update the
> KVM MCE injection path and hmp_mce() accordingly.
>
> Notes:
> - we may want to print the error in KVM path too
> - multiple error prints are now accumulated with error hints
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> target/i386/cpu.h | 4 ++--
> target/i386/helper.c | 49 ++++++++++++++++++++++++++++---------------------
> target/i386/kvm/kvm.c | 4 ++--
> target/i386/monitor.c | 6 ++++--
> 4 files changed, 36 insertions(+), 27 deletions(-)
> diff --git a/target/i386/monitor.c b/target/i386/monitor.c
> index a536712c755..785a13dd710 100644
> --- a/target/i386/monitor.c
> +++ b/target/i386/monitor.c
> @@ -580,6 +580,7 @@ void hmp_mce(Monitor *mon, const QDict *qdict)
> uint64_t addr = qdict_get_int(qdict, "addr");
> uint64_t misc = qdict_get_int(qdict, "misc");
> int flags = MCE_INJECT_UNCOND_AO;
> + Error *err = NULL;
>
> if (qdict_get_try_bool(qdict, "broadcast", false)) {
> flags |= MCE_INJECT_BROADCAST;
> @@ -587,7 +588,8 @@ void hmp_mce(Monitor *mon, const QDict *qdict)
> cs = qemu_get_cpu(cpu_index);
if (!cs) {
error_setg(errp, "Invalid CPU %d", cpu_index);
return;
}
?
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> if (cs != NULL) {
> cpu = X86_CPU(cs);
> - cpu_x86_inject_mce(mon, cpu, bank, status, mcg_status, addr, misc,
> - flags);
> + cpu_x86_inject_mce(cpu, bank, status, mcg_status, addr, misc,
> + flags, &err);
> + hmp_handle_error(mon, err);
> }
> }
>
^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [PATCH 05/40] system: move gpa2hva() to system memory unit
2026-05-20 21:49 ` [PATCH 05/40] system: move gpa2hva() to system memory unit Marc-André Lureau
@ 2026-05-21 5:50 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 55+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-21 5:50 UTC (permalink / raw)
To: Marc-André Lureau, qemu-devel
On 20/5/26 23:49, Marc-André Lureau wrote:
> The function is now used by SEV code path. Move it to physmem.c rather
> than hmp-cmds.c.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> include/monitor/monitor.h | 2 --
> include/system/memory.h | 2 ++
> monitor/hmp-cmds.c | 31 -------------------------------
> system/physmem.c | 31 +++++++++++++++++++++++++++++++
> 4 files changed, 33 insertions(+), 33 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [PATCH 02/40] hmp: remove 'vcpu' argument from trace-event help
2026-05-20 21:49 ` [PATCH 02/40] hmp: remove 'vcpu' argument from trace-event help Marc-André Lureau
@ 2026-05-21 5:50 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 55+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-21 5:50 UTC (permalink / raw)
To: Marc-André Lureau, qemu-devel
On 20/5/26 23:49, Marc-André Lureau wrote:
> Fixes: 89aafcf2a793 ("trace: remove code that depends on setting vcpu")
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> hmp-commands-info.hx | 6 +++---
> hmp-commands.hx | 7 +++----
> 2 files changed, 6 insertions(+), 7 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [PATCH 09/40] monitor: move HMP-only fields from Monitor to MonitorHMP
2026-05-20 21:49 ` [PATCH 09/40] monitor: move HMP-only fields from Monitor to MonitorHMP Marc-André Lureau
@ 2026-05-21 5:53 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 55+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-21 5:53 UTC (permalink / raw)
To: Marc-André Lureau, qemu-devel
On 20/5/26 23:49, Marc-André Lureau wrote:
> mon_cpu_path and reset_seen are only used by HMP monitors; move them
> from the base Monitor struct into MonitorHMP to properly encapsulate
> HMP-specific state.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> monitor/monitor-internal.h | 4 ++--
> monitor/hmp-cmds.c | 17 ++++++++++-------
> monitor/hmp.c | 5 +++--
> monitor/monitor.c | 16 +++++++++++-----
> 4 files changed, 26 insertions(+), 16 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [PATCH 10/40] tests/functional: use query-version QMP command instead of HMP
2026-05-20 21:49 ` [PATCH 10/40] tests/functional: use query-version QMP command instead of HMP Marc-André Lureau
@ 2026-05-21 5:54 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 55+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-21 5:54 UTC (permalink / raw)
To: Marc-André Lureau, qemu-devel
On 20/5/26 23:49, Marc-André Lureau wrote:
> Replace the human-monitor-command based version test with the native
> QMP query-version command, which returns structured version data.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> tests/functional/generic/test_version.py | 10 ++++++----
> 1 file changed, 6 insertions(+), 4 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [PATCH 14/40] qemu-io: propagate errors through Error API instead of printf
2026-05-20 21:49 ` [PATCH 14/40] qemu-io: propagate errors through Error API instead of printf Marc-André Lureau
@ 2026-05-21 6:02 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 55+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-21 6:02 UTC (permalink / raw)
To: Marc-André Lureau, qemu-devel
On 20/5/26 23:49, Marc-André Lureau wrote:
> Convert the qemu-io command infrastructure to use QEMU's Error API
> (Error **errp) for error propagation instead of printing directly to
> stdout/stderr via printf/fprintf.
>
> The cfunc_t typedef, all ~35 command functions, the dispatcher chain
> (command/init_check_command/qemuio_command), and helper functions
> (parse_pattern, create_iovec, qemu_io_alloc_from_file) all gain an
> Error **errp parameter. Async completion callbacks (aio_read_done,
> aio_write_done, aio_discard_done) use error_report() since they have
> no Error path back to the caller.
>
> Update tests:
> - error_report_err() prepends qemu-io: prefix
> - copy-before-write: check the HMP return value, rather than stdio
> - other tests: update to check JSON {"return": "Error: error text"}
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> include/qemu-io.h | 4 +-
> block/monitor/block-hmp-cmds.c | 2 +-
> qemu-io-cmds.c | 426 +++++++++++++++--------------
> qemu-io.c | 17 +-
> tests/qemu-iotests/004.out | 20 +-
> tests/qemu-iotests/021.out | 60 ++--
> tests/qemu-iotests/060.out | 44 ++-
> tests/qemu-iotests/071.out | 10 +-
> tests/qemu-iotests/072.out | 2 +-
> tests/qemu-iotests/080.out | 4 +-
> tests/qemu-iotests/089.out | 4 +-
> tests/qemu-iotests/114.out | 2 +-
> tests/qemu-iotests/134.out | 2 +-
> tests/qemu-iotests/137.out | 2 +-
> tests/qemu-iotests/171 | 2 +-
> tests/qemu-iotests/171.out | 68 ++---
> tests/qemu-iotests/214.out | 2 +-
> tests/qemu-iotests/220.out | 2 +-
> tests/qemu-iotests/244.out | 12 +-
> tests/qemu-iotests/249.out | 6 +-
> tests/qemu-iotests/271.out | 14 +-
> tests/qemu-iotests/tests/copy-before-write | 66 +++--
> 22 files changed, 404 insertions(+), 367 deletions(-)
> diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
> index de4c1966fea..5093aa4169a 100644
> --- a/qemu-io-cmds.c
> +++ b/qemu-io-cmds.c
> -static int reopen_f(BlockBackend *blk, int argc, char **argv)
> +static int reopen_f(BlockBackend *blk, int argc, char **argv, Error **errp)
> {
> BlockDriverState *bs = blk_bs(blk);
> QemuOpts *qopts;
> @@ -2609,37 +2624,41 @@ static int reopen_f(BlockBackend *blk, int argc, char **argv)
> qdict_put_bool(opts, BDRV_OPT_CACHE_NO_FLUSH, flags & BDRV_O_NO_FLUSH);
> }
>
> - bdrv_reopen(bs, opts, true, &local_err);
> -
> - if (local_err) {
> - error_report_err(local_err);
> - return -EINVAL;
> + {
> + Error *local_err = NULL;
> + bdrv_reopen(bs, opts, true, &local_err);
> + if (local_err) {
> + error_propagate(errp, local_err);
> + return -EINVAL;
> + }
> }
if (bdrv_reopen(bs, opts, true, errp) < 0) {
return -EINVAL;
}
Otherwise:
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
>
> blk_set_enable_write_cache(blk, !writethrough);
> return 0;
> }
^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [PATCH 24/40] tests/qtest/pnv: drop unnecessary -serial mon:stdio
2026-05-20 21:49 ` [PATCH 24/40] tests/qtest/pnv: drop unnecessary -serial mon:stdio Marc-André Lureau
@ 2026-05-21 6:02 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 55+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-21 6:02 UTC (permalink / raw)
To: Marc-André Lureau, qemu-devel
On 20/5/26 23:49, Marc-André Lureau wrote:
> The pnv-xive2-test and pnv-host-i2c-test pass "-serial mon:stdio"
> but never use HMP commands. The "mon:" chardev prefix creates an
> HMP monitor mux, which fails when HMP is disabled. Other pnv tests
> (e.g. pnv-spi-seeprom-test) don't specify -serial at all.
>
> Drop the unnecessary -serial mon:stdio option.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> tests/qtest/pnv-host-i2c-test.c | 2 +-
> tests/qtest/pnv-xive2-test.c | 2 +-
> 2 files changed, 2 insertions(+), 2 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [PATCH 27/40] tests/qtest/cdrom-test: replace HMP "info block" with QMP query-block
2026-05-20 21:49 ` [PATCH 27/40] tests/qtest/cdrom-test: replace HMP "info block" with QMP query-block Marc-André Lureau
@ 2026-05-21 6:03 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 55+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-21 6:03 UTC (permalink / raw)
To: Marc-André Lureau, qemu-devel
On 20/5/26 23:49, Marc-André Lureau wrote:
> The test_cdrom_param() function uses qtest_hmp() to run "info block",
> which depends on the human-monitor-command QMP endpoint. Replace it
> with the QMP query-block command so the test works when HMP is
> disabled (-Dhmp=disabled).
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> tests/qtest/cdrom-test.c | 29 ++++++++++++++++++++++++-----
> 1 file changed, 24 insertions(+), 5 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [PATCH 36/40] hw: guard BusClass::print_dev with CONFIG_HMP
2026-05-20 21:49 ` [PATCH 36/40] hw: guard BusClass::print_dev " Marc-André Lureau
@ 2026-05-21 6:07 ` Philippe Mathieu-Daudé
2026-05-29 21:31 ` marcandre.lureau
0 siblings, 1 reply; 55+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-21 6:07 UTC (permalink / raw)
To: Marc-André Lureau, qemu-devel
On 20/5/26 23:49, Marc-André Lureau wrote:
> The print_dev callback is only used by HMP 'info qtree'. Guard the field
> in BusClass, all implementations, and the caller with CONFIG_HMP.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> include/hw/core/qdev.h | 2 ++
> hw/char/virtio-serial-bus.c | 6 ++++++
> hw/core/sysbus.c | 6 ++++++
> hw/misc/auxbus.c | 16 +++++++++++-----
> hw/pci/pci-hmp-cmds.c | 2 ++
> hw/pci/pci.c | 2 ++
> hw/usb/bus.c | 6 ++++++
> hw/xen/xen-bus.c | 4 ++++
> system/qdev-monitor.c | 2 ++
> 9 files changed, 41 insertions(+), 5 deletions(-)
>
> diff --git a/include/hw/core/qdev.h b/include/hw/core/qdev.h
> index e1476223411..22dd143acf0 100644
> --- a/include/hw/core/qdev.h
> +++ b/include/hw/core/qdev.h
> @@ -322,8 +322,10 @@ DECLARE_OBJ_CHECKERS(BusState, BusClass,
> struct BusClass {
> ObjectClass parent_class;
>
> +#ifdef CONFIG_HMP
> /* FIXME first arg should be BusState */
> void (*print_dev)(Monitor *mon, DeviceState *dev, int indent);
We should fill a GString instead, avoiding the need of #ifdef'ry in hw/.
> +#endif
> /*
> * Return a newly allocated string containing the path of the
> * device on this bus.
^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [PATCH 00/40] Make HMP optional (and later standalone)
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
` (39 preceding siblings ...)
2026-05-20 21:49 ` [PATCH 40/40] gitlab-ci: add --disable-hmp to build-without-defaults Marc-André Lureau
@ 2026-05-21 7:55 ` Daniel P. Berrangé
2026-05-21 8:04 ` Marc-André Lureau
40 siblings, 1 reply; 55+ messages in thread
From: Daniel P. Berrangé @ 2026-05-21 7:55 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel
On Thu, May 21, 2026 at 01:49:01AM +0400, Marc-André Lureau wrote:
> Hi,
>
> This series makes HMP compile-time optional via --disable-hmp. The
> resulting binary speaks only QMP - reducing the attack surface, binary
> size and enforcing a separation between machine-readable interface and
> interactive debugging console.
>
> QMP offers almost all the functionality HMP could provide, so a separate
> standalone "HMP-like" console could be implemented on top of it. The
> rough list of missing commands (+complexity estimation) after this
> series:
When you say "complexity estimation" is that an estimate for doing
a well designed QMP implementation ?
My view is that for anything still HMP-only, we should do a quick
& dirty hack, where we just expose the existing functionality
directly as QMP without any modelling, but mark it unstable. That
would make everything be largely easy.
If we expect proper QMP design, then the job will never get finished.
> Debugging / introspection:
> - info registers (medium) - plus $reg expression handling
> - x/xp read memory (medium)
> - gpa2hpa/gpa2hva/gva2gpa address translation (medium)
> - info lapic (high) - deep x86 APIC state, lots of registers
> - info mem (high) - virtual memory mappings, different per arch
> - info tlb (high) - virt-to-phys mappings, also per arch
> - info mtree (high) - memory region tree, multiple view modes
> - info skeys (medium) - s390x storage keys
> - info cmma (medium) - s390x CMMA values
> - info qdm (easy) - could probably be folded into QOM introspection
> - info qtree (medium) - same, maybe QOM introspection is enough
> - info snapshots (medium)
> - info usbhost (medium)
> - info via (medium) -- VIA south bridge state
>
> Simple actions / settings:
> - gdbserver (trivial)
> - boot_set (easy)
> - mce (easy) - x86 MCE injection
> - sum (easy) - memory checksum
> - sync-profile (easy) - enable/disable/reset
> - info sync-profile (medium)
> - one-insn-per-tb (easy) - could be a QOM property on the accelerator
> - pcie_aer_inject_error (easy)
> - migration_mode (medium?)
> - i/o ioport read/write (easy)
> - hostfwd-add/hostfwd-remove (medium) - slirp port forwarding
> - log/logfile (medium)
> - trace-file (medium)
>
> Also, to let clients do disassembly on their side, it'd be useful to
> have something like "query-disassemble-info" that gives the client what
> architecture and endianness is used etc.
>
> In the meantime, being able to build without HMP is valuable and helps
> identifying the missing pieces. The series does so by steps:
>
> - preparatory cleanups and bug fixes
> - add commands without QMP equivalent and needed for tests
> - convert most iotests and qtests from HMP to QMP
> - guard HMP-only code paths
> - make HMP source files conditional in the build system
>
With regards,
Daniel
--
|: https://berrange.com ~~ https://hachyderm.io/@berrange :|
|: https://libvirt.org ~~ https://entangle-photo.org :|
|: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|
^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [PATCH 00/40] Make HMP optional (and later standalone)
2026-05-21 7:55 ` [PATCH 00/40] Make HMP optional (and later standalone) Daniel P. Berrangé
@ 2026-05-21 8:04 ` Marc-André Lureau
0 siblings, 0 replies; 55+ messages in thread
From: Marc-André Lureau @ 2026-05-21 8:04 UTC (permalink / raw)
To: Daniel P. Berrangé; +Cc: qemu-devel
Hi
On Thu, May 21, 2026 at 11:56 AM Daniel P. Berrangé <berrange@redhat.com> wrote:
>
> On Thu, May 21, 2026 at 01:49:01AM +0400, Marc-André Lureau wrote:
> > Hi,
> >
> > This series makes HMP compile-time optional via --disable-hmp. The
> > resulting binary speaks only QMP - reducing the attack surface, binary
> > size and enforcing a separation between machine-readable interface and
> > interactive debugging console.
> >
> > QMP offers almost all the functionality HMP could provide, so a separate
> > standalone "HMP-like" console could be implemented on top of it. The
> > rough list of missing commands (+complexity estimation) after this
> > series:
>
> When you say "complexity estimation" is that an estimate for doing
> a well designed QMP implementation ?
>
> My view is that for anything still HMP-only, we should do a quick
> & dirty hack, where we just expose the existing functionality
> directly as QMP without any modelling, but mark it unstable. That
> would make everything be largely easy.
If that's reasonable, we can have more x-unstable HumanReadableText commands.
>
> If we expect proper QMP design, then the job will never get finished.
Yeah, I expect to have a bit better than just plain string though, for
some commands. We can do it progressively.
See for example x-query-usernet & x-query-network added in this
series, they are structured, but a few info fields remain "free-form"
(slirp data, etc).
We could work on exposing the other missing commands in separate series.
>
>
> > Debugging / introspection:
> > - info registers (medium) - plus $reg expression handling
> > - x/xp read memory (medium)
> > - gpa2hpa/gpa2hva/gva2gpa address translation (medium)
> > - info lapic (high) - deep x86 APIC state, lots of registers
> > - info mem (high) - virtual memory mappings, different per arch
> > - info tlb (high) - virt-to-phys mappings, also per arch
> > - info mtree (high) - memory region tree, multiple view modes
> > - info skeys (medium) - s390x storage keys
> > - info cmma (medium) - s390x CMMA values
> > - info qdm (easy) - could probably be folded into QOM introspection
> > - info qtree (medium) - same, maybe QOM introspection is enough
> > - info snapshots (medium)
> > - info usbhost (medium)
> > - info via (medium) -- VIA south bridge state
> >
> > Simple actions / settings:
> > - gdbserver (trivial)
> > - boot_set (easy)
> > - mce (easy) - x86 MCE injection
> > - sum (easy) - memory checksum
> > - sync-profile (easy) - enable/disable/reset
> > - info sync-profile (medium)
> > - one-insn-per-tb (easy) - could be a QOM property on the accelerator
> > - pcie_aer_inject_error (easy)
> > - migration_mode (medium?)
> > - i/o ioport read/write (easy)
> > - hostfwd-add/hostfwd-remove (medium) - slirp port forwarding
> > - log/logfile (medium)
> > - trace-file (medium)
> >
> > Also, to let clients do disassembly on their side, it'd be useful to
> > have something like "query-disassemble-info" that gives the client what
> > architecture and endianness is used etc.
> >
> > In the meantime, being able to build without HMP is valuable and helps
> > identifying the missing pieces. The series does so by steps:
> >
> > - preparatory cleanups and bug fixes
> > - add commands without QMP equivalent and needed for tests
> > - convert most iotests and qtests from HMP to QMP
> > - guard HMP-only code paths
> > - make HMP source files conditional in the build system
> >
>
> With regards,
> Daniel
> --
> |: https://berrange.com ~~ https://hachyderm.io/@berrange :|
> |: https://libvirt.org ~~ https://entangle-photo.org :|
> |: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|
>
>
^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [PATCH 04/40] target/i386: decouple cpu_x86_inject_mce() from Monitor
2026-05-21 5:49 ` Philippe Mathieu-Daudé
@ 2026-05-29 21:28 ` marcandre.lureau
0 siblings, 0 replies; 55+ messages in thread
From: marcandre.lureau @ 2026-05-29 21:28 UTC (permalink / raw)
To: Philippe Mathieu-Daudé; +Cc: Marc-André Lureau, qemu-devel
Hi
On 2026-05-21 07:49:38+02:00, Philippe Mathieu-Daudé wrote:
> On 20/5/26 23:49, Marc-André Lureau wrote:
>
> > Replace monitor_printf() error reporting with the standard **errp
> > pattern. Drop the Monitor *mon parameter and return bool to indicate
> > success, improving the function usage from non-HMP contexts. Update the
> > KVM MCE injection path and hmp_mce() accordingly.
> >
> > Notes:
> > - we may want to print the error in KVM path too
> > - multiple error prints are now accumulated with error hints
> >
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> > target/i386/cpu.h | 4 ++--
> > target/i386/helper.c | 49 ++++++++++++++++++++++++++++---------------------
> > target/i386/kvm/kvm.c | 4 ++--
> > target/i386/monitor.c | 6 ++++--
> > 4 files changed, 36 insertions(+), 27 deletions(-)
>
>
>
> > diff --git a/target/i386/monitor.c b/target/i386/monitor.c
> > index a536712c755..785a13dd710 100644
> > --- a/target/i386/monitor.c
> > +++ b/target/i386/monitor.c
> > @@ -580,6 +580,7 @@ void hmp_mce(Monitor *mon, const QDict *qdict)
> > uint64_t addr = qdict_get_int(qdict, "addr");
> > uint64_t misc = qdict_get_int(qdict, "misc");
> > int flags = MCE_INJECT_UNCOND_AO;
> > + Error *err = NULL;
> >
> > if (qdict_get_try_bool(qdict, "broadcast", false)) {
> > flags |= MCE_INJECT_BROADCAST;
> > @@ -587,7 +588,8 @@ void hmp_mce(Monitor *mon, const QDict *qdict)
> > cs = qemu_get_cpu(cpu_index);
>
> if (!cs) {
> error_setg(errp, "Invalid CPU %d", cpu_index);
> return;
> }
>
> ?
good idea,
>
> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
thanks
^ permalink raw reply [flat|nested] 55+ messages in thread
* Re: [PATCH 36/40] hw: guard BusClass::print_dev with CONFIG_HMP
2026-05-21 6:07 ` Philippe Mathieu-Daudé
@ 2026-05-29 21:31 ` marcandre.lureau
0 siblings, 0 replies; 55+ messages in thread
From: marcandre.lureau @ 2026-05-29 21:31 UTC (permalink / raw)
To: Philippe Mathieu-Daudé; +Cc: Marc-André Lureau, qemu-devel
hi
On 2026-05-21 08:07:39+02:00, Philippe Mathieu-Daudé wrote:
> On 20/5/26 23:49, Marc-André Lureau wrote:
>
> > The print_dev callback is only used by HMP 'info qtree'. Guard the field
> > in BusClass, all implementations, and the caller with CONFIG_HMP.
> >
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> > include/hw/core/qdev.h | 2 ++
> > hw/char/virtio-serial-bus.c | 6 ++++++
> > hw/core/sysbus.c | 6 ++++++
> > hw/misc/auxbus.c | 16 +++++++++++-----
> > hw/pci/pci-hmp-cmds.c | 2 ++
> > hw/pci/pci.c | 2 ++
> > hw/usb/bus.c | 6 ++++++
> > hw/xen/xen-bus.c | 4 ++++
> > system/qdev-monitor.c | 2 ++
> > 9 files changed, 41 insertions(+), 5 deletions(-)
> >
> > diff --git a/include/hw/core/qdev.h b/include/hw/core/qdev.h
> > index e1476223411..22dd143acf0 100644
> > --- a/include/hw/core/qdev.h
> > +++ b/include/hw/core/qdev.h
> > @@ -322,8 +322,10 @@ DECLARE_OBJ_CHECKERS(BusState, BusClass,
> > struct BusClass {
> > ObjectClass parent_class;
> >
> > +#ifdef CONFIG_HMP
> > /* FIXME first arg should be BusState */
> > void (*print_dev)(Monitor *mon, DeviceState *dev, int indent);
>
> We should fill a GString instead, avoiding the need of #ifdef'ry in hw/.
We could, but there is not much benefit. The function is still HMP specific, and
the point is to have HMP-only code clearly identifed and compiled out.
^ permalink raw reply [flat|nested] 55+ messages in thread
end of thread, other threads:[~2026-05-29 21:31 UTC | newest]
Thread overview: 55+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-20 21:49 [PATCH 00/40] Make HMP optional (and later standalone) Marc-André Lureau
2026-05-20 21:49 ` [PATCH 01/40] vl: fix -monitor none prefix matching Marc-André Lureau
2026-05-20 21:49 ` [PATCH 02/40] hmp: remove 'vcpu' argument from trace-event help Marc-André Lureau
2026-05-21 5:50 ` Philippe Mathieu-Daudé
2026-05-20 21:49 ` [PATCH 03/40] hmp: fix snapshot_blkdev argument type Marc-André Lureau
2026-05-20 21:49 ` [PATCH 04/40] target/i386: decouple cpu_x86_inject_mce() from Monitor Marc-André Lureau
2026-05-21 5:49 ` Philippe Mathieu-Daudé
2026-05-29 21:28 ` marcandre.lureau
2026-05-20 21:49 ` [PATCH 05/40] system: move gpa2hva() to system memory unit Marc-André Lureau
2026-05-21 5:50 ` Philippe Mathieu-Daudé
2026-05-20 21:49 ` [PATCH 06/40] s390x: prevent crash if given invalid CPU# Marc-André Lureau
2026-05-21 0:47 ` Eric Farman
2026-05-20 21:49 ` [PATCH 07/40] system: decouple qmp_inject_nmi() from Monitor Marc-André Lureau
2026-05-20 21:49 ` [PATCH 08/40] hmp: correct the nmi documentation Marc-André Lureau
2026-05-20 21:49 ` [PATCH 09/40] monitor: move HMP-only fields from Monitor to MonitorHMP Marc-André Lureau
2026-05-21 5:53 ` Philippe Mathieu-Daudé
2026-05-20 21:49 ` [PATCH 10/40] tests/functional: use query-version QMP command instead of HMP Marc-André Lureau
2026-05-21 5:54 ` Philippe Mathieu-Daudé
2026-05-20 21:49 ` [PATCH 11/40] net/qapi: add x-query-usernet Marc-André Lureau
2026-05-20 21:49 ` [PATCH 12/40] tests: use x-query-usernet Marc-André Lureau
2026-05-20 21:49 ` [PATCH 13/40] RFC: qtest: add -qtest-no-ts option Marc-André Lureau
2026-05-20 21:49 ` [PATCH 14/40] qemu-io: propagate errors through Error API instead of printf Marc-André Lureau
2026-05-21 6:02 ` Philippe Mathieu-Daudé
2026-05-20 21:49 ` [PATCH 15/40] block: add x-qemu-io QMP command Marc-André Lureau
2026-05-20 21:49 ` [PATCH 16/40] tests/qemu-iotests/N: use " Marc-André Lureau
2026-05-20 21:49 ` [PATCH 17/40] tests/qemu-iotests/181, 192, 249: convert to QMP Marc-André Lureau
2026-05-20 21:49 ` [PATCH 18/40] tests/qemu-iotests/186: convert from HMP " Marc-André Lureau
2026-05-20 21:49 ` [PATCH 19/40] tests/qemu-iotests/copy-before-write: convert " Marc-André Lureau
2026-05-20 21:49 ` [PATCH 20/40] tests/qemu-iotests: skip some 172 & 267 that require HMP Marc-André Lureau
2026-05-20 21:49 ` [PATCH 21/40] RFC: qtest: add qemu-io command to the qtest protocol Marc-André Lureau
2026-05-20 21:49 ` [PATCH 22/40] RFC: qtest/ide-test: convert to use qtest qemu-io command Marc-André Lureau
2026-05-20 21:49 ` [PATCH 23/40] tests/qtest/numa-test: replace HMP "info numa" with QMP query-cpus-fast Marc-André Lureau
2026-05-20 21:49 ` [PATCH 24/40] tests/qtest/pnv: drop unnecessary -serial mon:stdio Marc-André Lureau
2026-05-21 6:02 ` Philippe Mathieu-Daudé
2026-05-20 21:49 ` [PATCH 25/40] net: add x-query-network QMP command Marc-André Lureau
2026-05-20 21:49 ` [PATCH 26/40] tests/qtest/netdev-socket: replace HMP with x-query-network QMP Marc-André Lureau
2026-05-20 21:49 ` [PATCH 27/40] tests/qtest/cdrom-test: replace HMP "info block" with QMP query-block Marc-André Lureau
2026-05-21 6:03 ` Philippe Mathieu-Daudé
2026-05-20 21:49 ` [PATCH 28/40] tests/qtest/qmp-test: don't depend on human-monitor-command Marc-André Lureau
2026-05-20 21:49 ` [PATCH 29/40] build-sys: add 'hmp' option Marc-André Lureau
2026-05-20 21:49 ` [PATCH 30/40] tests/qtest/device-introspect-test: fix test without HMP Marc-André Lureau
2026-05-20 21:49 ` [PATCH 31/40] tests/qtest/drive_del-test: guard HMP-dependent tests with CONFIG_HMP Marc-André Lureau
2026-05-20 21:49 ` [PATCH 32/40] qapi: make HMP-specific schema entries conditional on CONFIG_HMP Marc-André Lureau
2026-05-20 21:49 ` [PATCH 33/40] monitor: guard HMP-specific code with CONFIG_HMP Marc-André Lureau
2026-05-20 21:49 ` [PATCH 34/40] util: guard monitor_vprintf callers " Marc-André Lureau
2026-05-20 21:49 ` [PATCH 35/40] system: guard HMP initialization paths " Marc-André Lureau
2026-05-20 21:49 ` [PATCH 36/40] hw: guard BusClass::print_dev " Marc-André Lureau
2026-05-21 6:07 ` Philippe Mathieu-Daudé
2026-05-29 21:31 ` marcandre.lureau
2026-05-20 21:49 ` [PATCH 37/40] target: guard MonitorDef tables " Marc-André Lureau
2026-05-20 21:49 ` [PATCH 38/40] Guard HMP command implementations " Marc-André Lureau
2026-05-20 21:49 ` [PATCH 39/40] build-sys: make HMP source files conditional on have_hmp Marc-André Lureau
2026-05-20 21:49 ` [PATCH 40/40] gitlab-ci: add --disable-hmp to build-without-defaults Marc-André Lureau
2026-05-21 7:55 ` [PATCH 00/40] Make HMP optional (and later standalone) Daniel P. Berrangé
2026-05-21 8:04 ` Marc-André Lureau
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.