[PATCH v2 00/13] qemu: use 'usb-bot' device to properly emulate USB cdroms

Version 2 of this series includes changes I've requested in the review and much more that I've learned during adaptation and testing: - 'usb-bot' and 'usb-storage' are not ABI compatible for CDROMs Migrating a guest from 'usb-bot'(with cdrom) to 'usb-storage' results in I/O errors on reads with linux guest. This required adding compatibility layer - exposing the model in -xml and corresponding post-parse and migratable XML config This patchset still tries as much as possible to use the 'usb-bot' device for cdroms to fix the definition - more tests - keeping of 'usb-storage' support - XML config and documentation - cleanup of the code The necessary logic is explained in the patches as comments. Akihiko Odaki (2): qemu_capabilities: Introduce QEMU_CAPS_DEVICE_USB_BOT qemu: Replace usb-storage with usb-bot Peter Krempa (11): qemuhotplugtest: Use VIR_DOMAIN_DEF_PARSE_ABI_UPDATE for virDomainDeviceDefParse qemuxmlconftest: Test various combinations of config qemusecuritytest: Use 'disk-usb-device' case instead of 'disk-cdrom-bus-other' qemuxmlconftest: Drop 'disk-cdrom-bus-other' qemuxmlconftest: Distribute testing of 'removable' disk property qemuxmlconftest: Invoke "disk-usb-device" case also without QEMU_CAPS_DEVICE_USB_BOT and with ABI_UPDATE conf: introduce usb disk models 'usb-storage' and 'usb-bot' qemu: Fill in model of 'usb' disks to preserve ABI compatibility qemuBuildDeviceAddresDriveProps: Prepare for 'drive' address for usb-bot disks qemu: monitor: Introduce 'qemuMonitorSetUSBDiskAttached' qemuxmlconftest: Prepare for proper testing in 'disk-cdrom-usb-empty' docs/formatdomain.rst | 23 +++- src/conf/domain_conf.c | 2 + src/conf/domain_conf.h | 3 + src/conf/schemas/domaincommon.rng | 2 + src/qemu/qemu_alias.c | 20 ++- src/qemu/qemu_capabilities.c | 7 +- src/qemu/qemu_capabilities.h | 3 + src/qemu/qemu_command.c | 101 ++++++++++++-- src/qemu/qemu_command.h | 5 + src/qemu/qemu_domain.c | 21 +++ src/qemu/qemu_domain_address.c | 2 + src/qemu/qemu_hotplug.c | 18 +++ src/qemu/qemu_monitor.c | 12 ++ src/qemu/qemu_monitor.h | 3 + src/qemu/qemu_monitor_json.c | 20 +++ src/qemu/qemu_monitor_json.h | 5 + src/qemu/qemu_postparse.c | 49 ++++++- src/qemu/qemu_postparse.h | 4 +- src/qemu/qemu_validate.c | 37 +++++- tests/qemublocktest.c | 13 +- .../caps_10.0.0_aarch64.xml | 1 + .../caps_10.0.0_ppc64.xml | 1 + .../caps_10.0.0_s390x.xml | 1 + .../caps_10.0.0_x86_64+amdsev.xml | 1 + .../caps_10.0.0_x86_64.xml | 1 + .../qemucapabilitiesdata/caps_6.2.0_ppc64.xml | 1 + .../caps_6.2.0_x86_64.xml | 1 + .../qemucapabilitiesdata/caps_7.0.0_ppc64.xml | 1 + .../caps_7.0.0_x86_64.xml | 1 + .../qemucapabilitiesdata/caps_7.1.0_ppc64.xml | 1 + .../caps_7.1.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_7.2.0_ppc.xml | 1 + .../caps_7.2.0_x86_64+hvf.xml | 1 + .../caps_7.2.0_x86_64.xml | 1 + .../caps_8.0.0_x86_64.xml | 1 + .../qemucapabilitiesdata/caps_8.1.0_s390x.xml | 1 + .../caps_8.1.0_x86_64.xml | 1 + .../caps_8.2.0_aarch64.xml | 1 + .../caps_8.2.0_armv7l.xml | 1 + .../caps_8.2.0_loongarch64.xml | 1 + .../qemucapabilitiesdata/caps_8.2.0_s390x.xml | 1 + .../caps_8.2.0_x86_64.xml | 1 + .../caps_9.0.0_x86_64.xml | 1 + .../caps_9.1.0_riscv64.xml | 1 + .../qemucapabilitiesdata/caps_9.1.0_s390x.xml | 1 + .../caps_9.1.0_x86_64.xml | 1 + .../caps_9.2.0_aarch64+hvf.xml | 1 + .../qemucapabilitiesdata/caps_9.2.0_s390x.xml | 1 + .../caps_9.2.0_x86_64+amdsev.xml | 1 + .../caps_9.2.0_x86_64.xml | 1 + tests/qemuhotplugtest.c | 8 +- .../qemuhotplug-base-live+cdrom-usb.xml | 2 +- .../qemuhotplug-base-live+disk-usb.xml | 2 +- tests/qemusecuritytest.c | 2 +- .../disk-cache.x86_64-latest.xml | 2 +- .../qemuxmlconfdata/disk-cdrom-bus-other.xml | 30 ----- ...m-usb-empty.x86_64-latest.abi-update.args} | 4 +- ...om-usb-empty.x86_64-latest.abi-update.xml} | 6 +- .../disk-device-removable.x86_64-latest.args | 40 ------ .../qemuxmlconfdata/disk-device-removable.xml | 32 ----- .../disk-scsi.x86_64-latest.args | 2 +- tests/qemuxmlconfdata/disk-scsi.xml | 2 +- .../disk-usb-device-model.x86_64-latest.args | 48 +++++++ ...> disk-usb-device-model.x86_64-latest.xml} | 46 ++++--- .../qemuxmlconfdata/disk-usb-device-model.xml | 46 +++++++ ...est.QEMU_CAPS_DEVICE_USB_BOT-disabled.args | 59 +++++++++ ...test.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml | 107 +++++++++++++++ ...ate.QEMU_CAPS_DEVICE_USB_BOT-disabled.args | 59 +++++++++ ...date.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml | 125 ++++++++++++++++++ ...k-usb-device.x86_64-latest.abi-update.args | 63 +++++++++ ...sk-usb-device.x86_64-latest.abi-update.xml | 125 ++++++++++++++++++ .../disk-usb-device.x86_64-latest.args | 30 ++++- .../disk-usb-device.x86_64-latest.xml | 82 ++++++++++-- tests/qemuxmlconfdata/disk-usb-device.xml | 66 ++++++++- tests/qemuxmlconftest.c | 16 ++- 75 files changed, 1197 insertions(+), 187 deletions(-) delete mode 100644 tests/qemuxmlconfdata/disk-cdrom-bus-other.xml rename tests/qemuxmlconfdata/{disk-cdrom-bus-other.x86_64-latest.args => disk-cdrom-usb-empty.x86_64-latest.abi-update.args} (84%) rename tests/qemuxmlconfdata/{disk-cdrom-bus-other.x86_64-latest.xml => disk-cdrom-usb-empty.x86_64-latest.abi-update.xml} (89%) delete mode 100644 tests/qemuxmlconfdata/disk-device-removable.x86_64-latest.args delete mode 100644 tests/qemuxmlconfdata/disk-device-removable.xml create mode 100644 tests/qemuxmlconfdata/disk-usb-device-model.x86_64-latest.args rename tests/qemuxmlconfdata/{disk-device-removable.x86_64-latest.xml => disk-usb-device-model.x86_64-latest.xml} (56%) create mode 100644 tests/qemuxmlconfdata/disk-usb-device-model.xml create mode 100644 tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.QEMU_CAPS_DEVICE_USB_BOT-disabled.args create mode 100644 tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml create mode 100644 tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.QEMU_CAPS_DEVICE_USB_BOT-disabled.args create mode 100644 tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml create mode 100644 tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.args create mode 100644 tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.xml -- 2.49.0

