public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [PATCH qemu-server 0/5] small cleanup/refactor/fixes
@ 2026-10-15  7:52 Dominik Csapak
  2026-10-15  7:52 ` [PATCH qemu-server 1/5] helpers: factor out the version parts parsing Dominik Csapak
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Dominik Csapak @ 2026-10-15  7:52 UTC (permalink / raw)
  To: pve-devel

this series contains a few (more or less independent) cleanups,
refactors and a one fix (3/5).

This is a pre-requsisite for my upcoming rfc v2 of the pci-layout
changes.

While I based this on my recent hotplug v3 series [0], it should
apply cleanly to master.

0: https://lore.proxmox.com/all/20261007142145.984970-1-d.csapak@proxmox.com/

Dominik Csapak (5):
  helpers: factor out the version parts parsing
  usb: drop always-true spice_usb3 feature flag
  net: use version guard for the machine version checks of NICs
  usb: factor out the default usb bus of the tablet
  drive device: check the machine version for blockdev only once

 src/PVE/QemuServer.pm                        | 41 ++++++++------------
 src/PVE/QemuServer/DriveDevice.pm            | 14 +++----
 src/PVE/QemuServer/Helpers.pm                | 22 ++++++++++-
 src/PVE/QemuServer/USB.pm                    | 13 ++++++-
 src/test/cfg2cmd/simple-11.0-binary.conf.cmd |  2 +-
 5 files changed, 55 insertions(+), 37 deletions(-)

-- 
2.47.3





^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH qemu-server 1/5] helpers: factor out the version parts parsing
  2026-10-15  7:52 [PATCH qemu-server 0/5] small cleanup/refactor/fixes Dominik Csapak
@ 2026-10-15  7:52 ` Dominik Csapak
  2026-10-15  7:52 ` [PATCH qemu-server 2/5] usb: drop always-true spice_usb3 feature flag Dominik Csapak
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Dominik Csapak @ 2026-10-15  7:52 UTC (permalink / raw)
  To: pve-devel

this can be useful on it's own when needing to pass the individual parts
of the version to something else.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 src/PVE/QemuServer/Helpers.pm | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/src/PVE/QemuServer/Helpers.pm b/src/PVE/QemuServer/Helpers.pm
index dd17eef5..1e55ad6c 100644
--- a/src/PVE/QemuServer/Helpers.pm
+++ b/src/PVE/QemuServer/Helpers.pm
@@ -21,6 +21,7 @@ our @EXPORT_OK = qw(
     parse_number_sets
     windows_version
     get_host_arch
+    version_parts
 );
 
 my $nodename = PVE::INotify::nodename();
@@ -224,11 +225,28 @@ sub vm_running_locally {
     return instance_running_locally($pidfile);
 }
 
+# Parses a version string like X.Y.Z-pveW and returns (X, Y, Z, W) as numeric values.
+sub version_parts {
+    my ($verstr) = @_;
+
+    if ($verstr =~ m/^(\d+)\.(\d+)(?:\.(\d+))?(?:\+pve(\d+))?/) {
+        my $major = $1 + 0;
+        my $minor = $2 + 0;
+        my $patch = $3;
+        $patch += 0 if defined($patch);
+        my $pve = $4;
+        $pve += 0 if defined($pve);
+        return ($major, $minor, $patch, $pve);
+    }
+
+    return;
+}
+
 sub min_version {
     my ($verstr, $major, $minor, $pve) = @_;
 
-    if ($verstr =~ m/^(\d+)\.(\d+)(?:\.(\d+))?(?:\+pve(\d+))?/) {
-        return 1 if version_cmp($1, $major, $2, $minor, $4, $pve) >= 0;
+    if (my ($got_major, $got_minor, $got_patch, $got_pve) = version_parts($verstr)) {
+        return 1 if version_cmp($got_major, $major, $got_minor, $minor, $got_pve, $pve) >= 0;
         return 0;
     }
 
-- 
2.47.3





^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH qemu-server 2/5] usb: drop always-true spice_usb3 feature flag
  2026-10-15  7:52 [PATCH qemu-server 0/5] small cleanup/refactor/fixes Dominik Csapak
  2026-10-15  7:52 ` [PATCH qemu-server 1/5] helpers: factor out the version parts parsing Dominik Csapak
