* [pve-devel] [PATCH pve-qemu 1/1] add fake 10.0
[not found] <20250603075558.627850-1-alexandre.derumier@groupe-cyllene.com>
@ 2025-06-03 7:55 ` Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support Alexandre Derumier via pve-devel
` (21 subsequent siblings)
22 siblings, 0 replies; 39+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-06-03 7:55 UTC (permalink / raw)
To: pve-devel; +Cc: Alexandre Derumier
[-- Attachment #1: Type: message/rfc822, Size: 19319 bytes --]
From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH pve-qemu 1/1] add fake 10.0
Date: Tue, 3 Jun 2025 09:55:36 +0200
Message-ID: <20250603075558.627850-2-alexandre.derumier@groupe-cyllene.com>
Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
debian/changelog | 6 +
| 19 ++
...438a42f7a178504347456b9e50e3d2c50478.patch | 247 ++++++++++++++++++
...b0606879ddeddf04bcf8440aabcfe1393b9c.patch | 120 +++++++++
debian/patches/series | 3 +
5 files changed, 395 insertions(+)
create mode 100644 debian/patches/extra/0001-bump-version-to-10.0.0.patch
create mode 100644 debian/patches/extra/0a7c438a42f7a178504347456b9e50e3d2c50478.patch
create mode 100644 debian/patches/extra/7956b0606879ddeddf04bcf8440aabcfe1393b9c.patch
diff --git a/debian/changelog b/debian/changelog
index f83e130..c103a8b 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+pve-qemu-kvm (10.0.0-1) bookworm; urgency=medium
+
+ * fake 10.0.0 for blockdevtest
+
+ -- Proxmox Support Team <support@proxmox.com> Fri, 30 Apr 2025 16:15:58 +0200
+
pve-qemu-kvm (9.2.0-5) bookworm; urgency=medium
* pve backup: backup-access api: simplify bitmap logic
--git a/debian/patches/extra/0001-bump-version-to-10.0.0.patch b/debian/patches/extra/0001-bump-version-to-10.0.0.patch
new file mode 100644
index 0000000..9b36046
--- /dev/null
+++ b/debian/patches/extra/0001-bump-version-to-10.0.0.patch
@@ -0,0 +1,19 @@
+From fb47d062f660bec03ae460df07efd267fc55ce0c Mon Sep 17 00:00:00 2001
+From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
+Date: Mon, 26 May 2025 14:18:53 +0200
+Subject: [PATCH] bump version to 10.0.0
+
+---
+ VERSION | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/VERSION b/VERSION
+index deeb3d6..a13e7b9 100644
+--- a/VERSION
++++ b/VERSION
+@@ -1 +1 @@
+-9.2.0
++10.0.0
+--
+2.39.5
+
diff --git a/debian/patches/extra/0a7c438a42f7a178504347456b9e50e3d2c50478.patch b/debian/patches/extra/0a7c438a42f7a178504347456b9e50e3d2c50478.patch
new file mode 100644
index 0000000..e8b644d
--- /dev/null
+++ b/debian/patches/extra/0a7c438a42f7a178504347456b9e50e3d2c50478.patch
@@ -0,0 +1,247 @@
+From 0a7c438a42f7a178504347456b9e50e3d2c50478 Mon Sep 17 00:00:00 2001
+From: Cornelia Huck <cohuck@redhat.com>
+Date: Tue, 26 Nov 2024 11:30:05 +0100
+Subject: [PATCH] hw: add compat machines for 10.0
+
+Add 10.0 machine types for arm/i440fx/m68k/q35/s390x/spapr.
+
+Signed-off-by: Cornelia Huck <cohuck@redhat.com>
+Reviewed-by: Thomas Huth <thuth@redhat.com>
+Message-ID: <20241126103005.3794748-3-cohuck@redhat.com>
+Signed-off-by: Thomas Huth <thuth@redhat.com>
+---
+ hw/arm/virt.c | 9 ++++++++-
+ hw/core/machine.c | 3 +++
+ hw/i386/pc.c | 3 +++
+ hw/i386/pc_piix.c | 13 +++++++++++--
+ hw/i386/pc_q35.c | 13 +++++++++++--
+ hw/m68k/virt.c | 9 ++++++++-
+ hw/ppc/spapr.c | 15 +++++++++++++--
+ hw/s390x/s390-virtio-ccw.c | 14 +++++++++++++-
+ include/hw/boards.h | 3 +++
+ include/hw/i386/pc.h | 3 +++
+ 10 files changed, 76 insertions(+), 9 deletions(-)
+
+diff --git a/hw/arm/virt.c b/hw/arm/virt.c
+index 1a381e9a2bd71..3bd9dd0f863cf 100644
+--- a/hw/arm/virt.c
++++ b/hw/arm/virt.c
+@@ -3353,10 +3353,17 @@ static void machvirt_machine_init(void)
+ }
+ type_init(machvirt_machine_init);
+
++static void virt_machine_10_0_options(MachineClass *mc)
++{
++}
++DEFINE_VIRT_MACHINE_AS_LATEST(10, 0)
++
+ static void virt_machine_9_2_options(MachineClass *mc)
+ {
++ virt_machine_10_0_options(mc);
++ compat_props_add(mc->compat_props, hw_compat_9_2, hw_compat_9_2_len);
+ }
+-DEFINE_VIRT_MACHINE_AS_LATEST(9, 2)
++DEFINE_VIRT_MACHINE(9, 2)
+
+ static void virt_machine_9_1_options(MachineClass *mc)
+ {
+diff --git a/hw/core/machine.c b/hw/core/machine.c
+index f29fe959647f5..e6900b43efa2e 100644
+--- a/hw/core/machine.c
++++ b/hw/core/machine.c
+@@ -36,6 +36,9 @@
+ #include "hw/virtio/virtio-iommu.h"
+ #include "audio/audio.h"
+
++GlobalProperty hw_compat_9_2[] = {};
++const size_t hw_compat_9_2_len = G_N_ELEMENTS(hw_compat_9_2);
++
+ GlobalProperty hw_compat_9_1[] = {
+ { TYPE_PCI_DEVICE, "x-pcie-ext-tag", "false" },
+ };
+diff --git a/hw/i386/pc.c b/hw/i386/pc.c
+index 317aaca25a06b..99b9b105e26df 100644
+--- a/hw/i386/pc.c
++++ b/hw/i386/pc.c
+@@ -79,6 +79,9 @@
+ { "qemu64-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, },\
+ { "athlon-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, },
+
++GlobalProperty pc_compat_9_2[] = {};
++const size_t pc_compat_9_2_len = G_N_ELEMENTS(pc_compat_9_2);
++
+ GlobalProperty pc_compat_9_1[] = {
+ { "ICH9-LPC", "x-smi-swsmi-timer", "off" },
+ { "ICH9-LPC", "x-smi-periodic-timer", "off" },
+diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
+index 4953676170099..e4365cbdb0a48 100644
+--- a/hw/i386/pc_piix.c
++++ b/hw/i386/pc_piix.c
+@@ -477,12 +477,21 @@ static void pc_i440fx_machine_options(MachineClass *m)
+ "Use a different south bridge than PIIX3");
+ }
+
+-static void pc_i440fx_machine_9_2_options(MachineClass *m)
++static void pc_i440fx_machine_10_0_options(MachineClass *m)
+ {
+ pc_i440fx_machine_options(m);
+ }
+
+-DEFINE_I440FX_MACHINE_AS_LATEST(9, 2);
++DEFINE_I440FX_MACHINE_AS_LATEST(10, 0);
++
++static void pc_i440fx_machine_9_2_options(MachineClass *m)
++{
++ pc_i440fx_machine_10_0_options(m);
++ compat_props_add(m->compat_props, hw_compat_9_2, hw_compat_9_2_len);
++ compat_props_add(m->compat_props, pc_compat_9_2, pc_compat_9_2_len);
++}
++
++DEFINE_I440FX_MACHINE(9, 2);
+
+ static void pc_i440fx_machine_9_1_options(MachineClass *m)
+ {
+diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
+index 42bdedbaa403a..bbbdacda8e4ac 100644
+--- a/hw/i386/pc_q35.c
++++ b/hw/i386/pc_q35.c
+@@ -359,12 +359,21 @@ static void pc_q35_machine_options(MachineClass *m)
+ pc_q35_compat_defaults, pc_q35_compat_defaults_len);
+ }
+
+-static void pc_q35_machine_9_2_options(MachineClass *m)
++static void pc_q35_machine_10_0_options(MachineClass *m)
+ {
+ pc_q35_machine_options(m);
+ }
+
+-DEFINE_Q35_MACHINE_AS_LATEST(9, 2);
++DEFINE_Q35_MACHINE_AS_LATEST(10, 0);
++
++static void pc_q35_machine_9_2_options(MachineClass *m)
++{
++ pc_q35_machine_10_0_options(m);
++ compat_props_add(m->compat_props, hw_compat_9_2, hw_compat_9_2_len);
++ compat_props_add(m->compat_props, pc_compat_9_2, pc_compat_9_2_len);
++}
++
++DEFINE_Q35_MACHINE(9, 2);
+
+ static void pc_q35_machine_9_1_options(MachineClass *m)
+ {
+diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c
+index ea5c4a5a570bb..d0a7a6bfe2417 100644
+--- a/hw/m68k/virt.c
++++ b/hw/m68k/virt.c
+@@ -366,10 +366,17 @@ type_init(virt_machine_register_types)
+ #define DEFINE_VIRT_MACHINE(major, minor) \
+ DEFINE_VIRT_MACHINE_IMPL(false, major, minor)
+
++static void virt_machine_10_0_options(MachineClass *mc)
++{
++}
++DEFINE_VIRT_MACHINE_AS_LATEST(10, 0)
++
+ static void virt_machine_9_2_options(MachineClass *mc)
+ {
++ virt_machine_10_0_options(mc);
++ compat_props_add(mc->compat_props, hw_compat_9_2, hw_compat_9_2_len);
+ }
+-DEFINE_VIRT_MACHINE_AS_LATEST(9, 2)
++DEFINE_VIRT_MACHINE(9, 2)
+
+ static void virt_machine_9_1_options(MachineClass *mc)
+ {
+diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
+index 0d4efaa0c091b..7251eea521dae 100644
+--- a/hw/ppc/spapr.c
++++ b/hw/ppc/spapr.c
+@@ -4732,15 +4732,26 @@ static void spapr_machine_latest_class_options(MachineClass *mc)
+ #define DEFINE_SPAPR_MACHINE(major, minor) \
+ DEFINE_SPAPR_MACHINE_IMPL(false, major, minor)
+
++/*
++ * pseries-10.0
++ */
++static void spapr_machine_10_0_class_options(MachineClass *mc)
++{
++ /* Defaults for the latest behaviour inherited from the base class */
++}
++
++DEFINE_SPAPR_MACHINE_AS_LATEST(10, 0);
++
+ /*
+ * pseries-9.2
+ */
+ static void spapr_machine_9_2_class_options(MachineClass *mc)
+ {
+- /* Defaults for the latest behaviour inherited from the base class */
++ spapr_machine_10_0_class_options(mc);
++ compat_props_add(mc->compat_props, hw_compat_9_2, hw_compat_9_2_len);
+ }
+
+-DEFINE_SPAPR_MACHINE_AS_LATEST(9, 2);
++DEFINE_SPAPR_MACHINE(9, 2);
+
+ /*
+ * pseries-9.1
+diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
+index fe03f716f314d..67ae34aead90a 100644
+--- a/hw/s390x/s390-virtio-ccw.c
++++ b/hw/s390x/s390-virtio-ccw.c
+@@ -849,14 +849,26 @@ static const TypeInfo ccw_machine_info = {
+ DEFINE_CCW_MACHINE_IMPL(false, major, minor)
+
+
++static void ccw_machine_10_0_instance_options(MachineState *machine)
++{
++}
++
++static void ccw_machine_10_0_class_options(MachineClass *mc)
++{
++}
++DEFINE_CCW_MACHINE_AS_LATEST(10, 0);
++
+ static void ccw_machine_9_2_instance_options(MachineState *machine)
+ {
++ ccw_machine_10_0_instance_options(machine);
+ }
+
+ static void ccw_machine_9_2_class_options(MachineClass *mc)
+ {
++ ccw_machine_10_0_class_options(mc);
++ compat_props_add(mc->compat_props, hw_compat_9_2, hw_compat_9_2_len);
+ }
+-DEFINE_CCW_MACHINE_AS_LATEST(9, 2);
++DEFINE_CCW_MACHINE(9, 2);
+
+ static void ccw_machine_9_1_instance_options(MachineState *machine)
+ {
+diff --git a/include/hw/boards.h b/include/hw/boards.h
+index 36fbb9b59df86..7456889c37eb2 100644
+--- a/include/hw/boards.h
++++ b/include/hw/boards.h
+@@ -756,6 +756,9 @@ struct MachineState {
+ } \
+ type_init(machine_initfn##_register_types)
+
++extern GlobalProperty hw_compat_9_2[];
++extern const size_t hw_compat_9_2_len;
++
+ extern GlobalProperty hw_compat_9_1[];
+ extern const size_t hw_compat_9_1_len;
+
+diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
+index 890427c56ed25..1b26a417bd45a 100644
+--- a/include/hw/i386/pc.h
++++ b/include/hw/i386/pc.h
+@@ -215,6 +215,9 @@ void pc_system_parse_ovmf_flash(uint8_t *flash_ptr, size_t flash_size);
+ /* sgx.c */
+ void pc_machine_init_sgx_epc(PCMachineState *pcms);
+
++extern GlobalProperty pc_compat_9_2[];
++extern const size_t pc_compat_9_2_len;
++
+ extern GlobalProperty pc_compat_9_1[];
+ extern const size_t pc_compat_9_1_len;
+
diff --git a/debian/patches/extra/7956b0606879ddeddf04bcf8440aabcfe1393b9c.patch b/debian/patches/extra/7956b0606879ddeddf04bcf8440aabcfe1393b9c.patch
new file mode 100644
index 0000000..0212c82
--- /dev/null
+++ b/debian/patches/extra/7956b0606879ddeddf04bcf8440aabcfe1393b9c.patch
@@ -0,0 +1,120 @@
+From 7956b0606879ddeddf04bcf8440aabcfe1393b9c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
+Date: Tue, 26 Nov 2024 11:30:04 +0100
+Subject: [PATCH] hw/i386: define _AS_LATEST() macros for machine types
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Follow the other architecture targets by adding extra macros for
+defining a versioned machine type as the latest. This reduces the
+size of the changes when introducing new machine types at the start
+of each release cycle.
+
+Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
+Reviewed-by: Cornelia Huck <cohuck@redhat.com>
+Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
+Message-ID: <20240910163041.3764176-1-berrange@redhat.com>
+Signed-off-by: Cornelia Huck <cohuck@redhat.com>
+Message-ID: <20241126103005.3794748-2-cohuck@redhat.com>
+Signed-off-by: Thomas Huth <thuth@redhat.com>
+---
+ hw/i386/pc_piix.c | 11 +++++------
+ hw/i386/pc_q35.c | 11 ++++++-----
+ include/hw/i386/pc.h | 4 +++-
+ 3 files changed, 14 insertions(+), 12 deletions(-)
+
+diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
+index 2bf6865d405eb..4953676170099 100644
+--- a/hw/i386/pc_piix.c
++++ b/hw/i386/pc_piix.c
+@@ -446,7 +446,10 @@ static void pc_i440fx_init(MachineState *machine)
+ }
+
+ #define DEFINE_I440FX_MACHINE(major, minor) \
+- DEFINE_PC_VER_MACHINE(pc_i440fx, "pc-i440fx", pc_i440fx_init, major, minor);
++ DEFINE_PC_VER_MACHINE(pc_i440fx, "pc-i440fx", pc_i440fx_init, false, NULL, major, minor);
++
++#define DEFINE_I440FX_MACHINE_AS_LATEST(major, minor) \
++ DEFINE_PC_VER_MACHINE(pc_i440fx, "pc-i440fx", pc_i440fx_init, true, "pc", major, minor);
+
+ static void pc_i440fx_machine_options(MachineClass *m)
+ {
+@@ -477,17 +480,13 @@ static void pc_i440fx_machine_options(MachineClass *m)
+ static void pc_i440fx_machine_9_2_options(MachineClass *m)
+ {
+ pc_i440fx_machine_options(m);
+- m->alias = "pc";
+- m->is_default = true;
+ }
+
+-DEFINE_I440FX_MACHINE(9, 2);
++DEFINE_I440FX_MACHINE_AS_LATEST(9, 2);
+
+ static void pc_i440fx_machine_9_1_options(MachineClass *m)
+ {
+ pc_i440fx_machine_9_2_options(m);
+- m->alias = NULL;
+- m->is_default = false;
+ compat_props_add(m->compat_props, hw_compat_9_1, hw_compat_9_1_len);
+ compat_props_add(m->compat_props, pc_compat_9_1, pc_compat_9_1_len);
+ }
+diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
+index 8319b6d45ee3f..42bdedbaa403a 100644
+--- a/hw/i386/pc_q35.c
++++ b/hw/i386/pc_q35.c
+@@ -327,10 +327,13 @@ static void pc_q35_init(MachineState *machine)
+ }
+
+ #define DEFINE_Q35_MACHINE(major, minor) \
+- DEFINE_PC_VER_MACHINE(pc_q35, "pc-q35", pc_q35_init, major, minor);
++ DEFINE_PC_VER_MACHINE(pc_q35, "pc-q35", pc_q35_init, false, NULL, major, minor);
++
++#define DEFINE_Q35_MACHINE_AS_LATEST(major, minor) \
++ DEFINE_PC_VER_MACHINE(pc_q35, "pc-q35", pc_q35_init, false, "q35", major, minor);
+
+ #define DEFINE_Q35_MACHINE_BUGFIX(major, minor, micro) \
+- DEFINE_PC_VER_MACHINE(pc_q35, "pc-q35", pc_q35_init, major, minor, micro);
++ DEFINE_PC_VER_MACHINE(pc_q35, "pc-q35", pc_q35_init, false, NULL, major, minor, micro);
+
+ static void pc_q35_machine_options(MachineClass *m)
+ {
+@@ -359,15 +362,13 @@ static void pc_q35_machine_options(MachineClass *m)
+ static void pc_q35_machine_9_2_options(MachineClass *m)
+ {
+ pc_q35_machine_options(m);
+- m->alias = "q35";
+ }
+
+-DEFINE_Q35_MACHINE(9, 2);
++DEFINE_Q35_MACHINE_AS_LATEST(9, 2);
+
+ static void pc_q35_machine_9_1_options(MachineClass *m)
+ {
+ pc_q35_machine_9_2_options(m);
+- m->alias = NULL;
+ compat_props_add(m->compat_props, hw_compat_9_1, hw_compat_9_1_len);
+ compat_props_add(m->compat_props, pc_compat_9_1, pc_compat_9_1_len);
+ }
+diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
+index 14ee06287da34..890427c56ed25 100644
+--- a/include/hw/i386/pc.h
++++ b/include/hw/i386/pc.h
+@@ -320,7 +320,7 @@ extern const size_t pc_compat_2_3_len;
+ } \
+ type_init(pc_machine_init_##suffix)
+
+-#define DEFINE_PC_VER_MACHINE(namesym, namestr, initfn, ...) \
++#define DEFINE_PC_VER_MACHINE(namesym, namestr, initfn, isdefault, malias, ...) \
+ static void MACHINE_VER_SYM(init, namesym, __VA_ARGS__)( \
+ MachineState *machine) \
+ { \
+@@ -334,6 +334,8 @@ extern const size_t pc_compat_2_3_len;
+ MACHINE_VER_SYM(options, namesym, __VA_ARGS__)(mc); \
+ mc->init = MACHINE_VER_SYM(init, namesym, __VA_ARGS__); \
+ MACHINE_VER_DEPRECATION(__VA_ARGS__); \
++ mc->is_default = isdefault; \
++ mc->alias = malias; \
+ } \
+ static const TypeInfo MACHINE_VER_SYM(info, namesym, __VA_ARGS__) = \
+ { \
diff --git a/debian/patches/series b/debian/patches/series
index 18cd6ba..da35737 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -9,6 +9,9 @@ extra/0008-pci-acpi-Windows-PCI-Label-Id-bug-workaround.patch
extra/0009-hw-usb-hcd-xhci-pci-Use-modulo-to-select-MSI-vector-.patch
extra/0010-pci-ensure-valid-link-status-bits-for-downstream-por.patch
extra/0011-pci-msix-Fix-msix-pba-read-vector-poll-end-calculati.patch
+extra/7956b0606879ddeddf04bcf8440aabcfe1393b9c.patch
+extra/0a7c438a42f7a178504347456b9e50e3d2c50478.patch
+extra/0001-bump-version-to-10.0.0.patch
bitmap-mirror/0001-drive-mirror-add-support-for-sync-bitmap-mode-never.patch
bitmap-mirror/0002-drive-mirror-add-support-for-conditional-and-always-.patch
bitmap-mirror/0003-mirror-add-check-for-bitmap-mode-without-bitmap.patch
--
2.39.5
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support
[not found] <20250603075558.627850-1-alexandre.derumier@groupe-cyllene.com>
2025-06-03 7:55 ` [pve-devel] [PATCH pve-qemu 1/1] add fake 10.0 Alexandre Derumier via pve-devel
@ 2025-06-03 7:55 ` Alexandre Derumier via pve-devel
2025-06-05 13:23 ` Fiona Ebner
` (2 more replies)
2025-06-03 7:55 ` [pve-devel] [PATCH pve-storage 1/9] common: add qemu_img_create an preallocation_cmd_option Alexandre Derumier via pve-devel
` (20 subsequent siblings)
22 siblings, 3 replies; 39+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-06-03 7:55 UTC (permalink / raw)
To: pve-devel; +Cc: Alexandre Derumier
[-- Attachment #1: Type: message/rfc822, Size: 112356 bytes --]
From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support
Date: Tue, 3 Jun 2025 09:55:37 +0200
Message-ID: <20250603075558.627850-3-alexandre.derumier@groupe-cyllene.com>
use the blockdev syntax for machine_type > 10.0 only
The blockdev chain is:
-throttle-group-node (drive-(ide|scsi|virtio)x)
- format-node (fmt-drive-x)
- file-node (file-drive -x)
Volumes activation is done earlier now, at config_to_command,
as we need it for file blockdev generation
fixme:
-desactivate volumes on config_to_command fail
Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
PVE/QemuServer.pm | 201 +++----------
PVE/QemuServer/Blockdev.pm | 272 ++++++++++++++++++
PVE/QemuServer/Drive.pm | 201 +++++++++++++
PVE/QemuServer/Makefile | 1 +
test/cfg2cmd/bootorder-blockdev.conf | 15 +
test/cfg2cmd/bootorder-blockdev.conf.cmd | 43 +++
test/cfg2cmd/bootorder-empty-blockdev.conf | 15 +
.../cfg2cmd/bootorder-empty-blockdev.conf.cmd | 43 +++
test/cfg2cmd/bootorder-empty.conf | 1 +
test/cfg2cmd/bootorder-empty.conf.cmd | 2 +-
test/cfg2cmd/bootorder-legacy.conf | 1 +
test/cfg2cmd/bootorder-legacy.conf.cmd | 2 +-
test/cfg2cmd/bootorder.conf | 1 +
test/cfg2cmd/bootorder.conf.cmd | 2 +-
.../cputype-icelake-client-deprecation.conf | 3 -
...putype-icelake-client-deprecation.conf.cmd | 7 +-
.../custom-cpu-model-defaults.conf.cmd | 2 +-
test/cfg2cmd/efi-raw-template.conf.cmd | 2 +-
test/cfg2cmd/efi-raw.conf | 1 +
test/cfg2cmd/efi-raw.conf.cmd | 2 +-
test/cfg2cmd/efi-secboot-and-tpm-q35.conf.cmd | 2 +-
test/cfg2cmd/efi-secboot-and-tpm.conf.cmd | 2 +-
test/cfg2cmd/efidisk-on-rbd.conf.cmd | 2 +-
test/cfg2cmd/i440fx-viommu-virtio.conf.cmd | 2 +-
test/cfg2cmd/ide-blockdev.conf | 14 +
test/cfg2cmd/ide-blockdev.conf.cmd | 46 +++
test/cfg2cmd/ide.conf | 1 +
test/cfg2cmd/ide.conf.cmd | 2 +-
.../cfg2cmd/memory-hotplug-hugepages.conf.cmd | 2 +-
test/cfg2cmd/memory-hotplug.conf.cmd | 2 +-
test/cfg2cmd/memory-hugepages-1g.conf.cmd | 2 +-
test/cfg2cmd/memory-hugepages-2m.conf.cmd | 2 +-
test/cfg2cmd/minimal-defaults.conf.cmd | 2 +-
test/cfg2cmd/netdev-7.1-multiqueues.conf.cmd | 2 +-
test/cfg2cmd/netdev-7.1.conf.cmd | 2 +-
test/cfg2cmd/q35-ide-blockdev.conf | 15 +
test/cfg2cmd/q35-ide-blockdev.conf.cmd | 45 +++
test/cfg2cmd/q35-ide.conf | 2 +-
test/cfg2cmd/q35-ide.conf.cmd | 3 +-
.../q35-linux-hostpci-mapping.conf.cmd | 2 +-
.../q35-linux-hostpci-multifunction.conf.cmd | 2 +-
.../q35-linux-hostpci-template.conf.cmd | 5 +-
...q35-linux-hostpci-x-pci-overrides.conf.cmd | 4 +-
test/cfg2cmd/q35-linux-hostpci.conf.cmd | 2 +-
test/cfg2cmd/q35-simple.conf.cmd | 2 +-
test/cfg2cmd/q35-viommu-intel.conf.cmd | 2 +-
test/cfg2cmd/q35-viommu-virtio.conf.cmd | 2 +-
test/cfg2cmd/seabios_serial.conf | 4 -
test/cfg2cmd/seabios_serial.conf.cmd | 7 +-
test/cfg2cmd/sev-es.conf.cmd | 2 +-
test/cfg2cmd/sev-snp.conf.cmd | 2 +-
test/cfg2cmd/sev-std.conf.cmd | 2 +-
test/cfg2cmd/simple-btrfs.conf | 1 +
test/cfg2cmd/simple-btrfs.conf.cmd | 2 +-
.../simple-disk-passthrough-blockdev.conf | 15 +
.../simple-disk-passthrough-blockdev.conf.cmd | 40 +++
test/cfg2cmd/simple-disk-passthrough.conf | 1 +
test/cfg2cmd/simple-disk-passthrough.conf.cmd | 2 +-
test/cfg2cmd/simple-rbd-blockdev.conf | 15 +
test/cfg2cmd/simple-rbd-blockdev.conf.cmd | 38 +++
test/cfg2cmd/simple-rbd.conf | 1 +
test/cfg2cmd/simple-rbd.conf.cmd | 2 +-
test/cfg2cmd/simple-virtio-blk-blockdev.conf | 13 +
.../simple-virtio-blk-blockdev.conf.cmd | 35 +++
test/cfg2cmd/simple-virtio-blk.conf | 1 +
test/cfg2cmd/simple-virtio-blk.conf.cmd | 2 +-
.../simple-zfs-over-iscsi-blockdev.conf | 14 +
.../simple-zfs-over-iscsi-blockdev.conf.cmd | 35 +++
test/cfg2cmd/simple-zfs-over-iscsi.conf | 1 +
test/cfg2cmd/simple-zfs-over-iscsi.conf.cmd | 2 +-
test/cfg2cmd/simple1-blockdev.conf | 14 +
test/cfg2cmd/simple1-blockdev.conf.cmd | 35 +++
test/cfg2cmd/simple1-template.conf.cmd | 13 +-
test/cfg2cmd/simple1.conf | 1 +
test/cfg2cmd/simple1.conf.cmd | 2 +-
test/cfg2cmd/vnc-clipboard-spice.conf.cmd | 2 +-
test/cfg2cmd/vnc-clipboard-std.conf.cmd | 2 +-
test/run_config2command_tests.pl | 26 ++
78 files changed, 1093 insertions(+), 227 deletions(-)
create mode 100644 PVE/QemuServer/Blockdev.pm
create mode 100644 test/cfg2cmd/bootorder-blockdev.conf
create mode 100644 test/cfg2cmd/bootorder-blockdev.conf.cmd
create mode 100644 test/cfg2cmd/bootorder-empty-blockdev.conf
create mode 100644 test/cfg2cmd/bootorder-empty-blockdev.conf.cmd
create mode 100644 test/cfg2cmd/ide-blockdev.conf
create mode 100644 test/cfg2cmd/ide-blockdev.conf.cmd
create mode 100644 test/cfg2cmd/q35-ide-blockdev.conf
create mode 100644 test/cfg2cmd/q35-ide-blockdev.conf.cmd
create mode 100644 test/cfg2cmd/simple-disk-passthrough-blockdev.conf
create mode 100644 test/cfg2cmd/simple-disk-passthrough-blockdev.conf.cmd
create mode 100644 test/cfg2cmd/simple-rbd-blockdev.conf
create mode 100644 test/cfg2cmd/simple-rbd-blockdev.conf.cmd
create mode 100644 test/cfg2cmd/simple-virtio-blk-blockdev.conf
create mode 100644 test/cfg2cmd/simple-virtio-blk-blockdev.conf.cmd
create mode 100644 test/cfg2cmd/simple-zfs-over-iscsi-blockdev.conf
create mode 100644 test/cfg2cmd/simple-zfs-over-iscsi-blockdev.conf.cmd
create mode 100644 test/cfg2cmd/simple1-blockdev.conf
create mode 100644 test/cfg2cmd/simple1-blockdev.conf.cmd
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 577959a4..383a5833 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -52,10 +52,11 @@ use PVE::QMPClient;
use PVE::QemuConfig;
use PVE::QemuConfig::NoWrite;
use PVE::QemuServer::Helpers qw(config_aware_timeout min_version kvm_user_version windows_version);
+use PVE::QemuServer::Blockdev qw(generate_drive_blockdev);
use PVE::QemuServer::Cloudinit;
use PVE::QemuServer::CGroup;
use PVE::QemuServer::CPUConfig qw(print_cpu_device get_cpu_options get_cpu_bitness is_native_arch get_amd_sev_object get_amd_sev_type);
-use PVE::QemuServer::Drive qw(is_valid_drivename checked_volume_format drive_is_cloudinit drive_is_cdrom drive_is_read_only parse_drive print_drive);
+use PVE::QemuServer::Drive qw(is_valid_drivename checked_volume_format drive_is_cloudinit drive_is_cdrom drive_is_read_only parse_drive print_drive print_drive_commandline_full print_drive_throttle_group);
use PVE::QemuServer::Machine;
use PVE::QemuServer::Memory qw(get_current_memory);
use PVE::QemuServer::MetaInfo;
@@ -1308,6 +1309,8 @@ sub print_drivedevice_full {
my $maxdev = 0;
my $drive_id = PVE::QemuServer::Drive::get_drive_id($drive);
+ my $machine_version = extract_version($machine_type, kvm_user_version());
+
if ($drive->{interface} eq 'virtio') {
my $pciaddr = print_pci_addr("$drive_id", $bridges, $arch, $machine_type);
$device = "virtio-blk-pci,drive=drive-$drive_id,id=${drive_id}${pciaddr}";
@@ -1317,7 +1320,6 @@ sub print_drivedevice_full {
my ($maxdev, $controller, $controller_prefix) = scsihw_infos($conf, $drive);
my $unit = $drive->{index} % $maxdev;
- my $machine_version = extract_version($machine_type, kvm_user_version());
my $device_type = PVE::QemuServer::Drive::get_scsi_device_type(
$drive, $storecfg, $machine_version);
@@ -1367,7 +1369,15 @@ sub print_drivedevice_full {
} else {
$device .= ",bus=ahci$controller.$unit";
}
- $device .= ",drive=drive-$drive_id,id=$drive_id";
+
+ if (min_version($machine_version, 10, 0, 0)) {
+ $device .= ",id=$drive_id";
+ #with blockdev, empty cdrom device don't have any blockdev attached, so drive param can't be declared
+ #with drive=none (and throttle-filter can't be defined without media too)
+ $device .= ",drive=drive-$drive_id" if $device_type ne 'cd' || $drive->{file} ne 'none';
+ } else {
+ $device .= ",drive=drive-$drive_id,id=$drive_id";
+ }
if ($device_type eq 'hd') {
if (my $model = $drive->{model}) {
@@ -1393,7 +1403,16 @@ sub print_drivedevice_full {
$device .= ",serial=$serial";
}
+ if (min_version($machine_version, 10, 0, 0)) {
+ my $writecache = $drive->{cache} && $drive->{cache} =~ /^(?:none|writeback|unsafe)$/ ? "on" : "off";
+ $device .= ",write-cache=$writecache" if $drive->{media} && $drive->{media} ne 'cdrom';
+
+ my @qemu_drive_options = qw(heads secs cyls trans rerror werror);
+ foreach my $o (@qemu_drive_options) {
+ $device .= ",$o=$drive->{$o}" if defined($drive->{$o});
+ }
+ }
return $device;
}
@@ -1411,154 +1430,6 @@ sub get_initiator_name {
return $initiator;
}
-my sub storage_allows_io_uring_default {
- my ($scfg, $cache_direct) = @_;
-
- # io_uring with cache mode writeback or writethrough on krbd will hang...
- return if $scfg && $scfg->{type} eq 'rbd' && $scfg->{krbd} && !$cache_direct;
-
- # io_uring with cache mode writeback or writethrough on LVM will hang, without cache only
- # sometimes, just plain disable...
- return if $scfg && $scfg->{type} eq 'lvm';
-
- # io_uring causes problems when used with CIFS since kernel 5.15
- # Some discussion: https://www.spinics.net/lists/linux-cifs/msg26734.html
- return if $scfg && $scfg->{type} eq 'cifs';
-
- return 1;
-}
-
-my sub drive_uses_cache_direct {
- my ($drive, $scfg) = @_;
-
- my $cache_direct = 0;
-
- if (my $cache = $drive->{cache}) {
- $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
- } elsif (!drive_is_cdrom($drive) && !($scfg && $scfg->{type} eq 'btrfs' && !$scfg->{nocow})) {
- $cache_direct = 1;
- }
-
- return $cache_direct;
-}
-
-sub print_drive_commandline_full {
- my ($storecfg, $vmid, $drive, $live_restore_name, $io_uring) = @_;
-
- my $drive_id = PVE::QemuServer::Drive::get_drive_id($drive);
-
- my ($storeid) = PVE::Storage::parse_volume_id($drive->{file}, 1);
- my $scfg = $storeid ? PVE::Storage::storage_config($storecfg, $storeid) : undef;
- my $vtype = $storeid ? (PVE::Storage::parse_volname($storecfg, $drive->{file}))[0] : undef;
-
- my ($path, $format) = PVE::QemuServer::Drive::get_path_and_format(
- $storecfg, $vmid, $drive, $live_restore_name);
-
- my $is_rbd = $path =~ m/^rbd:/;
-
- my $opts = '';
- my @qemu_drive_options = qw(heads secs cyls trans media cache rerror werror aio discard);
- foreach my $o (@qemu_drive_options) {
- $opts .= ",$o=$drive->{$o}" if defined($drive->{$o});
- }
-
- # snapshot only accepts on|off
- if (defined($drive->{snapshot})) {
- my $v = $drive->{snapshot} ? 'on' : 'off';
- $opts .= ",snapshot=$v";
- }
-
- if (defined($drive->{ro})) { # ro maps to QEMUs `readonly`, which accepts `on` or `off` only
- $opts .= ",readonly=" . ($drive->{ro} ? 'on' : 'off');
- }
-
- foreach my $type (['', '-total'], [_rd => '-read'], [_wr => '-write']) {
- my ($dir, $qmpname) = @$type;
- if (my $v = $drive->{"mbps$dir"}) {
- $opts .= ",throttling.bps$qmpname=".int($v*1024*1024);
- }
- if (my $v = $drive->{"mbps${dir}_max"}) {
- $opts .= ",throttling.bps$qmpname-max=".int($v*1024*1024);
- }
- if (my $v = $drive->{"bps${dir}_max_length"}) {
- $opts .= ",throttling.bps$qmpname-max-length=$v";
- }
- if (my $v = $drive->{"iops${dir}"}) {
- $opts .= ",throttling.iops$qmpname=$v";
- }
- if (my $v = $drive->{"iops${dir}_max"}) {
- $opts .= ",throttling.iops$qmpname-max=$v";
- }
- if (my $v = $drive->{"iops${dir}_max_length"}) {
- $opts .= ",throttling.iops$qmpname-max-length=$v";
- }
- }
-
- if ($live_restore_name) {
- $format = "rbd" if $is_rbd;
- die "$drive_id: Proxmox Backup Server backed drive cannot auto-detect the format\n"
- if !$format;
- $opts .= ",format=alloc-track,file.driver=$format";
- } elsif ($format) {
- $opts .= ",format=$format";
- }
-
- my $cache_direct = drive_uses_cache_direct($drive, $scfg);
-
- $opts .= ",cache=none" if !$drive->{cache} && $cache_direct;
-
- if (!$drive->{aio}) {
- if ($io_uring && storage_allows_io_uring_default($scfg, $cache_direct)) {
- # io_uring supports all cache modes
- $opts .= ",aio=io_uring";
- } else {
- # aio native works only with O_DIRECT
- if($cache_direct) {
- $opts .= ",aio=native";
- } else {
- $opts .= ",aio=threads";
- }
- }
- }
-
- die "$drive_id: explicit media parameter is required for iso images\n"
- if !defined($drive->{media}) && defined($vtype) && $vtype eq 'iso';
-
- if (!drive_is_cdrom($drive)) {
- my $detectzeroes;
- if (defined($drive->{detect_zeroes}) && !$drive->{detect_zeroes}) {
- $detectzeroes = 'off';
- } elsif ($drive->{discard}) {
- $detectzeroes = $drive->{discard} eq 'on' ? 'unmap' : 'on';
- } else {
- # This used to be our default with discard not being specified:
- $detectzeroes = 'on';
- }
-
- # note: 'detect-zeroes' works per blockdev and we want it to persist
- # after the alloc-track is removed, so put it on 'file' directly
- my $dz_param = $live_restore_name ? "file.detect-zeroes" : "detect-zeroes";
- $opts .= ",$dz_param=$detectzeroes" if $detectzeroes;
- }
-
- if ($live_restore_name) {
- $opts .= ",backing=$live_restore_name";
- $opts .= ",auto-remove=on";
- }
-
- # my $file_param = $live_restore_name ? "file.file.filename" : "file";
- my $file_param = "file";
- if ($live_restore_name) {
- # non-rbd drivers require the underlying file to be a separate block
- # node, so add a second .file indirection
- $file_param .= ".file" if !$is_rbd;
- $file_param .= ".filename";
- }
- my $pathinfo = $path ? "$file_param=$path," : '';
-
- return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
-}
-
sub print_pbs_blockdev {
my ($pbs_conf, $pbs_name) = @_;
my $blockdev = "driver=pbs,node-name=$pbs_name,read-only=on";
@@ -3899,6 +3770,7 @@ sub config_to_command {
if (PVE::Storage::parse_volume_id($drive->{file}, 1)) {
check_volume_storage_type($storecfg, $drive->{file});
+ PVE::Storage::activate_volumes($storecfg, [$drive->{file}]);
push @$vollist, $drive->{file};
}
@@ -3960,13 +3832,22 @@ sub config_to_command {
push @$devices, '-blockdev', $live_restore->{blockdev};
}
- my $drive_cmd = print_drive_commandline_full(
- $storecfg, $vmid, $drive, $live_blockdev_name, min_version($kvmver, 6, 0));
+ if(min_version($machine_version, 10, 0, 0)) {
+ my $throttle_group = print_drive_throttle_group($drive);
+ push @$devices, '-object', $throttle_group if $throttle_group;
- # extra protection for templates, but SATA and IDE don't support it..
- $drive_cmd .= ',readonly=on' if drive_is_read_only($conf, $drive);
+ # extra protection for templates, but SATA and IDE don't support it..
+ $drive->{ro} = 1 if drive_is_read_only($conf, $drive);
+ my $blockdev = generate_drive_blockdev($storecfg, $drive, $live_blockdev_name);
+ push @$devices, '-blockdev', JSON->new->canonical->allow_nonref->encode($blockdev) if $blockdev;
+
+ } else {
+ my $drive_cmd = print_drive_commandline_full(
+ $storecfg, $vmid, $drive, $live_blockdev_name, min_version($kvmver, 6, 0));
+ $drive_cmd .= ',readonly=on' if drive_is_read_only($conf, $drive);
+ push @$devices, '-drive',$drive_cmd;
+ }
- push @$devices, '-drive',$drive_cmd;
push @$devices, '-device', print_drivedevice_full(
$storecfg, $conf, $vmid, $drive, $bridges, $arch, $machine_type);
});
@@ -5810,9 +5691,6 @@ sub vm_start_nolock {
die $err;
}
- PVE::Storage::activate_volumes($storecfg, $vollist);
-
-
my %silence_std_outs = (outfunc => sub {}, errfunc => sub {});
eval { run_command(['/bin/systemctl', 'reset-failed', "$vmid.scope"], %silence_std_outs) };
eval { run_command(['/bin/systemctl', 'stop', "$vmid.scope"], %silence_std_outs) };
@@ -6081,9 +5959,12 @@ sub vm_commandline {
my $defaults = load_defaults();
- my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine, $forcecpu);
+ my ($cmd, $vollist) = (config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine, $forcecpu))[0,1];
+
# if the vm is not running, we need to clean up the reserved/created devices
if (!PVE::QemuServer::Helpers::vm_running_locally($vmid)) {
+ eval { PVE::Storage::deactivate_volumes($storecfg, $vollist); };
+ warn $@ if $@;
eval { cleanup_pci_devices($vmid, $conf) };
warn $@ if $@;
}
diff --git a/PVE/QemuServer/Blockdev.pm b/PVE/QemuServer/Blockdev.pm
new file mode 100644
index 00000000..48d1821f
--- /dev/null
+++ b/PVE/QemuServer/Blockdev.pm
@@ -0,0 +1,272 @@
+package PVE::QemuServer::Blockdev;
+
+use strict;
+use warnings;
+
+use PVE::QemuServer::Drive qw(checked_volume_format drive_is_cdrom drive_uses_cache_direct get_drive_id get_iso_path storage_allows_io_uring_default);
+use PVE::Storage;
+
+use base qw(Exporter);
+
+our @EXPORT_OK = qw(
+generate_drive_blockdev
+);
+
+sub encode_base62 {
+ my ($input) = @_;
+ my @chars = ('0'..'9', 'A'..'Z', 'a'..'z');
+ my $base = 62;
+ my $value = 0;
+
+ foreach my $byte (unpack('C*', $input)) {
+ $value = $value * 256 + $byte;
+ }
+
+ my $result = '';
+ while ($value > 0) {
+ $result = $chars[$value % $base] . $result;
+ $value = int($value / $base);
+ }
+
+ return $result || '0';
+}
+
+sub encode_nodename {
+ my ($type, $volid, $snap) = @_;
+
+ my $nodename = "$volid";
+ $nodename .= "-$snap" if $snap;
+ $nodename = encode_base62(Digest::SHA::sha1($nodename));
+ my $prefix = "";
+ if ($type eq 'fmt') {
+ $prefix = 'f';
+ } elsif ($type eq 'file') {
+ $prefix = 'e';
+ } else {
+ die "wrong node type";
+ }
+ #node-name start with an alpha character
+ return "$prefix-$nodename";
+}
+
+sub generate_blockdev_drive_aio {
+ my ($drive, $scfg) = @_;
+
+ my $cache_direct = drive_uses_cache_direct($drive, $scfg);
+ $drive->{aio} = 'threads' if drive_is_cdrom($drive);
+ my $aio = $drive->{aio};
+ if (!$aio) {
+ if (storage_allows_io_uring_default($scfg, $cache_direct)) {
+ # io_uring supports all cache modes
+ $aio = "io_uring";
+ } else {
+ # aio native works only with O_DIRECT
+ if($cache_direct) {
+ $aio = "native";
+ } else {
+ $aio = "threads";
+ }
+ }
+ }
+ return $aio;
+}
+
+sub generate_blockdev_drive_cache {
+ my ($drive, $scfg) = @_;
+
+ my $cache_direct = drive_uses_cache_direct($drive, $scfg);
+ my $cache = {};
+ $cache->{direct} = $cache_direct ? JSON::true : JSON::false;
+ $cache->{'no-flush'} = $drive->{cache} && $drive->{cache} eq 'unsafe' ? JSON::true : JSON::false;
+ return $cache;
+}
+
+sub generate_throttle_group {
+ my ($drive) = @_;
+
+ my $drive_id = get_drive_id($drive);
+
+ my $throttle_group = { id => "throttle-drive-$drive_id" };
+ my $limits = {};
+
+ foreach my $type (['', '-total'], [_rd => '-read'], [_wr => '-write']) {
+ my ($dir, $qmpname) = @$type;
+
+ if (my $v = $drive->{"mbps$dir"}) {
+ $limits->{"bps$qmpname"} = int($v*1024*1024);
+ }
+ if (my $v = $drive->{"mbps${dir}_max"}) {
+ $limits->{"bps$qmpname-max"} = int($v*1024*1024);
+ }
+ if (my $v = $drive->{"bps${dir}_max_length"}) {
+ $limits->{"bps$qmpname-max-length"} = int($v)
+ }
+ if (my $v = $drive->{"iops${dir}"}) {
+ $limits->{"iops$qmpname"} = int($v);
+ }
+ if (my $v = $drive->{"iops${dir}_max"}) {
+ $limits->{"iops$qmpname-max"} = int($v);
+ }
+ if (my $v = $drive->{"iops${dir}_max_length"}) {
+ $limits->{"iops$qmpname-max-length"} = int($v);
+ }
+ }
+
+ $throttle_group->{limits} = $limits;
+
+ return $throttle_group;
+}
+
+sub print_drive_throttle_group {
+ my ($drive) = @_;
+
+ return if drive_is_cdrom($drive) && $drive->{file} eq 'none';
+
+ my $group = generate_throttle_group($drive);
+ $group->{'qom-type'} = "throttle-group";
+ return JSON->new->canonical->allow_nonref->encode($group)
+}
+
+sub generate_file_blockdev {
+ my ($storecfg, $drive, $snap, $nodename) = @_;
+
+ my $volid = $drive->{file};
+ my $drive_id = get_drive_id($drive);
+ my $blockdev = {};
+
+ my $scfg = undef;
+ my $path = $volid;
+ my $storeid = undef;
+
+ ($storeid) = PVE::Storage::parse_volume_id($volid, 1);
+ my $vtype = $storeid ? (PVE::Storage::parse_volname($storecfg, $drive->{file}))[0] : undef;
+ die "$drive_id: explicit media parameter is required for iso images\n"
+ if !defined($drive->{media}) && defined($vtype) && $vtype eq 'iso';
+
+ if ($path =~ m/^nbd:(\S+):(\d+):exportname=(\S+)$/) {
+ my $server = { type => 'inet', host => $1, port => $2 };
+ $blockdev = { driver => 'nbd', server => $server, export => $3 };
+ } elsif($storeid) {
+ $blockdev = PVE::Storage::qemu_blockdev_options($storecfg, $volid, $snap);
+ $scfg = PVE::Storage::storage_config($storecfg, $storeid);
+ } elsif (drive_is_cdrom($drive)) {
+ $path = get_iso_path($storecfg, $volid);
+ my $driver = $path =~ m/^\/dev/ ? 'host_cdrom' : 'file';
+ $blockdev = { driver => $driver, filename => $path };
+ } elsif ($path =~ m/^\/dev/) {
+ $blockdev = { driver => 'host_device', filename => $path };
+ } elsif ($path =~ m/^\//) {
+ $blockdev = { driver => 'file', filename => $path};
+ } else {
+ die "unsupported path: $path\n";
+ }
+
+ $blockdev->{cache} = generate_blockdev_drive_cache($drive, $scfg);
+ #non-host qemu block driver (rbd, gluster,iscsi,..) don't have aio attribute
+ $blockdev->{aio} = generate_blockdev_drive_aio($drive, $scfg) if $blockdev->{filename};
+
+ ##discard && detect-zeroes
+ my $discard = 'ignore';
+ if($drive->{discard}) {
+ $discard = $drive->{discard};
+ $discard = 'unmap' if $discard eq 'on';
+ }
+ $blockdev->{discard} = $discard if !drive_is_cdrom($drive);
+
+ my $detect_zeroes;
+ if (defined($drive->{detect_zeroes}) && !$drive->{detect_zeroes}) {
+ $detect_zeroes = 'off';
+ } elsif ($drive->{discard}) {
+ $detect_zeroes = $drive->{discard} eq 'on' ? 'unmap' : 'on';
+ } else {
+ # This used to be our default with discard not being specified:
+ $detect_zeroes = 'on';
+ }
+ $blockdev->{'detect-zeroes'} = $detect_zeroes if !drive_is_cdrom($drive);
+
+ $nodename = encode_nodename('file', $volid, $snap) if !$nodename;
+ $blockdev->{'node-name'} = $nodename;
+
+ return $blockdev;
+}
+
+sub generate_format_blockdev {
+ my ($storecfg, $drive, $file, $snap, $nodename) = @_;
+
+ my $volid = $drive->{file};
+ #nbd don't support format blockdev, return the fileblockdev
+ return $file if $volid =~ /^nbd:/;
+
+ my $scfg = undef;
+ $nodename = encode_nodename('fmt', $volid, $snap) if !$nodename;
+
+ my $drive_id = get_drive_id($drive);
+
+ if ($drive->{zeroinit}) {
+ #fixme how to handle zeroinit ? insert special blockdev filter ?
+ }
+
+ my ($storeid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
+
+ # For PVE-managed volumes, use the format from the storage layer and prevent overrides via the
+ # drive's 'format' option. For unmanaged volumes, fallback to 'raw' to avoid auto-detection by
+ # QEMU.
+ my $format = undef;
+ if($storeid) {
+ $scfg = PVE::Storage::storage_config($storecfg, $storeid);
+ $format = checked_volume_format($storecfg, $volid);
+ if ($drive->{format} && $drive->{format} ne $format) {
+ die "drive '$drive->{interface}$drive->{index}' - volume '$volid'"
+ ." - 'format=$drive->{format}' option different from storage format '$format'\n";
+ }
+ } else {
+ $format = $drive->{format} // 'raw';
+ }
+
+ my $readonly = defined($drive->{ro}) ? JSON::true : JSON::false;
+
+ #libvirt define cache option on both format && file
+ my $cache = generate_blockdev_drive_cache($drive, $scfg);
+
+ my $blockdev = { 'node-name' => $nodename, driver => $format, file => $file, cache => $cache, 'read-only' => $readonly };
+
+ return $blockdev;
+}
+
+sub generate_drive_blockdev {
+ my ($storecfg, $drive, $live_restore_name) = @_;
+
+ my $volid = $drive->{file};
+ my $drive_id = get_drive_id($drive);
+
+ if (drive_is_cdrom($drive)) {
+ die "$drive_id: cannot back cdrom drive with a live restore image\n" if $live_restore_name;
+
+ my $path = get_iso_path($storecfg, $volid);
+ #throttle-filter can't be defined without attached disk
+ return if !$path;
+ $drive->{ro} = 1;
+ }
+
+ my $blockdev_file = generate_file_blockdev($storecfg, $drive);
+ my $blockdev_format = generate_format_blockdev($storecfg, $drive, $blockdev_file);
+
+ my $blockdev_live_restore = undef;
+ if ($live_restore_name) {
+ die "$drive_id: Proxmox Backup Server backed drive cannot auto-detect the format\n"
+ if !$drive->{format};
+
+ $blockdev_live_restore = { 'node-name' => "liverestore-drive-$drive_id",
+ backing => $live_restore_name,
+ 'auto-remove' => 'on', format => "alloc-track",
+ file => $blockdev_format };
+ }
+
+ #this is the topfilter entry point, use $drive-drive_id as nodename
+ my $blockdev_throttle = { driver => "throttle", 'node-name' => "drive-$drive_id", 'throttle-group' => "throttle-drive-$drive_id" };
+ #put liverestore filter between throttle && format filter
+ $blockdev_throttle->{file} = $live_restore_name ? $blockdev_live_restore : $blockdev_format;
+ return $blockdev_throttle,
+}
+
+1;
diff --git a/PVE/QemuServer/Drive.pm b/PVE/QemuServer/Drive.pm
index 473970c1..f2b70e48 100644
--- a/PVE/QemuServer/Drive.pm
+++ b/PVE/QemuServer/Drive.pm
@@ -21,9 +21,15 @@ checked_volume_format
drive_is_cloudinit
drive_is_cdrom
drive_is_read_only
+drive_uses_cache_direct
+get_drive_id
+get_iso_path
get_scsi_devicetype
parse_drive
print_drive
+print_drive_commandline_full
+print_drive_throttle_group
+storage_allows_io_uring_default
);
our $QEMU_FORMAT_RE = qr/raw|qcow|qcow2|qed|vmdk|cloop/;
@@ -998,4 +1004,199 @@ sub get_scsi_device_type {
return $devicetype;
}
+
+sub storage_allows_io_uring_default {
+ my ($scfg, $cache_direct) = @_;
+
+ # io_uring with cache mode writeback or writethrough on krbd will hang...
+ return if $scfg && $scfg->{type} eq 'rbd' && $scfg->{krbd} && !$cache_direct;
+
+ # io_uring with cache mode writeback or writethrough on LVM will hang, without cache only
+ # sometimes, just plain disable...
+ return if $scfg && $scfg->{type} eq 'lvm';
+
+ # io_uring causes problems when used with CIFS since kernel 5.15
+ # Some discussion: https://www.spinics.net/lists/linux-cifs/msg26734.html
+ return if $scfg && $scfg->{type} eq 'cifs';
+
+ return 1;
+}
+
+sub drive_uses_cache_direct {
+ my ($drive, $scfg) = @_;
+
+ my $cache_direct = 0;
+
+ if (my $cache = $drive->{cache}) {
+ $cache_direct = $cache =~ /^(?:off|none|directsync)$/;
+ } elsif (!drive_is_cdrom($drive) && !($scfg && $scfg->{type} eq 'btrfs' && !$scfg->{nocow})) {
+ $cache_direct = 1;
+ }
+
+ return $cache_direct;
+}
+
+sub print_drive_commandline_full {
+ my ($storecfg, $vmid, $drive, $live_restore_name, $io_uring) = @_;
+
+ my $drive_id = get_drive_id($drive);
+
+ my ($storeid) = PVE::Storage::parse_volume_id($drive->{file}, 1);
+ my $scfg = $storeid ? PVE::Storage::storage_config($storecfg, $storeid) : undef;
+ my $vtype = $storeid ? (PVE::Storage::parse_volname($storecfg, $drive->{file}))[0] : undef;
+
+ my ($path, $format) = get_path_and_format(
+ $storecfg, $vmid, $drive, $live_restore_name);
+
+ my $is_rbd = $path =~ m/^rbd:/;
+
+ my $opts = '';
+ my @qemu_drive_options = qw(heads secs cyls trans media cache rerror werror aio discard);
+ foreach my $o (@qemu_drive_options) {
+ $opts .= ",$o=$drive->{$o}" if defined($drive->{$o});
+ }
+
+ # snapshot only accepts on|off
+ if (defined($drive->{snapshot})) {
+ my $v = $drive->{snapshot} ? 'on' : 'off';
+ $opts .= ",snapshot=$v";
+ }
+
+ if (defined($drive->{ro})) { # ro maps to QEMUs `readonly`, which accepts `on` or `off` only
+ $opts .= ",readonly=" . ($drive->{ro} ? 'on' : 'off');
+ }
+
+ foreach my $type (['', '-total'], [_rd => '-read'], [_wr => '-write']) {
+ my ($dir, $qmpname) = @$type;
+ if (my $v = $drive->{"mbps$dir"}) {
+ $opts .= ",throttling.bps$qmpname=".int($v*1024*1024);
+ }
+ if (my $v = $drive->{"mbps${dir}_max"}) {
+ $opts .= ",throttling.bps$qmpname-max=".int($v*1024*1024);
+ }
+ if (my $v = $drive->{"bps${dir}_max_length"}) {
+ $opts .= ",throttling.bps$qmpname-max-length=$v";
+ }
+ if (my $v = $drive->{"iops${dir}"}) {
+ $opts .= ",throttling.iops$qmpname=$v";
+ }
+ if (my $v = $drive->{"iops${dir}_max"}) {
+ $opts .= ",throttling.iops$qmpname-max=$v";
+ }
+ if (my $v = $drive->{"iops${dir}_max_length"}) {
+ $opts .= ",throttling.iops$qmpname-max-length=$v";
+ }
+ }
+
+ if ($live_restore_name) {
+ $format = "rbd" if $is_rbd;
+ die "$drive_id: Proxmox Backup Server backed drive cannot auto-detect the format\n"
+ if !$format;
+ $opts .= ",format=alloc-track,file.driver=$format";
+ } elsif ($format) {
+ $opts .= ",format=$format";
+ }
+
+ my $cache_direct = drive_uses_cache_direct($drive, $scfg);
+
+ $opts .= ",cache=none" if !$drive->{cache} && $cache_direct;
+
+ if (!$drive->{aio}) {
+ if ($io_uring && storage_allows_io_uring_default($scfg, $cache_direct)) {
+ # io_uring supports all cache modes
+ $opts .= ",aio=io_uring";
+ } else {
+ # aio native works only with O_DIRECT
+ if($cache_direct) {
+ $opts .= ",aio=native";
+ } else {
+ $opts .= ",aio=threads";
+ }
+ }
+ }
+
+ die "$drive_id: explicit media parameter is required for iso images\n"
+ if !defined($drive->{media}) && defined($vtype) && $vtype eq 'iso';
+
+ if (!drive_is_cdrom($drive)) {
+ my $detectzeroes;
+ if (defined($drive->{detect_zeroes}) && !$drive->{detect_zeroes}) {
+ $detectzeroes = 'off';
+ } elsif ($drive->{discard}) {
+ $detectzeroes = $drive->{discard} eq 'on' ? 'unmap' : 'on';
+ } else {
+ # This used to be our default with discard not being specified:
+ $detectzeroes = 'on';
+ }
+
+ # note: 'detect-zeroes' works per blockdev and we want it to persist
+ # after the alloc-track is removed, so put it on 'file' directly
+ my $dz_param = $live_restore_name ? "file.detect-zeroes" : "detect-zeroes";
+ $opts .= ",$dz_param=$detectzeroes" if $detectzeroes;
+ }
+
+ if ($live_restore_name) {
+ $opts .= ",backing=$live_restore_name";
+ $opts .= ",auto-remove=on";
+ }
+
+ # my $file_param = $live_restore_name ? "file.file.filename" : "file";
+ my $file_param = "file";
+ if ($live_restore_name) {
+ # non-rbd drivers require the underlying file to be a separate block
+ # node, so add a second .file indirection
+ $file_param .= ".file" if !$is_rbd;
+ $file_param .= ".filename";
+ }
+ my $pathinfo = $path ? "$file_param=$path," : '';
+
+ return "${pathinfo}if=none,id=drive-$drive->{interface}$drive->{index}$opts";
+}
+
+sub generate_throttle_group {
+ my ($drive) = @_;
+
+ my $drive_id = get_drive_id($drive);
+
+ my $throttle_group = { id => "throttle-drive-$drive_id" };
+ my $limits = {};
+
+ foreach my $type (['', '-total'], [_rd => '-read'], [_wr => '-write']) {
+ my ($dir, $qmpname) = @$type;
+
+ if (my $v = $drive->{"mbps$dir"}) {
+ $limits->{"bps$qmpname"} = int($v*1024*1024);
+ }
+ if (my $v = $drive->{"mbps${dir}_max"}) {
+ $limits->{"bps$qmpname-max"} = int($v*1024*1024);
+ }
+ if (my $v = $drive->{"bps${dir}_max_length"}) {
+ $limits->{"bps$qmpname-max-length"} = int($v)
+ }
+ if (my $v = $drive->{"iops${dir}"}) {
+ $limits->{"iops$qmpname"} = int($v);
+ }
+ if (my $v = $drive->{"iops${dir}_max"}) {
+ $limits->{"iops$qmpname-max"} = int($v);
+ }
+ if (my $v = $drive->{"iops${dir}_max_length"}) {
+ $limits->{"iops$qmpname-max-length"} = int($v);
+ }
+ }
+
+ $throttle_group->{limits} = $limits;
+
+ return $throttle_group;
+}
+
+sub print_drive_throttle_group {
+ my ($drive) = @_;
+
+ return if drive_is_cdrom($drive) && $drive->{file} eq 'none';
+
+ my $group = generate_throttle_group($drive);
+ $group->{'qom-type'} = "throttle-group";
+ return JSON->new->canonical->allow_nonref->encode($group)
+}
+
1;
diff --git a/PVE/QemuServer/Makefile b/PVE/QemuServer/Makefile
index 8bcd484e..248e8859 100644
--- a/PVE/QemuServer/Makefile
+++ b/PVE/QemuServer/Makefile
@@ -11,6 +11,7 @@ SOURCES=PCI.pm \
MetaInfo.pm \
CPUConfig.pm \
CGroup.pm \
+ Blockdev.pm \
Drive.pm \
QMPHelpers.pm \
Virtiofs.pm
diff --git a/test/cfg2cmd/bootorder-blockdev.conf b/test/cfg2cmd/bootorder-blockdev.conf
new file mode 100644
index 00000000..7991065d
--- /dev/null
+++ b/test/cfg2cmd/bootorder-blockdev.conf
@@ -0,0 +1,15 @@
+# TEST: Test for a specific bootorder given by 'boot: order=' property
+cores: 3
+boot: order=virtio1;net0;scsi4;ide2
+ide2: none,media=cdrom
+memory: 768
+name: simple
+net0: virtio=A2:C0:43:77:08:A0,bridge=vmbr0
+numa: 0
+ostype: l26
+scsi4: local:8006/vm-8006-disk-0.qcow2,discard=on,size=104858K
+smbios1: uuid=7b10d7af-b932-4c66-b2c3-3996152ec465
+sockets: 1
+virtio0: local:8006/vm-8006-disk-0.qcow2,discard=on,iothread=1,size=104858K
+virtio1: local:8006/vm-8006-disk-0.qcow2,discard=on,iothread=1,size=104858K
+vmgenid: c773c261-d800-4348-9f5d-167fadd53cf8
diff --git a/test/cfg2cmd/bootorder-blockdev.conf.cmd b/test/cfg2cmd/bootorder-blockdev.conf.cmd
new file mode 100644
index 00000000..435ac280
--- /dev/null
+++ b/test/cfg2cmd/bootorder-blockdev.conf.cmd
@@ -0,0 +1,43 @@
+/usr/bin/kvm \
+ -id 8006 \
+ -name 'simple,debug-threads=on' \
+ -no-shutdown \
+ -chardev 'socket,id=qmp,path=/var/run/qemu-server/8006.qmp,server=on,wait=off' \
+ -mon 'chardev=qmp,mode=control' \
+ -chardev 'socket,id=qmp-event,path=/var/run/qmeventd.sock,reconnect-ms=5000' \
+ -mon 'chardev=qmp-event,mode=control' \
+ -pidfile /var/run/qemu-server/8006.pid \
+ -daemonize \
+ -smbios 'type=1,uuid=7b10d7af-b932-4c66-b2c3-3996152ec465' \
+ -smp '3,sockets=1,cores=3,maxcpus=3' \
+ -nodefaults \
+ -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
+ -vnc 'unix:/var/run/qemu-server/8006.vnc,password=on' \
+ -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
+ -m 768 \
+ -object 'iothread,id=iothread-virtio0' \
+ -object 'iothread,id=iothread-virtio1' \
+ -global 'PIIX4_PM.disable_s3=1' \
+ -global 'PIIX4_PM.disable_s4=1' \
+ -device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \
+ -device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \
+ -device 'vmgenid,guid=c773c261-d800-4348-9f5d-167fadd53cf8' \
+ -device 'piix3-usb-uhci,id=uhci,bus=pci.0,addr=0x1.0x2' \
+ -device 'usb-tablet,id=tablet,bus=uhci.0,port=1' \
+ -device 'VGA,id=vga,bus=pci.0,addr=0x2' \
+ -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
+ -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
+ -device 'ide-cd,bus=ide.1,unit=0,id=ide2,bootindex=103' \
+ -device 'lsi,id=scsihw0,bus=pci.0,addr=0x5' \
+ -object '{"id":"throttle-drive-scsi4","limits":{},"qom-type":"throttle-group"}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-0.qcow2","node-name":"e-IQHs2Stp3mYmKYSGmUACmUu8i6u"},"node-name":"f-IQHs2Stp3mYmKYSGmUACmUu8i6u","read-only":false},"node-name":"drive-scsi4","throttle-group":"throttle-drive-scsi4"}' \
+ -device 'scsi-hd,bus=scsihw0.0,scsi-id=4,drive=drive-scsi4,id=scsi4,bootindex=102' \
+ -object '{"id":"throttle-drive-virtio0","limits":{},"qom-type":"throttle-group"}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-0.qcow2","node-name":"e-IQHs2Stp3mYmKYSGmUACmUu8i6u"},"node-name":"f-IQHs2Stp3mYmKYSGmUACmUu8i6u","read-only":false},"node-name":"drive-virtio0","throttle-group":"throttle-drive-virtio0"}' \
+ -device 'virtio-blk-pci,drive=drive-virtio0,id=virtio0,bus=pci.0,addr=0xa,iothread=iothread-virtio0' \
+ -object '{"id":"throttle-drive-virtio1","limits":{},"qom-type":"throttle-group"}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-0.qcow2","node-name":"e-IQHs2Stp3mYmKYSGmUACmUu8i6u"},"node-name":"f-IQHs2Stp3mYmKYSGmUACmUu8i6u","read-only":false},"node-name":"drive-virtio1","throttle-group":"throttle-drive-virtio1"}' \
+ -device 'virtio-blk-pci,drive=drive-virtio1,id=virtio1,bus=pci.0,addr=0xb,iothread=iothread-virtio1,bootindex=100' \
+ -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=101' \
+ -machine 'type=pc+pve0'
diff --git a/test/cfg2cmd/bootorder-empty-blockdev.conf b/test/cfg2cmd/bootorder-empty-blockdev.conf
new file mode 100644
index 00000000..ccfadb9f
--- /dev/null
+++ b/test/cfg2cmd/bootorder-empty-blockdev.conf
@@ -0,0 +1,15 @@
+# TEST: Test for an empty boot parameter producing no bootindices either
+cores: 3
+boot:
+ide2: none,media=cdrom
+memory: 768
+name: simple
+net0: virtio=A2:C0:43:77:08:A0,bridge=vmbr0
+numa: 0
+ostype: l26
+scsi4: local:8006/vm-8006-disk-0.qcow2,discard=on,size=104858K
+smbios1: uuid=7b10d7af-b932-4c66-b2c3-3996152ec465
+sockets: 1
+virtio0: local:8006/vm-8006-disk-0.qcow2,discard=on,iothread=1,size=104858K
+virtio1: local:8006/vm-8006-disk-0.qcow2,discard=on,iothread=1,size=104858K
+vmgenid: c773c261-d800-4348-9f5d-167fadd53cf8
diff --git a/test/cfg2cmd/bootorder-empty-blockdev.conf.cmd b/test/cfg2cmd/bootorder-empty-blockdev.conf.cmd
new file mode 100644
index 00000000..3a41a28c
--- /dev/null
+++ b/test/cfg2cmd/bootorder-empty-blockdev.conf.cmd
@@ -0,0 +1,43 @@
+/usr/bin/kvm \
+ -id 8006 \
+ -name 'simple,debug-threads=on' \
+ -no-shutdown \
+ -chardev 'socket,id=qmp,path=/var/run/qemu-server/8006.qmp,server=on,wait=off' \
+ -mon 'chardev=qmp,mode=control' \
+ -chardev 'socket,id=qmp-event,path=/var/run/qmeventd.sock,reconnect-ms=5000' \
+ -mon 'chardev=qmp-event,mode=control' \
+ -pidfile /var/run/qemu-server/8006.pid \
+ -daemonize \
+ -smbios 'type=1,uuid=7b10d7af-b932-4c66-b2c3-3996152ec465' \
+ -smp '3,sockets=1,cores=3,maxcpus=3' \
+ -nodefaults \
+ -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
+ -vnc 'unix:/var/run/qemu-server/8006.vnc,password=on' \
+ -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
+ -m 768 \
+ -object 'iothread,id=iothread-virtio0' \
+ -object 'iothread,id=iothread-virtio1' \
+ -global 'PIIX4_PM.disable_s3=1' \
+ -global 'PIIX4_PM.disable_s4=1' \
+ -device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \
+ -device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \
+ -device 'vmgenid,guid=c773c261-d800-4348-9f5d-167fadd53cf8' \
+ -device 'piix3-usb-uhci,id=uhci,bus=pci.0,addr=0x1.0x2' \
+ -device 'usb-tablet,id=tablet,bus=uhci.0,port=1' \
+ -device 'VGA,id=vga,bus=pci.0,addr=0x2' \
+ -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
+ -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
+ -device 'ide-cd,bus=ide.1,unit=0,id=ide2' \
+ -device 'lsi,id=scsihw0,bus=pci.0,addr=0x5' \
+ -object '{"id":"throttle-drive-scsi4","limits":{},"qom-type":"throttle-group"}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-0.qcow2","node-name":"e-IQHs2Stp3mYmKYSGmUACmUu8i6u"},"node-name":"f-IQHs2Stp3mYmKYSGmUACmUu8i6u","read-only":false},"node-name":"drive-scsi4","throttle-group":"throttle-drive-scsi4"}'
+ -device 'scsi-hd,bus=scsihw0.0,scsi-id=4,drive=drive-scsi4,id=scsi4' \
+ -object '{"id":"throttle-drive-virtio0","limits":{},"qom-type":"throttle-group"}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-0.qcow2","node-name":"e-IQHs2Stp3mYmKYSGmUACmUu8i6u"},"node-name":"f-IQHs2Stp3mYmKYSGmUACmUu8i6u","read-only":false},"node-name":"drive-virtio0","throttle-group":"throttle-drive-virtio0"}' \
+ -device 'virtio-blk-pci,drive=drive-virtio0,id=virtio0,bus=pci.0,addr=0xa,iothread=iothread-virtio0' \
+ -object '{"id":"throttle-drive-virtio1","limits":{},"qom-type":"throttle-group"}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-0.qcow2","node-name":"e-IQHs2Stp3mYmKYSGmUACmUu8i6u"},"node-name":"f-IQHs2Stp3mYmKYSGmUACmUu8i6u","read-only":false},"node-name":"drive-virtio1","throttle-group":"throttle-drive-virtio1"}' \
+ -device 'virtio-blk-pci,drive=drive-virtio1,id=virtio1,bus=pci.0,addr=0xb,iothread=iothread-virtio1' \
+ -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' \
+ -machine 'type=pc+pve0'
diff --git a/test/cfg2cmd/bootorder-empty.conf b/test/cfg2cmd/bootorder-empty.conf
index ccfadb9f..19dcf054 100644
--- a/test/cfg2cmd/bootorder-empty.conf
+++ b/test/cfg2cmd/bootorder-empty.conf
@@ -2,6 +2,7 @@
cores: 3
boot:
ide2: none,media=cdrom
+machine: pc-i440fx-9.2+pve1
memory: 768
name: simple
net0: virtio=A2:C0:43:77:08:A0,bridge=vmbr0
diff --git a/test/cfg2cmd/bootorder-empty.conf.cmd b/test/cfg2cmd/bootorder-empty.conf.cmd
index 07d46ee9..b4e95f13 100644
--- a/test/cfg2cmd/bootorder-empty.conf.cmd
+++ b/test/cfg2cmd/bootorder-empty.conf.cmd
@@ -38,4 +38,4 @@
-device 'virtio-blk-pci,drive=drive-virtio1,id=virtio1,bus=pci.0,addr=0xb,iothread=iothread-virtio1' \
-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' \
- -machine 'type=pc+pve1'
+ -machine 'type=pc-i440fx-9.2+pve1'
diff --git a/test/cfg2cmd/bootorder-legacy.conf b/test/cfg2cmd/bootorder-legacy.conf
index 4e59268b..c6716740 100644
--- a/test/cfg2cmd/bootorder-legacy.conf
+++ b/test/cfg2cmd/bootorder-legacy.conf
@@ -3,6 +3,7 @@ cores: 3
boot: ndca
bootdisk: virtio1
ide2: none,media=cdrom
+machine: pc-i440fx-9.2+pve1
memory: 768
name: simple
net0: virtio=A2:C0:43:77:08:A0,bridge=vmbr0
diff --git a/test/cfg2cmd/bootorder-legacy.conf.cmd b/test/cfg2cmd/bootorder-legacy.conf.cmd
index d12dcd94..4e520b2e 100644
--- a/test/cfg2cmd/bootorder-legacy.conf.cmd
+++ b/test/cfg2cmd/bootorder-legacy.conf.cmd
@@ -38,4 +38,4 @@
-device 'virtio-blk-pci,drive=drive-virtio1,id=virtio1,bus=pci.0,addr=0xb,iothread=iothread-virtio1,bootindex=302' \
-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=100' \
- -machine 'type=pc+pve1'
+ -machine 'type=pc-i440fx-9.2+pve1'
diff --git a/test/cfg2cmd/bootorder.conf b/test/cfg2cmd/bootorder.conf
index 7991065d..5ae38bf4 100644
--- a/test/cfg2cmd/bootorder.conf
+++ b/test/cfg2cmd/bootorder.conf
@@ -2,6 +2,7 @@
cores: 3
boot: order=virtio1;net0;scsi4;ide2
ide2: none,media=cdrom
+machine: pc-i440fx-9.2+pve1
memory: 768
name: simple
net0: virtio=A2:C0:43:77:08:A0,bridge=vmbr0
diff --git a/test/cfg2cmd/bootorder.conf.cmd b/test/cfg2cmd/bootorder.conf.cmd
index 2f2aa555..e8f9b666 100644
--- a/test/cfg2cmd/bootorder.conf.cmd
+++ b/test/cfg2cmd/bootorder.conf.cmd
@@ -38,4 +38,4 @@
-device 'virtio-blk-pci,drive=drive-virtio1,id=virtio1,bus=pci.0,addr=0xb,iothread=iothread-virtio1,bootindex=100' \
-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=101' \
- -machine 'type=pc+pve1'
+ -machine 'type=pc-i440fx-9.2+pve1'
diff --git a/test/cfg2cmd/cputype-icelake-client-deprecation.conf b/test/cfg2cmd/cputype-icelake-client-deprecation.conf
index c0c4b929..dc186e52 100644
--- a/test/cfg2cmd/cputype-icelake-client-deprecation.conf
+++ b/test/cfg2cmd/cputype-icelake-client-deprecation.conf
@@ -2,12 +2,9 @@
bootdisk: scsi0
cores: 2
cpu: Icelake-Client
-ide2: none,media=cdrom
memory: 768
name: simple
ostype: l26
-scsi0: local:8006/base-8006-disk-0.qcow2,discard=on,size=104858K
-scsihw: virtio-scsi-pci
smbios1: uuid=7b10d7af-b932-4c66-b2c3-3996152ec465
sockets: 1
vmgenid: c773c261-d800-4348-9f5d-167fadd53cf8
diff --git a/test/cfg2cmd/cputype-icelake-client-deprecation.conf.cmd b/test/cfg2cmd/cputype-icelake-client-deprecation.conf.cmd
index 4fe10b66..d84d96b7 100644
--- a/test/cfg2cmd/cputype-icelake-client-deprecation.conf.cmd
+++ b/test/cfg2cmd/cputype-icelake-client-deprecation.conf.cmd
@@ -25,9 +25,4 @@
-device 'VGA,id=vga,bus=pci.0,addr=0x2' \
-device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
- -drive 'if=none,id=drive-ide2,media=cdrom,aio=io_uring' \
- -device 'ide-cd,bus=ide.1,unit=0,drive=drive-ide2,id=ide2,bootindex=200' \
- -device 'virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5' \
- -drive 'file=/var/lib/vz/images/8006/base-8006-disk-0.qcow2,if=none,id=drive-scsi0,discard=on,format=qcow2,cache=none,aio=io_uring,detect-zeroes=unmap' \
- -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,bootindex=100' \
- -machine 'type=pc+pve1'
+ -machine 'type=pc+pve0'
diff --git a/test/cfg2cmd/custom-cpu-model-defaults.conf.cmd b/test/cfg2cmd/custom-cpu-model-defaults.conf.cmd
index 7e023f33..2908fdc0 100644
--- a/test/cfg2cmd/custom-cpu-model-defaults.conf.cmd
+++ b/test/cfg2cmd/custom-cpu-model-defaults.conf.cmd
@@ -24,4 +24,4 @@
-device 'VGA,id=vga,bus=pci.0,addr=0x2' \
-device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
- -machine 'type=pc+pve1'
+ -machine 'type=pc+pve0'
diff --git a/test/cfg2cmd/efi-raw-template.conf.cmd b/test/cfg2cmd/efi-raw-template.conf.cmd
index ee9b0683..f66cbb0d 100644
--- a/test/cfg2cmd/efi-raw-template.conf.cmd
+++ b/test/cfg2cmd/efi-raw-template.conf.cmd
@@ -25,5 +25,5 @@
-device 'usb-tablet,id=tablet,bus=uhci.0,port=1' \
-device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
- -machine 'accel=tcg,type=pc+pve1' \
+ -machine 'accel=tcg,type=pc+pve0' \
-snapshot
diff --git a/test/cfg2cmd/efi-raw.conf b/test/cfg2cmd/efi-raw.conf
index 11e6a3e6..d69cf8d6 100644
--- a/test/cfg2cmd/efi-raw.conf
+++ b/test/cfg2cmd/efi-raw.conf
@@ -1,4 +1,5 @@
# TEST: Test raw efidisk size parameter
smbios1: uuid=7b10d7af-b932-4c66-b2c3-3996152ec465
bios: ovmf
+machine: pc-i440fx-9.2+pve1
efidisk0: local:100/vm-disk-100-0.raw
diff --git a/test/cfg2cmd/efi-raw.conf.cmd b/test/cfg2cmd/efi-raw.conf.cmd
index 9d2c57ec..9d6f3f25 100644
--- a/test/cfg2cmd/efi-raw.conf.cmd
+++ b/test/cfg2cmd/efi-raw.conf.cmd
@@ -26,4 +26,4 @@
-device 'VGA,id=vga,bus=pci.0,addr=0x2' \
-device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
- -machine 'type=pc+pve1'
+ -machine 'type=pc-i440fx-9.2+pve1'
diff --git a/test/cfg2cmd/efi-secboot-and-tpm-q35.conf.cmd b/test/cfg2cmd/efi-secboot-and-tpm-q35.conf.cmd
index 16d58fdf..4e9a7e87 100644
--- a/test/cfg2cmd/efi-secboot-and-tpm-q35.conf.cmd
+++ b/test/cfg2cmd/efi-secboot-and-tpm-q35.conf.cmd
@@ -27,4 +27,4 @@
-device 'VGA,id=vga,bus=pcie.0,addr=0x1' \
-device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
- -machine 'type=q35+pve1'
+ -machine 'type=q35+pve0'
diff --git a/test/cfg2cmd/efi-secboot-and-tpm.conf.cmd b/test/cfg2cmd/efi-secboot-and-tpm.conf.cmd
index 1dd76a0a..175d9b10 100644
--- a/test/cfg2cmd/efi-secboot-and-tpm.conf.cmd
+++ b/test/cfg2cmd/efi-secboot-and-tpm.conf.cmd
@@ -29,4 +29,4 @@
-device 'VGA,id=vga,bus=pci.0,addr=0x2' \
-device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
- -machine 'type=pc+pve1'
+ -machine 'type=pc+pve0'
diff --git a/test/cfg2cmd/efidisk-on-rbd.conf.cmd b/test/cfg2cmd/efidisk-on-rbd.conf.cmd
index c8cd79ac..5c55c01b 100644
--- a/test/cfg2cmd/efidisk-on-rbd.conf.cmd
+++ b/test/cfg2cmd/efidisk-on-rbd.conf.cmd
@@ -31,4 +31,4 @@
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-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=2E:01:68:F9:9C:87,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256,bootindex=300' \
- -machine 'type=pc+pve1'
+ -machine 'type=pc+pve0'
diff --git a/test/cfg2cmd/i440fx-viommu-virtio.conf.cmd b/test/cfg2cmd/i440fx-viommu-virtio.conf.cmd
index 5830ec5c..4e9f0fb8 100644
--- a/test/cfg2cmd/i440fx-viommu-virtio.conf.cmd
+++ b/test/cfg2cmd/i440fx-viommu-virtio.conf.cmd
@@ -24,4 +24,4 @@
-device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-device virtio-iommu-pci \
- -machine 'type=pc+pve1'
+ -machine 'type=pc+pve0'
diff --git a/test/cfg2cmd/ide-blockdev.conf b/test/cfg2cmd/ide-blockdev.conf
new file mode 100644
index 00000000..0c48aac8
--- /dev/null
+++ b/test/cfg2cmd/ide-blockdev.conf
@@ -0,0 +1,14 @@
+# TEST: Config with default machine type, Linux & four IDE CD-ROMs
+bootdisk: scsi0
+cores: 2
+ide0: cifs-store:iso/zero.iso,media=cdrom,size=112M
+ide1: cifs-store:iso/one.iso,media=cdrom,size=112M
+ide2: cifs-store:iso/two.iso,media=cdrom,size=112M
+ide3: cifs-store:iso/three.iso,media=cdrom,size=112M
+memory: 512
+net0: virtio=2E:01:68:F9:9C:87,bridge=vmbr0
+ostype: l26
+scsi0: local:100/vm-100-disk-2.qcow2,size=10G
+scsihw: virtio-scsi-pci
+smbios1: uuid=3dd750ce-d910-44d0-9493-525c0be4e687
+vmgenid: 54d1c06c-8f5b-440f-b5b2-6eab1380e13d
diff --git a/test/cfg2cmd/ide-blockdev.conf.cmd b/test/cfg2cmd/ide-blockdev.conf.cmd
new file mode 100644
index 00000000..856d3f97
--- /dev/null
+++ b/test/cfg2cmd/ide-blockdev.conf.cmd
@@ -0,0 +1,46 @@
+/usr/bin/kvm \
+ -id 8006 \
+ -name 'vm8006,debug-threads=on' \
+ -no-shutdown \
+ -chardev 'socket,id=qmp,path=/var/run/qemu-server/8006.qmp,server=on,wait=off' \
+ -mon 'chardev=qmp,mode=control' \
+ -chardev 'socket,id=qmp-event,path=/var/run/qmeventd.sock,reconnect-ms=5000' \
+ -mon 'chardev=qmp-event,mode=control' \
+ -pidfile /var/run/qemu-server/8006.pid \
+ -daemonize \
+ -smbios 'type=1,uuid=3dd750ce-d910-44d0-9493-525c0be4e687' \
+ -smp '2,sockets=1,cores=2,maxcpus=2' \
+ -nodefaults \
+ -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
+ -vnc 'unix:/var/run/qemu-server/8006.vnc,password=on' \
+ -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
+ -m 512 \
+ -global 'PIIX4_PM.disable_s3=1' \
+ -global 'PIIX4_PM.disable_s4=1' \
+ -device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \
+ -device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \
+ -device 'vmgenid,guid=54d1c06c-8f5b-440f-b5b2-6eab1380e13d' \
+ -device 'piix3-usb-uhci,id=uhci,bus=pci.0,addr=0x1.0x2' \
+ -device 'usb-tablet,id=tablet,bus=uhci.0,port=1' \
+ -device 'VGA,id=vga,bus=pci.0,addr=0x2' \
+ -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
+ -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
+ -object '{"id":"throttle-drive-ide0","limits":{},"qom-type":"throttle-group"}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"threads","cache":{"direct":false,"no-flush":false},"driver":"file","filename":"/mnt/pve/cifs-store/template/iso/zero.iso","node-name":"e-OO9IkxxtCYSqog6okQom0we4S48"},"node-name":"f-OO9IkxxtCYSqog6okQom0we4S48","read-only":true},"node-name":"drive-ide0","throttle-group":"throttle-drive-ide0"}' \
+ -device 'ide-cd,bus=ide.0,unit=0,id=ide0,drive=drive-ide0,bootindex=200' \
+ -object '{"id":"throttle-drive-ide1","limits":{},"qom-type":"throttle-group"}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"threads","cache":{"direct":false,"no-flush":false},"driver":"file","filename":"/mnt/pve/cifs-store/template/iso/one.iso","node-name":"e-OiteZ9aAusKmw6oIO8qucwmmmUU"},"node-name":"f-OiteZ9aAusKmw6oIO8qucwmmmUU","read-only":true},"node-name":"drive-ide1","throttle-group":"throttle-drive-ide1"}' \
+ -device 'ide-cd,bus=ide.0,unit=1,id=ide1,drive=drive-ide1,bootindex=201' \
+ -object '{"id":"throttle-drive-ide2","limits":{},"qom-type":"throttle-group"}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"threads","cache":{"direct":false,"no-flush":false},"driver":"file","filename":"/mnt/pve/cifs-store/template/iso/two.iso","node-name":"e-1Aib1Kemp2sgocAWokMGOyIQyQY"},"node-name":"f-1Aib1Kemp2sgocAWokMGOyIQyQY","read-only":true},"node-name":"drive-ide2","throttle-group":"throttle-drive-ide2"}' \
+ -device 'ide-cd,bus=ide.1,unit=0,id=ide2,drive=drive-ide2,bootindex=202' \
+ -object '{"id":"throttle-drive-ide3","limits":{},"qom-type":"throttle-group"}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"threads","cache":{"direct":false,"no-flush":false},"driver":"file","filename":"/mnt/pve/cifs-store/template/iso/three.iso","node-name":"e-UKCOEDGubQ8AywsAyqqGIywCIWQ"},"node-name":"f-UKCOEDGubQ8AywsAyqqGIywCIWQ","read-only":true},"node-name":"drive-ide3","throttle-group":"throttle-drive-ide3"}' \
+ -device 'ide-cd,bus=ide.1,unit=1,id=ide3,drive=drive-ide3,bootindex=203' \
+ -device 'virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5' \
+ -object '{"id":"throttle-drive-scsi0","limits":{},"qom-type":"throttle-group"}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"on","discard":"ignore","driver":"file","filename":"/var/lib/vz/images/100/vm-100-disk-2.qcow2","node-name":"e-6zrMeiDDrkeISyGMGwACygKAISG"},"node-name":"f-6zrMeiDDrkeISyGMGwACygKAISG","read-only":false},"node-name":"drive-scsi0","throttle-group":"throttle-drive-scsi0"}' \
+ -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,bootindex=100' \
+ -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=2E:01:68:F9:9C:87,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256,bootindex=300' \
+ -machine 'type=pc+pve0'
diff --git a/test/cfg2cmd/ide.conf b/test/cfg2cmd/ide.conf
index 0c48aac8..4fd3e1b3 100644
--- a/test/cfg2cmd/ide.conf
+++ b/test/cfg2cmd/ide.conf
@@ -5,6 +5,7 @@ ide0: cifs-store:iso/zero.iso,media=cdrom,size=112M
ide1: cifs-store:iso/one.iso,media=cdrom,size=112M
ide2: cifs-store:iso/two.iso,media=cdrom,size=112M
ide3: cifs-store:iso/three.iso,media=cdrom,size=112M
+machine: pc-i440fx-9.2+pve1
memory: 512
net0: virtio=2E:01:68:F9:9C:87,bridge=vmbr0
ostype: l26
diff --git a/test/cfg2cmd/ide.conf.cmd b/test/cfg2cmd/ide.conf.cmd
index 273b8e7d..a5ff4695 100644
--- a/test/cfg2cmd/ide.conf.cmd
+++ b/test/cfg2cmd/ide.conf.cmd
@@ -38,4 +38,4 @@
-device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,bootindex=100' \
-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=2E:01:68:F9:9C:87,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256,bootindex=300' \
- -machine 'type=pc+pve1'
+ -machine 'type=pc-i440fx-9.2+pve1'
diff --git a/test/cfg2cmd/memory-hotplug-hugepages.conf.cmd b/test/cfg2cmd/memory-hotplug-hugepages.conf.cmd
index b0c9519f..e069bd6b 100644
--- a/test/cfg2cmd/memory-hotplug-hugepages.conf.cmd
+++ b/test/cfg2cmd/memory-hotplug-hugepages.conf.cmd
@@ -61,4 +61,4 @@
-device 'VGA,id=vga,bus=pci.0,addr=0x2' \
-device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
- -machine 'type=pc+pve1'
+ -machine 'type=pc+pve0'
diff --git a/test/cfg2cmd/memory-hotplug.conf.cmd b/test/cfg2cmd/memory-hotplug.conf.cmd
index 9711cf45..af80917b 100644
--- a/test/cfg2cmd/memory-hotplug.conf.cmd
+++ b/test/cfg2cmd/memory-hotplug.conf.cmd
@@ -173,4 +173,4 @@
-device 'VGA,id=vga,bus=pci.0,addr=0x2' \
-device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
- -machine 'type=pc+pve1'
+ -machine 'type=pc+pve0'
diff --git a/test/cfg2cmd/memory-hugepages-1g.conf.cmd b/test/cfg2cmd/memory-hugepages-1g.conf.cmd
index f476b6b9..73c3036f 100644
--- a/test/cfg2cmd/memory-hugepages-1g.conf.cmd
+++ b/test/cfg2cmd/memory-hugepages-1g.conf.cmd
@@ -29,4 +29,4 @@
-device 'VGA,id=vga,bus=pci.0,addr=0x2' \
-device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
- -machine 'type=pc+pve1'
+ -machine 'type=pc+pve0'
diff --git a/test/cfg2cmd/memory-hugepages-2m.conf.cmd b/test/cfg2cmd/memory-hugepages-2m.conf.cmd
index 2756dcf6..9eb85a72 100644
--- a/test/cfg2cmd/memory-hugepages-2m.conf.cmd
+++ b/test/cfg2cmd/memory-hugepages-2m.conf.cmd
@@ -29,4 +29,4 @@
-device 'VGA,id=vga,bus=pci.0,addr=0x2' \
-device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
- -machine 'type=pc+pve1'
+ -machine 'type=pc+pve0'
diff --git a/test/cfg2cmd/minimal-defaults.conf.cmd b/test/cfg2cmd/minimal-defaults.conf.cmd
index 3f958052..5a419ddf 100644
--- a/test/cfg2cmd/minimal-defaults.conf.cmd
+++ b/test/cfg2cmd/minimal-defaults.conf.cmd
@@ -24,4 +24,4 @@
-device 'VGA,id=vga,bus=pci.0,addr=0x2' \
-device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
- -machine 'type=pc+pve1'
+ -machine 'type=pc+pve0'
diff --git a/test/cfg2cmd/netdev-7.1-multiqueues.conf.cmd b/test/cfg2cmd/netdev-7.1-multiqueues.conf.cmd
index 43e40742..776bab30 100644
--- a/test/cfg2cmd/netdev-7.1-multiqueues.conf.cmd
+++ b/test/cfg2cmd/netdev-7.1-multiqueues.conf.cmd
@@ -25,4 +25,4 @@
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-netdev 'type=tap,id=net0,ifname=tap8006i0,script=/usr/libexec/qemu-server/pve-bridge,downscript=/usr/libexec/qemu-server/pve-bridgedown,vhost=on,queues=2' \
-device 'virtio-net-pci,mac=A2:C0:43:77:08:A0,netdev=net0,bus=pci.0,addr=0x12,id=net0,vectors=6,mq=on,packed=on,rx_queue_size=1024,tx_queue_size=256,bootindex=300,host_mtu=900' \
- -machine 'type=pc+pve1'
+ -machine 'type=pc+pve0'
diff --git a/test/cfg2cmd/netdev-7.1.conf.cmd b/test/cfg2cmd/netdev-7.1.conf.cmd
index 10404de4..0d6b3ad2 100644
--- a/test/cfg2cmd/netdev-7.1.conf.cmd
+++ b/test/cfg2cmd/netdev-7.1.conf.cmd
@@ -25,4 +25,4 @@
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-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=900' \
- -machine 'type=pc+pve1'
+ -machine 'type=pc+pve0'
diff --git a/test/cfg2cmd/q35-ide-blockdev.conf b/test/cfg2cmd/q35-ide-blockdev.conf
new file mode 100644
index 00000000..bfef0a14
--- /dev/null
+++ b/test/cfg2cmd/q35-ide-blockdev.conf
@@ -0,0 +1,15 @@
+# TEST: Config with q35, Linux & four IDE CD-ROMs
+bootdisk: scsi0
+cores: 2
+ide0: cifs-store:iso/zero.iso,media=cdrom,size=112M
+ide1: cifs-store:iso/one.iso,media=cdrom,size=112M
+ide2: cifs-store:iso/two.iso,media=cdrom,size=112M
+ide3: cifs-store:iso/three.iso,media=cdrom,size=112M
+machine: q35
+memory: 512
+net0: virtio=2E:01:68:F9:9C:87,bridge=vmbr0
+ostype: l26
+scsi0: local:100/vm-100-disk-2.qcow2,size=10G
+scsihw: virtio-scsi-pci
+smbios1: uuid=3dd750ce-d910-44d0-9493-525c0be4e687
+vmgenid: 54d1c06c-8f5b-440f-b5b2-6eab1380e13d
diff --git a/test/cfg2cmd/q35-ide-blockdev.conf.cmd b/test/cfg2cmd/q35-ide-blockdev.conf.cmd
new file mode 100644
index 00000000..1a4c3f81
--- /dev/null
+++ b/test/cfg2cmd/q35-ide-blockdev.conf.cmd
@@ -0,0 +1,45 @@
+/usr/bin/kvm \
+ -id 8006 \
+ -name 'vm8006,debug-threads=on' \
+ -no-shutdown \
+ -chardev 'socket,id=qmp,path=/var/run/qemu-server/8006.qmp,server=on,wait=off' \
+ -mon 'chardev=qmp,mode=control' \
+ -chardev 'socket,id=qmp-event,path=/var/run/qmeventd.sock,reconnect-ms=5000' \
+ -mon 'chardev=qmp-event,mode=control' \
+ -pidfile /var/run/qemu-server/8006.pid \
+ -daemonize \
+ -smbios 'type=1,uuid=3dd750ce-d910-44d0-9493-525c0be4e687' \
+ -global 'ICH9-LPC.acpi-pci-hotplug-with-bridge-support=off' \
+ -smp '2,sockets=1,cores=2,maxcpus=2' \
+ -nodefaults \
+ -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
+ -vnc 'unix:/var/run/qemu-server/8006.vnc,password=on' \
+ -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
+ -m 512 \
+ -global 'ICH9-LPC.disable_s3=1' \
+ -global 'ICH9-LPC.disable_s4=1' \
+ -readconfig /usr/share/qemu-server/pve-q35-4.0.cfg \
+ -device 'vmgenid,guid=54d1c06c-8f5b-440f-b5b2-6eab1380e13d' \
+ -device 'usb-tablet,id=tablet,bus=ehci.0,port=1' \
+ -device 'VGA,id=vga,bus=pcie.0,addr=0x1' \
+ -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
+ -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
+ -object '{"id":"throttle-drive-ide0","limits":{},"qom-type":"throttle-group"}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"threads","cache":{"direct":false,"no-flush":false},"driver":"file","filename":"/mnt/pve/cifs-store/template/iso/zero.iso","node-name":"e-OO9IkxxtCYSqog6okQom0we4S48"},"node-name":"f-OO9IkxxtCYSqog6okQom0we4S48","read-only":true},"node-name":"drive-ide0","throttle-group":"throttle-drive-ide0"}' \
+ -device 'ide-cd,bus=ide.0,unit=0,id=ide0,drive=drive-ide0,bootindex=200' \
+ -object '{"id":"throttle-drive-ide1","limits":{},"qom-type":"throttle-group"}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"threads","cache":{"direct":false,"no-flush":false},"driver":"file","filename":"/mnt/pve/cifs-store/template/iso/one.iso","node-name":"e-OiteZ9aAusKmw6oIO8qucwmmmUU"},"node-name":"f-OiteZ9aAusKmw6oIO8qucwmmmUU","read-only":true},"node-name":"drive-ide1","throttle-group":"throttle-drive-ide1"}' \
+ -device 'ide-cd,bus=ide.2,unit=0,id=ide1,drive=drive-ide1,bootindex=201' \
+ -object '{"id":"throttle-drive-ide2","limits":{},"qom-type":"throttle-group"}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"threads","cache":{"direct":false,"no-flush":false},"driver":"file","filename":"/mnt/pve/cifs-store/template/iso/two.iso","node-name":"e-1Aib1Kemp2sgocAWokMGOyIQyQY"},"node-name":"f-1Aib1Kemp2sgocAWokMGOyIQyQY","read-only":true},"node-name":"drive-ide2","throttle-group":"throttle-drive-ide2"}' \
+ -device 'ide-cd,bus=ide.1,unit=0,id=ide2,drive=drive-ide2,bootindex=202' \
+ -object '{"id":"throttle-drive-ide3","limits":{},"qom-type":"throttle-group"}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"threads","cache":{"direct":false,"no-flush":false},"driver":"file","filename":"/mnt/pve/cifs-store/template/iso/three.iso","node-name":"e-UKCOEDGubQ8AywsAyqqGIywCIWQ"},"node-name":"f-UKCOEDGubQ8AywsAyqqGIywCIWQ","read-only":true},"node-name":"drive-ide3","throttle-group":"throttle-drive-ide3"}' \
+ -device 'ide-cd,bus=ide.3,unit=0,id=ide3,drive=drive-ide3,bootindex=203' \
+ -device 'virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5' \
+ -object '{"id":"throttle-drive-scsi0","limits":{},"qom-type":"throttle-group"}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"on","discard":"ignore","driver":"file","filename":"/var/lib/vz/images/100/vm-100-disk-2.qcow2","node-name":"e-6zrMeiDDrkeISyGMGwACygKAISG"},"node-name":"f-6zrMeiDDrkeISyGMGwACygKAISG","read-only":false},"node-name":"drive-scsi0","throttle-group":"throttle-drive-scsi0"}' \
+ -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,bootindex=100' \
+ -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=2E:01:68:F9:9C:87,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256,bootindex=300' \
+ -machine 'type=q35+pve0'
diff --git a/test/cfg2cmd/q35-ide.conf b/test/cfg2cmd/q35-ide.conf
index bfef0a14..6a091141 100644
--- a/test/cfg2cmd/q35-ide.conf
+++ b/test/cfg2cmd/q35-ide.conf
@@ -5,7 +5,7 @@ ide0: cifs-store:iso/zero.iso,media=cdrom,size=112M
ide1: cifs-store:iso/one.iso,media=cdrom,size=112M
ide2: cifs-store:iso/two.iso,media=cdrom,size=112M
ide3: cifs-store:iso/three.iso,media=cdrom,size=112M
-machine: q35
+machine: pc-q35-9.2+pve1
memory: 512
net0: virtio=2E:01:68:F9:9C:87,bridge=vmbr0
ostype: l26
diff --git a/test/cfg2cmd/q35-ide.conf.cmd b/test/cfg2cmd/q35-ide.conf.cmd
index 4e910ff7..e88fd744 100644
--- a/test/cfg2cmd/q35-ide.conf.cmd
+++ b/test/cfg2cmd/q35-ide.conf.cmd
@@ -9,7 +9,6 @@
-pidfile /var/run/qemu-server/8006.pid \
-daemonize \
-smbios 'type=1,uuid=3dd750ce-d910-44d0-9493-525c0be4e687' \
- -global 'ICH9-LPC.acpi-pci-hotplug-with-bridge-support=off' \
-smp '2,sockets=1,cores=2,maxcpus=2' \
-nodefaults \
-boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
@@ -37,4 +36,4 @@
-device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,bootindex=100' \
-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=2E:01:68:F9:9C:87,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256,bootindex=300' \
- -machine 'type=q35+pve1'
+ -machine 'type=pc-q35-9.2+pve1'
diff --git a/test/cfg2cmd/q35-linux-hostpci-mapping.conf.cmd b/test/cfg2cmd/q35-linux-hostpci-mapping.conf.cmd
index 533e1983..2d66cb66 100644
--- a/test/cfg2cmd/q35-linux-hostpci-mapping.conf.cmd
+++ b/test/cfg2cmd/q35-linux-hostpci-mapping.conf.cmd
@@ -35,4 +35,4 @@
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-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=2E:01:68:F9:9C:87,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256,bootindex=300' \
- -machine 'type=q35+pve1'
+ -machine 'type=q35+pve0'
diff --git a/test/cfg2cmd/q35-linux-hostpci-multifunction.conf.cmd b/test/cfg2cmd/q35-linux-hostpci-multifunction.conf.cmd
index 07609745..146bf3e5 100644
--- a/test/cfg2cmd/q35-linux-hostpci-multifunction.conf.cmd
+++ b/test/cfg2cmd/q35-linux-hostpci-multifunction.conf.cmd
@@ -35,4 +35,4 @@
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-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=2E:01:68:F9:9C:87,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256,bootindex=300' \
- -machine 'type=q35+pve1'
+ -machine 'type=q35+pve0'
diff --git a/test/cfg2cmd/q35-linux-hostpci-template.conf.cmd b/test/cfg2cmd/q35-linux-hostpci-template.conf.cmd
index 1bf1feb6..fa75d393 100644
--- a/test/cfg2cmd/q35-linux-hostpci-template.conf.cmd
+++ b/test/cfg2cmd/q35-linux-hostpci-template.conf.cmd
@@ -26,7 +26,8 @@
-device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-device 'virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5' \
- -drive 'file=/var/lib/vz/images/100/base-100-disk-2.raw,if=none,id=drive-scsi0,format=raw,cache=none,aio=io_uring,detect-zeroes=on,readonly=on' \
+ -object '{"id":"throttle-drive-scsi0","limits":{},"qom-type":"throttle-group"}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"on","discard":"ignore","driver":"file","filename":"/var/lib/vz/images/100/base-100-disk-2.raw","node-name":"e-3nPTM162JEOAymkwqg2Ww2QUioK"},"node-name":"f-3nPTM162JEOAymkwqg2Ww2QUioK","read-only":true},"node-name":"drive-scsi0","throttle-group":"throttle-drive-scsi0"}' \
-device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0' \
- -machine 'accel=tcg,type=pc+pve1' \
+ -machine 'accel=tcg,type=pc+pve0' \
-snapshot
diff --git a/test/cfg2cmd/q35-linux-hostpci-x-pci-overrides.conf.cmd b/test/cfg2cmd/q35-linux-hostpci-x-pci-overrides.conf.cmd
index ca8e03b9..96f9da18 100644
--- a/test/cfg2cmd/q35-linux-hostpci-x-pci-overrides.conf.cmd
+++ b/test/cfg2cmd/q35-linux-hostpci-x-pci-overrides.conf.cmd
@@ -11,7 +11,7 @@
-smbios 'type=1,uuid=3dd750ce-d910-44d0-9493-525c0be4e687' \
-drive 'if=pflash,unit=0,format=raw,readonly=on,file=/usr/share/pve-edk2-firmware//OVMF_CODE.fd' \
-drive 'if=pflash,unit=1,id=drive-efidisk0,format=qcow2,file=/var/lib/vz/images/100/vm-100-disk-1.qcow2' \
- -global 'ICH9-LPC.acpi-pci-hotplug-with-bridge-support=off' \
+ -global 'ICH9-LPC.acpi-pci-hotplug-with-bridge-support=off'
-smp '2,sockets=2,cores=1,maxcpus=2' \
-nodefaults \
-boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
@@ -34,4 +34,4 @@
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-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=2E:01:68:F9:9C:87,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256,bootindex=300' \
- -machine 'type=q35+pve1'
+ -machine 'type=q35+pve0'
diff --git a/test/cfg2cmd/q35-linux-hostpci.conf.cmd b/test/cfg2cmd/q35-linux-hostpci.conf.cmd
index 1bebae18..0abb569b 100644
--- a/test/cfg2cmd/q35-linux-hostpci.conf.cmd
+++ b/test/cfg2cmd/q35-linux-hostpci.conf.cmd
@@ -40,4 +40,4 @@
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-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=2E:01:68:F9:9C:87,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256,bootindex=300' \
- -machine 'type=q35+pve1'
+ -machine 'type=q35+pve0'
diff --git a/test/cfg2cmd/q35-simple.conf.cmd b/test/cfg2cmd/q35-simple.conf.cmd
index f42b42d5..371ea7dd 100644
--- a/test/cfg2cmd/q35-simple.conf.cmd
+++ b/test/cfg2cmd/q35-simple.conf.cmd
@@ -28,4 +28,4 @@
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-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=2E:01:68:F9:9C:87,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256,bootindex=300' \
- -machine 'type=q35+pve1'
+ -machine 'type=q35+pve0'
diff --git a/test/cfg2cmd/q35-viommu-intel.conf.cmd b/test/cfg2cmd/q35-viommu-intel.conf.cmd
index 6f71bf07..2ddc57ca 100644
--- a/test/cfg2cmd/q35-viommu-intel.conf.cmd
+++ b/test/cfg2cmd/q35-viommu-intel.conf.cmd
@@ -22,4 +22,4 @@
-device 'VGA,id=vga,bus=pcie.0,addr=0x1' \
-device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
- -machine 'type=q35+pve1,kernel-irqchip=split'
+ -machine 'type=q35+pve0,kernel-irqchip=split'
diff --git a/test/cfg2cmd/q35-viommu-virtio.conf.cmd b/test/cfg2cmd/q35-viommu-virtio.conf.cmd
index bf05eff0..0ae11208 100644
--- a/test/cfg2cmd/q35-viommu-virtio.conf.cmd
+++ b/test/cfg2cmd/q35-viommu-virtio.conf.cmd
@@ -22,4 +22,4 @@
-device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-device virtio-iommu-pci \
- -machine 'type=q35+pve1'
+ -machine 'type=q35+pve0'
diff --git a/test/cfg2cmd/seabios_serial.conf b/test/cfg2cmd/seabios_serial.conf
index 7ebfa504..d2ebe57a 100644
--- a/test/cfg2cmd/seabios_serial.conf
+++ b/test/cfg2cmd/seabios_serial.conf
@@ -1,14 +1,10 @@
# TEST: Test for smm-related regression with SeaBIOS and serial display
-bootdisk: scsi0
cores: 3
-ide2: none,media=cdrom
memory: 768
name: seabiosserial
net0: virtio=A2:C0:43:77:08:A0,bridge=vmbr0
numa: 0
ostype: l26
-scsi0: local:8006/vm-8006-disk-0.qcow2,discard=on,size=104858K
-scsihw: virtio-scsi-pci
serial0: socket
smbios1: uuid=7b10d7af-b932-4c66-b2c3-3996152ec465
sockets: 1
diff --git a/test/cfg2cmd/seabios_serial.conf.cmd b/test/cfg2cmd/seabios_serial.conf.cmd
index 114c6752..82b72bb8 100644
--- a/test/cfg2cmd/seabios_serial.conf.cmd
+++ b/test/cfg2cmd/seabios_serial.conf.cmd
@@ -25,11 +25,6 @@
-device 'isa-serial,chardev=serial0' \
-device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
- -drive 'if=none,id=drive-ide2,media=cdrom,aio=io_uring' \
- -device 'ide-cd,bus=ide.1,unit=0,drive=drive-ide2,id=ide2,bootindex=200' \
- -device 'virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5' \
- -drive 'file=/var/lib/vz/images/8006/vm-8006-disk-0.qcow2,if=none,id=drive-scsi0,discard=on,format=qcow2,cache=none,aio=io_uring,detect-zeroes=unmap' \
- -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,bootindex=100' \
-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' \
- -machine 'smm=off,type=pc+pve1'
+ -machine 'smm=off,type=pc+pve0'
diff --git a/test/cfg2cmd/sev-es.conf.cmd b/test/cfg2cmd/sev-es.conf.cmd
index 266b63a5..3a100306 100644
--- a/test/cfg2cmd/sev-es.conf.cmd
+++ b/test/cfg2cmd/sev-es.conf.cmd
@@ -27,4 +27,4 @@
-device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-object 'sev-guest,id=sev0,cbitpos=51,reduced-phys-bits=6,policy=0xc' \
- -machine 'type=pc+pve1,confidential-guest-support=sev0'
+ -machine 'type=pc+pve0,confidential-guest-support=sev0'
diff --git a/test/cfg2cmd/sev-snp.conf.cmd b/test/cfg2cmd/sev-snp.conf.cmd
index 858ba0d9..3308e86e 100644
--- a/test/cfg2cmd/sev-snp.conf.cmd
+++ b/test/cfg2cmd/sev-snp.conf.cmd
@@ -26,4 +26,4 @@
-device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-object 'sev-snp-guest,id=sev0,cbitpos=51,reduced-phys-bits=6,policy=0xb0000' \
- -machine 'type=pc+pve1,confidential-guest-support=sev0'
+ -machine 'type=pc+pve0,confidential-guest-support=sev0'
diff --git a/test/cfg2cmd/sev-std.conf.cmd b/test/cfg2cmd/sev-std.conf.cmd
index 76edce07..06da2ca0 100644
--- a/test/cfg2cmd/sev-std.conf.cmd
+++ b/test/cfg2cmd/sev-std.conf.cmd
@@ -27,4 +27,4 @@
-device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-object 'sev-guest,id=sev0,cbitpos=51,reduced-phys-bits=6,policy=0x8' \
- -machine 'type=pc+pve1,confidential-guest-support=sev0'
+ -machine 'type=pc+pve0,confidential-guest-support=sev0'
diff --git a/test/cfg2cmd/simple-btrfs.conf b/test/cfg2cmd/simple-btrfs.conf
index e18d1349..d9185cfd 100644
--- a/test/cfg2cmd/simple-btrfs.conf
+++ b/test/cfg2cmd/simple-btrfs.conf
@@ -2,6 +2,7 @@
bootdisk: scsi0
cores: 3
ide2: none,media=cdrom
+machine: pc-i440fx-9.2+pve1
memory: 768
name: simple
net0: virtio=A2:C0:43:77:08:A0,bridge=vmbr0
diff --git a/test/cfg2cmd/simple-btrfs.conf.cmd b/test/cfg2cmd/simple-btrfs.conf.cmd
index 2d92b0f6..192e9869 100644
--- a/test/cfg2cmd/simple-btrfs.conf.cmd
+++ b/test/cfg2cmd/simple-btrfs.conf.cmd
@@ -32,4 +32,4 @@
-device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,bootindex=100' \
-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' \
- -machine 'type=pc+pve1'
+ -machine 'type=pc-i440fx-9.2+pve1'
diff --git a/test/cfg2cmd/simple-disk-passthrough-blockdev.conf b/test/cfg2cmd/simple-disk-passthrough-blockdev.conf
new file mode 100644
index 00000000..308da4ab
--- /dev/null
+++ b/test/cfg2cmd/simple-disk-passthrough-blockdev.conf
@@ -0,0 +1,15 @@
+# TEST: Simple test for disk && cdrom passthrough
+bootdisk: scsi0
+cores: 3
+ide2: cdrom,media=cdrom
+memory: 768
+name: simple
+net0: virtio=A2:C0:43:77:08:A0,bridge=vmbr0
+numa: 0
+ostype: l26
+scsi0: /dev/sda
+scsi1: /mnt/file.raw
+scsihw: virtio-scsi-pci
+smbios1: uuid=7b10d7af-b932-4c66-b2c3-3996152ec465
+sockets: 1
+vmgenid: c773c261-d800-4348-9f5d-167fadd53cf8
diff --git a/test/cfg2cmd/simple-disk-passthrough-blockdev.conf.cmd b/test/cfg2cmd/simple-disk-passthrough-blockdev.conf.cmd
new file mode 100644
index 00000000..eb903b9c
--- /dev/null
+++ b/test/cfg2cmd/simple-disk-passthrough-blockdev.conf.cmd
@@ -0,0 +1,40 @@
+/usr/bin/kvm \
+ -id 8006 \
+ -name 'simple,debug-threads=on' \
+ -no-shutdown \
+ -chardev 'socket,id=qmp,path=/var/run/qemu-server/8006.qmp,server=on,wait=off' \
+ -mon 'chardev=qmp,mode=control' \
+ -chardev 'socket,id=qmp-event,path=/var/run/qmeventd.sock,reconnect-ms=5000' \
+ -mon 'chardev=qmp-event,mode=control' \
+ -pidfile /var/run/qemu-server/8006.pid \
+ -daemonize \
+ -smbios 'type=1,uuid=7b10d7af-b932-4c66-b2c3-3996152ec465' \
+ -smp '3,sockets=1,cores=3,maxcpus=3' \
+ -nodefaults \
+ -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
+ -vnc 'unix:/var/run/qemu-server/8006.vnc,password=on' \
+ -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
+ -m 768 \
+ -global 'PIIX4_PM.disable_s3=1' \
+ -global 'PIIX4_PM.disable_s4=1' \
+ -device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \
+ -device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \
+ -device 'vmgenid,guid=c773c261-d800-4348-9f5d-167fadd53cf8' \
+ -device 'piix3-usb-uhci,id=uhci,bus=pci.0,addr=0x1.0x2' \
+ -device 'usb-tablet,id=tablet,bus=uhci.0,port=1' \
+ -device 'VGA,id=vga,bus=pci.0,addr=0x2' \
+ -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
+ -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
+ -object '{"id":"throttle-drive-ide2","limits":{},"qom-type":"throttle-group"}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":false,"no-flush":false},"driver":"raw","file":{"aio":"threads","cache":{"direct":false,"no-flush":false},"driver":"host_cdrom","filename":"/dev/cdrom","node-name":"e-59mSJaWzNY8Eg6eyOAiKqyoU6Q4"},"node-name":"f-59mSJaWzNY8Eg6eyOAiKqyoU6Q4","read-only":true},"node-name":"drive-ide2","throttle-group":"throttle-drive-ide2"}' \
+ -device 'ide-cd,bus=ide.1,unit=0,id=ide2,drive=drive-ide2,bootindex=200' \
+ -device 'virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5' \
+ -object '{"id":"throttle-drive-scsi0","limits":{},"qom-type":"throttle-group"}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"on","discard":"ignore","driver":"host_device","filename":"/dev/sda","node-name":"e-4BHkNLIiz2quuiY0o0yQ2WO8SUG"},"node-name":"f-4BHkNLIiz2quuiY0o0yQ2WO8SUG","read-only":false},"node-name":"drive-scsi0","throttle-group":"throttle-drive-scsi0"}' \
+ -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,bootindex=100' \
+ -object '{"id":"throttle-drive-scsi1","limits":{},"qom-type":"throttle-group"}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"on","discard":"ignore","driver":"file","filename":"/mnt/file.raw","node-name":"e-4Z0R2kiQGecKCcma0k2qO0CCQ0O"},"node-name":"f-4Z0R2kiQGecKCcma0k2qO0CCQ0O","read-only":false},"node-name":"drive-scsi1","throttle-group":"throttle-drive-scsi1"}' \
+ -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=1,drive=drive-scsi1,id=scsi1' \
+ -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' \
+ -machine 'type=pc+pve0'
diff --git a/test/cfg2cmd/simple-disk-passthrough.conf b/test/cfg2cmd/simple-disk-passthrough.conf
index 308da4ab..274709b9 100644
--- a/test/cfg2cmd/simple-disk-passthrough.conf
+++ b/test/cfg2cmd/simple-disk-passthrough.conf
@@ -2,6 +2,7 @@
bootdisk: scsi0
cores: 3
ide2: cdrom,media=cdrom
+machine: pc-i440fx-9.2+pve1
memory: 768
name: simple
net0: virtio=A2:C0:43:77:08:A0,bridge=vmbr0
diff --git a/test/cfg2cmd/simple-disk-passthrough.conf.cmd b/test/cfg2cmd/simple-disk-passthrough.conf.cmd
index ca613a8f..add6c6e2 100644
--- a/test/cfg2cmd/simple-disk-passthrough.conf.cmd
+++ b/test/cfg2cmd/simple-disk-passthrough.conf.cmd
@@ -34,4 +34,4 @@
-device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=1,drive=drive-scsi1,id=scsi1' \
-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' \
- -machine 'type=pc+pve1'
+ -machine 'type=pc-i440fx-9.2+pve1'
diff --git a/test/cfg2cmd/simple-rbd-blockdev.conf b/test/cfg2cmd/simple-rbd-blockdev.conf
new file mode 100644
index 00000000..535491de
--- /dev/null
+++ b/test/cfg2cmd/simple-rbd-blockdev.conf
@@ -0,0 +1,15 @@
+# TEST: Simple test for RBD && KRBD backend vm
+bootdisk: scsi0
+cores: 3
+ide2: none,media=cdrom
+memory: 768
+name: simple
+net0: virtio=A2:C0:43:77:08:A0,bridge=vmbr0
+numa: 0
+ostype: l26
+scsi0: rbd-store:vm-8006-disk-0,discard=on,size=104858K
+scsi1: krbd-store:vm-8006-disk-0,discard=on,size=104858K
+scsihw: virtio-scsi-pci
+smbios1: uuid=7b10d7af-b932-4c66-b2c3-3996152ec465
+sockets: 1
+vmgenid: c773c261-d800-4348-1010-1010add53cf8
diff --git a/test/cfg2cmd/simple-rbd-blockdev.conf.cmd b/test/cfg2cmd/simple-rbd-blockdev.conf.cmd
new file mode 100644
index 00000000..5039639c
--- /dev/null
+++ b/test/cfg2cmd/simple-rbd-blockdev.conf.cmd
@@ -0,0 +1,38 @@
+/usr/bin/kvm \
+ -id 8006 \
+ -name 'simple,debug-threads=on' \
+ -no-shutdown \
+ -chardev 'socket,id=qmp,path=/var/run/qemu-server/8006.qmp,server=on,wait=off' \
+ -mon 'chardev=qmp,mode=control' \
+ -chardev 'socket,id=qmp-event,path=/var/run/qmeventd.sock,reconnect-ms=5000' \
+ -mon 'chardev=qmp-event,mode=control' \
+ -pidfile /var/run/qemu-server/8006.pid \
+ -daemonize \
+ -smbios 'type=1,uuid=7b10d7af-b932-4c66-b2c3-3996152ec465' \
+ -smp '3,sockets=1,cores=3,maxcpus=3' \
+ -nodefaults \
+ -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
+ -vnc 'unix:/var/run/qemu-server/8006.vnc,password=on' \
+ -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
+ -m 768 \
+ -global 'PIIX4_PM.disable_s3=1' \
+ -global 'PIIX4_PM.disable_s4=1' \
+ -device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \
+ -device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \
+ -device 'vmgenid,guid=c773c261-d800-4348-1010-1010add53cf8' \
+ -device 'piix3-usb-uhci,id=uhci,bus=pci.0,addr=0x1.0x2' \
+ -device 'usb-tablet,id=tablet,bus=uhci.0,port=1' \
+ -device 'VGA,id=vga,bus=pci.0,addr=0x2' \
+ -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
+ -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
+ -device 'ide-cd,bus=ide.1,unit=0,id=ide2,bootindex=200' \
+ -device 'virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5' \
+ -object '{"id":"throttle-drive-scsi0","limits":{},"qom-type":"throttle-group"}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"auth-client-required":["none"],"cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"rbd","image":"vm-8006-disk-0","node-name":"e-WH7PdKLViYcsYSWkcQoqQ0U40uI","pool":"cpool","server":[{"host":"127.0.0.42","port":"3300"},{"host":"127.0.0.21","port":"3300"},{"host":"::1","port":"3300"}]},"node-name":"f-WH7PdKLViYcsYSWkcQoqQ0U40uI","read-only":false},"node-name":"drive-scsi0","throttle-group":"throttle-drive-scsi0"}' \
+ -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,bootindex=100' \
+ -object '{"id":"throttle-drive-scsi1","limits":{},"qom-type":"throttle-group"}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"host_device","filename":"/dev/rbd-pve/fc4181a6-56eb-4f68-b452-8ba1f381ca2a/cpool/vm-8006-disk-0","node-name":"e-426qW8R920KGyGqY480ymoSywiU"},"node-name":"f-426qW8R920KGyGqY480ymoSywiU","read-only":false},"node-name":"drive-scsi1","throttle-group":"throttle-drive-scsi1"}' \
+ -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=1,drive=drive-scsi1,id=scsi1'
+ -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' \
+ -machine 'type=pc+pve0'
diff --git a/test/cfg2cmd/simple-rbd.conf b/test/cfg2cmd/simple-rbd.conf
index 535491de..491fe1c7 100644
--- a/test/cfg2cmd/simple-rbd.conf
+++ b/test/cfg2cmd/simple-rbd.conf
@@ -2,6 +2,7 @@
bootdisk: scsi0
cores: 3
ide2: none,media=cdrom
+machine: pc-i440fx-9.2+pve1
memory: 768
name: simple
net0: virtio=A2:C0:43:77:08:A0,bridge=vmbr0
diff --git a/test/cfg2cmd/simple-rbd.conf.cmd b/test/cfg2cmd/simple-rbd.conf.cmd
index 644ff18c..2ba43bbf 100644
--- a/test/cfg2cmd/simple-rbd.conf.cmd
+++ b/test/cfg2cmd/simple-rbd.conf.cmd
@@ -34,4 +34,4 @@
-device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=1,drive=drive-scsi1,id=scsi1'
-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' \
- -machine 'type=pc+pve1'
+ -machine 'type=pc-i440fx-9.2+pve1'
diff --git a/test/cfg2cmd/simple-virtio-blk-blockdev.conf b/test/cfg2cmd/simple-virtio-blk-blockdev.conf
new file mode 100644
index 00000000..d9db7580
--- /dev/null
+++ b/test/cfg2cmd/simple-virtio-blk-blockdev.conf
@@ -0,0 +1,13 @@
+# TEST: Test for a basic configuration with a VirtIO Block IOThread disk
+bootdisk: virtio0
+cores: 3
+ide2: none,media=cdrom
+memory: 768
+name: simple
+net0: virtio=A2:C0:43:77:08:A0,bridge=vmbr0
+numa: 0
+ostype: l26
+smbios1: uuid=7b10d7af-b932-4c66-b2c3-3996152ec465
+sockets: 1
+virtio0: local:8006/vm-8006-disk-0.qcow2,discard=on,iothread=1,size=104858K
+vmgenid: c773c261-d800-4348-9f5d-167fadd53cf8
diff --git a/test/cfg2cmd/simple-virtio-blk-blockdev.conf.cmd b/test/cfg2cmd/simple-virtio-blk-blockdev.conf.cmd
new file mode 100644
index 00000000..e1aee040
--- /dev/null
+++ b/test/cfg2cmd/simple-virtio-blk-blockdev.conf.cmd
@@ -0,0 +1,35 @@
+/usr/bin/kvm \
+ -id 8006 \
+ -name 'simple,debug-threads=on' \
+ -no-shutdown \
+ -chardev 'socket,id=qmp,path=/var/run/qemu-server/8006.qmp,server=on,wait=off' \
+ -mon 'chardev=qmp,mode=control' \
+ -chardev 'socket,id=qmp-event,path=/var/run/qmeventd.sock,reconnect-ms=5000' \
+ -mon 'chardev=qmp-event,mode=control' \
+ -pidfile /var/run/qemu-server/8006.pid \
+ -daemonize \
+ -smbios 'type=1,uuid=7b10d7af-b932-4c66-b2c3-3996152ec465' \
+ -smp '3,sockets=1,cores=3,maxcpus=3' \
+ -nodefaults \
+ -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
+ -vnc 'unix:/var/run/qemu-server/8006.vnc,password=on' \
+ -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
+ -m 768 \
+ -object 'iothread,id=iothread-virtio0' \
+ -global 'PIIX4_PM.disable_s3=1' \
+ -global 'PIIX4_PM.disable_s4=1' \
+ -device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \
+ -device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \
+ -device 'vmgenid,guid=c773c261-d800-4348-9f5d-167fadd53cf8' \
+ -device 'piix3-usb-uhci,id=uhci,bus=pci.0,addr=0x1.0x2' \
+ -device 'usb-tablet,id=tablet,bus=uhci.0,port=1' \
+ -device 'VGA,id=vga,bus=pci.0,addr=0x2' \
+ -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
+ -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
+ -device 'ide-cd,bus=ide.1,unit=0,id=ide2,bootindex=200' \
+ -object '{"id":"throttle-drive-virtio0","limits":{},"qom-type":"throttle-group"}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-0.qcow2","node-name":"e-IQHs2Stp3mYmKYSGmUACmUu8i6u"},"node-name":"f-IQHs2Stp3mYmKYSGmUACmUu8i6u","read-only":false},"node-name":"drive-virtio0","throttle-group":"throttle-drive-virtio0"}' \
+ -device 'virtio-blk-pci,drive=drive-virtio0,id=virtio0,bus=pci.0,addr=0xa,iothread=iothread-virtio0,bootindex=100' \
+ -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' \
+ -machine 'type=pc+pve0'
diff --git a/test/cfg2cmd/simple-virtio-blk.conf b/test/cfg2cmd/simple-virtio-blk.conf
index d9db7580..0b92852a 100644
--- a/test/cfg2cmd/simple-virtio-blk.conf
+++ b/test/cfg2cmd/simple-virtio-blk.conf
@@ -2,6 +2,7 @@
bootdisk: virtio0
cores: 3
ide2: none,media=cdrom
+machine: pc-i440fx-9.2+pve1
memory: 768
name: simple
net0: virtio=A2:C0:43:77:08:A0,bridge=vmbr0
diff --git a/test/cfg2cmd/simple-virtio-blk.conf.cmd b/test/cfg2cmd/simple-virtio-blk.conf.cmd
index 1680f541..092cffd1 100644
--- a/test/cfg2cmd/simple-virtio-blk.conf.cmd
+++ b/test/cfg2cmd/simple-virtio-blk.conf.cmd
@@ -32,4 +32,4 @@
-device 'virtio-blk-pci,drive=drive-virtio0,id=virtio0,bus=pci.0,addr=0xa,iothread=iothread-virtio0,bootindex=100' \
-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' \
- -machine 'type=pc+pve1'
+ -machine 'type=pc-i440fx-9.2+pve1'
diff --git a/test/cfg2cmd/simple-zfs-over-iscsi-blockdev.conf b/test/cfg2cmd/simple-zfs-over-iscsi-blockdev.conf
new file mode 100644
index 00000000..055c6fc4
--- /dev/null
+++ b/test/cfg2cmd/simple-zfs-over-iscsi-blockdev.conf
@@ -0,0 +1,14 @@
+# TEST: Simple test for zfs-over-scsi backed VM.
+bootdisk: scsi0
+cores: 3
+ide2: none,media=cdrom
+memory: 768
+name: simple
+net0: virtio=A2:C0:43:77:08:A0,bridge=vmbr0
+numa: 0
+ostype: l26
+scsi0: zfs-over-iscsi-store:vm-8006-disk-0,discard=on,size=104858K
+scsihw: virtio-scsi-pci
+smbios1: uuid=7b10d7af-b932-4c66-b2c3-3996152ec465
+sockets: 1
+vmgenid: c773c261-d800-4348-1010-1010add53cf8
diff --git a/test/cfg2cmd/simple-zfs-over-iscsi-blockdev.conf.cmd b/test/cfg2cmd/simple-zfs-over-iscsi-blockdev.conf.cmd
new file mode 100644
index 00000000..2e97685f
--- /dev/null
+++ b/test/cfg2cmd/simple-zfs-over-iscsi-blockdev.conf.cmd
@@ -0,0 +1,35 @@
+/usr/bin/kvm \
+ -id 8006 \
+ -name 'simple,debug-threads=on' \
+ -no-shutdown \
+ -chardev 'socket,id=qmp,path=/var/run/qemu-server/8006.qmp,server=on,wait=off' \
+ -mon 'chardev=qmp,mode=control' \
+ -chardev 'socket,id=qmp-event,path=/var/run/qmeventd.sock,reconnect-ms=5000' \
+ -mon 'chardev=qmp-event,mode=control' \
+ -pidfile /var/run/qemu-server/8006.pid \
+ -daemonize \
+ -smbios 'type=1,uuid=7b10d7af-b932-4c66-b2c3-3996152ec465' \
+ -smp '3,sockets=1,cores=3,maxcpus=3' \
+ -nodefaults \
+ -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
+ -vnc 'unix:/var/run/qemu-server/8006.vnc,password=on' \
+ -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
+ -m 768 \
+ -global 'PIIX4_PM.disable_s3=1' \
+ -global 'PIIX4_PM.disable_s4=1' \
+ -device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \
+ -device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \
+ -device 'vmgenid,guid=c773c261-d800-4348-1010-1010add53cf8' \
+ -device 'piix3-usb-uhci,id=uhci,bus=pci.0,addr=0x1.0x2' \
+ -device 'usb-tablet,id=tablet,bus=uhci.0,port=1' \
+ -device 'VGA,id=vga,bus=pci.0,addr=0x2' \
+ -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
+ -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
+ -device 'ide-cd,bus=ide.1,unit=0,id=ide2,bootindex=200' \
+ -device 'virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5' \
+ -object '{"id":"throttle-drive-scsi0","limits":{},"qom-type":"throttle-group"}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"iscsi","lun":0,"node-name":"e-R6iR6TPY7y2M8YsIOasguK8KEEo","portal":"127.0.0.1","target":"iqn.2019-10.org.test:foobar","transport":"tcp"},"node-name":"f-R6iR6TPY7y2M8YsIOasguK8KEEo","read-only":false},"node-name":"drive-scsi0","throttle-group":"throttle-drive-scsi0"}' \
+ -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,bootindex=100' \
+ -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' \
+ -machine 'type=pc+pve0'
diff --git a/test/cfg2cmd/simple-zfs-over-iscsi.conf b/test/cfg2cmd/simple-zfs-over-iscsi.conf
index 055c6fc4..5d77d4e8 100644
--- a/test/cfg2cmd/simple-zfs-over-iscsi.conf
+++ b/test/cfg2cmd/simple-zfs-over-iscsi.conf
@@ -2,6 +2,7 @@
bootdisk: scsi0
cores: 3
ide2: none,media=cdrom
+machine: pc-i440fx-9.2+pve1
memory: 768
name: simple
net0: virtio=A2:C0:43:77:08:A0,bridge=vmbr0
diff --git a/test/cfg2cmd/simple-zfs-over-iscsi.conf.cmd b/test/cfg2cmd/simple-zfs-over-iscsi.conf.cmd
index 196d74d4..fc0626ae 100644
--- a/test/cfg2cmd/simple-zfs-over-iscsi.conf.cmd
+++ b/test/cfg2cmd/simple-zfs-over-iscsi.conf.cmd
@@ -32,4 +32,4 @@
-device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,bootindex=100' \
-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' \
- -machine 'type=pc+pve1'
+ -machine 'type=pc-i440fx-9.2+pve1'
diff --git a/test/cfg2cmd/simple1-blockdev.conf b/test/cfg2cmd/simple1-blockdev.conf
new file mode 100644
index 00000000..9feb9d26
--- /dev/null
+++ b/test/cfg2cmd/simple1-blockdev.conf
@@ -0,0 +1,14 @@
+# TEST: Simple test for a basic configuration with no special things
+bootdisk: scsi0
+cores: 3
+ide2: none,media=cdrom
+memory: 768
+name: simple
+net0: virtio=A2:C0:43:77:08:A0,bridge=vmbr0
+numa: 0
+ostype: l26
+scsi0: local:8006/vm-8006-disk-0.qcow2,discard=on,size=104858K
+scsihw: virtio-scsi-pci
+smbios1: uuid=7b10d7af-b932-4c66-b2c3-3996152ec465
+sockets: 1
+vmgenid: c773c261-d800-4348-9f5d-167fadd53cf8
diff --git a/test/cfg2cmd/simple1-blockdev.conf.cmd b/test/cfg2cmd/simple1-blockdev.conf.cmd
new file mode 100644
index 00000000..6d960396
--- /dev/null
+++ b/test/cfg2cmd/simple1-blockdev.conf.cmd
@@ -0,0 +1,35 @@
+/usr/bin/kvm \
+ -id 8006 \
+ -name 'simple,debug-threads=on' \
+ -no-shutdown \
+ -chardev 'socket,id=qmp,path=/var/run/qemu-server/8006.qmp,server=on,wait=off' \
+ -mon 'chardev=qmp,mode=control' \
+ -chardev 'socket,id=qmp-event,path=/var/run/qmeventd.sock,reconnect-ms=5000' \
+ -mon 'chardev=qmp-event,mode=control' \
+ -pidfile /var/run/qemu-server/8006.pid \
+ -daemonize \
+ -smbios 'type=1,uuid=7b10d7af-b932-4c66-b2c3-3996152ec465' \
+ -smp '3,sockets=1,cores=3,maxcpus=3' \
+ -nodefaults \
+ -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
+ -vnc 'unix:/var/run/qemu-server/8006.vnc,password=on' \
+ -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
+ -m 768 \
+ -global 'PIIX4_PM.disable_s3=1' \
+ -global 'PIIX4_PM.disable_s4=1' \
+ -device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \
+ -device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \
+ -device 'vmgenid,guid=c773c261-d800-4348-9f5d-167fadd53cf8' \
+ -device 'piix3-usb-uhci,id=uhci,bus=pci.0,addr=0x1.0x2' \
+ -device 'usb-tablet,id=tablet,bus=uhci.0,port=1' \
+ -device 'VGA,id=vga,bus=pci.0,addr=0x2' \
+ -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
+ -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
+ -device 'ide-cd,bus=ide.1,unit=0,id=ide2,bootindex=200' \
+ -device 'virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5' \
+ -object '{"id":"throttle-drive-scsi0","limits":{},"qom-type":"throttle-group"}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-0.qcow2","node-name":"e-IQHs2Stp3mYmKYSGmUACmUu8i6u"},"node-name":"f-IQHs2Stp3mYmKYSGmUACmUu8i6u","read-only":false},"node-name":"drive-scsi0","throttle-group":"throttle-drive-scsi0"}' \
+ -device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,bootindex=100' \
+ -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' \
+ -machine 'type=pc+pve0'
diff --git a/test/cfg2cmd/simple1-template.conf.cmd b/test/cfg2cmd/simple1-template.conf.cmd
index 1de512e8..28be21c4 100644
--- a/test/cfg2cmd/simple1-template.conf.cmd
+++ b/test/cfg2cmd/simple1-template.conf.cmd
@@ -23,13 +23,14 @@
-device 'usb-tablet,id=tablet,bus=uhci.0,port=1' \
-device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
- -drive 'if=none,id=drive-ide2,media=cdrom,aio=io_uring' \
- -device 'ide-cd,bus=ide.1,unit=0,drive=drive-ide2,id=ide2,bootindex=200' \
+ -device 'ide-cd,bus=ide.1,unit=0,id=ide2,bootindex=200' \
-device 'virtio-scsi-pci,id=scsihw0,bus=pci.0,addr=0x5' \
- -drive 'file=/var/lib/vz/images/8006/base-8006-disk-1.qcow2,if=none,id=drive-scsi0,discard=on,format=qcow2,cache=none,aio=io_uring,detect-zeroes=unmap,readonly=on' \
+ -object '{"id":"throttle-drive-scsi0","limits":{},"qom-type":"throttle-group"}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/base-8006-disk-1.qcow2","node-name":"e-ZRitpbHqRyeSoKUmIwwMc4Uq0oQ"},"node-name":"f-ZRitpbHqRyeSoKUmIwwMc4Uq0oQ","read-only":true},"node-name":"drive-scsi0","throttle-group":"throttle-drive-scsi0"}' \
-device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0' \
-device 'ahci,id=ahci0,multifunction=on,bus=pci.0,addr=0x7' \
- -drive 'file=/var/lib/vz/images/8006/base-8006-disk-0.qcow2,if=none,id=drive-sata0,discard=on,format=qcow2,cache=none,aio=io_uring,detect-zeroes=unmap' \
- -device 'ide-hd,bus=ahci0.0,drive=drive-sata0,id=sata0' \
- -machine 'accel=tcg,smm=off,type=pc+pve1' \
+ -object '{"id":"throttle-drive-sata0","limits":{},"qom-type":"throttle-group"}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"unmap","discard":"unmap","driver":"file","filename":"/var/lib/vz/images/8006/base-8006-disk-0.qcow2","node-name":"e-Nc8rhHZ7kcE2uuU2M8keyicwm0w"},"node-name":"f-Nc8rhHZ7kcE2uuU2M8keyicwm0w","read-only":false},"node-name":"drive-sata0","throttle-group":"throttle-drive-sata0"}' \
+ -device 'ide-hd,bus=ahci0.0,id=sata0,drive=drive-sata0' \
+ -machine 'accel=tcg,smm=off,type=pc+pve0' \
-snapshot
diff --git a/test/cfg2cmd/simple1.conf b/test/cfg2cmd/simple1.conf
index 9feb9d26..2fdd30bc 100644
--- a/test/cfg2cmd/simple1.conf
+++ b/test/cfg2cmd/simple1.conf
@@ -2,6 +2,7 @@
bootdisk: scsi0
cores: 3
ide2: none,media=cdrom
+machine: pc-i440fx-9.2+pve1
memory: 768
name: simple
net0: virtio=A2:C0:43:77:08:A0,bridge=vmbr0
diff --git a/test/cfg2cmd/simple1.conf.cmd b/test/cfg2cmd/simple1.conf.cmd
index c7fa1e0a..aab53fdc 100644
--- a/test/cfg2cmd/simple1.conf.cmd
+++ b/test/cfg2cmd/simple1.conf.cmd
@@ -32,4 +32,4 @@
-device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0,bootindex=100' \
-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' \
- -machine 'type=pc+pve1'
+ -machine 'type=pc-i440fx-9.2+pve1'
diff --git a/test/cfg2cmd/vnc-clipboard-spice.conf.cmd b/test/cfg2cmd/vnc-clipboard-spice.conf.cmd
index 883251cf..8915bcf4 100644
--- a/test/cfg2cmd/vnc-clipboard-spice.conf.cmd
+++ b/test/cfg2cmd/vnc-clipboard-spice.conf.cmd
@@ -26,4 +26,4 @@
-spice 'tls-port=61000,addr=127.0.0.1,tls-ciphers=HIGH,seamless-migration=on' \
-device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
- -machine 'type=pc+pve1'
+ -machine 'type=pc+pve0'
diff --git a/test/cfg2cmd/vnc-clipboard-std.conf.cmd b/test/cfg2cmd/vnc-clipboard-std.conf.cmd
index ce0e4be4..26341d3d 100644
--- a/test/cfg2cmd/vnc-clipboard-std.conf.cmd
+++ b/test/cfg2cmd/vnc-clipboard-std.conf.cmd
@@ -26,4 +26,4 @@
-device 'virtserialport,chardev=vdagent,name=com.redhat.spice.0' \
-device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
- -machine 'type=pc+pve1'
+ -machine 'type=pc+pve0'
diff --git a/test/run_config2command_tests.pl b/test/run_config2command_tests.pl
index f94d9c02..d689fc5b 100755
--- a/test/run_config2command_tests.pl
+++ b/test/run_config2command_tests.pl
@@ -247,6 +247,25 @@ $qemu_server_module->mock(
},
);
+my $storage_plugin_module = Test::MockModule->new("PVE::Storage::Plugin");
+$storage_plugin_module->mock(
+ qemu_blockdev_options => sub {
+ my ($class, $scfg, $storeid, $volname, $options) = @_;
+
+ my ($path) = $class->filesystem_path($scfg, $volname, $options->{'snapshot-name'});
+
+ my $blockdev = {};
+ if ($path =~ m/^\/dev/) {
+ $blockdev = { driver => 'host_device', filename => $path};
+ } elsif ($path =~ m/^\//) {
+ $blockdev = { driver => 'file', filename => $path};
+ } else {
+ die "storage plugin doesn't implement qemu_blockdev_options() method\n";
+ }
+ return $blockdev;
+ },
+);
+
my $zfsplugin_module = Test::MockModule->new("PVE::Storage::ZFSPlugin");
$zfsplugin_module->mock(
zfs_get_lu_name => sub {
@@ -469,6 +488,13 @@ $pci_module->mock(
}
);
+my $storage_module = Test::MockModule->new("PVE::Storage");
+$storage_module->mock(
+ activate_volumes => sub {
+ return;
+ }
+);
+
sub diff($$) {
my ($a, $b) = @_;
return if $a eq $b;
--
2.39.5
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* [pve-devel] [PATCH pve-storage 1/9] common: add qemu_img_create an preallocation_cmd_option
[not found] <20250603075558.627850-1-alexandre.derumier@groupe-cyllene.com>
2025-06-03 7:55 ` [pve-devel] [PATCH pve-qemu 1/1] add fake 10.0 Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support Alexandre Derumier via pve-devel
@ 2025-06-03 7:55 ` Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 02/13] blockdev: add support for ovmf && efidisk Alexandre Derumier via pve-devel
` (19 subsequent siblings)
22 siblings, 0 replies; 39+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-06-03 7:55 UTC (permalink / raw)
To: pve-devel; +Cc: Alexandre Derumier
[-- Attachment #1: Type: message/rfc822, Size: 8325 bytes --]
From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH pve-storage 1/9] common: add qemu_img_create an preallocation_cmd_option
Date: Tue, 3 Jun 2025 09:55:38 +0200
Message-ID: <20250603075558.627850-4-alexandre.derumier@groupe-cyllene.com>
Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
src/PVE/Storage/Common.pm | 72 ++++++++++++++++++++++++++++++
src/PVE/Storage/GlusterfsPlugin.pm | 2 +-
src/PVE/Storage/Plugin.pm | 47 +------------------
3 files changed, 74 insertions(+), 47 deletions(-)
diff --git a/src/PVE/Storage/Common.pm b/src/PVE/Storage/Common.pm
index bd9c951..4e4ad30 100644
--- a/src/PVE/Storage/Common.pm
+++ b/src/PVE/Storage/Common.pm
@@ -5,12 +5,26 @@ use warnings;
use PVE::JSONSchema;
use PVE::Syscall;
+use PVE::Tools qw(run_command);
use constant {
FALLOC_FL_KEEP_SIZE => 0x01, # see linux/falloc.h
FALLOC_FL_PUNCH_HOLE => 0x02, # see linux/falloc.h
};
+my $QCOW2_PREALLOCATION = {
+ off => 1,
+ metadata => 1,
+ falloc => 1,
+ full => 1,
+};
+
+my $RAW_PREALLOCATION = {
+ off => 1,
+ falloc => 1,
+ full => 1,
+};
+
=pod
=head1 NAME
@@ -107,4 +121,62 @@ sub deallocate : prototype($$$) {
}
}
+=pod
+
+=head3 preallocation_cmd_option
+
+ preallocation_cmd_option($scfg, $fmt)
+
+Returns the qemu-img preallocation command line for a specific image format C<$format>.
+
+=cut
+
+sub preallocation_cmd_option {
+ my ($scfg, $fmt) = @_;
+
+ my $prealloc = $scfg->{preallocation};
+
+ if ($fmt eq 'qcow2') {
+ $prealloc = $prealloc // 'metadata';
+
+ die "preallocation mode '$prealloc' not supported by format '$fmt'\n"
+ if !$QCOW2_PREALLOCATION->{$prealloc};
+
+ return "preallocation=$prealloc";
+ } elsif ($fmt eq 'raw') {
+ $prealloc = $prealloc // 'off';
+ $prealloc = 'off' if $prealloc eq 'metadata';
+
+ die "preallocation mode '$prealloc' not supported by format '$fmt'\n"
+ if !$RAW_PREALLOCATION->{$prealloc};
+
+ return "preallocation=$prealloc";
+ }
+
+ return;
+}
+
+=pod
+
+=head3 qemu_img_create
+
+ qemu_img_create($scfg, $fmt, $size, $path)
+
+Create a new qemu image with a specific format C<$format> and size C<$size> for a target C<$path>.
+
+=cut
+
+sub qemu_img_create {
+ my ($scfg, $fmt, $size, $path) = @_;
+
+ my $cmd = ['/usr/bin/qemu-img', 'create'];
+
+ my $prealloc_opt = preallocation_cmd_option($scfg, $fmt);
+ push @$cmd, '-o', $prealloc_opt if defined($prealloc_opt);
+
+ push @$cmd, '-f', $fmt, $path, "${size}K";
+
+ run_command($cmd, errmsg => "unable to create image");
+}
+
1;
diff --git a/src/PVE/Storage/GlusterfsPlugin.pm b/src/PVE/Storage/GlusterfsPlugin.pm
index 18493cb..b1a541d 100644
--- a/src/PVE/Storage/GlusterfsPlugin.pm
+++ b/src/PVE/Storage/GlusterfsPlugin.pm
@@ -265,7 +265,7 @@ sub alloc_image {
my $cmd = ['/usr/bin/qemu-img', 'create'];
- my $prealloc_opt = PVE::Storage::Plugin::preallocation_cmd_option($scfg, $fmt);
+ my $prealloc_opt = PVE::Storage::Common::preallocation_cmd_option($scfg, $fmt);
push @$cmd, '-o', $prealloc_opt if defined($prealloc_opt);
push @$cmd, '-f', $fmt, $volumepath, "${size}K";
diff --git a/src/PVE/Storage/Plugin.pm b/src/PVE/Storage/Plugin.pm
index b59fc72..90627b2 100644
--- a/src/PVE/Storage/Plugin.pm
+++ b/src/PVE/Storage/Plugin.pm
@@ -47,19 +47,6 @@ our @SHARED_STORAGE = (
'pbs',
);
-our $QCOW2_PREALLOCATION = {
- off => 1,
- metadata => 1,
- falloc => 1,
- full => 1,
-};
-
-our $RAW_PREALLOCATION = {
- off => 1,
- falloc => 1,
- full => 1,
-};
-
our $MAX_VOLUMES_PER_GUEST = 1024;
cfs_register_file ('storage.cfg',
@@ -577,31 +564,6 @@ sub parse_config {
return $cfg;
}
-sub preallocation_cmd_option {
- my ($scfg, $fmt) = @_;
-
- my $prealloc = $scfg->{preallocation};
-
- if ($fmt eq 'qcow2') {
- $prealloc = $prealloc // 'metadata';
-
- die "preallocation mode '$prealloc' not supported by format '$fmt'\n"
- if !$QCOW2_PREALLOCATION->{$prealloc};
-
- return "preallocation=$prealloc";
- } elsif ($fmt eq 'raw') {
- $prealloc = $prealloc // 'off';
- $prealloc = 'off' if $prealloc eq 'metadata';
-
- die "preallocation mode '$prealloc' not supported by format '$fmt'\n"
- if !$RAW_PREALLOCATION->{$prealloc};
-
- return "preallocation=$prealloc";
- }
-
- return;
-}
-
# Storage implementation
# called during addition of storage (before the new storage config got written)
@@ -926,14 +888,7 @@ sub alloc_image {
umask $old_umask;
die $err if $err;
} else {
- my $cmd = ['/usr/bin/qemu-img', 'create'];
-
- my $prealloc_opt = preallocation_cmd_option($scfg, $fmt);
- push @$cmd, '-o', $prealloc_opt if defined($prealloc_opt);
-
- push @$cmd, '-f', $fmt, $path, "${size}K";
-
- eval { run_command($cmd, errmsg => "unable to create image"); };
+ eval { PVE::Storage::Common::qemu_img_create($scfg, $fmt, $size, $path) };
if ($@) {
unlink $path;
rmdir $imagedir;
--
2.39.5
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* [pve-devel] [PATCH qemu-server 02/13] blockdev: add support for ovmf && efidisk
[not found] <20250603075558.627850-1-alexandre.derumier@groupe-cyllene.com>
` (2 preceding siblings ...)
2025-06-03 7:55 ` [pve-devel] [PATCH pve-storage 1/9] common: add qemu_img_create an preallocation_cmd_option Alexandre Derumier via pve-devel
@ 2025-06-03 7:55 ` Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH pve-storage 2/9] common: add qemu_img_create_qcow2_backed Alexandre Derumier via pve-devel
` (18 subsequent siblings)
22 siblings, 0 replies; 39+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-06-03 7:55 UTC (permalink / raw)
To: pve-devel; +Cc: Alexandre Derumier
[-- Attachment #1: Type: message/rfc822, Size: 37605 bytes --]
From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH qemu-server 02/13] blockdev: add support for ovmf && efidisk
Date: Tue, 3 Jun 2025 09:55:39 +0200
Message-ID: <20250603075558.627850-5-alexandre.derumier@groupe-cyllene.com>
for raw format, use offset=0 && size=$ovmf_size
Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
PVE/QemuServer.pm | 63 +++++++++++++++++--
PVE/QemuServer/Blockdev.pm | 22 +++++--
test/cfg2cmd/efi-raw-template.conf.cmd | 7 ++-
test/cfg2cmd/efi-secboot-and-tpm-q35.conf.cmd | 7 ++-
test/cfg2cmd/efi-secboot-and-tpm.conf.cmd | 7 ++-
test/cfg2cmd/efidisk-on-rbd.conf | 1 +
test/cfg2cmd/efidisk-on-rbd.conf.cmd | 2 +-
.../q35-linux-hostpci-mapping.conf.cmd | 7 ++-
.../q35-linux-hostpci-multifunction.conf.cmd | 7 ++-
.../q35-linux-hostpci-template.conf.cmd | 7 ++-
...q35-linux-hostpci-x-pci-overrides.conf.cmd | 7 ++-
test/cfg2cmd/q35-linux-hostpci.conf.cmd | 7 ++-
test/cfg2cmd/q35-simple.conf.cmd | 7 ++-
test/cfg2cmd/sev-es.conf.cmd | 7 ++-
test/cfg2cmd/sev-std.conf.cmd | 7 ++-
15 files changed, 121 insertions(+), 44 deletions(-)
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 383a5833..a27dcabb 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -3285,6 +3285,52 @@ my sub print_ovmf_drive_commandlines {
return ("if=pflash,unit=0,format=raw,readonly=on,file=$ovmf_code", $var_drive_str);
}
+my sub generate_ovmf_blockdev {
+ my ($conf, $storecfg, $vmid, $arch, $q35, $version_guard) = @_;
+
+ my $d = $conf->{efidisk0} ? parse_drive('efidisk0', $conf->{efidisk0}) : undef;
+
+ my $amd_sev_type = get_amd_sev_type($conf);
+ die "Attempting to configure SEV-SNP with pflash devices instead of using `-bios`\n"
+ if $amd_sev_type && $amd_sev_type eq 'snp';
+
+ my ($ovmf_code, $ovmf_vars) = get_ovmf_files($arch, $d, $q35, $amd_sev_type);
+
+ my $ovmf_code_drive = { file => $ovmf_code, ro => 1, interface => 'pflash', index => '0' };
+
+ my $ovmf_blockdev = generate_drive_blockdev($storecfg, $ovmf_code_drive);
+
+ my $efi_size = undef;
+
+ if ($d) {
+ my ($storeid, $volname) = PVE::Storage::parse_volume_id($d->{file}, 1);
+ my ($path, $format) = $d->@{'file', 'format'};
+ if ($storeid) {
+ $path = PVE::Storage::path($storecfg, $d->{file});
+ $format //= checked_volume_format($storecfg, $d->{file});
+ } elsif (!defined($format)) {
+ die "efidisk format must be specified\n";
+ }
+
+ # SPI flash does lots of read-modify-write OPs, without writeback this gets really slow #3329
+ $d->{cache} = 'writeback' if $path =~ m/^rbd:/;
+ $d->{ro} = JSON::true if drive_is_read_only($conf, $d);
+ $efi_size = -s $ovmf_vars if $format eq 'raw';
+
+ } else {
+ log_warn("no efidisk configured! Using temporary efivars disk.");
+ my $path = "/tmp/$vmid-ovmf.fd";
+ PVE::Tools::file_copy($ovmf_vars, $path, -s $ovmf_vars);
+ $d->{file} = $path;
+ $efi_size = -s $ovmf_vars;
+ }
+
+ my $var_blockdev = generate_drive_blockdev($storecfg, $d, undef, $efi_size);
+ my $throttle_group = print_drive_throttle_group($d);
+
+ return ($ovmf_blockdev, $var_blockdev, $throttle_group);
+}
+
my sub get_vga_properties {
my ($conf, $arch, $machine_version, $winversion) = @_;
@@ -3465,10 +3511,19 @@ sub config_to_command {
}
push $cmd->@*, '-bios', get_ovmf_files($arch, undef, undef, $amd_sev_type);
} else {
- my ($code_drive_str, $var_drive_str) = print_ovmf_drive_commandlines(
- $conf, $storecfg, $vmid, $arch, $q35, $version_guard);
- push $cmd->@*, '-drive', $code_drive_str;
- push $cmd->@*, '-drive', $var_drive_str;
+ if(min_version($machine_version, 10, 0, 0)) {
+ my ($code_blockdev, $var_blockdev, $throttle_group) = generate_ovmf_blockdev(
+ $conf, $storecfg, $vmid, $arch, $q35, $version_guard);
+ push @$devices, '-object', $throttle_group;
+ push $cmd->@*, '-blockdev', JSON->new->canonical->allow_nonref->encode($code_blockdev);
+ push $cmd->@*, '-blockdev', JSON->new->canonical->allow_nonref->encode($var_blockdev);
+ push @$machineFlags, "pflash0=$code_blockdev->{'node-name'}", "pflash1=$var_blockdev->{'node-name'}";
+ } else {
+ my ($code_drive_str, $var_drive_str) = print_ovmf_drive_commandlines(
+ $conf, $storecfg, $vmid, $arch, $q35, $version_guard);
+ push $cmd->@*, '-drive', $code_drive_str;
+ push $cmd->@*, '-drive', $var_drive_str;
+ }
}
}
diff --git a/PVE/QemuServer/Blockdev.pm b/PVE/QemuServer/Blockdev.pm
index 48d1821f..b4dd1ef5 100644
--- a/PVE/QemuServer/Blockdev.pm
+++ b/PVE/QemuServer/Blockdev.pm
@@ -147,7 +147,9 @@ sub generate_file_blockdev {
my $server = { type => 'inet', host => $1, port => $2 };
$blockdev = { driver => 'nbd', server => $server, export => $3 };
} elsif($storeid) {
- $blockdev = PVE::Storage::qemu_blockdev_options($storecfg, $volid, $snap);
+ my $blockdev_options = {};
+ $blockdev_options->{hints}->{'efi-disk'} = 1 if $drive_id =~ m/^efidisk(\d+)$/;
+ $blockdev = PVE::Storage::qemu_blockdev_options($storecfg, $volid, $blockdev_options);
$scfg = PVE::Storage::storage_config($storecfg, $storeid);
} elsif (drive_is_cdrom($drive)) {
$path = get_iso_path($storecfg, $volid);
@@ -163,7 +165,7 @@ sub generate_file_blockdev {
$blockdev->{cache} = generate_blockdev_drive_cache($drive, $scfg);
#non-host qemu block driver (rbd, gluster,iscsi,..) don't have aio attribute
- $blockdev->{aio} = generate_blockdev_drive_aio($drive, $scfg) if $blockdev->{filename};
+ $blockdev->{aio} = generate_blockdev_drive_aio($drive, $scfg) if $blockdev->{filename} && $drive->{interface} !~ m/^(pflash|efidisk)$/;
##discard && detect-zeroes
my $discard = 'ignore';
@@ -182,7 +184,7 @@ sub generate_file_blockdev {
# This used to be our default with discard not being specified:
$detect_zeroes = 'on';
}
- $blockdev->{'detect-zeroes'} = $detect_zeroes if !drive_is_cdrom($drive);
+ $blockdev->{'detect-zeroes'} = $detect_zeroes if !drive_is_cdrom($drive) && $drive->{interface} !~ m/^(pflash|efidisk)$/;
$nodename = encode_nodename('file', $volid, $snap) if !$nodename;
$blockdev->{'node-name'} = $nodename;
@@ -191,7 +193,7 @@ sub generate_file_blockdev {
}
sub generate_format_blockdev {
- my ($storecfg, $drive, $file, $snap, $nodename) = @_;
+ my ($storecfg, $drive, $file, $snap, $size, $nodename) = @_;
my $volid = $drive->{file};
#nbd don't support format blockdev, return the fileblockdev
@@ -230,11 +232,16 @@ sub generate_format_blockdev {
my $blockdev = { 'node-name' => $nodename, driver => $format, file => $file, cache => $cache, 'read-only' => $readonly };
+ if ($size) {
+ die "size param can only be used with raw format" if $format ne 'raw';
+ $blockdev->{offset} = 0;
+ $blockdev->{size} = $size;
+ }
return $blockdev;
}
sub generate_drive_blockdev {
- my ($storecfg, $drive, $live_restore_name) = @_;
+ my ($storecfg, $drive, $live_restore_name, $size) = @_;
my $volid = $drive->{file};
my $drive_id = get_drive_id($drive);
@@ -249,9 +256,12 @@ sub generate_drive_blockdev {
}
my $blockdev_file = generate_file_blockdev($storecfg, $drive);
- my $blockdev_format = generate_format_blockdev($storecfg, $drive, $blockdev_file);
+ my $blockdev_format = generate_format_blockdev($storecfg, $drive, $blockdev_file, undef, $size);
my $blockdev_live_restore = undef;
+ #pflash0 don't support throttle-filter
+ return $blockdev_format if $drive_id eq 'pflash0';
+
if ($live_restore_name) {
die "$drive_id: Proxmox Backup Server backed drive cannot auto-detect the format\n"
if !$drive->{format};
diff --git a/test/cfg2cmd/efi-raw-template.conf.cmd b/test/cfg2cmd/efi-raw-template.conf.cmd
index f66cbb0d..b7ca94e9 100644
--- a/test/cfg2cmd/efi-raw-template.conf.cmd
+++ b/test/cfg2cmd/efi-raw-template.conf.cmd
@@ -8,8 +8,8 @@
-mon 'chardev=qmp-event,mode=control' \
-pidfile /var/run/qemu-server/8006.pid \
-daemonize \
- -drive 'if=pflash,unit=0,format=raw,readonly=on,file=/usr/share/pve-edk2-firmware//OVMF_CODE.fd' \
- -drive 'if=pflash,unit=1,id=drive-efidisk0,format=raw,file=/var/lib/vz/images/100/base-disk-100-0.raw,size=131072,readonly=on' \
+ -blockdev '{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"cache":{"direct":true,"no-flush":false},"discard":"ignore","driver":"file","filename":"/usr/share/pve-edk2-firmware//OVMF_CODE.fd","node-name":"e-WxbgqVgkl6KMmuyWKSKESesSKws"},"node-name":"f-WxbgqVgkl6KMmuyWKSKESesSKws","read-only":true}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"cache":{"direct":true,"no-flush":false},"discard":"ignore","driver":"file","filename":"/var/lib/vz/images/100/base-disk-100-0.raw","node-name":"e-5ATbcxKbL6wm0IU2wAmSqYkmaYY"},"node-name":"f-5ATbcxKbL6wm0IU2wAmSqYkmaYY","offset":0,"read-only":true,"size":131072},"node-name":"drive-efidisk0","throttle-group":"throttle-drive-efidisk0"}' \
-smp '1,sockets=1,cores=1,maxcpus=1' \
-nodefaults \
-boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
@@ -21,9 +21,10 @@
-global 'PIIX4_PM.disable_s4=1' \
-device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \
-device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \
+ -object '{"id":"throttle-drive-efidisk0","limits":{},"qom-type":"throttle-group"}' \
-device 'piix3-usb-uhci,id=uhci,bus=pci.0,addr=0x1.0x2' \
-device 'usb-tablet,id=tablet,bus=uhci.0,port=1' \
-device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
- -machine 'accel=tcg,type=pc+pve0' \
+ -machine 'pflash0=f-WxbgqVgkl6KMmuyWKSKESesSKws,pflash1=drive-efidisk0,accel=tcg,type=pc+pve0' \
-snapshot
diff --git a/test/cfg2cmd/efi-secboot-and-tpm-q35.conf.cmd b/test/cfg2cmd/efi-secboot-and-tpm-q35.conf.cmd
index 4e9a7e87..a3757078 100644
--- a/test/cfg2cmd/efi-secboot-and-tpm-q35.conf.cmd
+++ b/test/cfg2cmd/efi-secboot-and-tpm-q35.conf.cmd
@@ -9,8 +9,8 @@
-pidfile /var/run/qemu-server/8006.pid \
-daemonize \
-smbios 'type=1,uuid=7b10d7af-b932-4c66-b2c3-3996152ec465' \
- -drive 'if=pflash,unit=0,format=raw,readonly=on,file=/usr/share/pve-edk2-firmware//OVMF_CODE_4M.secboot.fd' \
- -drive 'if=pflash,unit=1,id=drive-efidisk0,format=raw,file=/var/lib/vz/images/100/vm-disk-100-0.raw,size=540672' \
+ -blockdev '{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"cache":{"direct":true,"no-flush":false},"discard":"ignore","driver":"file","filename":"/usr/share/pve-edk2-firmware//OVMF_CODE_4M.secboot.fd","node-name":"e-5KLU1JFuj26s2YWi2qIwa6GWooG"},"node-name":"f-5KLU1JFuj26s2YWi2qIwa6GWooG","read-only":true}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"cache":{"direct":true,"no-flush":false},"discard":"ignore","driver":"file","filename":"/var/lib/vz/images/100/vm-disk-100-0.raw","node-name":"e-2lc6uRlbPUs6Si4A2GQOg0qicCW"},"node-name":"f-2lc6uRlbPUs6Si4A2GQOg0qicCW","offset":0,"read-only":false,"size":540672},"node-name":"drive-efidisk0","throttle-group":"throttle-drive-efidisk0"}' \
-smp '1,sockets=1,cores=1,maxcpus=1' \
-nodefaults \
-boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
@@ -19,6 +19,7 @@
-m 512 \
-global 'ICH9-LPC.disable_s3=1' \
-global 'ICH9-LPC.disable_s4=1' \
+ -object '{"id":"throttle-drive-efidisk0","limits":{},"qom-type":"throttle-group"}' \
-readconfig /usr/share/qemu-server/pve-q35-4.0.cfg \
-device 'usb-tablet,id=tablet,bus=ehci.0,port=1' \
-chardev 'socket,id=tpmchar,path=/var/run/qemu-server/8006.swtpm' \
@@ -27,4 +28,4 @@
-device 'VGA,id=vga,bus=pcie.0,addr=0x1' \
-device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
- -machine 'type=q35+pve0'
+ -machine 'pflash0=f-5KLU1JFuj26s2YWi2qIwa6GWooG,pflash1=drive-efidisk0,type=q35+pve0'
diff --git a/test/cfg2cmd/efi-secboot-and-tpm.conf.cmd b/test/cfg2cmd/efi-secboot-and-tpm.conf.cmd
index 175d9b10..d7e97d58 100644
--- a/test/cfg2cmd/efi-secboot-and-tpm.conf.cmd
+++ b/test/cfg2cmd/efi-secboot-and-tpm.conf.cmd
@@ -9,8 +9,8 @@
-pidfile /var/run/qemu-server/8006.pid \
-daemonize \
-smbios 'type=1,uuid=7b10d7af-b932-4c66-b2c3-3996152ec465' \
- -drive 'if=pflash,unit=0,format=raw,readonly=on,file=/usr/share/pve-edk2-firmware//OVMF_CODE_4M.fd' \
- -drive 'if=pflash,unit=1,id=drive-efidisk0,format=raw,file=/var/lib/vz/images/100/vm-disk-100-0.raw,size=540672' \
+ -blockdev '{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"cache":{"direct":true,"no-flush":false},"discard":"ignore","driver":"file","filename":"/usr/share/pve-edk2-firmware//OVMF_CODE_4M.fd","node-name":"e-EZlnnyuTA0O8GkASqSEMwmmyysG"},"node-name":"f-EZlnnyuTA0O8GkASqSEMwmmyysG","read-only":true}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"cache":{"direct":true,"no-flush":false},"discard":"ignore","driver":"file","filename":"/var/lib/vz/images/100/vm-disk-100-0.raw","node-name":"e-2lc6uRlbPUs6Si4A2GQOg0qicCW"},"node-name":"f-2lc6uRlbPUs6Si4A2GQOg0qicCW","offset":0,"read-only":false,"size":540672},"node-name":"drive-efidisk0","throttle-group":"throttle-drive-efidisk0"}' \
-smp '1,sockets=1,cores=1,maxcpus=1' \
-nodefaults \
-boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
@@ -21,6 +21,7 @@
-global 'PIIX4_PM.disable_s4=1' \
-device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \
-device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \
+ -object '{"id":"throttle-drive-efidisk0","limits":{},"qom-type":"throttle-group"}' \
-device 'piix3-usb-uhci,id=uhci,bus=pci.0,addr=0x1.0x2' \
-device 'usb-tablet,id=tablet,bus=uhci.0,port=1' \
-chardev 'socket,id=tpmchar,path=/var/run/qemu-server/8006.swtpm' \
@@ -29,4 +30,4 @@
-device 'VGA,id=vga,bus=pci.0,addr=0x2' \
-device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
- -machine 'type=pc+pve0'
+ -machine 'pflash0=f-EZlnnyuTA0O8GkASqSEMwmmyysG,pflash1=drive-efidisk0,type=pc+pve0'
diff --git a/test/cfg2cmd/efidisk-on-rbd.conf b/test/cfg2cmd/efidisk-on-rbd.conf
index 1958fe61..6ae7a734 100644
--- a/test/cfg2cmd/efidisk-on-rbd.conf
+++ b/test/cfg2cmd/efidisk-on-rbd.conf
@@ -3,6 +3,7 @@ bios: ovmf
bootdisk: scsi0
cores: 1
efidisk0: rbd-store:vm-100-disk-1,size=128K
+machine: pc-i440fx-9.2+pve1
memory: 512
net0: virtio=2E:01:68:F9:9C:87,bridge=vmbr0
numa: 1
diff --git a/test/cfg2cmd/efidisk-on-rbd.conf.cmd b/test/cfg2cmd/efidisk-on-rbd.conf.cmd
index 5c55c01b..f9b7bb2d 100644
--- a/test/cfg2cmd/efidisk-on-rbd.conf.cmd
+++ b/test/cfg2cmd/efidisk-on-rbd.conf.cmd
@@ -31,4 +31,4 @@
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-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=2E:01:68:F9:9C:87,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256,bootindex=300' \
- -machine 'type=pc+pve0'
+ -machine 'type=pc-i440fx-9.2+pve1'
diff --git a/test/cfg2cmd/q35-linux-hostpci-mapping.conf.cmd b/test/cfg2cmd/q35-linux-hostpci-mapping.conf.cmd
index 2d66cb66..03bf0ccd 100644
--- a/test/cfg2cmd/q35-linux-hostpci-mapping.conf.cmd
+++ b/test/cfg2cmd/q35-linux-hostpci-mapping.conf.cmd
@@ -9,8 +9,8 @@
-pidfile /var/run/qemu-server/8006.pid \
-daemonize \
-smbios 'type=1,uuid=3dd750ce-d910-44d0-9493-525c0be4e687' \
- -drive 'if=pflash,unit=0,format=raw,readonly=on,file=/usr/share/pve-edk2-firmware//OVMF_CODE.fd' \
- -drive 'if=pflash,unit=1,id=drive-efidisk0,format=qcow2,file=/var/lib/vz/images/100/vm-100-disk-1.qcow2' \
+ -blockdev '{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"cache":{"direct":true,"no-flush":false},"discard":"ignore","driver":"file","filename":"/usr/share/pve-edk2-firmware//OVMF_CODE.fd","node-name":"e-WxbgqVgkl6KMmuyWKSKESesSKws"},"node-name":"f-WxbgqVgkl6KMmuyWKSKESesSKws","read-only":true}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"cache":{"direct":true,"no-flush":false},"discard":"ignore","driver":"file","filename":"/var/lib/vz/images/100/vm-100-disk-1.qcow2","node-name":"e-YmZE4AYMcYc6MkGe04mCmUEo22K"},"node-name":"f-YmZE4AYMcYc6MkGe04mCmUEo22K","read-only":false},"node-name":"drive-efidisk0","throttle-group":"throttle-drive-efidisk0"}' \
-global 'ICH9-LPC.acpi-pci-hotplug-with-bridge-support=off' \
-smp '2,sockets=2,cores=1,maxcpus=2' \
-nodefaults \
@@ -24,6 +24,7 @@
-numa 'node,nodeid=1,cpus=1,memdev=ram-node1' \
-global 'ICH9-LPC.disable_s3=1' \
-global 'ICH9-LPC.disable_s4=1' \
+ -object '{"id":"throttle-drive-efidisk0","limits":{},"qom-type":"throttle-group"}' \
-readconfig /usr/share/qemu-server/pve-q35-4.0.cfg \
-device 'vmgenid,guid=54d1c06c-8f5b-440f-b5b2-6eab1380e13d' \
-device 'usb-tablet,id=tablet,bus=ehci.0,port=1' \
@@ -35,4 +36,4 @@
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-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=2E:01:68:F9:9C:87,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256,bootindex=300' \
- -machine 'type=q35+pve0'
+ -machine 'pflash0=f-WxbgqVgkl6KMmuyWKSKESesSKws,pflash1=drive-efidisk0,type=q35+pve0'
diff --git a/test/cfg2cmd/q35-linux-hostpci-multifunction.conf.cmd b/test/cfg2cmd/q35-linux-hostpci-multifunction.conf.cmd
index 146bf3e5..7199066f 100644
--- a/test/cfg2cmd/q35-linux-hostpci-multifunction.conf.cmd
+++ b/test/cfg2cmd/q35-linux-hostpci-multifunction.conf.cmd
@@ -9,8 +9,8 @@
-pidfile /var/run/qemu-server/8006.pid \
-daemonize \
-smbios 'type=1,uuid=3dd750ce-d910-44d0-9493-525c0be4e687' \
- -drive 'if=pflash,unit=0,format=raw,readonly=on,file=/usr/share/pve-edk2-firmware//OVMF_CODE.fd' \
- -drive 'if=pflash,unit=1,id=drive-efidisk0,format=qcow2,file=/var/lib/vz/images/100/vm-100-disk-1.qcow2' \
+ -blockdev '{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"cache":{"direct":true,"no-flush":false},"discard":"ignore","driver":"file","filename":"/usr/share/pve-edk2-firmware//OVMF_CODE.fd","node-name":"e-WxbgqVgkl6KMmuyWKSKESesSKws"},"node-name":"f-WxbgqVgkl6KMmuyWKSKESesSKws","read-only":true}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"cache":{"direct":true,"no-flush":false},"discard":"ignore","driver":"file","filename":"/var/lib/vz/images/100/vm-100-disk-1.qcow2","node-name":"e-YmZE4AYMcYc6MkGe04mCmUEo22K"},"node-name":"f-YmZE4AYMcYc6MkGe04mCmUEo22K","read-only":false},"node-name":"drive-efidisk0","throttle-group":"throttle-drive-efidisk0"}' \
-global 'ICH9-LPC.acpi-pci-hotplug-with-bridge-support=off' \
-smp '2,sockets=2,cores=1,maxcpus=2' \
-nodefaults \
@@ -24,6 +24,7 @@
-numa 'node,nodeid=1,cpus=1,memdev=ram-node1' \
-global 'ICH9-LPC.disable_s3=1' \
-global 'ICH9-LPC.disable_s4=1' \
+ -object '{"id":"throttle-drive-efidisk0","limits":{},"qom-type":"throttle-group"}' \
-readconfig /usr/share/qemu-server/pve-q35-4.0.cfg \
-device 'vmgenid,guid=54d1c06c-8f5b-440f-b5b2-6eab1380e13d' \
-device 'usb-tablet,id=tablet,bus=ehci.0,port=1' \
@@ -35,4 +36,4 @@
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-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=2E:01:68:F9:9C:87,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256,bootindex=300' \
- -machine 'type=q35+pve0'
+ -machine 'pflash0=f-WxbgqVgkl6KMmuyWKSKESesSKws,pflash1=drive-efidisk0,type=q35+pve0'
diff --git a/test/cfg2cmd/q35-linux-hostpci-template.conf.cmd b/test/cfg2cmd/q35-linux-hostpci-template.conf.cmd
index fa75d393..06e0d37c 100644
--- a/test/cfg2cmd/q35-linux-hostpci-template.conf.cmd
+++ b/test/cfg2cmd/q35-linux-hostpci-template.conf.cmd
@@ -8,8 +8,8 @@
-mon 'chardev=qmp-event,mode=control' \
-pidfile /var/run/qemu-server/8006.pid \
-daemonize \
- -drive 'if=pflash,unit=0,format=raw,readonly=on,file=/usr/share/pve-edk2-firmware//OVMF_CODE.fd' \
- -drive 'if=pflash,unit=1,id=drive-efidisk0,format=qcow2,file=/var/lib/vz/images/100/base-100-disk-1.qcow2,readonly=on' \
+ -blockdev '{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"cache":{"direct":true,"no-flush":false},"discard":"ignore","driver":"file","filename":"/usr/share/pve-edk2-firmware//OVMF_CODE.fd","node-name":"e-WxbgqVgkl6KMmuyWKSKESesSKws"},"node-name":"f-WxbgqVgkl6KMmuyWKSKESesSKws","read-only":true}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"cache":{"direct":true,"no-flush":false},"discard":"ignore","driver":"file","filename":"/var/lib/vz/images/100/base-100-disk-1.qcow2","node-name":"e-9Jhq1WNiwSsAISiGaCEW80ygeYG"},"node-name":"f-9Jhq1WNiwSsAISiGaCEW80ygeYG","read-only":true},"node-name":"drive-efidisk0","throttle-group":"throttle-drive-efidisk0"}' \
-smp '1,sockets=1,cores=1,maxcpus=1' \
-nodefaults \
-boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
@@ -21,6 +21,7 @@
-global 'PIIX4_PM.disable_s4=1' \
-device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \
-device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \
+ -object '{"id":"throttle-drive-efidisk0","limits":{},"qom-type":"throttle-group"}' \
-device 'piix3-usb-uhci,id=uhci,bus=pci.0,addr=0x1.0x2' \
-device 'usb-tablet,id=tablet,bus=uhci.0,port=1' \
-device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
@@ -29,5 +30,5 @@
-object '{"id":"throttle-drive-scsi0","limits":{},"qom-type":"throttle-group"}' \
-blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"on","discard":"ignore","driver":"file","filename":"/var/lib/vz/images/100/base-100-disk-2.raw","node-name":"e-3nPTM162JEOAymkwqg2Ww2QUioK"},"node-name":"f-3nPTM162JEOAymkwqg2Ww2QUioK","read-only":true},"node-name":"drive-scsi0","throttle-group":"throttle-drive-scsi0"}' \
-device 'scsi-hd,bus=scsihw0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0,id=scsi0' \
- -machine 'accel=tcg,type=pc+pve0' \
+ -machine 'pflash0=f-WxbgqVgkl6KMmuyWKSKESesSKws,pflash1=drive-efidisk0,accel=tcg,type=pc+pve0' \
-snapshot
diff --git a/test/cfg2cmd/q35-linux-hostpci-x-pci-overrides.conf.cmd b/test/cfg2cmd/q35-linux-hostpci-x-pci-overrides.conf.cmd
index 96f9da18..a2f2ee1f 100644
--- a/test/cfg2cmd/q35-linux-hostpci-x-pci-overrides.conf.cmd
+++ b/test/cfg2cmd/q35-linux-hostpci-x-pci-overrides.conf.cmd
@@ -9,8 +9,8 @@
-pidfile /var/run/qemu-server/8006.pid \
-daemonize \
-smbios 'type=1,uuid=3dd750ce-d910-44d0-9493-525c0be4e687' \
- -drive 'if=pflash,unit=0,format=raw,readonly=on,file=/usr/share/pve-edk2-firmware//OVMF_CODE.fd' \
- -drive 'if=pflash,unit=1,id=drive-efidisk0,format=qcow2,file=/var/lib/vz/images/100/vm-100-disk-1.qcow2' \
+ -blockdev '{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"cache":{"direct":true,"no-flush":false},"discard":"ignore","driver":"file","filename":"/usr/share/pve-edk2-firmware//OVMF_CODE.fd","node-name":"e-WxbgqVgkl6KMmuyWKSKESesSKws"},"node-name":"f-WxbgqVgkl6KMmuyWKSKESesSKws","read-only":true}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"cache":{"direct":true,"no-flush":false},"discard":"ignore","driver":"file","filename":"/var/lib/vz/images/100/vm-100-disk-1.qcow2","node-name":"e-YmZE4AYMcYc6MkGe04mCmUEo22K"},"node-name":"f-YmZE4AYMcYc6MkGe04mCmUEo22K","read-only":false},"node-name":"drive-efidisk0","throttle-group":"throttle-drive-efidisk0"}' \
-global 'ICH9-LPC.acpi-pci-hotplug-with-bridge-support=off'
-smp '2,sockets=2,cores=1,maxcpus=2' \
-nodefaults \
@@ -24,6 +24,7 @@
-numa 'node,nodeid=1,cpus=1,memdev=ram-node1' \
-global 'ICH9-LPC.disable_s3=1' \
-global 'ICH9-LPC.disable_s4=1' \
+ -object '{"id":"throttle-drive-efidisk0","limits":{},"qom-type":"throttle-group"}' \
-readconfig /usr/share/qemu-server/pve-q35-4.0.cfg \
-device 'vmgenid,guid=54d1c06c-8f5b-440f-b5b2-6eab1380e13d' \
-device 'usb-tablet,id=tablet,bus=ehci.0,port=1' \
@@ -34,4 +35,4 @@
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-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=2E:01:68:F9:9C:87,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256,bootindex=300' \
- -machine 'type=q35+pve0'
+ -machine 'pflash0=f-WxbgqVgkl6KMmuyWKSKESesSKws,pflash1=drive-efidisk0,type=q35+pve0'
diff --git a/test/cfg2cmd/q35-linux-hostpci.conf.cmd b/test/cfg2cmd/q35-linux-hostpci.conf.cmd
index 0abb569b..5ec240de 100644
--- a/test/cfg2cmd/q35-linux-hostpci.conf.cmd
+++ b/test/cfg2cmd/q35-linux-hostpci.conf.cmd
@@ -9,8 +9,8 @@
-pidfile /var/run/qemu-server/8006.pid \
-daemonize \
-smbios 'type=1,uuid=3dd750ce-d910-44d0-9493-525c0be4e687' \
- -drive 'if=pflash,unit=0,format=raw,readonly=on,file=/usr/share/pve-edk2-firmware//OVMF_CODE.fd' \
- -drive 'if=pflash,unit=1,id=drive-efidisk0,format=qcow2,file=/var/lib/vz/images/100/vm-100-disk-1.qcow2' \
+ -blockdev '{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"cache":{"direct":true,"no-flush":false},"discard":"ignore","driver":"file","filename":"/usr/share/pve-edk2-firmware//OVMF_CODE.fd","node-name":"e-WxbgqVgkl6KMmuyWKSKESesSKws"},"node-name":"f-WxbgqVgkl6KMmuyWKSKESesSKws","read-only":true}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"cache":{"direct":true,"no-flush":false},"discard":"ignore","driver":"file","filename":"/var/lib/vz/images/100/vm-100-disk-1.qcow2","node-name":"e-YmZE4AYMcYc6MkGe04mCmUEo22K"},"node-name":"f-YmZE4AYMcYc6MkGe04mCmUEo22K","read-only":false},"node-name":"drive-efidisk0","throttle-group":"throttle-drive-efidisk0"}' \
-global 'ICH9-LPC.acpi-pci-hotplug-with-bridge-support=off' \
-smp '2,sockets=2,cores=1,maxcpus=2' \
-nodefaults \
@@ -24,6 +24,7 @@
-numa 'node,nodeid=1,cpus=1,memdev=ram-node1' \
-global 'ICH9-LPC.disable_s3=1' \
-global 'ICH9-LPC.disable_s4=1' \
+ -object '{"id":"throttle-drive-efidisk0","limits":{},"qom-type":"throttle-group"}' \
-readconfig /usr/share/qemu-server/pve-q35-4.0.cfg \
-device 'vmgenid,guid=54d1c06c-8f5b-440f-b5b2-6eab1380e13d' \
-device 'usb-tablet,id=tablet,bus=ehci.0,port=1' \
@@ -40,4 +41,4 @@
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-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=2E:01:68:F9:9C:87,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256,bootindex=300' \
- -machine 'type=q35+pve0'
+ -machine 'pflash0=f-WxbgqVgkl6KMmuyWKSKESesSKws,pflash1=drive-efidisk0,type=q35+pve0'
diff --git a/test/cfg2cmd/q35-simple.conf.cmd b/test/cfg2cmd/q35-simple.conf.cmd
index 371ea7dd..0434928d 100644
--- a/test/cfg2cmd/q35-simple.conf.cmd
+++ b/test/cfg2cmd/q35-simple.conf.cmd
@@ -9,8 +9,8 @@
-pidfile /var/run/qemu-server/8006.pid \
-daemonize \
-smbios 'type=1,uuid=3dd750ce-d910-44d0-9493-525c0be4e687' \
- -drive 'if=pflash,unit=0,format=raw,readonly=on,file=/usr/share/pve-edk2-firmware//OVMF_CODE.fd' \
- -drive 'if=pflash,unit=1,id=drive-efidisk0,format=qcow2,file=/var/lib/vz/images/100/vm-100-disk-1.qcow2' \
+ -blockdev '{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"cache":{"direct":true,"no-flush":false},"discard":"ignore","driver":"file","filename":"/usr/share/pve-edk2-firmware//OVMF_CODE.fd","node-name":"e-WxbgqVgkl6KMmuyWKSKESesSKws"},"node-name":"f-WxbgqVgkl6KMmuyWKSKESesSKws","read-only":true}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"cache":{"direct":true,"no-flush":false},"discard":"ignore","driver":"file","filename":"/var/lib/vz/images/100/vm-100-disk-1.qcow2","node-name":"e-YmZE4AYMcYc6MkGe04mCmUEo22K"},"node-name":"f-YmZE4AYMcYc6MkGe04mCmUEo22K","read-only":false},"node-name":"drive-efidisk0","throttle-group":"throttle-drive-efidisk0"}' \
-global 'ICH9-LPC.acpi-pci-hotplug-with-bridge-support=off' \
-smp '2,sockets=1,cores=2,maxcpus=2' \
-nodefaults \
@@ -20,6 +20,7 @@
-m 512 \
-global 'ICH9-LPC.disable_s3=1' \
-global 'ICH9-LPC.disable_s4=1' \
+ -object '{"id":"throttle-drive-efidisk0","limits":{},"qom-type":"throttle-group"}' \
-readconfig /usr/share/qemu-server/pve-q35-4.0.cfg \
-device 'vmgenid,guid=54d1c06c-8f5b-440f-b5b2-6eab1380e13d' \
-device 'usb-tablet,id=tablet,bus=ehci.0,port=1' \
@@ -28,4 +29,4 @@
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-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=2E:01:68:F9:9C:87,netdev=net0,bus=pci.0,addr=0x12,id=net0,rx_queue_size=1024,tx_queue_size=256,bootindex=300' \
- -machine 'type=q35+pve0'
+ -machine 'pflash0=f-WxbgqVgkl6KMmuyWKSKESesSKws,pflash1=drive-efidisk0,type=q35+pve0'
diff --git a/test/cfg2cmd/sev-es.conf.cmd b/test/cfg2cmd/sev-es.conf.cmd
index 3a100306..c277d048 100644
--- a/test/cfg2cmd/sev-es.conf.cmd
+++ b/test/cfg2cmd/sev-es.conf.cmd
@@ -9,8 +9,8 @@
-pidfile /var/run/qemu-server/8006.pid \
-daemonize \
-smbios 'type=1,uuid=7b10d7af-b932-4c66-b2c3-3996152ec465' \
- -drive 'if=pflash,unit=0,format=raw,readonly=on,file=/usr/share/pve-edk2-firmware//OVMF_CVM_CODE_4M.fd' \
- -drive 'if=pflash,unit=1,id=drive-efidisk0,format=raw,file=/var/lib/vz/images/100/vm-disk-100-0.raw,size=540672' \
+ -blockdev '{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"cache":{"direct":true,"no-flush":false},"discard":"ignore","driver":"file","filename":"/usr/share/pve-edk2-firmware//OVMF_CVM_CODE_4M.fd","node-name":"e-Egy95mPdB2m26CC4EwGQ88as0o"},"node-name":"f-Egy95mPdB2m26CC4EwGQ88as0o","read-only":true}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"cache":{"direct":true,"no-flush":false},"discard":"ignore","driver":"file","filename":"/var/lib/vz/images/100/vm-disk-100-0.raw","node-name":"e-2lc6uRlbPUs6Si4A2GQOg0qicCW"},"node-name":"f-2lc6uRlbPUs6Si4A2GQOg0qicCW","offset":0,"read-only":false,"size":540672},"node-name":"drive-efidisk0","throttle-group":"throttle-drive-efidisk0"}' \
-smp '1,sockets=1,cores=1,maxcpus=1' \
-nodefaults \
-boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
@@ -21,10 +21,11 @@
-global 'PIIX4_PM.disable_s4=1' \
-device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \
-device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \
+ -object '{"id":"throttle-drive-efidisk0","limits":{},"qom-type":"throttle-group"}' \
-device 'piix3-usb-uhci,id=uhci,bus=pci.0,addr=0x1.0x2' \
-device 'usb-tablet,id=tablet,bus=uhci.0,port=1' \
-device 'VGA,id=vga,bus=pci.0,addr=0x2' \
-device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-object 'sev-guest,id=sev0,cbitpos=51,reduced-phys-bits=6,policy=0xc' \
- -machine 'type=pc+pve0,confidential-guest-support=sev0'
+ -machine 'pflash0=f-Egy95mPdB2m26CC4EwGQ88as0o,pflash1=drive-efidisk0,type=pc+pve0,confidential-guest-support=sev0'
diff --git a/test/cfg2cmd/sev-std.conf.cmd b/test/cfg2cmd/sev-std.conf.cmd
index 06da2ca0..a2a7f6a2 100644
--- a/test/cfg2cmd/sev-std.conf.cmd
+++ b/test/cfg2cmd/sev-std.conf.cmd
@@ -9,8 +9,8 @@
-pidfile /var/run/qemu-server/8006.pid \
-daemonize \
-smbios 'type=1,uuid=7b10d7af-b932-4c66-b2c3-3996152ec465' \
- -drive 'if=pflash,unit=0,format=raw,readonly=on,file=/usr/share/pve-edk2-firmware//OVMF_CVM_CODE_4M.fd' \
- -drive 'if=pflash,unit=1,id=drive-efidisk0,format=raw,file=/var/lib/vz/images/100/vm-disk-100-0.raw,size=540672' \
+ -blockdev '{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"cache":{"direct":true,"no-flush":false},"discard":"ignore","driver":"file","filename":"/usr/share/pve-edk2-firmware//OVMF_CVM_CODE_4M.fd","node-name":"e-Egy95mPdB2m26CC4EwGQ88as0o"},"node-name":"f-Egy95mPdB2m26CC4EwGQ88as0o","read-only":true}' \
+ -blockdev '{"driver":"throttle","file":{"cache":{"direct":true,"no-flush":false},"driver":"raw","file":{"cache":{"direct":true,"no-flush":false},"discard":"ignore","driver":"file","filename":"/var/lib/vz/images/100/vm-disk-100-0.raw","node-name":"e-2lc6uRlbPUs6Si4A2GQOg0qicCW"},"node-name":"f-2lc6uRlbPUs6Si4A2GQOg0qicCW","offset":0,"read-only":false,"size":540672},"node-name":"drive-efidisk0","throttle-group":"throttle-drive-efidisk0"}' \
-smp '1,sockets=1,cores=1,maxcpus=1' \
-nodefaults \
-boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
@@ -21,10 +21,11 @@
-global 'PIIX4_PM.disable_s4=1' \
-device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \
-device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \
+ -object '{"id":"throttle-drive-efidisk0","limits":{},"qom-type":"throttle-group"}' \
-device 'piix3-usb-uhci,id=uhci,bus=pci.0,addr=0x1.0x2' \
-device 'usb-tablet,id=tablet,bus=uhci.0,port=1' \
-device 'VGA,id=vga,bus=pci.0,addr=0x2' \
-device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
-iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-object 'sev-guest,id=sev0,cbitpos=51,reduced-phys-bits=6,policy=0x8' \
- -machine 'type=pc+pve0,confidential-guest-support=sev0'
+ -machine 'pflash0=f-Egy95mPdB2m26CC4EwGQ88as0o,pflash1=drive-efidisk0,type=pc+pve0,confidential-guest-support=sev0'
--
2.39.5
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* [pve-devel] [PATCH pve-storage 2/9] common: add qemu_img_create_qcow2_backed
[not found] <20250603075558.627850-1-alexandre.derumier@groupe-cyllene.com>
` (3 preceding siblings ...)
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 02/13] blockdev: add support for ovmf && efidisk Alexandre Derumier via pve-devel
@ 2025-06-03 7:55 ` Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 03/13] blockdev: vm_devices_list : fix block-query Alexandre Derumier via pve-devel
` (17 subsequent siblings)
22 siblings, 0 replies; 39+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-06-03 7:55 UTC (permalink / raw)
To: pve-devel; +Cc: Alexandre Derumier
[-- Attachment #1: Type: message/rfc822, Size: 6280 bytes --]
From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH pve-storage 2/9] common: add qemu_img_create_qcow2_backed
Date: Tue, 3 Jun 2025 09:55:40 +0200
Message-ID: <20250603075558.627850-6-alexandre.derumier@groupe-cyllene.com>
and use it for plugin linked clone
This also enable extended_l2=on, as it's mandatory for backing file
preallocation.
Preallocation was missing previously, so it should increase performance
for linked clone now (around x5 in randwrite 4k)
cluster_size is set to 128k, as it reduce qcow2 overhead (reduce disk,
but also memory needed to cache metadatas)
l2_extended is not enabled yet on base image, but it could help too
to reduce overhead without impacting performance
bench on 100G qcow2 file:
fio --filename=/dev/sdb --direct=1 --rw=randwrite --bs=4k --iodepth=32 --ioengine=libaio --name=test
fio --filename=/dev/sdb --direct=1 --rw=randread --bs=4k --iodepth=32 --ioengine=libaio --name=test
base image:
randwrite 4k: prealloc=metadata, l2_extended=off, cluster_size=64k: 20215
randread 4k: prealloc=metadata, l2_extended=off, cluster_size=64k: 22219
randwrite 4k: prealloc=metadata, l2_extended=on, cluster_size=64k: 20217
randread 4k: prealloc=metadata, l2_extended=on, cluster_size=64k: 21742
randwrite 4k: prealloc=metadata, l2_extended=on, cluster_size=128k: 21599
randread 4k: prealloc=metadata, l2_extended=on, cluster_size=128k: 22037
clone image with backing file:
randwrite 4k: prealloc=metadata, l2_extended=off, cluster_size=64k: 3912
randread 4k: prealloc=metadata, l2_extended=off, cluster_size=64k: 21476
randwrite 4k: prealloc=metadata, l2_extended=on, cluster_size=64k: 20563
randread 4k: prealloc=metadata, l2_extended=on, cluster_size=64k: 22265
randwrite 4k: prealloc=metadata, l2_extended=on, cluster_size=128k: 18016
randread 4k: prealloc=metadata, l2_extended=on, cluster_size=128k: 21611
Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
src/PVE/Storage/Common.pm | 27 +++++++++++++++++++++++++++
src/PVE/Storage/Plugin.pm | 5 +----
2 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/src/PVE/Storage/Common.pm b/src/PVE/Storage/Common.pm
index 4e4ad30..8910988 100644
--- a/src/PVE/Storage/Common.pm
+++ b/src/PVE/Storage/Common.pm
@@ -25,6 +25,10 @@ my $RAW_PREALLOCATION = {
full => 1,
};
+my $QCOW2_CLUSTERS = {
+ backed => ['extended_l2=on','cluster_size=128k']
+};
+
=pod
=head1 NAME
@@ -179,4 +183,27 @@ sub qemu_img_create {
run_command($cmd, errmsg => "unable to create image");
}
+=pod
+
+=head3 qemu_img_create_qcow2_backed
+
+ qemu_img_create_qcow2_backed($scfg, $path, $backing_path, $backing_format)
+
+Create a new qemu qcow2 image C<$path> using an existing backing image C<$backing_path> with backing_format C<$backing_format>.
+
+=cut
+
+sub qemu_img_create_qcow2_backed {
+ my ($scfg, $path, $backing_path, $backing_format) = @_;
+
+ my $cmd = ['/usr/bin/qemu-img', 'create', '-F', $backing_format, '-b', $backing_path, '-f', 'qcow2', $path];
+
+ my $options = $QCOW2_CLUSTERS->{backed};
+
+ push @$options, preallocation_cmd_option($scfg, 'qcow2');
+ push @$cmd, '-o', join(',', @$options) if @$options > 0;
+
+ run_command($cmd, errmsg => "unable to create image");
+}
+
1;
diff --git a/src/PVE/Storage/Plugin.pm b/src/PVE/Storage/Plugin.pm
index 90627b2..8bf4ed3 100644
--- a/src/PVE/Storage/Plugin.pm
+++ b/src/PVE/Storage/Plugin.pm
@@ -847,10 +847,7 @@ sub clone_image {
eval {
local $CWD = $imagedir;
- my $cmd = ['/usr/bin/qemu-img', 'create', '-b', "../$basevmid/$basename",
- '-F', $format, '-f', 'qcow2', $path];
-
- run_command($cmd);
+ PVE::Storage::Common::qemu_img_create_qcow2_backed($scfg, $path, "../$basevmid/$basename", $format);
};
my $err = $@;
--
2.39.5
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* [pve-devel] [PATCH qemu-server 03/13] blockdev: vm_devices_list : fix block-query
[not found] <20250603075558.627850-1-alexandre.derumier@groupe-cyllene.com>
` (4 preceding siblings ...)
2025-06-03 7:55 ` [pve-devel] [PATCH pve-storage 2/9] common: add qemu_img_create_qcow2_backed Alexandre Derumier via pve-devel
@ 2025-06-03 7:55 ` Alexandre Derumier via pve-devel
2025-06-17 14:44 ` Fiona Ebner
2025-06-03 7:55 ` [pve-devel] [PATCH pve-storage 3/9] common: add qemu_img_info helper Alexandre Derumier via pve-devel
` (16 subsequent siblings)
22 siblings, 1 reply; 39+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-06-03 7:55 UTC (permalink / raw)
To: pve-devel; +Cc: Alexandre Derumier
[-- Attachment #1: Type: message/rfc822, Size: 4145 bytes --]
From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH qemu-server 03/13] blockdev: vm_devices_list : fix block-query
Date: Tue, 3 Jun 2025 09:55:41 +0200
Message-ID: <20250603075558.627850-7-alexandre.derumier@groupe-cyllene.com>
Look at qdev value, as cdrom drives can be empty
without any inserted media
Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
PVE/QemuServer.pm | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index a27dcabb..b15b05aa 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -4061,11 +4061,22 @@ sub vm_devices_list {
$devices_to_check = $to_check;
}
+ # block devices need to be queried at qdev level, as a device
+ # don't always have a blockdev drive media attached (cdrom for example).
+ # Also top node of the graph could have a different name than the device
+ # (we still use "drive-$deviceid" for throttle filter, but it's not 100% safe
+ # if we change that in the future
my $resblock = mon_cmd($vmid, 'query-block');
foreach my $block (@$resblock) {
- if($block->{device} =~ m/^drive-(\S+)/){
- $devices->{$1} = 1;
- }
+ my $qdev_id = $block->{qdev};
+ if ($qdev_id =~ m|^/machine/peripheral/(virtio(\d+))/virtio-backend$|) {
+ $qdev_id = $1;
+ } elsif ($qdev_id =~ m|^/machine/system.flash0$|) {
+ $qdev_id = 'pflash0';
+ } elsif ($qdev_id =~ m|^/machine/system.flash1$|) {
+ $qdev_id = 'efidisk0';
+ }
+ $devices->{$qdev_id} = 1 if $qdev_id;
}
my $resmice = mon_cmd($vmid, 'query-mice');
--
2.39.5
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* [pve-devel] [PATCH pve-storage 3/9] common: add qemu_img_info helper
[not found] <20250603075558.627850-1-alexandre.derumier@groupe-cyllene.com>
` (5 preceding siblings ...)
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 03/13] blockdev: vm_devices_list : fix block-query Alexandre Derumier via pve-devel
@ 2025-06-03 7:55 ` Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 04/13] blockdev: add support to qemu_driveadd && qemu_drivedel Alexandre Derumier via pve-devel
` (15 subsequent siblings)
22 siblings, 0 replies; 39+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-06-03 7:55 UTC (permalink / raw)
To: pve-devel; +Cc: Alexandre Derumier
[-- Attachment #1: Type: message/rfc822, Size: 5332 bytes --]
From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH pve-storage 3/9] common: add qemu_img_info helper
Date: Tue, 3 Jun 2025 09:55:42 +0200
Message-ID: <20250603075558.627850-8-alexandre.derumier@groupe-cyllene.com>
Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
src/PVE/Storage/Common.pm | 35 +++++++++++++++++++++++++++++++++++
src/PVE/Storage/Plugin.pm | 19 +------------------
2 files changed, 36 insertions(+), 18 deletions(-)
diff --git a/src/PVE/Storage/Common.pm b/src/PVE/Storage/Common.pm
index 8910988..25f5d28 100644
--- a/src/PVE/Storage/Common.pm
+++ b/src/PVE/Storage/Common.pm
@@ -206,4 +206,39 @@ sub qemu_img_create_qcow2_backed {
run_command($cmd, errmsg => "unable to create image");
}
+=pod
+
+=head3 qemu_img_info
+
+ qemu_img_info($filename, $file_format, $timeout)
+
+Returns a json with qemu image C<$filename> informations with format <$file_format>.
+
+=cut
+
+sub qemu_img_info {
+ my ($filename, $file_format, $timeout) = @_;
+
+ my $cmd = ['/usr/bin/qemu-img', 'info', '--output=json', $filename];
+ push $cmd->@*, '-f', $file_format if $file_format;
+
+ my $json = '';
+ my $err_output = '';
+ eval {
+ run_command($cmd,
+ timeout => $timeout,
+ outfunc => sub { $json .= shift },
+ errfunc => sub { $err_output .= shift . "\n"},
+ );
+ };
+ warn $@ if $@;
+ if ($err_output) {
+ # if qemu did not output anything to stdout we die with stderr as an error
+ die $err_output if !$json;
+ # otherwise we warn about it and try to parse the json
+ warn $err_output;
+ }
+ return $json;
+}
+
1;
diff --git a/src/PVE/Storage/Plugin.pm b/src/PVE/Storage/Plugin.pm
index 8bf4ed3..dee10e6 100644
--- a/src/PVE/Storage/Plugin.pm
+++ b/src/PVE/Storage/Plugin.pm
@@ -995,25 +995,8 @@ sub file_size_info {
warn "file_size_info: '$filename': falling back to 'raw' from unknown format '$file_format'\n";
$file_format = 'raw';
}
- my $cmd = ['/usr/bin/qemu-img', 'info', '--output=json', $filename];
- push $cmd->@*, '-f', $file_format if $file_format;
- my $json = '';
- my $err_output = '';
- eval {
- run_command($cmd,
- timeout => $timeout,
- outfunc => sub { $json .= shift },
- errfunc => sub { $err_output .= shift . "\n"},
- );
- };
- warn $@ if $@;
- if ($err_output) {
- # if qemu did not output anything to stdout we die with stderr as an error
- die $err_output if !$json;
- # otherwise we warn about it and try to parse the json
- warn $err_output;
- }
+ my $json = PVE::Storage::Common::qemu_img_info($filename, $file_format, $timeout);
if (!$json) {
die "failed to query file information with qemu-img\n" if $untrusted;
# skip decoding if there was no output, e.g. if there was a timeout.
--
2.39.5
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* [pve-devel] [PATCH qemu-server 04/13] blockdev: add support to qemu_driveadd && qemu_drivedel
[not found] <20250603075558.627850-1-alexandre.derumier@groupe-cyllene.com>
` (6 preceding siblings ...)
2025-06-03 7:55 ` [pve-devel] [PATCH pve-storage 3/9] common: add qemu_img_info helper Alexandre Derumier via pve-devel
@ 2025-06-03 7:55 ` Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH pve-storage 4/9] common: add qemu_img_measure Alexandre Derumier via pve-devel
` (14 subsequent siblings)
22 siblings, 0 replies; 39+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-06-03 7:55 UTC (permalink / raw)
To: pve-devel; +Cc: Alexandre Derumier
[-- Attachment #1: Type: message/rfc822, Size: 9395 bytes --]
From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH qemu-server 04/13] blockdev: add support to qemu_driveadd && qemu_drivedel
Date: Tue, 3 Jun 2025 09:55:43 +0200
Message-ID: <20250603075558.627850-9-alexandre.derumier@groupe-cyllene.com>
fixme:
- backup seem to use a tpmstate0-backup drive. Not sure how it's works, but
I think it could be converted to blockdev too
- verify drivedel with fleecing temp image
Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
PVE/QemuServer.pm | 93 ++++++++++++++++++++++++++++++--------
PVE/QemuServer/Blockdev.pm | 1 +
2 files changed, 74 insertions(+), 20 deletions(-)
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index b15b05aa..fa072fca 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -52,7 +52,7 @@ use PVE::QMPClient;
use PVE::QemuConfig;
use PVE::QemuConfig::NoWrite;
use PVE::QemuServer::Helpers qw(config_aware_timeout min_version kvm_user_version windows_version);
-use PVE::QemuServer::Blockdev qw(generate_drive_blockdev);
+use PVE::QemuServer::Blockdev qw(generate_drive_blockdev generate_throttle_group);
use PVE::QemuServer::Cloudinit;
use PVE::QemuServer::CGroup;
use PVE::QemuServer::CPUConfig qw(print_cpu_device get_cpu_options get_cpu_bitness is_native_arch get_amd_sev_object get_amd_sev_type);
@@ -4130,7 +4130,7 @@ sub vm_deviceplug {
qemu_deviceadd($vmid, $devicefull);
eval { qemu_deviceaddverify($vmid, $deviceid); };
if (my $err = $@) {
- eval { qemu_drivedel($vmid, $deviceid); };
+ eval { qemu_drivedel($vmid, $deviceid, $device); };
warn $@ if $@;
die $err;
}
@@ -4159,7 +4159,7 @@ sub vm_deviceplug {
my $devicefull = print_drivedevice_full($storecfg, $conf, $vmid, $device, undef, $arch, $machine_type);
eval { qemu_deviceadd($vmid, $devicefull); };
if (my $err = $@) {
- eval { qemu_drivedel($vmid, $deviceid); };
+ eval { qemu_drivedel($vmid, $deviceid, $device); };
warn $@ if $@;
die $err;
}
@@ -4220,7 +4220,7 @@ sub vm_deviceunplug {
qemu_devicedel($vmid, $deviceid);
qemu_devicedelverify($vmid, $deviceid);
- qemu_drivedel($vmid, $deviceid);
+ qemu_drivedel($vmid, $deviceid, $device);
qemu_iothread_del($vmid, $deviceid, $device);
} elsif ($deviceid =~ m/^(virtioscsi|scsihw)(\d+)$/) {
qemu_devicedel($vmid, $deviceid);
@@ -4230,7 +4230,7 @@ sub vm_deviceunplug {
qemu_devicedel($vmid, $deviceid);
qemu_devicedelverify($vmid, $deviceid);
- qemu_drivedel($vmid, $deviceid);
+ qemu_drivedel($vmid, $deviceid, $device);
qemu_deletescsihw($conf, $vmid, $deviceid);
qemu_iothread_del($vmid, "virtioscsi$device->{index}", $device)
@@ -4281,30 +4281,83 @@ sub qemu_iothread_del {
sub qemu_driveadd {
my ($storecfg, $vmid, $device) = @_;
- my $kvmver = get_running_qemu_version($vmid);
- my $io_uring = min_version($kvmver, 6, 0);
- my $drive = print_drive_commandline_full($storecfg, $vmid, $device, undef, $io_uring);
- $drive =~ s/\\/\\\\/g;
- my $ret = PVE::QemuServer::Monitor::hmp_cmd($vmid, "drive_add auto \"$drive\"", 60);
+ my $machine_type = PVE::QemuServer::Machine::get_current_qemu_machine($vmid);
+
+ if (PVE::QemuServer::Machine::is_machine_version_at_least($machine_type, 10, 0)) {
+
+ my $drive_id = PVE::QemuServer::Drive::get_drive_id($device);
+ # always add a throttle-group, as it's mandatory for the throttle-filter root node.
+ my $throttle_group = generate_throttle_group($device);
+ mon_cmd($vmid, 'object-add', "qom-type" => "throttle-group", %$throttle_group);
+
+ # The throttle filter is the root node with a stable name attached to the device,
+ # and currently it's not possible to insert it later
+ my $blockdev = generate_drive_blockdev($storecfg, $device);
+ mon_cmd($vmid, 'blockdev-add', %$blockdev, timeout => 10 * 60);
+ return 1;
+
+ } else {
+
+ my $kvmver = get_running_qemu_version($vmid);
+ my $io_uring = min_version($kvmver, 6, 0);
+ my $drive = print_drive_commandline_full($storecfg, $vmid, $device, undef, $io_uring);
+ $drive =~ s/\\/\\\\/g;
+ my $ret = PVE::QemuServer::Monitor::hmp_cmd($vmid, "drive_add auto \"$drive\"", 60);
+
+ # If the command succeeds qemu prints: "OK"
+ return 1 if $ret =~ m/OK/s;
+
+ die "adding drive failed: $ret\n";
+ }
+}
- # If the command succeeds qemu prints: "OK"
- return 1 if $ret =~ m/OK/s;
- die "adding drive failed: $ret\n";
+my sub qemu_drivedel_backingchain;
+sub qemu_drivedel_backingchain {
+ my ($fmt_node, $vmid) = @_;
+
+ qemu_drivedel_backingchain($fmt_node->{backing}, $vmid) if $fmt_node->{backing};
+
+ eval { mon_cmd($vmid, 'blockdev-del', 'node-name' => $fmt_node->{'node-name'}); };
+ my $file_node = $fmt_node->{file};
+ eval { mon_cmd($vmid, 'blockdev-del', 'node-name' => $file_node->{'node-name'}); };
}
sub qemu_drivedel {
- my ($vmid, $deviceid) = @_;
+ my ($vmid, $deviceid, $device) = @_;
+
+ my $machine_type = PVE::QemuServer::Machine::get_current_qemu_machine($vmid);
- my $ret = PVE::QemuServer::Monitor::hmp_cmd($vmid, "drive_del drive-$deviceid", 10 * 60);
- $ret =~ s/^\s+//;
+ if (PVE::QemuServer::Machine::is_machine_version_at_least($machine_type, 10, 0)) {
+ #remove top-node
+ eval { mon_cmd($vmid, 'blockdev-del', 'node-name' => "drive-$deviceid", timeout => 10 * 60); };
+ die "deleting blockdev $deviceid failed : $@\n" if $@;
- return 1 if $ret eq "";
+ eval { mon_cmd($vmid, 'object-del', id => "throttle-drive-$deviceid"); };
+ die "deleting throttle group throttle-drive-$deviceid failed : $@\n" if $@;
- # NB: device not found errors mean the drive was auto-deleted and we ignore the error
- return 1 if $ret =~ m/Device \'.*?\' not found/s;
+ #qemu auto-remove fmt && file-node without backing chain
+ #fixme: backup|fleecing temp drivedel don't pass $device currently, maybe it's enough
+ #as they don't have backing chain
+ if($device) {
+ my $storecfg = PVE::Storage::config();
+ my $blockdev = generate_drive_blockdev($storecfg, $device);
+ my $fmt_node = $blockdev->{file};
+ qemu_drivedel_backingchain($fmt_node, $vmid);
+ }
+
+ } else {
+
+ my $ret = PVE::QemuServer::Monitor::hmp_cmd($vmid, "drive_del drive-$deviceid", 10 * 60);
+ $ret =~ s/^\s+//;
- die "deleting drive $deviceid failed : $ret\n";
+ return 1 if $ret eq "";
+
+ # NB: device not found errors mean the drive was auto-deleted and we ignore the error
+ return 1 if $ret =~ m/Device \'.*?\' not found/s;
+
+ die "deleting drive $deviceid failed : $ret\n";
+ }
}
sub qemu_deviceaddverify {
diff --git a/PVE/QemuServer/Blockdev.pm b/PVE/QemuServer/Blockdev.pm
index b4dd1ef5..01fef66d 100644
--- a/PVE/QemuServer/Blockdev.pm
+++ b/PVE/QemuServer/Blockdev.pm
@@ -10,6 +10,7 @@ use base qw(Exporter);
our @EXPORT_OK = qw(
generate_drive_blockdev
+generate_throttle_group
);
sub encode_base62 {
--
2.39.5
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* [pve-devel] [PATCH pve-storage 4/9] common: add qemu_img_measure
[not found] <20250603075558.627850-1-alexandre.derumier@groupe-cyllene.com>
` (7 preceding siblings ...)
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 04/13] blockdev: add support to qemu_driveadd && qemu_drivedel Alexandre Derumier via pve-devel
@ 2025-06-03 7:55 ` Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 05/13] blockdev: add support to qemu_block_set_io_throttle Alexandre Derumier via pve-devel
` (13 subsequent siblings)
22 siblings, 0 replies; 39+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-06-03 7:55 UTC (permalink / raw)
To: pve-devel; +Cc: Alexandre Derumier
[-- Attachment #1: Type: message/rfc822, Size: 4344 bytes --]
From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH pve-storage 4/9] common: add qemu_img_measure
Date: Tue, 3 Jun 2025 09:55:44 +0200
Message-ID: <20250603075558.627850-10-alexandre.derumier@groupe-cyllene.com>
Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
src/PVE/Storage/Common.pm | 40 +++++++++++++++++++++++++++++++++++++++
1 file changed, 40 insertions(+)
diff --git a/src/PVE/Storage/Common.pm b/src/PVE/Storage/Common.pm
index 25f5d28..11b5b94 100644
--- a/src/PVE/Storage/Common.pm
+++ b/src/PVE/Storage/Common.pm
@@ -241,4 +241,44 @@ sub qemu_img_info {
return $json;
}
+=pod
+
+=head3 qemu_img_measure
+
+ qemu_img_measure($size, $fmt, $timeout, $is_backed)
+
+Returns a json with the maximum size including all metadatas overhead for an image with format C<$fmt> and original size C<$size>Kb.
+If the image is backed C<$is_backed>, we use different cluster size informations.
+=cut
+
+sub qemu_img_measure {
+ my ($size, $fmt, $timeout, $is_backed) = @_;
+
+ die "format is missing" if !$fmt;
+
+ my $cmd = ['/usr/bin/qemu-img', 'measure', '--output=json', '--size', "${size}K", '-O', $fmt];
+ if ($is_backed) {
+ my $options = $QCOW2_CLUSTERS->{backed};
+ push $cmd->@*, '-o', join(',', @$options) if @$options > 0;
+ }
+
+ my $json = '';
+ my $err_output = '';
+ eval {
+ run_command($cmd,
+ timeout => $timeout,
+ outfunc => sub { $json .= shift },
+ errfunc => sub { $err_output .= shift . "\n"},
+ );
+ };
+ warn $@ if $@;
+ if ($err_output) {
+ # if qemu did not output anything to stdout we die with stderr as an error
+ die $err_output if !$json;
+ # otherwise we warn about it and try to parse the json
+ warn $err_output;
+ }
+ return $json;
+}
+
1;
--
2.39.5
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* [pve-devel] [PATCH qemu-server 05/13] blockdev: add support to qemu_block_set_io_throttle
[not found] <20250603075558.627850-1-alexandre.derumier@groupe-cyllene.com>
` (8 preceding siblings ...)
2025-06-03 7:55 ` [pve-devel] [PATCH pve-storage 4/9] common: add qemu_img_measure Alexandre Derumier via pve-devel
@ 2025-06-03 7:55 ` Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH pve-storage 5/9] rename_volume: add source && target snap Alexandre Derumier via pve-devel
` (12 subsequent siblings)
22 siblings, 0 replies; 39+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-06-03 7:55 UTC (permalink / raw)
To: pve-devel; +Cc: Alexandre Derumier
[-- Attachment #1: Type: message/rfc822, Size: 5751 bytes --]
From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH qemu-server 05/13] blockdev: add support to qemu_block_set_io_throttle
Date: Tue, 3 Jun 2025 09:55:45 +0200
Message-ID: <20250603075558.627850-11-alexandre.derumier@groupe-cyllene.com>
Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
PVE/QemuServer.pm | 71 +++++++++++++++++++++++++++++++++--------------
1 file changed, 50 insertions(+), 21 deletions(-)
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index fa072fca..0af091aa 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -4592,27 +4592,56 @@ sub qemu_block_set_io_throttle {
return if !check_running($vmid) ;
- mon_cmd($vmid, "block_set_io_throttle", device => $deviceid,
- bps => int($bps),
- bps_rd => int($bps_rd),
- bps_wr => int($bps_wr),
- iops => int($iops),
- iops_rd => int($iops_rd),
- iops_wr => int($iops_wr),
- bps_max => int($bps_max),
- bps_rd_max => int($bps_rd_max),
- bps_wr_max => int($bps_wr_max),
- iops_max => int($iops_max),
- iops_rd_max => int($iops_rd_max),
- iops_wr_max => int($iops_wr_max),
- bps_max_length => int($bps_max_length),
- bps_rd_max_length => int($bps_rd_max_length),
- bps_wr_max_length => int($bps_wr_max_length),
- iops_max_length => int($iops_max_length),
- iops_rd_max_length => int($iops_rd_max_length),
- iops_wr_max_length => int($iops_wr_max_length),
- );
-
+ my $machine_type = PVE::QemuServer::Machine::get_current_qemu_machine($vmid);
+ if (PVE::QemuServer::Machine::is_machine_version_at_least($machine_type, 10, 0)) {
+ mon_cmd(
+ $vmid,
+ 'qom-set',
+ path => "throttle-$deviceid",
+ property => "limits",
+ value => {
+ 'bps-total' => int($bps),
+ 'bps-read' => int($bps_rd),
+ 'bps-write' => int($bps_wr),
+ 'iops-total' => int($iops),
+ 'iops-read' => int($iops_rd),
+ 'iops-write' => int($iops_wr),
+ 'bps-total-max' => int($bps_max),
+ 'bps-read-max' => int($bps_rd_max),
+ 'bps-write-max' => int($bps_wr_max),
+ 'iops-total-max' => int($iops_max),
+ 'iops-read-max' => int($iops_rd_max),
+ 'iops-write-max' => int($iops_wr_max),
+ 'bps-total-max-length' => int($bps_max_length),
+ 'bps-read-max-length' => int($bps_rd_max_length),
+ 'bps-write-max-length' => int($bps_wr_max_length),
+ 'iops-total-max-length' => int($iops_max_length),
+ 'iops-read-max-length' => int($iops_rd_max_length),
+ 'iops-write-max-length' => int($iops_wr_max_length),
+ }
+ );
+ } else {
+ mon_cmd($vmid, "block_set_io_throttle", device => $deviceid,
+ bps => int($bps),
+ bps_rd => int($bps_rd),
+ bps_wr => int($bps_wr),
+ iops => int($iops),
+ iops_rd => int($iops_rd),
+ iops_wr => int($iops_wr),
+ bps_max => int($bps_max),
+ bps_rd_max => int($bps_rd_max),
+ bps_wr_max => int($bps_wr_max),
+ iops_max => int($iops_max),
+ iops_rd_max => int($iops_rd_max),
+ iops_wr_max => int($iops_wr_max),
+ bps_max_length => int($bps_max_length),
+ bps_rd_max_length => int($bps_rd_max_length),
+ bps_wr_max_length => int($bps_wr_max_length),
+ iops_max_length => int($iops_max_length),
+ iops_rd_max_length => int($iops_rd_max_length),
+ iops_wr_max_length => int($iops_wr_max_length),
+ );
+ }
}
sub qemu_block_resize {
--
2.39.5
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* [pve-devel] [PATCH pve-storage 5/9] rename_volume: add source && target snap
[not found] <20250603075558.627850-1-alexandre.derumier@groupe-cyllene.com>
` (9 preceding siblings ...)
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 05/13] blockdev: add support to qemu_block_set_io_throttle Alexandre Derumier via pve-devel
@ 2025-06-03 7:55 ` Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 06/13] blockdev: add support for cdrom media eject/insert Alexandre Derumier via pve-devel
` (11 subsequent siblings)
22 siblings, 0 replies; 39+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-06-03 7:55 UTC (permalink / raw)
To: pve-devel; +Cc: Alexandre Derumier
[-- Attachment #1: Type: message/rfc822, Size: 6172 bytes --]
From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH pve-storage 5/9] rename_volume: add source && target snap
Date: Tue, 3 Jun 2025 09:55:46 +0200
Message-ID: <20250603075558.627850-12-alexandre.derumier@groupe-cyllene.com>
allow to rename from|to external snapshot volname
Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
src/PVE/Storage.pm | 4 ++--
src/PVE/Storage/LVMPlugin.pm | 8 ++++++--
src/PVE/Storage/Plugin.pm | 5 ++++-
3 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/src/PVE/Storage.pm b/src/PVE/Storage.pm
index 423e45f..27472d1 100755
--- a/src/PVE/Storage.pm
+++ b/src/PVE/Storage.pm
@@ -2127,7 +2127,7 @@ sub complete_volume {
}
sub rename_volume {
- my ($cfg, $source_volid, $target_vmid, $target_volname) = @_;
+ my ($cfg, $source_volid, $target_vmid, $target_volname, $source_snap, $target_snap) = @_;
die "no source volid provided\n" if !$source_volid;
die "no target VMID or target volname provided\n" if !$target_vmid && !$target_volname;
@@ -2142,7 +2142,7 @@ sub rename_volume {
$target_vmid = ($plugin->parse_volname($source_volname))[3] if !$target_vmid;
return $plugin->cluster_lock_storage($storeid, $scfg->{shared}, undef, sub {
- return $plugin->rename_volume($scfg, $storeid, $source_volname, $target_vmid, $target_volname);
+ return $plugin->rename_volume($scfg, $storeid, $source_volname, $target_vmid, $target_volname, $source_snap, $target_snap);
});
}
diff --git a/src/PVE/Storage/LVMPlugin.pm b/src/PVE/Storage/LVMPlugin.pm
index 2ebec88..c4648ec 100644
--- a/src/PVE/Storage/LVMPlugin.pm
+++ b/src/PVE/Storage/LVMPlugin.pm
@@ -718,7 +718,7 @@ sub volume_import_write {
}
sub rename_volume {
- my ($class, $scfg, $storeid, $source_volname, $target_vmid, $target_volname) = @_;
+ my ($class, $scfg, $storeid, $source_volname, $target_vmid, $target_volname, $source_snap, $target_snap) = @_;
my (
undef,
@@ -729,6 +729,10 @@ sub rename_volume {
undef,
$format
) = $class->parse_volname($source_volname);
+
+ $source_image = $class->get_snap_volname($source_volname, $source_snap) if $source_snap;
+ $target_volname = $class->get_snap_volname($source_volname, $target_snap) if $target_snap;
+
$target_volname = $class->find_free_diskname($storeid, $scfg, $target_vmid, $format)
if !$target_volname;
@@ -737,7 +741,7 @@ sub rename_volume {
die "target volume '${target_volname}' already exists\n"
if ($lvs->{$vg}->{$target_volname});
- lvrename($vg, $source_volname, $target_volname);
+ lvrename($vg, $source_image, $target_volname);
return "${storeid}:${target_volname}";
}
diff --git a/src/PVE/Storage/Plugin.pm b/src/PVE/Storage/Plugin.pm
index dee10e6..a183e41 100644
--- a/src/PVE/Storage/Plugin.pm
+++ b/src/PVE/Storage/Plugin.pm
@@ -1781,7 +1781,7 @@ sub volume_import_formats {
}
sub rename_volume {
- my ($class, $scfg, $storeid, $source_volname, $target_vmid, $target_volname) = @_;
+ my ($class, $scfg, $storeid, $source_volname, $target_vmid, $target_volname, $source_snap, $target_snap) = @_;
die "not implemented in storage plugin '$class'\n" if $class->can('api') && $class->api() < 10;
die "no path found\n" if !$scfg->{path};
@@ -1795,6 +1795,9 @@ sub rename_volume {
$format
) = $class->parse_volname($source_volname);
+ $source_image = $class->get_snap_name($source_volname, $source_snap) if $source_snap;
+ $target_volname = $class->get_snap_name($source_volname, $target_snap) if $target_snap;
+
$target_volname = $class->find_free_diskname($storeid, $scfg, $target_vmid, $format, 1)
if !$target_volname;
--
2.39.5
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* [pve-devel] [PATCH qemu-server 06/13] blockdev: add support for cdrom media eject/insert
[not found] <20250603075558.627850-1-alexandre.derumier@groupe-cyllene.com>
` (10 preceding siblings ...)
2025-06-03 7:55 ` [pve-devel] [PATCH pve-storage 5/9] rename_volume: add source && target snap Alexandre Derumier via pve-devel
@ 2025-06-03 7:55 ` Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH pve-storage 6/9] storage: volume_snapshot: add $running param + api bump Alexandre Derumier via pve-devel
` (10 subsequent siblings)
22 siblings, 0 replies; 39+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-06-03 7:55 UTC (permalink / raw)
To: pve-devel; +Cc: Alexandre Derumier
[-- Attachment #1: Type: message/rfc822, Size: 6132 bytes --]
From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH qemu-server 06/13] blockdev: add support for cdrom media eject/insert
Date: Tue, 3 Jun 2025 09:55:47 +0200
Message-ID: <20250603075558.627850-13-alexandre.derumier@groupe-cyllene.com>
reuse the code for cloud-init too
Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
PVE/QemuServer.pm | 79 ++++++++++++++++++++++++++---------------------
1 file changed, 43 insertions(+), 36 deletions(-)
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 0af091aa..8e1369fc 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -5347,6 +5347,42 @@ sub vmconfig_update_agent {
return; # either no actual change (e.g., format string reordered) or just hotpluggable changes
}
+my sub qemu_change_cdrom_media {
+ my ($storecfg, $vmid, $opt, $drive) = @_;
+
+ my $machine_type = PVE::QemuServer::Machine::get_current_qemu_machine($vmid);
+ if (PVE::QemuServer::Machine::is_machine_version_at_least($machine_type, 10, 0)) {
+ # force eject if locked
+ mon_cmd($vmid, "blockdev-open-tray", force => JSON::true, id => $opt);
+ mon_cmd($vmid, "blockdev-remove-medium", id => $opt);
+ eval { qemu_drivedel($vmid, $opt) };
+
+ my $blockdev = generate_drive_blockdev($storecfg, $drive);
+ return if !$blockdev;
+
+ qemu_driveadd($storecfg, $vmid, $drive);
+ mon_cmd($vmid, "blockdev-insert-medium", id => $opt, 'node-name' => $blockdev->{'node-name'});
+ mon_cmd($vmid, "blockdev-close-tray", id => $opt);
+ } else {
+ # force eject if locked
+ mon_cmd($vmid, "eject", force => JSON::true, id => "$opt");
+ return if $drive->{file} eq 'none';
+
+ my ($path, $format) = PVE::QemuServer::Drive::get_path_and_format(
+ $storecfg, $vmid, $drive);
+
+ if ($path) {
+ mon_cmd(
+ $vmid,
+ "blockdev-change-medium",
+ id => "$opt",
+ filename => "$path",
+ format => "$format",
+ );
+ }
+ }
+}
+
sub vmconfig_update_disk {
my ($storecfg, $conf, $hotplug, $vmid, $opt, $value, $arch, $machine_type) = @_;
@@ -5430,29 +5466,12 @@ sub vmconfig_update_disk {
return 1;
}
- } else { # cdrom
+ } else { # cdrom
- if ($drive->{file} eq 'none') {
- mon_cmd($vmid, "eject", force => JSON::true, id => "$opt");
- if (drive_is_cloudinit($old_drive)) {
- vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive);
- }
- } else {
- my ($path, $format) = PVE::QemuServer::Drive::get_path_and_format(
- $storecfg, $vmid, $drive);
-
- # force eject if locked
- mon_cmd($vmid, "eject", force => JSON::true, id => "$opt");
-
- if ($path) {
- mon_cmd(
- $vmid,
- "blockdev-change-medium",
- id => "$opt",
- filename => "$path",
- format => "$format",
- );
- }
+ qemu_change_cdrom_media($storecfg, $vmid, $opt, $drive);
+
+ if ($drive->{file} eq 'none' && drive_is_cloudinit($old_drive)) {
+ vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive);
}
return 1;
@@ -5486,21 +5505,9 @@ sub vmconfig_update_cloudinit_drive {
}
my $running = PVE::QemuServer::check_running($vmid);
+ return if !$running;
- if ($running) {
- my ($path, $format) = PVE::QemuServer::Drive::get_path_and_format(
- $storecfg, $vmid, $cloudinit_drive);
- if ($path) {
- mon_cmd($vmid, "eject", force => JSON::true, id => "$cloudinit_ds");
- mon_cmd(
- $vmid,
- "blockdev-change-medium",
- id => "$cloudinit_ds",
- filename => "$path",
- format => "$format",
- );
- }
- }
+ qemu_change_cdrom_media($storecfg, $vmid, $cloudinit_ds, $cloudinit_drive);
}
# called in locked context by incoming migration
--
2.39.5
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* [pve-devel] [PATCH pve-storage 6/9] storage: volume_snapshot: add $running param + api bump
[not found] <20250603075558.627850-1-alexandre.derumier@groupe-cyllene.com>
` (11 preceding siblings ...)
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 06/13] blockdev: add support for cdrom media eject/insert Alexandre Derumier via pve-devel
@ 2025-06-03 7:55 ` Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 07/13] blockdev: add support for block_resize Alexandre Derumier via pve-devel
` (9 subsequent siblings)
22 siblings, 0 replies; 39+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-06-03 7:55 UTC (permalink / raw)
To: pve-devel; +Cc: Alexandre Derumier
[-- Attachment #1: Type: message/rfc822, Size: 9116 bytes --]
From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH pve-storage 6/9] storage: volume_snapshot: add $running param + api bump
Date: Tue, 3 Jun 2025 09:55:48 +0200
Message-ID: <20250603075558.627850-14-alexandre.derumier@groupe-cyllene.com>
This add a $running param to volume_snapshot,
it can be used if some extra actions need to be done at the storage
layer when the snapshot has already be done at qemu level.
Note: zfs && rbd plugins already used this param in create_base,
but it was not implemented in volume_snapshot.
Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
src/PVE/Storage.pm | 8 ++++----
src/PVE/Storage/BTRFSPlugin.pm | 2 +-
src/PVE/Storage/ESXiPlugin.pm | 2 +-
src/PVE/Storage/ISCSIDirectPlugin.pm | 2 +-
src/PVE/Storage/LVMPlugin.pm | 2 +-
src/PVE/Storage/LvmThinPlugin.pm | 2 +-
src/PVE/Storage/PBSPlugin.pm | 2 +-
src/PVE/Storage/Plugin.pm | 2 +-
src/PVE/Storage/RBDPlugin.pm | 2 +-
src/PVE/Storage/ZFSPoolPlugin.pm | 2 +-
10 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/src/PVE/Storage.pm b/src/PVE/Storage.pm
index 27472d1..973161f 100755
--- a/src/PVE/Storage.pm
+++ b/src/PVE/Storage.pm
@@ -42,11 +42,11 @@ use PVE::Storage::BTRFSPlugin;
use PVE::Storage::ESXiPlugin;
# Storage API version. Increment it on changes in storage API interface.
-use constant APIVER => 11;
+use constant APIVER => 12;
# Age is the number of versions we're backward compatible with.
# This is like having 'current=APIVER' and age='APIAGE' in libtool,
# see https://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html
-use constant APIAGE => 2;
+use constant APIAGE => 3;
our $KNOWN_EXPORT_FORMATS = ['raw+size', 'tar+size', 'qcow2+size', 'vmdk+size', 'zfs', 'btrfs'];
@@ -348,13 +348,13 @@ sub volume_rollback_is_possible {
}
sub volume_snapshot {
- my ($cfg, $volid, $snap) = @_;
+ my ($cfg, $volid, $snap, $running) = @_;
my ($storeid, $volname) = parse_volume_id($volid, 1);
if ($storeid) {
my $scfg = storage_config($cfg, $storeid);
my $plugin = PVE::Storage::Plugin->lookup($scfg->{type});
- return $plugin->volume_snapshot($scfg, $storeid, $volname, $snap);
+ return $plugin->volume_snapshot($scfg, $storeid, $volname, $snap, $running);
} elsif ($volid =~ m|^(/.+)$| && -e $volid) {
die "snapshot file/device '$volid' is not possible\n";
} else {
diff --git a/src/PVE/Storage/BTRFSPlugin.pm b/src/PVE/Storage/BTRFSPlugin.pm
index 5d472fa..45f4cd1 100644
--- a/src/PVE/Storage/BTRFSPlugin.pm
+++ b/src/PVE/Storage/BTRFSPlugin.pm
@@ -512,7 +512,7 @@ sub volume_resize {
}
sub volume_snapshot {
- my ($class, $scfg, $storeid, $volname, $snap) = @_;
+ my ($class, $scfg, $storeid, $volname, $snap, $running) = @_;
my ($name, $vmid, $format) = ($class->parse_volname($volname))[1,2,6];
if ($format ne 'subvol' && $format ne 'raw') {
diff --git a/src/PVE/Storage/ESXiPlugin.pm b/src/PVE/Storage/ESXiPlugin.pm
index bedeac8..cd11ec6 100644
--- a/src/PVE/Storage/ESXiPlugin.pm
+++ b/src/PVE/Storage/ESXiPlugin.pm
@@ -544,7 +544,7 @@ sub volume_size_info {
}
sub volume_snapshot {
- my ($class, $scfg, $storeid, $volname, $snap) = @_;
+ my ($class, $scfg, $storeid, $volname, $snap, $running) = @_;
die "creating snapshots is not supported for $class\n";
}
diff --git a/src/PVE/Storage/ISCSIDirectPlugin.pm b/src/PVE/Storage/ISCSIDirectPlugin.pm
index 394c98f..c226f54 100644
--- a/src/PVE/Storage/ISCSIDirectPlugin.pm
+++ b/src/PVE/Storage/ISCSIDirectPlugin.pm
@@ -227,7 +227,7 @@ sub volume_resize {
}
sub volume_snapshot {
- my ($class, $scfg, $storeid, $volname, $snap) = @_;
+ my ($class, $scfg, $storeid, $volname, $snap, $running) = @_;
die "volume snapshot is not possible on iscsi device\n";
}
diff --git a/src/PVE/Storage/LVMPlugin.pm b/src/PVE/Storage/LVMPlugin.pm
index c4648ec..25268a4 100644
--- a/src/PVE/Storage/LVMPlugin.pm
+++ b/src/PVE/Storage/LVMPlugin.pm
@@ -586,7 +586,7 @@ sub volume_size_info {
}
sub volume_snapshot {
- my ($class, $scfg, $storeid, $volname, $snap) = @_;
+ my ($class, $scfg, $storeid, $volname, $snap, $running) = @_;
die "lvm snapshot is not implemented";
}
diff --git a/src/PVE/Storage/LvmThinPlugin.pm b/src/PVE/Storage/LvmThinPlugin.pm
index 49a4dcb..2bb8665 100644
--- a/src/PVE/Storage/LvmThinPlugin.pm
+++ b/src/PVE/Storage/LvmThinPlugin.pm
@@ -325,7 +325,7 @@ sub create_base {
# sub volume_resize {} reuse code from parent class
sub volume_snapshot {
- my ($class, $scfg, $storeid, $volname, $snap) = @_;
+ my ($class, $scfg, $storeid, $volname, $snap, $running) = @_;
my $vg = $scfg->{vgname};
my $snapvol = "snap_${volname}_$snap";
diff --git a/src/PVE/Storage/PBSPlugin.pm b/src/PVE/Storage/PBSPlugin.pm
index 9f75794..830aba5 100644
--- a/src/PVE/Storage/PBSPlugin.pm
+++ b/src/PVE/Storage/PBSPlugin.pm
@@ -956,7 +956,7 @@ sub volume_resize {
}
sub volume_snapshot {
- my ($class, $scfg, $storeid, $volname, $snap) = @_;
+ my ($class, $scfg, $storeid, $volname, $snap, $running) = @_;
die "volume snapshot is not possible on pbs device";
}
diff --git a/src/PVE/Storage/Plugin.pm b/src/PVE/Storage/Plugin.pm
index a183e41..00eebd3 100644
--- a/src/PVE/Storage/Plugin.pm
+++ b/src/PVE/Storage/Plugin.pm
@@ -1118,7 +1118,7 @@ sub volume_resize {
}
sub volume_snapshot {
- my ($class, $scfg, $storeid, $volname, $snap) = @_;
+ my ($class, $scfg, $storeid, $volname, $snap, $running) = @_;
die "can't snapshot this image format\n" if $volname !~ m/\.(qcow2|qed)$/;
diff --git a/src/PVE/Storage/RBDPlugin.pm b/src/PVE/Storage/RBDPlugin.pm
index 5a2cf7c..afed2be 100644
--- a/src/PVE/Storage/RBDPlugin.pm
+++ b/src/PVE/Storage/RBDPlugin.pm
@@ -845,7 +845,7 @@ sub volume_resize {
}
sub volume_snapshot {
- my ($class, $scfg, $storeid, $volname, $snap) = @_;
+ my ($class, $scfg, $storeid, $volname, $snap, $running) = @_;
my ($vtype, $name, $vmid) = $class->parse_volname($volname);
diff --git a/src/PVE/Storage/ZFSPoolPlugin.pm b/src/PVE/Storage/ZFSPoolPlugin.pm
index cd01414..21f2db1 100644
--- a/src/PVE/Storage/ZFSPoolPlugin.pm
+++ b/src/PVE/Storage/ZFSPoolPlugin.pm
@@ -475,7 +475,7 @@ sub volume_size_info {
}
sub volume_snapshot {
- my ($class, $scfg, $storeid, $volname, $snap) = @_;
+ my ($class, $scfg, $storeid, $volname, $snap, $running) = @_;
my $vname = ($class->parse_volname($volname))[1];
--
2.39.5
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* [pve-devel] [PATCH qemu-server 07/13] blockdev: add support for block_resize
[not found] <20250603075558.627850-1-alexandre.derumier@groupe-cyllene.com>
` (12 preceding siblings ...)
2025-06-03 7:55 ` [pve-devel] [PATCH pve-storage 6/9] storage: volume_snapshot: add $running param + api bump Alexandre Derumier via pve-devel
@ 2025-06-03 7:55 ` Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH pve-storage 7/9] qcow2: add external snapshot support Alexandre Derumier via pve-devel
` (8 subsequent siblings)
22 siblings, 0 replies; 39+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-06-03 7:55 UTC (permalink / raw)
To: pve-devel; +Cc: Alexandre Derumier
[-- Attachment #1: Type: message/rfc822, Size: 3811 bytes --]
From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH qemu-server 07/13] blockdev: add support for block_resize
Date: Tue, 3 Jun 2025 09:55:49 +0200
Message-ID: <20250603075558.627850-15-alexandre.derumier@groupe-cyllene.com>
We need to use the top blocknode (throttle) as name-node
Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
PVE/QemuServer.pm | 25 ++++++++++++++++++-------
1 file changed, 18 insertions(+), 7 deletions(-)
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 8e1369fc..04e71fb6 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -4656,13 +4656,24 @@ sub qemu_block_resize {
my $padding = (1024 - $size % 1024) % 1024;
$size = $size + $padding;
- mon_cmd(
- $vmid,
- "block_resize",
- device => $deviceid,
- size => int($size),
- timeout => 60,
- );
+ my $machine_type = PVE::QemuServer::Machine::get_current_qemu_machine($vmid);
+ if (PVE::QemuServer::Machine::is_machine_version_at_least($machine_type, 10, 0)) {
+ mon_cmd(
+ $vmid,
+ "block_resize",
+ 'node-name' => $deviceid,
+ size => int($size),
+ timeout => 60,
+ );
+ } else {
+ mon_cmd(
+ $vmid,
+ "block_resize",
+ device => $deviceid,
+ size => int($size),
+ timeout => 60,
+ );
+ }
}
sub qemu_volume_snapshot {
--
2.39.5
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* [pve-devel] [PATCH pve-storage 7/9] qcow2: add external snapshot support
[not found] <20250603075558.627850-1-alexandre.derumier@groupe-cyllene.com>
` (13 preceding siblings ...)
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 07/13] blockdev: add support for block_resize Alexandre Derumier via pve-devel
@ 2025-06-03 7:55 ` Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 08/13] blockdev: add support for nbd_export: block-export-add Alexandre Derumier via pve-devel
` (7 subsequent siblings)
22 siblings, 0 replies; 39+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-06-03 7:55 UTC (permalink / raw)
To: pve-devel; +Cc: Alexandre Derumier
[-- Attachment #1: Type: message/rfc822, Size: 15842 bytes --]
From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH pve-storage 7/9] qcow2: add external snapshot support
Date: Tue, 3 Jun 2025 09:55:50 +0200
Message-ID: <20250603075558.627850-16-alexandre.derumier@groupe-cyllene.com>
add a snapext option to enable the feature
When a snapshot is taken, the current volume is renamed to snap volname
and a current image is created with the snap volume as backing file
Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
src/PVE/Storage.pm | 1 -
src/PVE/Storage/Common.pm | 3 +-
src/PVE/Storage/DirPlugin.pm | 1 +
src/PVE/Storage/Plugin.pm | 241 +++++++++++++++++++++++++++++++++--
4 files changed, 230 insertions(+), 16 deletions(-)
diff --git a/src/PVE/Storage.pm b/src/PVE/Storage.pm
index 973161f..2a2005b 100755
--- a/src/PVE/Storage.pm
+++ b/src/PVE/Storage.pm
@@ -378,7 +378,6 @@ sub volume_snapshot_rollback {
}
}
-# FIXME PVE 8.x remove $running parameter (needs APIAGE reset)
sub volume_snapshot_delete {
my ($cfg, $volid, $snap, $running) = @_;
diff --git a/src/PVE/Storage/Common.pm b/src/PVE/Storage/Common.pm
index 11b5b94..7e87a54 100644
--- a/src/PVE/Storage/Common.pm
+++ b/src/PVE/Storage/Common.pm
@@ -217,10 +217,11 @@ Returns a json with qemu image C<$filename> informations with format <$file_form
=cut
sub qemu_img_info {
- my ($filename, $file_format, $timeout) = @_;
+ my ($filename, $file_format, $timeout, $follow_backing_files) = @_;
my $cmd = ['/usr/bin/qemu-img', 'info', '--output=json', $filename];
push $cmd->@*, '-f', $file_format if $file_format;
+ push $cmd->@*, '--backing-chain' if $follow_backing_files;
my $json = '';
my $err_output = '';
diff --git a/src/PVE/Storage/DirPlugin.pm b/src/PVE/Storage/DirPlugin.pm
index 734309f..54d8d74 100644
--- a/src/PVE/Storage/DirPlugin.pm
+++ b/src/PVE/Storage/DirPlugin.pm
@@ -83,6 +83,7 @@ sub options {
is_mountpoint => { optional => 1 },
bwlimit => { optional => 1 },
preallocation => { optional => 1 },
+ snapext => { optional => 1 },
};
}
diff --git a/src/PVE/Storage/Plugin.pm b/src/PVE/Storage/Plugin.pm
index 00eebd3..fd50b9e 100644
--- a/src/PVE/Storage/Plugin.pm
+++ b/src/PVE/Storage/Plugin.pm
@@ -202,6 +202,11 @@ my $defaultData = {
maximum => 65535,
optional => 1,
},
+ 'snapext' => {
+ type => 'boolean',
+ description => 'enable external snapshot.',
+ optional => 1,
+ },
},
};
@@ -696,6 +701,8 @@ sub filesystem_path {
my ($vtype, $name, $vmid, undef, undef, $isBase, $format) =
$class->parse_volname($volname);
+ $name = $class->get_snap_name($volname, $snapname) if $scfg->{snapext} && $snapname;
+
# Note: qcow2/qed has internal snapshot, so path is always
# the same (with or without snapshot => same file).
die "can't snapshot this image format\n"
@@ -896,6 +903,26 @@ sub alloc_image {
return "$vmid/$name";
}
+my sub alloc_backed_image {
+ my ($class, $storeid, $scfg, $volname, $backing_snap) = @_;
+
+ my $path = $class->path($scfg, $volname, $storeid);
+ my $backing_path = $class->path($scfg, $volname, $storeid, $backing_snap);
+
+ eval { PVE::Storage::Common::qemu_img_create_qcow2_backed($scfg, $path, $backing_path, 'qcow2') };
+ if ($@) {
+ unlink $path;
+ die "$@";
+ }
+}
+
+my sub free_snap_image {
+ my ($class, $storeid, $scfg, $volname, $snap) = @_;
+
+ my $path = $class->path($scfg, $volname, $storeid, $snap);
+ unlink($path) || die "unlink '$path' failed - $!\n";
+}
+
sub free_image {
my ($class, $storeid, $scfg, $volname, $isBase, $format) = @_;
@@ -918,6 +945,17 @@ sub free_image {
return undef;
}
+ #delete external snapshots
+ if($scfg->{snapext}) {
+ my $snapshots = $class->volume_snapshot_info($scfg, $storeid, $volname);
+ for my $snapid (sort { $snapshots->{$b}->{order} <=> $snapshots->{$a}->{order} } keys %$snapshots) {
+ my $snap = $snapshots->{$snapid};
+ next if $snapid eq 'current';
+ next if !$snap->{ext};
+ free_snap_image($class, $storeid, $scfg, $volname, $snapid);
+ }
+ }
+
unlink($path) || die "unlink '$path' failed - $!\n";
}
@@ -1122,11 +1160,33 @@ sub volume_snapshot {
die "can't snapshot this image format\n" if $volname !~ m/\.(qcow2|qed)$/;
- my $path = $class->filesystem_path($scfg, $volname);
+ if($scfg->{snapext}) {
- my $cmd = ['/usr/bin/qemu-img', 'snapshot','-c', $snap, $path];
+ my $vmid = ($class->parse_volname($volname))[2];
- run_command($cmd);
+ #if running, the old current has been renamed with blockdev-reopen by qemu
+ if (!$running) {
+ #rename current volume to snap volume
+ $class->rename_volume($scfg, $storeid, $volname, $vmid, undef, 'current', $snap);
+ }
+
+ eval { alloc_backed_image($class, $storeid, $scfg, $volname, $snap) };
+ if ($@) {
+ warn "$@ \n";
+ #if running, the revert is done by qemu with blockdev-reopen
+ if (!$running) {
+ eval { $class->rename_volume($scfg, $storeid, $volname, $vmid, undef, $snap, 'current') };
+ warn $@ if $@;
+ }
+ die "can't allocate new volume $volname with $snap backing image\n";
+ }
+
+ } else {
+
+ my $path = $class->filesystem_path($scfg, $volname);
+ my $cmd = ['/usr/bin/qemu-img', 'snapshot','-c', $snap, $path];
+ run_command($cmd);
+ }
return undef;
}
@@ -1137,6 +1197,21 @@ sub volume_snapshot {
sub volume_rollback_is_possible {
my ($class, $scfg, $storeid, $volname, $snap, $blockers) = @_;
+ if ($scfg->{snapext}) {
+ #technically, we could manage multibranch, we it need lot more work for snapshot delete
+ #we need to implemente block-stream from deleted snapshot to all others child branchs
+ #when online, we need to do a transaction for multiple disk when delete the last snapshot
+ #and need to merge in current running file
+
+ my $snappath = $class->path($scfg, $volname, $storeid, $snap);
+ my $snapshots = $class->volume_snapshot_info($scfg, $storeid, $volname);
+ my $parentsnap = $snapshots->{current}->{parent};
+
+ return 1 if $parentsnap eq $snap;
+
+ die "can't rollback, '$snap' is not most recent snapshot on '$volname'\n";
+ }
+
return 1;
}
@@ -1145,11 +1220,22 @@ sub volume_snapshot_rollback {
die "can't rollback snapshot this image format\n" if $volname !~ m/\.(qcow2|qed)$/;
- my $path = $class->filesystem_path($scfg, $volname);
-
- my $cmd = ['/usr/bin/qemu-img', 'snapshot','-a', $snap, $path];
+ if ($scfg->{snapext}) {
+ #simply delete the current snapshot and recreate it
+ eval { free_snap_image($class, $storeid, $scfg, $volname, 'current') };
+ if ($@) {
+ die "can't delete old volume $volname: $@\n";
+ }
- run_command($cmd);
+ eval { alloc_backed_image($class, $storeid, $scfg, $volname, $snap) };
+ if ($@) {
+ die "can't allocate new volume $volname: $@\n";
+ }
+ } else {
+ my $path = $class->filesystem_path($scfg, $volname);
+ my $cmd = ['/usr/bin/qemu-img', 'snapshot','-a', $snap, $path];
+ run_command($cmd);
+ }
return undef;
}
@@ -1159,15 +1245,71 @@ sub volume_snapshot_delete {
die "can't delete snapshot for this image format\n" if $volname !~ m/\.(qcow2|qed)$/;
- return 1 if $running;
+ my $cmd = "";
- my $path = $class->filesystem_path($scfg, $volname);
+ if ($scfg->{snapext}) {
- $class->deactivate_volume($storeid, $scfg, $volname, $snap, {});
+ #qemu has already live commit|stream the snapshot, therefore we only have to drop the image itself
+ if ($running) {
+ eval { free_snap_image($class, $storeid, $scfg, $volname, $snap) };
+ if ($@) {
+ die "can't delete snapshot $snap of volume $volname: $@\n";
+ }
+ return;
+ }
+
+ my $snapshots = $class->volume_snapshot_info($scfg, $storeid, $volname);
+ my $snappath = $snapshots->{$snap}->{file};
+ my $snap_volname = $snapshots->{$snap}->{volname};
+ die "volume $snappath is missing" if !-e $snappath;
+
+ my $parentsnap = $snapshots->{$snap}->{parent};
+ my $childsnap = $snapshots->{$snap}->{child};
+ my $childpath = $snapshots->{$childsnap}->{file};
+
+ #if first snapshot,as it should be bigger, we merge child, and rename the snapshot to child
+ if(!$parentsnap) {
+ print "$volname: deleting snapshot '$snap' by commiting snapshot '$childsnap'\n";
+ print "running 'qemu-img commit $childpath'\n";
+ $cmd = ['/usr/bin/qemu-img', 'commit', $childpath];
+ eval { run_command($cmd) };
+ if ($@) {
+ warn "The state of $snap is now invalid. Don't try to clone or rollback it. You can only try to delete it again later\n";
+ die "error commiting $childsnap to $snap; $@\n";
+ }
+
+ print"rename $snappath to $childpath\n";
+ rename($snappath, $childpath) ||
+ die "rename '$snappath' to '$childpath' failed - $!\n";
+
+ } else {
+ #we rebase the child image on the parent as new backing image
+ my $parentpath = $snapshots->{$parentsnap}->{file};
+ print "$volname: deleting snapshot '$snap' by rebasing '$childsnap' on top of '$parentsnap'\n";
+ print "running 'qemu-img rebase -b $parentpath -F qcow -f qcow2 $childpath'\n";
+ $cmd = ['/usr/bin/qemu-img', 'rebase', '-b', $parentpath, '-F', 'qcow2', '-f', 'qcow2', $childpath];
+ eval { run_command($cmd) };
+ if ($@) {
+ #in case of abort, the state of the snap is still clean, just a little bit bigger
+ die "error rebase $childsnap from $parentsnap; $@\n";
+ }
+ #delete the old snapshot file (not part of the backing chain anymore)
+ eval { free_snap_image($class, $storeid, $scfg, $volname, $snap) };
+ if ($@) {
+ die "error delete old snapshot volume $snap_volname: $@\n";
+ }
+ }
+
+ } else {
- my $cmd = ['/usr/bin/qemu-img', 'snapshot','-d', $snap, $path];
+ return 1 if $running;
- run_command($cmd);
+ my $path = $class->filesystem_path($scfg, $volname);
+ $class->deactivate_volume($storeid, $scfg, $volname, $snap, {});
+
+ $cmd = ['/usr/bin/qemu-img', 'snapshot','-d', $snap, $path];
+ run_command($cmd);
+ }
return undef;
}
@@ -1441,7 +1583,52 @@ sub status {
sub volume_snapshot_info {
my ($class, $scfg, $storeid, $volname) = @_;
- die "volume_snapshot_info is not implemented for $class";
+ my $path = $class->filesystem_path($scfg, $volname);
+ my ($vtype, $name, $vmid, $basename, $basevmid, $isBase, $format) = $class->parse_volname($volname);
+
+ my $json = PVE::Storage::Common::qemu_img_info($path, undef, 10, 1);
+ die "failed to query file information with qemu-img\n" if !$json;
+ my $json_decode = eval { decode_json($json) };
+ if ($@) {
+ die "Can't decode qemu snapshot list. Invalid JSON: $@\n";
+ }
+ my $info = {};
+ my $order = 0;
+ if (ref($json_decode) eq 'HASH') {
+ #internal snapshots is a hashref
+ my $snapshots = $json_decode->{snapshots};
+ for my $snap (@$snapshots) {
+ my $snapname = $snap->{name};
+ $info->{$snapname}->{order} = $snap->{id};
+ $info->{$snapname}->{timestamp} = $snap->{'date-sec'};
+
+ }
+ } elsif (ref($json_decode) eq 'ARRAY') {
+ #no snapshot or external snapshots is an arrayref
+ my $snapshots = $json_decode;
+ for my $snap (@$snapshots) {
+ my $snapfile = $snap->{filename};
+ my $snapname = parse_snapname($snapfile);
+ $snapname = 'current' if !$snapname;
+ my $snapvolname = $class->get_snap_volname($volname, $snapname);
+
+ $info->{$snapname}->{order} = $order;
+ $info->{$snapname}->{file}= $snapfile;
+ $info->{$snapname}->{volname} = "$snapvolname";
+ $info->{$snapname}->{volid} = "$storeid:$snapvolname";
+ $info->{$snapname}->{ext} = 1;
+
+ my $parentfile = $snap->{'backing-filename'};
+ if ($parentfile) {
+ my $parentname = parse_snapname($parentfile);
+ $info->{$snapname}->{parent} = $parentname;
+ $info->{$parentname}->{child} = $snapname;
+ }
+ $order++;
+ }
+ }
+
+ return $info;
}
sub activate_storage {
@@ -1896,7 +2083,7 @@ sub qemu_blockdev_options {
# the snapshot alone.
my $format = ($class->parse_volname($volname))[6];
die "cannot attach only the snapshot of a '$format' image\n"
- if $options->{'snapshot-name'} && ($format eq 'qcow2' || $format eq 'qed');
+ if $options->{'snapshot-name'} && !$scfg->{snapext} && ($format eq 'qcow2' || $format eq 'qed');
# The 'file' driver only works for regular files. The check below is taken from
# block/file-posix.c:hdev_probe_device() in QEMU. Do not bother with detecting 'host_cdrom'
@@ -1935,4 +2122,30 @@ sub config_aware_base_mkdir {
}
}
+sub get_snap_name {
+ my ($class, $volname, $snapname) = @_;
+
+ my ($vtype, $name, $vmid, $basename, $basevmid, $isBase, $format) = $class->parse_volname($volname);
+ $name = !$snapname || $snapname eq 'current' ? $name : "snap-$snapname-$name";
+ return $name;
+}
+
+sub get_snap_volname {
+ my ($class, $volname, $snapname) = @_;
+
+ my $vmid = ($class->parse_volname($volname))[2];
+ my $name = $class->get_snap_name($volname, $snapname);
+ return "$vmid/$name";
+}
+
+sub parse_snapname {
+ my ($name) = @_;
+
+ my $basename = basename($name);
+ if ($basename =~ m/^snap-(.*)-vm(.*)$/) {
+ return $1;
+ }
+ return undef;
+}
+
1;
--
2.39.5
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* [pve-devel] [PATCH qemu-server 08/13] blockdev: add support for nbd_export: block-export-add
[not found] <20250603075558.627850-1-alexandre.derumier@groupe-cyllene.com>
` (14 preceding siblings ...)
2025-06-03 7:55 ` [pve-devel] [PATCH pve-storage 7/9] qcow2: add external snapshot support Alexandre Derumier via pve-devel
@ 2025-06-03 7:55 ` Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH pve-storage 8/9] lvmplugin: add qcow2 snapshot Alexandre Derumier via pve-devel
` (6 subsequent siblings)
22 siblings, 0 replies; 39+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-06-03 7:55 UTC (permalink / raw)
To: pve-devel; +Cc: Alexandre Derumier
[-- Attachment #1: Type: message/rfc822, Size: 4150 bytes --]
From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH qemu-server 08/13] blockdev: add support for nbd_export: block-export-add
Date: Tue, 3 Jun 2025 09:55:51 +0200
Message-ID: <20250603075558.627850-17-alexandre.derumier@groupe-cyllene.com>
simply use the "drive-$id" top node
Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
PVE/QemuServer.pm | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 04e71fb6..8e48f52b 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -6010,20 +6010,27 @@ sub vm_start_nolock {
$migrate_storage_uri = "nbd:${localip}:${storage_migrate_port}";
}
- my $block_info = mon_cmd($vmid, "query-block");
- $block_info = { map { $_->{device} => $_ } $block_info->@* };
+ my $block_info = {};
+ my $use_blockdev = undef;
+
+ if (PVE::QemuServer::Machine::is_machine_version_at_least($forcemachine, 10, 0)) {
+ $use_blockdev = 1;
+ } else {
+ my $block_info = mon_cmd($vmid, "query-block");
+ $block_info = { map { $_->{device} => $_ } $block_info->@* };
+ }
foreach my $opt (sort keys %$nbd) {
my $drivestr = $nbd->{$opt}->{drivestr};
my $volid = $nbd->{$opt}->{volid};
- my $block_node = $block_info->{"drive-$opt"}->{inserted}->{'node-name'};
+ my $nodename = $use_blockdev ? "drive-$opt" : $block_info->{"drive-$opt"}->{inserted}->{'node-name'};
mon_cmd(
$vmid,
"block-export-add",
id => "drive-$opt",
- 'node-name' => $block_node,
+ 'node-name' => $nodename,
writable => JSON::true,
type => "nbd",
name => "drive-$opt", # NBD export name
--
2.39.5
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* [pve-devel] [PATCH pve-storage 8/9] lvmplugin: add qcow2 snapshot
[not found] <20250603075558.627850-1-alexandre.derumier@groupe-cyllene.com>
` (15 preceding siblings ...)
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 08/13] blockdev: add support for nbd_export: block-export-add Alexandre Derumier via pve-devel
@ 2025-06-03 7:55 ` Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 09/13] blockdev: add blockdev_mirror Alexandre Derumier via pve-devel
` (5 subsequent siblings)
22 siblings, 0 replies; 39+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-06-03 7:55 UTC (permalink / raw)
To: pve-devel; +Cc: Alexandre Derumier
[-- Attachment #1: Type: message/rfc822, Size: 24170 bytes --]
From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH pve-storage 8/9] lvmplugin: add qcow2 snapshot
Date: Tue, 3 Jun 2025 09:55:52 +0200
Message-ID: <20250603075558.627850-18-alexandre.derumier@groupe-cyllene.com>
we format lvm logical volume with qcow2 to handle snapshot chain.
like for qcow2 file, when a snapshot is taken, the current lvm volume
is renamed to snap volname, and a new current lvm volume is created
with the snap volname as backing file
Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
src/PVE/Storage/LVMPlugin.pm | 450 ++++++++++++++++++++++++++++++-----
1 file changed, 385 insertions(+), 65 deletions(-)
diff --git a/src/PVE/Storage/LVMPlugin.pm b/src/PVE/Storage/LVMPlugin.pm
index 25268a4..af50b91 100644
--- a/src/PVE/Storage/LVMPlugin.pm
+++ b/src/PVE/Storage/LVMPlugin.pm
@@ -11,6 +11,8 @@ use PVE::JSONSchema qw(get_standard_option);
use PVE::Storage::Common;
+use JSON;
+
use base qw(PVE::Storage::Plugin);
# lvm helper functions
@@ -209,6 +211,59 @@ sub lvm_list_volumes {
return $lvs;
}
+sub free_lvm_volumes {
+ my ($class, $scfg, $storeid, $volnames) = @_;
+
+ my $vg = $scfg->{vgname};
+
+ # we need to zero out LVM data for security reasons
+ # and to allow thin provisioning
+ my $zero_out_worker = sub {
+ # wipe throughput up to 10MB/s by default; may be overwritten with saferemove_throughput
+ my $throughput = '-10485760';
+ if ($scfg->{saferemove_throughput}) {
+ $throughput = $scfg->{saferemove_throughput};
+ }
+ for my $name (@$volnames) {
+ print "zero-out data on image $name (/dev/$vg/del-$name)\n";
+
+ my $cmd = [
+ '/usr/bin/cstream',
+ '-i', '/dev/zero',
+ '-o', "/dev/$vg/del-$name",
+ '-T', '10',
+ '-v', '1',
+ '-b', '1048576',
+ '-t', "$throughput"
+ ];
+ eval { run_command($cmd, errmsg => "zero out finished (note: 'No space left on device' is ok here)"); };
+ warn $@ if $@;
+
+ $class->cluster_lock_storage($storeid, $scfg->{shared}, undef, sub {
+ my $cmd = ['/sbin/lvremove', '-f', "$vg/del-$name"];
+ run_command($cmd, errmsg => "lvremove '$vg/del-$name' error");
+ });
+ print "successfully removed volume $name ($vg/del-$name)\n";
+ }
+ };
+
+ if ($scfg->{saferemove}) {
+ for my $name (@$volnames) {
+ # avoid long running task, so we only rename here
+ my $cmd = ['/sbin/lvrename', $vg, $name, "del-$name"];
+ run_command($cmd, errmsg => "lvrename '$vg/$name' error");
+ }
+ return $zero_out_worker;
+ } else {
+ for my $name (@$volnames) {
+ my $tmpvg = $scfg->{vgname};
+ my $cmd = ['/sbin/lvremove', '-f', "$tmpvg/$name"];
+ run_command($cmd, errmsg => "lvremove '$tmpvg/$name' error");
+ }
+ }
+}
+
+
# Configuration
sub type {
@@ -218,6 +273,7 @@ sub type {
sub plugindata {
return {
content => [ {images => 1, rootdir => 1}, { images => 1 }],
+ format => [ { raw => 1, qcow2 => 1 } , 'raw' ],
'sensitive-properties' => {},
};
}
@@ -294,7 +350,10 @@ sub parse_volname {
PVE::Storage::Plugin::parse_lvm_name($volname);
if ($volname =~ m/^(vm-(\d+)-\S+)$/) {
- return ('images', $1, $2, undef, undef, undef, 'raw');
+ my $name = $1;
+ my $vmid = $2;
+ my $format = $volname =~ m/\.qcow2$/ ? 'qcow2' : 'raw';
+ return ('images', $name, $vmid, undef, undef, undef, $format);
}
die "unable to parse lvm volume name '$volname'\n";
@@ -303,11 +362,13 @@ sub parse_volname {
sub filesystem_path {
my ($class, $scfg, $volname, $snapname) = @_;
- die "lvm snapshot is not implemented"if defined($snapname);
+ my ($vtype, $name, $vmid, $basename, $basevmid, $isBase, $format) =
+ $class->parse_volname($volname);
- my ($vtype, $name, $vmid) = $class->parse_volname($volname);
+ die "snapshot is working with qcow2 format only" if defined($snapname) && $format ne 'qcow2';
my $vg = $scfg->{vgname};
+ $name = $class->get_snap_name($volname, $snapname) if $snapname;
my $path = "/dev/$vg/$name";
@@ -335,7 +396,9 @@ sub find_free_diskname {
my $disk_list = [ keys %{$lvs->{$vg}} ];
- return PVE::Storage::Plugin::get_next_vm_diskname($disk_list, $storeid, $vmid, undef, $scfg);
+ $add_fmt_suffix = $fmt eq 'qcow2' ? 1 : undef;
+
+ return PVE::Storage::Plugin::get_next_vm_diskname($disk_list, $storeid, $vmid, $fmt, $scfg, $add_fmt_suffix);
}
sub lvcreate {
@@ -363,13 +426,47 @@ sub lvrename {
);
}
-sub alloc_image {
- my ($class, $storeid, $scfg, $vmid, $fmt, $name, $size) = @_;
+my sub lvm_qcow2_format {
+ my ($class, $storeid, $scfg, $name, $fmt, $backing_snap, $size) = @_;
- die "unsupported format '$fmt'" if $fmt ne 'raw';
+ die "Can't format the volume, the format is not qcow2" if $fmt ne 'qcow2';
+
+ $class->activate_volume($storeid, $scfg, $name);
+ my $path = $class->path($scfg, $name, $storeid);
+
+ if ($backing_snap) {
+ my $backing_path = $class->path($scfg, $name, $storeid, $backing_snap);
+ PVE::Storage::Common::qemu_img_create_qcow2_backed($scfg, $path, $backing_path, $fmt);
+ } else {
+ PVE::Storage::Common::qemu_img_create($scfg, $fmt, $size, $path);
+ }
+}
+
+my sub calculate_lvm_size {
+ my ($size, $fmt, $backing_snap) = @_;
+ #input size = qcow2 image size in kb
+
+ return $size if $fmt ne 'qcow2';
+
+ my $json = PVE::Storage::Common::qemu_img_measure($size, $fmt, 5, $backing_snap);
+ die "failed to query file information with qemu-img measure\n" if !$json;
+ my $info = eval { decode_json($json) };
+ if ($@) {
+ die "Invalid JSON: $@\n";
+ }
+
+ die "Missing fully-allocated value from json" if !$info->{'fully-allocated'};
+
+ return $info->{'fully-allocated'} / 1024;
+}
+
+my sub alloc_lvm_image {
+ my ($class, $storeid, $scfg, $vmid, $fmt, $name, $size, $backing_snap) = @_;
+
+ die "unsupported format '$fmt'" if $fmt !~ m/(raw|qcow2)/;
die "illegal name '$name' - should be 'vm-$vmid-*'\n"
- if $name && $name !~ m/^vm-$vmid-/;
+ if $name !~ m/^vm-$vmid-/;
my $vgs = lvm_vgs();
@@ -378,70 +475,94 @@ sub alloc_image {
die "no such volume group '$vg'\n" if !defined ($vgs->{$vg});
my $free = int($vgs->{$vg}->{free});
+ my $lvmsize = calculate_lvm_size($size, $fmt, $backing_snap);
die "not enough free space ($free < $size)\n" if $free < $size;
- $name = $class->find_free_diskname($storeid, $scfg, $vmid)
+ my $tags = ["pve-vm-$vmid"];
+ #tags all snapshots volumes with the main volume tag for easier activation of the whole group
+ push @$tags, "\@pve-$name" if $fmt eq 'qcow2';
+ lvcreate($vg, $name, $lvmsize, $tags);
+
+ return if $fmt ne 'qcow2';
+
+ #format the lvm volume with qcow2 format
+ eval { lvm_qcow2_format($class, $storeid, $scfg, $name, $fmt, $backing_snap, $size) };
+ if ($@) {
+ my $err = $@;
+ #no need to safe cleanup as the volume is still empty
+ eval {
+ my $cmd = ['/sbin/lvremove', '-f', "$vg/$name"];
+ run_command($cmd, errmsg => "lvremove '$vg/$name' error");
+ };
+ die $err;
+ }
+}
+
+sub alloc_image {
+ my ($class, $storeid, $scfg, $vmid, $fmt, $name, $size) = @_;
+
+ $name = $class->find_free_diskname($storeid, $scfg, $vmid, $fmt)
if !$name;
- lvcreate($vg, $name, $size, ["pve-vm-$vmid"]);
+ alloc_lvm_image($class, $storeid, $scfg, $vmid, $fmt, $name, $size);
return $name;
}
-sub free_image {
- my ($class, $storeid, $scfg, $volname, $isBase) = @_;
+sub alloc_snap_image {
+ my ($class, $storeid, $scfg, $volname, $backing_snap) = @_;
- my $vg = $scfg->{vgname};
+ my ($vmid, $format) = ($class->parse_volname($volname))[2,6];
+ my $path = $class->path($scfg, $volname, $storeid, $backing_snap);
- # we need to zero out LVM data for security reasons
- # and to allow thin provisioning
+ #we need to use same size than the backing image qcow2 virtual-size
+ my $size = PVE::Storage::Plugin::file_size_info($path, 5, $format);
+ $size = $size / 1024; #we use kb in lvcreate
- my $zero_out_worker = sub {
- print "zero-out data on image $volname (/dev/$vg/del-$volname)\n";
+ alloc_lvm_image($class, $storeid, $scfg, $vmid, $format, $volname, $size, $backing_snap);
+}
- # wipe throughput up to 10MB/s by default; may be overwritten with saferemove_throughput
- my $throughput = '-10485760';
- if ($scfg->{saferemove_throughput}) {
- $throughput = $scfg->{saferemove_throughput};
- }
+sub free_snap_image {
+ my ($class, $storeid, $scfg, $volname, $snap) = @_;
- my $cmd = [
- '/usr/bin/cstream',
- '-i', '/dev/zero',
- '-o', "/dev/$vg/del-$volname",
- '-T', '10',
- '-v', '1',
- '-b', '1048576',
- '-t', "$throughput"
- ];
- eval { run_command($cmd, errmsg => "zero out finished (note: 'No space left on device' is ok here)"); };
- warn $@ if $@;
+ #activate only the snapshot volume
+ my $path = $class->path($scfg, $volname, $storeid, $snap);
+ my $cmd = ['/sbin/lvchange', '-aly', $path];
+ run_command($cmd, errmsg => "can't activate LV '$path' to zero-out its data");
+ $cmd = ['/sbin/lvchange', '--refresh', $path];
+ run_command($cmd, errmsg => "can't refresh LV '$path' to zero-out its data");
- $class->cluster_lock_storage($storeid, $scfg->{shared}, undef, sub {
- my $cmd = ['/sbin/lvremove', '-f', "$vg/del-$volname"];
- run_command($cmd, errmsg => "lvremove '$vg/del-$volname' error");
- });
- print "successfully removed volume $volname ($vg/del-$volname)\n";
- };
+ my $snap_volname = $class->get_snap_volname($volname, $snap);
+ return $class->free_lvm_volumes($scfg, $storeid, [$snap_volname]);
+}
- my $cmd = ['/sbin/lvchange', '-aly', "$vg/$volname"];
- run_command($cmd, errmsg => "can't activate LV '$vg/$volname' to zero-out its data");
- $cmd = ['/sbin/lvchange', '--refresh', "$vg/$volname"];
- run_command($cmd, errmsg => "can't refresh LV '$vg/$volname' to zero-out its data");
+sub free_image {
+ my ($class, $storeid, $scfg, $volname, $isBase, $format) = @_;
- if ($scfg->{saferemove}) {
- # avoid long running task, so we only rename here
- $cmd = ['/sbin/lvrename', $vg, $volname, "del-$volname"];
- run_command($cmd, errmsg => "lvrename '$vg/$volname' error");
- return $zero_out_worker;
- } else {
- my $tmpvg = $scfg->{vgname};
- $cmd = ['/sbin/lvremove', '-f', "$tmpvg/$volname"];
- run_command($cmd, errmsg => "lvremove '$tmpvg/$volname' error");
+ my $name = ($class->parse_volname($volname))[1];
+
+ #activate volumes && snapshot volumes
+ my $path = $class->path($scfg, $volname, $storeid);
+ $path = "\@pve-$name" if $format && $format eq 'qcow2';
+ my $cmd = ['/sbin/lvchange', '-aly', $path];
+ run_command($cmd, errmsg => "can't activate LV '$path' to zero-out its data");
+ $cmd = ['/sbin/lvchange', '--refresh', $path];
+ run_command($cmd, errmsg => "can't refresh LV '$path' to zero-out its data");
+
+ my $volnames = [];
+ my $snapshots = $class->volume_snapshot_info($scfg, $storeid, $volname);
+ for my $snapid (sort { $snapshots->{$b}->{order} <=> $snapshots->{$a}->{order} } keys %$snapshots) {
+ my $snap = $snapshots->{$snapid};
+ next if $snapid eq 'current';
+ next if !$snap->{volid};
+ next if !$snap->{ext};
+ my ($snap_storeid, $snap_volname) = PVE::Storage::parse_volume_id($snap->{volid});
+ push @$volnames, $snap_volname;
}
+ push @$volnames, $volname;
- return undef;
+ return $class->free_lvm_volumes($scfg, $storeid, $volnames);
}
my $check_tags = sub {
@@ -539,6 +660,12 @@ sub activate_volume {
my $lvm_activate_mode = 'ey';
+ #activate volume && all snapshots volumes by tag
+ my ($vtype, $name, $vmid, $basename, $basevmid, $isBase, $format) =
+ $class->parse_volname($volname);
+
+ $path = "\@pve-$name" if $format eq 'qcow2';
+
my $cmd = ['/sbin/lvchange', "-a$lvm_activate_mode", $path];
run_command($cmd, errmsg => "can't activate LV '$path'");
$cmd = ['/sbin/lvchange', '--refresh', $path];
@@ -551,6 +678,10 @@ sub deactivate_volume {
my $path = $class->path($scfg, $volname, $storeid, $snapname);
return if ! -b $path;
+ my ($vtype, $name, $vmid, $basename, $basevmid, $isBase, $format) =
+ $class->parse_volname($volname);
+ $path = "\@pve-$name" if $format eq 'qcow2';
+
my $cmd = ['/sbin/lvchange', '-aln', $path];
run_command($cmd, errmsg => "can't deactivate LV '$path'");
}
@@ -558,21 +689,31 @@ sub deactivate_volume {
sub volume_resize {
my ($class, $scfg, $storeid, $volname, $size, $running) = @_;
- $size = ($size/1024/1024) . "M";
+ my ($vtype, $name, $vmid, $basename, $basevmid, $isBase, $format) =
+ $class->parse_volname($volname);
+
+ my $lvmsize = calculate_lvm_size($size/1024, $format);
+ $lvmsize = "${lvmsize}k";
my $path = $class->path($scfg, $volname);
- my $cmd = ['/sbin/lvextend', '-L', $size, $path];
+ my $cmd = ['/sbin/lvextend', '-L', $lvmsize, $path];
$class->cluster_lock_storage($storeid, $scfg->{shared}, undef, sub {
run_command($cmd, errmsg => "error resizing volume '$path'");
});
+ if(!$running && $format eq 'qcow2') {
+ my $prealloc_opt = PVE::Storage::Plugin::preallocation_cmd_option($scfg, $format);
+ my $cmd = ['/usr/bin/qemu-img', 'resize', "--$prealloc_opt", '-f', $format, $path , $size];
+ run_command($cmd, timeout => 10);
+ }
+
return 1;
}
sub volume_size_info {
- my ($class, $scfg, $storeid, $volname, $timeout) = @_;
- my $path = $class->filesystem_path($scfg, $volname);
+ my ($class, $scfg, $storeid, $volname, $timeout, $snap) = @_;
+ my $path = $class->filesystem_path($scfg, $volname, $snap);
my $cmd = ['/sbin/lvs', '--separator', ':', '--noheadings', '--units', 'b',
'--unbuffered', '--nosuffix', '--options', 'lv_size', $path];
@@ -588,30 +729,181 @@ sub volume_size_info {
sub volume_snapshot {
my ($class, $scfg, $storeid, $volname, $snap, $running) = @_;
- die "lvm snapshot is not implemented";
+ my ($vmid, $format) = ($class->parse_volname($volname))[2,6];
+
+ die "can't snapshot this image format\n" if $format ne 'qcow2';
+
+ if ($running) {
+ #rename with blockdev-reopen is done at qemu level when running
+ $class->alloc_snap_image($storeid, $scfg, $volname, $snap);
+ if ($@) {
+ die "can't allocate new volume $volname: $@\n";
+ }
+ return;
+ }
+
+ #rename current volume to snap volume
+ eval { $class->rename_volume($scfg, $storeid, $volname, $vmid, undef, 'current', $snap) };
+ die "error rename $volname to $snap\n" if $@;
+
+ eval { $class->alloc_snap_image($storeid, $scfg, $volname, $snap) };
+ if ($@) {
+ my $err = $@;
+ eval { $class->rename_volume($scfg, $storeid, $volname, $vmid, undef, $snap, 'current') };
+ die $err;
+ }
+}
+
+sub volume_rollback_is_possible {
+ my ($class, $scfg, $storeid, $volname, $snap, $blockers) = @_;
+
+ my $snap_path = $class->path($scfg, $volname, $storeid, $snap);
+
+ $class->activate_volume($storeid, $scfg, $volname, undef, {});
+ my $snapshots = $class->volume_snapshot_info($scfg, $storeid, $volname);
+ my $parent_snap = $snapshots->{current}->{parent};
+
+ return 1 if $parent_snap eq $snap;
+ die "can't rollback, '$snap' is not most recent snapshot on '$volname'\n";
+
+ return 1;
}
sub volume_snapshot_rollback {
my ($class, $scfg, $storeid, $volname, $snap) = @_;
- die "lvm snapshot rollback is not implemented";
+ my $format = ($class->parse_volname($volname))[6];
+
+ die "can't rollback snapshot for this image format\n" if $format ne 'qcow2';
+
+ $class->activate_volume($storeid, $scfg, $volname, undef, {});
+
+ # we can simply reformat the current lvm volume to avoid
+ # a long safe remove.(not needed here, as the allocated space
+ # is still the same owner)
+ eval { lvm_qcow2_format($class, $storeid, $scfg, $volname, $format, $snap) };
+ if($@) {
+ die "can't rollback. Error reformating current $volname\n";
+ }
+ return undef;
}
sub volume_snapshot_delete {
- my ($class, $scfg, $storeid, $volname, $snap) = @_;
+ my ($class, $scfg, $storeid, $volname, $snap, $running) = @_;
- die "lvm snapshot delete is not implemented";
+ my ($vtype, $name, $vmid, $basename, $basevmid, $isBase, $format) = $class->parse_volname($volname);
+
+ die "can't delete snapshot for this image format\n" if $format ne 'qcow2';
+
+ if ($running) {
+ my $cleanup_worker = eval { $class->free_snap_image($storeid, $scfg, $volname, $snap); };
+ die "error deleting snapshot $snap $@\n" if $@;
+
+ if ($cleanup_worker) {
+ my $rpcenv = PVE::RPCEnvironment::get();
+ my $authuser = $rpcenv->get_user();
+ $rpcenv->fork_worker('imgdel', undef, $authuser, $cleanup_worker);
+ }
+ return;
+ }
+
+ my $cmd = "";
+ my $path = $class->filesystem_path($scfg, $volname);
+
+ $class->activate_volume($storeid, $scfg, $volname);
+
+ my $snapshots = $class->volume_snapshot_info($scfg, $storeid, $volname);
+ my $snappath = $snapshots->{$snap}->{file};
+ my $snapvolname = $snapshots->{$snap}->{volname};
+ die "volume $snappath is missing" if !-e $snappath;
+
+ my $parentsnap = $snapshots->{$snap}->{parent};
+
+ my $childsnap = $snapshots->{$snap}->{child};
+ my $childpath = $snapshots->{$childsnap}->{file};
+ my $childvolname = $snapshots->{$childsnap}->{volname};
+
+ my $cleanup_worker = undef;
+ my $err = undef;
+ #if first snapshot,as it should be bigger, we merge child, and rename the snapshot to child
+ if(!$parentsnap) {
+ print "$volname: deleting snapshot '$snap' by commiting snapshot '$childsnap'\n";
+ print "running 'qemu-img commit $childpath'\n";
+ #can't use -d here, as it's an lvm volume
+ $cmd = ['/usr/bin/qemu-img', 'commit', $childpath];
+ eval { run_command($cmd) };
+ if ($@) {
+ warn "The state of $snap is now invalid. Don't try to clone or rollback it. You can only try to delete it again later\n";
+ die "error commiting $childsnap to $snap; $@\n";
+ }
+ print"delete $childvolname\n";
+ $cleanup_worker = eval { $class->free_snap_image($storeid, $scfg, $volname, $childsnap) };
+ if ($@) {
+ die "error delete old snapshot volume $childvolname: $@\n";
+ }
+
+ print"rename $snapvolname to $childvolname\n";
+ my $vg = $scfg->{vgname};
+ eval { lvrename($vg, $snapvolname, $childvolname) };
+ if ($@) {
+ warn $@;
+ $err = "error renaming snapshot: $@\n";
+ }
+
+ } else {
+ #we rebase the child image on the parent as new backing image
+ my $parentpath = $snapshots->{$parentsnap}->{file};
+ print "$volname: deleting snapshot '$snap' by rebasing '$childsnap' on top of '$parentsnap'\n";
+ print "running 'qemu-img rebase -b $parentpath -F qcow -f qcow2 $childpath'\n";
+ $cmd = ['/usr/bin/qemu-img', 'rebase', '-b', $parentpath, '-F', 'qcow2', '-f', 'qcow2', $childpath];
+ eval { run_command($cmd) };
+ if ($@) {
+ #in case of abort, the state of the snap is still clean, just a little bit bigger
+ die "error rebase $childsnap from $parentsnap; $@\n";
+ }
+ #delete the snapshot
+ eval { $cleanup_worker = $class->free_snap_image($storeid, $scfg, $volname, $snap); };
+ if ($@) {
+ die "error deleting old snapshot volume $snapvolname\n";
+ }
+ }
+
+ if ($cleanup_worker) {
+ my $rpcenv = PVE::RPCEnvironment::get();
+ my $authuser = $rpcenv->get_user();
+ $rpcenv->fork_worker('imgdel', undef, $authuser, $cleanup_worker);
+ }
+
+ die $err if $err;
}
sub volume_has_feature {
my ($class, $scfg, $feature, $storeid, $volname, $snapname, $running) = @_;
my $features = {
- copy => { base => 1, current => 1},
- rename => {current => 1},
+ copy => {
+ base => { qcow2 => 1, raw => 1 },
+ current => { qcow2 => 1, raw => 1},
+ snap => { qcow2 => 1 },
+ },
+ 'rename' => {
+ current => { qcow2 => 1, raw => 1},
+ },
+ snapshot => {
+ current => { qcow2 => 1 },
+ snap => { qcow2 => 1 },
+ },
+# fixme: add later ? (we need to handle basepath, volume activation,...)
+# template => {
+# current => { raw => 1, qcow2 => 1},
+# },
+# clone => {
+# base => { qcow2 => 1 },
+# },
};
- my ($vtype, $name, $vmid, $basename, $basevmid, $isBase) =
+
+ my ($vtype, $name, $vmid, $basename, $basevmid, $isBase, $format) =
$class->parse_volname($volname);
my $key = undef;
@@ -620,7 +912,7 @@ sub volume_has_feature {
}else{
$key = $isBase ? 'base' : 'current';
}
- return 1 if $features->{$feature}->{$key};
+ return 1 if defined($features->{$feature}->{$key}->{$format});
return undef;
}
@@ -745,4 +1037,32 @@ sub rename_volume {
return "${storeid}:${target_volname}";
}
+sub qemu_blockdev_options {
+ my ($class, $scfg, $storeid, $volname, $options) = @_;
+
+ my ($path) = $class->filesystem_path($scfg, $volname, $options->{'snapshot-name'});
+
+ my $format = ($class->parse_volname($volname))[6];
+ die "can attach only the snapshot of a qcow2 image\n"
+ if $options->{'snapshot-name'} && $format ne 'qcow2';
+
+ my $blockdev = { driver => 'host_device', filename => $path };
+
+ return $blockdev;
+}
+
+sub get_snap_name {
+ my ($class, $volname, $snapname) = @_;
+
+ my ($vtype, $name, $vmid, $basename, $basevmid, $isBase, $format) = $class->parse_volname($volname);
+ $name = !$snapname || $snapname eq 'current' ? $name : "snap-$snapname-$name";
+ return $name;
+}
+
+sub get_snap_volname {
+ my ($class, $volname, $snapname) = @_;
+
+ return $class->get_snap_name($volname, $snapname);
+}
+
1;
--
2.39.5
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* [pve-devel] [PATCH qemu-server 09/13] blockdev: add blockdev_mirror
[not found] <20250603075558.627850-1-alexandre.derumier@groupe-cyllene.com>
` (16 preceding siblings ...)
2025-06-03 7:55 ` [pve-devel] [PATCH pve-storage 8/9] lvmplugin: add qcow2 snapshot Alexandre Derumier via pve-devel
@ 2025-06-03 7:55 ` Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH pve-storage 9/9] storage: add volume_support_qemu_snapshot Alexandre Derumier via pve-devel
` (4 subsequent siblings)
22 siblings, 0 replies; 39+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-06-03 7:55 UTC (permalink / raw)
To: pve-devel; +Cc: Alexandre Derumier
[-- Attachment #1: Type: message/rfc822, Size: 11188 bytes --]
From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH qemu-server 09/13] blockdev: add blockdev_mirror
Date: Tue, 3 Jun 2025 09:55:53 +0200
Message-ID: <20250603075558.627850-19-alexandre.derumier@groupe-cyllene.com>
FIXME:
port qemu bitmap drive-mirror patch to blockdev-mirror
Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
PVE/QemuMigrate.pm | 2 +-
PVE/QemuServer.pm | 115 ++++++++++++++++++++++----
test/MigrationTest/QemuMigrateMock.pm | 10 ++-
3 files changed, 104 insertions(+), 23 deletions(-)
diff --git a/PVE/QemuMigrate.pm b/PVE/QemuMigrate.pm
index 5a54f173..ca9f59fb 100644
--- a/PVE/QemuMigrate.pm
+++ b/PVE/QemuMigrate.pm
@@ -1149,7 +1149,7 @@ sub phase2 {
my $bitmap = $target->{bitmap};
$self->log('info', "$drive: start migration to $nbd_uri");
- PVE::QemuServer::qemu_drive_mirror($vmid, $drive, $nbd_uri, $vmid, undef, $self->{storage_migration_jobs}, 'skip', undef, $bwlimit, $bitmap);
+ PVE::QemuServer::qemu_drive_mirror($vmid, $source_drive, $nbd_uri, $vmid, undef, $self->{storage_migration_jobs}, 'skip', undef, $bwlimit, $bitmap);
}
if (PVE::QemuServer::QMPHelpers::runs_at_least_qemu_version($vmid, 8, 2)) {
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 8e48f52b..f68c5bf2 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -8153,60 +8153,139 @@ sub qemu_img_convert {
die "copy failed: $err" if $err;
}
+
sub qemu_drive_mirror {
my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized, $jobs, $completion, $qga, $bwlimit, $src_bitmap) = @_;
$jobs = {} if !$jobs;
+ my $machine_type = PVE::QemuServer::Machine::get_current_qemu_machine($vmid);
+ if (PVE::QemuServer::Machine::is_machine_version_at_least($machine_type, 10, 0)) {
+ return qemu_blockdev_mirror($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized, $jobs, $completion, $qga, $bwlimit, $src_bitmap);
+ }
+
my $qemu_target;
my $format;
- $jobs->{"drive-$drive"} = {};
+
+ my $drive_id = PVE::QemuServer::Drive::get_drive_id($drive);
+ my $deviceid = "drive-$drive_id";
+
+ $jobs->{$deviceid} = {};
if ($dst_volid =~ /^nbd:/) {
- $qemu_target = $dst_volid;
- $format = "nbd";
+ $qemu_target = $dst_volid;
+ $format = "nbd";
} else {
- my $storecfg = PVE::Storage::config();
+ my $storecfg = PVE::Storage::config();
+
+ $format = checked_volume_format($storecfg, $dst_volid);
- $format = checked_volume_format($storecfg, $dst_volid);
+ my $dst_path = PVE::Storage::path($storecfg, $dst_volid);
- my $dst_path = PVE::Storage::path($storecfg, $dst_volid);
+ $qemu_target = $is_zero_initialized ? "zeroinit:$dst_path" : $dst_path;
+ }
- $qemu_target = $is_zero_initialized ? "zeroinit:$dst_path" : $dst_path;
+ my $opts = {
+ timeout => 10,
+ device => $deviceid,
+ mode => "existing",
+ sync => "full",
+ target => $qemu_target,
+ 'auto-dismiss' => JSON::false,
+ };
+ $opts->{format} = $format if $format;
+
+ if (defined($src_bitmap)) {
+ $opts->{sync} = 'incremental';
+ $opts->{bitmap} = $src_bitmap;
+ print "drive mirror re-using dirty bitmap '$src_bitmap'\n";
+ }
+
+ if (defined($bwlimit)) {
+ $opts->{speed} = $bwlimit * 1024;
+ print "drive mirror is starting for $deviceid with bandwidth limit: ${bwlimit} KB/s\n";
+ } else {
+ print "drive mirror is starting for $deviceid\n";
+ }
+
+ # if a job already runs for this device we get an error, catch it for cleanup
+ eval { mon_cmd($vmid, "drive-mirror", %$opts); };
+ if (my $err = $@) {
+ eval { PVE::QemuServer::qemu_blockjobs_cancel($vmid, $jobs) };
+ warn "$@\n" if $@;
+ die "mirroring error: $err\n";
}
+ qemu_drive_mirror_monitor ($vmid, $vmiddst, $jobs, $completion, $qga);
+}
+
+sub qemu_blockdev_mirror {
+ my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized, $jobs, $completion, $qga, $bwlimit, $src_bitmap) = @_;
+
+ my $storecfg = PVE::Storage::config();
+
+ # copy original drive config (aio,cache,discard,...)
+ my $dst_drive = dclone($drive);
+ $dst_drive->{file} = $dst_volid;
+ $dst_drive->{zeroinit} = 1 if $is_zero_initialized;
+ #improve: if target storage don't support aio uring,change it to default native
+ #and remove clone_disk_check_io_uring()
+
+ #add new block device
+ my $target_drive_blockdev = generate_drive_blockdev($storecfg, $dst_drive);
+ my $target_blockdev = $target_drive_blockdev->{file}; #can be fmt or only file for nbd
+ PVE::QemuServer::Monitor::mon_cmd($vmid, 'blockdev-add', %$target_blockdev);
+ my $target_nodename = $target_blockdev->{'node-name'};
+
+ # we replace the original src_fmt node in the blockdev graph.
+ # need to be defined, or if not, it'll replace the root throttle-filter
+ my $src_drive_blockdev = generate_drive_blockdev($storecfg, $drive);
+ my $src_fmt_nodename = $src_drive_blockdev->{file}->{'node-name'};
+
+
+ my $drive_id = PVE::QemuServer::Drive::get_drive_id($drive);
+ my $deviceid = "drive-$drive_id";
+
+ $jobs = {} if !$jobs;
+ my $jobid = "mirror-$deviceid";
+ $jobs->{$jobid} = {};
+
my $opts = {
+ 'job-id' => $jobid,
timeout => 10,
- device => "drive-$drive",
- mode => "existing",
+ device => $deviceid,
+ replaces => $src_fmt_nodename,
sync => "full",
- target => $qemu_target,
+ target => $target_nodename,
'auto-dismiss' => JSON::false,
};
- $opts->{format} = $format if $format;
if (defined($src_bitmap)) {
$opts->{sync} = 'incremental';
- $opts->{bitmap} = $src_bitmap;
+ $opts->{bitmap} = $src_bitmap; ##FIXME: port qemu bitmap drive-mirror patch to blockdev-mirror
print "drive mirror re-using dirty bitmap '$src_bitmap'\n";
}
if (defined($bwlimit)) {
$opts->{speed} = $bwlimit * 1024;
- print "drive mirror is starting for drive-$drive with bandwidth limit: ${bwlimit} KB/s\n";
+ print "drive mirror is starting for $deviceid with bandwidth limit: ${bwlimit} KB/s\n";
} else {
- print "drive mirror is starting for drive-$drive\n";
+ print "drive mirror is starting for $deviceid\n";
}
# if a job already runs for this device we get an error, catch it for cleanup
- eval { mon_cmd($vmid, "drive-mirror", %$opts); };
+ eval { mon_cmd($vmid, "blockdev-mirror", %$opts); };
+
if (my $err = $@) {
eval { PVE::QemuServer::qemu_blockjobs_cancel($vmid, $jobs) };
warn "$@\n" if $@;
+ eval { mon_cmd($vmid, 'blockdev-del', 'node-name' => $target_blockdev->{file}->{'node-name'}) };
+ warn "$@\n" if $@;
+ eval { mon_cmd($vmid, 'blockdev-del', 'node-name' => $target_nodename) };
+ warn "$@\n" if $@;
die "mirroring error: $err\n";
}
-
- qemu_drive_mirror_monitor ($vmid, $vmiddst, $jobs, $completion, $qga);
+ qemu_drive_mirror_monitor ($vmid, $vmiddst, $jobs, $completion, $qga, 'mirror');
}
# $completion can be either
@@ -8565,7 +8644,7 @@ sub clone_disk {
my $sparseinit = PVE::Storage::volume_has_feature($storecfg, 'sparseinit', $newvolid);
if ($use_drive_mirror) {
- qemu_drive_mirror($vmid, $src_drivename, $newvolid, $newvmid, $sparseinit, $jobs,
+ qemu_drive_mirror($vmid, $drive, $newvolid, $newvmid, $sparseinit, $jobs,
$completion, $qga, $bwlimit);
} else {
if ($dst_drivename eq 'efidisk0') {
diff --git a/test/MigrationTest/QemuMigrateMock.pm b/test/MigrationTest/QemuMigrateMock.pm
index 11c58c08..d156ff1b 100644
--- a/test/MigrationTest/QemuMigrateMock.pm
+++ b/test/MigrationTest/QemuMigrateMock.pm
@@ -132,14 +132,16 @@ $MigrationTest::Shared::qemu_server_module->mock(
qemu_drive_mirror => sub {
my ($vmid, $drive, $dst_volid, $vmiddst, $is_zero_initialized, $jobs, $completion, $qga, $bwlimit, $src_bitmap) = @_;
+ my $drive_id = "$drive->{interface}$drive->{index}";
+
die "drive_mirror with wrong vmid: '$vmid'\n" if $vmid ne $test_vmid;
- die "qemu_drive_mirror '$drive' error\n"
- if $fail_config->{qemu_drive_mirror} && $fail_config->{qemu_drive_mirror} eq $drive;
+ die "qemu_drive_mirror '$drive_id' error\n"
+ if $fail_config->{qemu_drive_mirror} && $fail_config->{qemu_drive_mirror} eq $drive_id;
my $nbd_info = decode_json(file_get_contents("${RUN_DIR_PATH}/nbd_info"));
die "target does not expect drive mirror for '$drive'\n"
- if !defined($nbd_info->{$drive});
- delete $nbd_info->{$drive};
+ if !defined($nbd_info->{$drive_id});
+ delete $nbd_info->{$drive_id};
file_set_contents("${RUN_DIR_PATH}/nbd_info", to_json($nbd_info));
},
qemu_drive_mirror_monitor => sub {
--
2.39.5
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* [pve-devel] [PATCH pve-storage 9/9] storage: add volume_support_qemu_snapshot
[not found] <20250603075558.627850-1-alexandre.derumier@groupe-cyllene.com>
` (17 preceding siblings ...)
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 09/13] blockdev: add blockdev_mirror Alexandre Derumier via pve-devel
@ 2025-06-03 7:55 ` Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 10/13] blockdev: change aio on target if io_uring is not default Alexandre Derumier via pve-devel
` (3 subsequent siblings)
22 siblings, 0 replies; 39+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-06-03 7:55 UTC (permalink / raw)
To: pve-devel; +Cc: Alexandre Derumier
[-- Attachment #1: Type: message/rfc822, Size: 6443 bytes --]
From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH pve-storage 9/9] storage: add volume_support_qemu_snapshot
Date: Tue, 3 Jun 2025 09:55:54 +0200
Message-ID: <20250603075558.627850-20-alexandre.derumier@groupe-cyllene.com>
Returns if the volume is supporting qemu snapshot:
'internal' : do the snapshot with qemu internal snapshot
'external' : do the snapshot with qemu external snapshot
undef : does not support qemu snapshot
Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
src/PVE/Storage.pm | 15 +++++++++++++++
src/PVE/Storage/DirPlugin.pm | 10 ++++++++++
src/PVE/Storage/LVMPlugin.pm | 7 +++++++
src/PVE/Storage/Plugin.pm | 20 ++++++++++++++++++++
src/PVE/Storage/RBDPlugin.pm | 6 ++++++
5 files changed, 58 insertions(+)
diff --git a/src/PVE/Storage.pm b/src/PVE/Storage.pm
index 2a2005b..413ad0c 100755
--- a/src/PVE/Storage.pm
+++ b/src/PVE/Storage.pm
@@ -2145,6 +2145,21 @@ sub rename_volume {
});
}
+sub volume_support_qemu_snapshot {
+ my ($cfg, $volid) = @_;
+
+ my ($storeid, $volname) = parse_volume_id($volid, 1);
+
+ if ($storeid) {
+ my $scfg = storage_config($cfg, $storeid);
+
+ my $plugin = PVE::Storage::Plugin->lookup($scfg->{type});
+
+ return $plugin->volume_support_qemu_snapshot($storeid, $scfg, $volname);
+ }
+ return undef;
+}
+
# Various io-heavy operations require io/bandwidth limits which can be
# configured on multiple levels: The global defaults in datacenter.cfg, and
# per-storage overrides. When we want to do a restore from storage A to storage
diff --git a/src/PVE/Storage/DirPlugin.pm b/src/PVE/Storage/DirPlugin.pm
index 54d8d74..3287fde 100644
--- a/src/PVE/Storage/DirPlugin.pm
+++ b/src/PVE/Storage/DirPlugin.pm
@@ -302,4 +302,14 @@ sub get_import_metadata {
};
}
+sub volume_support_qemu_snapshot {
+ my ($class, $storeid, $scfg, $volname) = @_;
+
+ my $format = ($class->parse_volname($volname))[6];
+ return if $format ne 'qcow2';
+
+ my $type = $scfg->{snapext} ? 'external' : 'internal';
+ return $type;
+}
+
1;
diff --git a/src/PVE/Storage/LVMPlugin.pm b/src/PVE/Storage/LVMPlugin.pm
index af50b91..3ba2f0f 100644
--- a/src/PVE/Storage/LVMPlugin.pm
+++ b/src/PVE/Storage/LVMPlugin.pm
@@ -1065,4 +1065,11 @@ sub get_snap_volname {
return $class->get_snap_name($volname, $snapname);
}
+sub volume_support_qemu_snapshot {
+ my ($class, $storeid, $scfg, $volname) = @_;
+
+ my $format = ($class->parse_volname($volname))[6];
+ return 'external' if $format eq 'qcow2';
+}
+
1;
diff --git a/src/PVE/Storage/Plugin.pm b/src/PVE/Storage/Plugin.pm
index fd50b9e..6bdd9c6 100644
--- a/src/PVE/Storage/Plugin.pm
+++ b/src/PVE/Storage/Plugin.pm
@@ -2113,6 +2113,26 @@ sub new_backup_provider {
die "implement me if enabling the feature 'backup-provider' in plugindata()->{features}\n";
}
+=pod
+
+=head3 volume_support_qemu_snapshot
+
+ $blockdev = $plugin->volume_support_qemu_snapshot($storeid, $scfg, $volname)
+
+Returns a string with the type of snapshot that qemu can do for a specific volume
+
+'internal' : support snapshot with qemu internal snapshot
+'external' : support snapshot with qemu external snapshot
+undef : don't support qemu snapshot
+=cut
+
+sub volume_support_qemu_snapshot {
+ my ($class, $storeid, $scfg, $volname) = @_;
+
+ my $format = ($class->parse_volname($volname))[6];
+ return 'internal' if $format eq 'qcow2';
+}
+
sub config_aware_base_mkdir {
my ($class, $scfg, $path) = @_;
diff --git a/src/PVE/Storage/RBDPlugin.pm b/src/PVE/Storage/RBDPlugin.pm
index afed2be..88227bd 100644
--- a/src/PVE/Storage/RBDPlugin.pm
+++ b/src/PVE/Storage/RBDPlugin.pm
@@ -1039,4 +1039,10 @@ sub rename_volume {
return "${storeid}:${base_name}${target_volname}";
}
+sub volume_support_qemu_snapshot {
+ my ($class, $storeid, $scfg, $volname) = @_;
+
+ return 'internal' if !$scfg->{krbd};
+}
+
1;
--
2.39.5
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* [pve-devel] [PATCH qemu-server 10/13] blockdev: change aio on target if io_uring is not default.
[not found] <20250603075558.627850-1-alexandre.derumier@groupe-cyllene.com>
` (18 preceding siblings ...)
2025-06-03 7:55 ` [pve-devel] [PATCH pve-storage 9/9] storage: add volume_support_qemu_snapshot Alexandre Derumier via pve-devel
@ 2025-06-03 7:55 ` Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 11/13] qemu_img convert : add external snapshot support Alexandre Derumier via pve-devel
` (2 subsequent siblings)
22 siblings, 0 replies; 39+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-06-03 7:55 UTC (permalink / raw)
To: pve-devel; +Cc: Alexandre Derumier
[-- Attachment #1: Type: message/rfc822, Size: 4777 bytes --]
From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH qemu-server 10/13] blockdev: change aio on target if io_uring is not default.
Date: Tue, 3 Jun 2025 09:55:55 +0200
Message-ID: <20250603075558.627850-21-alexandre.derumier@groupe-cyllene.com>
This was a limitation of drive-mirror, blockdev mirror is able
to reopen image with a different aio.
Do the change when generating the blockdev_format
Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
PVE/QemuServer.pm | 9 ++++++---
PVE/QemuServer/Blockdev.pm | 3 +++
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index f68c5bf2..534aa2df 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -8228,8 +8228,6 @@ sub qemu_blockdev_mirror {
my $dst_drive = dclone($drive);
$dst_drive->{file} = $dst_volid;
$dst_drive->{zeroinit} = 1 if $is_zero_initialized;
- #improve: if target storage don't support aio uring,change it to default native
- #and remove clone_disk_check_io_uring()
#add new block device
my $target_drive_blockdev = generate_drive_blockdev($storecfg, $dst_drive);
@@ -8621,7 +8619,12 @@ sub clone_disk {
$dst_format = 'raw';
$size = PVE::QemuServer::Drive::TPMSTATE_DISK_SIZE;
} else {
- clone_disk_check_io_uring($drive, $storecfg, $src_storeid, $storeid, $use_drive_mirror);
+
+ my $machine_type = PVE::QemuServer::Machine::get_current_qemu_machine($vmid);
+ # blockdev can reopen with a different aio
+ if (!PVE::QemuServer::Machine::is_machine_version_at_least($machine_type, 10, 0)) {
+ clone_disk_check_io_uring($drive, $storecfg, $src_storeid, $storeid, $use_drive_mirror);
+ }
$size = PVE::Storage::volume_size_info($storecfg, $drive->{file}, 10);
}
diff --git a/PVE/QemuServer/Blockdev.pm b/PVE/QemuServer/Blockdev.pm
index 01fef66d..60a996f3 100644
--- a/PVE/QemuServer/Blockdev.pm
+++ b/PVE/QemuServer/Blockdev.pm
@@ -68,6 +68,9 @@ sub generate_blockdev_drive_aio {
$aio = "threads";
}
}
+ } elsif ($drive->{aio} eq 'io_uring' && !storage_allows_io_uring_default($scfg, $cache_direct)) {
+ #change aio if io_uring is not supported by storage
+ $aio = $cache_direct ? 'native' : 'threads';
}
return $aio;
}
--
2.39.5
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* [pve-devel] [PATCH qemu-server 11/13] qemu_img convert : add external snapshot support
[not found] <20250603075558.627850-1-alexandre.derumier@groupe-cyllene.com>
` (19 preceding siblings ...)
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 10/13] blockdev: change aio on target if io_uring is not default Alexandre Derumier via pve-devel
@ 2025-06-03 7:55 ` Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 12/13] blockdev: add backing_chain support Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 13/13] qcow2: add external snapshot support Alexandre Derumier via pve-devel
22 siblings, 0 replies; 39+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-06-03 7:55 UTC (permalink / raw)
To: pve-devel; +Cc: Alexandre Derumier
[-- Attachment #1: Type: message/rfc822, Size: 5746 bytes --]
From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH qemu-server 11/13] qemu_img convert : add external snapshot support
Date: Tue, 3 Jun 2025 09:55:56 +0200
Message-ID: <20250603075558.627850-22-alexandre.derumier@groupe-cyllene.com>
for external snapshot, we simply use snap volname as src.
don't use internal snapshot option in the command line.
Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
PVE/QemuServer.pm | 4 ++-
test/run_qemu_img_convert_tests.pl | 44 ++++++++++++++++++++++++++++++
2 files changed, 47 insertions(+), 1 deletion(-)
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 534aa2df..53135894 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -8104,11 +8104,13 @@ sub qemu_img_convert {
my $dst_format = checked_volume_format($storecfg, $dst_volid);
my $dst_path = PVE::Storage::path($storecfg, $dst_volid);
my $dst_is_iscsi = ($dst_path =~ m|^iscsi://|);
+ my $support_qemu_snapshots = PVE::Storage::volume_support_qemu_snapshot($storecfg, $src_volid);
my $cmd = [];
push @$cmd, '/usr/bin/qemu-img', 'convert', '-p', '-n';
push @$cmd, '-l', "snapshot.name=$snapname"
- if $snapname && $src_format && $src_format eq "qcow2";
+ if $snapname && $src_format eq 'qcow2' && $support_qemu_snapshots && $support_qemu_snapshots eq 'internal';
+
push @$cmd, '-t', 'none' if $dst_scfg->{type} eq 'zfspool';
push @$cmd, '-T', $cachemode if defined($cachemode);
push @$cmd, '-r', "${bwlimit}K" if defined($bwlimit);
diff --git a/test/run_qemu_img_convert_tests.pl b/test/run_qemu_img_convert_tests.pl
index 0a622cd1..5f43d326 100755
--- a/test/run_qemu_img_convert_tests.pl
+++ b/test/run_qemu_img_convert_tests.pl
@@ -21,6 +21,15 @@ my $storage_config = {
type => "dir",
shared => 0,
},
+ localsnapext => {
+ content => {
+ images => 1,
+ },
+ path => "/var/lib/vz",
+ type => "dir",
+ snapext => 1,
+ shared => 0,
+ },
btrfs => {
content => {
images => 1,
@@ -61,6 +70,13 @@ my $storage_config = {
images => 1,
}
},
+ "lvm-store" => {
+ vgname => "pve",
+ type => "lvm",
+ content => {
+ images => 1,
+ }
+ },
"zfs-over-iscsi" => {
type => "zfs",
iscsiprovider => "LIO",
@@ -308,6 +324,34 @@ my $tests = [
"/var/lib/vz/images/$vmid/vm-$vmid-disk-0.raw",
]
},
+ {
+ name => "qcow2_external_snapshot",
+ parameters => [
+ "localsnapext:$vmid/vm-$vmid-disk-0.qcow2",
+ "local:$vmid/vm-$vmid-disk-0.raw",
+ 1024*10,
+ { snapname => 'foo' },
+ ],
+ expected => [
+ "/usr/bin/qemu-img", "convert", "-p", "-n", "-f", "qcow2", "-O", "raw",
+ "/var/lib/vz/images/$vmid/snap-foo-vm-$vmid-disk-0.qcow2",
+ "/var/lib/vz/images/$vmid/vm-$vmid-disk-0.raw",
+ ]
+ },
+ {
+ name => "lvmqcow2_external_snapshot",
+ parameters => [
+ "lvm-store:vm-$vmid-disk-0.qcow2",
+ "local:$vmid/vm-$vmid-disk-0.raw",
+ 1024*10,
+ { snapname => 'foo' },
+ ],
+ expected => [
+ "/usr/bin/qemu-img", "convert", "-p", "-n", "-f", "qcow2", "-O", "raw",
+ "/dev/pve/snap-foo-vm-$vmid-disk-0.qcow2",
+ "/var/lib/vz/images/$vmid/vm-$vmid-disk-0.raw",
+ ]
+ },
];
my $command;
--
2.39.5
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* [pve-devel] [PATCH qemu-server 12/13] blockdev: add backing_chain support
[not found] <20250603075558.627850-1-alexandre.derumier@groupe-cyllene.com>
` (20 preceding siblings ...)
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 11/13] qemu_img convert : add external snapshot support Alexandre Derumier via pve-devel
@ 2025-06-03 7:55 ` Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 13/13] qcow2: add external snapshot support Alexandre Derumier via pve-devel
22 siblings, 0 replies; 39+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-06-03 7:55 UTC (permalink / raw)
To: pve-devel; +Cc: Alexandre Derumier
[-- Attachment #1: Type: message/rfc822, Size: 10968 bytes --]
From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH qemu-server 12/13] blockdev: add backing_chain support
Date: Tue, 3 Jun 2025 09:55:57 +0200
Message-ID: <20250603075558.627850-23-alexandre.derumier@groupe-cyllene.com>
We need to define name-nodes for all backing chain images,
to be able to live rename them with blockdev-reopen
For linked clone, we don't need to definebase image(s) chain.
They are auto added with #block nodename.
Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
PVE/QemuServer/Blockdev.pm | 35 +++++++++++++++++++++++
test/cfg2cmd/simple-backingchain.conf | 21 ++++++++++++++
test/cfg2cmd/simple-backingchain.conf.cmd | 30 +++++++++++++++++++
test/run_config2command_tests.pl | 26 +++++++++++++++++
4 files changed, 112 insertions(+)
create mode 100644 test/cfg2cmd/simple-backingchain.conf
create mode 100644 test/cfg2cmd/simple-backingchain.conf.cmd
diff --git a/PVE/QemuServer/Blockdev.pm b/PVE/QemuServer/Blockdev.pm
index 60a996f3..692336c1 100644
--- a/PVE/QemuServer/Blockdev.pm
+++ b/PVE/QemuServer/Blockdev.pm
@@ -153,6 +153,7 @@ sub generate_file_blockdev {
} elsif($storeid) {
my $blockdev_options = {};
$blockdev_options->{hints}->{'efi-disk'} = 1 if $drive_id =~ m/^efidisk(\d+)$/;
+ $blockdev_options->{'snapshot-name'} = $snap if $snap;
$blockdev = PVE::Storage::qemu_blockdev_options($storecfg, $volid, $blockdev_options);
$scfg = PVE::Storage::storage_config($storecfg, $storeid);
} elsif (drive_is_cdrom($drive)) {
@@ -244,6 +245,34 @@ sub generate_format_blockdev {
return $blockdev;
}
+my sub generate_backing_blockdev;
+sub generate_backing_blockdev {
+ my ($storecfg, $snapshots, $deviceid, $drive, $snap_id) = @_;
+
+ my $snapshot = $snapshots->{$snap_id};
+ my $parentid = $snapshot->{parent};
+
+ my $volid = $drive->{file};
+
+ my $snap_file_blockdev = generate_file_blockdev($storecfg, $drive, $snap_id);
+ $snap_file_blockdev->{filename} = $snapshot->{file};
+ $drive->{ro} = 1;
+ my $snap_fmt_blockdev = generate_format_blockdev($storecfg, $drive, $snap_file_blockdev, $snap_id);
+ $snap_fmt_blockdev->{backing} = generate_backing_blockdev($storecfg, $snapshots, $deviceid, $drive, $parentid) if $parentid;
+ return $snap_fmt_blockdev;
+}
+
+my sub generate_backing_chain_blockdev {
+ my ($storecfg, $deviceid, $drive) = @_;
+
+ my $volid = $drive->{file};
+
+ my $snapshots = PVE::Storage::volume_snapshot_info($storecfg, $volid);
+ my $parentid = $snapshots->{'current'}->{parent};
+ return undef if !$parentid;
+ return generate_backing_blockdev($storecfg, $snapshots, $deviceid, $drive, $parentid);
+}
+
sub generate_drive_blockdev {
my ($storecfg, $drive, $live_restore_name, $size) = @_;
@@ -262,6 +291,12 @@ sub generate_drive_blockdev {
my $blockdev_file = generate_file_blockdev($storecfg, $drive);
my $blockdev_format = generate_format_blockdev($storecfg, $drive, $blockdev_file, undef, $size);
+ my $support_qemu_snapshots = PVE::Storage::volume_support_qemu_snapshot($storecfg, $volid);
+ if ($support_qemu_snapshots && $support_qemu_snapshots eq 'external') {
+ my $backing_chain = generate_backing_chain_blockdev($storecfg, "drive-$drive_id", $drive);
+ $blockdev_format->{backing} = $backing_chain if $backing_chain;
+ }
+
my $blockdev_live_restore = undef;
#pflash0 don't support throttle-filter
return $blockdev_format if $drive_id eq 'pflash0';
diff --git a/test/cfg2cmd/simple-backingchain.conf b/test/cfg2cmd/simple-backingchain.conf
new file mode 100644
index 00000000..71664bd5
--- /dev/null
+++ b/test/cfg2cmd/simple-backingchain.conf
@@ -0,0 +1,21 @@
+# TEST: Simple test for external snapshot backing chain
+name: simple
+parent: snap3
+scsi0: localsnapext:8006/vm-8006-disk-0.qcow2,size=1G
+
+[snap1]
+name: simple
+scsi0: localsnapext:8006/vm-8006-disk-0.qcow2,size=1G
+snaptime: 1748933042
+
+[snap2]
+parent: snap1
+name: simple
+scsi0: localsnapext:8006/vm-8006-disk-0.qcow2,size=1G
+snaptime: 1748933043
+
+[snap3]
+parent: snap2
+name: simple
+scsi0: localsnapext:8006/vm-8006-disk-0.qcow2,size=1G
+snaptime: 1748933044
diff --git a/test/cfg2cmd/simple-backingchain.conf.cmd b/test/cfg2cmd/simple-backingchain.conf.cmd
new file mode 100644
index 00000000..739183ee
--- /dev/null
+++ b/test/cfg2cmd/simple-backingchain.conf.cmd
@@ -0,0 +1,30 @@
+/usr/bin/kvm \
+ -id 8006 \
+ -name 'simple,debug-threads=on' \
+ -no-shutdown \
+ -chardev 'socket,id=qmp,path=/var/run/qemu-server/8006.qmp,server=on,wait=off' \
+ -mon 'chardev=qmp,mode=control' \
+ -chardev 'socket,id=qmp-event,path=/var/run/qmeventd.sock,reconnect-ms=5000' \
+ -mon 'chardev=qmp-event,mode=control' \
+ -pidfile /var/run/qemu-server/8006.pid \
+ -daemonize \
+ -smp '1,sockets=1,cores=1,maxcpus=1' \
+ -nodefaults \
+ -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
+ -vnc 'unix:/var/run/qemu-server/8006.vnc,password=on' \
+ -cpu kvm64,enforce,+kvm_pv_eoi,+kvm_pv_unhalt,+lahf_lm,+sep \
+ -m 512 \
+ -global 'PIIX4_PM.disable_s3=1' \
+ -global 'PIIX4_PM.disable_s4=1' \
+ -device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \
+ -device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \
+ -device 'piix3-usb-uhci,id=uhci,bus=pci.0,addr=0x1.0x2' \
+ -device 'usb-tablet,id=tablet,bus=uhci.0,port=1' \
+ -device 'VGA,id=vga,bus=pci.0,addr=0x2' \
+ -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3,free-page-reporting=on' \
+ -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
+ -device 'lsi,id=scsihw0,bus=pci.0,addr=0x5' \
+ -object '{"id":"throttle-drive-scsi0","limits":{},"qom-type":"throttle-group"}' \
+ -blockdev '{"driver":"throttle","file":{"backing":{"backing":{"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"on","discard":"ignore","driver":"file","filename":"/var/lib/vz/images/8006/snap1-vm-8006-disk-0.qcow2","node-name":"e-aN9FfpTi1eqQ4kUSoMKsyEYSM6k"},"node-name":"f-aN9FfpTi1eqQ4kUSoMKsyEYSM6k","read-only":true},"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"on","discard":"ignore","driver":"file","filename":"/var/lib/vz/images/8006/snap2-vm-8006-disk-0.qcow2","node-name":"e-Zu2dZCd1WKQe604KQ0Cy4AMmGww"},"node-name":"f-Zu2dZCd1WKQe604KQ0Cy4AMmGww","read-only":true},"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":{"aio":"io_uring","cache":{"direct":true,"no-flush":false},"detect-zeroes":"on","discard":"ignore","driver":"file","filename":"/var/lib/vz/images/8006/vm-8006-disk-0.qcow2","node-name":"e-8ps94lIsZyMk28qw4ggmas8MCki"},"node-name":"f-8ps94lIsZyMk28qw4ggmas8MCki","read-only":false},"node-name":"drive-scsi0","throttle-group":"throttle-drive-scsi0"}' \
+ -device 'scsi-hd,bus=scsihw0.0,scsi-id=0,drive=drive-scsi0,id=scsi0' \
+ -machine 'type=pc+pve0'
diff --git a/test/run_config2command_tests.pl b/test/run_config2command_tests.pl
index d689fc5b..83b513ec 100755
--- a/test/run_config2command_tests.pl
+++ b/test/run_config2command_tests.pl
@@ -33,6 +33,15 @@ my $base_env = {
type => 'dir',
shared => 0,
},
+ localsnapext => {
+ content => {
+ images => 1,
+ },
+ path => '/var/lib/vz',
+ type => 'dir',
+ shared => 0,
+ snapext => 1,
+ },
noimages => {
content => {
iso => 1,
@@ -492,6 +501,23 @@ my $storage_module = Test::MockModule->new("PVE::Storage");
$storage_module->mock(
activate_volumes => sub {
return;
+ },
+ volume_snapshot_info => sub {
+ my $snapshots = {
+ current => {
+ file => '/var/lib/vz/images/8006/vm-8006-disk-0.qcow2',
+ parent => 'snap2'
+ },
+ snap2 => {
+ file => '/var/lib/vz/images/8006/snap2-vm-8006-disk-0.qcow2',
+ parent => 'snap1'
+ },
+ snap1 => {
+ file => '/var/lib/vz/images/8006/snap1-vm-8006-disk-0.qcow2',
+
+ },
+ };
+ return $snapshots;
}
);
--
2.39.5
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* [pve-devel] [PATCH qemu-server 13/13] qcow2: add external snapshot support
[not found] <20250603075558.627850-1-alexandre.derumier@groupe-cyllene.com>
` (21 preceding siblings ...)
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 12/13] blockdev: add backing_chain support Alexandre Derumier via pve-devel
@ 2025-06-03 7:55 ` Alexandre Derumier via pve-devel
22 siblings, 0 replies; 39+ messages in thread
From: Alexandre Derumier via pve-devel @ 2025-06-03 7:55 UTC (permalink / raw)
To: pve-devel; +Cc: Alexandre Derumier
[-- Attachment #1: Type: message/rfc822, Size: 20339 bytes --]
From: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH qemu-server 13/13] qcow2: add external snapshot support
Date: Tue, 3 Jun 2025 09:55:58 +0200
Message-ID: <20250603075558.627850-24-alexandre.derumier@groupe-cyllene.com>
fixme:
- add test for internal (was missing) && external qemu snapshots
- is it possible to use blockjob transactions for commit && steam
for atomatic disk commit ?
Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
---
PVE/QemuConfig.pm | 4 +-
PVE/QemuServer.pm | 79 ++++++++++-----
PVE/QemuServer/Blockdev.pm | 199 ++++++++++++++++++++++++++++++++++---
test/snapshot-test.pm | 4 +-
4 files changed, 245 insertions(+), 41 deletions(-)
diff --git a/PVE/QemuConfig.pm b/PVE/QemuConfig.pm
index 2609542c..785c84a2 100644
--- a/PVE/QemuConfig.pm
+++ b/PVE/QemuConfig.pm
@@ -378,7 +378,7 @@ sub __snapshot_create_vol_snapshot {
print "snapshotting '$device' ($drive->{file})\n";
- PVE::QemuServer::qemu_volume_snapshot($vmid, $device, $storecfg, $volid, $snapname);
+ PVE::QemuServer::qemu_volume_snapshot($vmid, $device, $storecfg, $drive, $snapname);
}
sub __snapshot_delete_remove_drive {
@@ -415,7 +415,7 @@ sub __snapshot_delete_vol_snapshot {
my $storecfg = PVE::Storage::config();
my $volid = $drive->{file};
- PVE::QemuServer::qemu_volume_snapshot_delete($vmid, $storecfg, $volid, $snapname);
+ PVE::QemuServer::qemu_volume_snapshot_delete($vmid, $storecfg, $drive, $snapname);
push @$unused, $volid;
}
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 53135894..9857c536 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -52,7 +52,7 @@ use PVE::QMPClient;
use PVE::QemuConfig;
use PVE::QemuConfig::NoWrite;
use PVE::QemuServer::Helpers qw(config_aware_timeout min_version kvm_user_version windows_version);
-use PVE::QemuServer::Blockdev qw(generate_drive_blockdev generate_throttle_group);
+use PVE::QemuServer::Blockdev qw(generate_drive_blockdev generate_throttle_group blockdev_external_snapshot blockdev_delete blockdev_rename blockdev_commit blockdev_stream);
use PVE::QemuServer::Cloudinit;
use PVE::QemuServer::CGroup;
use PVE::QemuServer::CPUConfig qw(print_cpu_device get_cpu_options get_cpu_bitness is_native_arch get_amd_sev_object get_amd_sev_type);
@@ -4677,20 +4677,37 @@ sub qemu_block_resize {
}
sub qemu_volume_snapshot {
- my ($vmid, $deviceid, $storecfg, $volid, $snap) = @_;
+ my ($vmid, $deviceid, $storecfg, $drive, $snap) = @_;
+ my $volid = $drive->{file};
my $running = check_running($vmid);
- if ($running && do_snapshots_with_qemu($storecfg, $volid, $deviceid)) {
+ my $do_snapshots_type = do_snapshots_type($storecfg, $volid, $deviceid, $running);
+
+ if ($do_snapshots_type eq 'internal') {
+ print "internal qemu snapshot\n";
mon_cmd($vmid, 'blockdev-snapshot-internal-sync', device => $deviceid, name => $snap);
- } else {
+ } elsif ($do_snapshots_type eq 'external') {
+ my $storeid = (PVE::Storage::parse_volume_id($volid))[0];
+ my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
+ print "external qemu snapshot\n";
+ my $snapshots = PVE::Storage::volume_snapshot_info($storecfg, $volid);
+ my $parent_snap = $snapshots->{'current'}->{parent};
+ blockdev_rename($storecfg, $vmid, $deviceid, $drive, 'current', $snap, $parent_snap);
+ eval { blockdev_external_snapshot($storecfg, $vmid, $deviceid, $drive, $snap) };
+ if ($@) {
+ print "error creating snapshot. Revert rename\n";
+ eval { blockdev_rename($storecfg, $vmid, $deviceid, $drive, $snap, 'current', $parent_snap) };
+ }
+ } elsif ($do_snapshots_type eq 'storage') {
PVE::Storage::volume_snapshot($storecfg, $volid, $snap);
}
}
sub qemu_volume_snapshot_delete {
- my ($vmid, $storecfg, $volid, $snap) = @_;
+ my ($vmid, $storecfg, $drive, $snap) = @_;
+ my $volid = $drive->{file};
my $running = check_running($vmid);
my $attached_deviceid;
@@ -4702,14 +4719,35 @@ sub qemu_volume_snapshot_delete {
});
}
- if ($attached_deviceid && do_snapshots_with_qemu($storecfg, $volid, $attached_deviceid)) {
+ my $do_snapshots_type = do_snapshots_type($storecfg, $volid, $attached_deviceid, $running);
+
+ if ($do_snapshots_type eq 'internal') {
mon_cmd(
$vmid,
'blockdev-snapshot-delete-internal-sync',
device => $attached_deviceid,
name => $snap,
);
- } else {
+ } elsif ($do_snapshots_type eq 'external') {
+ print "delete qemu external snapshot\n";
+
+ my $path = PVE::Storage::path($storecfg, $volid);
+ my $snapshots = PVE::Storage::volume_snapshot_info($storecfg, $volid);
+ my $parentsnap = $snapshots->{$snap}->{parent};
+ my $childsnap = $snapshots->{$snap}->{child};
+
+ # if we delete the first snasphot, we commit because the first snapshot original base image, it should be big.
+ # improve-me: if firstsnap > child : commit, if firstsnap < child do a stream.
+ if(!$parentsnap) {
+ print"delete first snapshot $snap\n";
+ blockdev_commit($storecfg, $vmid, $attached_deviceid, $drive, $childsnap, $snap);
+ blockdev_rename($storecfg, $vmid, $attached_deviceid, $drive, $snap, $childsnap, $snapshots->{$childsnap}->{child});
+ } else {
+ #intermediate snapshot, we always stream the snapshot to child snapshot
+ print"stream intermediate snapshot $snap to $childsnap\n";
+ blockdev_stream($storecfg, $vmid, $attached_deviceid, $drive, $snap, $parentsnap, $childsnap);
+ }
+ } elsif ($do_snapshots_type eq 'storage') {
PVE::Storage::volume_snapshot_delete(
$storecfg, $volid, $snap, $attached_deviceid ? 1 : undef);
}
@@ -7976,27 +8014,20 @@ sub foreach_storage_used_by_vm {
}
}
-my $qemu_snap_storage = {
- rbd => 1,
-};
-sub do_snapshots_with_qemu {
- my ($storecfg, $volid, $deviceid) = @_;
+sub do_snapshots_type {
+ my ($storecfg, $volid, $deviceid, $running) = @_;
- return if $deviceid =~ m/tpmstate0/;
+ #we skip snapshot for tpmstate
+ return if $deviceid && $deviceid =~ m/tpmstate0/;
- my $storage_name = PVE::Storage::parse_volume_id($volid);
- my $scfg = $storecfg->{ids}->{$storage_name};
- die "could not find storage '$storage_name'\n" if !defined($scfg);
+ #we use storage snapshot if vm is not running or if disk is unused;
+ return 'storage' if !$running || !$deviceid;
- if ($qemu_snap_storage->{$scfg->{type}} && !$scfg->{krbd}){
- return 1;
- }
+ my $qemu_snapshot_type = PVE::Storage::volume_support_qemu_snapshot($storecfg, $volid);
+ # if running, but don't support qemu snapshot, we use storage snapshot
+ return 'storage' if !$qemu_snapshot_type;
- if ($volid =~ m/\.(qcow2|qed)$/){
- return 1;
- }
-
- return;
+ return $qemu_snapshot_type;
}
sub qga_check_running {
diff --git a/PVE/QemuServer/Blockdev.pm b/PVE/QemuServer/Blockdev.pm
index 692336c1..3a199c9e 100644
--- a/PVE/QemuServer/Blockdev.pm
+++ b/PVE/QemuServer/Blockdev.pm
@@ -3,6 +3,8 @@ package PVE::QemuServer::Blockdev;
use strict;
use warnings;
+use PVE::QemuServer;
+use PVE::QemuServer::Monitor qw(mon_cmd);
use PVE::QemuServer::Drive qw(checked_volume_format drive_is_cdrom drive_uses_cache_direct get_drive_id get_iso_path storage_allows_io_uring_default);
use PVE::Storage;
@@ -11,6 +13,11 @@ use base qw(Exporter);
our @EXPORT_OK = qw(
generate_drive_blockdev
generate_throttle_group
+blockdev_external_snapshot
+blockdev_delete
+blockdev_rename
+blockdev_commit
+blockdev_stream
);
sub encode_base62 {
@@ -134,6 +141,8 @@ sub print_drive_throttle_group {
sub generate_file_blockdev {
my ($storecfg, $drive, $snap, $nodename) = @_;
+ $snap = undef if $snap && $snap eq 'current';
+
my $volid = $drive->{file};
my $drive_id = get_drive_id($drive);
my $blockdev = {};
@@ -200,6 +209,8 @@ sub generate_file_blockdev {
sub generate_format_blockdev {
my ($storecfg, $drive, $file, $snap, $size, $nodename) = @_;
+ $snap = undef if $snap && $snap eq 'current';
+
my $volid = $drive->{file};
#nbd don't support format blockdev, return the fileblockdev
return $file if $volid =~ /^nbd:/;
@@ -273,6 +284,15 @@ my sub generate_backing_chain_blockdev {
return generate_backing_blockdev($storecfg, $snapshots, $deviceid, $drive, $parentid);
}
+sub generate_blockdev_throttle {
+ my ($drive, $blockdev_file) = @_;
+
+ my $drive_id = get_drive_id($drive);
+ #this is the topfilter entry point, use $drive-drive_id as nodename
+ my $blockdev_throttle = { driver => "throttle", 'node-name' => "drive-$drive_id", 'throttle-group' => "throttle-drive-$drive_id", 'file' => $blockdev_file };
+ return $blockdev_throttle;
+}
+
sub generate_drive_blockdev {
my ($storecfg, $drive, $live_restore_name, $size) = @_;
@@ -297,25 +317,178 @@ sub generate_drive_blockdev {
$blockdev_format->{backing} = $backing_chain if $backing_chain;
}
- my $blockdev_live_restore = undef;
#pflash0 don't support throttle-filter
return $blockdev_format if $drive_id eq 'pflash0';
- if ($live_restore_name) {
- die "$drive_id: Proxmox Backup Server backed drive cannot auto-detect the format\n"
- if !$drive->{format};
+ return generate_blockdev_throttle($drive, $blockdev_format) if !$live_restore_name;
- $blockdev_live_restore = { 'node-name' => "liverestore-drive-$drive_id",
- backing => $live_restore_name,
- 'auto-remove' => 'on', format => "alloc-track",
- file => $blockdev_format };
- }
+ die "$drive_id: Proxmox Backup Server backed drive cannot auto-detect the format\n"
+ if !$drive->{format};
- #this is the topfilter entry point, use $drive-drive_id as nodename
- my $blockdev_throttle = { driver => "throttle", 'node-name' => "drive-$drive_id", 'throttle-group' => "throttle-drive-$drive_id" };
#put liverestore filter between throttle && format filter
- $blockdev_throttle->{file} = $live_restore_name ? $blockdev_live_restore : $blockdev_format;
- return $blockdev_throttle,
+ my $blockdev_live_restore = { 'node-name' => "liverestore-drive-$drive_id",
+ backing => $live_restore_name,
+ 'auto-remove' => 'on', format => "alloc-track",
+ file => $blockdev_format };
+
+ return generate_blockdev_throttle($drive, $blockdev_live_restore);
+}
+
+sub blockdev_external_snapshot {
+ my ($storecfg, $vmid, $deviceid, $drive, $snap, $size) = @_;
+
+ my $volid = $drive->{file};
+
+ #preallocate add a new current file with reference to backing-file
+ PVE::Storage::volume_snapshot($storecfg, $volid, $snap, 1);
+
+ #be sure to add drive in write mode
+ delete($drive->{ro});
+
+ my $new_file_blockdev = generate_file_blockdev($storecfg, $drive);
+ my $new_fmt_blockdev = generate_format_blockdev($storecfg, $drive, $new_file_blockdev);
+
+ my $snap_file_blockdev = generate_file_blockdev($storecfg, $drive, $snap);
+ my $snap_fmt_blockdev = generate_format_blockdev($storecfg, $drive, $snap_file_blockdev, $snap);
+
+ #backing need to be forced to undef in blockdev, to avoid reopen of backing-file on blockdev-add
+ $new_fmt_blockdev->{backing} = undef;
+
+ mon_cmd($vmid, 'blockdev-add', %$new_fmt_blockdev);
+
+ mon_cmd($vmid, 'blockdev-snapshot', node => $snap_fmt_blockdev->{'node-name'}, overlay => $new_fmt_blockdev->{'node-name'});
+}
+
+sub blockdev_delete {
+ my ($storecfg, $vmid, $drive, $file_blockdev, $fmt_blockdev, $snap) = @_;
+
+ #add eval as reopen is auto removing the old nodename automatically only if it was created at vm start in command line argument
+ eval { mon_cmd($vmid, 'blockdev-del', 'node-name' => $file_blockdev->{'node-name'}) };
+ eval { mon_cmd($vmid, 'blockdev-del', 'node-name' => $fmt_blockdev->{'node-name'}) };
+
+ #delete the file (don't use vdisk_free as we don't want to delete all snapshot chain)
+ print"delete old $file_blockdev->{filename}\n";
+
+ my $storage_name = PVE::Storage::parse_volume_id($drive->{file});
+
+ my $volid = $drive->{file};
+ PVE::Storage::volume_snapshot_delete($storecfg, $volid, $snap, 1);
}
+sub blockdev_rename {
+ my ($storecfg, $vmid, $deviceid, $drive, $src_snap, $target_snap, $parent_snap) = @_;
+
+ print "rename $src_snap to $target_snap\n";
+
+ my $volid = $drive->{file};
+
+ my $src_file_blockdev = generate_file_blockdev($storecfg, $drive, $src_snap);
+ my $src_fmt_blockdev = generate_format_blockdev($storecfg, $drive, $src_file_blockdev, $src_snap);
+
+ #rename volume image
+ PVE::Storage::rename_volume($storecfg, $volid, $vmid, undef, $src_snap, $target_snap);
+
+ my $target_file_blockdev = generate_file_blockdev($storecfg, $drive, $target_snap);
+ my $target_fmt_blockdev = generate_format_blockdev($storecfg, $drive, $target_file_blockdev, $target_snap);
+
+ if($target_snap eq 'current' || $src_snap eq 'current') {
+ #rename from|to current
+
+ #add backing to target
+ if ($parent_snap) {
+ my $parent_fmt_nodename = encode_nodename('fmt', $volid, $parent_snap);
+ $target_fmt_blockdev->{backing} = $parent_fmt_nodename;
+ }
+ mon_cmd($vmid, 'blockdev-add', %$target_fmt_blockdev);
+
+ #reopen the current throttlefilter nodename with the target fmt nodename
+ my $throttle_blockdev = generate_blockdev_throttle($drive, $target_fmt_blockdev->{'node-name'});
+ mon_cmd($vmid, 'blockdev-reopen', options => [$throttle_blockdev]);
+ } else {
+ rename($src_file_blockdev->{filename}, $target_file_blockdev->{filename});
+
+ #intermediate snapshot
+ mon_cmd($vmid, 'blockdev-add', %$target_fmt_blockdev);
+
+ #reopen the parent node with the new target fmt backing node
+ my $parent_file_blockdev = generate_file_blockdev($storecfg, $drive, $parent_snap);
+ my $parent_fmt_blockdev = generate_format_blockdev($storecfg, $drive, $parent_file_blockdev, $parent_snap);
+ $parent_fmt_blockdev->{backing} = $target_fmt_blockdev->{'node-name'};
+ mon_cmd($vmid, 'blockdev-reopen', options => [$parent_fmt_blockdev]);
+
+ #change backing-file in qcow2 metadatas
+ mon_cmd($vmid, 'change-backing-file', device => $deviceid, 'image-node-name' => $parent_fmt_blockdev->{'node-name'}, 'backing-file' => $target_file_blockdev->{filename});
+ }
+
+ # delete old file|fmt nodes
+ # add eval as reopen is auto removing the old nodename automatically only if it was created at vm start in command line argument
+ eval { mon_cmd($vmid, 'blockdev-del', 'node-name' => $src_file_blockdev->{'node-name'})};
+ eval { mon_cmd($vmid, 'blockdev-del', 'node-name' => $src_fmt_blockdev->{'node-name'})};
+}
+
+sub blockdev_commit {
+ my ($storecfg, $vmid, $deviceid, $drive, $src_snap, $target_snap) = @_;
+
+ my $volid = $drive->{file};
+
+ print "block-commit $src_snap to base:$target_snap\n";
+
+ my $target_file_blockdev = generate_file_blockdev($storecfg, $drive, $target_snap);
+ my $target_fmt_blockdev = generate_format_blockdev($storecfg, $drive, $target_file_blockdev, $target_snap);
+
+ my $src_file_blockdev = generate_file_blockdev($storecfg, $drive, $src_snap);
+ my $src_fmt_blockdev = generate_format_blockdev($storecfg, $drive, $src_file_blockdev, $src_snap);
+
+ my $job_id = "commit-$deviceid";
+ my $jobs = {};
+ my $opts = { 'job-id' => $job_id, device => $deviceid };
+
+ $opts->{'base-node'} = $target_fmt_blockdev->{'node-name'};
+ $opts->{'top-node'} = $src_fmt_blockdev->{'node-name'};
+
+ mon_cmd($vmid, "block-commit", %$opts);
+ $jobs->{$job_id} = {};
+
+ # if we commit the current, the blockjob need to be in 'complete' mode
+ my $complete = $src_snap && $src_snap ne 'current' ? 'auto' : 'complete';
+
+ eval { PVE::QemuServer::qemu_drive_mirror_monitor($vmid, undef, $jobs, $complete, 0, 'commit'); };
+ if ($@) {
+ die "Failed to complete block commit: $@\n";
+ }
+
+ blockdev_delete($storecfg, $vmid, $drive, $src_file_blockdev, $src_fmt_blockdev, $src_snap);
+}
+
+sub blockdev_stream {
+ my ($storecfg, $vmid, $deviceid, $drive, $snap, $parent_snap, $target_snap) = @_;
+
+ my $volid = $drive->{file};
+ $target_snap = undef if $target_snap eq 'current';
+
+ my $parent_file_blockdev = generate_file_blockdev($storecfg, $drive, $parent_snap);
+ my $parent_fmt_blockdev = generate_format_blockdev($storecfg, $drive, $parent_file_blockdev, $parent_snap);
+
+ my $target_file_blockdev = generate_file_blockdev($storecfg, $drive, $target_snap);
+ my $target_fmt_blockdev = generate_format_blockdev($storecfg, $drive, $target_file_blockdev, $target_snap);
+
+ my $snap_file_blockdev = generate_file_blockdev($storecfg, $drive, $snap);
+ my $snap_fmt_blockdev = generate_format_blockdev($storecfg, $drive, $snap_file_blockdev, $snap);
+
+ my $job_id = "stream-$deviceid";
+ my $jobs = {};
+ my $options = { 'job-id' => $job_id, device => $target_fmt_blockdev->{'node-name'} };
+ $options->{'base-node'} = $parent_fmt_blockdev->{'node-name'};
+ $options->{'backing-file'} = $parent_file_blockdev->{filename};
+
+ mon_cmd($vmid, 'block-stream', %$options);
+ $jobs->{$job_id} = {};
+
+ eval { PVE::QemuServer::qemu_drive_mirror_monitor($vmid, undef, $jobs, 'auto', 0, 'stream'); };
+ if ($@) {
+ die "Failed to complete block stream: $@\n";
+ }
+
+ blockdev_delete($storecfg, $vmid, $drive, $snap_file_blockdev, $snap_fmt_blockdev, $snap);
+}
1;
diff --git a/test/snapshot-test.pm b/test/snapshot-test.pm
index f130a5a5..1f61a13f 100644
--- a/test/snapshot-test.pm
+++ b/test/snapshot-test.pm
@@ -362,8 +362,8 @@ sub qmp_cmd {
# BEGIN redefine PVE::QemuServer methods
-sub do_snapshots_with_qemu {
- return 0;
+sub do_snapshots_type {
+ return 'storage';
}
sub vm_start {
--
2.39.5
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support Alexandre Derumier via pve-devel
@ 2025-06-05 13:23 ` Fiona Ebner
2025-06-05 14:17 ` Fabian Grünbichler
` (2 more replies)
2025-06-06 8:50 ` Fiona Ebner
2025-06-10 14:03 ` Fiona Ebner
2 siblings, 3 replies; 39+ messages in thread
From: Fiona Ebner @ 2025-06-05 13:23 UTC (permalink / raw)
To: Proxmox VE development discussion
Am 03.06.25 um 09:55 schrieb Alexandre Derumier via pve-devel:
> +sub encode_nodename {
> + my ($type, $volid, $snap) = @_;
> +
> + my $nodename = "$volid";
> + $nodename .= "-$snap" if $snap;
This will lead to clashes in some cases:
1. Currently, we allow attaching the same volume multiple times to a
single guest.
2. You can end up with the same name for
volname = vm-1234-disk-0-foo
and for
volname = vm-1234-disk-0, snap = foo
The latter can be rather easily fixed by just using a character we don't
usually support for volume names, but not the former. So I'd like to do
the switch to -blockdev without support for "looking up which node a
certain volume is" at first. In general, I feel like mixing the switch
to -blockdev with your larger series is too much at once. We should
first get the switch to -blockdev completely and cleanly sorted out,
then we can add your external qcow2 support on top.
I think we can even rely on auto-generated-by-QEMU node names at first.
We can later switch to a variant where node names encode additional
information. Or we could also think about patching QEMU to better fit
the need for the "looking up which node a certain volume is" feature.
But I don't think figuring this out should block us right now for the
switch to "-blockdev".
I'll try to work out a series that focuses just on the switch to
"-blockdev" based on your patches during the next week or so. Maybe not
much else needs to be changed :) The work is certainly greatly appreciated!
@Fabian opinions?
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support
2025-06-05 13:23 ` Fiona Ebner
@ 2025-06-05 14:17 ` Fabian Grünbichler
2025-06-05 14:39 ` DERUMIER, Alexandre via pve-devel
[not found] ` <ee4940c99e9866910405b492dad15c68718c49ea.camel@groupe-cyllene.com>
2 siblings, 0 replies; 39+ messages in thread
From: Fabian Grünbichler @ 2025-06-05 14:17 UTC (permalink / raw)
To: Fiona Ebner, Proxmox VE development discussion
> Fiona Ebner <f.ebner@proxmox.com> hat am 05.06.2025 15:23 CEST geschrieben:
>
>
> Am 03.06.25 um 09:55 schrieb Alexandre Derumier via pve-devel:
> > +sub encode_nodename {
> > + my ($type, $volid, $snap) = @_;
> > +
> > + my $nodename = "$volid";
> > + $nodename .= "-$snap" if $snap;
>
> This will lead to clashes in some cases:
> 1. Currently, we allow attaching the same volume multiple times to a
> single guest.
> 2. You can end up with the same name for
> volname = vm-1234-disk-0-foo
> and for
> volname = vm-1234-disk-0, snap = foo
>
> The latter can be rather easily fixed by just using a character we don't
> usually support for volume names, but not the former. So I'd like to do
> the switch to -blockdev without support for "looking up which node a
> certain volume is" at first. In general, I feel like mixing the switch
> to -blockdev with your larger series is too much at once. We should
> first get the switch to -blockdev completely and cleanly sorted out,
> then we can add your external qcow2 support on top.
>
> I think we can even rely on auto-generated-by-QEMU node names at first.
> We can later switch to a variant where node names encode additional
> information. Or we could also think about patching QEMU to better fit
> the need for the "looking up which node a certain volume is" feature.
> But I don't think figuring this out should block us right now for the
> switch to "-blockdev".
>
> I'll try to work out a series that focuses just on the switch to
> "-blockdev" based on your patches during the next week or so. Maybe not
> much else needs to be changed :) The work is certainly greatly appreciated!
>
> @Fabian opinions?
I think this is a good disentanglement approach, provided we keep anything
"special" required by the qcow2 series in mind while doing so (to avoid
the need for double compat hacks).
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support
2025-06-05 13:23 ` Fiona Ebner
2025-06-05 14:17 ` Fabian Grünbichler
@ 2025-06-05 14:39 ` DERUMIER, Alexandre via pve-devel
[not found] ` <ee4940c99e9866910405b492dad15c68718c49ea.camel@groupe-cyllene.com>
2 siblings, 0 replies; 39+ messages in thread
From: DERUMIER, Alexandre via pve-devel @ 2025-06-05 14:39 UTC (permalink / raw)
To: pve-devel, f.ebner; +Cc: DERUMIER, Alexandre
[-- Attachment #1: Type: message/rfc822, Size: 17299 bytes --]
From: "DERUMIER, Alexandre" <alexandre.derumier@groupe-cyllene.com>
To: "pve-devel@lists.proxmox.com" <pve-devel@lists.proxmox.com>, "f.ebner@proxmox.com" <f.ebner@proxmox.com>
Subject: Re: [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support
Date: Thu, 5 Jun 2025 14:39:48 +0000
Message-ID: <ee4940c99e9866910405b492dad15c68718c49ea.camel@groupe-cyllene.com>
Am 03.06.25 um 09:55 schrieb Alexandre Derumier via pve-devel:
> +sub encode_nodename {
> + my ($type, $volid, $snap) = @_;
> +
> + my $nodename = "$volid";
> + $nodename .= "-$snap" if $snap;
This will lead to clashes in some cases:
>>1. Currently, we allow attaching the same volume multiple times to a
>>single guest.
do you mean, manually with editing the vm configuration ? What is the
usecase ? (I mean, without breaking the fs because the drive could be
mounted twice )
(the vm will not start if node-name is duplicated, so it's look more
secure now ^_^)
>>2. You can end up with the same name for
>>volname = vm-1234-disk-0-foo
>>and for
>>volname = vm-1234-disk-0, snap = foo
>>
>>The latter can be rather easily fixed by just using a character we
>>don't
>>usually support for volume names, but not the former.
we could also generate the full path= , and encode it
>> So I'd like to do
>>the switch to -blockdev without support for "looking up which node a
>>certain volume is" at first.
yes, if you find a way to do it , could be better !
>>In general, I feel like mixing the switch
>>to -blockdev with your larger series is too much at once.
>>We should
>>first get the switch to -blockdev completely and cleanly sorted out,
>>then we can add your external qcow2 support on top.
yes sure. (the qcow2 snap are only the last 2 patches anyway, and they
still are a lot of work on the backup side, but I really don't known
how the specific proxmox patches are working , so help is welcome ;)
>>I think we can even rely on auto-generated-by-QEMU node names at
>>first.
The main blocking problem is that auto-generated #block name are not
working with some block action. (if I remember, the drive-reopen wasn't
working correctly, so this was a blocker for snapshots).
I need to retest because in early patches, I was reopening the file
node, and now the format-node, so maybe the behaviour is different now
They are also different behaviour is node-name are defined or notto the
command-line on blockdev-remove. (for example, sometime you remove the
top-node, the format+file node can be autoremove or not, also the
backing chain)
I really don't known if it's qemu bug or not. (I don't have digged the
qemu code)
>>We can later switch to a variant where node names encode additional
>>information. Or we could also think about patching QEMU to better fit
>>the need for the "looking up which node a certain volume is" feature.
>>But I don't think figuring this out should block us right now for the
>>switch to "-blockdev".
you are better than me for this, my C skill is pretty poor ^_^
>>I'll try to work out a series that focuses just on the switch to
>>"-blockdev" based on your patches during the next week or so. Maybe
>>not
>>much else needs to be changed :) The work is certainly greatly
>>appreciated!
Great! Tell me if it needed testing. (my patches should cover all basic
actions excluding backup)
I'm currently working to add tests for all live action
(hotplug/unplug,cdeject,mirror,snap,...but until it's done, I can help
with manually testing.
I'll be on holiday from arund 15th July (for 3 weeks),but until that
I'm also full-time free to work on it and help.
Alexandre
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support
[not found] ` <ee4940c99e9866910405b492dad15c68718c49ea.camel@groupe-cyllene.com>
@ 2025-06-06 7:50 ` Fiona Ebner
2025-06-06 8:27 ` Fabian Grünbichler
0 siblings, 1 reply; 39+ messages in thread
From: Fiona Ebner @ 2025-06-06 7:50 UTC (permalink / raw)
To: DERUMIER, Alexandre, pve-devel
Am 05.06.25 um 16:39 schrieb DERUMIER, Alexandre:
> Am 03.06.25 um 09:55 schrieb Alexandre Derumier via pve-devel:
>> +sub encode_nodename {
>> + my ($type, $volid, $snap) = @_;
>> +
>> + my $nodename = "$volid";
>> + $nodename .= "-$snap" if $snap;
>
> This will lead to clashes in some cases:
>>> 1. Currently, we allow attaching the same volume multiple times to a
>>> single guest.
> do you mean, manually with editing the vm configuration ? What is the
> usecase ? (I mean, without breaking the fs because the drive could be
> mounted twice )
> (the vm will not start if node-name is duplicated, so it's look more
> secure now ^_^)
No manual editing needed, just use "qm set" twice with the same volume
;) Sure, those are most likely quite exotic use cases. If we want to, we
could go ahead an prohibit this for PVE 9. There always is the -args
escape hatch for people that really need it. Would also avoid cases
where it's done accidentally, so I'm not opposed to this. We'd need to
document it as a breaking change in the upgrade guide and add a check to
the pve8to9 script.
>>> 2. You can end up with the same name for
>>> volname = vm-1234-disk-0-foo
>>> and for
>>> volname = vm-1234-disk-0, snap = foo
>>>
>>> The latter can be rather easily fixed by just using a character we
>>> don't
>>> usually support for volume names, but not the former.
> we could also generate the full path= , and encode it
Volume ID + snapshot should already be unique, we just need to
separate/map it in such a way that it cannot be confused as a volume ID
when there is a snapshot. E.g. could also be the encoding of the string
"snap=Y,volid=X". Using the full QEMU path seems overly involved.
>>> I think we can even rely on auto-generated-by-QEMU node names at
>>> first.
>
> The main blocking problem is that auto-generated #block name are not
> working with some block action. (if I remember, the drive-reopen wasn't
> working correctly, so this was a blocker for snapshots).
> I need to retest because in early patches, I was reopening the file
> node, and now the format-node, so maybe the behaviour is different now
>
>
> They are also different behaviour is node-name are defined or notto the
> command-line on blockdev-remove. (for example, sometime you remove the
> top-node, the format+file node can be autoremove or not, also the
> backing chain)
>
> I really don't known if it's qemu bug or not. (I don't have digged the
> qemu code)
Hmm, will have to look into this. For top-level nodes, it's required to
specify an explicit node-name in any case.
>>> I'll try to work out a series that focuses just on the switch to
>>> "-blockdev" based on your patches during the next week or so. Maybe
>>> not
>>> much else needs to be changed :) The work is certainly greatly
>>> appreciated!
>
> Great! Tell me if it needed testing. (my patches should cover all basic
> actions excluding backup)
Sure, testing is always appreciated! I'll focus on this and hope to get
a version out by the end of next week.
> I'm currently working to add tests for all live action
> (hotplug/unplug,cdeject,mirror,snap,...but until it's done, I can help
> with manually testing.
Such automatic tests would be very nice to have indeed! Even better if
we have the tests before the switch to blockdev is applied, so we can
check that the behavior is still the same :)
Best Regards,
Fiona
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support
2025-06-06 7:50 ` Fiona Ebner
@ 2025-06-06 8:27 ` Fabian Grünbichler
2025-06-06 9:54 ` DERUMIER, Alexandre via pve-devel
0 siblings, 1 reply; 39+ messages in thread
From: Fabian Grünbichler @ 2025-06-06 8:27 UTC (permalink / raw)
To: Fiona Ebner, DERUMIER, Alexandre, pve-devel
> Fiona Ebner <f.ebner@proxmox.com> hat am 06.06.2025 09:50 CEST geschrieben:
>
>
> Am 05.06.25 um 16:39 schrieb DERUMIER, Alexandre:
> > Am 03.06.25 um 09:55 schrieb Alexandre Derumier via pve-devel:
> >> +sub encode_nodename {
> >> + my ($type, $volid, $snap) = @_;
> >> +
> >> + my $nodename = "$volid";
> >> + $nodename .= "-$snap" if $snap;
> >
> > This will lead to clashes in some cases:
> >>> 1. Currently, we allow attaching the same volume multiple times to a
> >>> single guest.
> > do you mean, manually with editing the vm configuration ? What is the
> > usecase ? (I mean, without breaking the fs because the drive could be
> > mounted twice )
> > (the vm will not start if node-name is duplicated, so it's look more
> > secure now ^_^)
>
> No manual editing needed, just use "qm set" twice with the same volume
> ;) Sure, those are most likely quite exotic use cases. If we want to, we
> could go ahead an prohibit this for PVE 9. There always is the -args
> escape hatch for people that really need it. Would also avoid cases
> where it's done accidentally, so I'm not opposed to this. We'd need to
> document it as a breaking change in the upgrade guide and add a check to
> the pve8to9 script.
it is very handy for testing multipath ;) we could add the "slot" to the
input for deriving the node name?
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support Alexandre Derumier via pve-devel
2025-06-05 13:23 ` Fiona Ebner
@ 2025-06-06 8:50 ` Fiona Ebner
2025-06-06 9:42 ` DERUMIER, Alexandre via pve-devel
[not found] ` <0605a27428cfb920ffefc51abdfec050a0a6b535.camel@groupe-cyllene.com>
2025-06-10 14:03 ` Fiona Ebner
2 siblings, 2 replies; 39+ messages in thread
From: Fiona Ebner @ 2025-06-06 8:50 UTC (permalink / raw)
To: Proxmox VE development discussion
Am 03.06.25 um 09:55 schrieb Alexandre Derumier via pve-devel:
> +sub generate_blockdev_drive_aio {
> + my ($drive, $scfg) = @_;
> +
> + my $cache_direct = drive_uses_cache_direct($drive, $scfg);
> + $drive->{aio} = 'threads' if drive_is_cdrom($drive);
We didn't force aio=threads for CD-ROMs before. In principle, it could
be fine (I'm going with the version guarded approach), but could you
provide some rationale for this change?
> + my $aio = $drive->{aio};
> + if (!$aio) {
> + if (storage_allows_io_uring_default($scfg, $cache_direct)) {
> + # io_uring supports all cache modes
> + $aio = "io_uring";
> + } else {
> + # aio native works only with O_DIRECT
> + if($cache_direct) {
> + $aio = "native";
> + } else {
> + $aio = "threads";
> + }
> + }
> + }
> + return $aio;
> +}
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support
2025-06-06 8:50 ` Fiona Ebner
@ 2025-06-06 9:42 ` DERUMIER, Alexandre via pve-devel
[not found] ` <0605a27428cfb920ffefc51abdfec050a0a6b535.camel@groupe-cyllene.com>
1 sibling, 0 replies; 39+ messages in thread
From: DERUMIER, Alexandre via pve-devel @ 2025-06-06 9:42 UTC (permalink / raw)
To: pve-devel, f.ebner; +Cc: DERUMIER, Alexandre
[-- Attachment #1: Type: message/rfc822, Size: 13239 bytes --]
From: "DERUMIER, Alexandre" <alexandre.derumier@groupe-cyllene.com>
To: "pve-devel@lists.proxmox.com" <pve-devel@lists.proxmox.com>, "f.ebner@proxmox.com" <f.ebner@proxmox.com>
Subject: Re: [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support
Date: Fri, 6 Jun 2025 09:42:03 +0000
Message-ID: <0605a27428cfb920ffefc51abdfec050a0a6b535.camel@groupe-cyllene.com>
Am 03.06.25 um 09:55 schrieb Alexandre Derumier via pve-devel:
> +sub generate_blockdev_drive_aio {
> + my ($drive, $scfg) = @_;
> +
> + my $cache_direct = drive_uses_cache_direct($drive, $scfg);
> + $drive->{aio} = 'threads' if drive_is_cdrom($drive);
>>We didn't force aio=threads for CD-ROMs before. In principle, it
>>could
>>be fine (I'm going with the version guarded approach), but could you
>>provide some rationale for this change?
ah, indeed. I think I'll use the ide.conf test to verify (this is the
only test with cdrom medias attached, and it's using cifs-store, where
io_uring is disabled).
should be io_uring or threads if storage don't support io_uring.
I'll fix it, and improve tests with cdrom on differents storage
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support
2025-06-06 8:27 ` Fabian Grünbichler
@ 2025-06-06 9:54 ` DERUMIER, Alexandre via pve-devel
0 siblings, 0 replies; 39+ messages in thread
From: DERUMIER, Alexandre via pve-devel @ 2025-06-06 9:54 UTC (permalink / raw)
To: pve-devel, f.ebner, f.gruenbichler; +Cc: DERUMIER, Alexandre
[-- Attachment #1: Type: message/rfc822, Size: 13663 bytes --]
From: "DERUMIER, Alexandre" <alexandre.derumier@groupe-cyllene.com>
To: "pve-devel@lists.proxmox.com" <pve-devel@lists.proxmox.com>, "f.ebner@proxmox.com" <f.ebner@proxmox.com>, "f.gruenbichler@proxmox.com" <f.gruenbichler@proxmox.com>
Subject: Re: [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support
Date: Fri, 6 Jun 2025 09:54:05 +0000
Message-ID: <cec1b6bc4e24f3c7c3b8508b767999b00baf7773.camel@groupe-cyllene.com>
>
> No manual editing needed, just use "qm set" twice with the same
> volume
> ;) Sure, those are most likely quite exotic use cases. If we want to,
> we
> could go ahead an prohibit this for PVE 9. There always is the -args
> escape hatch for people that really need it. Would also avoid cases
> where it's done accidentally, so I'm not opposed to this. We'd need
> to
> document it as a breaking change in the upgrade guide and add a check
> to
> the pve8to9 script.
>>it is very handy for testing multipath ;)
Well, indeed, that can be an usecase. (if you don't use qcow2,
snapshots, cache=writeback, ceph rbd with exclusive lock, .... ;)
>> we could add the "slot" to the input for deriving the node name?
I wait fiona the decision for the node-name :)
(for slot, one way could be to append deviceid (ide0, virtio0,..) in
the encoded nodename)
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support
[not found] ` <0605a27428cfb920ffefc51abdfec050a0a6b535.camel@groupe-cyllene.com>
@ 2025-06-06 10:57 ` DERUMIER, Alexandre via pve-devel
0 siblings, 0 replies; 39+ messages in thread
From: DERUMIER, Alexandre via pve-devel @ 2025-06-06 10:57 UTC (permalink / raw)
To: pve-devel, f.ebner; +Cc: DERUMIER, Alexandre
[-- Attachment #1: Type: message/rfc822, Size: 13587 bytes --]
From: "DERUMIER, Alexandre" <alexandre.derumier@groupe-cyllene.com>
To: "pve-devel@lists.proxmox.com" <pve-devel@lists.proxmox.com>, "f.ebner@proxmox.com" <f.ebner@proxmox.com>
Subject: Re: [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support
Date: Fri, 6 Jun 2025 10:57:41 +0000
Message-ID: <6f26508c39c68abcebb0a59d3e149ff1164485d1.camel@groupe-cyllene.com>
>>
>>ah, indeed. I think I'll use the ide.conf test to verify (this is the
>>only test with cdrom medias attached, and it's using cifs-store,
>>where
>>io_uring is disabled).
>>
>>should be io_uring or threads if storage don't support io_uring.
>>
>>I'll fix it, and improve tests with cdrom on differents storage
Thinking about that, it could be interesting that the storage plugin
return if io_uring is supported or not, as it's currently hardcoded
in qemu-server
(I have send test patch)
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support Alexandre Derumier via pve-devel
2025-06-05 13:23 ` Fiona Ebner
2025-06-06 8:50 ` Fiona Ebner
@ 2025-06-10 14:03 ` Fiona Ebner
2025-06-11 6:37 ` DERUMIER, Alexandre via pve-devel
[not found] ` <405662415075c0248618833b512b58258f80e0f7.camel@groupe-cyllene.com>
2 siblings, 2 replies; 39+ messages in thread
From: Fiona Ebner @ 2025-06-10 14:03 UTC (permalink / raw)
To: Proxmox VE development discussion
The way the node name encoding is implemented is problematic as we
operate outside of integer ranges:
[I] febner@dev8 ~/repos/pve/qemu-server (qemu-blockdev-options)> cat asdf.pm
use strict;
use warnings;
use Digest::SHA;
sub encode_base62 {
my ($input) = @_;
my @chars = ('0'..'9', 'A'..'Z', 'a'..'z');
my $base = 62;
my $value = 0;
my $result = '';
for my $byte (unpack('C*', $input)) {
$value = $value * 256 + $byte;
print "$value\n";
}
}
encode_base62(Digest::SHA::sha1("foo"));
[I] febner@dev8 ~/repos/pve/qemu-server (qemu-blockdev-options)> perl
asdf.pm
11
3054
782023
200198069
51250705898
13120180709951
3358766261747471
859844163007352795
2.20120105729882e+20
5.63507470668499e+22
1.44257912491136e+25
3.69300255977307e+27
9.45408655301907e+29
2.42024615757288e+32
6.19583016338658e+34
1.58613252182696e+37
4.06049925587703e+39
1.03948780950452e+42
2.66108879233157e+44
6.81238730836881e+46
Also, while the use case here shouldn't be cryptographically sensitive,
you never know, so I'll just use a different hash function than sha1.
I'll cut off the result from that hash to 30 hex digits. Then we still
have one letter for the prefix of the node name.
As for collision probability, that will be 120 bits and should be more
than enough, even 2^50 nodes have a very small probability to collide
with that:
>>> math.log2(16**30)
120.0
>>> d=2**120
>>> n=2**50
>>> 1 - math.exp(-(n*n)/(2*d))
4.768370445162873e-07
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support
2025-06-10 14:03 ` Fiona Ebner
@ 2025-06-11 6:37 ` DERUMIER, Alexandre via pve-devel
[not found] ` <405662415075c0248618833b512b58258f80e0f7.camel@groupe-cyllene.com>
1 sibling, 0 replies; 39+ messages in thread
From: DERUMIER, Alexandre via pve-devel @ 2025-06-11 6:37 UTC (permalink / raw)
To: pve-devel, f.ebner; +Cc: DERUMIER, Alexandre
[-- Attachment #1: Type: message/rfc822, Size: 13191 bytes --]
From: "DERUMIER, Alexandre" <alexandre.derumier@groupe-cyllene.com>
To: "pve-devel@lists.proxmox.com" <pve-devel@lists.proxmox.com>, "f.ebner@proxmox.com" <f.ebner@proxmox.com>
Subject: Re: [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support
Date: Wed, 11 Jun 2025 06:37:14 +0000
Message-ID: <405662415075c0248618833b512b58258f80e0f7.camel@groupe-cyllene.com>
>>Also, while the use case here shouldn't be cryptographically
>>sensitive,
>>you never know, so I'll just use a different hash function than sha1.
>>I'll cut off the result from that hash to 30 hex digits. Then we
>>still
>>have one letter for the prefix of the node name.
so, maybe something like :
$digest = substr(sha256_hex("${volname}+${snap}"),0,30);
?
I still unsure how to handle same volume multiple time (if we really
want it). I was thinking to use the deviceid in the name (virtio0,..),
but it don't work when you unplug/replug to a deviceid.
Maybe some kind of slot number like fabian have suggested, but I think
it'll need some kind of lookup.
or maybe, if we want same volume multiple volume, we just keep
autogenerated qemu blockdev for this specific case, as anyway, we can't
do snapshot, unplug, or other dynamic features.
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support
[not found] ` <405662415075c0248618833b512b58258f80e0f7.camel@groupe-cyllene.com>
@ 2025-06-11 7:24 ` Fiona Ebner
2025-06-11 14:02 ` DERUMIER, Alexandre via pve-devel
[not found] ` <733f5eefb25b76a0794a84d4f93ada8d70aea7be.camel@groupe-cyllene.com>
0 siblings, 2 replies; 39+ messages in thread
From: Fiona Ebner @ 2025-06-11 7:24 UTC (permalink / raw)
To: DERUMIER, Alexandre, pve-devel
Am 11.06.25 um 08:37 schrieb DERUMIER, Alexandre:
>>> Also, while the use case here shouldn't be cryptographically
>>> sensitive,
>>> you never know, so I'll just use a different hash function than sha1.
>>> I'll cut off the result from that hash to 30 hex digits. Then we
>>> still
>>> have one letter for the prefix of the node name.
>
> so, maybe something like :
>
> $digest = substr(sha256_hex("${volname}+${snap}"),0,30);
>
> ?
>
>
> I still unsure how to handle same volume multiple time (if we really
> want it). I was thinking to use the deviceid in the name (virtio0,..),
> but it don't work when you unplug/replug to a deviceid.
Why wouldn't it work?
> Maybe some kind of slot number like fabian have suggested, but I think
> it'll need some kind of lookup.
>
> or maybe, if we want same volume multiple volume, we just keep
> autogenerated qemu blockdev for this specific case, as anyway, we can't
> do snapshot, unplug, or other dynamic features.
My proposal is:
my sub get_node_name {
my ($type, $drive_id, $volid, $snap) = @_;
my $info = "drive=$drive_id,";
$info .= "snap=$snap," if defined($snap);
$info .= "volid=$volid";
my $encoded = substr(Digest::SHA::sha256_hex($info), 0, 30);
my $prefix = "";
if ($type eq 'fmt') {
$prefix = 'f';
} elsif ($type eq 'file') {
$prefix = 'e';
} else {
die "unknown node type '$type'";
}
# node-name must start with an alphabetical character
return "${prefix}${encoded}";
}
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support
2025-06-11 7:24 ` Fiona Ebner
@ 2025-06-11 14:02 ` DERUMIER, Alexandre via pve-devel
[not found] ` <733f5eefb25b76a0794a84d4f93ada8d70aea7be.camel@groupe-cyllene.com>
1 sibling, 0 replies; 39+ messages in thread
From: DERUMIER, Alexandre via pve-devel @ 2025-06-11 14:02 UTC (permalink / raw)
To: pve-devel, f.ebner; +Cc: DERUMIER, Alexandre
[-- Attachment #1: Type: message/rfc822, Size: 14087 bytes --]
From: "DERUMIER, Alexandre" <alexandre.derumier@groupe-cyllene.com>
To: "pve-devel@lists.proxmox.com" <pve-devel@lists.proxmox.com>, "f.ebner@proxmox.com" <f.ebner@proxmox.com>
Subject: Re: [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support
Date: Wed, 11 Jun 2025 14:02:27 +0000
Message-ID: <733f5eefb25b76a0794a84d4f93ada8d70aea7be.camel@groupe-cyllene.com>
> >
> >>
> >I still unsure how to handle same volume multiple time (if we really
> >want it). I was thinking to use the deviceid in the name
> >(virtio0,..),
> >but it don't work when you unplug/replug to a deviceid.
>>Why wouldn't it work?
Ah sorry, I forgot that we delete the blocknode on unplug.
so it should work indeed
> Maybe some kind of slot number like fabian have suggested, but I
> think
> it'll need some kind of lookup.
>
> or maybe, if we want same volume multiple volume, we just keep
> autogenerated qemu blockdev for this specific case, as anyway, we
> can't
> do snapshot, unplug, or other dynamic features.
>>My proposal is:
>>
>>my sub get_node_name {
>> my ($type, $drive_id, $volid, $snap) = @_;
>>
>> my $info = "drive=$drive_id,";
>> $info .= "snap=$snap," if defined($snap);
>> $info .= "volid=$volid";
>>
>> my $encoded = substr(Digest::SHA::sha256_hex($info), 0, 30);
>>
>> my $prefix = "";
>> if ($type eq 'fmt') {
>> $prefix = 'f';
>> } elsif ($type eq 'file') {
>> $prefix = 'e';
>> } else {
>> die "unknown node type '$type'";
>> }
>> # node-name must start with an alphabetical character
>> return "${prefix}${encoded}";
>>}
Ok !
I'm going to test it like this
(I'll be busy with proxmox training tomorrow && friday, so I'll rework
on it next week)
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support
[not found] ` <733f5eefb25b76a0794a84d4f93ada8d70aea7be.camel@groupe-cyllene.com>
@ 2025-06-11 14:13 ` Fiona Ebner
2025-06-12 5:20 ` DERUMIER, Alexandre via pve-devel
0 siblings, 1 reply; 39+ messages in thread
From: Fiona Ebner @ 2025-06-11 14:13 UTC (permalink / raw)
To: DERUMIER, Alexandre, pve-devel
Am 11.06.25 um 16:02 schrieb DERUMIER, Alexandre:
> (I'll be busy with proxmox training tomorrow && friday, so I'll rework
> on it next week)
I did mention in an earlier mail that I'm already working on a series
for the switch to blockdev based on your patches myself. Sorry, if that
wasn't clear! I'm planning to send an initial version tomorrow with
mostly preparation which should be possible to apply up-front.
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support
2025-06-11 14:13 ` Fiona Ebner
@ 2025-06-12 5:20 ` DERUMIER, Alexandre via pve-devel
0 siblings, 0 replies; 39+ messages in thread
From: DERUMIER, Alexandre via pve-devel @ 2025-06-12 5:20 UTC (permalink / raw)
To: pve-devel, f.ebner; +Cc: DERUMIER, Alexandre
[-- Attachment #1: Type: message/rfc822, Size: 13841 bytes --]
From: "DERUMIER, Alexandre" <alexandre.derumier@groupe-cyllene.com>
To: "pve-devel@lists.proxmox.com" <pve-devel@lists.proxmox.com>, "f.ebner@proxmox.com" <f.ebner@proxmox.com>
Subject: Re: [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support
Date: Thu, 12 Jun 2025 05:20:59 +0000
Message-ID: <e4ba117800b41e357051004bf27a0b21ce0c1222.camel@groupe-cyllene.com>
Am 11.06.25 um 16:02 schrieb DERUMIER, Alexandre:
> (I'll be busy with proxmox training tomorrow && friday, so I'll
> rework
> on it next week)
>>I did mention in an earlier mail that I'm already working on a series
>>for the switch to blockdev based on your patches myself. Sorry, if
>>that
>>wasn't clear! I'm planning to send an initial version tomorrow with
>>mostly preparation which should be possible to apply up-front.
Ah ok, I was waiting for it, but I didn't known that it was based on my
patches. Thanks for the precision !
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [pve-devel] [PATCH qemu-server 03/13] blockdev: vm_devices_list : fix block-query
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 03/13] blockdev: vm_devices_list : fix block-query Alexandre Derumier via pve-devel
@ 2025-06-17 14:44 ` Fiona Ebner
0 siblings, 0 replies; 39+ messages in thread
From: Fiona Ebner @ 2025-06-17 14:44 UTC (permalink / raw)
To: Proxmox VE development discussion
Am 03.06.25 um 09:55 schrieb Alexandre Derumier via pve-devel:
>
> Look at qdev value, as cdrom drives can be empty
> without any inserted media
>
> Signed-off-by: Alexandre Derumier <alexandre.derumier@groupe-cyllene.com>
> ---
> PVE/QemuServer.pm | 17 ++++++++++++++---
> 1 file changed, 14 insertions(+), 3 deletions(-)
>
> diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
> index a27dcabb..b15b05aa 100644
> --- a/PVE/QemuServer.pm
> +++ b/PVE/QemuServer.pm
> @@ -4061,11 +4061,22 @@ sub vm_devices_list {
> $devices_to_check = $to_check;
> }
>
> + # block devices need to be queried at qdev level, as a device
> + # don't always have a blockdev drive media attached (cdrom for example).
> + # Also top node of the graph could have a different name than the device
> + # (we still use "drive-$deviceid" for throttle filter, but it's not 100% safe
> + # if we change that in the future
> my $resblock = mon_cmd($vmid, 'query-block');
> foreach my $block (@$resblock) {
> - if($block->{device} =~ m/^drive-(\S+)/){
But this is already looking at the device ID, not the block node
name. AFAICS, the function does always work for -drive, but never for
-blockdev, regardless of the presence of a media. So I'm a bit confused
by the comment and commit message.
That said, the change itself looks good to me. I slightly adapted it and
will pick it up for v2 of the preparatory series with the following
commit message:
vm devices list: prepare querying block device names for -blockdev
Look at the 'qdev' value, because the 'device' property is not
initialized with '-blockdev'. This can be seen in the QEMU source code
(the device property is the name of the block backend and blk->name is
assigned a value only in a code path reached via drive_new()). This
most likely was done to avoid confusion/clashes, since with
'-blockdev', the node that's inserted for a front-end device can
change and then both the block backend and the node would be named
the same, but not connected.
> - $devices->{$1} = 1;
> - }
> + my $qdev_id = $block->{qdev};
> + if ($qdev_id =~ m|^/machine/peripheral/(virtio(\d+))/virtio-backend$|) {
> + $qdev_id = $1;
> + } elsif ($qdev_id =~ m|^/machine/system.flash0$|) {
> + $qdev_id = 'pflash0';
> + } elsif ($qdev_id =~ m|^/machine/system.flash1$|) {
> + $qdev_id = 'efidisk0';
> + }
> + $devices->{$qdev_id} = 1 if $qdev_id;
> }
>
> my $resmice = mon_cmd($vmid, 'query-mice');
> --
> 2.39.5
>
>
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 39+ messages in thread
end of thread, other threads:[~2025-06-17 14:44 UTC | newest]
Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <20250603075558.627850-1-alexandre.derumier@groupe-cyllene.com>
2025-06-03 7:55 ` [pve-devel] [PATCH pve-qemu 1/1] add fake 10.0 Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 01/13] blockdev: cmdline: add blockdev syntax support Alexandre Derumier via pve-devel
2025-06-05 13:23 ` Fiona Ebner
2025-06-05 14:17 ` Fabian Grünbichler
2025-06-05 14:39 ` DERUMIER, Alexandre via pve-devel
[not found] ` <ee4940c99e9866910405b492dad15c68718c49ea.camel@groupe-cyllene.com>
2025-06-06 7:50 ` Fiona Ebner
2025-06-06 8:27 ` Fabian Grünbichler
2025-06-06 9:54 ` DERUMIER, Alexandre via pve-devel
2025-06-06 8:50 ` Fiona Ebner
2025-06-06 9:42 ` DERUMIER, Alexandre via pve-devel
[not found] ` <0605a27428cfb920ffefc51abdfec050a0a6b535.camel@groupe-cyllene.com>
2025-06-06 10:57 ` DERUMIER, Alexandre via pve-devel
2025-06-10 14:03 ` Fiona Ebner
2025-06-11 6:37 ` DERUMIER, Alexandre via pve-devel
[not found] ` <405662415075c0248618833b512b58258f80e0f7.camel@groupe-cyllene.com>
2025-06-11 7:24 ` Fiona Ebner
2025-06-11 14:02 ` DERUMIER, Alexandre via pve-devel
[not found] ` <733f5eefb25b76a0794a84d4f93ada8d70aea7be.camel@groupe-cyllene.com>
2025-06-11 14:13 ` Fiona Ebner
2025-06-12 5:20 ` DERUMIER, Alexandre via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH pve-storage 1/9] common: add qemu_img_create an preallocation_cmd_option Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 02/13] blockdev: add support for ovmf && efidisk Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH pve-storage 2/9] common: add qemu_img_create_qcow2_backed Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 03/13] blockdev: vm_devices_list : fix block-query Alexandre Derumier via pve-devel
2025-06-17 14:44 ` Fiona Ebner
2025-06-03 7:55 ` [pve-devel] [PATCH pve-storage 3/9] common: add qemu_img_info helper Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 04/13] blockdev: add support to qemu_driveadd && qemu_drivedel Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH pve-storage 4/9] common: add qemu_img_measure Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 05/13] blockdev: add support to qemu_block_set_io_throttle Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH pve-storage 5/9] rename_volume: add source && target snap Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 06/13] blockdev: add support for cdrom media eject/insert Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH pve-storage 6/9] storage: volume_snapshot: add $running param + api bump Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 07/13] blockdev: add support for block_resize Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH pve-storage 7/9] qcow2: add external snapshot support Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 08/13] blockdev: add support for nbd_export: block-export-add Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH pve-storage 8/9] lvmplugin: add qcow2 snapshot Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 09/13] blockdev: add blockdev_mirror Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH pve-storage 9/9] storage: add volume_support_qemu_snapshot Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 10/13] blockdev: change aio on target if io_uring is not default Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 11/13] qemu_img convert : add external snapshot support Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 12/13] blockdev: add backing_chain support Alexandre Derumier via pve-devel
2025-06-03 7:55 ` [pve-devel] [PATCH qemu-server 13/13] qcow2: add external snapshot support Alexandre Derumier via pve-devel
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