From: Peter Krempa <pkrempa@redhat.com> The qemu hotplug code parses the device with ABI updates enabled so qemuhotplugtest ought to do the same. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- tests/qemuhotplugtest.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c index d2a1f5acf1..fdb5093549 100644 --- a/tests/qemuhotplugtest.c +++ b/tests/qemuhotplugtest.c @@ -152,7 +152,7 @@ testQemuHotplug(const void *data) const char *const *tmp; bool fail = test->fail; bool keep = test->keep; - unsigned int device_parse_flags = 0; + unsigned int device_parse_flags = VIR_DOMAIN_DEF_PARSE_ABI_UPDATE; virDomainObj *vm = NULL; g_autoptr(virDomainDeviceDef) dev = NULL; g_autoptr(qemuMonitorTest) test_mon = NULL; @@ -191,7 +191,7 @@ testQemuHotplug(const void *data) } if (test->action == ATTACH) - device_parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE; + device_parse_flags |= VIR_DOMAIN_DEF_PARSE_INACTIVE; if (!(dev = virDomainDeviceDefParse(device_xml, vm->def, driver.xmlopt, NULL, -- 2.49.0

On Mon, Jun 23, 2025 at 21:59:06 +0200, Peter Krempa wrote:
From: Peter Krempa <pkrempa@redhat.com>
The qemu hotplug code parses the device with ABI updates enabled so qemuhotplugtest ought to do the same.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- tests/qemuhotplugtest.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>

From: Peter Krempa <pkrempa@redhat.com> Add multiple USB disks to the definition testing a matrix of 'disk' and 'cdrom' <disk> elements with user-aliases, 'serial' and 'removable' properties configured. This patch also removes the 'ide' disk which is not related to what we're testing here. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- .../disk-usb-device.x86_64-latest.args | 30 ++++++- .../disk-usb-device.x86_64-latest.xml | 80 ++++++++++++++++--- tests/qemuxmlconfdata/disk-usb-device.xml | 66 +++++++++++++-- 3 files changed, 158 insertions(+), 18 deletions(-) diff --git a/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.args b/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.args index 0fd7e755b1..079dfe5d99 100644 --- a/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.args +++ b/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.args @@ -27,10 +27,32 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ -no-shutdown \ -boot strict=on \ -device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \ --blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest1","node-name":"libvirt-2-storage","read-only":false}' \ --device '{"driver":"ide-hd","bus":"ide.0","unit":0,"drive":"libvirt-2-storage","id":"ide0-0-0","bootindex":1}' \ --blockdev '{"driver":"file","filename":"/tmp/usbdisk.img","node-name":"libvirt-1-storage","read-only":false}' \ --device '{"driver":"usb-storage","bus":"usb.0","port":"1","drive":"libvirt-1-storage","id":"usb-disk0","removable":false}' \ +-device '{"driver":"usb-hub","id":"hub0","bus":"usb.0","port":"1"}' \ +-device '{"driver":"usb-hub","id":"hub1","bus":"usb.0","port":"2"}' \ +-blockdev '{"driver":"file","filename":"/tmp/img1","node-name":"libvirt-12-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.1","drive":"libvirt-12-storage","id":"usb-disk0","bootindex":1,"removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img2","node-name":"libvirt-11-storage","read-only":true}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.2","drive":"libvirt-11-storage","id":"usb-disk1","removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img3","node-name":"libvirt-10-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.3","drive":"libvirt-10-storage","id":"usb-disk2","removable":false,"serial":"testserial1"}' \ +-blockdev '{"driver":"file","filename":"/tmp/img4","node-name":"libvirt-9-storage","read-only":true}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.4","drive":"libvirt-9-storage","id":"usb-disk3","removable":false,"serial":"testserial2"}' \ +-blockdev '{"driver":"file","filename":"/tmp/img5","node-name":"libvirt-8-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.5","drive":"libvirt-8-storage","id":"ua-test1","removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img6","node-name":"libvirt-7-storage","read-only":true}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.6","drive":"libvirt-7-storage","id":"ua-test2","removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img7","node-name":"libvirt-6-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.7","drive":"libvirt-6-storage","id":"ua-test3","removable":false,"serial":"testserial3"}' \ +-blockdev '{"driver":"file","filename":"/tmp/img8","node-name":"libvirt-5-storage","read-only":true}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.8","drive":"libvirt-5-storage","id":"ua-test4","removable":false,"serial":"testserial4"}' \ +-blockdev '{"driver":"file","filename":"/tmp/img9","node-name":"libvirt-4-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"2.1","drive":"libvirt-4-storage","id":"usb-disk8","removable":true}' \ +-blockdev '{"driver":"file","filename":"/tmp/imga","node-name":"libvirt-3-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"2.2","drive":"libvirt-3-storage","id":"usb-disk9","removable":true,"serial":"testserial5"}' \ +-blockdev '{"driver":"file","filename":"/tmp/imgb","node-name":"libvirt-2-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"2.3","drive":"libvirt-2-storage","id":"ua-test5","removable":true}' \ +-blockdev '{"driver":"file","filename":"/tmp/imgc","node-name":"libvirt-1-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"2.4","drive":"libvirt-1-storage","id":"ua-test6","removable":true,"serial":"testserial6"}' \ -audiodev '{"id":"audio1","driver":"none"}' \ -device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x2"}' \ -sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ diff --git a/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.xml b/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.xml index e42dc23178..8b78f77e63 100644 --- a/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.xml +++ b/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.xml @@ -17,24 +17,86 @@ <on_crash>destroy</on_crash> <devices> <emulator>/usr/bin/qemu-system-x86_64</emulator> - <disk type='block' device='disk'> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img1'/> + <target dev='sda' bus='usb'/> + </disk> + <disk type='file' device='cdrom'> <driver name='qemu' type='raw'/> - <source dev='/dev/HostVG/QEMUGuest1'/> - <target dev='hda' bus='ide'/> - <address type='drive' controller='0' bus='0' target='0' unit='0'/> + <source file='/tmp/img2'/> + <target dev='sdb' bus='usb'/> + <readonly/> </disk> <disk type='file' device='disk'> <driver name='qemu' type='raw'/> - <source file='/tmp/usbdisk.img'/> - <target dev='sda' bus='usb'/> + <source file='/tmp/img3'/> + <target dev='sdc' bus='usb'/> + <serial>testserial1</serial> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img4'/> + <target dev='sdd' bus='usb'/> + <readonly/> + <serial>testserial2</serial> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img5'/> + <target dev='sde' bus='usb'/> + <alias name='ua-test1'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img6'/> + <target dev='sdf' bus='usb'/> + <readonly/> + <alias name='ua-test2'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img7'/> + <target dev='sdg' bus='usb'/> + <serial>testserial3</serial> + <alias name='ua-test3'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img8'/> + <target dev='sdh' bus='usb'/> + <readonly/> + <serial>testserial4</serial> + <alias name='ua-test4'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img9'/> + <target dev='sdi' bus='usb' removable='on'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/imga'/> + <target dev='sdj' bus='usb' removable='on'/> + <serial>testserial5</serial> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/imgb'/> + <target dev='sdk' bus='usb' removable='on'/> + <alias name='ua-test5'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/imgc'/> + <target dev='sdl' bus='usb' removable='on'/> + <serial>testserial6</serial> + <alias name='ua-test6'/> </disk> <controller type='usb' index='0' model='piix3-uhci'> <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> </controller> <controller type='pci' index='0' model='pci-root'/> - <controller type='ide' index='0'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> - </controller> <input type='mouse' bus='ps2'/> <input type='keyboard' bus='ps2'/> <audio id='1' type='none'/> diff --git a/tests/qemuxmlconfdata/disk-usb-device.xml b/tests/qemuxmlconfdata/disk-usb-device.xml index 92dcc659ac..0478875177 100644 --- a/tests/qemuxmlconfdata/disk-usb-device.xml +++ b/tests/qemuxmlconfdata/disk-usb-device.xml @@ -14,14 +14,70 @@ <on_crash>destroy</on_crash> <devices> <emulator>/usr/bin/qemu-system-x86_64</emulator> - <disk type='block' device='disk'> - <source dev='/dev/HostVG/QEMUGuest1'/> - <target dev='hda' bus='ide'/> - </disk> <disk type='file' device='disk'> - <source file='/tmp/usbdisk.img'/> + <source file='/tmp/img1'/> <target dev='sda' bus='usb'/> </disk> + <disk type='file' device='cdrom'> + <source file='/tmp/img2'/> + <target dev='sdb' bus='usb'/> + <readonly/> + </disk> + <disk type='file' device='disk'> + <source file='/tmp/img3'/> + <target dev='sdc' bus='usb'/> + <serial>testserial1</serial> + </disk> + <disk type='file' device='cdrom'> + <source file='/tmp/img4'/> + <target dev='sdd' bus='usb'/> + <readonly/> + <serial>testserial2</serial> + </disk> + <disk type='file' device='disk'> + <source file='/tmp/img5'/> + <target dev='sde' bus='usb'/> + <alias name='ua-test1'/> + </disk> + <disk type='file' device='cdrom'> + <source file='/tmp/img6'/> + <target dev='sdf' bus='usb'/> + <readonly/> + <alias name='ua-test2'/> + </disk> + <disk type='file' device='disk'> + <source file='/tmp/img7'/> + <target dev='sdg' bus='usb'/> + <serial>testserial3</serial> + <alias name='ua-test3'/> + </disk> + <disk type='file' device='cdrom'> + <source file='/tmp/img8'/> + <target dev='sdh' bus='usb'/> + <readonly/> + <serial>testserial4</serial> + <alias name='ua-test4'/> + </disk> + <disk type='file' device='disk'> + <source file='/tmp/img9'/> + <target dev='sdi' bus='usb' removable='on'/> + </disk> + <disk type='file' device='disk'> + <source file='/tmp/imga'/> + <target dev='sdj' bus='usb' removable='on'/> + <serial>testserial5</serial> + </disk> + <disk type='file' device='disk'> + <source file='/tmp/imgb'/> + <target dev='sdk' bus='usb' removable='on'/> + <alias name='ua-test5'/> + </disk> + <disk type='file' device='disk'> + <source file='/tmp/imgc'/> + <target dev='sdl' bus='usb' removable='on'/> + <serial>testserial6</serial> + <alias name='ua-test6'/> + </disk> <memballoon model='virtio'/> </devices> </domain> -- 2.49.0

On Mon, Jun 23, 2025 at 21:59:07 +0200, Peter Krempa wrote:
From: Peter Krempa <pkrempa@redhat.com>
Add multiple USB disks to the definition testing a matrix of 'disk' and 'cdrom' <disk> elements with user-aliases, 'serial' and 'removable' properties configured.
This patch also removes the 'ide' disk which is not related to what we're testing here.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- .../disk-usb-device.x86_64-latest.args | 30 ++++++- .../disk-usb-device.x86_64-latest.xml | 80 ++++++++++++++++--- tests/qemuxmlconfdata/disk-usb-device.xml | 66 +++++++++++++-- 3 files changed, 158 insertions(+), 18 deletions(-)
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>

From: Peter Krempa <pkrempa@redhat.com> Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- tests/qemusecuritytest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/qemusecuritytest.c b/tests/qemusecuritytest.c index 88c8617d69..ba9506d0a0 100644 --- a/tests/qemusecuritytest.c +++ b/tests/qemusecuritytest.c @@ -207,7 +207,7 @@ mymain(void) DO_TEST_DOMAIN("disk-backing-chains-noindex"); DO_TEST_DOMAIN("disk-cache"); DO_TEST_DOMAIN("disk-cdrom"); - DO_TEST_DOMAIN("disk-cdrom-bus-other"); + DO_TEST_DOMAIN("disk-usb-device"); DO_TEST_DOMAIN("disk-cdrom-network"); DO_TEST_DOMAIN("disk-cdrom-tray"); DO_TEST_DOMAIN("disk-copy_on_read"); -- 2.49.0

On Mon, Jun 23, 2025 at 21:59:08 +0200, Peter Krempa wrote:
From: Peter Krempa <pkrempa@redhat.com>
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- tests/qemusecuritytest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>

From: Peter Krempa <pkrempa@redhat.com> The test case is now redundant since 'disk-usb-device' case also tests all cdrom configurations. Remove it. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- .../disk-cdrom-bus-other.x86_64-latest.args | 34 ----------------- .../disk-cdrom-bus-other.x86_64-latest.xml | 38 ------------------- .../qemuxmlconfdata/disk-cdrom-bus-other.xml | 30 --------------- tests/qemuxmlconftest.c | 1 - 4 files changed, 103 deletions(-) delete mode 100644 tests/qemuxmlconfdata/disk-cdrom-bus-other.x86_64-latest.args delete mode 100644 tests/qemuxmlconfdata/disk-cdrom-bus-other.x86_64-latest.xml delete mode 100644 tests/qemuxmlconfdata/disk-cdrom-bus-other.xml diff --git a/tests/qemuxmlconfdata/disk-cdrom-bus-other.x86_64-latest.args b/tests/qemuxmlconfdata/disk-cdrom-bus-other.x86_64-latest.args deleted file mode 100644 index e1406af663..0000000000 --- a/tests/qemuxmlconfdata/disk-cdrom-bus-other.x86_64-latest.args +++ /dev/null @@ -1,34 +0,0 @@ -LC_ALL=C \ -PATH=/bin \ -HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1 \ -USER=test \ -LOGNAME=test \ -XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.local/share \ -XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.cache \ -XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ -/usr/bin/qemu-system-x86_64 \ --name guest=QEMUGuest1,debug-threads=on \ --S \ --object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ --machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \ --accel tcg \ --cpu qemu64 \ --m size=219136k \ --object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ --overcommit mem-lock=off \ --smp 1,sockets=1,cores=1,threads=1 \ --uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ --display none \ --no-user-config \ --nodefaults \ --chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ --mon chardev=charmonitor,id=monitor,mode=control \ --rtc base=utc \ --no-shutdown \ --boot strict=on \ --device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \ --blockdev '{"driver":"file","filename":"/root/boot.iso","node-name":"libvirt-1-storage","read-only":true}' \ --device '{"driver":"usb-storage","bus":"usb.0","port":"1","drive":"libvirt-1-storage","id":"usb-disk0","removable":false}' \ --audiodev '{"id":"audio1","driver":"none"}' \ --sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ --msg timestamp=on diff --git a/tests/qemuxmlconfdata/disk-cdrom-bus-other.x86_64-latest.xml b/tests/qemuxmlconfdata/disk-cdrom-bus-other.x86_64-latest.xml deleted file mode 100644 index f16fe63057..0000000000 --- a/tests/qemuxmlconfdata/disk-cdrom-bus-other.x86_64-latest.xml +++ /dev/null @@ -1,38 +0,0 @@ -<domain type='qemu'> - <name>QEMUGuest1</name> - <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> - <memory unit='KiB'>219100</memory> - <currentMemory unit='KiB'>219100</currentMemory> - <vcpu placement='static'>1</vcpu> - <os> - <type arch='x86_64' machine='pc'>hvm</type> - <boot dev='hd'/> - </os> - <cpu mode='custom' match='exact' check='none'> - <model fallback='forbid'>qemu64</model> - </cpu> - <clock offset='utc'/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-system-x86_64</emulator> - <disk type='file' device='cdrom'> - <driver name='qemu' type='raw'/> - <source file='/root/boot.iso'/> - <target dev='sda' bus='usb'/> - <readonly/> - </disk> - <controller type='usb' index='0' model='piix3-uhci'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> - </controller> - <controller type='ide' index='0'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> - </controller> - <controller type='pci' index='0' model='pci-root'/> - <input type='mouse' bus='ps2'/> - <input type='keyboard' bus='ps2'/> - <audio id='1' type='none'/> - <memballoon model='none'/> - </devices> -</domain> diff --git a/tests/qemuxmlconfdata/disk-cdrom-bus-other.xml b/tests/qemuxmlconfdata/disk-cdrom-bus-other.xml deleted file mode 100644 index 119ce297a0..0000000000 --- a/tests/qemuxmlconfdata/disk-cdrom-bus-other.xml +++ /dev/null @@ -1,30 +0,0 @@ -<domain type='qemu'> - <name>QEMUGuest1</name> - <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> - <memory unit='KiB'>219100</memory> - <currentMemory unit='KiB'>219100</currentMemory> - <vcpu placement='static'>1</vcpu> - <os> - <type arch='x86_64' machine='pc'>hvm</type> - <boot dev='hd'/> - </os> - <clock offset='utc'/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-system-x86_64</emulator> - <disk type='file' device='cdrom'> - <driver name='qemu' type='raw'/> - <source file='/root/boot.iso'/> - <target dev='sda' bus='usb'/> - <readonly/> - </disk> - <controller type='usb' index='0'/> - <controller type='ide' index='0'/> - <controller type='pci' index='0' model='pci-root'/> - <input type='mouse' bus='ps2'/> - <input type='keyboard' bus='ps2'/> - <memballoon model='none'/> - </devices> -</domain> diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index 3f99026a31..dc93e59d34 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1545,7 +1545,6 @@ mymain(void) DO_TEST_CAPS_LATEST("disk-cdrom"); DO_TEST_CAPS_LATEST("disk-cdrom-empty-network-invalid"); - DO_TEST_CAPS_LATEST("disk-cdrom-bus-other"); DO_TEST_CAPS_LATEST_PARSE_ERROR("disk-cdrom-usb-empty"); DO_TEST_CAPS_LATEST("disk-cdrom-network"); DO_TEST_CAPS_LATEST("disk-cdrom-tray"); -- 2.49.0

On Mon, Jun 23, 2025 at 21:59:09 +0200, Peter Krempa wrote:
From: Peter Krempa <pkrempa@redhat.com>
The test case is now redundant since 'disk-usb-device' case also tests all cdrom configurations. Remove it.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- .../disk-cdrom-bus-other.x86_64-latest.args | 34 ----------------- .../disk-cdrom-bus-other.x86_64-latest.xml | 38 ------------------- .../qemuxmlconfdata/disk-cdrom-bus-other.xml | 30 --------------- tests/qemuxmlconftest.c | 1 - 4 files changed, 103 deletions(-) delete mode 100644 tests/qemuxmlconfdata/disk-cdrom-bus-other.x86_64-latest.args delete mode 100644 tests/qemuxmlconfdata/disk-cdrom-bus-other.x86_64-latest.xml delete mode 100644 tests/qemuxmlconfdata/disk-cdrom-bus-other.xml
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>

From: Peter Krempa <pkrempa@redhat.com> The 'removable' property is tested for 'usb' and 'scsi' disks. The test case for 'usb' disks already has another test case for this, so add testing of 'removable' SCSI disks into the 'disk-scsi' case and remove the 'disk-device-removable' case completely. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- .../disk-device-removable.x86_64-latest.args | 40 -------------- .../disk-device-removable.x86_64-latest.xml | 54 ------------------- .../qemuxmlconfdata/disk-device-removable.xml | 32 ----------- .../disk-scsi.x86_64-latest.args | 2 +- tests/qemuxmlconfdata/disk-scsi.xml | 2 +- tests/qemuxmlconftest.c | 1 - 6 files changed, 2 insertions(+), 129 deletions(-) delete mode 100644 tests/qemuxmlconfdata/disk-device-removable.x86_64-latest.args delete mode 100644 tests/qemuxmlconfdata/disk-device-removable.x86_64-latest.xml delete mode 100644 tests/qemuxmlconfdata/disk-device-removable.xml diff --git a/tests/qemuxmlconfdata/disk-device-removable.x86_64-latest.args b/tests/qemuxmlconfdata/disk-device-removable.x86_64-latest.args deleted file mode 100644 index e0701f4bd2..0000000000 --- a/tests/qemuxmlconfdata/disk-device-removable.x86_64-latest.args +++ /dev/null @@ -1,40 +0,0 @@ -LC_ALL=C \ -PATH=/bin \ -HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1 \ -USER=test \ -LOGNAME=test \ -XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.local/share \ -XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.cache \ -XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ -/usr/bin/qemu-system-x86_64 \ --name guest=QEMUGuest1,debug-threads=on \ --S \ --object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ --machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \ --accel tcg \ --cpu qemu64 \ --m size=219136k \ --object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ --overcommit mem-lock=off \ --smp 1,sockets=1,cores=1,threads=1 \ --uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ --display none \ --no-user-config \ --nodefaults \ --chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ --mon chardev=charmonitor,id=monitor,mode=control \ --rtc base=utc \ --no-shutdown \ --boot strict=on \ --device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \ --device '{"driver":"virtio-scsi-pci","id":"scsi0","bus":"pci.0","addr":"0x2"}' \ --blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest1","node-name":"libvirt-3-storage","read-only":false}' \ --device '{"driver":"ide-hd","bus":"ide.0","unit":0,"drive":"libvirt-3-storage","id":"ide0-0-0","bootindex":1}' \ --blockdev '{"driver":"file","filename":"/tmp/usbdisk.img","node-name":"libvirt-2-storage","read-only":false}' \ --device '{"driver":"usb-storage","bus":"usb.0","port":"1","drive":"libvirt-2-storage","id":"usb-disk0","removable":true}' \ --blockdev '{"driver":"file","filename":"/tmp/scsidisk.img","node-name":"libvirt-1-storage","read-only":false}' \ --device '{"driver":"scsi-hd","bus":"scsi0.0","channel":0,"scsi-id":0,"lun":1,"device_id":"drive-scsi0-0-0-1","drive":"libvirt-1-storage","id":"scsi0-0-0-1","removable":true}' \ --audiodev '{"id":"audio1","driver":"none"}' \ --device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x3"}' \ --sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ --msg timestamp=on diff --git a/tests/qemuxmlconfdata/disk-device-removable.x86_64-latest.xml b/tests/qemuxmlconfdata/disk-device-removable.x86_64-latest.xml deleted file mode 100644 index 2fd3284dee..0000000000 --- a/tests/qemuxmlconfdata/disk-device-removable.x86_64-latest.xml +++ /dev/null @@ -1,54 +0,0 @@ -<domain type='qemu'> - <name>QEMUGuest1</name> - <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> - <memory unit='KiB'>219136</memory> - <currentMemory unit='KiB'>219136</currentMemory> - <vcpu placement='static'>1</vcpu> - <os> - <type arch='x86_64' machine='pc'>hvm</type> - <boot dev='hd'/> - </os> - <cpu mode='custom' match='exact' check='none'> - <model fallback='forbid'>qemu64</model> - </cpu> - <clock offset='utc'/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-system-x86_64</emulator> - <disk type='block' device='disk'> - <driver name='qemu' type='raw'/> - <source dev='/dev/HostVG/QEMUGuest1'/> - <target dev='hda' bus='ide'/> - <address type='drive' controller='0' bus='0' target='0' unit='0'/> - </disk> - <disk type='file' device='disk'> - <driver name='qemu' type='raw'/> - <source file='/tmp/usbdisk.img'/> - <target dev='sda' bus='usb' removable='on'/> - </disk> - <disk type='file' device='disk'> - <driver name='qemu' type='raw'/> - <source file='/tmp/scsidisk.img'/> - <target dev='sdb' bus='scsi'/> - <address type='drive' controller='0' bus='0' target='0' unit='1'/> - </disk> - <controller type='scsi' index='0' model='virtio-scsi'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> - </controller> - <controller type='usb' index='0' model='piix3-uhci'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> - </controller> - <controller type='pci' index='0' model='pci-root'/> - <controller type='ide' index='0'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> - </controller> - <input type='mouse' bus='ps2'/> - <input type='keyboard' bus='ps2'/> - <audio id='1' type='none'/> - <memballoon model='virtio'> - <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> - </memballoon> - </devices> -</domain> diff --git a/tests/qemuxmlconfdata/disk-device-removable.xml b/tests/qemuxmlconfdata/disk-device-removable.xml deleted file mode 100644 index 9400c84863..0000000000 --- a/tests/qemuxmlconfdata/disk-device-removable.xml +++ /dev/null @@ -1,32 +0,0 @@ -<domain type='qemu'> - <name>QEMUGuest1</name> - <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> - <memory unit='KiB'>219136</memory> - <currentMemory unit='KiB'>219136</currentMemory> - <vcpu placement='static'>1</vcpu> - <os> - <type arch='x86_64' machine='pc'>hvm</type> - <boot dev='hd'/> - </os> - <clock offset='utc'/> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-system-x86_64</emulator> - <disk type='block' device='disk'> - <source dev='/dev/HostVG/QEMUGuest1'/> - <target dev='hda' bus='ide'/> - </disk> - <disk type='file' device='disk'> - <source file='/tmp/usbdisk.img'/> - <target dev='sda' bus='usb' removable='on'/> - </disk> - <disk type='file' device='disk'> - <source file='/tmp/scsidisk.img'/> - <target dev='sdb' bus='scsi' removable='on'/> - </disk> - <controller type='scsi' index='0' model='virtio-scsi'/> - <memballoon model='virtio'/> - </devices> -</domain> diff --git a/tests/qemuxmlconfdata/disk-scsi.x86_64-latest.args b/tests/qemuxmlconfdata/disk-scsi.x86_64-latest.args index 1b8150f4d4..cd07cd2d22 100644 --- a/tests/qemuxmlconfdata/disk-scsi.x86_64-latest.args +++ b/tests/qemuxmlconfdata/disk-scsi.x86_64-latest.args @@ -43,7 +43,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ -blockdev '{"driver":"file","filename":"/tmp/scsidisk4.img","node-name":"libvirt-2-storage","read-only":false}' \ -device '{"driver":"scsi-hd","bus":"scsi3.0","channel":0,"scsi-id":0,"lun":0,"device_id":"drive-scsi3-0-0-0","drive":"libvirt-2-storage","id":"scsi3-0-0-0"}' \ -blockdev '{"driver":"file","filename":"/tmp/scsidisk5.img","node-name":"libvirt-1-storage","read-only":false}' \ --device '{"driver":"scsi-hd","bus":"scsi4.0","channel":0,"scsi-id":0,"lun":0,"device_id":"drive-scsi4-0-0-0","drive":"libvirt-1-storage","id":"scsi4-0-0-0"}' \ +-device '{"driver":"scsi-hd","bus":"scsi4.0","channel":0,"scsi-id":0,"lun":0,"device_id":"drive-scsi4-0-0-0","drive":"libvirt-1-storage","id":"scsi4-0-0-0","removable":true}' \ -audiodev '{"id":"audio1","driver":"none"}' \ -device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x6"}' \ -sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ diff --git a/tests/qemuxmlconfdata/disk-scsi.xml b/tests/qemuxmlconfdata/disk-scsi.xml index 1072e8b6fc..755c856b98 100644 --- a/tests/qemuxmlconfdata/disk-scsi.xml +++ b/tests/qemuxmlconfdata/disk-scsi.xml @@ -43,7 +43,7 @@ </disk> <disk type='file' device='disk'> <source file='/tmp/scsidisk5.img'/> - <target dev='sde' bus='scsi'/> + <target dev='sde' bus='scsi' removable='on'/> <address type='drive' controller='4' bus='0' target='0' unit='0'/> </disk> <controller type='usb' index='0'/> diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index dc93e59d34..c7b6df5a6a 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1609,7 +1609,6 @@ mymain(void) DO_TEST_CAPS_LATEST_PARSE_ERROR("disk-device-lun-type-invalid"); DO_TEST_CAPS_LATEST_PARSE_ERROR("disk-attaching-partition-nosupport"); DO_TEST_CAPS_LATEST("disk-usb-device"); - DO_TEST_CAPS_LATEST("disk-device-removable"); DO_TEST_CAPS_LATEST_PARSE_ERROR("disk-usb-pci"); DO_TEST_CAPS_LATEST("disk-scsi"); DO_TEST_CAPS_LATEST("disk-scsi-device-auto"); -- 2.49.0

On Mon, Jun 23, 2025 at 21:59:10 +0200, Peter Krempa wrote:
From: Peter Krempa <pkrempa@redhat.com>
The 'removable' property is tested for 'usb' and 'scsi' disks. The test case for 'usb' disks already has another test case for this, so add testing of 'removable' SCSI disks into the 'disk-scsi' case and remove the 'disk-device-removable' case completely.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- .../disk-device-removable.x86_64-latest.args | 40 -------------- .../disk-device-removable.x86_64-latest.xml | 54 ------------------- .../qemuxmlconfdata/disk-device-removable.xml | 32 ----------- .../disk-scsi.x86_64-latest.args | 2 +- tests/qemuxmlconfdata/disk-scsi.xml | 2 +- tests/qemuxmlconftest.c | 1 - 6 files changed, 2 insertions(+), 129 deletions(-) delete mode 100644 tests/qemuxmlconfdata/disk-device-removable.x86_64-latest.args delete mode 100644 tests/qemuxmlconfdata/disk-device-removable.x86_64-latest.xml delete mode 100644 tests/qemuxmlconfdata/disk-device-removable.xml
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>

From: Akihiko Odaki <akihiko.odaki@daynix.com> usb-bot is supported by all supported QEMU versions; it is present since 1.4.0 and libvirt supports 4.2.0 or later. Add a capability just in case USB_STORAGE_BOT is disabled when building QEMU. Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_capabilities.c | 4 ++++ src/qemu/qemu_capabilities.h | 3 +++ tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_10.0.0_ppc64.xml | 1 + tests/qemucapabilitiesdata/caps_10.0.0_s390x.xml | 1 + tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml | 1 + tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_6.2.0_ppc64.xml | 1 + tests/qemucapabilitiesdata/caps_6.2.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_7.0.0_ppc64.xml | 1 + tests/qemucapabilitiesdata/caps_7.0.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_7.1.0_ppc64.xml | 1 + tests/qemucapabilitiesdata/caps_7.1.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_7.2.0_ppc.xml | 1 + tests/qemucapabilitiesdata/caps_7.2.0_x86_64+hvf.xml | 1 + tests/qemucapabilitiesdata/caps_7.2.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_8.0.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_8.1.0_s390x.xml | 1 + tests/qemucapabilitiesdata/caps_8.1.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_8.2.0_aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_8.2.0_armv7l.xml | 1 + tests/qemucapabilitiesdata/caps_8.2.0_loongarch64.xml | 1 + tests/qemucapabilitiesdata/caps_8.2.0_s390x.xml | 1 + tests/qemucapabilitiesdata/caps_8.2.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_9.1.0_riscv64.xml | 1 + tests/qemucapabilitiesdata/caps_9.1.0_s390x.xml | 1 + tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_9.2.0_aarch64+hvf.xml | 1 + tests/qemucapabilitiesdata/caps_9.2.0_s390x.xml | 1 + tests/qemucapabilitiesdata/caps_9.2.0_x86_64+amdsev.xml | 1 + tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml | 1 + 32 files changed, 37 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 2ba5462bb2..f480060e50 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -736,6 +736,9 @@ VIR_ENUM_IMPL(virQEMUCaps, "bus-floppy", /* QEMU_CAPS_BUS_FLOPPY */ "nvme", /* QEMU_CAPS_DEVICE_NVME */ "nvme-ns", /* QEMU_CAPS_DEVICE_NVME_NS */ + + /* 480 */ + "usb-bot", /* QEMU_CAPS_DEVICE_USB_BOT */ ); @@ -1422,6 +1425,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "virtio-mem-ccw", QEMU_CAPS_DEVICE_VIRTIO_MEM_CCW }, { "nvme", QEMU_CAPS_DEVICE_NVME }, { "nvme-ns", QEMU_CAPS_DEVICE_NVME_NS }, + { "usb-bot", QEMU_CAPS_DEVICE_USB_BOT }, }; diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 3c3d12159f..cef36bf64b 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -718,6 +718,9 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_DEVICE_NVME, /* -device nvme */ QEMU_CAPS_DEVICE_NVME_NS, /* -device nvme-ns */ + /* 480 */ + QEMU_CAPS_DEVICE_USB_BOT, /* -device usb-bot */ + QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml b/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml index 95752eb223..200873b3a2 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml @@ -163,6 +163,7 @@ <flag name='machine.virt.highmem-mmio-size'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>10000000</version> <microcodeVersion>61700285</microcodeVersion> <package>v10.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_ppc64.xml b/tests/qemucapabilitiesdata/caps_10.0.0_ppc64.xml index 12afb64af8..0c57798255 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_ppc64.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_ppc64.xml @@ -171,6 +171,7 @@ <flag name='bus-floppy'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>10000000</version> <microcodeVersion>42900285</microcodeVersion> <package>v10.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_s390x.xml b/tests/qemucapabilitiesdata/caps_10.0.0_s390x.xml index 032b527188..070e673d0b 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_s390x.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_s390x.xml @@ -137,6 +137,7 @@ <flag name='virtio-scsi.iothread-mapping'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>10000000</version> <microcodeVersion>39100285</microcodeVersion> <package>v10.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml index ec79c6d4b1..bbfa007acc 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml @@ -208,6 +208,7 @@ <flag name='bus-floppy'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>10000000</version> <microcodeVersion>43100285</microcodeVersion> <package>v10.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml index 014aca0032..9ac7729d2a 100644 --- a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml @@ -207,6 +207,7 @@ <flag name='bus-floppy'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>10000000</version> <microcodeVersion>43100285</microcodeVersion> <package>v10.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_6.2.0_ppc64.xml b/tests/qemucapabilitiesdata/caps_6.2.0_ppc64.xml index 7f4633eb36..31292f153f 100644 --- a/tests/qemucapabilitiesdata/caps_6.2.0_ppc64.xml +++ b/tests/qemucapabilitiesdata/caps_6.2.0_ppc64.xml @@ -133,6 +133,7 @@ <flag name='bus-floppy'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>6002000</version> <microcodeVersion>42900244</microcodeVersion> <package>v6.2.0</package> diff --git a/tests/qemucapabilitiesdata/caps_6.2.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_6.2.0_x86_64.xml index e894479a61..b64f1bd5cc 100644 --- a/tests/qemucapabilitiesdata/caps_6.2.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_6.2.0_x86_64.xml @@ -175,6 +175,7 @@ <flag name='bus-floppy'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>6002000</version> <microcodeVersion>43100244</microcodeVersion> <package>v6.2.0</package> diff --git a/tests/qemucapabilitiesdata/caps_7.0.0_ppc64.xml b/tests/qemucapabilitiesdata/caps_7.0.0_ppc64.xml index f57e72c3a1..affe9c7ed2 100644 --- a/tests/qemucapabilitiesdata/caps_7.0.0_ppc64.xml +++ b/tests/qemucapabilitiesdata/caps_7.0.0_ppc64.xml @@ -152,6 +152,7 @@ <flag name='bus-floppy'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>7000000</version> <microcodeVersion>42900243</microcodeVersion> <package>v7.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_7.0.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_7.0.0_x86_64.xml index 0556d930d1..0ce03fa0fd 100644 --- a/tests/qemucapabilitiesdata/caps_7.0.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_7.0.0_x86_64.xml @@ -183,6 +183,7 @@ <flag name='bus-floppy'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>7000000</version> <microcodeVersion>43100243</microcodeVersion> <package>v7.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_7.1.0_ppc64.xml b/tests/qemucapabilitiesdata/caps_7.1.0_ppc64.xml index 2f1996189d..beafad1e70 100644 --- a/tests/qemucapabilitiesdata/caps_7.1.0_ppc64.xml +++ b/tests/qemucapabilitiesdata/caps_7.1.0_ppc64.xml @@ -153,6 +153,7 @@ <flag name='bus-floppy'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>7001000</version> <microcodeVersion>42900244</microcodeVersion> <package>v7.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_7.1.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_7.1.0_x86_64.xml index 481634cb68..d989fb6600 100644 --- a/tests/qemucapabilitiesdata/caps_7.1.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_7.1.0_x86_64.xml @@ -188,6 +188,7 @@ <flag name='bus-floppy'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>7001000</version> <microcodeVersion>43100244</microcodeVersion> <package>v7.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_7.2.0_ppc.xml b/tests/qemucapabilitiesdata/caps_7.2.0_ppc.xml index 615dce08af..8dcf050c54 100644 --- a/tests/qemucapabilitiesdata/caps_7.2.0_ppc.xml +++ b/tests/qemucapabilitiesdata/caps_7.2.0_ppc.xml @@ -148,6 +148,7 @@ <flag name='bus-floppy'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>7002000</version> <microcodeVersion>0</microcodeVersion> <package>qemu-7.2.0-6.fc37</package> diff --git a/tests/qemucapabilitiesdata/caps_7.2.0_x86_64+hvf.xml b/tests/qemucapabilitiesdata/caps_7.2.0_x86_64+hvf.xml index 570b3a5758..b5ff75a8b7 100644 --- a/tests/qemucapabilitiesdata/caps_7.2.0_x86_64+hvf.xml +++ b/tests/qemucapabilitiesdata/caps_7.2.0_x86_64+hvf.xml @@ -192,6 +192,7 @@ <flag name='bus-floppy'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>7002000</version> <microcodeVersion>43100245</microcodeVersion> <package>v7.2.0</package> diff --git a/tests/qemucapabilitiesdata/caps_7.2.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_7.2.0_x86_64.xml index 2ee28761ac..a3e4433048 100644 --- a/tests/qemucapabilitiesdata/caps_7.2.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_7.2.0_x86_64.xml @@ -192,6 +192,7 @@ <flag name='bus-floppy'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>7002000</version> <microcodeVersion>43100245</microcodeVersion> <package>v7.2.0</package> diff --git a/tests/qemucapabilitiesdata/caps_8.0.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_8.0.0_x86_64.xml index b09ec334e3..98aec32e63 100644 --- a/tests/qemucapabilitiesdata/caps_8.0.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_8.0.0_x86_64.xml @@ -196,6 +196,7 @@ <flag name='bus-floppy'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>8000000</version> <microcodeVersion>43100244</microcodeVersion> <package>v8.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_8.1.0_s390x.xml b/tests/qemucapabilitiesdata/caps_8.1.0_s390x.xml index 51e27e08c4..acbb7caa20 100644 --- a/tests/qemucapabilitiesdata/caps_8.1.0_s390x.xml +++ b/tests/qemucapabilitiesdata/caps_8.1.0_s390x.xml @@ -113,6 +113,7 @@ <flag name='display-reload'/> <flag name='usb-mtp'/> <flag name='netdev.user'/> + <flag name='usb-bot'/> <version>8001000</version> <microcodeVersion>39100245</microcodeVersion> <package>v8.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_8.1.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_8.1.0_x86_64.xml index 7c4602aa77..482cd33853 100644 --- a/tests/qemucapabilitiesdata/caps_8.1.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_8.1.0_x86_64.xml @@ -198,6 +198,7 @@ <flag name='bus-floppy'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>8001000</version> <microcodeVersion>43100245</microcodeVersion> <package>v8.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_8.2.0_aarch64.xml b/tests/qemucapabilitiesdata/caps_8.2.0_aarch64.xml index e8c6201ec2..95a141c521 100644 --- a/tests/qemucapabilitiesdata/caps_8.2.0_aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_8.2.0_aarch64.xml @@ -162,6 +162,7 @@ <flag name='acpi-erst'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>8002000</version> <microcodeVersion>61700246</microcodeVersion> <package>v8.2.0</package> diff --git a/tests/qemucapabilitiesdata/caps_8.2.0_armv7l.xml b/tests/qemucapabilitiesdata/caps_8.2.0_armv7l.xml index 96d602753d..cb46dd1977 100644 --- a/tests/qemucapabilitiesdata/caps_8.2.0_armv7l.xml +++ b/tests/qemucapabilitiesdata/caps_8.2.0_armv7l.xml @@ -169,6 +169,7 @@ <flag name='acpi-erst'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>8002000</version> <microcodeVersion>0</microcodeVersion> <package>qemu-8.2.0-7.fc39</package> diff --git a/tests/qemucapabilitiesdata/caps_8.2.0_loongarch64.xml b/tests/qemucapabilitiesdata/caps_8.2.0_loongarch64.xml index ba8eaa2fe1..39e36e5aa0 100644 --- a/tests/qemucapabilitiesdata/caps_8.2.0_loongarch64.xml +++ b/tests/qemucapabilitiesdata/caps_8.2.0_loongarch64.xml @@ -152,6 +152,7 @@ <flag name='acpi-erst'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>8002000</version> <microcodeVersion>106300246</microcodeVersion> <package>v8.2.0</package> diff --git a/tests/qemucapabilitiesdata/caps_8.2.0_s390x.xml b/tests/qemucapabilitiesdata/caps_8.2.0_s390x.xml index 37e98624ed..23e3bc827c 100644 --- a/tests/qemucapabilitiesdata/caps_8.2.0_s390x.xml +++ b/tests/qemucapabilitiesdata/caps_8.2.0_s390x.xml @@ -116,6 +116,7 @@ <flag name='netdev.user'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>8002000</version> <microcodeVersion>39100246</microcodeVersion> <package>v8.2.0</package> diff --git a/tests/qemucapabilitiesdata/caps_8.2.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_8.2.0_x86_64.xml index 93ab4bd2b9..202246c0b2 100644 --- a/tests/qemucapabilitiesdata/caps_8.2.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_8.2.0_x86_64.xml @@ -201,6 +201,7 @@ <flag name='bus-floppy'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>8002000</version> <microcodeVersion>43100246</microcodeVersion> <package>v8.2.0</package> diff --git a/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml index 009d14a4a8..bd3d289b76 100644 --- a/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml @@ -203,6 +203,7 @@ <flag name='bus-floppy'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>9000000</version> <microcodeVersion>43100245</microcodeVersion> <package>v9.0.0</package> diff --git a/tests/qemucapabilitiesdata/caps_9.1.0_riscv64.xml b/tests/qemucapabilitiesdata/caps_9.1.0_riscv64.xml index 5833e4b269..0f7ce7ce1b 100644 --- a/tests/qemucapabilitiesdata/caps_9.1.0_riscv64.xml +++ b/tests/qemucapabilitiesdata/caps_9.1.0_riscv64.xml @@ -162,6 +162,7 @@ <flag name='machine.virt.aia'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>9001000</version> <microcodeVersion>0</microcodeVersion> <package>v9.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_9.1.0_s390x.xml b/tests/qemucapabilitiesdata/caps_9.1.0_s390x.xml index c2f2377b8c..59e7207ed1 100644 --- a/tests/qemucapabilitiesdata/caps_9.1.0_s390x.xml +++ b/tests/qemucapabilitiesdata/caps_9.1.0_s390x.xml @@ -127,6 +127,7 @@ <flag name='migrate-incoming.exit-on-error'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>9001000</version> <microcodeVersion>39100246</microcodeVersion> <package>v9.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml index e6ef686d3d..0cf6f7d1de 100644 --- a/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml @@ -202,6 +202,7 @@ <flag name='bus-floppy'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>9001000</version> <microcodeVersion>43100246</microcodeVersion> <package>v9.1.0</package> diff --git a/tests/qemucapabilitiesdata/caps_9.2.0_aarch64+hvf.xml b/tests/qemucapabilitiesdata/caps_9.2.0_aarch64+hvf.xml index 179958d331..aa964b4885 100644 --- a/tests/qemucapabilitiesdata/caps_9.2.0_aarch64+hvf.xml +++ b/tests/qemucapabilitiesdata/caps_9.2.0_aarch64+hvf.xml @@ -135,6 +135,7 @@ <flag name='migrate-incoming.exit-on-error'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>9002002</version> <microcodeVersion>61700247</microcodeVersion> <package></package> diff --git a/tests/qemucapabilitiesdata/caps_9.2.0_s390x.xml b/tests/qemucapabilitiesdata/caps_9.2.0_s390x.xml index 5bc535a4d1..27a9b4c924 100644 --- a/tests/qemucapabilitiesdata/caps_9.2.0_s390x.xml +++ b/tests/qemucapabilitiesdata/caps_9.2.0_s390x.xml @@ -130,6 +130,7 @@ <flag name='migrate-incoming.exit-on-error'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>9002000</version> <microcodeVersion>39100247</microcodeVersion> <package>v9.2.0</package> diff --git a/tests/qemucapabilitiesdata/caps_9.2.0_x86_64+amdsev.xml b/tests/qemucapabilitiesdata/caps_9.2.0_x86_64+amdsev.xml index bd11b702e4..5c1cea6c8f 100644 --- a/tests/qemucapabilitiesdata/caps_9.2.0_x86_64+amdsev.xml +++ b/tests/qemucapabilitiesdata/caps_9.2.0_x86_64+amdsev.xml @@ -206,6 +206,7 @@ <flag name='bus-floppy'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>9002000</version> <microcodeVersion>43100247</microcodeVersion> <package>v9.2.0</package> diff --git a/tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml index 2db0672110..739166be31 100644 --- a/tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml @@ -204,6 +204,7 @@ <flag name='bus-floppy'/> <flag name='nvme'/> <flag name='nvme-ns'/> + <flag name='usb-bot'/> <version>9002000</version> <microcodeVersion>43100247</microcodeVersion> <package>v9.2.0</package> -- 2.49.0