@ 2026-10-15  7:52 ` Dominik Csapak
  2026-10-15  7:52 ` [PATCH qemu-server 3/5] net: use version guard for the machine version checks of NICs Dominik Csapak
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Dominik Csapak @ 2026-10-15  7:52 UTC (permalink / raw)
  To: pve-devel

The 'spice_usb3' feature was only set for machine versions 4.0 and
newer. Since config_to_command refuses to start machines older than
5.0, the flag is always set, so a SPICE USB port with 'usb3' enabled
always ends up on the xhci controller anyway.

Drop the feature hash from get_usb_devices and check 'usb3' directly.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 src/PVE/QemuServer.pm     | 8 +-------
 src/PVE/QemuServer/USB.pm | 4 ++--
 2 files changed, 3 insertions(+), 9 deletions(-)

diff --git a/src/PVE/QemuServer.pm b/src/PVE/QemuServer.pm
index 7e5f7bbb..097c88b6 100644
--- a/src/PVE/QemuServer.pm
+++ b/src/PVE/QemuServer.pm
@@ -3325,13 +3325,7 @@ sub config_to_command {
             $vmid, $conf, $devices, $vga, $winversion, $arch, $bootorder, $dry_run,
         );
 
-    # usb devices
-    my $usb_dev_features = {};
-    $usb_dev_features->{spice_usb3} = 1 if min_version($machine_version, 4, 0);
-
-    my @usbdevices = PVE::QemuServer::USB::get_usb_devices(
-        $conf, $usb_dev_features, $bootorder, $machine_version,
-    );
+    my @usbdevices = PVE::QemuServer::USB::get_usb_devices($conf, $bootorder, $machine_version);
     push @$devices, @usbdevices if @usbdevices;
 
     # serial devices
