From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [45.144.208.40]) by lore.proxmox.com (Postfix) with ESMTPS id 83A6A1FF0B7 for ; Fri, 30 Oct 2026 11:11:57 +0100 (CET) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id ABB6C214D0; Fri, 30 Oct 2026 11:11:40 +0100 (CET) From: Dominik Csapak To: pve-devel@lists.proxmox.com Subject: [PATCH qemu-server v5 1/4] hotplug: scsi: only keep controller if a disk on it is still present Date: Fri, 30 Oct 2026 11:04:40 +0100 Message-ID: <20261030101134.2090350-2-d.csapak@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20261030101134.2090350-1-d.csapak@proxmox.com> References: <20261030101134.2090350-1-d.csapak@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.344 Adjusted score from AWL reputation of From: address DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: W5FKOBYXPXJIPCSU6ORORO6L4UY6PJ4N X-Message-ID-Hash: W5FKOBYXPXJIPCSU6ORORO6L4UY6PJ4N X-MailFrom: d.csapak@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: The check whether a non-single SCSI controller is still in use compared the disk index against (maxdev - 1) * (controller + 1). For LSI (7 disks per controller), this ignores the last slot of the first controller for example, and treats any disk on a lower controller as user of the higher ones. So unplugging scsi0 with only scsi6 left unplugged the controller that scsi6 is still attached to, while unplugging scsi7 left the then unused second controller behind. Use scsihw_infos() to determine the controller of each remaining disk, like when plugging them, and only keep the controller if one of them is on it. Also don't rely on the drive being in the config, since on hotplug cleanup this does not have to be the case. This combines the index extraction with the check for 'scsi'. The added regression tests would have failed without the code change. Signed-off-by: Dominik Csapak --- src/PVE/QemuServer.pm | 13 ++++--------- src/test/hotplug/disk-remove-lsi-last-slot.conf | 16 ++++++++++++++++ .../disk-remove-lsi-last-slot.conf.expected | 3 +++ .../disk-remove-lsi-second-controller.conf | 16 ++++++++++++++++ ...sk-remove-lsi-second-controller.conf.expected | 4 ++++ 5 files changed, 43 insertions(+), 9 deletions(-) create mode 100644 src/test/hotplug/disk-remove-lsi-last-slot.conf create mode 100644 src/test/hotplug/disk-remove-lsi-last-slot.conf.expected create mode 100644 src/test/hotplug/disk-remove-lsi-second-controller.conf create mode 100644 src/test/hotplug/disk-remove-lsi-second-controller.conf.expected diff --git a/src/PVE/QemuServer.pm b/src/PVE/QemuServer.pm index b4a1a38d..6ac3c685 100644 --- a/src/PVE/QemuServer.pm +++ b/src/PVE/QemuServer.pm @@ -4144,15 +4144,10 @@ sub qemu_deletescsihw { my $devices_list = vm_devices_list($vmid); foreach my $opt (keys %{$devices_list}) { - if (is_valid_drivename($opt)) { - my $drive = parse_drive($opt, $conf->{$opt}); - if ( - $drive->{interface} eq 'scsi' - && $drive->{index} < (($maxdev - 1) * ($controller + 1)) - ) { - return 1; - } - } + next if $opt !~ m/^scsi(\d+)$/; + my $index = $1; + my (undef, $drive_controller) = scsihw_infos($conf->{scsihw}, $index); + return 1 if $drive_controller == $controller; } my $scsihwid = "scsihw$controller"; diff --git a/src/test/hotplug/disk-remove-lsi-last-slot.conf b/src/test/hotplug/disk-remove-lsi-last-slot.conf new file mode 100644 index 00000000..aa50098b --- /dev/null +++ b/src/test/hotplug/disk-remove-lsi-last-slot.conf @@ -0,0 +1,16 @@ +# TEST: hot-unplug a SCSI disk keeps the LSI controller if a disk in its last slot still uses it +bootdisk: scsi6 +cores: 2 +machine: pc-i440fx-10.1 +memory: 2048 +name: hotplug +net0: virtio=A2:C0:43:77:08:A0,bridge=vmbr0 +ostype: l26 +scsi0: local:8006/vm-8006-disk-0.qcow2,size=32G +scsi6: local:8006/vm-8006-disk-1.qcow2,size=32G +smbios1: uuid=7b10d7af-b932-4c66-b2c3-3996152ec465 +sockets: 1 +vmgenid: c773c261-d800-4348-9f5d-167fadd53cf8 + +[PENDING] +delete: scsi0 diff --git a/src/test/hotplug/disk-remove-lsi-last-slot.conf.expected b/src/test/hotplug/disk-remove-lsi-last-slot.conf.expected new file mode 100644 index 00000000..e24d5479 --- /dev/null +++ b/src/test/hotplug/disk-remove-lsi-last-slot.conf.expected @@ -0,0 +1,3 @@ +hmp device_del scsi0 +qmp blockdev-del {"node-name":"drive-scsi0"} +qmp object-del {"id":"throttle-drive-scsi0"} diff --git a/src/test/hotplug/disk-remove-lsi-second-controller.conf b/src/test/hotplug/disk-remove-lsi-second-controller.conf new file mode 100644 index 00000000..fc32cda6 --- /dev/null +++ b/src/test/hotplug/disk-remove-lsi-second-controller.conf @@ -0,0 +1,16 @@ +# TEST: hot-unplug the last SCSI disk of the second LSI controller also removes that controller +bootdisk: scsi0 +cores: 2 +machine: pc-i440fx-10.1 +memory: 2048 +name: hotplug +net0: virtio=A2:C0:43:77:08:A0,bridge=vmbr0 +ostype: l26 +scsi0: local:8006/vm-8006-disk-0.qcow2,size=32G +scsi7: local:8006/vm-8006-disk-1.qcow2,size=32G +smbios1: uuid=7b10d7af-b932-4c66-b2c3-3996152ec465 +sockets: 1 +vmgenid: c773c261-d800-4348-9f5d-167fadd53cf8 + +[PENDING] +delete: scsi7 diff --git a/src/test/hotplug/disk-remove-lsi-second-controller.conf.expected b/src/test/hotplug/disk-remove-lsi-second-controller.conf.expected new file mode 100644 index 00000000..1287300a --- /dev/null +++ b/src/test/hotplug/disk-remove-lsi-second-controller.conf.expected @@ -0,0 +1,4 @@ +hmp device_del scsi7 +qmp blockdev-del {"node-name":"drive-scsi7"} +qmp object-del {"id":"throttle-drive-scsi7"} +hmp device_del scsihw1 -- 2.47.3