On Mon, Jun 23, 2025 at 21:59:11 +0200, Peter Krempa wrote:
From: Akihiko Odaki <akihiko.odaki@daynix.com>
usb-bot is supported by all supported QEMU versions; it is present since 1.4.0 and libvirt supports 4.2.0 or later.
Add a capability just in case USB_STORAGE_BOT is disabled when building QEMU.
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_capabilities.c | 4 ++++ src/qemu/qemu_capabilities.h | 3 +++ tests/qemucapabilitiesdata/caps_10.0.0_aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_10.0.0_ppc64.xml | 1 + tests/qemucapabilitiesdata/caps_10.0.0_s390x.xml | 1 + tests/qemucapabilitiesdata/caps_10.0.0_x86_64+amdsev.xml | 1 + tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_6.2.0_ppc64.xml | 1 + tests/qemucapabilitiesdata/caps_6.2.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_7.0.0_ppc64.xml | 1 + tests/qemucapabilitiesdata/caps_7.0.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_7.1.0_ppc64.xml | 1 + tests/qemucapabilitiesdata/caps_7.1.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_7.2.0_ppc.xml | 1 + tests/qemucapabilitiesdata/caps_7.2.0_x86_64+hvf.xml | 1 + tests/qemucapabilitiesdata/caps_7.2.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_8.0.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_8.1.0_s390x.xml | 1 + tests/qemucapabilitiesdata/caps_8.1.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_8.2.0_aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_8.2.0_armv7l.xml | 1 + tests/qemucapabilitiesdata/caps_8.2.0_loongarch64.xml | 1 + tests/qemucapabilitiesdata/caps_8.2.0_s390x.xml | 1 + tests/qemucapabilitiesdata/caps_8.2.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_9.0.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_9.1.0_riscv64.xml | 1 + tests/qemucapabilitiesdata/caps_9.1.0_s390x.xml | 1 + tests/qemucapabilitiesdata/caps_9.1.0_x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_9.2.0_aarch64+hvf.xml | 1 + tests/qemucapabilitiesdata/caps_9.2.0_s390x.xml | 1 + tests/qemucapabilitiesdata/caps_9.2.0_x86_64+amdsev.xml | 1 + tests/qemucapabilitiesdata/caps_9.2.0_x86_64.xml | 1 + 32 files changed, 37 insertions(+)
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>