diff --git a/src/PVE/QemuServer/USB.pm b/src/PVE/QemuServer/USB.pm
index d75507e4..bf2741f6 100644
--- a/src/PVE/QemuServer/USB.pm
+++ b/src/PVE/QemuServer/USB.pm
@@ -168,7 +168,7 @@ sub get_usb_controllers {
 }
 
 sub get_usb_devices {
-    my ($conf, $features, $bootorder, $machine_version) = @_;
+    my ($conf, $bootorder, $machine_version) = @_;
 
     my $devices = [];
 
@@ -190,7 +190,7 @@ sub get_usb_devices {
         if ($d->{host} && $d->{host} =~ m/^spice$/) {
             # usb redir support for spice
             my $bus = 'ehci';
-            $bus = 'xhci' if ($d->{usb3} && $features->{spice_usb3}) || $use_qemu_xhci;
+            $bus = 'xhci' if $d->{usb3} || $use_qemu_xhci;
 
             push @$devices, '-chardev', "spicevmc,id=usbredirchardev$i,name=usbredir";
             push @$devices, '-device', print_spice_usbdevice($i, $bus, $port);
-- 
2.47.3





^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH qemu-server 3/5] net: use version guard for the machine version checks of NICs
  2026-10-15  7:52 [PATCH qemu-server 0/5] small cleanup/refactor/fixes Dominik Csapak
  2026-10-15  7:52 ` [PATCH qemu-server 1/5] helpers: factor out the version parts parsing Dominik Csapak
  2026-10-15  7:52 ` [PATCH qemu-server 2/5] usb: drop always-true spice_usb3 feature flag Dominik Csapak
@ 2026-10-15  7:52 ` Dominik Csapak
  2026-10-15  7:52 ` [PATCH qemu-server 4/5] usb: factor out the default usb bus of the tablet Dominik Csapak
  2026-10-15  7:52 ` [PATCH qemu-server 5/5] drive device: check the machine version for blockdev only once Dominik Csapak
  4 siblings, 0 replies; 6+ messages in thread
From: Dominik Csapak @ 2026-10-15  7:52 UTC (permalink / raw)
  To: pve-devel

Since commit 41734ab8 ("fix #7627: net: virtio: disable host_tunnel
feature again with 11.0+pve1"), VirtIO NICs get 'host_tunnel=off' with
machine version 11.0+pve1 and newer. The check uses min_version, which
does not record the required PVE machine revision.

So a guest started with an unversioned machine type on QEMU 11.0 got
'host_tunnel=off', but its machine type was recorded as '+pve0'.
Migration, snapshots and hibernation then use that recorded machine
type, for which the NIC is generated without 'host_tunnel=off'.

The checks in print_netdevice_full could not use the version guard,
since the function is also called for hotplug, where there is none.
The 'host_mtu' differentiation for 10.0+pve1 works around that with a
separate guard call in config_to_command.

Instead, pass the version guard to print_netdevice_full and use it for
all of its machine version checks, so the required revision gets
recorded where the feature is decided. For hotplug, pass a stub
around min_version, as the machine is already running there.

The separate guard call for 'host_mtu' is kept, as it also records
'+pve1' for NICs that skip the 'host_mtu' check, for example when it
is omitted for migration compatibility.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 src/PVE/QemuServer.pm                        | 23 ++++++++++++--------
 src/test/cfg2cmd/simple-11.0-binary.conf.cmd |  2 +-
 2 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/src/PVE/QemuServer.pm b/src/PVE/QemuServer.pm
index 097c88b6..39096199 100644
--- a/src/PVE/QemuServer.pm
+++ b/src/PVE/QemuServer.pm
@@ -1327,7 +1327,7 @@ sub print_netdevice_full {
         $netid,
         $use_old_bios_files,
         $arch,
-        $machine_version,
+        $version_guard, # checks the machine version and records the required +pveX revision
         $host_mtu_migration, # force this value for host_mtu, 0 means force absence of param
     ) = @_;
 
@@ -1343,12 +1343,12 @@ sub print_netdevice_full {
         # and out of each queue plus one config interrupt and control vector queue
         my $vectors = $net->{queues} * 2 + 2;
         $tmpstr .= ",vectors=$vectors,mq=on";
-        if (min_version($machine_version, 7, 1)) {
+        if ($version_guard->(7, 1)) {
             $tmpstr .= ",packed=on";
         }
     }
 
-    if (min_version($machine_version, 7, 1) && $net->{model} eq 'virtio') {
+    if ($version_guard->(7, 1) && $net->{model} eq 'virtio') {
         $tmpstr .= ",rx_queue_size=1024,tx_queue_size=256";
     }
 
@@ -1378,7 +1378,7 @@ sub print_netdevice_full {
                 . " that the bridge is configured as desired.\n";
         }
 
-        if (min_version($machine_version, 10, 0, 1) || $host_mtu_migration) {
+        if ($version_guard->(10, 0, 1) || $host_mtu_migration) {
             # Always add host_mtu for migration compatibility, because the presence of host_mtu
             # means that the virtual hardware is generated differently (at least for i440fx)
             $tmpstr .= ",host_mtu=$mtu";
@@ -1390,7 +1390,7 @@ sub print_netdevice_full {
         if ($migration_skip_host_mtu) {
             # When the machine version is less than 10.0+pve1 and the MTU is 1500, not having the
             # host_mtu parameter is fully expected. Only log when not expected to avoid confusion.
-            if (min_version($machine_version, 10, 0, 1) || $mtu != 1500) {
+            if ($version_guard->(10, 0, 1) || $mtu != 1500) {
                 log_warn(
                     "$msg_prefix, not used on the source side according to migration parameters");
             }
@@ -1423,10 +1423,10 @@ sub print_netdevice_full {
     # include the fix "virtio_net: do not allow tunnel csum offload for non GSO packets" with a
     # prominent notice in the upgrade guide.
     if ($net->{model} eq 'virtio') {
-        if (min_version($machine_version, 11, 0, 1)) {
+        if ($version_guard->(11, 0, 1)) {
             # Turn off if not explicitly enabled starting with 11.0+pve1
             $tmpstr .= ",host_tunnel=off" if !$net->{'host-tunnel'};
-        } elsif (min_version($machine_version, 10, 2)) {
+        } elsif ($version_guard->(10, 2)) {
             # The feature was introduced in QEMU 10.2. Turn off if explicitly disabled.
             $tmpstr .= ",host_tunnel=off"
                 if defined($net->{'host-tunnel'}) && !$net->{'host-tunnel'};
@@ -3705,7 +3705,7 @@ sub config_to_command {
             $netname,
             $use_old_bios_files,
             $arch,
-            $machine_version,
+            $version_guard,
             $nets_host_mtu->{$netname},
         );
 
@@ -3949,8 +3949,13 @@ sub vm_deviceplug {
         my $use_old_bios_files = undef;
         ($use_old_bios_files, $machine_type) = qemu_use_old_bios_files($machine_type);
 
+        # the machine is already running, so there is no required version to record
+        my $version_guard = sub {
+            my ($major, $minor, $pve) = @_;
+            return min_version($machine_version, $major, $minor, $pve);
+        };
         my $netdevicefull = print_netdevice_full(
-            $vmid, $conf, $device, $deviceid, $use_old_bios_files, $arch, $machine_version,
+            $vmid, $conf, $device, $deviceid, $use_old_bios_files, $arch, $version_guard,
         );
         qemu_deviceadd($vmid, $netdevicefull);
         eval {
diff --git a/src/test/cfg2cmd/simple-11.0-binary.conf.cmd b/src/test/cfg2cmd/simple-11.0-binary.conf.cmd
index 924d8041..5d01263e 100644
--- a/src/test/cfg2cmd/simple-11.0-binary.conf.cmd
+++ b/src/test/cfg2cmd/simple-11.0-binary.conf.cmd
@@ -32,4 +32,4 @@
   -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,device_id=drive-scsi0,bootindex=100,write-cache=on' \
   -netdev 'type=tap,id=net0,ifname=tap8006i0,script=/usr/libexec/qemu-server/pve-bridge,downscript=/usr/libexec/qemu-server/pve-bridgedown,vhost=on' \
   -device 'virtio-net-pci,mac=A2:C0:43:77:08:A0,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256,bootindex=300,host_mtu=1500,host_tunnel=off' \
-  -machine 'hpet=off,type=pc+pve0'
+  -machine 'hpet=off,type=pc+pve1'
-- 
2.47.3





^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH qemu-server 4/5] usb: factor out the default usb bus of the tablet
  2026-10-15  7:52 [PATCH qemu-server 0/5] small cleanup/refactor/fixes Dominik Csapak
                   ` (2 preceding siblings ...)
  2026-10-15  7:52 ` [PATCH qemu-server 3/5] net: use version guard for the machine version checks of NICs Dominik Csapak
@ 2026-10-15  7:52 ` Dominik Csapak
  2026-10-15  7:52 ` [PATCH qemu-server 5/5] drive device: check the machine version for blockdev only once Dominik Csapak
  4 siblings, 0 replies; 6+ messages in thread
From: Dominik Csapak @ 2026-10-15  7:52 UTC (permalink / raw)
  To: pve-devel

The bus of the tablet depends on which USB controllers exist, which is
decided in get_usb_controllers. Move the choice next to it, so both can
be adapted together when the controllers change.

No functional change intended.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 src/PVE/QemuServer.pm     | 10 +---------
 src/PVE/QemuServer/USB.pm |  9 +++++++++
 2 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/src/PVE/QemuServer.pm b/src/PVE/QemuServer.pm
index 39096199..4a67d3a0 100644
--- a/src/PVE/QemuServer.pm
+++ b/src/PVE/QemuServer.pm
@@ -1182,15 +1182,7 @@ sub assert_clipboard_config {
 sub print_tabletdevice_full {
     my ($conf, $arch) = @_;
 
-    my $q35 = PVE::QemuServer::Machine::machine_type_is_q35($conf);
-
-    # we use uhci for old VMs because tablet driver was buggy in older qemu
-    my $usbbus;
-    if ($q35 || $arch eq 'aarch64') {
-        $usbbus = 'ehci';
-    } else {
-        $usbbus = 'uhci';
-    }
+    my $usbbus = PVE::QemuServer::USB::get_default_usb_bus($conf, $arch);
 
     return "usb-tablet,id=tablet,bus=$usbbus.0,port=1";
 }
diff --git a/src/PVE/QemuServer/USB.pm b/src/PVE/QemuServer/USB.pm
index bf2741f6..0ab43614 100644
--- a/src/PVE/QemuServer/USB.pm
+++ b/src/PVE/QemuServer/USB.pm
@@ -119,6 +119,15 @@ my sub assert_usb_index_is_useable {
     return undef;
 }
 
+sub get_default_usb_bus {
+    my ($conf, $arch) = @_;
+
+    my $q35 = PVE::QemuServer::Machine::machine_type_is_q35($conf);
+
+    # we use uhci for old VMs because tablet driver was buggy in older qemu
+    return $q35 || $arch eq 'aarch64' ? 'ehci' : 'uhci';
+}
+
 sub get_usb_controllers {
     my ($conf, $arch, $machine_version) = @_;
 
-- 
2.47.3





^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH qemu-server 5/5] drive device: check the machine version for blockdev only once
  2026-10-15  7:52 [PATCH qemu-server 0/5] small cleanup/refactor/fixes Dominik Csapak
                   ` (3 preceding siblings ...)
  2026-10-15  7:52 ` [PATCH qemu-server 4/5] usb: factor out the default usb bus of the tablet Dominik Csapak
@ 2026-10-15  7:52 ` Dominik Csapak
  4 siblings, 0 replies; 6+ messages in thread
From: Dominik Csapak @ 2026-10-15  7:52 UTC (permalink / raw)
  To: pve-devel

print_drivedevice_full checks for machine version 10.0 in five places
to decide whether the drive uses -blockdev. Do the check once, so the
places read as what they decide and only one call needs adapting when
the source of the machine version changes.

No functional change intended.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
 src/PVE/QemuServer/DriveDevice.pm | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/PVE/QemuServer/DriveDevice.pm b/src/PVE/QemuServer/DriveDevice.pm
index 8974bae0..621fcc2b 100644
--- a/src/PVE/QemuServer/DriveDevice.pm
+++ b/src/PVE/QemuServer/DriveDevice.pm
@@ -78,12 +78,14 @@ sub print_drivedevice_full {
         PVE::QemuServer::Machine::extract_version($machine_type, kvm_user_version());
     my $has_write_cache = 1; # whether the device has a 'write-cache' option
 
+    my $use_blockdev = min_version($machine_version, 10, 0);
+
     my $drive_id = PVE::QemuServer::Drive::get_drive_id($drive);
     if ($drive->{interface} eq 'virtio') {
         my $pciaddr = print_pci_addr("$drive_id", $arch);
         $device = 'virtio-blk-pci';
         # for the switch to -blockdev, there is no blockdev for 'none'
-        if (!min_version($machine_version, 10, 0) || $drive->{file} ne 'none') {
+        if (!$use_blockdev || $drive->{file} ne 'none') {
             $device .= ",drive=drive-$drive_id";
         }
         $device .= ",id=${drive_id}${pciaddr}";
@@ -104,16 +106,14 @@ sub print_drivedevice_full {
                 . ",lun=$drive->{index}";
         }
         # for the switch to -blockdev, there is no blockdev for 'none'
-        if (!min_version($machine_version, 10, 0) || $drive->{file} ne 'none') {
+        if (!$use_blockdev || $drive->{file} ne 'none') {
             $device .= ",drive=drive-$drive_id";
         }
         $device .= ",id=$drive_id";
 
         # For the switch to -blockdev, the SCSI device ID needs to be explicitly specified. Note
         # that only ide-cd and ide-hd have a 'device_id' option.
-        if (
-            min_version($machine_version, 10, 0) && ($device_type eq 'cd' || $device_type eq 'hd')
-        ) {
+        if ($use_blockdev && ($device_type eq 'cd' || $device_type eq 'hd')) {
             $device .= ",device_id=drive-${drive_id}";
         }
 
@@ -169,7 +169,7 @@ sub print_drivedevice_full {
         } else {
             $device .= ",bus=ahci$controller.$unit";
         }
-        if (!min_version($machine_version, 10, 0) || $drive->{file} ne 'none') {
+        if (!$use_blockdev || $drive->{file} ne 'none') {
             $device .= ",drive=drive-$drive_id";
         }
         $device .= ",id=$drive_id";
@@ -198,7 +198,7 @@ sub print_drivedevice_full {
         $device .= ",serial=$serial";
     }
 
-    if (min_version($machine_version, 10, 0)) { # for the switch to -blockdev
+    if ($use_blockdev) { # for the switch to -blockdev
         if (!drive_is_cdrom($drive) && $has_write_cache) {
             my $write_cache = 'on';
             if (my $cache = $drive->{cache}) {
-- 
2.47.3





^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-10-15  7:55 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-15  7:52 [PATCH qemu-server 0/5] small cleanup/refactor/fixes Dominik Csapak
2026-10-15  7:52 ` [PATCH qemu-server 1/5] helpers: factor out the version parts parsing Dominik Csapak
2026-10-15  7:52 ` [PATCH qemu-server 2/5] usb: drop always-true spice_usb3 feature flag Dominik Csapak
2026-10-15  7:52 ` [PATCH qemu-server 3/5] net: use version guard for the machine version checks of NICs Dominik Csapak
2026-10-15  7:52 ` [PATCH qemu-server 4/5] usb: factor out the default usb bus of the tablet Dominik Csapak
2026-10-15  7:52 ` [PATCH qemu-server 5/5] drive device: check the machine version for blockdev only once Dominik Csapak

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal