From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id 4FBAF1FF183 for ; Wed, 2 Jul 2025 16:48:44 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 68E4B1DA28; Wed, 2 Jul 2025 16:49:13 +0200 (CEST) To: pve-devel@lists.proxmox.com Date: Wed, 2 Jul 2025 16:48:51 +0200 In-Reply-To: <20250702144900.3963405-1-alexandre.derumier@groupe-cyllene.com> References: <20250702144900.3963405-1-alexandre.derumier@groupe-cyllene.com> MIME-Version: 1.0 Message-ID: List-Id: Proxmox VE development discussion List-Post: From: Alexandre Derumier via pve-devel Precedence: list Cc: Alexandre Derumier X-Mailman-Version: 2.1.29 X-BeenThere: pve-devel@lists.proxmox.com List-Subscribe: , List-Unsubscribe: , List-Archive: Reply-To: Proxmox VE development discussion List-Help: Subject: [pve-devel] [PATCH qemu-server 01/10] introduce DriveDevice module Content-Type: multipart/mixed; boundary="===============4835492017450712612==" Errors-To: pve-devel-bounces@lists.proxmox.com Sender: "pve-devel" --===============4835492017450712612== Content-Type: message/rfc822 Content-Disposition: inline Return-Path: X-Original-To: pve-devel@lists.proxmox.com Delivered-To: pve-devel@lists.proxmox.com Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 6524CD3C7C for ; Wed, 2 Jul 2025 16:49:11 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 481321D935 for ; Wed, 2 Jul 2025 16:49:11 +0200 (CEST) Received: from bastiontest.odiso.net (unknown [IPv6:2a0a:1580:2000:6700::14]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS for ; Wed, 2 Jul 2025 16:49:08 +0200 (CEST) Received: from formationkvm1.odiso.net (unknown [10.11.201.57]) by bastiontest.odiso.net (Postfix) with ESMTP id 5BA00860F13; Wed, 2 Jul 2025 16:49:01 +0200 (CEST) Received: by formationkvm1.odiso.net (Postfix, from userid 0) id 4BA34112B913; Wed, 2 Jul 2025 16:49:01 +0200 (CEST) From: Alexandre Derumier To: pve-devel@lists.proxmox.com Subject: [PATCH qemu-server 01/10] introduce DriveDevice module Date: Wed, 2 Jul 2025 16:48:51 +0200 Message-Id: <20250702144900.3963405-2-alexandre.derumier@groupe-cyllene.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250702144900.3963405-1-alexandre.derumier@groupe-cyllene.com> References: <20250702144900.3963405-1-alexandre.derumier@groupe-cyllene.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.105 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_NONE 0.1 DMARC none policy HEADER_FROM_DIFFERENT_DOMAINS 0.017 From and EnvelopeFrom 2nd level mail domains are different KAM_DMARC_NONE 0.25 DKIM has Failed or SPF has failed on the message and the domain has no DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment KAM_LAZY_DOMAIN_SECURITY 1 Sending domain does not have any anti-forgery methods RDNS_NONE 0.793 Delivered to internal network by a host with no rDNS SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_NONE 0.001 SPF: sender does not publish an SPF Record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [cpuconfig.pm,machine.pm,drive.pm,helpers.pm,cloudinit.pm,agent.pm,qemuserver.pm,importdisk.pm,drivedevice.pm] and move print_drivedevice_full Signed-off-by: Alexandre Derumier --- src/PVE/QemuServer.pm | 144 +------------------------- src/PVE/QemuServer/DriveDevice.pm | 163 ++++++++++++++++++++++++++++++ src/PVE/QemuServer/Makefile | 1 + 3 files changed, 165 insertions(+), 143 deletions(-) create mode 100644 src/PVE/QemuServer/DriveDevice.pm diff --git a/src/PVE/QemuServer.pm b/src/PVE/QemuServer.pm index 50352e82..eed56b0d 100644 --- a/src/PVE/QemuServer.pm +++ b/src/PVE/QemuServer.pm @@ -73,6 +73,7 @@ use PVE::QemuServer::Drive qw( print_drive storage_allows_io_uring_default ); +use PVE::QemuServer::DriveDevice qw(print_drivedevice_full scsihw_infos); use PVE::QemuServer::Machine; use PVE::QemuServer::Memory qw(get_current_memory); use PVE::QemuServer::MetaInfo; @@ -1197,127 +1198,6 @@ sub print_keyboarddevice_full { return "usb-kbd,id=keyboard,bus=ehci.0,port=2"; } -sub print_drivedevice_full { - my ($storecfg, $conf, $vmid, $drive, $bridges, $arch, $machine_type) = @_; - - my $device = ''; - my $maxdev = 0; - - my $machine_version = extract_version($machine_type, kvm_user_version()); - - my $drive_id = PVE::QemuServer::Drive::get_drive_id($drive); - if ($drive->{interface} eq 'virtio') { - my $pciaddr = print_pci_addr("$drive_id", $bridges, $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') { - $device .= ",drive=drive-$drive_id"; - } - $device .= ",id=${drive_id}${pciaddr}"; - $device .= ",iothread=iothread-$drive_id" if $drive->{iothread}; - } elsif ($drive->{interface} eq 'scsi') { - - my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $drive); - my $unit = $drive->{index} % $maxdev; - - my $device_type = - PVE::QemuServer::Drive::get_scsi_device_type($drive, $storecfg, $machine_version); - - if (!$conf->{scsihw} || $conf->{scsihw} =~ m/^lsi/ || $conf->{scsihw} eq 'pvscsi') { - $device = "scsi-$device_type,bus=$controller_prefix$controller.0,scsi-id=$unit"; - } else { - $device = "scsi-$device_type,bus=$controller_prefix$controller.0,channel=0,scsi-id=0" - . ",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') { - $device .= ",drive=drive-$drive_id"; - } - $device .= ",id=$drive_id"; - - if ($drive->{ssd} && ($device_type eq 'block' || $device_type eq 'hd')) { - $device .= ",rotation_rate=1"; - } - $device .= ",wwn=$drive->{wwn}" if $drive->{wwn}; - - # only scsi-hd and scsi-cd support passing vendor and product information - if ($device_type eq 'hd' || $device_type eq 'cd') { - if (my $vendor = $drive->{vendor}) { - $device .= ",vendor=$vendor"; - } - if (my $product = $drive->{product}) { - $device .= ",product=$product"; - } - } - - } elsif ($drive->{interface} eq 'ide' || $drive->{interface} eq 'sata') { - my $maxdev = ($drive->{interface} eq 'sata') ? $PVE::QemuServer::Drive::MAX_SATA_DISKS : 2; - my $controller = int($drive->{index} / $maxdev); - my $unit = $drive->{index} % $maxdev; - - # machine type q35 only supports unit=0 for IDE rather than 2 units. This wasn't handled - # correctly before, so e.g. index=2 was mapped to controller=1,unit=0 rather than - # controller=2,unit=0. Note that odd indices never worked, as they would be mapped to - # unit=1, so to keep backwards compat for migration, it suffices to keep even ones as they - # were before. Move odd ones up by 2 where they don't clash. - if (PVE::QemuServer::Machine::machine_type_is_q35($conf) && $drive->{interface} eq 'ide') { - $controller += 2 * ($unit % 2); - $unit = 0; - } - - my $device_type = ($drive->{media} && $drive->{media} eq 'cdrom') ? "cd" : "hd"; - - $device = "ide-$device_type"; - if ($drive->{interface} eq 'ide') { - $device .= ",bus=ide.$controller,unit=$unit"; - } else { - $device .= ",bus=ahci$controller.$unit"; - } - if (!min_version($machine_version, 10, 0) || $drive->{file} ne 'none') { - $device .= ",drive=drive-$drive_id"; - } - $device .= ",id=$drive_id"; - - if ($device_type eq 'hd') { - if (my $model = $drive->{model}) { - $model = URI::Escape::uri_unescape($model); - $device .= ",model=$model"; - } - if ($drive->{ssd}) { - $device .= ",rotation_rate=1"; - } - } - $device .= ",wwn=$drive->{wwn}" if $drive->{wwn}; - } elsif ($drive->{interface} eq 'usb') { - die "implement me"; - # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0 - } else { - die "unsupported interface type"; - } - - $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex}; - - if (my $serial = $drive->{serial}) { - $serial = URI::Escape::uri_unescape($serial); - $device .= ",serial=$serial"; - } - - if (min_version($machine_version, 10, 0)) { # for the switch to -blockdev - if (!drive_is_cdrom($drive)) { - my $write_cache = 'on'; - if (my $cache = $drive->{cache}) { - $write_cache = 'off' if $cache eq 'writethrough' || $cache eq 'directsync'; - } - $device .= ",write-cache=$write_cache"; - } - for my $o (qw(rerror werror)) { - $device .= ",$o=$drive->{$o}" if defined($drive->{$o}); - } - } - - return $device; -} - sub print_drive_commandline_full { my ($storecfg, $vmid, $drive, $live_restore_name) = @_; @@ -7875,28 +7755,6 @@ sub vm_iothreads_list { return $iothreads; } -sub scsihw_infos { - my ($conf, $drive) = @_; - - my $maxdev = 0; - - if (!$conf->{scsihw} || ($conf->{scsihw} =~ m/^lsi/)) { - $maxdev = 7; - } elsif ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) { - $maxdev = 1; - } else { - $maxdev = 256; - } - - my $controller = int($drive->{index} / $maxdev); - my $controller_prefix = - ($conf->{scsihw} && $conf->{scsihw} eq 'virtio-scsi-single') - ? "virtioscsi" - : "scsihw"; - - return ($maxdev, $controller, $controller_prefix); -} - sub resolve_dst_disk_format { my ($storecfg, $storeid, $src_volid, $format) = @_; diff --git a/src/PVE/QemuServer/DriveDevice.pm b/src/PVE/QemuServer/DriveDevice.pm new file mode 100644 index 00000000..764afc93 --- /dev/null +++ b/src/PVE/QemuServer/DriveDevice.pm @@ -0,0 +1,163 @@ +package PVE::QemuServer::DriveDevice; + +use strict; +use warnings; + +use URI::Escape; + +use PVE::QemuServer::Drive qw (drive_is_cdrom); +use PVE::QemuServer::Helpers qw(kvm_user_version min_version); +use PVE::QemuServer::Machine; +use PVE::QemuServer::PCI qw(print_pci_addr); + +use base qw(Exporter); + +our @EXPORT_OK = qw( + print_drivedevice_full + scsihw_infos +); + +sub scsihw_infos { + my ($conf, $drive) = @_; + + my $maxdev = 0; + + if (!$conf->{scsihw} || ($conf->{scsihw} =~ m/^lsi/)) { + $maxdev = 7; + } elsif ($conf->{scsihw} && ($conf->{scsihw} eq 'virtio-scsi-single')) { + $maxdev = 1; + } else { + $maxdev = 256; + } + + my $controller = int($drive->{index} / $maxdev); + my $controller_prefix = + ($conf->{scsihw} && $conf->{scsihw} eq 'virtio-scsi-single') + ? "virtioscsi" + : "scsihw"; + + return ($maxdev, $controller, $controller_prefix); +} + +sub print_drivedevice_full { + my ($storecfg, $conf, $vmid, $drive, $bridges, $arch, $machine_type) = @_; + + my $device = ''; + my $maxdev = 0; + + my $machine_version = PVE::QemuServer::Machine::extract_version($machine_type, kvm_user_version()); + + my $drive_id = PVE::QemuServer::Drive::get_drive_id($drive); + if ($drive->{interface} eq 'virtio') { + my $pciaddr = print_pci_addr("$drive_id", $bridges, $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') { + $device .= ",drive=drive-$drive_id"; + } + $device .= ",id=${drive_id}${pciaddr}"; + $device .= ",iothread=iothread-$drive_id" if $drive->{iothread}; + } elsif ($drive->{interface} eq 'scsi') { + + my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $drive); + my $unit = $drive->{index} % $maxdev; + + my $device_type = + PVE::QemuServer::Drive::get_scsi_device_type($drive, $storecfg, $machine_version); + + if (!$conf->{scsihw} || $conf->{scsihw} =~ m/^lsi/ || $conf->{scsihw} eq 'pvscsi') { + $device = "scsi-$device_type,bus=$controller_prefix$controller.0,scsi-id=$unit"; + } else { + $device = "scsi-$device_type,bus=$controller_prefix$controller.0,channel=0,scsi-id=0" + . ",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') { + $device .= ",drive=drive-$drive_id"; + } + $device .= ",id=$drive_id"; + + if ($drive->{ssd} && ($device_type eq 'block' || $device_type eq 'hd')) { + $device .= ",rotation_rate=1"; + } + $device .= ",wwn=$drive->{wwn}" if $drive->{wwn}; + + # only scsi-hd and scsi-cd support passing vendor and product information + if ($device_type eq 'hd' || $device_type eq 'cd') { + if (my $vendor = $drive->{vendor}) { + $device .= ",vendor=$vendor"; + } + if (my $product = $drive->{product}) { + $device .= ",product=$product"; + } + } + + } elsif ($drive->{interface} eq 'ide' || $drive->{interface} eq 'sata') { + my $maxdev = ($drive->{interface} eq 'sata') ? $PVE::QemuServer::Drive::MAX_SATA_DISKS : 2; + my $controller = int($drive->{index} / $maxdev); + my $unit = $drive->{index} % $maxdev; + + # machine type q35 only supports unit=0 for IDE rather than 2 units. This wasn't handled + # correctly before, so e.g. index=2 was mapped to controller=1,unit=0 rather than + # controller=2,unit=0. Note that odd indices never worked, as they would be mapped to + # unit=1, so to keep backwards compat for migration, it suffices to keep even ones as they + # were before. Move odd ones up by 2 where they don't clash. + if (PVE::QemuServer::Machine::machine_type_is_q35($conf) && $drive->{interface} eq 'ide') { + $controller += 2 * ($unit % 2); + $unit = 0; + } + + my $device_type = ($drive->{media} && $drive->{media} eq 'cdrom') ? "cd" : "hd"; + + $device = "ide-$device_type"; + if ($drive->{interface} eq 'ide') { + $device .= ",bus=ide.$controller,unit=$unit"; + } else { + $device .= ",bus=ahci$controller.$unit"; + } + if (!min_version($machine_version, 10, 0) || $drive->{file} ne 'none') { + $device .= ",drive=drive-$drive_id"; + } + $device .= ",id=$drive_id"; + + if ($device_type eq 'hd') { + if (my $model = $drive->{model}) { + $model = URI::Escape::uri_unescape($model); + $device .= ",model=$model"; + } + if ($drive->{ssd}) { + $device .= ",rotation_rate=1"; + } + } + $device .= ",wwn=$drive->{wwn}" if $drive->{wwn}; + } elsif ($drive->{interface} eq 'usb') { + die "implement me"; + # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0 + } else { + die "unsupported interface type"; + } + + $device .= ",bootindex=$drive->{bootindex}" if $drive->{bootindex}; + + if (my $serial = $drive->{serial}) { + $serial = URI::Escape::uri_unescape($serial); + $device .= ",serial=$serial"; + } + + if (min_version($machine_version, 10, 0)) { # for the switch to -blockdev + if (!drive_is_cdrom($drive)) { + my $write_cache = 'on'; + if (my $cache = $drive->{cache}) { + $write_cache = 'off' if $cache eq 'writethrough' || $cache eq 'directsync'; + } + $device .= ",write-cache=$write_cache"; + } + for my $o (qw(rerror werror)) { + $device .= ",$o=$drive->{$o}" if defined($drive->{$o}); + } + } + + return $device; +} + +1; diff --git a/src/PVE/QemuServer/Makefile b/src/PVE/QemuServer/Makefile index ca30a0ad..150f2229 100644 --- a/src/PVE/QemuServer/Makefile +++ b/src/PVE/QemuServer/Makefile @@ -9,6 +9,7 @@ SOURCES=Agent.pm \ Cloudinit.pm \ CPUConfig.pm \ Drive.pm \ + DriveDevice.pm \ Helpers.pm \ ImportDisk.pm \ Machine.pm \ -- 2.39.5 --===============4835492017450712612== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel --===============4835492017450712612==--