From: Peter Krempa <pkrempa@redhat.com> The QEMU_CAPS_DEVICE_USB_BOT device can be compiled out but realistically it makes no sense to do it thus also makes no sense to have another variant of input data for it. Add another invocation of "disk-usb-device" clearing QEMU_CAPS_DEVICE_USB_BOT to show the fallback code paths. Also add "ABI_UPDATE" version for the two cases above as the ABI of usb-bot cdrom is not migration-compatible and we'll be wanting to update to the fixed configuration. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- ...est.QEMU_CAPS_DEVICE_USB_BOT-disabled.args | 59 +++++++++ ...test.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml | 107 +++++++++++++++ ...ate.QEMU_CAPS_DEVICE_USB_BOT-disabled.args | 59 +++++++++ ...date.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml | 125 ++++++++++++++++++ ...k-usb-device.x86_64-latest.abi-update.args | 59 +++++++++ ...sk-usb-device.x86_64-latest.abi-update.xml | 125 ++++++++++++++++++ tests/qemuxmlconftest.c | 12 ++ 7 files changed, 546 insertions(+) create mode 100644 tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.QEMU_CAPS_DEVICE_USB_BOT-disabled.args create mode 100644 tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml create mode 100644 tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.QEMU_CAPS_DEVICE_USB_BOT-disabled.args create mode 100644 tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml create mode 100644 tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.args create mode 100644 tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.xml diff --git a/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.QEMU_CAPS_DEVICE_USB_BOT-disabled.args b/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.QEMU_CAPS_DEVICE_USB_BOT-disabled.args new file mode 100644 index 0000000000..079dfe5d99 --- /dev/null +++ b/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.QEMU_CAPS_DEVICE_USB_BOT-disabled.args @@ -0,0 +1,59 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ +/usr/bin/qemu-system-x86_64 \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ +-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \ +-accel tcg \ +-cpu qemu64 \ +-m size=219136k \ +-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-boot strict=on \ +-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \ +-device '{"driver":"usb-hub","id":"hub0","bus":"usb.0","port":"1"}' \ +-device '{"driver":"usb-hub","id":"hub1","bus":"usb.0","port":"2"}' \ +-blockdev '{"driver":"file","filename":"/tmp/img1","node-name":"libvirt-12-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.1","drive":"libvirt-12-storage","id":"usb-disk0","bootindex":1,"removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img2","node-name":"libvirt-11-storage","read-only":true}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.2","drive":"libvirt-11-storage","id":"usb-disk1","removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img3","node-name":"libvirt-10-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.3","drive":"libvirt-10-storage","id":"usb-disk2","removable":false,"serial":"testserial1"}' \ +-blockdev '{"driver":"file","filename":"/tmp/img4","node-name":"libvirt-9-storage","read-only":true}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.4","drive":"libvirt-9-storage","id":"usb-disk3","removable":false,"serial":"testserial2"}' \ +-blockdev '{"driver":"file","filename":"/tmp/img5","node-name":"libvirt-8-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.5","drive":"libvirt-8-storage","id":"ua-test1","removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img6","node-name":"libvirt-7-storage","read-only":true}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.6","drive":"libvirt-7-storage","id":"ua-test2","removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img7","node-name":"libvirt-6-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.7","drive":"libvirt-6-storage","id":"ua-test3","removable":false,"serial":"testserial3"}' \ +-blockdev '{"driver":"file","filename":"/tmp/img8","node-name":"libvirt-5-storage","read-only":true}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.8","drive":"libvirt-5-storage","id":"ua-test4","removable":false,"serial":"testserial4"}' \ +-blockdev '{"driver":"file","filename":"/tmp/img9","node-name":"libvirt-4-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"2.1","drive":"libvirt-4-storage","id":"usb-disk8","removable":true}' \ +-blockdev '{"driver":"file","filename":"/tmp/imga","node-name":"libvirt-3-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"2.2","drive":"libvirt-3-storage","id":"usb-disk9","removable":true,"serial":"testserial5"}' \ +-blockdev '{"driver":"file","filename":"/tmp/imgb","node-name":"libvirt-2-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"2.3","drive":"libvirt-2-storage","id":"ua-test5","removable":true}' \ +-blockdev '{"driver":"file","filename":"/tmp/imgc","node-name":"libvirt-1-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"2.4","drive":"libvirt-1-storage","id":"ua-test6","removable":true,"serial":"testserial6"}' \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x2"}' \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml b/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml new file mode 100644 index 0000000000..8b78f77e63 --- /dev/null +++ b/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml @@ -0,0 +1,107 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219136</memory> + <currentMemory unit='KiB'>219136</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img1'/> + <target dev='sda' bus='usb'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img2'/> + <target dev='sdb' bus='usb'/> + <readonly/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img3'/> + <target dev='sdc' bus='usb'/> + <serial>testserial1</serial> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img4'/> + <target dev='sdd' bus='usb'/> + <readonly/> + <serial>testserial2</serial> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img5'/> + <target dev='sde' bus='usb'/> + <alias name='ua-test1'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img6'/> + <target dev='sdf' bus='usb'/> + <readonly/> + <alias name='ua-test2'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img7'/> + <target dev='sdg' bus='usb'/> + <serial>testserial3</serial> + <alias name='ua-test3'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img8'/> + <target dev='sdh' bus='usb'/> + <readonly/> + <serial>testserial4</serial> + <alias name='ua-test4'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img9'/> + <target dev='sdi' bus='usb' removable='on'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/imga'/> + <target dev='sdj' bus='usb' removable='on'/> + <serial>testserial5</serial> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/imgb'/> + <target dev='sdk' bus='usb' removable='on'/> + <alias name='ua-test5'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/imgc'/> + <target dev='sdl' bus='usb' removable='on'/> + <serial>testserial6</serial> + <alias name='ua-test6'/> + </disk> + <controller type='usb' index='0' model='piix3-uhci'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.QEMU_CAPS_DEVICE_USB_BOT-disabled.args b/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.QEMU_CAPS_DEVICE_USB_BOT-disabled.args new file mode 100644 index 0000000000..079dfe5d99 --- /dev/null +++ b/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.QEMU_CAPS_DEVICE_USB_BOT-disabled.args @@ -0,0 +1,59 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ +/usr/bin/qemu-system-x86_64 \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ +-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \ +-accel tcg \ +-cpu qemu64 \ +-m size=219136k \ +-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-boot strict=on \ +-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \ +-device '{"driver":"usb-hub","id":"hub0","bus":"usb.0","port":"1"}' \ +-device '{"driver":"usb-hub","id":"hub1","bus":"usb.0","port":"2"}' \ +-blockdev '{"driver":"file","filename":"/tmp/img1","node-name":"libvirt-12-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.1","drive":"libvirt-12-storage","id":"usb-disk0","bootindex":1,"removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img2","node-name":"libvirt-11-storage","read-only":true}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.2","drive":"libvirt-11-storage","id":"usb-disk1","removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img3","node-name":"libvirt-10-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.3","drive":"libvirt-10-storage","id":"usb-disk2","removable":false,"serial":"testserial1"}' \ +-blockdev '{"driver":"file","filename":"/tmp/img4","node-name":"libvirt-9-storage","read-only":true}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.4","drive":"libvirt-9-storage","id":"usb-disk3","removable":false,"serial":"testserial2"}' \ +-blockdev '{"driver":"file","filename":"/tmp/img5","node-name":"libvirt-8-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.5","drive":"libvirt-8-storage","id":"ua-test1","removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img6","node-name":"libvirt-7-storage","read-only":true}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.6","drive":"libvirt-7-storage","id":"ua-test2","removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img7","node-name":"libvirt-6-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.7","drive":"libvirt-6-storage","id":"ua-test3","removable":false,"serial":"testserial3"}' \ +-blockdev '{"driver":"file","filename":"/tmp/img8","node-name":"libvirt-5-storage","read-only":true}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.8","drive":"libvirt-5-storage","id":"ua-test4","removable":false,"serial":"testserial4"}' \ +-blockdev '{"driver":"file","filename":"/tmp/img9","node-name":"libvirt-4-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"2.1","drive":"libvirt-4-storage","id":"usb-disk8","removable":true}' \ +-blockdev '{"driver":"file","filename":"/tmp/imga","node-name":"libvirt-3-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"2.2","drive":"libvirt-3-storage","id":"usb-disk9","removable":true,"serial":"testserial5"}' \ +-blockdev '{"driver":"file","filename":"/tmp/imgb","node-name":"libvirt-2-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"2.3","drive":"libvirt-2-storage","id":"ua-test5","removable":true}' \ +-blockdev '{"driver":"file","filename":"/tmp/imgc","node-name":"libvirt-1-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"2.4","drive":"libvirt-1-storage","id":"ua-test6","removable":true,"serial":"testserial6"}' \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x2"}' \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml b/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml new file mode 100644 index 0000000000..732230e722 --- /dev/null +++ b/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml @@ -0,0 +1,125 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219136</memory> + <currentMemory unit='KiB'>219136</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img1'/> + <target dev='sda' bus='usb'/> + <address type='usb' bus='0' port='1.1'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img2'/> + <target dev='sdb' bus='usb'/> + <readonly/> + <address type='usb' bus='0' port='1.2'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img3'/> + <target dev='sdc' bus='usb'/> + <serial>testserial1</serial> + <address type='usb' bus='0' port='1.3'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img4'/> + <target dev='sdd' bus='usb'/> + <readonly/> + <serial>testserial2</serial> + <address type='usb' bus='0' port='1.4'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img5'/> + <target dev='sde' bus='usb'/> + <alias name='ua-test1'/> + <address type='usb' bus='0' port='1.5'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img6'/> + <target dev='sdf' bus='usb'/> + <readonly/> + <alias name='ua-test2'/> + <address type='usb' bus='0' port='1.6'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img7'/> + <target dev='sdg' bus='usb'/> + <serial>testserial3</serial> + <alias name='ua-test3'/> + <address type='usb' bus='0' port='1.7'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img8'/> + <target dev='sdh' bus='usb'/> + <readonly/> + <serial>testserial4</serial> + <alias name='ua-test4'/> + <address type='usb' bus='0' port='1.8'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img9'/> + <target dev='sdi' bus='usb' removable='on'/> + <address type='usb' bus='0' port='2.1'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/imga'/> + <target dev='sdj' bus='usb' removable='on'/> + <serial>testserial5</serial> + <address type='usb' bus='0' port='2.2'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/imgb'/> + <target dev='sdk' bus='usb' removable='on'/> + <alias name='ua-test5'/> + <address type='usb' bus='0' port='2.3'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/imgc'/> + <target dev='sdl' bus='usb' removable='on'/> + <serial>testserial6</serial> + <alias name='ua-test6'/> + <address type='usb' bus='0' port='2.4'/> + </disk> + <controller type='usb' index='0' model='piix3-uhci'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <hub type='usb'> + <address type='usb' bus='0' port='1'/> + </hub> + <hub type='usb'> + <address type='usb' bus='0' port='2'/> + </hub> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.args b/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.args new file mode 100644 index 0000000000..079dfe5d99 --- /dev/null +++ b/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.args @@ -0,0 +1,59 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ +/usr/bin/qemu-system-x86_64 \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ +-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \ +-accel tcg \ +-cpu qemu64 \ +-m size=219136k \ +-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-boot strict=on \ +-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \ +-device '{"driver":"usb-hub","id":"hub0","bus":"usb.0","port":"1"}' \ +-device '{"driver":"usb-hub","id":"hub1","bus":"usb.0","port":"2"}' \ +-blockdev '{"driver":"file","filename":"/tmp/img1","node-name":"libvirt-12-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.1","drive":"libvirt-12-storage","id":"usb-disk0","bootindex":1,"removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img2","node-name":"libvirt-11-storage","read-only":true}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.2","drive":"libvirt-11-storage","id":"usb-disk1","removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img3","node-name":"libvirt-10-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.3","drive":"libvirt-10-storage","id":"usb-disk2","removable":false,"serial":"testserial1"}' \ +-blockdev '{"driver":"file","filename":"/tmp/img4","node-name":"libvirt-9-storage","read-only":true}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.4","drive":"libvirt-9-storage","id":"usb-disk3","removable":false,"serial":"testserial2"}' \ +-blockdev '{"driver":"file","filename":"/tmp/img5","node-name":"libvirt-8-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.5","drive":"libvirt-8-storage","id":"ua-test1","removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img6","node-name":"libvirt-7-storage","read-only":true}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.6","drive":"libvirt-7-storage","id":"ua-test2","removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img7","node-name":"libvirt-6-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.7","drive":"libvirt-6-storage","id":"ua-test3","removable":false,"serial":"testserial3"}' \ +-blockdev '{"driver":"file","filename":"/tmp/img8","node-name":"libvirt-5-storage","read-only":true}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.8","drive":"libvirt-5-storage","id":"ua-test4","removable":false,"serial":"testserial4"}' \ +-blockdev '{"driver":"file","filename":"/tmp/img9","node-name":"libvirt-4-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"2.1","drive":"libvirt-4-storage","id":"usb-disk8","removable":true}' \ +-blockdev '{"driver":"file","filename":"/tmp/imga","node-name":"libvirt-3-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"2.2","drive":"libvirt-3-storage","id":"usb-disk9","removable":true,"serial":"testserial5"}' \ +-blockdev '{"driver":"file","filename":"/tmp/imgb","node-name":"libvirt-2-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"2.3","drive":"libvirt-2-storage","id":"ua-test5","removable":true}' \ +-blockdev '{"driver":"file","filename":"/tmp/imgc","node-name":"libvirt-1-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"2.4","drive":"libvirt-1-storage","id":"ua-test6","removable":true,"serial":"testserial6"}' \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x2"}' \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.xml b/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.xml new file mode 100644 index 0000000000..732230e722 --- /dev/null +++ b/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.xml @@ -0,0 +1,125 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219136</memory> + <currentMemory unit='KiB'>219136</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img1'/> + <target dev='sda' bus='usb'/> + <address type='usb' bus='0' port='1.1'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img2'/> + <target dev='sdb' bus='usb'/> + <readonly/> + <address type='usb' bus='0' port='1.2'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img3'/> + <target dev='sdc' bus='usb'/> + <serial>testserial1</serial> + <address type='usb' bus='0' port='1.3'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img4'/> + <target dev='sdd' bus='usb'/> + <readonly/> + <serial>testserial2</serial> + <address type='usb' bus='0' port='1.4'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img5'/> + <target dev='sde' bus='usb'/> + <alias name='ua-test1'/> + <address type='usb' bus='0' port='1.5'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img6'/> + <target dev='sdf' bus='usb'/> + <readonly/> + <alias name='ua-test2'/> + <address type='usb' bus='0' port='1.6'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img7'/> + <target dev='sdg' bus='usb'/> + <serial>testserial3</serial> + <alias name='ua-test3'/> + <address type='usb' bus='0' port='1.7'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img8'/> + <target dev='sdh' bus='usb'/> + <readonly/> + <serial>testserial4</serial> + <alias name='ua-test4'/> + <address type='usb' bus='0' port='1.8'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img9'/> + <target dev='sdi' bus='usb' removable='on'/> + <address type='usb' bus='0' port='2.1'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/imga'/> + <target dev='sdj' bus='usb' removable='on'/> + <serial>testserial5</serial> + <address type='usb' bus='0' port='2.2'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/imgb'/> + <target dev='sdk' bus='usb' removable='on'/> + <alias name='ua-test5'/> + <address type='usb' bus='0' port='2.3'/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/imgc'/> + <target dev='sdl' bus='usb' removable='on'/> + <serial>testserial6</serial> + <alias name='ua-test6'/> + <address type='usb' bus='0' port='2.4'/> + </disk> + <controller type='usb' index='0' model='piix3-uhci'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <hub type='usb'> + <address type='usb' bus='0' port='1'/> + </hub> + <hub type='usb'> + <address type='usb' bus='0' port='2'/> + </hub> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index c7b6df5a6a..f2fc09d9fd 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1609,6 +1609,18 @@ mymain(void) DO_TEST_CAPS_LATEST_PARSE_ERROR("disk-device-lun-type-invalid"); DO_TEST_CAPS_LATEST_PARSE_ERROR("disk-attaching-partition-nosupport"); DO_TEST_CAPS_LATEST("disk-usb-device"); + DO_TEST_CAPS_ARCH_LATEST_ABI_UPDATE("disk-usb-device", "x86_64"); + DO_TEST_FULL("disk-usb-device", ".x86_64-latest.QEMU_CAPS_DEVICE_USB_BOT-disabled", + ARG_CAPS_ARCH, "x86_64", + ARG_CAPS_VER, "latest", + ARG_QEMU_CAPS_DEL, QEMU_CAPS_DEVICE_USB_BOT, QEMU_CAPS_LAST, + ARG_END); + DO_TEST_FULL("disk-usb-device", ".x86_64-latest.abi-update.QEMU_CAPS_DEVICE_USB_BOT-disabled", + ARG_CAPS_ARCH, "x86_64", + ARG_CAPS_VER, "latest", + ARG_PARSEFLAGS, VIR_DOMAIN_DEF_PARSE_ABI_UPDATE, + ARG_QEMU_CAPS_DEL, QEMU_CAPS_DEVICE_USB_BOT, QEMU_CAPS_LAST, + ARG_END); DO_TEST_CAPS_LATEST_PARSE_ERROR("disk-usb-pci"); DO_TEST_CAPS_LATEST("disk-scsi"); DO_TEST_CAPS_LATEST("disk-scsi-device-auto"); -- 2.49.0

On Mon, Jun 23, 2025 at 21:59:12 +0200, Peter Krempa wrote:
From: Peter Krempa <pkrempa@redhat.com>
The QEMU_CAPS_DEVICE_USB_BOT device can be compiled out but realistically it makes no sense to do it thus also makes no sense to have another variant of input data for it.
Add another invocation of "disk-usb-device" clearing QEMU_CAPS_DEVICE_USB_BOT to show the fallback code paths.
Also add "ABI_UPDATE" version for the two cases above as the ABI of usb-bot cdrom is not migration-compatible and we'll be wanting to update to the fixed configuration.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- ...est.QEMU_CAPS_DEVICE_USB_BOT-disabled.args | 59 +++++++++ ...test.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml | 107 +++++++++++++++ ...ate.QEMU_CAPS_DEVICE_USB_BOT-disabled.args | 59 +++++++++ ...date.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml | 125 ++++++++++++++++++ ...k-usb-device.x86_64-latest.abi-update.args | 59 +++++++++ ...sk-usb-device.x86_64-latest.abi-update.xml | 125 ++++++++++++++++++ tests/qemuxmlconftest.c | 12 ++ 7 files changed, 546 insertions(+) create mode 100644 tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.QEMU_CAPS_DEVICE_USB_BOT-disabled.args create mode 100644 tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml create mode 100644 tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.QEMU_CAPS_DEVICE_USB_BOT-disabled.args create mode 100644 tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml create mode 100644 tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.args create mode 100644 tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.xml
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>

From: Peter Krempa <pkrempa@redhat.com> Historically libvirt specified 'usb-storage' as driver for USB disks. This though combined with '-blockdev' doesn't properly configure the device to look like CDROM for <disk type='cdrom'>. 'usb-bot' acts like a controler and allows explicitly connecting a -device to it. In qemu the devices share implementation so they are effectively identical and can be used interchangably. There is though a slight difference in how the storage device itself (the SCSI bit) looks when CDROM as they were not declared as cdrom before. As this is effectively a bugfix we'll be fixing the behaviour for the default configuration. The possibility to explicitly set the model is added as a possibility for working around possible problems if they'd appear. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- docs/formatdomain.rst | 23 +++++-- src/conf/domain_conf.c | 2 + src/conf/domain_conf.h | 3 + src/conf/schemas/domaincommon.rng | 2 + src/qemu/qemu_domain_address.c | 2 + .../disk-usb-device-model.x86_64-latest.args | 46 +++++++++++++ .../disk-usb-device-model.x86_64-latest.xml | 64 +++++++++++++++++++ .../qemuxmlconfdata/disk-usb-device-model.xml | 46 +++++++++++++ tests/qemuxmlconftest.c | 1 + 9 files changed, 185 insertions(+), 4 deletions(-) create mode 100644 tests/qemuxmlconfdata/disk-usb-device-model.x86_64-latest.args create mode 100644 tests/qemuxmlconfdata/disk-usb-device-model.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/disk-usb-device-model.xml diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index ae054a52b3..e4ebf061c7 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -2862,10 +2862,25 @@ paravirtualized driver is specified via the ``disk`` element. ``model`` Indicates the emulated device model of the disk. Typically this is - indicated solely by the ``bus`` property but for ``bus`` "virtio" the - model can be specified further with "virtio", "virtio-transitional" or - "virtio-non-transitional". See `virtio device models`_ - for more details. :since:`Since 5.2.0` + indicated solely by the ``bus`` property. + + For ``bus`` "virtio" the model can be specified further with "virtio", + "virtio-transitional" or "virtio-non-transitional". See `virtio device + models`_ for more details. :since:`Since 5.2.0` + + For ``bus`` "usb" the model can be specified further with ``usb-storage`` + or ``usb-bot``. There is no difference between the two models for + ``<disk type='disk'``. However with ``usb-bot`` a device configured as + ``<disk type='cdrom'>`` is properly exposed as a cdrom device inside the + guest OS. Unfortunately this configuration is not ABI compatible and thus + it can't be interchanged. + + The QEMU hypervisor driver will pick ``usb-bot`` for cold starts or + hotplug for cdrom devices to properly configure the devices. This is + not compatible for migration to older versions of libvirt and explicit + configuration needs to be used. + :since:`Since 11.5.0`; relevant only for ``QEMU`` hypervisor. + ``rawio`` Indicates whether the disk needs rawio capability. Valid settings are "yes" or "no" (default is "no"). If any one disk in a domain has diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 1a6c8afb1d..2882a7746b 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1399,6 +1399,8 @@ VIR_ENUM_IMPL(virDomainDiskModel, "virtio", "virtio-transitional", "virtio-non-transitional", + "usb-storage", + "usb-bot", ); VIR_ENUM_IMPL(virDomainDiskMirrorState, diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 3d380073cf..73e8a2fb99 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -439,6 +439,9 @@ typedef enum { VIR_DOMAIN_DISK_MODEL_VIRTIO_TRANSITIONAL, VIR_DOMAIN_DISK_MODEL_VIRTIO_NON_TRANSITIONAL, + VIR_DOMAIN_DISK_MODEL_USB_STORAGE, + VIR_DOMAIN_DISK_MODEL_USB_BOT, + VIR_DOMAIN_DISK_MODEL_LAST } virDomainDiskModel; diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index b1fe51f519..a80005562a 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -1766,6 +1766,8 @@ <value>virtio</value> <value>virtio-transitional</value> <value>virtio-non-transitional</value> + <value>usb-storage</value> + <value>usb-bot</value> </choice> </attribute> </optional> diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index bb86cfa0c3..3a23f70d39 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -729,6 +729,8 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDef *dev, case VIR_DOMAIN_DISK_MODEL_DEFAULT: return virtioFlags; case VIR_DOMAIN_DISK_MODEL_LAST: + case VIR_DOMAIN_DISK_MODEL_USB_STORAGE: + case VIR_DOMAIN_DISK_MODEL_USB_BOT: break; } return 0; diff --git a/tests/qemuxmlconfdata/disk-usb-device-model.x86_64-latest.args b/tests/qemuxmlconfdata/disk-usb-device-model.x86_64-latest.args new file mode 100644 index 0000000000..6d31319a49 --- /dev/null +++ b/tests/qemuxmlconfdata/disk-usb-device-model.x86_64-latest.args @@ -0,0 +1,46 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ +/usr/bin/qemu-system-x86_64 \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ +-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \ +-accel tcg \ +-cpu qemu64 \ +-m size=219136k \ +-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-boot strict=on \ +-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \ +-device '{"driver":"usb-hub","id":"hub0","bus":"usb.0","port":"1"}' \ +-blockdev '{"driver":"file","filename":"/tmp/img1","node-name":"libvirt-6-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"2","drive":"libvirt-6-storage","id":"usb-disk0","bootindex":1,"removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img2","node-name":"libvirt-5-storage","read-only":true}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.1","drive":"libvirt-5-storage","id":"usb-disk1","removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img3","node-name":"libvirt-4-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.2","drive":"libvirt-4-storage","id":"usb-disk2","removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img4","node-name":"libvirt-3-storage","read-only":true}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.3","drive":"libvirt-3-storage","id":"usb-disk3","removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img5","node-name":"libvirt-2-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.4","drive":"libvirt-2-storage","id":"usb-disk4","removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img6","node-name":"libvirt-1-storage","read-only":true}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.5","drive":"libvirt-1-storage","id":"usb-disk5","removable":false}' \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x2"}' \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxmlconfdata/disk-usb-device-model.x86_64-latest.xml b/tests/qemuxmlconfdata/disk-usb-device-model.x86_64-latest.xml new file mode 100644 index 0000000000..351257bc4a --- /dev/null +++ b/tests/qemuxmlconfdata/disk-usb-device-model.x86_64-latest.xml @@ -0,0 +1,64 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219136</memory> + <currentMemory unit='KiB'>219136</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='file' device='disk' model='usb-storage'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img1'/> + <target dev='sda' bus='usb'/> + </disk> + <disk type='file' device='cdrom' model='usb-storage'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img2'/> + <target dev='sdb' bus='usb'/> + <readonly/> + </disk> + <disk type='file' device='disk' model='usb-bot'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img3'/> + <target dev='sdc' bus='usb'/> + </disk> + <disk type='file' device='cdrom' model='usb-bot'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img4'/> + <target dev='sdd' bus='usb'/> + <readonly/> + </disk> + <disk type='file' device='disk'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img5'/> + <target dev='sde' bus='usb'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/tmp/img6'/> + <target dev='sdf' bus='usb'/> + <readonly/> + </disk> + <controller type='usb' index='0' model='piix3-uhci'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxmlconfdata/disk-usb-device-model.xml b/tests/qemuxmlconfdata/disk-usb-device-model.xml new file mode 100644 index 0000000000..47c8b698e9 --- /dev/null +++ b/tests/qemuxmlconfdata/disk-usb-device-model.xml @@ -0,0 +1,46 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219136</memory> + <currentMemory unit='KiB'>219136</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='file' device='disk' model='usb-storage'> + <source file='/tmp/img1'/> + <target dev='sda' bus='usb'/> + </disk> + <disk type='file' device='cdrom' model='usb-storage'> + <source file='/tmp/img2'/> + <target dev='sdb' bus='usb'/> + <readonly/> + </disk> + <disk type='file' device='disk' model='usb-bot'> + <source file='/tmp/img3'/> + <target dev='sdc' bus='usb'/> + </disk> + <disk type='file' device='cdrom' model='usb-bot'> + <source file='/tmp/img4'/> + <target dev='sdd' bus='usb'/> + <readonly/> + </disk> + <disk type='file' device='disk'> + <source file='/tmp/img5'/> + <target dev='sde' bus='usb'/> + </disk> + <disk type='file' device='cdrom'> + <source file='/tmp/img6'/> + <target dev='sdf' bus='usb'/> + <readonly/> + </disk> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index f2fc09d9fd..858dde6ae8 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1621,6 +1621,7 @@ mymain(void) ARG_PARSEFLAGS, VIR_DOMAIN_DEF_PARSE_ABI_UPDATE, ARG_QEMU_CAPS_DEL, QEMU_CAPS_DEVICE_USB_BOT, QEMU_CAPS_LAST, ARG_END); + DO_TEST_CAPS_LATEST("disk-usb-device-model"); DO_TEST_CAPS_LATEST_PARSE_ERROR("disk-usb-pci"); DO_TEST_CAPS_LATEST("disk-scsi"); DO_TEST_CAPS_LATEST("disk-scsi-device-auto"); -- 2.49.0

On Mon, Jun 23, 2025 at 21:59:13 +0200, Peter Krempa wrote:
From: Peter Krempa <pkrempa@redhat.com>
Historically libvirt specified 'usb-storage' as driver for USB disks. This though combined with '-blockdev' doesn't properly configure the device to look like CDROM for <disk type='cdrom'>.
'usb-bot' acts like a controler and allows explicitly connecting a -device to it.
In qemu the devices share implementation so they are effectively identical and can be used interchangably. There is though a slight difference in how the storage device itself (the SCSI bit) looks when CDROM as they were not declared as cdrom before.
Looks like some words were dropped from the last sentence above.
As this is effectively a bugfix we'll be fixing the behaviour for the default configuration. The possibility to explicitly set the model is added as a possibility for working around possible problems if they'd appear.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- docs/formatdomain.rst | 23 +++++-- src/conf/domain_conf.c | 2 + src/conf/domain_conf.h | 3 + src/conf/schemas/domaincommon.rng | 2 + src/qemu/qemu_domain_address.c | 2 + .../disk-usb-device-model.x86_64-latest.args | 46 +++++++++++++ .../disk-usb-device-model.x86_64-latest.xml | 64 +++++++++++++++++++ .../qemuxmlconfdata/disk-usb-device-model.xml | 46 +++++++++++++ tests/qemuxmlconftest.c | 1 + 9 files changed, 185 insertions(+), 4 deletions(-) create mode 100644 tests/qemuxmlconfdata/disk-usb-device-model.x86_64-latest.args create mode 100644 tests/qemuxmlconfdata/disk-usb-device-model.x86_64-latest.xml create mode 100644 tests/qemuxmlconfdata/disk-usb-device-model.xml
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index ae054a52b3..e4ebf061c7 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -2862,10 +2862,25 @@ paravirtualized driver is specified via the ``disk`` element.
``model`` Indicates the emulated device model of the disk. Typically this is - indicated solely by the ``bus`` property but for ``bus`` "virtio" the - model can be specified further with "virtio", "virtio-transitional" or - "virtio-non-transitional". See `virtio device models`_ - for more details. :since:`Since 5.2.0` + indicated solely by the ``bus`` property. + + For ``bus`` "virtio" the model can be specified further with "virtio", + "virtio-transitional" or "virtio-non-transitional". See `virtio device + models`_ for more details. :since:`Since 5.2.0` + + For ``bus`` "usb" the model can be specified further with ``usb-storage`` + or ``usb-bot``. There is no difference between the two models for + ``<disk type='disk'``. However with ``usb-bot`` a device configured as
Missing > in the disk element.
+ ``<disk type='cdrom'>`` is properly exposed as a cdrom device inside the + guest OS. Unfortunately this configuration is not ABI compatible and thus + it can't be interchanged.
This is not ABI compatible with usb-storage model, right? I suggest being explicit about it.
+ + The QEMU hypervisor driver will pick ``usb-bot`` for cold starts or + hotplug for cdrom devices to properly configure the devices. This is + not compatible for migration to older versions of libvirt and explicit + configuration needs to be used.
So are you saying starting an existing domain with usb cdrom after upgrading libvirt will cause issues during migration to an older libvirt? I don't think we can do this. We should rather pick usb-storage (which is the case now as I understood from the description) unless usb-bot is set explicitly in the XML.
+ :since:`Since 11.5.0`; relevant only for ``QEMU`` hypervisor. + ``rawio`` Indicates whether the disk needs rawio capability. Valid settings are "yes" or "no" (default is "no"). If any one disk in a domain has diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 1a6c8afb1d..2882a7746b 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1399,6 +1399,8 @@ VIR_ENUM_IMPL(virDomainDiskModel, "virtio", "virtio-transitional", "virtio-non-transitional", + "usb-storage", + "usb-bot", );
VIR_ENUM_IMPL(virDomainDiskMirrorState, diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 3d380073cf..73e8a2fb99 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -439,6 +439,9 @@ typedef enum { VIR_DOMAIN_DISK_MODEL_VIRTIO_TRANSITIONAL, VIR_DOMAIN_DISK_MODEL_VIRTIO_NON_TRANSITIONAL,
Extra empty line?
+ VIR_DOMAIN_DISK_MODEL_USB_STORAGE, + VIR_DOMAIN_DISK_MODEL_USB_BOT, + VIR_DOMAIN_DISK_MODEL_LAST } virDomainDiskModel;
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index b1fe51f519..a80005562a 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -1766,6 +1766,8 @@ <value>virtio</value> <value>virtio-transitional</value> <value>virtio-non-transitional</value> + <value>usb-storage</value> + <value>usb-bot</value> </choice> </attribute> </optional> diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index bb86cfa0c3..3a23f70d39 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -729,6 +729,8 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDef *dev, case VIR_DOMAIN_DISK_MODEL_DEFAULT: return virtioFlags; case VIR_DOMAIN_DISK_MODEL_LAST: + case VIR_DOMAIN_DISK_MODEL_USB_STORAGE: + case VIR_DOMAIN_DISK_MODEL_USB_BOT: break; } return 0; diff --git a/tests/qemuxmlconfdata/disk-usb-device-model.x86_64-latest.args b/tests/qemuxmlconfdata/disk-usb-device-model.x86_64-latest.args new file mode 100644 index 0000000000..6d31319a49 --- /dev/null +++ b/tests/qemuxmlconfdata/disk-usb-device-model.x86_64-latest.args @@ -0,0 +1,46 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ +/usr/bin/qemu-system-x86_64 \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ +-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \ +-accel tcg \ +-cpu qemu64 \ +-m size=219136k \ +-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-boot strict=on \ +-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \ +-device '{"driver":"usb-hub","id":"hub0","bus":"usb.0","port":"1"}' \ +-blockdev '{"driver":"file","filename":"/tmp/img1","node-name":"libvirt-6-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"2","drive":"libvirt-6-storage","id":"usb-disk0","bootindex":1,"removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img2","node-name":"libvirt-5-storage","read-only":true}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.1","drive":"libvirt-5-storage","id":"usb-disk1","removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img3","node-name":"libvirt-4-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.2","drive":"libvirt-4-storage","id":"usb-disk2","removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img4","node-name":"libvirt-3-storage","read-only":true}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.3","drive":"libvirt-3-storage","id":"usb-disk3","removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img5","node-name":"libvirt-2-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.4","drive":"libvirt-2-storage","id":"usb-disk4","removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img6","node-name":"libvirt-1-storage","read-only":true}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.5","drive":"libvirt-1-storage","id":"usb-disk5","removable":false}' \
Well, this is strange. The XML uses both usb-storage and usb-bot, but only usb-storage is present in *.args. This kind of makes sense since the code for handling model is not wired up yet, but having the tests in a commit that describes the new models and how libvirt handles them is confusing. Jirka

On Tue, Jun 24, 2025 at 11:25:03 +0200, Jiri Denemark wrote:
On Mon, Jun 23, 2025 at 21:59:13 +0200, Peter Krempa wrote:
From: Peter Krempa <pkrempa@redhat.com>
Historically libvirt specified 'usb-storage' as driver for USB disks. This though combined with '-blockdev' doesn't properly configure the device to look like CDROM for <disk type='cdrom'>.
'usb-bot' acts like a controler and allows explicitly connecting a -device to it.
In qemu the devices share implementation so they are effectively identical and can be used interchangably. There is though a slight difference in how the storage device itself (the SCSI bit) looks when CDROM as they were not declared as cdrom before.
Looks like some words were dropped from the last sentence above.
As this is effectively a bugfix we'll be fixing the behaviour for the default configuration. The possibility to explicitly set the model is added as a possibility for working around possible problems if they'd appear.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> ---
[...]
+ ``<disk type='cdrom'>`` is properly exposed as a cdrom device inside the + guest OS. Unfortunately this configuration is not ABI compatible and thus + it can't be interchanged.
This is not ABI compatible with usb-storage model, right? I suggest being explicit about it.
+ + The QEMU hypervisor driver will pick ``usb-bot`` for cold starts or + hotplug for cdrom devices to properly configure the devices. This is + not compatible for migration to older versions of libvirt and explicit + configuration needs to be used.
So are you saying starting an existing domain with usb cdrom after upgrading libvirt will cause issues during migration to an older libvirt? I don't think we can do this. We should rather pick usb-storage (which is the case now as I understood from the description) unless usb-bot is set explicitly in the XML.
Yes it will not work if you start a VM and attempt to migrate it to an older version. The reason why I did this is that this very technically is a ABI bug fix. Prior to use of '-blockdev', when the disk backend was instantiated via -drive, we'd format 'media=cdrom' with the backend which would be picked up with the 'usb-storage' frontend to make it into a cdrom: Now this went unnoticed at that time. While I debated just changing it, the fact that it silently corrupts inside the guest was a dealbreaker for me. But at the same time it's IMO unacceptable to default to the broken configuration which actually did work before. Thus I decided to do this where users can switch to the broken configuration (or just detach the cdrom) but the config with no extra bits will result to the proper configuration as it should have before. Resulting to the broken config is obviously much easier on the logic here but I really don't think we should do it.7
+ :since:`Since 11.5.0`; relevant only for ``QEMU`` hypervisor. + ``rawio`` Indicates whether the disk needs rawio capability. Valid settings are "yes" or "no" (default is "no"). If any one disk in a domain has diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 1a6c8afb1d..2882a7746b 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1399,6 +1399,8 @@ VIR_ENUM_IMPL(virDomainDiskModel, "virtio", "virtio-transitional", "virtio-non-transitional", + "usb-storage", + "usb-bot", );
VIR_ENUM_IMPL(virDomainDiskMirrorState, diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 3d380073cf..73e8a2fb99 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -439,6 +439,9 @@ typedef enum { VIR_DOMAIN_DISK_MODEL_VIRTIO_TRANSITIONAL, VIR_DOMAIN_DISK_MODEL_VIRTIO_NON_TRANSITIONAL,
Extra empty line?
+ VIR_DOMAIN_DISK_MODEL_USB_STORAGE, + VIR_DOMAIN_DISK_MODEL_USB_BOT, + VIR_DOMAIN_DISK_MODEL_LAST } virDomainDiskModel;
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index b1fe51f519..a80005562a 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -1766,6 +1766,8 @@ <value>virtio</value> <value>virtio-transitional</value> <value>virtio-non-transitional</value> + <value>usb-storage</value> + <value>usb-bot</value> </choice> </attribute> </optional> diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index bb86cfa0c3..3a23f70d39 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -729,6 +729,8 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDef *dev, case VIR_DOMAIN_DISK_MODEL_DEFAULT: return virtioFlags; case VIR_DOMAIN_DISK_MODEL_LAST: + case VIR_DOMAIN_DISK_MODEL_USB_STORAGE: + case VIR_DOMAIN_DISK_MODEL_USB_BOT: break; } return 0; diff --git a/tests/qemuxmlconfdata/disk-usb-device-model.x86_64-latest.args b/tests/qemuxmlconfdata/disk-usb-device-model.x86_64-latest.args new file mode 100644 index 0000000000..6d31319a49 --- /dev/null +++ b/tests/qemuxmlconfdata/disk-usb-device-model.x86_64-latest.args @@ -0,0 +1,46 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ +/usr/bin/qemu-system-x86_64 \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ +-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \ +-accel tcg \ +-cpu qemu64 \ +-m size=219136k \ +-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-boot strict=on \ +-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \ +-device '{"driver":"usb-hub","id":"hub0","bus":"usb.0","port":"1"}' \ +-blockdev '{"driver":"file","filename":"/tmp/img1","node-name":"libvirt-6-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"2","drive":"libvirt-6-storage","id":"usb-disk0","bootindex":1,"removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img2","node-name":"libvirt-5-storage","read-only":true}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.1","drive":"libvirt-5-storage","id":"usb-disk1","removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img3","node-name":"libvirt-4-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.2","drive":"libvirt-4-storage","id":"usb-disk2","removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img4","node-name":"libvirt-3-storage","read-only":true}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.3","drive":"libvirt-3-storage","id":"usb-disk3","removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img5","node-name":"libvirt-2-storage","read-only":false}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.4","drive":"libvirt-2-storage","id":"usb-disk4","removable":false}' \ +-blockdev '{"driver":"file","filename":"/tmp/img6","node-name":"libvirt-1-storage","read-only":true}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1.5","drive":"libvirt-1-storage","id":"usb-disk5","removable":false}' \
Well, this is strange. The XML uses both usb-storage and usb-bot, but only usb-storage is present in *.args. This kind of makes sense since the code for handling model is not wired up yet, but having the tests in a commit that describes the new models and how libvirt handles them is confusing.
I thought about activating the capability later, but decided against as it was showing all updates together. So while this ordering creates a history point where this doesn't work , it's much easier to see what the patches are doing actually.

On Tue, Jun 24, 2025 at 12:51:57 +0200, Peter Krempa wrote:
On Tue, Jun 24, 2025 at 11:25:03 +0200, Jiri Denemark wrote:
On Mon, Jun 23, 2025 at 21:59:13 +0200, Peter Krempa wrote:
From: Peter Krempa <pkrempa@redhat.com>
Historically libvirt specified 'usb-storage' as driver for USB disks. This though combined with '-blockdev' doesn't properly configure the device to look like CDROM for <disk type='cdrom'>.
'usb-bot' acts like a controler and allows explicitly connecting a -device to it.
In qemu the devices share implementation so they are effectively identical and can be used interchangably. There is though a slight difference in how the storage device itself (the SCSI bit) looks when CDROM as they were not declared as cdrom before.
Looks like some words were dropped from the last sentence above.
As this is effectively a bugfix we'll be fixing the behaviour for the default configuration. The possibility to explicitly set the model is added as a possibility for working around possible problems if they'd appear.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> ---
[...]
+ ``<disk type='cdrom'>`` is properly exposed as a cdrom device inside the + guest OS. Unfortunately this configuration is not ABI compatible and thus + it can't be interchanged.
This is not ABI compatible with usb-storage model, right? I suggest being explicit about it.
+ + The QEMU hypervisor driver will pick ``usb-bot`` for cold starts or + hotplug for cdrom devices to properly configure the devices. This is + not compatible for migration to older versions of libvirt and explicit + configuration needs to be used.
So are you saying starting an existing domain with usb cdrom after upgrading libvirt will cause issues during migration to an older libvirt? I don't think we can do this. We should rather pick usb-storage (which is the case now as I understood from the description) unless usb-bot is set explicitly in the XML.
Yes it will not work if you start a VM and attempt to migrate it to an older version. The reason why I did this is that this very technically is a ABI bug fix.
Prior to use of '-blockdev', when the disk backend was instantiated via -drive, we'd format 'media=cdrom' with the backend which would be picked up with the 'usb-storage' frontend to make it into a cdrom:
Now this went unnoticed at that time.
While I debated just changing it, the fact that it silently corrupts inside the guest was a dealbreaker for me.
But at the same time it's IMO unacceptable to default to the broken configuration which actually did work before.
Thus I decided to do this where users can switch to the broken configuration (or just detach the cdrom) but the config with no extra bits will result to the proper configuration as it should have before.
Resulting to the broken config is obviously much easier on the logic here but I really don't think we should do it.7
As I said in my comments to the following patch, you change the model only when VIR_DOMAIN_DEF_PARSE_ABI_UPDATE and don't change where the flag is actually used (except for tests). So this series is OK.
diff --git a/tests/qemuxmlconfdata/disk-usb-device-model.x86_64-latest.args b/tests/qemuxmlconfdata/disk-usb-device-model.x86_64-latest.args new file mode 100644 index 0000000000..6d31319a49 --- /dev/null +++ b/tests/qemuxmlconfdata/disk-usb-device-model.x86_64-latest.args
Well, this is strange. The XML uses both usb-storage and usb-bot, but only usb-storage is present in *.args. This kind of makes sense since the code for handling model is not wired up yet, but having the tests in a commit that describes the new models and how libvirt handles them is confusing.
I thought about activating the capability later, but decided against as it was showing all updates together.
So while this ordering creates a history point where this doesn't work , it's much easier to see what the patches are doing actually.
Yeah, I was just thinking the test addition would deserve a dedicated commit to avoid the discrepancy between the test and the documentation in a single patch :-) Reviewed-by: Jiri Denemark <jdenemar@redhat.com>

From: Peter Krempa <pkrempa@redhat.com> While 'usb-bot' and 'usb-storage' are ABI and migration compatible for disks it's not the case for cdroms. When migrating from a new config using 'usb-bot' to an older daemon which would use 'usb-storage' the guest os will get I/O errors. Thus we must properly fill in models for 'usb' disks so that cdroms can be handled properly. When parsing XML fill in the models and drop the appropriate models when formatting migratable XML. The logic is explained in comments in the code. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_domain.c | 21 ++++++++ src/qemu/qemu_postparse.c | 49 ++++++++++++++++++- src/qemu/qemu_postparse.h | 4 +- tests/qemublocktest.c | 13 +++-- .../qemuhotplug-base-live+cdrom-usb.xml | 2 +- .../qemuhotplug-base-live+disk-usb.xml | 2 +- .../disk-cache.x86_64-latest.xml | 2 +- .../disk-usb-device-model.x86_64-latest.xml | 4 +- ...test.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml | 24 ++++----- ...date.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml | 24 ++++----- ...sk-usb-device.x86_64-latest.abi-update.xml | 24 ++++----- .../disk-usb-device.x86_64-latest.xml | 24 ++++----- 12 files changed, 132 insertions(+), 61 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index ace42b516a..6e147563f3 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -5342,6 +5342,27 @@ qemuDomainDefFormatBufInternal(virQEMUDriver *driver, } } + for (i = 0; i < def->ndisks; i++) { + virDomainDiskDef *disk = def->disks[i]; + + /* The 'mode' property for USB disks was introduced long after USB + * disks to allow switching between 'usb-storage' and 'usb-bot' + * device. Despite sharing identical implementation 'usb-bot' allows + * proper configuration of USB cdroms. Unfortunately it is not ABI + * compatible. + * + * To preserve migration to older daemons we can strip the model to + * the default if: + * - it's a normal disk (not cdrom) as both are identical + * - for a usb-cdrom strip the model if it's not 'usb-bot' as that + * was the old configuration + */ + if (disk->bus == VIR_DOMAIN_DISK_BUS_USB && + (disk->model == VIR_DOMAIN_DISK_MODEL_USB_STORAGE || + disk->device == VIR_DOMAIN_DISK_DEVICE_DISK)) + disk->model = VIR_DOMAIN_DISK_MODEL_DEFAULT; + } + /* Replace the CPU definition updated according to QEMU with the one * used for starting the domain. The updated def will be sent * separately for backward compatibility. diff --git a/src/qemu/qemu_postparse.c b/src/qemu/qemu_postparse.c index 8150dffac6..7db378c5ce 100644 --- a/src/qemu/qemu_postparse.c +++ b/src/qemu/qemu_postparse.c @@ -202,7 +202,8 @@ qemuDomainDeviceDiskDefPostParseRestoreSecAlias(virDomainDiskDef *disk, int qemuDomainDeviceDiskDefPostParse(virDomainDiskDef *disk, - unsigned int parseFlags) + unsigned int parseFlags, + virQEMUCaps *qemuCaps) { virStorageSource *n; @@ -220,6 +221,50 @@ qemuDomainDeviceDiskDefPostParse(virDomainDiskDef *disk, disk->mirror->format == VIR_STORAGE_FILE_NONE) disk->mirror->format = VIR_STORAGE_FILE_RAW; + /* default USB disk model: + * + * Historically we didn't use model for USB disks. It became necessary once + * it turned out that 'usb-storage' doesn't properly expose CDROM devices + * with -blockdev. Additionally 'usb-bot' which does properly handle them, + * while having identical implementation in qemu and driver in guest, are + * not in fact ABI compatible. Thus the logic is as follows: + * + * If ABI update is not allowed: + * - use 'usb-storage' for either (unless only 'usb-bot' is supported) + * + * If ABI update is possible + * - for VIR_DOMAIN_DISK_DEVICE_DISK use 'usb-storage' as it doesn't matter + * (it is identical with 'usb-bot' ABI wise) + * - for VIR_DOMAIN_DISK_DEVICE_CDROM use 'usb-bot' if available + * (as it properly exposes cdrom) + * + * When formatting migratable XML the code strips 'usb-storage' to preserve + * migration to older daemons. If a new definition with 'usb-bot' cdrom is + * created via new start or hotplug it will fail migrating. Users must + * explicitly set the broken config in XML or unplug the device. + */ + if (qemuCaps && + disk->bus == VIR_DOMAIN_DISK_BUS_USB && + disk->model == VIR_DOMAIN_DISK_MODEL_DEFAULT) { + + if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM && + parseFlags & VIR_DOMAIN_DEF_PARSE_ABI_UPDATE) { + + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_USB_BOT)) { + disk->model = VIR_DOMAIN_DISK_MODEL_USB_BOT; + } else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_USB_STORAGE)) { + disk->model = VIR_DOMAIN_DISK_MODEL_USB_STORAGE; + } + + } else { + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_USB_STORAGE)) { + disk->model = VIR_DOMAIN_DISK_MODEL_USB_STORAGE; + } else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_USB_BOT)) { + disk->model = VIR_DOMAIN_DISK_MODEL_USB_BOT; + } + } + } + /* default disk encryption engine */ for (n = disk->src; virStorageSourceIsBacking(n); n = n->backingStore) { if (n->encryption && n->encryption->engine == VIR_STORAGE_ENCRYPTION_ENGINE_DEFAULT) @@ -843,7 +888,7 @@ qemuDomainDeviceDefPostParse(virDomainDeviceDef *dev, break; case VIR_DOMAIN_DEVICE_DISK: - ret = qemuDomainDeviceDiskDefPostParse(dev->data.disk, parseFlags); + ret = qemuDomainDeviceDiskDefPostParse(dev->data.disk, parseFlags, qemuCaps); break; case VIR_DOMAIN_DEVICE_VIDEO: diff --git a/src/qemu/qemu_postparse.h b/src/qemu/qemu_postparse.h index ac69c14604..46945adbd6 100644 --- a/src/qemu/qemu_postparse.h +++ b/src/qemu/qemu_postparse.h @@ -22,10 +22,12 @@ #pragma once #include "virconftypes.h" +#include "qemu_capabilities.h" int qemuDomainDeviceDiskDefPostParse(virDomainDiskDef *disk, - unsigned int parseFlags); + unsigned int parseFlags, + virQEMUCaps *qemuCaps); int qemuDomainDeviceDefPostParse(virDomainDeviceDef *dev, diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c index be3e421ac0..095a54e22c 100644 --- a/tests/qemublocktest.c +++ b/tests/qemublocktest.c @@ -271,7 +271,7 @@ testQemuDiskXMLToProps(const void *opaque) VIR_DOMAIN_DEF_PARSE_STATUS))) return -1; - if (qemuDomainDeviceDiskDefPostParse(disk, 0) < 0) + if (qemuDomainDeviceDiskDefPostParse(disk, 0, data->qemuCaps) < 0) return -1; if (!(vmdef = virDomainDefNew(data->driver->xmlopt))) @@ -464,7 +464,8 @@ static const char *testQemuImageCreatePath = abs_srcdir "/qemublocktestdata/imag static virStorageSource * testQemuImageCreateLoadDiskXML(const char *name, - virDomainXMLOption *xmlopt) + virDomainXMLOption *xmlopt, + virQEMUCaps *qemuCaps) { g_autoptr(virDomainDiskDef) disk = NULL; @@ -481,7 +482,7 @@ testQemuImageCreateLoadDiskXML(const char *name, VIR_DOMAIN_DEF_PARSE_STATUS))) return NULL; - if (qemuDomainDeviceDiskDefPostParse(disk, 0) < 0) + if (qemuDomainDeviceDiskDefPostParse(disk, 0, qemuCaps) < 0) return NULL; return g_steal_pointer(&disk->src); @@ -502,12 +503,14 @@ testQemuImageCreate(const void *opaque) g_autofree char *actual = NULL; g_autofree char *jsonpath = NULL; - if (!(src = testQemuImageCreateLoadDiskXML(data->name, data->driver->xmlopt))) + if (!(src = testQemuImageCreateLoadDiskXML(data->name, data->driver->xmlopt, + data->qemuCaps))) return -1; if (data->backingname && !(src->backingStore = testQemuImageCreateLoadDiskXML(data->backingname, - data->driver->xmlopt))) + data->driver->xmlopt, + data->qemuCaps))) return -1; if (testQemuDiskXMLToJSONFakeSecrets(src) < 0) diff --git a/tests/qemuhotplugtestdomains/qemuhotplug-base-live+cdrom-usb.xml b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+cdrom-usb.xml index d31136dbc8..bed4dcec14 100644 --- a/tests/qemuhotplugtestdomains/qemuhotplug-base-live+cdrom-usb.xml +++ b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+cdrom-usb.xml @@ -22,7 +22,7 @@ <on_crash>restart</on_crash> <devices> <emulator>/usr/bin/qemu-system-x86_64</emulator> - <disk type='file' device='cdrom'> + <disk type='file' device='cdrom' model='usb-bot'> <driver name='qemu' type='raw' cache='none'/> <source file='/dev/null' index='1'/> <backingStore/> diff --git a/tests/qemuhotplugtestdomains/qemuhotplug-base-live+disk-usb.xml b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+disk-usb.xml index 5964c23ba0..6f974892be 100644 --- a/tests/qemuhotplugtestdomains/qemuhotplug-base-live+disk-usb.xml +++ b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+disk-usb.xml @@ -22,7 +22,7 @@ <on_crash>restart</on_crash> <devices> <emulator>/usr/bin/qemu-system-x86_64</emulator> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw' cache='none'/> <source file='/dev/null' index='1'/> <backingStore/> diff --git a/tests/qemuxmlconfdata/disk-cache.x86_64-latest.xml b/tests/qemuxmlconfdata/disk-cache.x86_64-latest.xml index c770deaaab..a5d9cd388a 100644 --- a/tests/qemuxmlconfdata/disk-cache.x86_64-latest.xml +++ b/tests/qemuxmlconfdata/disk-cache.x86_64-latest.xml @@ -41,7 +41,7 @@ <target dev='vda' bus='virtio'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> </disk> - <disk type='block' device='disk'> + <disk type='block' device='disk' model='usb-storage'> <driver name='qemu' type='qcow2' cache='directsync'/> <source dev='/dev/HostVG/QEMUGuest1'/> <target dev='sdb' bus='usb'/> diff --git a/tests/qemuxmlconfdata/disk-usb-device-model.x86_64-latest.xml b/tests/qemuxmlconfdata/disk-usb-device-model.x86_64-latest.xml index 351257bc4a..9f2f383f30 100644 --- a/tests/qemuxmlconfdata/disk-usb-device-model.x86_64-latest.xml +++ b/tests/qemuxmlconfdata/disk-usb-device-model.x86_64-latest.xml @@ -39,12 +39,12 @@ <target dev='sdd' bus='usb'/> <readonly/> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img5'/> <target dev='sde' bus='usb'/> </disk> - <disk type='file' device='cdrom'> + <disk type='file' device='cdrom' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img6'/> <target dev='sdf' bus='usb'/> diff --git a/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml b/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml index 8b78f77e63..75e489ede3 100644 --- a/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml +++ b/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml @@ -17,51 +17,51 @@ <on_crash>destroy</on_crash> <devices> <emulator>/usr/bin/qemu-system-x86_64</emulator> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img1'/> <target dev='sda' bus='usb'/> </disk> - <disk type='file' device='cdrom'> + <disk type='file' device='cdrom' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img2'/> <target dev='sdb' bus='usb'/> <readonly/> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img3'/> <target dev='sdc' bus='usb'/> <serial>testserial1</serial> </disk> - <disk type='file' device='cdrom'> + <disk type='file' device='cdrom' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img4'/> <target dev='sdd' bus='usb'/> <readonly/> <serial>testserial2</serial> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img5'/> <target dev='sde' bus='usb'/> <alias name='ua-test1'/> </disk> - <disk type='file' device='cdrom'> + <disk type='file' device='cdrom' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img6'/> <target dev='sdf' bus='usb'/> <readonly/> <alias name='ua-test2'/> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img7'/> <target dev='sdg' bus='usb'/> <serial>testserial3</serial> <alias name='ua-test3'/> </disk> - <disk type='file' device='cdrom'> + <disk type='file' device='cdrom' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img8'/> <target dev='sdh' bus='usb'/> @@ -69,24 +69,24 @@ <serial>testserial4</serial> <alias name='ua-test4'/> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img9'/> <target dev='sdi' bus='usb' removable='on'/> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/imga'/> <target dev='sdj' bus='usb' removable='on'/> <serial>testserial5</serial> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/imgb'/> <target dev='sdk' bus='usb' removable='on'/> <alias name='ua-test5'/> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/imgc'/> <target dev='sdl' bus='usb' removable='on'/> diff --git a/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml b/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml index 732230e722..b5954973c6 100644 --- a/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml +++ b/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml @@ -17,27 +17,27 @@ <on_crash>destroy</on_crash> <devices> <emulator>/usr/bin/qemu-system-x86_64</emulator> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img1'/> <target dev='sda' bus='usb'/> <address type='usb' bus='0' port='1.1'/> </disk> - <disk type='file' device='cdrom'> + <disk type='file' device='cdrom' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img2'/> <target dev='sdb' bus='usb'/> <readonly/> <address type='usb' bus='0' port='1.2'/> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img3'/> <target dev='sdc' bus='usb'/> <serial>testserial1</serial> <address type='usb' bus='0' port='1.3'/> </disk> - <disk type='file' device='cdrom'> + <disk type='file' device='cdrom' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img4'/> <target dev='sdd' bus='usb'/> @@ -45,14 +45,14 @@ <serial>testserial2</serial> <address type='usb' bus='0' port='1.4'/> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img5'/> <target dev='sde' bus='usb'/> <alias name='ua-test1'/> <address type='usb' bus='0' port='1.5'/> </disk> - <disk type='file' device='cdrom'> + <disk type='file' device='cdrom' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img6'/> <target dev='sdf' bus='usb'/> @@ -60,7 +60,7 @@ <alias name='ua-test2'/> <address type='usb' bus='0' port='1.6'/> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img7'/> <target dev='sdg' bus='usb'/> @@ -68,7 +68,7 @@ <alias name='ua-test3'/> <address type='usb' bus='0' port='1.7'/> </disk> - <disk type='file' device='cdrom'> + <disk type='file' device='cdrom' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img8'/> <target dev='sdh' bus='usb'/> @@ -77,27 +77,27 @@ <alias name='ua-test4'/> <address type='usb' bus='0' port='1.8'/> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img9'/> <target dev='sdi' bus='usb' removable='on'/> <address type='usb' bus='0' port='2.1'/> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/imga'/> <target dev='sdj' bus='usb' removable='on'/> <serial>testserial5</serial> <address type='usb' bus='0' port='2.2'/> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/imgb'/> <target dev='sdk' bus='usb' removable='on'/> <alias name='ua-test5'/> <address type='usb' bus='0' port='2.3'/> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/imgc'/> <target dev='sdl' bus='usb' removable='on'/> diff --git a/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.xml b/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.xml index 732230e722..b77bf4717c 100644 --- a/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.xml +++ b/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.xml @@ -17,27 +17,27 @@ <on_crash>destroy</on_crash> <devices> <emulator>/usr/bin/qemu-system-x86_64</emulator> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img1'/> <target dev='sda' bus='usb'/> <address type='usb' bus='0' port='1.1'/> </disk> - <disk type='file' device='cdrom'> + <disk type='file' device='cdrom' model='usb-bot'> <driver name='qemu' type='raw'/> <source file='/tmp/img2'/> <target dev='sdb' bus='usb'/> <readonly/> <address type='usb' bus='0' port='1.2'/> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img3'/> <target dev='sdc' bus='usb'/> <serial>testserial1</serial> <address type='usb' bus='0' port='1.3'/> </disk> - <disk type='file' device='cdrom'> + <disk type='file' device='cdrom' model='usb-bot'> <driver name='qemu' type='raw'/> <source file='/tmp/img4'/> <target dev='sdd' bus='usb'/> @@ -45,14 +45,14 @@ <serial>testserial2</serial> <address type='usb' bus='0' port='1.4'/> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img5'/> <target dev='sde' bus='usb'/> <alias name='ua-test1'/> <address type='usb' bus='0' port='1.5'/> </disk> - <disk type='file' device='cdrom'> + <disk type='file' device='cdrom' model='usb-bot'> <driver name='qemu' type='raw'/> <source file='/tmp/img6'/> <target dev='sdf' bus='usb'/> @@ -60,7 +60,7 @@ <alias name='ua-test2'/> <address type='usb' bus='0' port='1.6'/> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img7'/> <target dev='sdg' bus='usb'/> @@ -68,7 +68,7 @@ <alias name='ua-test3'/> <address type='usb' bus='0' port='1.7'/> </disk> - <disk type='file' device='cdrom'> + <disk type='file' device='cdrom' model='usb-bot'> <driver name='qemu' type='raw'/> <source file='/tmp/img8'/> <target dev='sdh' bus='usb'/> @@ -77,27 +77,27 @@ <alias name='ua-test4'/> <address type='usb' bus='0' port='1.8'/> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img9'/> <target dev='sdi' bus='usb' removable='on'/> <address type='usb' bus='0' port='2.1'/> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/imga'/> <target dev='sdj' bus='usb' removable='on'/> <serial>testserial5</serial> <address type='usb' bus='0' port='2.2'/> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/imgb'/> <target dev='sdk' bus='usb' removable='on'/> <alias name='ua-test5'/> <address type='usb' bus='0' port='2.3'/> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/imgc'/> <target dev='sdl' bus='usb' removable='on'/> diff --git a/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.xml b/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.xml index 8b78f77e63..75e489ede3 100644 --- a/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.xml +++ b/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.xml @@ -17,51 +17,51 @@ <on_crash>destroy</on_crash> <devices> <emulator>/usr/bin/qemu-system-x86_64</emulator> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img1'/> <target dev='sda' bus='usb'/> </disk> - <disk type='file' device='cdrom'> + <disk type='file' device='cdrom' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img2'/> <target dev='sdb' bus='usb'/> <readonly/> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img3'/> <target dev='sdc' bus='usb'/> <serial>testserial1</serial> </disk> - <disk type='file' device='cdrom'> + <disk type='file' device='cdrom' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img4'/> <target dev='sdd' bus='usb'/> <readonly/> <serial>testserial2</serial> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img5'/> <target dev='sde' bus='usb'/> <alias name='ua-test1'/> </disk> - <disk type='file' device='cdrom'> + <disk type='file' device='cdrom' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img6'/> <target dev='sdf' bus='usb'/> <readonly/> <alias name='ua-test2'/> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img7'/> <target dev='sdg' bus='usb'/> <serial>testserial3</serial> <alias name='ua-test3'/> </disk> - <disk type='file' device='cdrom'> + <disk type='file' device='cdrom' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img8'/> <target dev='sdh' bus='usb'/> @@ -69,24 +69,24 @@ <serial>testserial4</serial> <alias name='ua-test4'/> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/img9'/> <target dev='sdi' bus='usb' removable='on'/> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/imga'/> <target dev='sdj' bus='usb' removable='on'/> <serial>testserial5</serial> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/imgb'/> <target dev='sdk' bus='usb' removable='on'/> <alias name='ua-test5'/> </disk> - <disk type='file' device='disk'> + <disk type='file' device='disk' model='usb-storage'> <driver name='qemu' type='raw'/> <source file='/tmp/imgc'/> <target dev='sdl' bus='usb' removable='on'/> -- 2.49.0

On Mon, Jun 23, 2025 at 21:59:14 +0200, Peter Krempa wrote:
From: Peter Krempa <pkrempa@redhat.com>
While 'usb-bot' and 'usb-storage' are ABI and migration compatible for disks it's not the case for cdroms. When migrating from a new config using 'usb-bot' to an older daemon which would use 'usb-storage' the guest os will get I/O errors.
Thus we must properly fill in models for 'usb' disks so that cdroms can be handled properly.
When parsing XML fill in the models and drop the appropriate models when formatting migratable XML.
The logic is explained in comments in the code.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_domain.c | 21 ++++++++ src/qemu/qemu_postparse.c | 49 ++++++++++++++++++- src/qemu/qemu_postparse.h | 4 +- tests/qemublocktest.c | 13 +++-- .../qemuhotplug-base-live+cdrom-usb.xml | 2 +- .../qemuhotplug-base-live+disk-usb.xml | 2 +- .../disk-cache.x86_64-latest.xml | 2 +- .../disk-usb-device-model.x86_64-latest.xml | 4 +- ...test.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml | 24 ++++----- ...date.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml | 24 ++++----- ...sk-usb-device.x86_64-latest.abi-update.xml | 24 ++++----- .../disk-usb-device.x86_64-latest.xml | 24 ++++----- 12 files changed, 132 insertions(+), 61 deletions(-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index ace42b516a..6e147563f3 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -5342,6 +5342,27 @@ qemuDomainDefFormatBufInternal(virQEMUDriver *driver, } }
+ for (i = 0; i < def->ndisks; i++) { + virDomainDiskDef *disk = def->disks[i]; + + /* The 'mode' property for USB disks was introduced long after USB
s/mode/model/
+ * disks to allow switching between 'usb-storage' and 'usb-bot' + * device. Despite sharing identical implementation 'usb-bot' allows + * proper configuration of USB cdroms. Unfortunately it is not ABI + * compatible. + * + * To preserve migration to older daemons we can strip the model to + * the default if: + * - it's a normal disk (not cdrom) as both are identical + * - for a usb-cdrom strip the model if it's not 'usb-bot' as that + * was the old configuration + */ + if (disk->bus == VIR_DOMAIN_DISK_BUS_USB && + (disk->model == VIR_DOMAIN_DISK_MODEL_USB_STORAGE || + disk->device == VIR_DOMAIN_DISK_DEVICE_DISK)) + disk->model = VIR_DOMAIN_DISK_MODEL_DEFAULT; + } + /* Replace the CPU definition updated according to QEMU with the one * used for starting the domain. The updated def will be sent * separately for backward compatibility. diff --git a/src/qemu/qemu_postparse.c b/src/qemu/qemu_postparse.c index 8150dffac6..7db378c5ce 100644 --- a/src/qemu/qemu_postparse.c +++ b/src/qemu/qemu_postparse.c @@ -202,7 +202,8 @@ qemuDomainDeviceDiskDefPostParseRestoreSecAlias(virDomainDiskDef *disk,
int qemuDomainDeviceDiskDefPostParse(virDomainDiskDef *disk, - unsigned int parseFlags) + unsigned int parseFlags, + virQEMUCaps *qemuCaps) { virStorageSource *n;
@@ -220,6 +221,50 @@ qemuDomainDeviceDiskDefPostParse(virDomainDiskDef *disk, disk->mirror->format == VIR_STORAGE_FILE_NONE) disk->mirror->format = VIR_STORAGE_FILE_RAW;
+ /* default USB disk model: + * + * Historically we didn't use model for USB disks. It became necessary once + * it turned out that 'usb-storage' doesn't properly expose CDROM devices + * with -blockdev. Additionally 'usb-bot' which does properly handle them, + * while having identical implementation in qemu and driver in guest, are + * not in fact ABI compatible. Thus the logic is as follows: + * + * If ABI update is not allowed: + * - use 'usb-storage' for either (unless only 'usb-bot' is supported) + * + * If ABI update is possible + * - for VIR_DOMAIN_DISK_DEVICE_DISK use 'usb-storage' as it doesn't matter + * (it is identical with 'usb-bot' ABI wise) + * - for VIR_DOMAIN_DISK_DEVICE_CDROM use 'usb-bot' if available + * (as it properly exposes cdrom) + * + * When formatting migratable XML the code strips 'usb-storage' to preserve + * migration to older daemons. If a new definition with 'usb-bot' cdrom is + * created via new start or hotplug it will fail migrating. Users must + * explicitly set the broken config in XML or unplug the device. + */ + if (qemuCaps && + disk->bus == VIR_DOMAIN_DISK_BUS_USB && + disk->model == VIR_DOMAIN_DISK_MODEL_DEFAULT) { + + if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM && + parseFlags & VIR_DOMAIN_DEF_PARSE_ABI_UPDATE) { + + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_USB_BOT)) { + disk->model = VIR_DOMAIN_DISK_MODEL_USB_BOT; + } else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_USB_STORAGE)) { + disk->model = VIR_DOMAIN_DISK_MODEL_USB_STORAGE; + } + + } else { + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_USB_STORAGE)) {
I would merge this with the else above to reduce nesting: if (DEVICE_CDROM && ABI_UPDATE) { } else if (MODEL_USB_STORAGE) { ... } else if (MODEL_USB_BOT) { ... }
+ disk->model = VIR_DOMAIN_DISK_MODEL_USB_STORAGE; + } else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_USB_BOT)) { + disk->model = VIR_DOMAIN_DISK_MODEL_USB_BOT; + } + } + } +
The logic is OK. I guess my comment in the previous patch was actually about using VIR_DOMAIN_DEF_PARSE_ABI_UPDATE flag. But you're not touching this part here so I guess everything should be fine. Although I'm still surprised we'd allow ABI update when starting a domain, I thought this was only allowed when defining it...
/* default disk encryption engine */ for (n = disk->src; virStorageSourceIsBacking(n); n = n->backingStore) { if (n->encryption && n->encryption->engine == VIR_STORAGE_ENCRYPTION_ENGINE_DEFAULT)
Jirka

On Tue, Jun 24, 2025 at 11:47:57 +0200, Jiri Denemark wrote:
From: Peter Krempa <pkrempa@redhat.com>
While 'usb-bot' and 'usb-storage' are ABI and migration compatible for disks it's not the case for cdroms. When migrating from a new config using 'usb-bot' to an older daemon which would use 'usb-storage' the guest os will get I/O errors.
Thus we must properly fill in models for 'usb' disks so that cdroms can be handled properly.
When parsing XML fill in the models and drop the appropriate models when formatting migratable XML.
The logic is explained in comments in the code.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_domain.c | 21 ++++++++ src/qemu/qemu_postparse.c | 49 ++++++++++++++++++- src/qemu/qemu_postparse.h | 4 +- tests/qemublocktest.c | 13 +++-- .../qemuhotplug-base-live+cdrom-usb.xml | 2 +- .../qemuhotplug-base-live+disk-usb.xml | 2 +- .../disk-cache.x86_64-latest.xml | 2 +- .../disk-usb-device-model.x86_64-latest.xml | 4 +- ...test.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml | 24 ++++----- ...date.QEMU_CAPS_DEVICE_USB_BOT-disabled.xml | 24 ++++----- ...sk-usb-device.x86_64-latest.abi-update.xml | 24 ++++----- .../disk-usb-device.x86_64-latest.xml | 24 ++++----- 12 files changed, 132 insertions(+), 61 deletions(-) ... The logic is OK. I guess my comment in the previous patch was actually about using VIR_DOMAIN_DEF_PARSE_ABI_UPDATE flag. But you're not touching this part here so I guess everything should be fine. Although I'm still surprised we'd allow ABI update when starting a domain, I
On Mon, Jun 23, 2025 at 21:59:14 +0200, Peter Krempa wrote: thought this was only allowed when defining it...
/* default disk encryption engine */ for (n = disk->src; virStorageSourceIsBacking(n); n = n->backingStore) { if (n->encryption && n->encryption->engine == VIR_STORAGE_ENCRYPTION_ENGINE_DEFAULT)
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>

From: Peter Krempa <pkrempa@redhat.com> While the 'usb-storage' based disks use the USB address directly, with 'usb-bot' the USB address is on the "controller" part of the device and the 'scsi-hd/cd' device will use a 'drive' address from qemu's PoV. Since we do not want to expose the 'usb-bot' as explicit controller to preserve compatibility with existing configs we plan to upgrade implement the formatter for 'drive' address when the "diskbus" property is VIR_DOMAIN_DISK_BUS_USB. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_command.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 4de6016784..910242a389 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -545,8 +545,21 @@ qemuBuildDeviceAddresDriveProps(virJSONValue *props, return -1; break; - case VIR_DOMAIN_DISK_BUS_VIRTIO: case VIR_DOMAIN_DISK_BUS_USB: + /* Device info with type VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE and + * VIR_DOMAIN_DISK_BUS_USB diskbus is an internal representation + * for the device address for 'usb-bot'. */ + bus = g_strdup_printf("%s.0", info->alias); + + if (virJSONValueObjectAdd(&props, + "s:bus", bus, + "u:scsi-id", info->addr.drive.target, + "u:lun", info->addr.drive.unit, + NULL) < 0) + return -1; + break; + + case VIR_DOMAIN_DISK_BUS_VIRTIO: case VIR_DOMAIN_DISK_BUS_XEN: case VIR_DOMAIN_DISK_BUS_UML: case VIR_DOMAIN_DISK_BUS_SD: -- 2.49.0

On Mon, Jun 23, 2025 at 21:59:15 +0200, Peter Krempa wrote:
From: Peter Krempa <pkrempa@redhat.com>
While the 'usb-storage' based disks use the USB address directly, with 'usb-bot' the USB address is on the "controller" part of the device and the 'scsi-hd/cd' device will use a 'drive' address from qemu's PoV.
Since we do not want to expose the 'usb-bot' as explicit controller to preserve compatibility with existing configs we plan to upgrade implement the formatter for 'drive' address when the "diskbus" property is VIR_DOMAIN_DISK_BUS_USB.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_command.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 4de6016784..910242a389 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -545,8 +545,21 @@ qemuBuildDeviceAddresDriveProps(virJSONValue *props, return -1; break;
- case VIR_DOMAIN_DISK_BUS_VIRTIO: case VIR_DOMAIN_DISK_BUS_USB: + /* Device info with type VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE and + * VIR_DOMAIN_DISK_BUS_USB diskbus is an internal representation + * for the device address for 'usb-bot'. */ + bus = g_strdup_printf("%s.0", info->alias); + + if (virJSONValueObjectAdd(&props, + "s:bus", bus, + "u:scsi-id", info->addr.drive.target, + "u:lun", info->addr.drive.unit, + NULL) < 0) + return -1; + break;
The code is indented one level more than it should be.
+ + case VIR_DOMAIN_DISK_BUS_VIRTIO: case VIR_DOMAIN_DISK_BUS_XEN: case VIR_DOMAIN_DISK_BUS_UML: case VIR_DOMAIN_DISK_BUS_SD:
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>

From: Peter Krempa <pkrempa@redhat.com> The helper sets the 'attached' property of the 'usb-bot' device to true, which will be used on the hotplug code path. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_monitor.c | 12 ++++++++++++ src/qemu/qemu_monitor.h | 3 +++ src/qemu/qemu_monitor_json.c | 20 ++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 5 +++++ 4 files changed, 40 insertions(+) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index d508f50ed6..95c88fd5e8 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2164,6 +2164,18 @@ qemuMonitorSetDBusVMStateIdList(qemuMonitor *mon, } +int +qemuMonitorSetUSBDiskAttached(qemuMonitor *mon, + const char *alias) +{ + QEMU_CHECK_MONITOR(mon); + + VIR_DEBUG("alias=%s", alias); + + return qemuMonitorJSONSetUSBDiskAttached(mon, alias); +} + + /** * qemuMonitorGetMigrationParams: * @mon: Pointer to the monitor object. diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 51b65b4019..6030c31598 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -768,6 +768,9 @@ int qemuMonitorSavePhysicalMemory(qemuMonitor *mon, int qemuMonitorSetDBusVMStateIdList(qemuMonitor *mon, GSList *list); +int qemuMonitorSetUSBDiskAttached(qemuMonitor *mon, + const char *alias); + int qemuMonitorGetMigrationParams(qemuMonitor *mon, virJSONValue **params); int qemuMonitorSetMigrationParams(qemuMonitor *mon, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index a6fb2a2013..5297ffb027 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2086,6 +2086,26 @@ qemuMonitorJSONSetDBusVMStateIdList(qemuMonitor *mon, } +/** + * qemuMonitorJSONSetUSBDiskAttached: + * @mon: monitor object + * @alias: alias of usb disk to set + * + * Sets the 'attached' property of @alias to true. + */ +int +qemuMonitorJSONSetUSBDiskAttached(qemuMonitor *mon, + const char *alias) +{ + qemuMonitorJSONObjectProperty prop = { + .type = QEMU_MONITOR_OBJECT_PROPERTY_BOOLEAN, + .val.b = true, + }; + + return qemuMonitorJSONSetObjectProperty(mon, alias, "attached", &prop); +} + + /* qemuMonitorJSONQueryNamedBlockNodes: * @mon: Monitor pointer * diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 7f07e55e06..bd437f7938 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -757,6 +757,11 @@ qemuMonitorJSONSetDBusVMStateIdList(qemuMonitor *mon, const char *idstr) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); +int +qemuMonitorJSONSetUSBDiskAttached(qemuMonitor *mon, + const char *alias) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + int qemuMonitorJSONGetCPUMigratable(qemuMonitor *mon, const char *cpuQOMPath, -- 2.49.0

On Mon, Jun 23, 2025 at 21:59:16 +0200, Peter Krempa wrote:
From: Peter Krempa <pkrempa@redhat.com>
The helper sets the 'attached' property of the 'usb-bot' device to true, which will be used on the hotplug code path.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_monitor.c | 12 ++++++++++++ src/qemu/qemu_monitor.h | 3 +++ src/qemu/qemu_monitor_json.c | 20 ++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 5 +++++ 4 files changed, 40 insertions(+)
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>

From: Peter Krempa <pkrempa@redhat.com> Modify the validation of empty cdroms to trigger only for VIR_DOMAIN_DISK_MODEL_USB_STORAGE as with 'usb-bot' we can properly emulate a cdrom. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_validate.c | 3 +- ...om-usb-empty.x86_64-latest.abi-update.args | 33 ++++++++++++++++ ...rom-usb-empty.x86_64-latest.abi-update.xml | 38 +++++++++++++++++++ tests/qemuxmlconftest.c | 1 + 4 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxmlconfdata/disk-cdrom-usb-empty.x86_64-latest.abi-update.args create mode 100644 tests/qemuxmlconfdata/disk-cdrom-usb-empty.x86_64-latest.abi-update.xml diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index b2faf43002..7e0e4db516 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -3189,7 +3189,8 @@ qemuValidateDomainDeviceDefDiskFrontend(const virDomainDiskDef *disk, return -1; } - if (virStorageSourceIsEmpty(disk->src)) { + if (disk->model == VIR_DOMAIN_DISK_MODEL_USB_STORAGE && + virStorageSourceIsEmpty(disk->src)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("'usb' disk must not be empty")); return -1; diff --git a/tests/qemuxmlconfdata/disk-cdrom-usb-empty.x86_64-latest.abi-update.args b/tests/qemuxmlconfdata/disk-cdrom-usb-empty.x86_64-latest.abi-update.args new file mode 100644 index 0000000000..cebc6e66e8 --- /dev/null +++ b/tests/qemuxmlconfdata/disk-cdrom-usb-empty.x86_64-latest.abi-update.args @@ -0,0 +1,33 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ +/usr/bin/qemu-system-x86_64 \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \ +-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \ +-accel tcg \ +-cpu qemu64 \ +-m size=219136k \ +-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-boot strict=on \ +-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \ +-device '{"driver":"usb-storage","bus":"usb.0","port":"1","id":"usb-disk1","removable":false}' \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxmlconfdata/disk-cdrom-usb-empty.x86_64-latest.abi-update.xml b/tests/qemuxmlconfdata/disk-cdrom-usb-empty.x86_64-latest.abi-update.xml new file mode 100644 index 0000000000..32aa011f90 --- /dev/null +++ b/tests/qemuxmlconfdata/disk-cdrom-usb-empty.x86_64-latest.abi-update.xml @@ -0,0 +1,38 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='file' device='cdrom' model='usb-bot'> + <driver name='qemu' type='raw'/> + <target dev='sdb' bus='usb'/> + <readonly/> + <address type='usb' bus='0' port='1'/> + </disk> + <controller type='usb' index='0' model='piix3-uhci'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index 858dde6ae8..db6f68cbe6 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -1545,6 +1545,7 @@ mymain(void) DO_TEST_CAPS_LATEST("disk-cdrom"); DO_TEST_CAPS_LATEST("disk-cdrom-empty-network-invalid"); + DO_TEST_CAPS_ARCH_LATEST_ABI_UPDATE("disk-cdrom-usb-empty", "x86_64"); DO_TEST_CAPS_LATEST_PARSE_ERROR("disk-cdrom-usb-empty"); DO_TEST_CAPS_LATEST("disk-cdrom-network"); DO_TEST_CAPS_LATEST("disk-cdrom-tray"); -- 2.49.0

On Mon, Jun 23, 2025 at 21:59:17 +0200, Peter Krempa wrote:
From: Peter Krempa <pkrempa@redhat.com>
Modify the validation of empty cdroms to trigger only for VIR_DOMAIN_DISK_MODEL_USB_STORAGE as with 'usb-bot' we can properly emulate a cdrom.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_validate.c | 3 +- ...om-usb-empty.x86_64-latest.abi-update.args | 33 ++++++++++++++++ ...rom-usb-empty.x86_64-latest.abi-update.xml | 38 +++++++++++++++++++ tests/qemuxmlconftest.c | 1 + 4 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxmlconfdata/disk-cdrom-usb-empty.x86_64-latest.abi-update.args create mode 100644 tests/qemuxmlconfdata/disk-cdrom-usb-empty.x86_64-latest.abi-update.xml
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>

From: Akihiko Odaki <akihiko.odaki@daynix.com> usb-storage is a compound device that automatically creates a USB mass storage device and a SCSI device as its backend. Unfortunately it lacks some configuration options that are usually present with a SCSI device, and cannot represent CD-ROM in particular. Replace usb-storage with usb-bot, which can be combined with a manually created SCSI device. libvirt will configure the SCSI device in a way identical with how QEMU does for usb-storage except that now it respects a configuration option to represent CD-ROM. Resolves: https://gitlab.com/libvirt/libvirt/-/issues/368 Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_alias.c | 20 ++++- src/qemu/qemu_capabilities.c | 3 +- src/qemu/qemu_command.c | 86 ++++++++++++++++--- src/qemu/qemu_command.h | 5 ++ src/qemu/qemu_hotplug.c | 18 ++++ src/qemu/qemu_validate.c | 38 ++++++-- tests/qemuhotplugtest.c | 4 +- ...om-usb-empty.x86_64-latest.abi-update.args | 3 +- .../disk-usb-device-model.x86_64-latest.args | 6 +- ...k-usb-device.x86_64-latest.abi-update.args | 12 ++- 10 files changed, 167 insertions(+), 28 deletions(-) diff --git a/src/qemu/qemu_alias.c b/src/qemu/qemu_alias.c index 9d39ebd63d..67cbddd470 100644 --- a/src/qemu/qemu_alias.c +++ b/src/qemu/qemu_alias.c @@ -268,8 +268,24 @@ qemuAssignDeviceDiskAlias(virDomainDef *def, break; case VIR_DOMAIN_DISK_BUS_USB: - diskPriv->qomName = g_strdup_printf("/machine/peripheral/%s/%s.0/legacy[0]", - disk->info.alias, disk->info.alias); + switch (disk->model) { + case VIR_DOMAIN_DISK_MODEL_USB_STORAGE: + diskPriv->qomName = g_strdup_printf("/machine/peripheral/%s/%s.0/legacy[0]", + disk->info.alias, disk->info.alias); + break; + + case VIR_DOMAIN_DISK_MODEL_USB_BOT: + diskPriv->qomName = g_strdup_printf("/machine/peripheral/%s-disk", + disk->info.alias); + break; + + case VIR_DOMAIN_DISK_MODEL_DEFAULT: + case VIR_DOMAIN_DISK_MODEL_VIRTIO: + case VIR_DOMAIN_DISK_MODEL_VIRTIO_TRANSITIONAL: + case VIR_DOMAIN_DISK_MODEL_VIRTIO_NON_TRANSITIONAL: + case VIR_DOMAIN_DISK_MODEL_LAST: + break; + } break; case VIR_DOMAIN_DISK_BUS_XEN: diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index f480060e50..ef6ec661ff 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -6472,7 +6472,8 @@ virQEMUCapsFillDomainDeviceDiskCaps(virQEMUCaps *qemuCaps, VIR_DOMAIN_DISK_BUS_VIRTIO, /* VIR_DOMAIN_DISK_BUS_SD */); - if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_USB_STORAGE)) + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_USB_STORAGE) || + virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_USB_BOT)) VIR_DOMAIN_CAPS_ENUM_SET(disk->bus, VIR_DOMAIN_DISK_BUS_USB); if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_ICH9_AHCI)) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 910242a389..98fd6fee85 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1626,6 +1626,33 @@ qemuBuildIothreadMappingProps(GSList *iothreads) return g_steal_pointer(&ret); } +int +qemuBuildDiskBusProps(const virDomainDef *def, + const virDomainDiskDef *disk, + virJSONValue **propsRet) +{ + g_autoptr(virJSONValue) props = NULL; + + *propsRet = NULL; + + if (disk->bus != VIR_DOMAIN_DISK_BUS_USB || + disk->model != VIR_DOMAIN_DISK_MODEL_USB_BOT) + return 0; + + if (virJSONValueObjectAdd(&props, + "s:driver", "usb-bot", + "s:id", disk->info.alias, + "S:serial", disk->serial, + NULL) < 0) + return -1; + + if (qemuBuildDeviceAddressProps(props, def, &disk->info) < 0) + return -1; + + *propsRet = g_steal_pointer(&props); + + return 0; +} virJSONValue * qemuBuildDiskDeviceProps(const virDomainDef *def, @@ -1652,6 +1679,18 @@ qemuBuildDiskDeviceProps(const virDomainDef *def, const char *rpolicy = NULL; const char *model = NULL; const char *product = NULL; + const char *alias = disk->info.alias; + g_autofree char *usbdiskalias = NULL; + const virDomainDeviceInfo *deviceinfo = &disk->info; + virDomainDeviceInfo usbSCSIinfo = { + .type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE, + .addr.drive = { .diskbus = VIR_DOMAIN_DISK_BUS_USB }, + .effectiveBootIndex = deviceinfo->effectiveBootIndex, + .alias = deviceinfo->alias, + }; + + if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) + disk->info.addr.drive.diskbus = disk->bus; switch (disk->bus) { case VIR_DOMAIN_DISK_BUS_IDE: @@ -1735,13 +1774,35 @@ qemuBuildDiskDeviceProps(const virDomainDef *def, break; case VIR_DOMAIN_DISK_BUS_USB: - driver = "usb-storage"; + switch (disk->model) { + case VIR_DOMAIN_DISK_MODEL_USB_STORAGE: + driver = "usb-storage"; - if (disk->removable == VIR_TRISTATE_SWITCH_ABSENT) - removable = VIR_TRISTATE_SWITCH_OFF; - else - removable = disk->removable; + if (disk->removable == VIR_TRISTATE_SWITCH_ABSENT) + removable = VIR_TRISTATE_SWITCH_OFF; + else + removable = disk->removable; + break; + + case VIR_DOMAIN_DISK_MODEL_USB_BOT: + if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) { + driver = "scsi-cd"; + } else { + driver = "scsi-hd"; + removable = disk->removable; + } + deviceinfo = &usbSCSIinfo; + alias = usbdiskalias = g_strdup_printf("%s-device", disk->info.alias); + break; + + case VIR_DOMAIN_DISK_MODEL_DEFAULT: + case VIR_DOMAIN_DISK_MODEL_VIRTIO: + case VIR_DOMAIN_DISK_MODEL_VIRTIO_TRANSITIONAL: + case VIR_DOMAIN_DISK_MODEL_VIRTIO_NON_TRANSITIONAL: + case VIR_DOMAIN_DISK_MODEL_LAST: + break; + } break; case VIR_DOMAIN_DISK_BUS_FDC: @@ -1771,10 +1832,7 @@ qemuBuildDiskDeviceProps(const virDomainDef *def, return NULL; } - if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) - disk->info.addr.drive.diskbus = disk->bus; - - if (qemuBuildDeviceAddressProps(props, def, &disk->info) < 0) + if (qemuBuildDeviceAddressProps(props, def, deviceinfo) < 0) return NULL; if (disk->src->shared) @@ -1836,7 +1894,7 @@ qemuBuildDiskDeviceProps(const virDomainDef *def, "T:share-rw", shareRW, "S:drive", drive, "S:chardev", chardev, - "s:id", disk->info.alias, + "s:id", alias, "p:bootindex", bootindex, "S:loadparm", bootLoadparm, "p:logical_block_size", logical_block_size, @@ -2201,6 +2259,7 @@ qemuBuildDiskCommandLine(virCommand *cmd, virQEMUCaps *qemuCaps) { g_autoptr(virJSONValue) devprops = NULL; + g_autoptr(virJSONValue) busprops = NULL; if (qemuBuildDiskSourceCommandLine(cmd, disk, qemuCaps) < 0) return -1; @@ -2216,6 +2275,13 @@ qemuBuildDiskCommandLine(virCommand *cmd, if (qemuCommandAddExtDevice(cmd, &disk->info, def, qemuCaps) < 0) return -1; + if (qemuBuildDiskBusProps(def, disk, &busprops) < 0) + return -1; + + if (busprops && + qemuBuildDeviceCommandlineFromJSON(cmd, busprops, def, qemuCaps) < 0) + return -1; + if (!(devprops = qemuBuildDiskDeviceProps(def, disk, qemuCaps))) return -1; diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index 2d43cf5506..574dffdc96 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -129,6 +129,11 @@ qemuBuildThrottleFiltersAttachPrepareBlockdev(virDomainDiskDef *disk); qemuBlockThrottleFiltersData * qemuBuildThrottleFiltersDetachPrepareBlockdev(virDomainDiskDef *disk); +int +qemuBuildDiskBusProps(const virDomainDef *def, + const virDomainDiskDef *disk, + virJSONValue **propsRet); + virJSONValue * qemuBuildDiskDeviceProps(const virDomainDef *def, virDomainDiskDef *disk, diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index e1ed8181e3..4f6a3d3414 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -703,8 +703,10 @@ qemuDomainAttachDiskGeneric(virDomainObj *vm, g_autoptr(qemuBlockStorageSourceChainData) data = NULL; g_autoptr(qemuBlockThrottleFiltersData) filterData = NULL; qemuDomainObjPrivate *priv = vm->privateData; + g_autoptr(virJSONValue) busprops = NULL; g_autoptr(virJSONValue) devprops = NULL; bool extensionDeviceAttached = false; + bool busAdded = false; int rc; g_autoptr(qemuSnapshotDiskContext) transientDiskSnapshotCtxt = NULL; bool origReadonly = disk->src->readonly; @@ -774,6 +776,9 @@ qemuDomainAttachDiskGeneric(virDomainObj *vm, } } + if (qemuBuildDiskBusProps(vm->def, disk, &busprops) < 0) + goto rollback; + if (!(devprops = qemuBuildDiskDeviceProps(vm->def, disk, priv->qemuCaps))) goto rollback; @@ -783,6 +788,10 @@ qemuDomainAttachDiskGeneric(virDomainObj *vm, if ((rc = qemuDomainAttachExtensionDevice(priv->mon, &disk->info)) == 0) extensionDeviceAttached = true; + if (rc == 0 && busprops && + (rc = qemuMonitorAddDeviceProps(priv->mon, &busprops)) == 0) + busAdded = true; + if (rc == 0) rc = qemuMonitorAddDeviceProps(priv->mon, &devprops); @@ -811,6 +820,12 @@ qemuDomainAttachDiskGeneric(virDomainObj *vm, } } + if (rc == 0) { + if (disk->bus == VIR_DOMAIN_DISK_BUS_USB && + disk->model == VIR_DOMAIN_DISK_MODEL_USB_BOT) + rc = qemuMonitorSetUSBDiskAttached(priv->mon, disk->info.alias); + } + qemuDomainObjExitMonitor(vm); if (rc < 0) @@ -822,6 +837,9 @@ qemuDomainAttachDiskGeneric(virDomainObj *vm, if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) < 0) return -1; + if (busAdded) + ignore_value(qemuMonitorDelDevice(priv->mon, disk->info.alias)); + if (extensionDeviceAttached) ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &disk->info)); diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 7e0e4db516..4b8d4fc692 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -3183,16 +3183,40 @@ qemuValidateDomainDeviceDefDiskFrontend(const virDomainDiskDef *disk, break; case VIR_DOMAIN_DISK_BUS_USB: - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_USB_STORAGE)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("This QEMU doesn't support '-device usb-storage'")); + switch (disk->model) { + case VIR_DOMAIN_DISK_MODEL_DEFAULT: + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("USB disk model was not selected by selection code")); return -1; - } - if (disk->model == VIR_DOMAIN_DISK_MODEL_USB_STORAGE && - virStorageSourceIsEmpty(disk->src)) { + case VIR_DOMAIN_DISK_MODEL_USB_STORAGE: + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_USB_STORAGE)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("This QEMU doesn't support '-device usb-storage'")); + return -1; + } + + if (virStorageSourceIsEmpty(disk->src)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("'usb' disk must not be empty")); + return -1; + } + break; + + case VIR_DOMAIN_DISK_MODEL_USB_BOT: + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_USB_BOT)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("This QEMU doesn't support '-device usb-bot'")); + return -1; + } + break; + + case VIR_DOMAIN_DISK_MODEL_VIRTIO_TRANSITIONAL: + case VIR_DOMAIN_DISK_MODEL_VIRTIO: + case VIR_DOMAIN_DISK_MODEL_VIRTIO_NON_TRANSITIONAL: + case VIR_DOMAIN_DISK_MODEL_LAST: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("'usb' disk must not be empty")); + _("USB disk supports only models: 'usb-storage', 'usb-bot''")); return -1; } diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c index fdb5093549..7881ccf327 100644 --- a/tests/qemuhotplugtest.c +++ b/tests/qemuhotplugtest.c @@ -746,7 +746,9 @@ mymain(void) DO_TEST_ATTACH("x86_64", "base-live", "cdrom-usb", false, true, "blockdev-add", QMP_OK, "device_add", QMP_OK, - "query-block", QMP_EMPTY_ARRAY); + "device_add", QMP_OK, + "query-block", QMP_EMPTY_ARRAY, + "qom-set", QMP_OK); DO_TEST_DETACH("x86_64", "base-live", "cdrom-usb", true, true, "device_del", QMP_OK); DO_TEST_DETACH("x86_64", "base-live", "cdrom-usb", false, false, diff --git a/tests/qemuxmlconfdata/disk-cdrom-usb-empty.x86_64-latest.abi-update.args b/tests/qemuxmlconfdata/disk-cdrom-usb-empty.x86_64-latest.abi-update.args index cebc6e66e8..44bf27e9a4 100644 --- a/tests/qemuxmlconfdata/disk-cdrom-usb-empty.x86_64-latest.abi-update.args +++ b/tests/qemuxmlconfdata/disk-cdrom-usb-empty.x86_64-latest.abi-update.args @@ -27,7 +27,8 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ -no-shutdown \ -boot strict=on \ -device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \ --device '{"driver":"usb-storage","bus":"usb.0","port":"1","id":"usb-disk1","removable":false}' \ +-device '{"driver":"usb-bot","id":"usb-disk1","bus":"usb.0","port":"1"}' \ +-device '{"driver":"scsi-cd","bus":"usb-disk1.0","scsi-id":0,"lun":0,"id":"usb-disk1-device"}' \ -audiodev '{"id":"audio1","driver":"none"}' \ -sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ -msg timestamp=on diff --git a/tests/qemuxmlconfdata/disk-usb-device-model.x86_64-latest.args b/tests/qemuxmlconfdata/disk-usb-device-model.x86_64-latest.args index 6d31319a49..f50b0d5849 100644 --- a/tests/qemuxmlconfdata/disk-usb-device-model.x86_64-latest.args +++ b/tests/qemuxmlconfdata/disk-usb-device-model.x86_64-latest.args @@ -33,9 +33,11 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ -blockdev '{"driver":"file","filename":"/tmp/img2","node-name":"libvirt-5-storage","read-only":true}' \ -device '{"driver":"usb-storage","bus":"usb.0","port":"1.1","drive":"libvirt-5-storage","id":"usb-disk1","removable":false}' \ -blockdev '{"driver":"file","filename":"/tmp/img3","node-name":"libvirt-4-storage","read-only":false}' \ --device '{"driver":"usb-storage","bus":"usb.0","port":"1.2","drive":"libvirt-4-storage","id":"usb-disk2","removable":false}' \ +-device '{"driver":"usb-bot","id":"usb-disk2","bus":"usb.0","port":"1.2"}' \ +-device '{"driver":"scsi-hd","bus":"usb-disk2.0","scsi-id":0,"lun":0,"drive":"libvirt-4-storage","id":"usb-disk2-device"}' \ -blockdev '{"driver":"file","filename":"/tmp/img4","node-name":"libvirt-3-storage","read-only":true}' \ --device '{"driver":"usb-storage","bus":"usb.0","port":"1.3","drive":"libvirt-3-storage","id":"usb-disk3","removable":false}' \ +-device '{"driver":"usb-bot","id":"usb-disk3","bus":"usb.0","port":"1.3"}' \ +-device '{"driver":"scsi-cd","bus":"usb-disk3.0","scsi-id":0,"lun":0,"drive":"libvirt-3-storage","id":"usb-disk3-device"}' \ -blockdev '{"driver":"file","filename":"/tmp/img5","node-name":"libvirt-2-storage","read-only":false}' \ -device '{"driver":"usb-storage","bus":"usb.0","port":"1.4","drive":"libvirt-2-storage","id":"usb-disk4","removable":false}' \ -blockdev '{"driver":"file","filename":"/tmp/img6","node-name":"libvirt-1-storage","read-only":true}' \ diff --git a/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.args b/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.args index 079dfe5d99..d8208d29b6 100644 --- a/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.args +++ b/tests/qemuxmlconfdata/disk-usb-device.x86_64-latest.abi-update.args @@ -32,19 +32,23 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ -blockdev '{"driver":"file","filename":"/tmp/img1","node-name":"libvirt-12-storage","read-only":false}' \ -device '{"driver":"usb-storage","bus":"usb.0","port":"1.1","drive":"libvirt-12-storage","id":"usb-disk0","bootindex":1,"removable":false}' \ -blockdev '{"driver":"file","filename":"/tmp/img2","node-name":"libvirt-11-storage","read-only":true}' \ --device '{"driver":"usb-storage","bus":"usb.0","port":"1.2","drive":"libvirt-11-storage","id":"usb-disk1","removable":false}' \ +-device '{"driver":"usb-bot","id":"usb-disk1","bus":"usb.0","port":"1.2"}' \ +-device '{"driver":"scsi-cd","bus":"usb-disk1.0","scsi-id":0,"lun":0,"drive":"libvirt-11-storage","id":"usb-disk1-device"}' \ -blockdev '{"driver":"file","filename":"/tmp/img3","node-name":"libvirt-10-storage","read-only":false}' \ -device '{"driver":"usb-storage","bus":"usb.0","port":"1.3","drive":"libvirt-10-storage","id":"usb-disk2","removable":false,"serial":"testserial1"}' \ -blockdev '{"driver":"file","filename":"/tmp/img4","node-name":"libvirt-9-storage","read-only":true}' \ --device '{"driver":"usb-storage","bus":"usb.0","port":"1.4","drive":"libvirt-9-storage","id":"usb-disk3","removable":false,"serial":"testserial2"}' \ +-device '{"driver":"usb-bot","id":"usb-disk3","serial":"testserial2","bus":"usb.0","port":"1.4"}' \ +-device '{"driver":"scsi-cd","bus":"usb-disk3.0","scsi-id":0,"lun":0,"drive":"libvirt-9-storage","id":"usb-disk3-device","serial":"testserial2"}' \ -blockdev '{"driver":"file","filename":"/tmp/img5","node-name":"libvirt-8-storage","read-only":false}' \ -device '{"driver":"usb-storage","bus":"usb.0","port":"1.5","drive":"libvirt-8-storage","id":"ua-test1","removable":false}' \ -blockdev '{"driver":"file","filename":"/tmp/img6","node-name":"libvirt-7-storage","read-only":true}' \ --device '{"driver":"usb-storage","bus":"usb.0","port":"1.6","drive":"libvirt-7-storage","id":"ua-test2","removable":false}' \ +-device '{"driver":"usb-bot","id":"ua-test2","bus":"usb.0","port":"1.6"}' \ +-device '{"driver":"scsi-cd","bus":"ua-test2.0","scsi-id":0,"lun":0,"drive":"libvirt-7-storage","id":"ua-test2-device"}' \ -blockdev '{"driver":"file","filename":"/tmp/img7","node-name":"libvirt-6-storage","read-only":false}' \ -device '{"driver":"usb-storage","bus":"usb.0","port":"1.7","drive":"libvirt-6-storage","id":"ua-test3","removable":false,"serial":"testserial3"}' \ -blockdev '{"driver":"file","filename":"/tmp/img8","node-name":"libvirt-5-storage","read-only":true}' \ --device '{"driver":"usb-storage","bus":"usb.0","port":"1.8","drive":"libvirt-5-storage","id":"ua-test4","removable":false,"serial":"testserial4"}' \ +-device '{"driver":"usb-bot","id":"ua-test4","serial":"testserial4","bus":"usb.0","port":"1.8"}' \ +-device '{"driver":"scsi-cd","bus":"ua-test4.0","scsi-id":0,"lun":0,"drive":"libvirt-5-storage","id":"ua-test4-device","serial":"testserial4"}' \ -blockdev '{"driver":"file","filename":"/tmp/img9","node-name":"libvirt-4-storage","read-only":false}' \ -device '{"driver":"usb-storage","bus":"usb.0","port":"2.1","drive":"libvirt-4-storage","id":"usb-disk8","removable":true}' \ -blockdev '{"driver":"file","filename":"/tmp/imga","node-name":"libvirt-3-storage","read-only":false}' \ -- 2.49.0

On Mon, Jun 23, 2025 at 21:59:18 +0200, Peter Krempa wrote:
From: Akihiko Odaki <akihiko.odaki@daynix.com>
usb-storage is a compound device that automatically creates a USB mass storage device and a SCSI device as its backend. Unfortunately it lacks some configuration options that are usually present with a SCSI device, and cannot represent CD-ROM in particular.
Replace usb-storage with usb-bot, which can be combined with a manually created SCSI device. libvirt will configure the SCSI device in a way identical with how QEMU does for usb-storage except that now it respects a configuration option to represent CD-ROM.
Resolves: https://gitlab.com/libvirt/libvirt/-/issues/368 Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_alias.c | 20 ++++- src/qemu/qemu_capabilities.c | 3 +- src/qemu/qemu_command.c | 86 ++++++++++++++++--- src/qemu/qemu_command.h | 5 ++ src/qemu/qemu_hotplug.c | 18 ++++ src/qemu/qemu_validate.c | 38 ++++++-- tests/qemuhotplugtest.c | 4 +- ...om-usb-empty.x86_64-latest.abi-update.args | 3 +- .../disk-usb-device-model.x86_64-latest.args | 6 +- ...k-usb-device.x86_64-latest.abi-update.args | 12 ++- 10 files changed, 167 insertions(+), 28 deletions(-) ... diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index e1ed8181e3..4f6a3d3414 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c ... @@ -811,6 +820,12 @@ qemuDomainAttachDiskGeneric(virDomainObj *vm, } }
+ if (rc == 0) { + if (disk->bus == VIR_DOMAIN_DISK_BUS_USB && + disk->model == VIR_DOMAIN_DISK_MODEL_USB_BOT) + rc = qemuMonitorSetUSBDiskAttached(priv->mon, disk->info.alias); + }
Why not just if (rc == 0 && disk->bus == ... && disk->model == ...)
+ qemuDomainObjExitMonitor(vm);
if (rc < 0) @@ -822,6 +837,9 @@ qemuDomainAttachDiskGeneric(virDomainObj *vm, if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) < 0) return -1;
+ if (busAdded) + ignore_value(qemuMonitorDelDevice(priv->mon, disk->info.alias)); + if (extensionDeviceAttached) ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &disk->info));
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 7e0e4db516..4b8d4fc692 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -3183,16 +3183,40 @@ qemuValidateDomainDeviceDefDiskFrontend(const virDomainDiskDef *disk, break;
case VIR_DOMAIN_DISK_BUS_USB: - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_USB_STORAGE)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("This QEMU doesn't support '-device usb-storage'")); + switch (disk->model) { + case VIR_DOMAIN_DISK_MODEL_DEFAULT: + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("USB disk model was not selected by selection code"));
This should only be possible if neither usb-storage nor usb-bot is supported by QEMU, shouldn't it? In that case, shouldn't the selection code itself report the error and actually be explicit about the failure?
return -1; - }
- if (disk->model == VIR_DOMAIN_DISK_MODEL_USB_STORAGE && - virStorageSourceIsEmpty(disk->src)) { + case VIR_DOMAIN_DISK_MODEL_USB_STORAGE: + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_USB_STORAGE)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("This QEMU doesn't support '-device usb-storage'")); + return -1; + } + + if (virStorageSourceIsEmpty(disk->src)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("'usb' disk must not be empty")); + return -1; + } + break; + + case VIR_DOMAIN_DISK_MODEL_USB_BOT: + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_USB_BOT)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("This QEMU doesn't support '-device usb-bot'")); + return -1; + } + break; + + case VIR_DOMAIN_DISK_MODEL_VIRTIO_TRANSITIONAL: + case VIR_DOMAIN_DISK_MODEL_VIRTIO: + case VIR_DOMAIN_DISK_MODEL_VIRTIO_NON_TRANSITIONAL: + case VIR_DOMAIN_DISK_MODEL_LAST: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("'usb' disk must not be empty")); + _("USB disk supports only models: 'usb-storage', 'usb-bot''"));
s/''/'/ And the error message looks weird to me, how about s/models/the following models/ ?
return -1; }
... Reviewed-by: Jiri Denemark <jdenemar@redhat.com>

On Tue, Jun 24, 2025 at 14:57:13 +0200, Jiri Denemark wrote:
On Mon, Jun 23, 2025 at 21:59:18 +0200, Peter Krempa wrote:
From: Akihiko Odaki <akihiko.odaki@daynix.com>
usb-storage is a compound device that automatically creates a USB mass storage device and a SCSI device as its backend. Unfortunately it lacks some configuration options that are usually present with a SCSI device, and cannot represent CD-ROM in particular.
Replace usb-storage with usb-bot, which can be combined with a manually created SCSI device. libvirt will configure the SCSI device in a way identical with how QEMU does for usb-storage except that now it respects a configuration option to represent CD-ROM.
Resolves: https://gitlab.com/libvirt/libvirt/-/issues/368 Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_alias.c | 20 ++++- src/qemu/qemu_capabilities.c | 3 +- src/qemu/qemu_command.c | 86 ++++++++++++++++--- src/qemu/qemu_command.h | 5 ++ src/qemu/qemu_hotplug.c | 18 ++++ src/qemu/qemu_validate.c | 38 ++++++-- tests/qemuhotplugtest.c | 4 +- ...om-usb-empty.x86_64-latest.abi-update.args | 3 +- .../disk-usb-device-model.x86_64-latest.args | 6 +- ...k-usb-device.x86_64-latest.abi-update.args | 12 ++- 10 files changed, 167 insertions(+), 28 deletions(-) ... diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index e1ed8181e3..4f6a3d3414 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c ... @@ -811,6 +820,12 @@ qemuDomainAttachDiskGeneric(virDomainObj *vm, } }
+ if (rc == 0) { + if (disk->bus == VIR_DOMAIN_DISK_BUS_USB && + disk->model == VIR_DOMAIN_DISK_MODEL_USB_BOT) + rc = qemuMonitorSetUSBDiskAttached(priv->mon, disk->info.alias); + }
Why not just
if (rc == 0 && disk->bus == ... && disk->model == ...)
Yeah; this was inspired by the block above that also starts with: if (rc == 0)
+ qemuDomainObjExitMonitor(vm);
if (rc < 0) @@ -822,6 +837,9 @@ qemuDomainAttachDiskGeneric(virDomainObj *vm, if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) < 0) return -1;
+ if (busAdded) + ignore_value(qemuMonitorDelDevice(priv->mon, disk->info.alias)); + if (extensionDeviceAttached) ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &disk->info));
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 7e0e4db516..4b8d4fc692 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -3183,16 +3183,40 @@ qemuValidateDomainDeviceDefDiskFrontend(const virDomainDiskDef *disk, break;
case VIR_DOMAIN_DISK_BUS_USB: - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_USB_STORAGE)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("This QEMU doesn't support '-device usb-storage'")); + switch (disk->model) { + case VIR_DOMAIN_DISK_MODEL_DEFAULT: + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("USB disk model was not selected by selection code"));
This should only be possible if neither usb-storage nor usb-bot is supported by QEMU, shouldn't it? In that case, shouldn't the selection code itself report the error and actually be explicit about the failure?
I used this as the final check that makes sure that a model was picked, as other startup code relies on the fact that it's already selected. Now the post-parse code should not do any rejection of configs here in case when e.g. the installed qemu will not have any of thos features, so this case should remain here, so that the VMs don't vanish. Although the error should probably be improved.
return -1; - }
- if (disk->model == VIR_DOMAIN_DISK_MODEL_USB_STORAGE && - virStorageSourceIsEmpty(disk->src)) { + case VIR_DOMAIN_DISK_MODEL_USB_STORAGE: + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_USB_STORAGE)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("This QEMU doesn't support '-device usb-storage'")); + return -1; + } + + if (virStorageSourceIsEmpty(disk->src)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("'usb' disk must not be empty")); + return -1; + } + break; + + case VIR_DOMAIN_DISK_MODEL_USB_BOT: + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_USB_BOT)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("This QEMU doesn't support '-device usb-bot'")); + return -1; + } + break; + + case VIR_DOMAIN_DISK_MODEL_VIRTIO_TRANSITIONAL: + case VIR_DOMAIN_DISK_MODEL_VIRTIO: + case VIR_DOMAIN_DISK_MODEL_VIRTIO_NON_TRANSITIONAL: + case VIR_DOMAIN_DISK_MODEL_LAST: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("'usb' disk must not be empty")); + _("USB disk supports only models: 'usb-storage', 'usb-bot''"));
s/''/'/ And the error message looks weird to me, how about s/models/the following models/ ?
return -1; }
...
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>

On Mon, Jun 23, 2025 at 21:59:18 +0200, Peter Krempa via Devel wrote:
From: Akihiko Odaki <akihiko.odaki@daynix.com>
usb-storage is a compound device that automatically creates a USB mass storage device and a SCSI device as its backend. Unfortunately it lacks some configuration options that are usually present with a SCSI device, and cannot represent CD-ROM in particular.
Replace usb-storage with usb-bot, which can be combined with a manually created SCSI device. libvirt will configure the SCSI device in a way identical with how QEMU does for usb-storage except that now it respects a configuration option to represent CD-ROM.
Resolves: https://gitlab.com/libvirt/libvirt/-/issues/368 Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_alias.c | 20 ++++- src/qemu/qemu_capabilities.c | 3 +- src/qemu/qemu_command.c | 86 ++++++++++++++++--- src/qemu/qemu_command.h | 5 ++ src/qemu/qemu_hotplug.c | 18 ++++ src/qemu/qemu_validate.c | 38 ++++++-- tests/qemuhotplugtest.c | 4 +- ...om-usb-empty.x86_64-latest.abi-update.args | 3 +- .../disk-usb-device-model.x86_64-latest.args | 6 +- ...k-usb-device.x86_64-latest.abi-update.args | 12 ++- 10 files changed, 167 insertions(+), 28 deletions(-)
diff --git a/src/qemu/qemu_alias.c b/src/qemu/qemu_alias.c index 9d39ebd63d..67cbddd470 100644 --- a/src/qemu/qemu_alias.c +++ b/src/qemu/qemu_alias.c @@ -268,8 +268,24 @@ qemuAssignDeviceDiskAlias(virDomainDef *def, break;
case VIR_DOMAIN_DISK_BUS_USB: - diskPriv->qomName = g_strdup_printf("/machine/peripheral/%s/%s.0/legacy[0]", - disk->info.alias, disk->info.alias); + switch (disk->model) { + case VIR_DOMAIN_DISK_MODEL_USB_STORAGE: + diskPriv->qomName = g_strdup_printf("/machine/peripheral/%s/%s.0/legacy[0]", + disk->info.alias, disk->info.alias); + break; + + case VIR_DOMAIN_DISK_MODEL_USB_BOT: + diskPriv->qomName = g_strdup_printf("/machine/peripheral/%s-disk",
I noticed that this is supposed to be "%s-device" to format the proper qom name: virsh qemu-monitor-command --pretty fedora41-mig query-block { "return": [ [...] { "io-status": "ok", "device": "", "locked": false, "removable": false, "inserted": { "iops_rd": 0, "detect_zeroes": "off", "active": true, "image": { "virtual-size": 104857600, "filename": "/tmp/img1", "format": "file", "actual-size": 104857600, "format-specific": { "type": "file", "data": {} }, "dirty-flag": false }, "iops_wr": 0, "ro": false, "node-name": "libvirt-6-storage", "backing_file_depth": 0, "drv": "file", "iops": 0, "bps_wr": 0, "write_threshold": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "cache": { "no-flush": false, "direct": false, "writeback": true }, "file": "/tmp/img1" }, "qdev": "usb-disk0-device", ^^^^^^^^^^^^^^^^ "type": "unknown" }, [...] I'll update it before pushing.
participants (3)
-
Jiri Denemark
-
Jiří Denemark
-
Peter Krempa