* [pve-devel] [PATCH-SERIES qemu 0/2] update submodule and patches to QEMU 10.0.2
@ 2025-06-02 10:22 Fiona Ebner
2025-06-02 10:22 ` [pve-devel] [PATCH qemu 1/2] " Fiona Ebner
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Fiona Ebner @ 2025-06-02 10:22 UTC (permalink / raw)
To: pve-devel
Only minor changes this time:
Adapt to changed include paths:
32cad1ffb8 ("include: Rename sysemu/ -> system/")
407bc4bf90 ("qapi: Move include/qapi/qmp/ to include/qobject/")
Adapt to a function signature change:
4822128693 ("migration: Drop inactivate_disk param in
qemu_savevm_state_complete*")
Also squash some related patches.
Fiona Ebner (2):
update submodule and patches to QEMU 10.0.2
squash some related patches
...d-support-for-sync-bitmap-mode-never.patch | 30 +-
...-support-for-conditional-and-always-.patch | 2 +-
...check-for-bitmap-mode-without-bitmap.patch | 4 +-
...-to-bdrv_dirty_bitmap_merge_internal.patch | 2 +-
.../0006-mirror-move-some-checks-to-qmp.patch | 6 +-
...race-with-clients-disconnecting-earl.patch | 8 +-
...ial-deadlock-when-draining-during-tr.patch | 2 +-
...Reset-free_temps-before-tcg_optimize.patch | 82 --
...t-TSCs-of-parked-vCPUs-too-on-VM-res.patch | 149 ---
...x10_version-filtered-when-prefix-is-.patch | 41 -
.../extra/0006-net-Fix-announce_self.patch | 67 --
...ectly-compute-Ethernet-packet-offset.patch | 67 --
...-Windows-PCI-Label-Id-bug-workaround.patch | 96 --
...pci-Use-modulo-to-select-MSI-vector-.patch | 53 --
...-link-status-bits-for-downstream-por.patch | 63 --
...x-pba-read-vector-poll-end-calculati.patch | 36 -
...k-file-change-locking-default-to-off.patch | 6 +-
...he-CPU-model-to-kvm64-32-instead-of-.patch | 4 +-
...ui-spice-default-to-pve-certificates.patch | 2 +-
...erfs-no-default-logfile-if-daemonize.patch | 2 +-
...lock-rbd-disable-rbd_cache_writethro.patch | 2 +-
...PVE-Up-glusterfs-allow-partial-reads.patch | 2 +-
...return-success-on-info-without-snaps.patch | 2 +-
...dd-add-osize-and-read-from-to-stdin-.patch | 12 +-
...E-Up-qemu-img-dd-add-isize-parameter.patch | 14 +-
...PVE-Up-qemu-img-dd-add-n-skip_create.patch | 10 +-
...-add-l-option-for-loading-a-snapshot.patch | 14 +-
...virtio-balloon-improve-query-balloon.patch | 4 +-
.../0014-PVE-qapi-modify-query-machines.patch | 8 +-
.../0015-PVE-qapi-modify-spice-query.patch | 4 +-
...nnel-implementation-for-savevm-async.patch | 14 +-
...async-for-background-state-snapshots.patch | 167 ++--
...add-optional-buffer-size-to-QEMUFile.patch | 58 +-
...add-the-zeroinit-block-driver-filter.patch | 8 +-
...-Add-dummy-id-command-line-parameter.patch | 10 +-
...t-target-i386-disable-LINT0-after-re.patch | 2 +-
...le-posix-make-locking-optiono-on-cre.patch | 20 +-
...3-PVE-monitor-disable-oob-capability.patch | 2 +-
...sed-balloon-qemu-4-0-config-size-fal.patch | 4 +-
...E-Allow-version-code-in-machine-type.patch | 18 +-
...e-bcs-bitmap-initialization-to-job-c.patch | 2 +-
...VE-Backup-add-vma-backup-format-code.patch | 18 +-
...-Backup-add-backup-dump-block-driver.patch | 12 +-
...d-sequential-job-transaction-support.patch | 8 +-
...ckup-Proxmox-backup-patches-for-QEMU.patch | 64 +-
...estore-new-command-to-restore-from-p.patch | 10 +-
...k-driver-to-map-backup-archives-into.patch | 20 +-
...ct-stderr-to-journal-when-daemonized.patch | 8 +-
...igrate-dirty-bitmap-state-via-savevm.patch | 26 +-
...dirty-bitmap-migrate-other-bitmaps-e.patch | 2 +-
...all-back-to-open-iscsi-initiatorname.patch | 2 +-
...PVE-block-stream-increase-chunk-size.patch | 2 +-
.../0038-block-add-alloc-track-driver.patch | 56 +-
...-rbd-workaround-for-ceph-issue-53784.patch | 2 +-
...-fix-handling-of-holes-in-.bdrv_co_b.patch | 2 +-
...k-rbd-implement-bdrv_co_block_status.patch | 2 +-
...0042-PVE-backup-add-fleecing-option.patch} | 291 ++++--
...rror-out-when-auto-remove-is-not-set.patch | 43 -
...-version-deprecation-for-Proxmox-VE.patch} | 8 +-
...d-seemingly-superfluous-child-permis.patch | 84 --
...oid-timer-storms-on-periodic-timers.patch} | 8 +-
...ve-error-when-copy-before-write-fail.patch | 117 ---
...-full-64-bit-target-value-of-the-co.patch} | 25 +-
...up-fixup-error-handling-for-fleecing.patch | 103 --
...hpet-accept-64-bit-reads-and-writes.patch} | 26 +-
...r-out-setting-up-snapshot-access-for.patch | 135 ---
...-read-only-bits-directly-in-new_val.patch} | 10 +-
...device-name-in-device-info-structure.patch | 135 ---
...t-remove-unnecessary-variable-index.patch} | 10 +-
...de-device-name-in-error-when-setting.patch | 25 -
...e-high-bits-of-comparator-in-32-bit.patch} | 6 +-
...nd-cleanup-persistence-of-interrupt.patch} | 10 +-
...-out-helper-to-clear-backup-state-s.patch} | 2 +-
...-out-helper-to-initialize-backup-st.patch} | 2 +-
...ackup-add-target-ID-in-backup-state.patch} | 2 +-
...vice-info-allow-caller-to-specify-f.patch} | 2 +-
...ment-backup-access-setup-and-teardow.patch | 898 ++++++++++++++++++
...rove-setting-state-of-snapshot-opera.patch | 81 --
...ame-saved_vm_running-to-vm_needs_sta.patch | 71 --
...rove-runstate-preservation-cleanup-e.patch | 120 ---
...se-dedicated-iothread-for-state-file.patch | 185 ----
...at-failure-to-set-iothread-context-a.patch | 33 -
...-up-directly-in-setup_snapshot_acces.patch | 41 -
...ment-backup-access-setup-and-teardow.patch | 495 ----------
...or-out-get_single_device_info-helper.patch | 122 ---
...ment-bitmap-support-for-external-bac.patch | 470 ---------
...p-access-api-indicate-situation-wher.patch | 57 --
...p-access-api-explicit-bitmap-mode-pa.patch | 84 --
...kup-access-api-simplify-bitmap-logic.patch | 206 ----
debian/patches/series | 55 +-
qemu | 2 +-
91 files changed, 1519 insertions(+), 3778 deletions(-)
delete mode 100644 debian/patches/extra/0003-tcg-Reset-free_temps-before-tcg_optimize.patch
delete mode 100644 debian/patches/extra/0004-target-i386-Reset-TSCs-of-parked-vCPUs-too-on-VM-res.patch
delete mode 100644 debian/patches/extra/0005-i386-cpu-Mark-avx10_version-filtered-when-prefix-is-.patch
delete mode 100644 debian/patches/extra/0006-net-Fix-announce_self.patch
delete mode 100644 debian/patches/extra/0007-net-dump-Correctly-compute-Ethernet-packet-offset.patch
delete mode 100644 debian/patches/extra/0008-pci-acpi-Windows-PCI-Label-Id-bug-workaround.patch
delete mode 100644 debian/patches/extra/0009-hw-usb-hcd-xhci-pci-Use-modulo-to-select-MSI-vector-.patch
delete mode 100644 debian/patches/extra/0010-pci-ensure-valid-link-status-bits-for-downstream-por.patch
delete mode 100644 debian/patches/extra/0011-pci-msix-Fix-msix-pba-read-vector-poll-end-calculati.patch
rename debian/patches/pve/{0044-PVE-backup-add-fleecing-option.patch => 0042-PVE-backup-add-fleecing-option.patch} (57%)
delete mode 100644 debian/patches/pve/0042-alloc-track-error-out-when-auto-remove-is-not-set.patch
rename debian/patches/pve/{0050-adapt-machine-version-deprecation-for-Proxmox-VE.patch => 0043-adapt-machine-version-deprecation-for-Proxmox-VE.patch} (97%)
delete mode 100644 debian/patches/pve/0043-alloc-track-avoid-seemingly-superfluous-child-permis.patch
rename debian/patches/pve/{0051-Revert-hpet-avoid-timer-storms-on-periodic-timers.patch => 0044-Revert-hpet-avoid-timer-storms-on-periodic-timers.patch} (87%)
delete mode 100644 debian/patches/pve/0045-PVE-backup-improve-error-when-copy-before-write-fail.patch
rename debian/patches/pve/{0052-Revert-hpet-store-full-64-bit-target-value-of-the-co.patch => 0045-Revert-hpet-store-full-64-bit-target-value-of-the-co.patch} (91%)
delete mode 100644 debian/patches/pve/0046-PVE-backup-fixup-error-handling-for-fleecing.patch
rename debian/patches/pve/{0053-Revert-hpet-accept-64-bit-reads-and-writes.patch => 0046-Revert-hpet-accept-64-bit-reads-and-writes.patch} (93%)
delete mode 100644 debian/patches/pve/0047-PVE-backup-factor-out-setting-up-snapshot-access-for.patch
rename debian/patches/pve/{0054-Revert-hpet-place-read-only-bits-directly-in-new_val.patch => 0047-Revert-hpet-place-read-only-bits-directly-in-new_val.patch} (89%)
delete mode 100644 debian/patches/pve/0048-PVE-backup-save-device-name-in-device-info-structure.patch
rename debian/patches/pve/{0055-Revert-hpet-remove-unnecessary-variable-index.patch => 0048-Revert-hpet-remove-unnecessary-variable-index.patch} (86%)
delete mode 100644 debian/patches/pve/0049-PVE-backup-include-device-name-in-error-when-setting.patch
rename debian/patches/pve/{0056-Revert-hpet-ignore-high-bits-of-comparator-in-32-bit.patch => 0049-Revert-hpet-ignore-high-bits-of-comparator-in-32-bit.patch} (92%)
rename debian/patches/pve/{0057-Revert-hpet-fix-and-cleanup-persistence-of-interrupt.patch => 0050-Revert-hpet-fix-and-cleanup-persistence-of-interrupt.patch} (93%)
rename debian/patches/pve/{0064-PVE-backup-factor-out-helper-to-clear-backup-state-s.patch => 0051-PVE-backup-factor-out-helper-to-clear-backup-state-s.patch} (98%)
rename debian/patches/pve/{0065-PVE-backup-factor-out-helper-to-initialize-backup-st.patch => 0052-PVE-backup-factor-out-helper-to-initialize-backup-st.patch} (98%)
rename debian/patches/pve/{0066-PVE-backup-add-target-ID-in-backup-state.patch => 0053-PVE-backup-add-target-ID-in-backup-state.patch} (98%)
rename debian/patches/pve/{0067-PVE-backup-get-device-info-allow-caller-to-specify-f.patch => 0054-PVE-backup-get-device-info-allow-caller-to-specify-f.patch} (98%)
create mode 100644 debian/patches/pve/0055-PVE-backup-implement-backup-access-setup-and-teardow.patch
delete mode 100644 debian/patches/pve/0058-savevm-async-improve-setting-state-of-snapshot-opera.patch
delete mode 100644 debian/patches/pve/0059-savevm-async-rename-saved_vm_running-to-vm_needs_sta.patch
delete mode 100644 debian/patches/pve/0060-savevm-async-improve-runstate-preservation-cleanup-e.patch
delete mode 100644 debian/patches/pve/0061-savevm-async-use-dedicated-iothread-for-state-file.patch
delete mode 100644 debian/patches/pve/0062-savevm-async-treat-failure-to-set-iothread-context-a.patch
delete mode 100644 debian/patches/pve/0063-PVE-backup-clean-up-directly-in-setup_snapshot_acces.patch
delete mode 100644 debian/patches/pve/0068-PVE-backup-implement-backup-access-setup-and-teardow.patch
delete mode 100644 debian/patches/pve/0069-PVE-backup-factor-out-get_single_device_info-helper.patch
delete mode 100644 debian/patches/pve/0070-PVE-backup-implement-bitmap-support-for-external-bac.patch
delete mode 100644 debian/patches/pve/0071-PVE-backup-backup-access-api-indicate-situation-wher.patch
delete mode 100644 debian/patches/pve/0072-PVE-backup-backup-access-api-explicit-bitmap-mode-pa.patch
delete mode 100644 debian/patches/pve/0073-PVE-backup-backup-access-api-simplify-bitmap-logic.patch
--
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] 4+ messages in thread
* [pve-devel] [PATCH qemu 1/2] update submodule and patches to QEMU 10.0.2
2025-06-02 10:22 [pve-devel] [PATCH-SERIES qemu 0/2] update submodule and patches to QEMU 10.0.2 Fiona Ebner
@ 2025-06-02 10:22 ` Fiona Ebner
2025-06-02 10:22 ` [pve-devel] [PATCH qemu 2/2] squash some related patches Fiona Ebner
2025-06-17 6:48 ` [pve-devel] applied: [PATCH-SERIES qemu 0/2] update submodule and patches to QEMU 10.0.2 Thomas Lamprecht
2 siblings, 0 replies; 4+ messages in thread
From: Fiona Ebner @ 2025-06-02 10:22 UTC (permalink / raw)
To: pve-devel
Only minor changes this time:
Adapt to changed include paths:
32cad1ffb8 ("include: Rename sysemu/ -> system/")
407bc4bf90 ("qapi: Move include/qapi/qmp/ to include/qobject/")
Adapt to a function signature change:
4822128693 ("migration: Drop inactivate_disk param in
qemu_savevm_state_complete*")
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
---
...d-support-for-sync-bitmap-mode-never.patch | 30 ++--
...-support-for-conditional-and-always-.patch | 2 +-
...check-for-bitmap-mode-without-bitmap.patch | 4 +-
...-to-bdrv_dirty_bitmap_merge_internal.patch | 2 +-
.../0006-mirror-move-some-checks-to-qmp.patch | 6 +-
...race-with-clients-disconnecting-earl.patch | 8 +-
...ial-deadlock-when-draining-during-tr.patch | 2 +-
...Reset-free_temps-before-tcg_optimize.patch | 82 ----------
...t-TSCs-of-parked-vCPUs-too-on-VM-res.patch | 149 ------------------
...x10_version-filtered-when-prefix-is-.patch | 41 -----
| 67 --------
...ectly-compute-Ethernet-packet-offset.patch | 67 --------
...-Windows-PCI-Label-Id-bug-workaround.patch | 96 -----------
...pci-Use-modulo-to-select-MSI-vector-.patch | 53 -------
...-link-status-bits-for-downstream-por.patch | 63 --------
...x-pba-read-vector-poll-end-calculati.patch | 36 -----
...k-file-change-locking-default-to-off.patch | 6 +-
...he-CPU-model-to-kvm64-32-instead-of-.patch | 4 +-
...ui-spice-default-to-pve-certificates.patch | 2 +-
...erfs-no-default-logfile-if-daemonize.patch | 2 +-
...lock-rbd-disable-rbd_cache_writethro.patch | 2 +-
...PVE-Up-glusterfs-allow-partial-reads.patch | 2 +-
...return-success-on-info-without-snaps.patch | 2 +-
...dd-add-osize-and-read-from-to-stdin-.patch | 12 +-
...E-Up-qemu-img-dd-add-isize-parameter.patch | 14 +-
...PVE-Up-qemu-img-dd-add-n-skip_create.patch | 10 +-
...-add-l-option-for-loading-a-snapshot.patch | 14 +-
...virtio-balloon-improve-query-balloon.patch | 4 +-
.../0014-PVE-qapi-modify-query-machines.patch | 8 +-
.../0015-PVE-qapi-modify-spice-query.patch | 4 +-
...nnel-implementation-for-savevm-async.patch | 14 +-
...async-for-background-state-snapshots.patch | 47 +++---
...add-optional-buffer-size-to-QEMUFile.patch | 58 +++----
...add-the-zeroinit-block-driver-filter.patch | 8 +-
...-Add-dummy-id-command-line-parameter.patch | 10 +-
...t-target-i386-disable-LINT0-after-re.patch | 2 +-
...le-posix-make-locking-optiono-on-cre.patch | 20 +--
...3-PVE-monitor-disable-oob-capability.patch | 2 +-
...sed-balloon-qemu-4-0-config-size-fal.patch | 4 +-
...E-Allow-version-code-in-machine-type.patch | 18 +--
...e-bcs-bitmap-initialization-to-job-c.patch | 2 +-
...VE-Backup-add-vma-backup-format-code.patch | 18 +--
...-Backup-add-backup-dump-block-driver.patch | 12 +-
...d-sequential-job-transaction-support.patch | 8 +-
...ckup-Proxmox-backup-patches-for-QEMU.patch | 39 ++---
...estore-new-command-to-restore-from-p.patch | 10 +-
...k-driver-to-map-backup-archives-into.patch | 20 +--
...ct-stderr-to-journal-when-daemonized.patch | 8 +-
...igrate-dirty-bitmap-state-via-savevm.patch | 26 +--
...dirty-bitmap-migrate-other-bitmaps-e.patch | 2 +-
...all-back-to-open-iscsi-initiatorname.patch | 2 +-
...PVE-block-stream-increase-chunk-size.patch | 2 +-
.../0038-block-add-alloc-track-driver.patch | 12 +-
...-rbd-workaround-for-ceph-issue-53784.patch | 2 +-
...-fix-handling-of-holes-in-.bdrv_co_b.patch | 2 +-
...k-rbd-implement-bdrv_co_block_status.patch | 2 +-
...rror-out-when-auto-remove-is-not-set.patch | 2 +-
...d-seemingly-superfluous-child-permis.patch | 2 +-
.../0044-PVE-backup-add-fleecing-option.patch | 46 +++---
...ve-error-when-copy-before-write-fail.patch | 8 +-
...up-fixup-error-handling-for-fleecing.patch | 2 +-
...r-out-setting-up-snapshot-access-for.patch | 2 +-
...device-name-in-device-info-structure.patch | 2 +-
...de-device-name-in-error-when-setting.patch | 2 +-
...e-version-deprecation-for-Proxmox-VE.patch | 8 +-
...void-timer-storms-on-periodic-timers.patch | 8 +-
...e-full-64-bit-target-value-of-the-co.patch | 25 ++-
...-hpet-accept-64-bit-reads-and-writes.patch | 26 +--
...e-read-only-bits-directly-in-new_val.patch | 10 +-
...et-remove-unnecessary-variable-index.patch | 10 +-
...re-high-bits-of-comparator-in-32-bit.patch | 6 +-
...and-cleanup-persistence-of-interrupt.patch | 10 +-
...rove-setting-state-of-snapshot-opera.patch | 6 +-
...ame-saved_vm_running-to-vm_needs_sta.patch | 12 +-
...rove-runstate-preservation-cleanup-e.patch | 18 +--
...se-dedicated-iothread-for-state-file.patch | 26 ++-
...at-failure-to-set-iothread-context-a.patch | 2 +-
...-up-directly-in-setup_snapshot_acces.patch | 2 +-
...r-out-helper-to-clear-backup-state-s.patch | 2 +-
...r-out-helper-to-initialize-backup-st.patch | 2 +-
...backup-add-target-ID-in-backup-state.patch | 2 +-
...evice-info-allow-caller-to-specify-f.patch | 2 +-
...ment-backup-access-setup-and-teardow.patch | 18 +--
...or-out-get_single_device_info-helper.patch | 2 +-
...ment-bitmap-support-for-external-bac.patch | 16 +-
...p-access-api-indicate-situation-wher.patch | 6 +-
...p-access-api-explicit-bitmap-mode-pa.patch | 6 +-
...kup-access-api-simplify-bitmap-logic.patch | 8 +-
debian/patches/series | 9 --
qemu | 2 +-
90 files changed, 390 insertions(+), 1064 deletions(-)
delete mode 100644 debian/patches/extra/0003-tcg-Reset-free_temps-before-tcg_optimize.patch
delete mode 100644 debian/patches/extra/0004-target-i386-Reset-TSCs-of-parked-vCPUs-too-on-VM-res.patch
delete mode 100644 debian/patches/extra/0005-i386-cpu-Mark-avx10_version-filtered-when-prefix-is-.patch
delete mode 100644 debian/patches/extra/0006-net-Fix-announce_self.patch
delete mode 100644 debian/patches/extra/0007-net-dump-Correctly-compute-Ethernet-packet-offset.patch
delete mode 100644 debian/patches/extra/0008-pci-acpi-Windows-PCI-Label-Id-bug-workaround.patch
delete mode 100644 debian/patches/extra/0009-hw-usb-hcd-xhci-pci-Use-modulo-to-select-MSI-vector-.patch
delete mode 100644 debian/patches/extra/0010-pci-ensure-valid-link-status-bits-for-downstream-por.patch
delete mode 100644 debian/patches/extra/0011-pci-msix-Fix-msix-pba-read-vector-poll-end-calculati.patch
diff --git a/debian/patches/bitmap-mirror/0001-drive-mirror-add-support-for-sync-bitmap-mode-never.patch b/debian/patches/bitmap-mirror/0001-drive-mirror-add-support-for-sync-bitmap-mode-never.patch
index ad1fc5d..ba25f6f 100644
--- a/debian/patches/bitmap-mirror/0001-drive-mirror-add-support-for-sync-bitmap-mode-never.patch
+++ b/debian/patches/bitmap-mirror/0001-drive-mirror-add-support-for-sync-bitmap-mode-never.patch
@@ -38,7 +38,7 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
5 files changed, 142 insertions(+), 28 deletions(-)
diff --git a/block/mirror.c b/block/mirror.c
-index 2afe700b4d..c3d4be9b15 100644
+index a53582f17b..fafca1360e 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -51,7 +51,7 @@ typedef struct MirrorBlockJob {
@@ -258,10 +258,10 @@ index 2afe700b4d..c3d4be9b15 100644
base_read_only, errp);
if (!job) {
diff --git a/blockdev.c b/blockdev.c
-index 6740663fda..38fa63155c 100644
+index 1d1f27cfff..ec45bbaa52 100644
--- a/blockdev.c
+++ b/blockdev.c
-@@ -2781,6 +2781,9 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
+@@ -2797,6 +2797,9 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
BlockDriverState *target,
const char *replaces,
enum MirrorSyncMode sync,
@@ -271,7 +271,7 @@ index 6740663fda..38fa63155c 100644
BlockMirrorBackingMode backing_mode,
bool zero_target,
bool has_speed, int64_t speed,
-@@ -2799,6 +2802,7 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
+@@ -2815,6 +2818,7 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
{
BlockDriverState *unfiltered_bs;
int job_flags = JOB_DEFAULT;
@@ -279,7 +279,7 @@ index 6740663fda..38fa63155c 100644
GLOBAL_STATE_CODE();
GRAPH_RDLOCK_GUARD_MAINLOOP();
-@@ -2853,6 +2857,29 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
+@@ -2869,6 +2873,29 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
sync = MIRROR_SYNC_MODE_FULL;
}
@@ -309,7 +309,7 @@ index 6740663fda..38fa63155c 100644
if (!replaces) {
/* We want to mirror from @bs, but keep implicit filters on top */
unfiltered_bs = bdrv_skip_implicit_filters(bs);
-@@ -2894,8 +2921,8 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
+@@ -2910,8 +2937,8 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
* and will allow to check whether the node still exist at mirror completion
*/
mirror_start(job_id, bs, target,
@@ -320,7 +320,7 @@ index 6740663fda..38fa63155c 100644
on_source_error, on_target_error, unmap, filter_node_name,
copy_mode, errp);
}
-@@ -3039,6 +3066,8 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
+@@ -3055,6 +3082,8 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
blockdev_mirror_common(arg->job_id, bs, target_bs,
arg->replaces, arg->sync,
@@ -329,7 +329,7 @@ index 6740663fda..38fa63155c 100644
backing_mode, zero_target,
arg->has_speed, arg->speed,
arg->has_granularity, arg->granularity,
-@@ -3058,6 +3087,8 @@ void qmp_blockdev_mirror(const char *job_id,
+@@ -3074,6 +3103,8 @@ void qmp_blockdev_mirror(const char *job_id,
const char *device, const char *target,
const char *replaces,
MirrorSyncMode sync,
@@ -338,7 +338,7 @@ index 6740663fda..38fa63155c 100644
bool has_speed, int64_t speed,
bool has_granularity, uint32_t granularity,
bool has_buf_size, int64_t buf_size,
-@@ -3098,7 +3129,8 @@ void qmp_blockdev_mirror(const char *job_id,
+@@ -3114,7 +3145,8 @@ void qmp_blockdev_mirror(const char *job_id,
}
blockdev_mirror_common(job_id, bs, target_bs,
@@ -364,10 +364,10 @@ index eb2d92a226..f0c642b194 100644
BlockdevOnError on_source_error,
BlockdevOnError on_target_error,
diff --git a/qapi/block-core.json b/qapi/block-core.json
-index fd3bcc1c17..48ba32049f 100644
+index b1937780e1..0e5f148d30 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
-@@ -2178,6 +2178,15 @@
+@@ -2182,6 +2182,15 @@
# destination (all the disk, only the sectors allocated in the
# topmost image, or only new I/O).
#
@@ -383,7 +383,7 @@ index fd3bcc1c17..48ba32049f 100644
# @granularity: granularity of the dirty bitmap, default is 64K if the
# image format doesn't have clusters, 4K if the clusters are
# smaller than that, else the cluster size. Must be a power of 2
-@@ -2220,7 +2229,9 @@
+@@ -2224,7 +2233,9 @@
{ 'struct': 'DriveMirror',
'data': { '*job-id': 'str', 'device': 'str', 'target': 'str',
'*format': 'str', '*node-name': 'str', '*replaces': 'str',
@@ -394,7 +394,7 @@ index fd3bcc1c17..48ba32049f 100644
'*speed': 'int', '*granularity': 'uint32',
'*buf-size': 'int', '*on-source-error': 'BlockdevOnError',
'*on-target-error': 'BlockdevOnError',
-@@ -2499,6 +2510,15 @@
+@@ -2503,6 +2514,15 @@
# destination (all the disk, only the sectors allocated in the
# topmost image, or only new I/O).
#
@@ -410,7 +410,7 @@ index fd3bcc1c17..48ba32049f 100644
# @granularity: granularity of the dirty bitmap, default is 64K if the
# image format doesn't have clusters, 4K if the clusters are
# smaller than that, else the cluster size. Must be a power of 2
-@@ -2547,7 +2567,8 @@
+@@ -2551,7 +2571,8 @@
{ 'command': 'blockdev-mirror',
'data': { '*job-id': 'str', 'device': 'str', 'target': 'str',
'*replaces': 'str',
@@ -421,7 +421,7 @@ index fd3bcc1c17..48ba32049f 100644
'*buf-size': 'int', '*on-source-error': 'BlockdevOnError',
'*on-target-error': 'BlockdevOnError',
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
-index 20ed54f570..4f50a99334 100644
+index 2b358eaaa8..2a149fe021 100644
--- a/tests/unit/test-block-iothread.c
+++ b/tests/unit/test-block-iothread.c
@@ -755,8 +755,8 @@ static void test_propagate_mirror(void)
diff --git a/debian/patches/bitmap-mirror/0002-drive-mirror-add-support-for-conditional-and-always-.patch b/debian/patches/bitmap-mirror/0002-drive-mirror-add-support-for-conditional-and-always-.patch
index 226c3e7..f22b013 100644
--- a/debian/patches/bitmap-mirror/0002-drive-mirror-add-support-for-conditional-and-always-.patch
+++ b/debian/patches/bitmap-mirror/0002-drive-mirror-add-support-for-conditional-and-always-.patch
@@ -24,7 +24,7 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/block/mirror.c b/block/mirror.c
-index c3d4be9b15..7b6f7c0068 100644
+index fafca1360e..05e738bcce 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -694,8 +694,6 @@ static int mirror_exit_common(Job *job)
diff --git a/debian/patches/bitmap-mirror/0003-mirror-add-check-for-bitmap-mode-without-bitmap.patch b/debian/patches/bitmap-mirror/0003-mirror-add-check-for-bitmap-mode-without-bitmap.patch
index 065519f..81c750b 100644
--- a/debian/patches/bitmap-mirror/0003-mirror-add-check-for-bitmap-mode-without-bitmap.patch
+++ b/debian/patches/bitmap-mirror/0003-mirror-add-check-for-bitmap-mode-without-bitmap.patch
@@ -16,10 +16,10 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
1 file changed, 3 insertions(+)
diff --git a/blockdev.c b/blockdev.c
-index 38fa63155c..204cf6fad1 100644
+index ec45bbaa52..9fab7ec554 100644
--- a/blockdev.c
+++ b/blockdev.c
-@@ -2878,6 +2878,9 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
+@@ -2894,6 +2894,9 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) {
return;
}
diff --git a/debian/patches/bitmap-mirror/0004-mirror-switch-to-bdrv_dirty_bitmap_merge_internal.patch b/debian/patches/bitmap-mirror/0004-mirror-switch-to-bdrv_dirty_bitmap_merge_internal.patch
index 71f22b6..abece60 100644
--- a/debian/patches/bitmap-mirror/0004-mirror-switch-to-bdrv_dirty_bitmap_merge_internal.patch
+++ b/debian/patches/bitmap-mirror/0004-mirror-switch-to-bdrv_dirty_bitmap_merge_internal.patch
@@ -16,7 +16,7 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/block/mirror.c b/block/mirror.c
-index 7b6f7c0068..2b1c07095d 100644
+index 05e738bcce..2a2a227f3b 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -809,8 +809,8 @@ static int mirror_exit_common(Job *job)
diff --git a/debian/patches/bitmap-mirror/0006-mirror-move-some-checks-to-qmp.patch b/debian/patches/bitmap-mirror/0006-mirror-move-some-checks-to-qmp.patch
index b34956a..50746b6 100644
--- a/debian/patches/bitmap-mirror/0006-mirror-move-some-checks-to-qmp.patch
+++ b/debian/patches/bitmap-mirror/0006-mirror-move-some-checks-to-qmp.patch
@@ -21,7 +21,7 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
3 files changed, 70 insertions(+), 59 deletions(-)
diff --git a/block/mirror.c b/block/mirror.c
-index 2b1c07095d..f5787b380c 100644
+index 2a2a227f3b..87c0856979 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -1763,31 +1763,13 @@ static BlockJob *mirror_start_job(
@@ -62,10 +62,10 @@ index 2b1c07095d..f5787b380c 100644
if (bitmap_mode != BITMAP_SYNC_MODE_NEVER) {
diff --git a/blockdev.c b/blockdev.c
-index 204cf6fad1..79d47b1920 100644
+index 9fab7ec554..158ac9314b 100644
--- a/blockdev.c
+++ b/blockdev.c
-@@ -2857,7 +2857,36 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
+@@ -2873,7 +2873,36 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
sync = MIRROR_SYNC_MODE_FULL;
}
diff --git a/debian/patches/extra/0001-monitor-qmp-fix-race-with-clients-disconnecting-earl.patch b/debian/patches/extra/0001-monitor-qmp-fix-race-with-clients-disconnecting-earl.patch
index 8954481..de0a350 100644
--- a/debian/patches/extra/0001-monitor-qmp-fix-race-with-clients-disconnecting-earl.patch
+++ b/debian/patches/extra/0001-monitor-qmp-fix-race-with-clients-disconnecting-earl.patch
@@ -60,7 +60,7 @@ index c3740ec616..7f38ce6b8b 100644
void monitor_init_globals(void);
void monitor_init_globals_core(void);
diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h
-index cb628f681d..93dbd62fc2 100644
+index 5676eb334e..4c452a6aeb 100644
--- a/monitor/monitor-internal.h
+++ b/monitor/monitor-internal.h
@@ -151,6 +151,13 @@ typedef struct {
@@ -78,7 +78,7 @@ index cb628f681d..93dbd62fc2 100644
/**
diff --git a/monitor/monitor.c b/monitor/monitor.c
-index 56786c0ccc..30071d0c8a 100644
+index c5a5d30877..07775784d4 100644
--- a/monitor/monitor.c
+++ b/monitor/monitor.c
@@ -116,6 +116,21 @@ bool monitor_cur_is_qmp(void)
@@ -104,7 +104,7 @@ index 56786c0ccc..30071d0c8a 100644
* Is @mon is using readline?
* Note: not all HMP monitors use readline, e.g., gdbserver has a
diff --git a/monitor/qmp.c b/monitor/qmp.c
-index 5e538f34c0..eb181d5979 100644
+index 2f46cf9e49..f093e256e9 100644
--- a/monitor/qmp.c
+++ b/monitor/qmp.c
@@ -165,6 +165,8 @@ static void monitor_qmp_dispatch(MonitorQMP *mon, QObject *req)
@@ -144,7 +144,7 @@ index 5e538f34c0..eb181d5979 100644
monitor_qmp_caps_reset(mon);
data = qmp_greeting(mon);
diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
-index 176b549473..790bb7d1da 100644
+index e569224eae..eb03782e91 100644
--- a/qapi/qmp-dispatch.c
+++ b/qapi/qmp-dispatch.c
@@ -117,16 +117,28 @@ typedef struct QmpDispatchBH {
diff --git a/debian/patches/extra/0002-ide-avoid-potential-deadlock-when-draining-during-tr.patch b/debian/patches/extra/0002-ide-avoid-potential-deadlock-when-draining-during-tr.patch
index b97684d..aca8620 100644
--- a/debian/patches/extra/0002-ide-avoid-potential-deadlock-when-draining-during-tr.patch
+++ b/debian/patches/extra/0002-ide-avoid-potential-deadlock-when-draining-during-tr.patch
@@ -55,7 +55,7 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/hw/ide/core.c b/hw/ide/core.c
-index 08d9218455..20d8c0cf66 100644
+index b14983ec54..41c543e627 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -456,7 +456,7 @@ static void ide_trim_bh_cb(void *opaque)
diff --git a/debian/patches/extra/0003-tcg-Reset-free_temps-before-tcg_optimize.patch b/debian/patches/extra/0003-tcg-Reset-free_temps-before-tcg_optimize.patch
deleted file mode 100644
index 15b3016..0000000
--- a/debian/patches/extra/0003-tcg-Reset-free_temps-before-tcg_optimize.patch
+++ /dev/null
@@ -1,82 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Richard Henderson <richard.henderson@linaro.org>
-Date: Sat, 7 Dec 2024 18:14:45 +0000
-Subject: [PATCH] tcg: Reset free_temps before tcg_optimize
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-When allocating new temps during tcg_optmize, do not re-use
-any EBB temps that were used within the TB. We do not have
-any idea what span of the TB in which the temp was live.
-
-Introduce tcg_temp_ebb_reset_freed and use before tcg_optimize,
-as well as replacing the equivalent in plugin_gen_inject and
-tcg_func_start.
-
-Cc: qemu-stable@nongnu.org
-Fixes: fb04ab7ddd8 ("tcg/optimize: Lower TCG_COND_TST{EQ,NE} if unsupported")
-Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2711
-Reported-by: wannacu <wannacu2049@gmail.com>
-Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
-Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
-Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
-(cherry picked from commit 04e006ab36a8565b92d4e21dd346367fbade7d74)
-Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
----
- accel/tcg/plugin-gen.c | 2 +-
- include/tcg/tcg-temp-internal.h | 6 ++++++
- tcg/tcg.c | 5 ++++-
- 3 files changed, 11 insertions(+), 2 deletions(-)
-
-diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c
-index 0f47bfbb48..1ef075552c 100644
---- a/accel/tcg/plugin-gen.c
-+++ b/accel/tcg/plugin-gen.c
-@@ -275,7 +275,7 @@ static void plugin_gen_inject(struct qemu_plugin_tb *plugin_tb)
- * that might be live within the existing opcode stream.
- * The simplest solution is to release them all and create new.
- */
-- memset(tcg_ctx->free_temps, 0, sizeof(tcg_ctx->free_temps));
-+ tcg_temp_ebb_reset_freed(tcg_ctx);
-
- QTAILQ_FOREACH_SAFE(op, &tcg_ctx->ops, link, next) {
- switch (op->opc) {
-diff --git a/include/tcg/tcg-temp-internal.h b/include/tcg/tcg-temp-internal.h
-index 44192c55a9..98f91e68b7 100644
---- a/include/tcg/tcg-temp-internal.h
-+++ b/include/tcg/tcg-temp-internal.h
-@@ -42,4 +42,10 @@ TCGv_i64 tcg_temp_ebb_new_i64(void);
- TCGv_ptr tcg_temp_ebb_new_ptr(void);
- TCGv_i128 tcg_temp_ebb_new_i128(void);
-
-+/* Forget all freed EBB temps, so that new allocations produce new temps. */
-+static inline void tcg_temp_ebb_reset_freed(TCGContext *s)
-+{
-+ memset(s->free_temps, 0, sizeof(s->free_temps));
-+}
-+
- #endif /* TCG_TEMP_FREE_H */
-diff --git a/tcg/tcg.c b/tcg/tcg.c
-index 0babae1b88..4578b185be 100644
---- a/tcg/tcg.c
-+++ b/tcg/tcg.c
-@@ -1489,7 +1489,7 @@ void tcg_func_start(TCGContext *s)
- s->nb_temps = s->nb_globals;
-
- /* No temps have been previously allocated for size or locality. */
-- memset(s->free_temps, 0, sizeof(s->free_temps));
-+ tcg_temp_ebb_reset_freed(s);
-
- /* No constant temps have been previously allocated. */
- for (int i = 0; i < TCG_TYPE_COUNT; ++i) {
-@@ -6120,6 +6120,9 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, uint64_t pc_start)
- }
- #endif
-
-+ /* Do not reuse any EBB that may be allocated within the TB. */
-+ tcg_temp_ebb_reset_freed(s);
-+
- tcg_optimize(s);
-
- reachable_code_pass(s);
diff --git a/debian/patches/extra/0004-target-i386-Reset-TSCs-of-parked-vCPUs-too-on-VM-res.patch b/debian/patches/extra/0004-target-i386-Reset-TSCs-of-parked-vCPUs-too-on-VM-res.patch
deleted file mode 100644
index 071d51a..0000000
--- a/debian/patches/extra/0004-target-i386-Reset-TSCs-of-parked-vCPUs-too-on-VM-res.patch
+++ /dev/null
@@ -1,149 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: "Maciej S. Szmigiero" <maciej.szmigiero@oracle.com>
-Date: Thu, 12 Dec 2024 15:51:15 +0100
-Subject: [PATCH] target/i386: Reset TSCs of parked vCPUs too on VM reset
-
-Since commit 5286c3662294 ("target/i386: properly reset TSC on reset")
-QEMU writes the special value of "1" to each online vCPU TSC on VM reset
-to reset it.
-
-However parked vCPUs don't get that handling and due to that their TSCs
-get desynchronized when the VM gets reset.
-This in turn causes KVM to turn off PVCLOCK_TSC_STABLE_BIT in its exported
-PV clock.
-Note that KVM has no understanding of vCPU being currently parked.
-
-Without PVCLOCK_TSC_STABLE_BIT the sched clock is marked unstable in
-the guest's kvm_sched_clock_init().
-This causes a performance regressions to show in some tests.
-
-Fix this issue by writing the special value of "1" also to TSCs of parked
-vCPUs on VM reset.
-
-Reproducing the issue:
-1) Boot a VM with "-smp 2,maxcpus=3" or similar
-
-2) device_add host-x86_64-cpu,id=vcpu,node-id=0,socket-id=0,core-id=2,thread-id=0
-
-3) Wait a few seconds
-
-4) device_del vcpu
-
-5) Inside the VM run:
-# echo "t" >/proc/sysrq-trigger; dmesg | grep sched_clock_stable
-Observe the sched_clock_stable() value is 1.
-
-6) Reboot the VM
-
-7) Once the VM boots once again run inside it:
-# echo "t" >/proc/sysrq-trigger; dmesg | grep sched_clock_stable
-Observe the sched_clock_stable() value is now 0.
-
-Fixes: 5286c3662294 ("target/i386: properly reset TSC on reset")
-Signed-off-by: Maciej S. Szmigiero <maciej.szmigiero@oracle.com>
-Link: https://lore.kernel.org/r/5a605a88e9a231386dc803c60f5fed9b48108139.1734014926.git.maciej.szmigiero@oracle.com
-Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-(cherry picked from commit 3f2a05b31ee9ce2ddb6c75a9bc3f5e7f7af9a76f)
-Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
----
- accel/kvm/kvm-all.c | 11 +++++++++++
- configs/targets/i386-softmmu.mak | 1 +
- configs/targets/x86_64-softmmu.mak | 1 +
- include/sysemu/kvm.h | 8 ++++++++
- target/i386/kvm/kvm.c | 15 +++++++++++++++
- 5 files changed, 36 insertions(+)
-
-diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
-index 801cff16a5..dec1d1c16a 100644
---- a/accel/kvm/kvm-all.c
-+++ b/accel/kvm/kvm-all.c
-@@ -437,6 +437,16 @@ int kvm_unpark_vcpu(KVMState *s, unsigned long vcpu_id)
- return kvm_fd;
- }
-
-+static void kvm_reset_parked_vcpus(void *param)
-+{
-+ KVMState *s = param;
-+ struct KVMParkedVcpu *cpu;
-+
-+ QLIST_FOREACH(cpu, &s->kvm_parked_vcpus, node) {
-+ kvm_arch_reset_parked_vcpu(cpu->vcpu_id, cpu->kvm_fd);
-+ }
-+}
-+
- int kvm_create_vcpu(CPUState *cpu)
- {
- unsigned long vcpu_id = kvm_arch_vcpu_id(cpu);
-@@ -2728,6 +2738,7 @@ static int kvm_init(MachineState *ms)
- }
-
- qemu_register_reset(kvm_unpoison_all, NULL);
-+ qemu_register_reset(kvm_reset_parked_vcpus, s);
-
- if (s->kernel_irqchip_allowed) {
- kvm_irqchip_create(s);
-diff --git a/configs/targets/i386-softmmu.mak b/configs/targets/i386-softmmu.mak
-index 2ac69d5ba3..2eb0e86250 100644
---- a/configs/targets/i386-softmmu.mak
-+++ b/configs/targets/i386-softmmu.mak
-@@ -1,4 +1,5 @@
- TARGET_ARCH=i386
- TARGET_SUPPORTS_MTTCG=y
- TARGET_KVM_HAVE_GUEST_DEBUG=y
-+TARGET_KVM_HAVE_RESET_PARKED_VCPU=y
- TARGET_XML_FILES= gdb-xml/i386-32bit.xml
-diff --git a/configs/targets/x86_64-softmmu.mak b/configs/targets/x86_64-softmmu.mak
-index e12ac3dc59..920e9a4200 100644
---- a/configs/targets/x86_64-softmmu.mak
-+++ b/configs/targets/x86_64-softmmu.mak
-@@ -2,4 +2,5 @@ TARGET_ARCH=x86_64
- TARGET_BASE_ARCH=i386
- TARGET_SUPPORTS_MTTCG=y
- TARGET_KVM_HAVE_GUEST_DEBUG=y
-+TARGET_KVM_HAVE_RESET_PARKED_VCPU=y
- TARGET_XML_FILES= gdb-xml/i386-64bit.xml
-diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
-index c3a60b2890..ab17c09a55 100644
---- a/include/sysemu/kvm.h
-+++ b/include/sysemu/kvm.h
-@@ -377,6 +377,14 @@ int kvm_arch_init(MachineState *ms, KVMState *s);
- int kvm_arch_init_vcpu(CPUState *cpu);
- int kvm_arch_destroy_vcpu(CPUState *cpu);
-
-+#ifdef TARGET_KVM_HAVE_RESET_PARKED_VCPU
-+void kvm_arch_reset_parked_vcpu(unsigned long vcpu_id, int kvm_fd);
-+#else
-+static inline void kvm_arch_reset_parked_vcpu(unsigned long vcpu_id, int kvm_fd)
-+{
-+}
-+#endif
-+
- bool kvm_vcpu_id_is_valid(int vcpu_id);
-
- /* Returns VCPU ID to be used on KVM_CREATE_VCPU ioctl() */
-diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
-index 8e17942c3b..2ff618fbf1 100644
---- a/target/i386/kvm/kvm.c
-+++ b/target/i386/kvm/kvm.c
-@@ -2415,6 +2415,21 @@ void kvm_arch_after_reset_vcpu(X86CPU *cpu)
- }
- }
-
-+void kvm_arch_reset_parked_vcpu(unsigned long vcpu_id, int kvm_fd)
-+{
-+ g_autofree struct kvm_msrs *msrs = NULL;
-+
-+ msrs = g_malloc0(sizeof(*msrs) + sizeof(msrs->entries[0]));
-+ msrs->entries[0].index = MSR_IA32_TSC;
-+ msrs->entries[0].data = 1; /* match the value in x86_cpu_reset() */
-+ msrs->nmsrs++;
-+
-+ if (ioctl(kvm_fd, KVM_SET_MSRS, msrs) != 1) {
-+ warn_report("parked vCPU %lu TSC reset failed: %d",
-+ vcpu_id, errno);
-+ }
-+}
-+
- void kvm_arch_do_init_vcpu(X86CPU *cpu)
- {
- CPUX86State *env = &cpu->env;
diff --git a/debian/patches/extra/0005-i386-cpu-Mark-avx10_version-filtered-when-prefix-is-.patch b/debian/patches/extra/0005-i386-cpu-Mark-avx10_version-filtered-when-prefix-is-.patch
deleted file mode 100644
index 6f5444c..0000000
--- a/debian/patches/extra/0005-i386-cpu-Mark-avx10_version-filtered-when-prefix-is-.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Zhao Liu <zhao1.liu@intel.com>
-Date: Wed, 6 Nov 2024 11:07:18 +0800
-Subject: [PATCH] i386/cpu: Mark avx10_version filtered when prefix is NULL
-
-In x86_cpu_filter_features(), if host doesn't support AVX10, the
-configured avx10_version should be marked as filtered regardless of
-whether prefix is NULL or not.
-
-Check prefix before warn_report() instead of checking for
-have_filtered_features.
-
-Cc: qemu-stable@nongnu.org
-Fixes: commit bccfb846fd52 ("target/i386: add AVX10 feature and AVX10 version property")
-Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
-Reviewed-by: Tao Su <tao1.su@linux.intel.com>
-Link: https://lore.kernel.org/r/20241106030728.553238-2-zhao1.liu@intel.com
-Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-(cherry picked from commit cf4c263551886964c5d58bd7b675b13fd497b402)
-Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
----
- target/i386/cpu.c | 6 ++++--
- 1 file changed, 4 insertions(+), 2 deletions(-)
-
-diff --git a/target/i386/cpu.c b/target/i386/cpu.c
-index 3725dbbc4b..1981aeaba5 100644
---- a/target/i386/cpu.c
-+++ b/target/i386/cpu.c
-@@ -7718,8 +7718,10 @@ static bool x86_cpu_filter_features(X86CPU *cpu, bool verbose)
- env->avx10_version = version;
- have_filtered_features = true;
- }
-- } else if (env->avx10_version && prefix) {
-- warn_report("%s: avx10.%d.", prefix, env->avx10_version);
-+ } else if (env->avx10_version) {
-+ if (prefix) {
-+ warn_report("%s: avx10.%d.", prefix, env->avx10_version);
-+ }
- have_filtered_features = true;
- }
-
diff --git a/debian/patches/extra/0006-net-Fix-announce_self.patch b/debian/patches/extra/0006-net-Fix-announce_self.patch
deleted file mode 100644
index 0c11819..0000000
--- a/debian/patches/extra/0006-net-Fix-announce_self.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Laurent Vivier <lvivier@redhat.com>
-Date: Fri, 17 Jan 2025 12:17:08 +0100
-Subject: [PATCH] net: Fix announce_self
-
-b9ad513e1876 ("net: Remove receive_raw()") adds an iovec entry
-in qemu_deliver_packet_iov() to add the virtio-net header
-in the data when QEMU_NET_PACKET_FLAG_RAW is set but forgets
-to increase the number of iovec entries in the array, so
-receive_iov() will only send the first entry (the virtio-net
-entry, full of 0) and no data. The packet will be discarded.
-
-The only user of QEMU_NET_PACKET_FLAG_RAW is announce_self.
-
-We can see the problem with tcpdump:
-
-- QEMU parameters:
-
- .. -monitor stdio \
- -netdev bridge,id=netdev0,br=virbr0 \
- -device virtio-net,mac=9a:2b:2c:2d:2e:2f,netdev=netdev0 \
-
-- HMP command:
-
- (qemu) announce_self
-
-- TCP dump:
-
- $ sudo tcpdump -nxi virbr0
-
- without the fix:
-
- <nothing>
-
- with the fix:
-
- ARP, Reverse Request who-is 9a:2b:2c:2d:2e:2f tell 9a:2b:2c:2d:2e:2f, length 46
- 0x0000: 0001 0800 0604 0003 9a2b 2c2d 2e2f 0000
- 0x0010: 0000 9a2b 2c2d 2e2f 0000 0000 0000 0000
- 0x0020: 0000 0000 0000 0000 0000 0000 0000
-
-Reported-by: Xiaohui Li <xiaohli@redhat.com>
-Bug: https://issues.redhat.com/browse/RHEL-73891
-Fixes: b9ad513e1876 ("net: Remove receive_raw()")
-Cc: akihiko.odaki@daynix.com
-Signed-off-by: Laurent Vivier <lvivier@redhat.com>
-Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>
-Acked-by: Jason Wang <jasowang@redhat.com>
-Reviewed-by: Michael Tokarev <mjt@tls.msk.ru>
-(picked from https://lore.kernel.org/qemu-devel/20250117111709.970789-2-lvivier@redhat.com/)
-Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
----
- net/net.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/net/net.c b/net/net.c
-index 7ef6885876..fefa701bb2 100644
---- a/net/net.c
-+++ b/net/net.c
-@@ -822,6 +822,7 @@ static ssize_t qemu_deliver_packet_iov(NetClientState *sender,
- iov_copy[0].iov_len = nc->vnet_hdr_len;
- memcpy(&iov_copy[1], iov, iovcnt * sizeof(*iov));
- iov = iov_copy;
-+ iovcnt++;
- }
-
- if (nc->info->receive_iov) {
diff --git a/debian/patches/extra/0007-net-dump-Correctly-compute-Ethernet-packet-offset.patch b/debian/patches/extra/0007-net-dump-Correctly-compute-Ethernet-packet-offset.patch
deleted file mode 100644
index 09b00f7..0000000
--- a/debian/patches/extra/0007-net-dump-Correctly-compute-Ethernet-packet-offset.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Laurent Vivier <lvivier@redhat.com>
-Date: Fri, 17 Jan 2025 12:17:09 +0100
-Subject: [PATCH] net/dump: Correctly compute Ethernet packet offset
-
-When a packet is sent with QEMU_NET_PACKET_FLAG_RAW by QEMU it
-never includes virtio-net header even if qemu_get_vnet_hdr_len()
-is not 0, and filter-dump is not managing this case.
-
-The only user of QEMU_NET_PACKET_FLAG_RAW is announce_self,
-we can show the problem using it and tcpddump:
-
-- QEMU parameters:
-
- .. -monitor stdio \
- -netdev bridge,id=netdev0,br=virbr0 \
- -device virtio-net,mac=9a:2b:2c:2d:2e:2f,netdev=netdev0 \
- -object filter-dump,netdev=netdev0,file=log.pcap,id=pcap0
-
-- HMP command:
-
- (qemu) announce_self
-
-- TCP dump:
-
- $ tcpdump -nxr log.pcap
-
- without the fix:
-
- 08:00:06:04:00:03 > 2e:2f:80:35:00:01, ethertype Unknown (0x9a2b), length 50:
- 0x0000: 2c2d 2e2f 0000 0000 9a2b 2c2d 2e2f 0000
- 0x0010: 0000 0000 0000 0000 0000 0000 0000 0000
- 0x0020: 0000 0000
-
- with the fix:
-
- ARP, Reverse Request who-is 9a:2b:2c:2d:2e:2f tell 9a:2b:2c:2d:2e:2f, length 46
- 0x0000: 0001 0800 0604 0003 9a2b 2c2d 2e2f 0000
- 0x0010: 0000 9a2b 2c2d 2e2f 0000 0000 0000 0000
- 0x0020: 0000 0000 0000 0000 0000 0000 0000
-
-Fixes: 481c52320a26 ("net: Strip virtio-net header when dumping")
-Cc: akihiko.odaki@daynix.com
-Signed-off-by: Laurent Vivier <lvivier@redhat.com>
-Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>
-Acked-by: Jason Wang <jasowang@redhat.com>
-Reviewed-by: Michael Tokarev <mjt@tls.msk.ru>
-(picked from https://lore.kernel.org/qemu-devel/20250117111709.970789-3-lvivier@redhat.com/)
-Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
----
- net/dump.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/net/dump.c b/net/dump.c
-index 956e34a123..42ab8d7716 100644
---- a/net/dump.c
-+++ b/net/dump.c
-@@ -155,7 +155,8 @@ static ssize_t filter_dump_receive_iov(NetFilterState *nf, NetClientState *sndr,
- {
- NetFilterDumpState *nfds = FILTER_DUMP(nf);
-
-- dump_receive_iov(&nfds->ds, iov, iovcnt, qemu_get_vnet_hdr_len(nf->netdev));
-+ dump_receive_iov(&nfds->ds, iov, iovcnt, flags & QEMU_NET_PACKET_FLAG_RAW ?
-+ 0 : qemu_get_vnet_hdr_len(nf->netdev));
- return 0;
- }
-
diff --git a/debian/patches/extra/0008-pci-acpi-Windows-PCI-Label-Id-bug-workaround.patch b/debian/patches/extra/0008-pci-acpi-Windows-PCI-Label-Id-bug-workaround.patch
deleted file mode 100644
index acb7662..0000000
--- a/debian/patches/extra/0008-pci-acpi-Windows-PCI-Label-Id-bug-workaround.patch
+++ /dev/null
@@ -1,96 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Igor Mammedov <imammedo@redhat.com>
-Date: Wed, 15 Jan 2025 13:53:41 +0100
-Subject: [PATCH] pci: acpi: Windows 'PCI Label Id' bug workaround
-
-Current versions of Windows call _DSM(func=7) regardless
-of whether it is supported or not. It leads to NICs having bogus
-'PCI Label Id = 0', where none should be set at all.
-
-Also presence of 'PCI Label Id' triggers another Windows bug
-on localized versions that leads to hangs. The later bug is fixed
-in latest updates for 'Windows Server' but not in consumer
-versions of Windows (and there is no plans to fix it
-as far as I'm aware).
-
-Given it's easy, implement Microsoft suggested workaround
-(return invalid Package) so that affected Windows versions
-could boot on QEMU.
-This would effectvely remove bogus 'PCI Label Id's on NICs,
-but MS teem confirmed that flipping 'PCI Label Id' should not
-change 'Network Connection' ennumeration, so it should be safe
-for QEMU to change _DSM without any compat code.
-
-Smoke tested with WinXP and WS2022
-Resolves: https://gitlab.com/qemu-project/qemu/-/issues/774
-Signed-off-by: Igor Mammedov <imammedo@redhat.com>
-Message-Id: <20250115125342.3883374-3-imammedo@redhat.com>
-Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
-Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
-(cherry picked from commit 0b053391985abcc40b16ac8fc4a7f6588d1d95c1)
-Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
----
- hw/i386/acpi-build.c | 33 +++++++++++++++++++++++----------
- 1 file changed, 23 insertions(+), 10 deletions(-)
-
-diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
-index 9fcc2897b8..f7b961e04c 100644
---- a/hw/i386/acpi-build.c
-+++ b/hw/i386/acpi-build.c
-@@ -654,6 +654,7 @@ static Aml *aml_pci_pdsm(void)
- Aml *acpi_index = aml_local(2);
- Aml *zero = aml_int(0);
- Aml *one = aml_int(1);
-+ Aml *not_supp = aml_int(0xFFFFFFFF);
- Aml *func = aml_arg(2);
- Aml *params = aml_arg(4);
- Aml *bnum = aml_derefof(aml_index(params, aml_int(0)));
-@@ -678,7 +679,7 @@ static Aml *aml_pci_pdsm(void)
- */
- ifctx1 = aml_if(aml_lnot(
- aml_or(aml_equal(acpi_index, zero),
-- aml_equal(acpi_index, aml_int(0xFFFFFFFF)), NULL)
-+ aml_equal(acpi_index, not_supp), NULL)
- ));
- {
- /* have supported functions */
-@@ -704,18 +705,30 @@ static Aml *aml_pci_pdsm(void)
- {
- Aml *pkg = aml_package(2);
-
-- aml_append(pkg, zero);
-- /*
-- * optional, if not impl. should return null string
-- */
-- aml_append(pkg, aml_string("%s", ""));
-- aml_append(ifctx, aml_store(pkg, ret));
--
- aml_append(ifctx, aml_store(aml_call2("AIDX", bnum, sunum), acpi_index));
-+ aml_append(ifctx, aml_store(pkg, ret));
- /*
-- * update acpi-index to actual value
-+ * Windows calls func=7 without checking if it's available,
-+ * as workaround Microsoft has suggested to return invalid for func7
-+ * Package, so return 2 elements package but only initialize elements
-+ * when acpi_index is supported and leave them uninitialized, which
-+ * leads elements to being Uninitialized ObjectType and should trip
-+ * Windows into discarding result as an unexpected and prevent setting
-+ * bogus 'PCI Label' on the device.
- */
-- aml_append(ifctx, aml_store(acpi_index, aml_index(ret, zero)));
-+ ifctx1 = aml_if(aml_lnot(aml_lor(
-+ aml_equal(acpi_index, zero), aml_equal(acpi_index, not_supp)
-+ )));
-+ {
-+ aml_append(ifctx1, aml_store(acpi_index, aml_index(ret, zero)));
-+ /*
-+ * optional, if not impl. should return null string
-+ */
-+ aml_append(ifctx1, aml_store(aml_string("%s", ""),
-+ aml_index(ret, one)));
-+ }
-+ aml_append(ifctx, ifctx1);
-+
- aml_append(ifctx, aml_return(ret));
- }
-
diff --git a/debian/patches/extra/0009-hw-usb-hcd-xhci-pci-Use-modulo-to-select-MSI-vector-.patch b/debian/patches/extra/0009-hw-usb-hcd-xhci-pci-Use-modulo-to-select-MSI-vector-.patch
deleted file mode 100644
index 780586c..0000000
--- a/debian/patches/extra/0009-hw-usb-hcd-xhci-pci-Use-modulo-to-select-MSI-vector-.patch
+++ /dev/null
@@ -1,53 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Phil Dennis-Jordan <phil@philjordan.eu>
-Date: Fri, 13 Dec 2024 17:06:14 +0100
-Subject: [PATCH] hw/usb/hcd-xhci-pci: Use modulo to select MSI vector as per
- spec
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-QEMU would crash with a failed assertion if the XHCI controller
-attempted to raise the interrupt on an interrupter corresponding
-to a MSI vector with a higher index than the highest configured
-for the device by the guest driver.
-
-This behaviour is correct on the MSI/PCI side: per PCI 3.0 spec,
-devices must ensure they do not send MSI notifications for
-vectors beyond the range of those allocated by the system/driver
-software. Unlike MSI-X, there is no generic way for handling
-aliasing in the case of fewer allocated vectors than requested,
-so the specifics are up to device implementors. (Section
-6.8.3.4. "Sending Messages")
-
-It turns out the XHCI spec (Implementation Note in section 4.17,
-"Interrupters") requires that the host controller signal the MSI
-vector with the number computed by taking the interrupter number
-modulo the number of enabled MSI vectors.
-
-This change introduces that modulo calculation, fixing the
-failed assertion. This makes the device work correctly in MSI mode
-with macOS's XHCI driver, which only allocates a single vector.
-
-Signed-off-by: Phil Dennis-Jordan <phil@philjordan.eu>
-Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
-Message-ID: <20250112210056.16658-2-phil@philjordan.eu>
-Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
-(cherry picked from commit bb5b7fced6b5d3334ab20702fc846e47bb1fb731)
-Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
----
- hw/usb/hcd-xhci-pci.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/hw/usb/hcd-xhci-pci.c b/hw/usb/hcd-xhci-pci.c
-index a039f5778a..516e6909d2 100644
---- a/hw/usb/hcd-xhci-pci.c
-+++ b/hw/usb/hcd-xhci-pci.c
-@@ -74,6 +74,7 @@ static bool xhci_pci_intr_raise(XHCIState *xhci, int n, bool level)
- }
-
- if (msi_enabled(pci_dev) && level) {
-+ n %= msi_nr_vectors_allocated(pci_dev);
- msi_notify(pci_dev, n);
- return true;
- }
diff --git a/debian/patches/extra/0010-pci-ensure-valid-link-status-bits-for-downstream-por.patch b/debian/patches/extra/0010-pci-ensure-valid-link-status-bits-for-downstream-por.patch
deleted file mode 100644
index f566570..0000000
--- a/debian/patches/extra/0010-pci-ensure-valid-link-status-bits-for-downstream-por.patch
+++ /dev/null
@@ -1,63 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Sebastian Ott <sebott@redhat.com>
-Date: Tue, 3 Dec 2024 13:19:28 +0100
-Subject: [PATCH] pci: ensure valid link status bits for downstream ports
-
-PCI hotplug for downstream endpoints on arm fails because Linux'
-PCIe hotplug driver doesn't like the QEMU provided LNKSTA:
-
- pcieport 0000:08:01.0: pciehp: Slot(2): Card present
- pcieport 0000:08:01.0: pciehp: Slot(2): Link Up
- pcieport 0000:08:01.0: pciehp: Slot(2): Cannot train link: status 0x2000
-
-There's 2 cases where LNKSTA isn't setup properly:
-* the downstream device has no express capability
-* max link width of the bridge is 0
-
-Move the sanity checks added via 88c869198aa63
-("pci: Sanity test minimum downstream LNKSTA") outside of the
-branch to make sure downstream ports always have a valid LNKSTA.
-
-Signed-off-by: Sebastian Ott <sebott@redhat.com>
-Tested-by: Zhenyu Zhang <zhenyzha@redhat.com>
-Message-Id: <20241203121928.14861-1-sebott@redhat.com>
-Reviewed-by: Alex Williamson <alex.williamson@redhat.com>
-Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
-Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
-(cherry picked from commit 694632fd44987cc4618612a38ad151047524a590)
-Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
----
- hw/pci/pcie.c | 12 ++++++++----
- 1 file changed, 8 insertions(+), 4 deletions(-)
-
-diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
-index 0b455c8654..1b12db6fa2 100644
---- a/hw/pci/pcie.c
-+++ b/hw/pci/pcie.c
-@@ -1113,18 +1113,22 @@ void pcie_sync_bridge_lnk(PCIDevice *bridge_dev)
- if ((lnksta & PCI_EXP_LNKSTA_NLW) > (lnkcap & PCI_EXP_LNKCAP_MLW)) {
- lnksta &= ~PCI_EXP_LNKSTA_NLW;
- lnksta |= lnkcap & PCI_EXP_LNKCAP_MLW;
-- } else if (!(lnksta & PCI_EXP_LNKSTA_NLW)) {
-- lnksta |= QEMU_PCI_EXP_LNKSTA_NLW(QEMU_PCI_EXP_LNK_X1);
- }
-
- if ((lnksta & PCI_EXP_LNKSTA_CLS) > (lnkcap & PCI_EXP_LNKCAP_SLS)) {
- lnksta &= ~PCI_EXP_LNKSTA_CLS;
- lnksta |= lnkcap & PCI_EXP_LNKCAP_SLS;
-- } else if (!(lnksta & PCI_EXP_LNKSTA_CLS)) {
-- lnksta |= QEMU_PCI_EXP_LNKSTA_CLS(QEMU_PCI_EXP_LNK_2_5GT);
- }
- }
-
-+ if (!(lnksta & PCI_EXP_LNKSTA_NLW)) {
-+ lnksta |= QEMU_PCI_EXP_LNKSTA_NLW(QEMU_PCI_EXP_LNK_X1);
-+ }
-+
-+ if (!(lnksta & PCI_EXP_LNKSTA_CLS)) {
-+ lnksta |= QEMU_PCI_EXP_LNKSTA_CLS(QEMU_PCI_EXP_LNK_2_5GT);
-+ }
-+
- pci_word_test_and_clear_mask(exp_cap + PCI_EXP_LNKSTA,
- PCI_EXP_LNKSTA_CLS | PCI_EXP_LNKSTA_NLW);
- pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA, lnksta &
diff --git a/debian/patches/extra/0011-pci-msix-Fix-msix-pba-read-vector-poll-end-calculati.patch b/debian/patches/extra/0011-pci-msix-Fix-msix-pba-read-vector-poll-end-calculati.patch
deleted file mode 100644
index 3ffee58..0000000
--- a/debian/patches/extra/0011-pci-msix-Fix-msix-pba-read-vector-poll-end-calculati.patch
+++ /dev/null
@@ -1,36 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Nicholas Piggin <npiggin@gmail.com>
-Date: Thu, 12 Dec 2024 22:04:02 +1000
-Subject: [PATCH] pci/msix: Fix msix pba read vector poll end calculation
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-The end vector calculation has a bug that results in polling fewer
-than required vectors when reading at a non-zero offset in PBA memory.
-
-Fixes: bbef882cc193 ("msi: add API to get notified about pending bit poll")
-Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
-Message-Id: <20241212120402.1475053-1-npiggin@gmail.com>
-Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
-Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
-Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
-(cherry picked from commit 42e2a7a0ab23784e44fcb18369e06067abc89305)
-Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
----
- hw/pci/msix.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/hw/pci/msix.c b/hw/pci/msix.c
-index 487e49834e..cc6e79ec67 100644
---- a/hw/pci/msix.c
-+++ b/hw/pci/msix.c
-@@ -250,7 +250,7 @@ static uint64_t msix_pba_mmio_read(void *opaque, hwaddr addr,
- PCIDevice *dev = opaque;
- if (dev->msix_vector_poll_notifier) {
- unsigned vector_start = addr * 8;
-- unsigned vector_end = MIN(addr + size * 8, dev->msix_entries_nr);
-+ unsigned vector_end = MIN((addr + size) * 8, dev->msix_entries_nr);
- dev->msix_vector_poll_notifier(dev, vector_start, vector_end);
- }
-
diff --git a/debian/patches/pve/0001-PVE-Config-block-file-change-locking-default-to-off.patch b/debian/patches/pve/0001-PVE-Config-block-file-change-locking-default-to-off.patch
index 72bd38d..60e6981 100644
--- a/debian/patches/pve/0001-PVE-Config-block-file-change-locking-default-to-off.patch
+++ b/debian/patches/pve/0001-PVE-Config-block-file-change-locking-default-to-off.patch
@@ -14,10 +14,10 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/block/file-posix.c b/block/file-posix.c
-index 90fa54352c..e2ea071315 100644
+index 56d1972d15..cfa0b832ba 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
-@@ -564,7 +564,7 @@ static QemuOptsList raw_runtime_opts = {
+@@ -565,7 +565,7 @@ static QemuOptsList raw_runtime_opts = {
{
.name = "locking",
.type = QEMU_OPT_STRING,
@@ -26,7 +26,7 @@ index 90fa54352c..e2ea071315 100644
},
{
.name = "pr-manager",
-@@ -664,7 +664,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
+@@ -665,7 +665,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
s->use_lock = false;
break;
case ON_OFF_AUTO_AUTO:
diff --git a/debian/patches/pve/0003-PVE-Config-set-the-CPU-model-to-kvm64-32-instead-of-.patch b/debian/patches/pve/0003-PVE-Config-set-the-CPU-model-to-kvm64-32-instead-of-.patch
index 516eb16..c960164 100644
--- a/debian/patches/pve/0003-PVE-Config-set-the-CPU-model-to-kvm64-32-instead-of-.patch
+++ b/debian/patches/pve/0003-PVE-Config-set-the-CPU-model-to-kvm64-32-instead-of-.patch
@@ -10,10 +10,10 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
-index 4c239a6970..be09263fb0 100644
+index 76f24446a5..2a47d79b49 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
-@@ -2475,9 +2475,9 @@ uint64_t cpu_get_tsc(CPUX86State *env);
+@@ -2556,9 +2556,9 @@ uint64_t cpu_get_tsc(CPUX86State *env);
#define CPU_RESOLVING_TYPE TYPE_X86_CPU
#ifdef TARGET_X86_64
diff --git a/debian/patches/pve/0004-PVE-Config-ui-spice-default-to-pve-certificates.patch b/debian/patches/pve/0004-PVE-Config-ui-spice-default-to-pve-certificates.patch
index b57ad9c..558f66e 100644
--- a/debian/patches/pve/0004-PVE-Config-ui-spice-default-to-pve-certificates.patch
+++ b/debian/patches/pve/0004-PVE-Config-ui-spice-default-to-pve-certificates.patch
@@ -9,7 +9,7 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/ui/spice-core.c b/ui/spice-core.c
-index bd9dbe03f1..a7ecaad9c7 100644
+index 0326c63bec..d523d00200 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -690,32 +690,35 @@ static void qemu_spice_init(void)
diff --git a/debian/patches/pve/0005-PVE-Config-glusterfs-no-default-logfile-if-daemonize.patch b/debian/patches/pve/0005-PVE-Config-glusterfs-no-default-logfile-if-daemonize.patch
index e957d0e..bbc9e36 100644
--- a/debian/patches/pve/0005-PVE-Config-glusterfs-no-default-logfile-if-daemonize.patch
+++ b/debian/patches/pve/0005-PVE-Config-glusterfs-no-default-logfile-if-daemonize.patch
@@ -9,7 +9,7 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/block/gluster.c b/block/gluster.c
-index e9c038042b..c8457a5014 100644
+index c6d25ae733..ccca125c3a 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -42,7 +42,7 @@
diff --git a/debian/patches/pve/0006-PVE-Config-rbd-block-rbd-disable-rbd_cache_writethro.patch b/debian/patches/pve/0006-PVE-Config-rbd-block-rbd-disable-rbd_cache_writethro.patch
index 7156d52..84e7a57 100644
--- a/debian/patches/pve/0006-PVE-Config-rbd-block-rbd-disable-rbd_cache_writethro.patch
+++ b/debian/patches/pve/0006-PVE-Config-rbd-block-rbd-disable-rbd_cache_writethro.patch
@@ -18,7 +18,7 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
1 file changed, 2 insertions(+)
diff --git a/block/rbd.c b/block/rbd.c
-index 04ed0e242e..728bce3b1e 100644
+index af984fb7db..bf143fac00 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -963,6 +963,8 @@ static int qemu_rbd_connect(rados_t *cluster, rados_ioctx_t *io_ctx,
diff --git a/debian/patches/pve/0007-PVE-Up-glusterfs-allow-partial-reads.patch b/debian/patches/pve/0007-PVE-Up-glusterfs-allow-partial-reads.patch
index 55967ce..92c539d 100644
--- a/debian/patches/pve/0007-PVE-Up-glusterfs-allow-partial-reads.patch
+++ b/debian/patches/pve/0007-PVE-Up-glusterfs-allow-partial-reads.patch
@@ -16,7 +16,7 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/block/gluster.c b/block/gluster.c
-index c8457a5014..c3a9555591 100644
+index ccca125c3a..301a653ea7 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -57,6 +57,7 @@ typedef struct GlusterAIOCB {
diff --git a/debian/patches/pve/0008-PVE-Up-qemu-img-return-success-on-info-without-snaps.patch b/debian/patches/pve/0008-PVE-Up-qemu-img-return-success-on-info-without-snaps.patch
index 45eacb9..f3ab731 100644
--- a/debian/patches/pve/0008-PVE-Up-qemu-img-return-success-on-info-without-snaps.patch
+++ b/debian/patches/pve/0008-PVE-Up-qemu-img-return-success-on-info-without-snaps.patch
@@ -9,7 +9,7 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/qemu-img.c b/qemu-img.c
-index 7668f86769..2575e97b43 100644
+index 2044c22a4c..4c8b5412c6 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -3075,7 +3075,8 @@ static int img_info(int argc, char **argv)
diff --git a/debian/patches/pve/0009-PVE-Up-qemu-img-dd-add-osize-and-read-from-to-stdin-.patch b/debian/patches/pve/0009-PVE-Up-qemu-img-dd-add-osize-and-read-from-to-stdin-.patch
index bc03837..0e8c047 100644
--- a/debian/patches/pve/0009-PVE-Up-qemu-img-dd-add-osize-and-read-from-to-stdin-.patch
+++ b/debian/patches/pve/0009-PVE-Up-qemu-img-dd-add-osize-and-read-from-to-stdin-.patch
@@ -54,10 +54,10 @@ index c9dd70a892..048788b23d 100644
DEF("info", img_info,
diff --git a/qemu-img.c b/qemu-img.c
-index 2575e97b43..8ec68b346f 100644
+index 4c8b5412c6..d5fa89a204 100644
--- a/qemu-img.c
+++ b/qemu-img.c
-@@ -4993,10 +4993,12 @@ static int img_bitmap(int argc, char **argv)
+@@ -4997,10 +4997,12 @@ static int img_bitmap(int argc, char **argv)
#define C_IF 04
#define C_OF 010
#define C_SKIP 020
@@ -70,7 +70,7 @@ index 2575e97b43..8ec68b346f 100644
};
struct DdIo {
-@@ -5072,6 +5074,19 @@ static int img_dd_skip(const char *arg,
+@@ -5076,6 +5078,19 @@ static int img_dd_skip(const char *arg,
return 0;
}
@@ -90,7 +90,7 @@ index 2575e97b43..8ec68b346f 100644
static int img_dd(int argc, char **argv)
{
int ret = 0;
-@@ -5112,6 +5127,7 @@ static int img_dd(int argc, char **argv)
+@@ -5116,6 +5131,7 @@ static int img_dd(int argc, char **argv)
{ "if", img_dd_if, C_IF },
{ "of", img_dd_of, C_OF },
{ "skip", img_dd_skip, C_SKIP },
@@ -98,7 +98,7 @@ index 2575e97b43..8ec68b346f 100644
{ NULL, NULL, 0 }
};
const struct option long_options[] = {
-@@ -5187,91 +5203,112 @@ static int img_dd(int argc, char **argv)
+@@ -5191,91 +5207,112 @@ static int img_dd(int argc, char **argv)
arg = NULL;
}
@@ -275,7 +275,7 @@ index 2575e97b43..8ec68b346f 100644
}
if (dd.flags & C_SKIP && (in.offset > INT64_MAX / in.bsz ||
-@@ -5288,20 +5325,43 @@ static int img_dd(int argc, char **argv)
+@@ -5292,20 +5329,43 @@ static int img_dd(int argc, char **argv)
in.buf = g_new(uint8_t, in.bsz);
for (out_pos = 0; in_pos < size; ) {
diff --git a/debian/patches/pve/0010-PVE-Up-qemu-img-dd-add-isize-parameter.patch b/debian/patches/pve/0010-PVE-Up-qemu-img-dd-add-isize-parameter.patch
index 31bbce2..af2c520 100644
--- a/debian/patches/pve/0010-PVE-Up-qemu-img-dd-add-isize-parameter.patch
+++ b/debian/patches/pve/0010-PVE-Up-qemu-img-dd-add-isize-parameter.patch
@@ -16,10 +16,10 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
1 file changed, 25 insertions(+), 3 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
-index 8ec68b346f..b98184bba1 100644
+index d5fa89a204..d458e85af2 100644
--- a/qemu-img.c
+++ b/qemu-img.c
-@@ -4994,11 +4994,13 @@ static int img_bitmap(int argc, char **argv)
+@@ -4998,11 +4998,13 @@ static int img_bitmap(int argc, char **argv)
#define C_OF 010
#define C_SKIP 020
#define C_OSIZE 040
@@ -33,7 +33,7 @@ index 8ec68b346f..b98184bba1 100644
};
struct DdIo {
-@@ -5087,6 +5089,19 @@ static int img_dd_osize(const char *arg,
+@@ -5091,6 +5093,19 @@ static int img_dd_osize(const char *arg,
return 0;
}
@@ -53,7 +53,7 @@ index 8ec68b346f..b98184bba1 100644
static int img_dd(int argc, char **argv)
{
int ret = 0;
-@@ -5101,12 +5116,14 @@ static int img_dd(int argc, char **argv)
+@@ -5105,12 +5120,14 @@ static int img_dd(int argc, char **argv)
int c, i;
const char *out_fmt = "raw";
const char *fmt = NULL;
@@ -69,7 +69,7 @@ index 8ec68b346f..b98184bba1 100644
};
struct DdIo in = {
.bsz = 512, /* Block size is by default 512 bytes */
-@@ -5128,6 +5145,7 @@ static int img_dd(int argc, char **argv)
+@@ -5132,6 +5149,7 @@ static int img_dd(int argc, char **argv)
{ "of", img_dd_of, C_OF },
{ "skip", img_dd_skip, C_SKIP },
{ "osize", img_dd_osize, C_OSIZE },
@@ -77,7 +77,7 @@ index 8ec68b346f..b98184bba1 100644
{ NULL, NULL, 0 }
};
const struct option long_options[] = {
-@@ -5324,9 +5342,10 @@ static int img_dd(int argc, char **argv)
+@@ -5328,9 +5346,10 @@ static int img_dd(int argc, char **argv)
in.buf = g_new(uint8_t, in.bsz);
@@ -90,7 +90,7 @@ index 8ec68b346f..b98184bba1 100644
if (blk1) {
in_ret = blk_pread(blk1, in_pos, bytes, in.buf, 0);
if (in_ret == 0) {
-@@ -5335,6 +5354,9 @@ static int img_dd(int argc, char **argv)
+@@ -5339,6 +5358,9 @@ static int img_dd(int argc, char **argv)
} else {
in_ret = read(STDIN_FILENO, in.buf, bytes);
if (in_ret == 0) {
diff --git a/debian/patches/pve/0011-PVE-Up-qemu-img-dd-add-n-skip_create.patch b/debian/patches/pve/0011-PVE-Up-qemu-img-dd-add-n-skip_create.patch
index a5bf769..cf94190 100644
--- a/debian/patches/pve/0011-PVE-Up-qemu-img-dd-add-n-skip_create.patch
+++ b/debian/patches/pve/0011-PVE-Up-qemu-img-dd-add-n-skip_create.patch
@@ -65,10 +65,10 @@ index 048788b23d..0b29a67a06 100644
DEF("info", img_info,
diff --git a/qemu-img.c b/qemu-img.c
-index b98184bba1..6fc8384f64 100644
+index d458e85af2..dc13efba8b 100644
--- a/qemu-img.c
+++ b/qemu-img.c
-@@ -5118,7 +5118,7 @@ static int img_dd(int argc, char **argv)
+@@ -5122,7 +5122,7 @@ static int img_dd(int argc, char **argv)
const char *fmt = NULL;
int64_t size = 0, readsize = 0;
int64_t out_pos, in_pos;
@@ -77,7 +77,7 @@ index b98184bba1..6fc8384f64 100644
struct DdInfo dd = {
.flags = 0,
.count = 0,
-@@ -5156,7 +5156,7 @@ static int img_dd(int argc, char **argv)
+@@ -5160,7 +5160,7 @@ static int img_dd(int argc, char **argv)
{ 0, 0, 0, 0 }
};
@@ -86,7 +86,7 @@ index b98184bba1..6fc8384f64 100644
if (c == EOF) {
break;
}
-@@ -5176,6 +5176,9 @@ static int img_dd(int argc, char **argv)
+@@ -5180,6 +5180,9 @@ static int img_dd(int argc, char **argv)
case 'h':
help();
break;
@@ -96,7 +96,7 @@ index b98184bba1..6fc8384f64 100644
case 'U':
force_share = true;
break;
-@@ -5306,13 +5309,15 @@ static int img_dd(int argc, char **argv)
+@@ -5310,13 +5313,15 @@ static int img_dd(int argc, char **argv)
size - in.bsz * in.offset, &error_abort);
}
diff --git a/debian/patches/pve/0012-qemu-img-dd-add-l-option-for-loading-a-snapshot.patch b/debian/patches/pve/0012-qemu-img-dd-add-l-option-for-loading-a-snapshot.patch
index 93a7380..493c61e 100644
--- a/debian/patches/pve/0012-qemu-img-dd-add-l-option-for-loading-a-snapshot.patch
+++ b/debian/patches/pve/0012-qemu-img-dd-add-l-option-for-loading-a-snapshot.patch
@@ -46,10 +46,10 @@ index 0b29a67a06..758f397232 100644
DEF("info", img_info,
diff --git a/qemu-img.c b/qemu-img.c
-index 6fc8384f64..a6c88e0860 100644
+index dc13efba8b..02f2e0aa45 100644
--- a/qemu-img.c
+++ b/qemu-img.c
-@@ -5110,6 +5110,7 @@ static int img_dd(int argc, char **argv)
+@@ -5114,6 +5114,7 @@ static int img_dd(int argc, char **argv)
BlockDriver *drv = NULL, *proto_drv = NULL;
BlockBackend *blk1 = NULL, *blk2 = NULL;
QemuOpts *opts = NULL;
@@ -57,7 +57,7 @@ index 6fc8384f64..a6c88e0860 100644
QemuOptsList *create_opts = NULL;
Error *local_err = NULL;
bool image_opts = false;
-@@ -5119,6 +5120,7 @@ static int img_dd(int argc, char **argv)
+@@ -5123,6 +5124,7 @@ static int img_dd(int argc, char **argv)
int64_t size = 0, readsize = 0;
int64_t out_pos, in_pos;
bool force_share = false, skip_create = false;
@@ -65,7 +65,7 @@ index 6fc8384f64..a6c88e0860 100644
struct DdInfo dd = {
.flags = 0,
.count = 0,
-@@ -5156,7 +5158,7 @@ static int img_dd(int argc, char **argv)
+@@ -5160,7 +5162,7 @@ static int img_dd(int argc, char **argv)
{ 0, 0, 0, 0 }
};
@@ -74,7 +74,7 @@ index 6fc8384f64..a6c88e0860 100644
if (c == EOF) {
break;
}
-@@ -5179,6 +5181,19 @@ static int img_dd(int argc, char **argv)
+@@ -5183,6 +5185,19 @@ static int img_dd(int argc, char **argv)
case 'n':
skip_create = true;
break;
@@ -94,7 +94,7 @@ index 6fc8384f64..a6c88e0860 100644
case 'U':
force_share = true;
break;
-@@ -5238,11 +5253,24 @@ static int img_dd(int argc, char **argv)
+@@ -5242,11 +5257,24 @@ static int img_dd(int argc, char **argv)
if (dd.flags & C_IF) {
blk1 = img_open(image_opts, in.filename, fmt, 0, false, false,
force_share);
@@ -120,7 +120,7 @@ index 6fc8384f64..a6c88e0860 100644
}
if (dd.flags & C_OSIZE) {
-@@ -5397,6 +5425,7 @@ static int img_dd(int argc, char **argv)
+@@ -5401,6 +5429,7 @@ static int img_dd(int argc, char **argv)
out:
g_free(arg);
qemu_opts_del(opts);
diff --git a/debian/patches/pve/0013-PVE-virtio-balloon-improve-query-balloon.patch b/debian/patches/pve/0013-PVE-virtio-balloon-improve-query-balloon.patch
index bb826a1..ec4b348 100644
--- a/debian/patches/pve/0013-PVE-virtio-balloon-improve-query-balloon.patch
+++ b/debian/patches/pve/0013-PVE-virtio-balloon-improve-query-balloon.patch
@@ -18,7 +18,7 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
4 files changed, 82 insertions(+), 4 deletions(-)
diff --git a/hw/core/machine-hmp-cmds.c b/hw/core/machine-hmp-cmds.c
-index 8701f00cc7..3b4c5ef403 100644
+index c6325cdcaa..7f817d622d 100644
--- a/hw/core/machine-hmp-cmds.c
+++ b/hw/core/machine-hmp-cmds.c
@@ -179,7 +179,35 @@ void hmp_info_balloon(Monitor *mon, const QDict *qdict)
@@ -59,7 +59,7 @@ index 8701f00cc7..3b4c5ef403 100644
qapi_free_BalloonInfo(info);
}
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
-index afd2ad6dd6..c724218c17 100644
+index 2eb5a14fa2..aa2fd6c32f 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -795,8 +795,37 @@ static uint64_t virtio_balloon_get_features(VirtIODevice *vdev, uint64_t f,
diff --git a/debian/patches/pve/0014-PVE-qapi-modify-query-machines.patch b/debian/patches/pve/0014-PVE-qapi-modify-query-machines.patch
index 9ff9090..3fa6209 100644
--- a/debian/patches/pve/0014-PVE-qapi-modify-query-machines.patch
+++ b/debian/patches/pve/0014-PVE-qapi-modify-query-machines.patch
@@ -13,10 +13,10 @@ Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/hw/core/machine-qmp-cmds.c b/hw/core/machine-qmp-cmds.c
-index 130217da8f..52a6d74820 100644
+index 1bc21b84a4..93fb4bc24a 100644
--- a/hw/core/machine-qmp-cmds.c
+++ b/hw/core/machine-qmp-cmds.c
-@@ -90,6 +90,12 @@ MachineInfoList *qmp_query_machines(bool has_compat_props, bool compat_props,
+@@ -91,6 +91,12 @@ MachineInfoList *qmp_query_machines(bool has_compat_props, bool compat_props,
info->numa_mem_supported = mc->numa_mem_supported;
info->deprecated = !!mc->deprecation_reason;
info->acpi = !!object_class_property_find(OBJECT_CLASS(mc), "acpi");
@@ -26,8 +26,8 @@ index 130217da8f..52a6d74820 100644
+ info->is_current = true;
+ }
+
- if (mc->default_cpu_type) {
- info->default_cpu_type = g_strdup(mc->default_cpu_type);
+ if (default_cpu_type) {
+ info->default_cpu_type = g_strdup(default_cpu_type);
}
diff --git a/qapi/machine.json b/qapi/machine.json
index 9f7ed0eaa0..16366b774a 100644
diff --git a/debian/patches/pve/0015-PVE-qapi-modify-spice-query.patch b/debian/patches/pve/0015-PVE-qapi-modify-spice-query.patch
index 1e4319e..cf85582 100644
--- a/debian/patches/pve/0015-PVE-qapi-modify-spice-query.patch
+++ b/debian/patches/pve/0015-PVE-qapi-modify-spice-query.patch
@@ -14,7 +14,7 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
2 files changed, 7 insertions(+)
diff --git a/qapi/ui.json b/qapi/ui.json
-index 460a26b981..42b911bda3 100644
+index c536d4e524..c2df48959b 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -312,11 +312,14 @@
@@ -33,7 +33,7 @@ index 460a26b981..42b911bda3 100644
'if': 'CONFIG_SPICE' }
diff --git a/ui/spice-core.c b/ui/spice-core.c
-index a7ecaad9c7..fecf002d50 100644
+index d523d00200..c76c224706 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -548,6 +548,10 @@ static SpiceInfo *qmp_query_spice_real(Error **errp)
diff --git a/debian/patches/pve/0016-PVE-add-IOChannel-implementation-for-savevm-async.patch b/debian/patches/pve/0016-PVE-add-IOChannel-implementation-for-savevm-async.patch
index 31cd174..0e69c98 100644
--- a/debian/patches/pve/0016-PVE-add-IOChannel-implementation-for-savevm-async.patch
+++ b/debian/patches/pve/0016-PVE-add-IOChannel-implementation-for-savevm-async.patch
@@ -25,7 +25,7 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
diff --git a/migration/channel-savevm-async.c b/migration/channel-savevm-async.c
new file mode 100644
-index 0000000000..081a192f49
+index 0000000000..e57ab2ae40
--- /dev/null
+++ b/migration/channel-savevm-async.c
@@ -0,0 +1,184 @@
@@ -35,7 +35,7 @@ index 0000000000..081a192f49
+#include "qemu/osdep.h"
+#include "migration/channel-savevm-async.h"
+#include "qapi/error.h"
-+#include "sysemu/block-backend.h"
++#include "system/block-backend.h"
+#include "trace.h"
+
+QIOChannelSavevmAsync *
@@ -271,14 +271,14 @@ index 0000000000..17ae2cb261
+
+#endif /* QIO_CHANNEL_SAVEVM_ASYNC_H */
diff --git a/migration/meson.build b/migration/meson.build
-index d53cf3417a..b00d58064d 100644
+index 9aa48b290e..cf66c78681 100644
--- a/migration/meson.build
+++ b/migration/meson.build
-@@ -13,6 +13,7 @@ system_ss.add(files(
- 'block-dirty-bitmap.c',
+@@ -14,6 +14,7 @@ system_ss.add(files(
+ 'block-active.c',
'channel.c',
'channel-block.c',
+ 'channel-savevm-async.c',
+ 'cpr.c',
+ 'cpr-transfer.c',
'cpu-throttle.c',
- 'dirtyrate.c',
- 'exec.c',
diff --git a/debian/patches/pve/0017-PVE-add-savevm-async-for-background-state-snapshots.patch b/debian/patches/pve/0017-PVE-add-savevm-async-for-background-state-snapshots.patch
index e558da6..6e19c3d 100644
--- a/debian/patches/pve/0017-PVE-add-savevm-async-for-background-state-snapshots.patch
+++ b/debian/patches/pve/0017-PVE-add-savevm-async-for-background-state-snapshots.patch
@@ -38,13 +38,13 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
include/migration/snapshot.h | 2 +
include/monitor/hmp.h | 3 +
migration/meson.build | 1 +
- migration/savevm-async.c | 571 +++++++++++++++++++++++++++++++++++
+ migration/savevm-async.c | 572 +++++++++++++++++++++++++++++++++++
monitor/hmp-cmds.c | 38 +++
qapi/migration.json | 34 +++
qapi/misc.json | 18 ++
qemu-options.hx | 12 +
system/vl.c | 10 +
- 11 files changed, 719 insertions(+)
+ 11 files changed, 720 insertions(+)
create mode 100644 migration/savevm-async.c
diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
@@ -129,10 +129,10 @@ index ae116d9804..2596cc2426 100644
void coroutine_fn hmp_screendump(Monitor *mon, const QDict *qdict);
void hmp_chardev_add(Monitor *mon, const QDict *qdict);
diff --git a/migration/meson.build b/migration/meson.build
-index b00d58064d..075b013971 100644
+index cf66c78681..46e92249a1 100644
--- a/migration/meson.build
+++ b/migration/meson.build
-@@ -29,6 +29,7 @@ system_ss.add(files(
+@@ -33,6 +33,7 @@ system_ss.add(files(
'options.c',
'postcopy-ram.c',
'savevm.c',
@@ -142,10 +142,10 @@ index b00d58064d..075b013971 100644
'threadinfo.c',
diff --git a/migration/savevm-async.c b/migration/savevm-async.c
new file mode 100644
-index 0000000000..ee8ef316d0
+index 0000000000..7c0e857519
--- /dev/null
+++ b/migration/savevm-async.c
-@@ -0,0 +1,571 @@
+@@ -0,0 +1,572 @@
+#include "qemu/osdep.h"
+#include "migration/channel-savevm-async.h"
+#include "migration/migration.h"
@@ -156,14 +156,14 @@ index 0000000000..ee8ef316d0
+#include "migration/global_state.h"
+#include "migration/ram.h"
+#include "migration/qemu-file.h"
-+#include "sysemu/cpu-throttle.h"
-+#include "sysemu/sysemu.h"
-+#include "sysemu/runstate.h"
++#include "system/cpu-throttle.h"
++#include "system/system.h"
++#include "system/runstate.h"
+#include "block/block.h"
-+#include "sysemu/block-backend.h"
++#include "system/block-backend.h"
+#include "qapi/error.h"
+#include "qapi/qmp/qerror.h"
-+#include "qapi/qmp/qdict.h"
++#include "qobject/qdict.h"
+#include "qapi/qapi-commands-migration.h"
+#include "qapi/qapi-commands-misc.h"
+#include "qapi/qapi-commands-block.h"
@@ -173,6 +173,7 @@ index 0000000000..ee8ef316d0
+#include "qemu/main-loop.h"
+#include "qemu/rcu.h"
+#include "qemu/yank.h"
++#include "system/iothread.h"
+
+/* #define DEBUG_SAVEVM_STATE */
+
@@ -333,7 +334,7 @@ index 0000000000..ee8ef316d0
+
+ if (!aborted) {
+ /* skip state saving if we aborted, snapshot will be invalid anyway */
-+ (void)qemu_savevm_state_complete_precopy(snap_state.file, false, false);
++ (void)qemu_savevm_state_complete_precopy(snap_state.file, false);
+ ret = qemu_file_get_error(snap_state.file);
+ if (ret < 0) {
+ save_snapshot_error("qemu_savevm_state_complete_precopy error %d", ret);
@@ -718,7 +719,7 @@ index 0000000000..ee8ef316d0
+ return ret;
+}
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
-index f601d06ab8..874084565f 100644
+index 7ded3378cf..bade2a4b92 100644
--- a/monitor/hmp-cmds.c
+++ b/monitor/hmp-cmds.c
@@ -24,6 +24,7 @@
@@ -727,10 +728,10 @@ index f601d06ab8..874084565f 100644
#include "qapi/qapi-commands-machine.h"
+#include "qapi/qapi-commands-migration.h"
#include "qapi/qapi-commands-misc.h"
- #include "qapi/qmp/qdict.h"
+ #include "qobject/qdict.h"
#include "qemu/cutils.h"
@@ -434,3 +435,40 @@ void hmp_dumpdtb(Monitor *mon, const QDict *qdict)
- monitor_printf(mon, "dtb dumped to %s", filename);
+ monitor_printf(mon, "DTB dumped to '%s'\n", filename);
}
#endif
+
@@ -771,10 +772,10 @@ index f601d06ab8..874084565f 100644
+ }
+}
diff --git a/qapi/migration.json b/qapi/migration.json
-index a605dc26db..927b1e1c7d 100644
+index 8b9c53595c..ff3479da65 100644
--- a/qapi/migration.json
+++ b/qapi/migration.json
-@@ -276,6 +276,40 @@
+@@ -279,6 +279,40 @@
'*dirty-limit-throttle-time-per-round': 'uint64',
'*dirty-limit-ring-full-time': 'uint64'} }
@@ -845,10 +846,10 @@ index 559b66f201..7959e89c1e 100644
# @CommandLineParameterType:
#
diff --git a/qemu-options.hx b/qemu-options.hx
-index dacc9790a4..c05f411599 100644
+index dc694a99a3..defee0c06a 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
-@@ -4764,6 +4764,18 @@ SRST
+@@ -4862,6 +4862,18 @@ SRST
Start right away with a saved state (``loadvm`` in monitor)
ERST
@@ -868,10 +869,10 @@ index dacc9790a4..c05f411599 100644
DEF("daemonize", 0, QEMU_OPTION_daemonize, \
"-daemonize daemonize QEMU after initializing\n", QEMU_ARCH_ALL)
diff --git a/system/vl.c b/system/vl.c
-index 2f855d83fb..39d451bb41 100644
+index ec93988a03..9b36ace6b4 100644
--- a/system/vl.c
+++ b/system/vl.c
-@@ -164,6 +164,7 @@ static const char *accelerators;
+@@ -171,6 +171,7 @@ static const char *accelerators;
static bool have_custom_ram_size;
static const char *ram_memdev_id;
static QDict *machine_opts_dict;
@@ -879,7 +880,7 @@ index 2f855d83fb..39d451bb41 100644
static QTAILQ_HEAD(, ObjectOption) object_opts = QTAILQ_HEAD_INITIALIZER(object_opts);
static QTAILQ_HEAD(, DeviceOption) device_opts = QTAILQ_HEAD_INITIALIZER(device_opts);
static int display_remote;
-@@ -2725,6 +2726,12 @@ void qmp_x_exit_preconfig(Error **errp)
+@@ -2814,6 +2815,12 @@ void qmp_x_exit_preconfig(Error **errp)
RunState state = autostart ? RUN_STATE_RUNNING : runstate_get();
load_snapshot(loadvm, NULL, false, NULL, &error_fatal);
load_snapshot_resume(state);
@@ -892,7 +893,7 @@ index 2f855d83fb..39d451bb41 100644
}
if (replay_mode != REPLAY_MODE_NONE) {
replay_vmstate_init();
-@@ -3262,6 +3269,9 @@ void qemu_init(int argc, char **argv)
+@@ -3360,6 +3367,9 @@ void qemu_init(int argc, char **argv)
case QEMU_OPTION_loadvm:
loadvm = optarg;
break;
diff --git a/debian/patches/pve/0018-PVE-add-optional-buffer-size-to-QEMUFile.patch b/debian/patches/pve/0018-PVE-add-optional-buffer-size-to-QEMUFile.patch
index 93598cf..13d522a 100644
--- a/debian/patches/pve/0018-PVE-add-optional-buffer-size-to-QEMUFile.patch
+++ b/debian/patches/pve/0018-PVE-add-optional-buffer-size-to-QEMUFile.patch
@@ -19,7 +19,7 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
3 files changed, 38 insertions(+), 17 deletions(-)
diff --git a/migration/qemu-file.c b/migration/qemu-file.c
-index b6d2f588bd..754dc0b3f7 100644
+index 1303a5bf58..6e2d58d5c0 100644
--- a/migration/qemu-file.c
+++ b/migration/qemu-file.c
@@ -34,8 +34,8 @@
@@ -31,9 +31,9 @@ index b6d2f588bd..754dc0b3f7 100644
+#define DEFAULT_IO_BUF_SIZE 32768
+#define MAX_IOV_SIZE MIN_CONST(IOV_MAX, 256)
- struct QEMUFile {
- QIOChannel *ioc;
-@@ -43,7 +43,8 @@ struct QEMUFile {
+ typedef struct FdEntry {
+ QTAILQ_ENTRY(FdEntry) entry;
+@@ -48,7 +48,8 @@ struct QEMUFile {
int buf_index;
int buf_size; /* 0 when writing */
@@ -43,7 +43,7 @@ index b6d2f588bd..754dc0b3f7 100644
DECLARE_BITMAP(may_free, MAX_IOV_SIZE);
struct iovec iov[MAX_IOV_SIZE];
-@@ -100,7 +101,9 @@ int qemu_file_shutdown(QEMUFile *f)
+@@ -108,7 +109,9 @@ int qemu_file_shutdown(QEMUFile *f)
return 0;
}
@@ -54,16 +54,16 @@ index b6d2f588bd..754dc0b3f7 100644
{
QEMUFile *f;
-@@ -109,6 +112,8 @@ static QEMUFile *qemu_file_new_impl(QIOChannel *ioc, bool is_writable)
- object_ref(ioc);
- f->ioc = ioc;
+@@ -119,6 +122,8 @@ static QEMUFile *qemu_file_new_impl(QIOChannel *ioc, bool is_writable)
f->is_writable = is_writable;
+ f->can_pass_fd = qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_FD_PASS);
+ QTAILQ_INIT(&f->fds);
+ f->buf_allocated_size = buffer_size;
+ f->buf = malloc(buffer_size);
return f;
}
-@@ -119,17 +124,27 @@ static QEMUFile *qemu_file_new_impl(QIOChannel *ioc, bool is_writable)
+@@ -129,17 +134,27 @@ static QEMUFile *qemu_file_new_impl(QIOChannel *ioc, bool is_writable)
*/
QEMUFile *qemu_file_get_return_path(QEMUFile *f)
{
@@ -94,17 +94,17 @@ index b6d2f588bd..754dc0b3f7 100644
}
/*
-@@ -327,7 +342,7 @@ static ssize_t coroutine_mixed_fn qemu_fill_buffer(QEMUFile *f)
+@@ -339,7 +354,7 @@ static ssize_t coroutine_mixed_fn qemu_fill_buffer(QEMUFile *f)
+ }
+
do {
- len = qio_channel_read(f->ioc,
- (char *)f->buf + pending,
-- IO_BUF_SIZE - pending,
-+ f->buf_allocated_size - pending,
- &local_error);
+- struct iovec iov = { f->buf + pending, IO_BUF_SIZE - pending };
++ struct iovec iov = { f->buf + pending, f->buf_allocated_size - pending };
+ len = qio_channel_readv_full(f->ioc, &iov, 1, pfds, pnfd, 0,
+ &local_error);
if (len == QIO_CHANNEL_ERR_BLOCK) {
- if (qemu_in_coroutine()) {
-@@ -367,6 +382,9 @@ int qemu_fclose(QEMUFile *f)
- ret = ret2;
+@@ -443,6 +458,9 @@ int qemu_fclose(QEMUFile *f)
+ g_free(fde);
}
g_clear_pointer(&f->ioc, object_unref);
+
@@ -113,7 +113,7 @@ index b6d2f588bd..754dc0b3f7 100644
error_free(f->last_error_obj);
g_free(f);
trace_qemu_file_fclose();
-@@ -415,7 +433,7 @@ static void add_buf_to_iovec(QEMUFile *f, size_t len)
+@@ -491,7 +509,7 @@ static void add_buf_to_iovec(QEMUFile *f, size_t len)
{
if (!add_to_iovec(f, f->buf + f->buf_index, len, false)) {
f->buf_index += len;
@@ -122,7 +122,7 @@ index b6d2f588bd..754dc0b3f7 100644
qemu_fflush(f);
}
}
-@@ -440,7 +458,7 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, size_t size)
+@@ -516,7 +534,7 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, size_t size)
}
while (size > 0) {
@@ -131,7 +131,7 @@ index b6d2f588bd..754dc0b3f7 100644
if (l > size) {
l = size;
}
-@@ -586,8 +604,8 @@ size_t coroutine_mixed_fn qemu_peek_buffer(QEMUFile *f, uint8_t **buf, size_t si
+@@ -662,8 +680,8 @@ size_t coroutine_mixed_fn qemu_peek_buffer(QEMUFile *f, uint8_t **buf, size_t si
size_t index;
assert(!qemu_file_is_writable(f));
@@ -142,7 +142,7 @@ index b6d2f588bd..754dc0b3f7 100644
/* The 1st byte to read from */
index = f->buf_index + offset;
-@@ -637,7 +655,7 @@ size_t coroutine_mixed_fn qemu_get_buffer(QEMUFile *f, uint8_t *buf, size_t size
+@@ -713,7 +731,7 @@ size_t coroutine_mixed_fn qemu_get_buffer(QEMUFile *f, uint8_t *buf, size_t size
size_t res;
uint8_t *src;
@@ -151,7 +151,7 @@ index b6d2f588bd..754dc0b3f7 100644
if (res == 0) {
return done;
}
-@@ -671,7 +689,7 @@ size_t coroutine_mixed_fn qemu_get_buffer(QEMUFile *f, uint8_t *buf, size_t size
+@@ -747,7 +765,7 @@ size_t coroutine_mixed_fn qemu_get_buffer(QEMUFile *f, uint8_t *buf, size_t size
*/
size_t coroutine_mixed_fn qemu_get_buffer_in_place(QEMUFile *f, uint8_t **buf, size_t size)
{
@@ -160,7 +160,7 @@ index b6d2f588bd..754dc0b3f7 100644
size_t res;
uint8_t *src = NULL;
-@@ -696,7 +714,7 @@ int coroutine_mixed_fn qemu_peek_byte(QEMUFile *f, int offset)
+@@ -772,7 +790,7 @@ int coroutine_mixed_fn qemu_peek_byte(QEMUFile *f, int offset)
int index = f->buf_index + offset;
assert(!qemu_file_is_writable(f));
@@ -170,7 +170,7 @@ index b6d2f588bd..754dc0b3f7 100644
if (index >= f->buf_size) {
qemu_fill_buffer(f);
diff --git a/migration/qemu-file.h b/migration/qemu-file.h
-index 11c2120edd..edf3c5d147 100644
+index f5b9f430e0..0179b90698 100644
--- a/migration/qemu-file.h
+++ b/migration/qemu-file.h
@@ -30,7 +30,9 @@
@@ -182,12 +182,12 @@ index 11c2120edd..edf3c5d147 100644
+QEMUFile *qemu_file_new_output_sized(QIOChannel *ioc, size_t buffer_size);
int qemu_fclose(QEMUFile *f);
- /*
+ G_DEFINE_AUTOPTR_CLEANUP_FUNC(QEMUFile, qemu_fclose)
diff --git a/migration/savevm-async.c b/migration/savevm-async.c
-index ee8ef316d0..1e79fce9ba 100644
+index 7c0e857519..fbcf74f9e2 100644
--- a/migration/savevm-async.c
+++ b/migration/savevm-async.c
-@@ -390,7 +390,7 @@ void qmp_savevm_start(const char *statefile, Error **errp)
+@@ -391,7 +391,7 @@ void qmp_savevm_start(const char *statefile, Error **errp)
QIOChannel *ioc = QIO_CHANNEL(qio_channel_savevm_async_new(snap_state.target,
&snap_state.bs_pos));
@@ -196,7 +196,7 @@ index ee8ef316d0..1e79fce9ba 100644
if (!snap_state.file) {
error_setg(errp, "failed to open '%s'", statefile);
-@@ -534,7 +534,8 @@ int load_snapshot_from_blockdev(const char *filename, Error **errp)
+@@ -535,7 +535,8 @@ int load_snapshot_from_blockdev(const char *filename, Error **errp)
bdrv_op_block_all(bs, blocker);
/* restore the VM state */
diff --git a/debian/patches/pve/0019-PVE-block-add-the-zeroinit-block-driver-filter.patch b/debian/patches/pve/0019-PVE-block-add-the-zeroinit-block-driver-filter.patch
index 360f54e..dc1145d 100644
--- a/debian/patches/pve/0019-PVE-block-add-the-zeroinit-block-driver-filter.patch
+++ b/debian/patches/pve/0019-PVE-block-add-the-zeroinit-block-driver-filter.patch
@@ -15,7 +15,7 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
create mode 100644 block/zeroinit.c
diff --git a/block/meson.build b/block/meson.build
-index f1262ec2ba..6a60b5d6b9 100644
+index 34b1b2a306..a21d9a5411 100644
--- a/block/meson.build
+++ b/block/meson.build
@@ -39,6 +39,7 @@ block_ss.add(files(
@@ -28,7 +28,7 @@ index f1262ec2ba..6a60b5d6b9 100644
system_ss.add(when: 'CONFIG_TCG', if_true: files('blkreplay.c'))
diff --git a/block/zeroinit.c b/block/zeroinit.c
new file mode 100644
-index 0000000000..2b2b194ccf
+index 0000000000..f9d513db15
--- /dev/null
+++ b/block/zeroinit.c
@@ -0,0 +1,207 @@
@@ -47,8 +47,8 @@ index 0000000000..2b2b194ccf
+#include "block/block_int.h"
+#include "block/block-io.h"
+#include "block/graph-lock.h"
-+#include "qapi/qmp/qdict.h"
-+#include "qapi/qmp/qstring.h"
++#include "qobject/qdict.h"
++#include "qobject/qstring.h"
+#include "qemu/cutils.h"
+#include "qemu/option.h"
+#include "qemu/module.h"
diff --git a/debian/patches/pve/0020-PVE-Add-dummy-id-command-line-parameter.patch b/debian/patches/pve/0020-PVE-Add-dummy-id-command-line-parameter.patch
index 1145940..1f7383c 100644
--- a/debian/patches/pve/0020-PVE-Add-dummy-id-command-line-parameter.patch
+++ b/debian/patches/pve/0020-PVE-Add-dummy-id-command-line-parameter.patch
@@ -14,10 +14,10 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
2 files changed, 11 insertions(+)
diff --git a/qemu-options.hx b/qemu-options.hx
-index c05f411599..0732077a0e 100644
+index defee0c06a..fb980a05cf 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
-@@ -1239,6 +1239,9 @@ legacy PC, they are not recommended for modern configurations.
+@@ -1280,6 +1280,9 @@ legacy PC, they are not recommended for modern configurations.
ERST
@@ -28,10 +28,10 @@ index c05f411599..0732077a0e 100644
"-fda/-fdb file use 'file' as floppy disk 0/1 image\n", QEMU_ARCH_ALL)
DEF("fdb", HAS_ARG, QEMU_OPTION_fdb, "", QEMU_ARCH_ALL)
diff --git a/system/vl.c b/system/vl.c
-index 39d451bb41..e7cae51f13 100644
+index 9b36ace6b4..452742ab58 100644
--- a/system/vl.c
+++ b/system/vl.c
-@@ -2762,6 +2762,7 @@ void qemu_init(int argc, char **argv)
+@@ -2854,6 +2854,7 @@ void qemu_init(int argc, char **argv)
MachineClass *machine_class;
bool userconfig = true;
FILE *vmstate_dump_file = NULL;
@@ -39,7 +39,7 @@ index 39d451bb41..e7cae51f13 100644
qemu_add_opts(&qemu_drive_opts);
qemu_add_drive_opts(&qemu_legacy_drive_opts);
-@@ -3374,6 +3375,13 @@ void qemu_init(int argc, char **argv)
+@@ -3472,6 +3473,13 @@ void qemu_init(int argc, char **argv)
machine_parse_property_opt(qemu_find_opts("smp-opts"),
"smp", optarg);
break;
diff --git a/debian/patches/pve/0021-PVE-Config-Revert-target-i386-disable-LINT0-after-re.patch b/debian/patches/pve/0021-PVE-Config-Revert-target-i386-disable-LINT0-after-re.patch
index b353e47..67c542b 100644
--- a/debian/patches/pve/0021-PVE-Config-Revert-target-i386-disable-LINT0-after-re.patch
+++ b/debian/patches/pve/0021-PVE-Config-Revert-target-i386-disable-LINT0-after-re.patch
@@ -11,7 +11,7 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
1 file changed, 9 insertions(+)
diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c
-index 62f3bbf203..89e0c7d995 100644
+index 2a3e878c4d..efbed1aea3 100644
--- a/hw/intc/apic_common.c
+++ b/hw/intc/apic_common.c
@@ -263,6 +263,15 @@ static void apic_reset_common(DeviceState *dev)
diff --git a/debian/patches/pve/0022-PVE-Up-Config-file-posix-make-locking-optiono-on-cre.patch b/debian/patches/pve/0022-PVE-Up-Config-file-posix-make-locking-optiono-on-cre.patch
index bb1b37e..bf230a5 100644
--- a/debian/patches/pve/0022-PVE-Up-Config-file-posix-make-locking-optiono-on-cre.patch
+++ b/debian/patches/pve/0022-PVE-Up-Config-file-posix-make-locking-optiono-on-cre.patch
@@ -13,10 +13,10 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
2 files changed, 46 insertions(+), 20 deletions(-)
diff --git a/block/file-posix.c b/block/file-posix.c
-index e2ea071315..4c3dc56c8e 100644
+index cfa0b832ba..d5c28cccc9 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
-@@ -2884,6 +2884,7 @@ raw_co_create(BlockdevCreateOptions *options, Error **errp)
+@@ -2897,6 +2897,7 @@ raw_co_create(BlockdevCreateOptions *options, Error **errp)
int fd;
uint64_t perm, shared;
int result = 0;
@@ -24,7 +24,7 @@ index e2ea071315..4c3dc56c8e 100644
/* Validate options and set default values */
assert(options->driver == BLOCKDEV_DRIVER_FILE);
-@@ -2924,19 +2925,22 @@ raw_co_create(BlockdevCreateOptions *options, Error **errp)
+@@ -2937,19 +2938,22 @@ raw_co_create(BlockdevCreateOptions *options, Error **errp)
perm = BLK_PERM_WRITE | BLK_PERM_RESIZE;
shared = BLK_PERM_ALL & ~BLK_PERM_RESIZE;
@@ -59,7 +59,7 @@ index e2ea071315..4c3dc56c8e 100644
}
/* Clear the file by truncating it to 0 */
-@@ -2990,13 +2994,15 @@ raw_co_create(BlockdevCreateOptions *options, Error **errp)
+@@ -3003,13 +3007,15 @@ raw_co_create(BlockdevCreateOptions *options, Error **errp)
}
out_unlock:
@@ -82,7 +82,7 @@ index e2ea071315..4c3dc56c8e 100644
}
out_close:
-@@ -3020,6 +3026,7 @@ raw_co_create_opts(BlockDriver *drv, const char *filename,
+@@ -3033,6 +3039,7 @@ raw_co_create_opts(BlockDriver *drv, const char *filename,
PreallocMode prealloc;
char *buf = NULL;
Error *local_err = NULL;
@@ -90,7 +90,7 @@ index e2ea071315..4c3dc56c8e 100644
/* Skip file: protocol prefix */
strstart(filename, "file:", &filename);
-@@ -3042,6 +3049,18 @@ raw_co_create_opts(BlockDriver *drv, const char *filename,
+@@ -3055,6 +3062,18 @@ raw_co_create_opts(BlockDriver *drv, const char *filename,
return -EINVAL;
}
@@ -109,7 +109,7 @@ index e2ea071315..4c3dc56c8e 100644
options = (BlockdevCreateOptions) {
.driver = BLOCKDEV_DRIVER_FILE,
.u.file = {
-@@ -3053,6 +3072,8 @@ raw_co_create_opts(BlockDriver *drv, const char *filename,
+@@ -3066,6 +3085,8 @@ raw_co_create_opts(BlockDriver *drv, const char *filename,
.nocow = nocow,
.has_extent_size_hint = has_extent_size_hint,
.extent_size_hint = extent_size_hint,
@@ -119,10 +119,10 @@ index e2ea071315..4c3dc56c8e 100644
};
return raw_co_create(&options, errp);
diff --git a/qapi/block-core.json b/qapi/block-core.json
-index 48ba32049f..321d1fd0e1 100644
+index 0e5f148d30..1c05413916 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
-@@ -4974,6 +4974,10 @@
+@@ -5016,6 +5016,10 @@
# @extent-size-hint: Extent size hint to add to the image file; 0 for
# not adding an extent size hint (default: 1 MB, since 5.1)
#
@@ -133,7 +133,7 @@ index 48ba32049f..321d1fd0e1 100644
# Since: 2.12
##
{ 'struct': 'BlockdevCreateOptionsFile',
-@@ -4981,7 +4985,8 @@
+@@ -5023,7 +5027,8 @@
'size': 'size',
'*preallocation': 'PreallocMode',
'*nocow': 'bool',
diff --git a/debian/patches/pve/0023-PVE-monitor-disable-oob-capability.patch b/debian/patches/pve/0023-PVE-monitor-disable-oob-capability.patch
index c7e00c9..569fe89 100644
--- a/debian/patches/pve/0023-PVE-monitor-disable-oob-capability.patch
+++ b/debian/patches/pve/0023-PVE-monitor-disable-oob-capability.patch
@@ -18,7 +18,7 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/monitor/qmp.c b/monitor/qmp.c
-index eb181d5979..20fc0d20a6 100644
+index f093e256e9..78f1c8e3c8 100644
--- a/monitor/qmp.c
+++ b/monitor/qmp.c
@@ -534,8 +534,7 @@ void monitor_init_qmp(Chardev *chr, bool pretty, Error **errp)
diff --git a/debian/patches/pve/0024-PVE-Compat-4.0-used-balloon-qemu-4-0-config-size-fal.patch b/debian/patches/pve/0024-PVE-Compat-4.0-used-balloon-qemu-4-0-config-size-fal.patch
index acc6583..d180117 100644
--- a/debian/patches/pve/0024-PVE-Compat-4.0-used-balloon-qemu-4-0-config-size-fal.patch
+++ b/debian/patches/pve/0024-PVE-Compat-4.0-used-balloon-qemu-4-0-config-size-fal.patch
@@ -26,10 +26,10 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/hw/core/machine.c b/hw/core/machine.c
-index f29fe95964..2c327fc36a 100644
+index 63c6ef93d2..9a34017e5a 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
-@@ -180,7 +180,8 @@ GlobalProperty hw_compat_4_0[] = {
+@@ -193,7 +193,8 @@ GlobalProperty hw_compat_4_0[] = {
{ "virtio-vga", "edid", "false" },
{ "virtio-gpu-device", "edid", "false" },
{ "virtio-device", "use-started", "false" },
diff --git a/debian/patches/pve/0025-PVE-Allow-version-code-in-machine-type.patch b/debian/patches/pve/0025-PVE-Allow-version-code-in-machine-type.patch
index 10a6bc1..14de9e8 100644
--- a/debian/patches/pve/0025-PVE-Allow-version-code-in-machine-type.patch
+++ b/debian/patches/pve/0025-PVE-Allow-version-code-in-machine-type.patch
@@ -21,10 +21,10 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
4 files changed, 34 insertions(+)
diff --git a/hw/core/machine-qmp-cmds.c b/hw/core/machine-qmp-cmds.c
-index 52a6d74820..362128842d 100644
+index 93fb4bc24a..b9999423b4 100644
--- a/hw/core/machine-qmp-cmds.c
+++ b/hw/core/machine-qmp-cmds.c
-@@ -94,6 +94,11 @@ MachineInfoList *qmp_query_machines(bool has_compat_props, bool compat_props,
+@@ -95,6 +95,11 @@ MachineInfoList *qmp_query_machines(bool has_compat_props, bool compat_props,
if (strcmp(mc->name, MACHINE_GET_CLASS(current_machine)->name) == 0) {
info->has_is_current = true;
info->is_current = true;
@@ -35,12 +35,12 @@ index 52a6d74820..362128842d 100644
+ }
}
- if (mc->default_cpu_type) {
+ if (default_cpu_type) {
diff --git a/include/hw/boards.h b/include/hw/boards.h
-index 36fbb9b59d..d1741ea121 100644
+index f22b2e7fc7..8ada4d5832 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
-@@ -268,6 +268,8 @@ struct MachineClass {
+@@ -271,6 +271,8 @@ struct MachineClass {
const char *desc;
const char *deprecation_reason;
@@ -71,10 +71,10 @@ index 16366b774a..12cfd3f260 100644
'features': ['unstable'] } } }
diff --git a/system/vl.c b/system/vl.c
-index e7cae51f13..3f4916ac5a 100644
+index 452742ab58..c3707b2412 100644
--- a/system/vl.c
+++ b/system/vl.c
-@@ -1675,6 +1675,7 @@ static MachineClass *select_machine(QDict *qdict, Error **errp)
+@@ -1674,6 +1674,7 @@ static MachineClass *select_machine(QDict *qdict, Error **errp)
{
ERRP_GUARD();
const char *machine_type = qdict_get_try_str(qdict, "type");
@@ -82,7 +82,7 @@ index e7cae51f13..3f4916ac5a 100644
g_autoptr(GSList) machines = object_class_get_list(TYPE_MACHINE, false);
MachineClass *machine_class = NULL;
-@@ -1694,7 +1695,11 @@ static MachineClass *select_machine(QDict *qdict, Error **errp)
+@@ -1693,7 +1694,11 @@ static MachineClass *select_machine(QDict *qdict, Error **errp)
if (!machine_class) {
error_append_hint(errp,
"Use -machine help to list supported machines\n");
@@ -94,7 +94,7 @@ index e7cae51f13..3f4916ac5a 100644
return machine_class;
}
-@@ -3316,12 +3321,31 @@ void qemu_init(int argc, char **argv)
+@@ -3414,12 +3419,31 @@ void qemu_init(int argc, char **argv)
case QEMU_OPTION_machine:
{
bool help;
diff --git a/debian/patches/pve/0026-block-backup-move-bcs-bitmap-initialization-to-job-c.patch b/debian/patches/pve/0026-block-backup-move-bcs-bitmap-initialization-to-job-c.patch
index efdfe39..23adf3b 100644
--- a/debian/patches/pve/0026-block-backup-move-bcs-bitmap-initialization-to-job-c.patch
+++ b/debian/patches/pve/0026-block-backup-move-bcs-bitmap-initialization-to-job-c.patch
@@ -25,7 +25,7 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/block/backup.c b/block/backup.c
-index a1292c01ec..2e38b30d67 100644
+index 79652bf57b..cc747e9163 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -237,8 +237,8 @@ static void backup_init_bcs_bitmap(BackupBlockJob *job)
diff --git a/debian/patches/pve/0027-PVE-Backup-add-vma-backup-format-code.patch b/debian/patches/pve/0027-PVE-Backup-add-vma-backup-format-code.patch
index aa60306..8b88b69 100644
--- a/debian/patches/pve/0027-PVE-Backup-add-vma-backup-format-code.patch
+++ b/debian/patches/pve/0027-PVE-Backup-add-vma-backup-format-code.patch
@@ -27,7 +27,7 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
create mode 100644 vma.h
diff --git a/block/meson.build b/block/meson.build
-index 6a60b5d6b9..652c8cbdb7 100644
+index a21d9a5411..1373612c10 100644
--- a/block/meson.build
+++ b/block/meson.build
@@ -42,6 +42,8 @@ block_ss.add(files(
@@ -40,10 +40,10 @@ index 6a60b5d6b9..652c8cbdb7 100644
system_ss.add(files('block-ram-registrar.c'))
diff --git a/meson.build b/meson.build
-index 147097c652..b9b673c271 100644
+index 8ec796d835..680ab48b9b 100644
--- a/meson.build
+++ b/meson.build
-@@ -2129,6 +2129,8 @@ endif
+@@ -2161,6 +2161,8 @@ endif
has_gettid = cc.has_function('gettid')
@@ -52,7 +52,7 @@ index 147097c652..b9b673c271 100644
# libselinux
selinux = dependency('libselinux',
required: get_option('selinux'),
-@@ -4344,6 +4346,9 @@ if have_tools
+@@ -4367,6 +4369,9 @@ if have_tools
dependencies: [blockdev, qemuutil, selinux],
install: true)
@@ -64,7 +64,7 @@ index 147097c652..b9b673c271 100644
foreach exe: [ 'qemu-img', 'qemu-io', 'qemu-nbd', 'qemu-storage-daemon']
diff --git a/vma-reader.c b/vma-reader.c
new file mode 100644
-index 0000000000..bb65ad313c
+index 0000000000..1888b21851
--- /dev/null
+++ b/vma-reader.c
@@ -0,0 +1,867 @@
@@ -90,7 +90,7 @@ index 0000000000..bb65ad313c
+#include "vma.h"
+#include "block/block.h"
+#include "block/graph-lock.h"
-+#include "sysemu/block-backend.h"
++#include "system/block-backend.h"
+
+static unsigned char zero_vma_block[VMA_BLOCK_SIZE];
+
@@ -1759,7 +1759,7 @@ index 0000000000..3f489092df
+}
diff --git a/vma.c b/vma.c
new file mode 100644
-index 0000000000..8d4b4be414
+index 0000000000..0e990b5e30
--- /dev/null
+++ b/vma.c
@@ -0,0 +1,941 @@
@@ -1785,8 +1785,8 @@ index 0000000000..8d4b4be414
+#include "qemu/main-loop.h"
+#include "qemu/cutils.h"
+#include "qemu/memalign.h"
-+#include "qapi/qmp/qdict.h"
-+#include "sysemu/block-backend.h"
++#include "qobject/qdict.h"
++#include "system/block-backend.h"
+
+static void help(void)
+{
diff --git a/debian/patches/pve/0028-PVE-Backup-add-backup-dump-block-driver.patch b/debian/patches/pve/0028-PVE-Backup-add-backup-dump-block-driver.patch
index b0cfb58..0142439 100644
--- a/debian/patches/pve/0028-PVE-Backup-add-backup-dump-block-driver.patch
+++ b/debian/patches/pve/0028-PVE-Backup-add-backup-dump-block-driver.patch
@@ -22,7 +22,7 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
diff --git a/block/backup-dump.c b/block/backup-dump.c
new file mode 100644
-index 0000000000..e46abf1070
+index 0000000000..354593bc10
--- /dev/null
+++ b/block/backup-dump.c
@@ -0,0 +1,172 @@
@@ -38,7 +38,7 @@ index 0000000000..e46abf1070
+
+#include "qemu/osdep.h"
+
-+#include "qapi/qmp/qdict.h"
++#include "qobject/qdict.h"
+#include "qom/object_interfaces.h"
+#include "block/block_int.h"
+
@@ -199,7 +199,7 @@ index 0000000000..e46abf1070
+ return bs;
+}
diff --git a/block/backup.c b/block/backup.c
-index 2e38b30d67..fe69723ada 100644
+index cc747e9163..6f7c45f922 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -29,28 +29,6 @@
@@ -247,7 +247,7 @@ index 2e38b30d67..fe69723ada 100644
if (perf->max_chunk && perf->max_chunk < cluster_size) {
error_setg(errp, "Required max-chunk (%" PRIi64 ") is less than backup "
diff --git a/block/meson.build b/block/meson.build
-index 652c8cbdb7..e1cf5a2e65 100644
+index 1373612c10..6278c4af0f 100644
--- a/block/meson.build
+++ b/block/meson.build
@@ -4,6 +4,7 @@ block_ss.add(files(
@@ -312,10 +312,10 @@ index ebb4e56a50..e717a74e5f 100644
BDRV_TRACKED_READ,
BDRV_TRACKED_WRITE,
diff --git a/job.c b/job.c
-index 660ce22c56..baf54c8d60 100644
+index 0653bc2ba6..b981070ee8 100644
--- a/job.c
+++ b/job.c
-@@ -331,7 +331,8 @@ static bool job_started_locked(Job *job)
+@@ -337,7 +337,8 @@ static bool job_started_locked(Job *job)
}
/* Called with job_mutex held. */
diff --git a/debian/patches/pve/0029-PVE-Add-sequential-job-transaction-support.patch b/debian/patches/pve/0029-PVE-Add-sequential-job-transaction-support.patch
index db86c7f..93ce858 100644
--- a/debian/patches/pve/0029-PVE-Add-sequential-job-transaction-support.patch
+++ b/debian/patches/pve/0029-PVE-Add-sequential-job-transaction-support.patch
@@ -11,7 +11,7 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
2 files changed, 46 insertions(+)
diff --git a/include/qemu/job.h b/include/qemu/job.h
-index 2b873f2576..528cd6acb9 100644
+index a5a04155ea..562cc7eaec 100644
--- a/include/qemu/job.h
+++ b/include/qemu/job.h
@@ -362,6 +362,18 @@ void job_unlock(void);
@@ -34,7 +34,7 @@ index 2b873f2576..528cd6acb9 100644
* Release a reference that was previously acquired with job_txn_add_job or
* job_txn_new. If it's the last reference to the object, it will be freed.
diff --git a/job.c b/job.c
-index baf54c8d60..3ac5e5cde2 100644
+index b981070ee8..f4646866ec 100644
--- a/job.c
+++ b/job.c
@@ -94,6 +94,8 @@ struct JobTxn {
@@ -72,7 +72,7 @@ index baf54c8d60..3ac5e5cde2 100644
/* Called with job_mutex held. */
static void job_txn_ref_locked(JobTxn *txn)
{
-@@ -1042,6 +1063,12 @@ static void job_completed_txn_success_locked(Job *job)
+@@ -1048,6 +1069,12 @@ static void job_completed_txn_success_locked(Job *job)
*/
QLIST_FOREACH(other_job, &txn->jobs, txn_list) {
if (!job_is_completed_locked(other_job)) {
@@ -85,7 +85,7 @@ index baf54c8d60..3ac5e5cde2 100644
return;
}
assert(other_job->ret == 0);
-@@ -1253,6 +1280,13 @@ int job_finish_sync_locked(Job *job,
+@@ -1259,6 +1286,13 @@ int job_finish_sync_locked(Job *job,
return -EBUSY;
}
diff --git a/debian/patches/pve/0030-PVE-Backup-Proxmox-backup-patches-for-QEMU.patch b/debian/patches/pve/0030-PVE-Backup-Proxmox-backup-patches-for-QEMU.patch
index 66372a5..060525f 100644
--- a/debian/patches/pve/0030-PVE-Backup-Proxmox-backup-patches-for-QEMU.patch
+++ b/debian/patches/pve/0030-PVE-Backup-Proxmox-backup-patches-for-QEMU.patch
@@ -94,17 +94,17 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
monitor/hmp-cmds.c | 72 +++
proxmox-backup-client.c | 146 +++++
proxmox-backup-client.h | 60 ++
- pve-backup.c | 1090 ++++++++++++++++++++++++++++++++
+ pve-backup.c | 1091 ++++++++++++++++++++++++++++++++
qapi/block-core.json | 233 +++++++
qapi/common.json | 14 +
qapi/machine.json | 16 +-
- 14 files changed, 1709 insertions(+), 14 deletions(-)
+ 14 files changed, 1710 insertions(+), 14 deletions(-)
create mode 100644 proxmox-backup-client.c
create mode 100644 proxmox-backup-client.h
create mode 100644 pve-backup.c
diff --git a/block/meson.build b/block/meson.build
-index e1cf5a2e65..2367e1ac1b 100644
+index 6278c4af0f..d1b16e40e9 100644
--- a/block/meson.build
+++ b/block/meson.build
@@ -44,6 +44,11 @@ block_ss.add(files(
@@ -120,10 +120,10 @@ index e1cf5a2e65..2367e1ac1b 100644
system_ss.add(when: 'CONFIG_TCG', if_true: files('blkreplay.c'))
system_ss.add(files('block-ram-registrar.c'))
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
-index bdf2eb50b6..439a7a14c8 100644
+index 6919a49bf5..4f30f99644 100644
--- a/block/monitor/block-hmp-cmds.c
+++ b/block/monitor/block-hmp-cmds.c
-@@ -1009,3 +1009,42 @@ void hmp_change_medium(Monitor *mon, const char *device, const char *target,
+@@ -1010,3 +1010,42 @@ void hmp_change_medium(Monitor *mon, const char *device, const char *target,
qmp_blockdev_change_medium(device, NULL, target, arg, true, force,
!!read_only, read_only_mode, errp);
}
@@ -167,7 +167,7 @@ index bdf2eb50b6..439a7a14c8 100644
+ hmp_handle_error(mon, error);
+}
diff --git a/blockdev.c b/blockdev.c
-index 79d47b1920..3f67eb413d 100644
+index 158ac9314b..17de5d2ae4 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -37,6 +37,7 @@
@@ -265,10 +265,10 @@ index 2596cc2426..9dda91d65a 100644
void hmp_device_add(Monitor *mon, const QDict *qdict);
void hmp_device_del(Monitor *mon, const QDict *qdict);
diff --git a/meson.build b/meson.build
-index b9b673c271..f6fb9b4fd8 100644
+index 680ab48b9b..1f74de1d93 100644
--- a/meson.build
+++ b/meson.build
-@@ -2130,6 +2130,7 @@ endif
+@@ -2162,6 +2162,7 @@ endif
has_gettid = cc.has_function('gettid')
libuuid = cc.find_library('uuid', required: true)
@@ -277,7 +277,7 @@ index b9b673c271..f6fb9b4fd8 100644
# libselinux
selinux = dependency('libselinux',
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
-index 874084565f..bedeb81f8c 100644
+index bade2a4b92..77a2fa409a 100644
--- a/monitor/hmp-cmds.c
+++ b/monitor/hmp-cmds.c
@@ -22,6 +22,7 @@
@@ -586,22 +586,23 @@ index 0000000000..8cbf645b2c
+#endif /* PROXMOX_BACKUP_CLIENT_H */
diff --git a/pve-backup.c b/pve-backup.c
new file mode 100644
-index 0000000000..fea0152de0
+index 0000000000..36e5042860
--- /dev/null
+++ b/pve-backup.c
-@@ -0,0 +1,1090 @@
+@@ -0,0 +1,1091 @@
+#include "proxmox-backup-client.h"
+#include "vma.h"
+
+#include "qemu/osdep.h"
+#include "qemu/module.h"
-+#include "sysemu/block-backend.h"
-+#include "sysemu/blockdev.h"
++#include "system/block-backend.h"
++#include "system/blockdev.h"
+#include "block/block_int-global-state.h"
+#include "block/blockjob.h"
+#include "block/dirty-bitmap.h"
+#include "block/graph-lock.h"
+#include "qapi/qapi-commands-block.h"
++#include "qobject/qdict.h"
+#include "qapi/qmp/qerror.h"
+#include "qemu/cutils.h"
+
@@ -1681,10 +1682,10 @@ index 0000000000..fea0152de0
+ return ret;
+}
diff --git a/qapi/block-core.json b/qapi/block-core.json
-index 321d1fd0e1..68caf30084 100644
+index 1c05413916..dd98e03bf1 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
-@@ -851,6 +851,239 @@
+@@ -855,6 +855,239 @@
{ 'command': 'query-block', 'returns': ['BlockInfo'],
'allow-preconfig': true }
@@ -1925,13 +1926,13 @@ index 321d1fd0e1..68caf30084 100644
# @BlockDeviceTimedStats:
#
diff --git a/qapi/common.json b/qapi/common.json
-index 6ffc7a3789..9c6c671ece 100644
+index 0e3a0bbbfb..554680c716 100644
--- a/qapi/common.json
+++ b/qapi/common.json
-@@ -212,3 +212,17 @@
+@@ -226,3 +226,17 @@
##
- { 'struct': 'HumanReadableText',
- 'data': { 'human-readable-text': 'str' } }
+ { 'enum': 'EndianMode',
+ 'data': [ 'unspecified', 'little', 'big' ] }
+
+##
+# @UuidInfo:
diff --git a/debian/patches/pve/0031-PVE-Backup-pbs-restore-new-command-to-restore-from-p.patch b/debian/patches/pve/0031-PVE-Backup-pbs-restore-new-command-to-restore-from-p.patch
index 0aefed3..618dedd 100644
--- a/debian/patches/pve/0031-PVE-Backup-pbs-restore-new-command-to-restore-from-p.patch
+++ b/debian/patches/pve/0031-PVE-Backup-pbs-restore-new-command-to-restore-from-p.patch
@@ -14,10 +14,10 @@ Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
create mode 100644 pbs-restore.c
diff --git a/meson.build b/meson.build
-index f6fb9b4fd8..f666d0f028 100644
+index 1f74de1d93..8508aab9c9 100644
--- a/meson.build
+++ b/meson.build
-@@ -4350,6 +4350,10 @@ if have_tools
+@@ -4373,6 +4373,10 @@ if have_tools
vma = executable('vma', files('vma.c', 'vma-reader.c') + genh,
dependencies: [authz, block, crypto, io, qemuutil, qom], install: true)
@@ -30,7 +30,7 @@ index f6fb9b4fd8..f666d0f028 100644
foreach exe: [ 'qemu-img', 'qemu-io', 'qemu-nbd', 'qemu-storage-daemon']
diff --git a/pbs-restore.c b/pbs-restore.c
new file mode 100644
-index 0000000000..f03d9bab8d
+index 0000000000..f165f418af
--- /dev/null
+++ b/pbs-restore.c
@@ -0,0 +1,236 @@
@@ -57,8 +57,8 @@ index 0000000000..f03d9bab8d
+#include "qemu/main-loop.h"
+#include "qemu/cutils.h"
+#include "qapi/error.h"
-+#include "qapi/qmp/qdict.h"
-+#include "sysemu/block-backend.h"
++#include "qobject/qdict.h"
++#include "system/block-backend.h"
+
+#include <proxmox-backup-qemu.h>
+
diff --git a/debian/patches/pve/0032-PVE-Add-PBS-block-driver-to-map-backup-archives-into.patch b/debian/patches/pve/0032-PVE-Add-PBS-block-driver-to-map-backup-archives-into.patch
index eaac4e5..80363f0 100644
--- a/debian/patches/pve/0032-PVE-Add-PBS-block-driver-to-map-backup-archives-into.patch
+++ b/debian/patches/pve/0032-PVE-Add-PBS-block-driver-to-map-backup-archives-into.patch
@@ -23,7 +23,7 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
create mode 100644 block/pbs.c
diff --git a/block/meson.build b/block/meson.build
-index 2367e1ac1b..e178047ec9 100644
+index d1b16e40e9..d243372c41 100644
--- a/block/meson.build
+++ b/block/meson.build
@@ -49,6 +49,8 @@ block_ss.add(files(
@@ -37,7 +37,7 @@ index 2367e1ac1b..e178047ec9 100644
system_ss.add(files('block-ram-registrar.c'))
diff --git a/block/pbs.c b/block/pbs.c
new file mode 100644
-index 0000000000..2d5e28ce8f
+index 0000000000..3e41421716
--- /dev/null
+++ b/block/pbs.c
@@ -0,0 +1,306 @@
@@ -47,8 +47,8 @@ index 0000000000..2d5e28ce8f
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
-+#include "qapi/qmp/qdict.h"
-+#include "qapi/qmp/qstring.h"
++#include "qobject/qdict.h"
++#include "qobject/qstring.h"
+#include "qemu/module.h"
+#include "qemu/option.h"
+#include "qemu/cutils.h"
@@ -348,10 +348,10 @@ index 0000000000..2d5e28ce8f
+
+block_init(bdrv_pbs_init);
diff --git a/meson.build b/meson.build
-index f666d0f028..4c85736ec3 100644
+index 8508aab9c9..9c39f54f86 100644
--- a/meson.build
+++ b/meson.build
-@@ -4815,7 +4815,7 @@ summary_info += {'Query Processing Library support': qpl}
+@@ -4838,7 +4838,7 @@ summary_info += {'Query Processing Library support': qpl}
summary_info += {'UADK Library support': uadk}
summary_info += {'qatzip support': qatzip}
summary_info += {'NUMA host support': numa}
@@ -361,10 +361,10 @@ index f666d0f028..4c85736ec3 100644
summary_info += {'libdaxctl support': libdaxctl}
summary_info += {'libcbor support': libcbor}
diff --git a/qapi/block-core.json b/qapi/block-core.json
-index 68caf30084..d45e8975a7 100644
+index dd98e03bf1..0c3ebfa74e 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
-@@ -3466,6 +3466,7 @@
+@@ -3470,6 +3470,7 @@
'parallels', 'preallocate', 'qcow', 'qcow2', 'qed', 'quorum',
'raw', 'rbd',
{ 'name': 'replication', 'if': 'CONFIG_REPLICATION' },
@@ -372,7 +372,7 @@ index 68caf30084..d45e8975a7 100644
'ssh', 'throttle', 'vdi', 'vhdx',
{ 'name': 'virtio-blk-vfio-pci', 'if': 'CONFIG_BLKIO' },
{ 'name': 'virtio-blk-vhost-user', 'if': 'CONFIG_BLKIO' },
-@@ -3552,6 +3553,33 @@
+@@ -3556,6 +3557,33 @@
{ 'struct': 'BlockdevOptionsNull',
'data': { '*size': 'int', '*latency-ns': 'uint64', '*read-zeroes': 'bool' } }
@@ -406,7 +406,7 @@ index 68caf30084..d45e8975a7 100644
##
# @BlockdevOptionsNVMe:
#
-@@ -4993,6 +5021,7 @@
+@@ -5003,6 +5031,7 @@
'nfs': 'BlockdevOptionsNfs',
'null-aio': 'BlockdevOptionsNull',
'null-co': 'BlockdevOptionsNull',
diff --git a/debian/patches/pve/0033-PVE-redirect-stderr-to-journal-when-daemonized.patch b/debian/patches/pve/0033-PVE-redirect-stderr-to-journal-when-daemonized.patch
index 4f88337..760ce46 100644
--- a/debian/patches/pve/0033-PVE-redirect-stderr-to-journal-when-daemonized.patch
+++ b/debian/patches/pve/0033-PVE-redirect-stderr-to-journal-when-daemonized.patch
@@ -14,10 +14,10 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/meson.build b/meson.build
-index 4c85736ec3..57f666d722 100644
+index 9c39f54f86..60af7fa723 100644
--- a/meson.build
+++ b/meson.build
-@@ -2130,6 +2130,7 @@ endif
+@@ -2162,6 +2162,7 @@ endif
has_gettid = cc.has_function('gettid')
libuuid = cc.find_library('uuid', required: true)
@@ -25,7 +25,7 @@ index 4c85736ec3..57f666d722 100644
libproxmox_backup_qemu = cc.find_library('proxmox_backup_qemu', required: true)
# libselinux
-@@ -3744,7 +3745,7 @@ if have_block
+@@ -3766,7 +3767,7 @@ if have_block
if host_os == 'windows'
system_ss.add(files('os-win32.c'))
else
@@ -35,7 +35,7 @@ index 4c85736ec3..57f666d722 100644
endif
diff --git a/os-posix.c b/os-posix.c
-index 43f9a43f3f..a47e46d1c2 100644
+index 52925c23d3..84b96d3da9 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -29,6 +29,8 @@
diff --git a/debian/patches/pve/0034-PVE-Migrate-dirty-bitmap-state-via-savevm.patch b/debian/patches/pve/0034-PVE-Migrate-dirty-bitmap-state-via-savevm.patch
index b794959..45a968b 100644
--- a/debian/patches/pve/0034-PVE-Migrate-dirty-bitmap-state-via-savevm.patch
+++ b/debian/patches/pve/0034-PVE-Migrate-dirty-bitmap-state-via-savevm.patch
@@ -26,19 +26,19 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
create mode 100644 migration/pbs-state.c
diff --git a/include/migration/misc.h b/include/migration/misc.h
-index 804eb23c06..c75b146ae6 100644
+index 8fd36eba1d..e963e93e71 100644
--- a/include/migration/misc.h
+++ b/include/migration/misc.h
-@@ -106,4 +106,7 @@ bool migration_incoming_postcopy_advised(void);
- /* True if background snapshot is active */
- bool migration_in_bg_snapshot(void);
+@@ -140,4 +140,7 @@ bool multifd_device_state_save_thread_should_exit(void);
+ void multifd_abort_device_state_save_threads(void);
+ bool multifd_join_device_state_save_threads(void);
+/* migration/pbs-state.c */
+void pbs_state_mig_init(void);
+
#endif
diff --git a/migration/meson.build b/migration/meson.build
-index 075b013971..eca57cb2a3 100644
+index 46e92249a1..fb3fd7d7d0 100644
--- a/migration/meson.build
+++ b/migration/meson.build
@@ -8,6 +8,7 @@ migration_files = files(
@@ -49,7 +49,7 @@ index 075b013971..eca57cb2a3 100644
system_ss.add(files(
'block-dirty-bitmap.c',
-@@ -27,6 +28,7 @@ system_ss.add(files(
+@@ -31,6 +32,7 @@ system_ss.add(files(
'multifd-zlib.c',
'multifd-zero-page.c',
'options.c',
@@ -58,10 +58,10 @@ index 075b013971..eca57cb2a3 100644
'savevm.c',
'savevm-async.c',
diff --git a/migration/migration.c b/migration/migration.c
-index 8c5bd0a75c..491d9aa017 100644
+index d46e776e24..2f3430f440 100644
--- a/migration/migration.c
+++ b/migration/migration.c
-@@ -266,6 +266,7 @@ void migration_object_init(void)
+@@ -319,6 +319,7 @@ void migration_object_init(void)
/* Initialize cpu throttle timers */
cpu_throttle_init();
@@ -180,10 +180,10 @@ index 0000000000..a97187e4d7
+ NULL);
+}
diff --git a/pve-backup.c b/pve-backup.c
-index fea0152de0..faa6a9b93c 100644
+index 36e5042860..11ea4b5c56 100644
--- a/pve-backup.c
+++ b/pve-backup.c
-@@ -1083,6 +1083,7 @@ ProxmoxSupportStatus *qmp_query_proxmox_support(Error **errp)
+@@ -1084,6 +1084,7 @@ ProxmoxSupportStatus *qmp_query_proxmox_support(Error **errp)
ret->pbs_library_version = g_strdup(proxmox_backup_qemu_version());
ret->pbs_dirty_bitmap = true;
ret->pbs_dirty_bitmap_savevm = true;
@@ -192,10 +192,10 @@ index fea0152de0..faa6a9b93c 100644
ret->pbs_masterkey = true;
ret->backup_max_workers = true;
diff --git a/qapi/block-core.json b/qapi/block-core.json
-index d45e8975a7..9795247c1f 100644
+index 0c3ebfa74e..6838187607 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
-@@ -1004,6 +1004,11 @@
+@@ -1008,6 +1008,11 @@
# @pbs-dirty-bitmap-savevm: True if 'dirty-bitmaps' migration capability can
# safely be set for savevm-async.
#
@@ -207,7 +207,7 @@ index d45e8975a7..9795247c1f 100644
# @pbs-masterkey: True if the QMP backup call supports the 'master_keyfile'
# parameter.
#
-@@ -1017,6 +1022,7 @@
+@@ -1021,6 +1026,7 @@
'data': { 'pbs-dirty-bitmap': 'bool',
'query-bitmap-info': 'bool',
'pbs-dirty-bitmap-savevm': 'bool',
diff --git a/debian/patches/pve/0035-migration-block-dirty-bitmap-migrate-other-bitmaps-e.patch b/debian/patches/pve/0035-migration-block-dirty-bitmap-migrate-other-bitmaps-e.patch
index 364824d..a8f20ad 100644
--- a/debian/patches/pve/0035-migration-block-dirty-bitmap-migrate-other-bitmaps-e.patch
+++ b/debian/patches/pve/0035-migration-block-dirty-bitmap-migrate-other-bitmaps-e.patch
@@ -19,7 +19,7 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/migration/block-dirty-bitmap.c b/migration/block-dirty-bitmap.c
-index a7d55048c2..44078ea670 100644
+index f2c352d4a7..931a8481e9 100644
--- a/migration/block-dirty-bitmap.c
+++ b/migration/block-dirty-bitmap.c
@@ -539,7 +539,11 @@ static int add_bitmaps_to_list(DBMSaveState *s, BlockDriverState *bs,
diff --git a/debian/patches/pve/0036-PVE-fall-back-to-open-iscsi-initiatorname.patch b/debian/patches/pve/0036-PVE-fall-back-to-open-iscsi-initiatorname.patch
index 0dc48df..773ee14 100644
--- a/debian/patches/pve/0036-PVE-fall-back-to-open-iscsi-initiatorname.patch
+++ b/debian/patches/pve/0036-PVE-fall-back-to-open-iscsi-initiatorname.patch
@@ -21,7 +21,7 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
1 file changed, 30 insertions(+)
diff --git a/block/iscsi.c b/block/iscsi.c
-index 979bf90cb7..961714a4be 100644
+index 2f0f4dac09..b523137cff 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -1392,12 +1392,42 @@ static char *get_initiator_name(QemuOpts *opts)
diff --git a/debian/patches/pve/0037-PVE-block-stream-increase-chunk-size.patch b/debian/patches/pve/0037-PVE-block-stream-increase-chunk-size.patch
index 32fd8ca..9edb3ec 100644
--- a/debian/patches/pve/0037-PVE-block-stream-increase-chunk-size.patch
+++ b/debian/patches/pve/0037-PVE-block-stream-increase-chunk-size.patch
@@ -11,7 +11,7 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/block/stream.c b/block/stream.c
-index 9076203193..1d1c65f061 100644
+index 999d9e56d4..e187cd1262 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -27,7 +27,7 @@ enum {
diff --git a/debian/patches/pve/0038-block-add-alloc-track-driver.patch b/debian/patches/pve/0038-block-add-alloc-track-driver.patch
index 6d1056b..5a527e4 100644
--- a/debian/patches/pve/0038-block-add-alloc-track-driver.patch
+++ b/debian/patches/pve/0038-block-add-alloc-track-driver.patch
@@ -42,7 +42,7 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
diff --git a/block/alloc-track.c b/block/alloc-track.c
new file mode 100644
-index 0000000000..b4a9851144
+index 0000000000..cb9829ae36
--- /dev/null
+++ b/block/alloc-track.c
@@ -0,0 +1,366 @@
@@ -63,13 +63,13 @@ index 0000000000..b4a9851144
+#include "block/block_int.h"
+#include "block/dirty-bitmap.h"
+#include "block/graph-lock.h"
-+#include "qapi/qmp/qdict.h"
-+#include "qapi/qmp/qstring.h"
++#include "qobject/qdict.h"
++#include "qobject/qstring.h"
+#include "qemu/cutils.h"
+#include "qemu/error-report.h"
+#include "qemu/option.h"
+#include "qemu/module.h"
-+#include "sysemu/block-backend.h"
++#include "system/block-backend.h"
+
+#define TRACK_OPT_AUTO_REMOVE "auto-remove"
+
@@ -413,7 +413,7 @@ index 0000000000..b4a9851144
+
+block_init(bdrv_alloc_track_init);
diff --git a/block/meson.build b/block/meson.build
-index e178047ec9..7ef7250d31 100644
+index d243372c41..9b45b5256d 100644
--- a/block/meson.build
+++ b/block/meson.build
@@ -2,6 +2,7 @@ block_ss.add(genh)
@@ -425,7 +425,7 @@ index e178047ec9..7ef7250d31 100644
'backup.c',
'backup-dump.c',
diff --git a/block/stream.c b/block/stream.c
-index 1d1c65f061..d499c8883f 100644
+index e187cd1262..0b61029399 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -120,6 +120,40 @@ static int stream_prepare(Job *job)
diff --git a/debian/patches/pve/0039-Revert-block-rbd-workaround-for-ceph-issue-53784.patch b/debian/patches/pve/0039-Revert-block-rbd-workaround-for-ceph-issue-53784.patch
index 0c4243a..a47e99d 100644
--- a/debian/patches/pve/0039-Revert-block-rbd-workaround-for-ceph-issue-53784.patch
+++ b/debian/patches/pve/0039-Revert-block-rbd-workaround-for-ceph-issue-53784.patch
@@ -13,7 +13,7 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
1 file changed, 2 insertions(+), 40 deletions(-)
diff --git a/block/rbd.c b/block/rbd.c
-index 728bce3b1e..6c9a8e0add 100644
+index bf143fac00..70d92966f7 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -1515,7 +1515,6 @@ static int coroutine_fn qemu_rbd_co_block_status(BlockDriverState *bs,
diff --git a/debian/patches/pve/0040-Revert-block-rbd-fix-handling-of-holes-in-.bdrv_co_b.patch b/debian/patches/pve/0040-Revert-block-rbd-fix-handling-of-holes-in-.bdrv_co_b.patch
index 95158ce..6659112 100644
--- a/debian/patches/pve/0040-Revert-block-rbd-fix-handling-of-holes-in-.bdrv_co_b.patch
+++ b/debian/patches/pve/0040-Revert-block-rbd-fix-handling-of-holes-in-.bdrv_co_b.patch
@@ -14,7 +14,7 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/block/rbd.c b/block/rbd.c
-index 6c9a8e0add..6f5fe90f3a 100644
+index 70d92966f7..931b513828 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -1474,11 +1474,11 @@ static int qemu_rbd_diff_iterate_cb(uint64_t offs, size_t len,
diff --git a/debian/patches/pve/0041-Revert-block-rbd-implement-bdrv_co_block_status.patch b/debian/patches/pve/0041-Revert-block-rbd-implement-bdrv_co_block_status.patch
index ed8bc16..9ed49f1 100644
--- a/debian/patches/pve/0041-Revert-block-rbd-implement-bdrv_co_block_status.patch
+++ b/debian/patches/pve/0041-Revert-block-rbd-implement-bdrv_co_block_status.patch
@@ -24,7 +24,7 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
1 file changed, 112 deletions(-)
diff --git a/block/rbd.c b/block/rbd.c
-index 6f5fe90f3a..24e820d056 100644
+index 931b513828..4ab9bb5e02 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -108,12 +108,6 @@ typedef struct RBDTask {
diff --git a/debian/patches/pve/0042-alloc-track-error-out-when-auto-remove-is-not-set.patch b/debian/patches/pve/0042-alloc-track-error-out-when-auto-remove-is-not-set.patch
index c0e323a..c65479d 100644
--- a/debian/patches/pve/0042-alloc-track-error-out-when-auto-remove-is-not-set.patch
+++ b/debian/patches/pve/0042-alloc-track-error-out-when-auto-remove-is-not-set.patch
@@ -17,7 +17,7 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/block/alloc-track.c b/block/alloc-track.c
-index b4a9851144..fc7d58a5d0 100644
+index cb9829ae36..30fac992fa 100644
--- a/block/alloc-track.c
+++ b/block/alloc-track.c
@@ -34,7 +34,6 @@ typedef struct {
diff --git a/debian/patches/pve/0043-alloc-track-avoid-seemingly-superfluous-child-permis.patch b/debian/patches/pve/0043-alloc-track-avoid-seemingly-superfluous-child-permis.patch
index 5e1683b..5113d34 100644
--- a/debian/patches/pve/0043-alloc-track-avoid-seemingly-superfluous-child-permis.patch
+++ b/debian/patches/pve/0043-alloc-track-avoid-seemingly-superfluous-child-permis.patch
@@ -20,7 +20,7 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
1 file changed, 26 deletions(-)
diff --git a/block/alloc-track.c b/block/alloc-track.c
-index fc7d58a5d0..b56425b7f0 100644
+index 30fac992fa..718aaabf2a 100644
--- a/block/alloc-track.c
+++ b/block/alloc-track.c
@@ -25,15 +25,9 @@
diff --git a/debian/patches/pve/0044-PVE-backup-add-fleecing-option.patch b/debian/patches/pve/0044-PVE-backup-add-fleecing-option.patch
index 8663a33..b6eaade 100644
--- a/debian/patches/pve/0044-PVE-backup-add-fleecing-option.patch
+++ b/debian/patches/pve/0044-PVE-backup-add-fleecing-option.patch
@@ -63,15 +63,15 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
---
block/monitor/block-hmp-cmds.c | 1 +
- pve-backup.c | 135 ++++++++++++++++++++++++++++++++-
+ pve-backup.c | 134 ++++++++++++++++++++++++++++++++-
qapi/block-core.json | 10 ++-
- 3 files changed, 142 insertions(+), 4 deletions(-)
+ 3 files changed, 141 insertions(+), 4 deletions(-)
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
-index 439a7a14c8..d0e7771dcc 100644
+index 4f30f99644..66d16d342f 100644
--- a/block/monitor/block-hmp-cmds.c
+++ b/block/monitor/block-hmp-cmds.c
-@@ -1044,6 +1044,7 @@ void coroutine_fn hmp_backup(Monitor *mon, const QDict *qdict)
+@@ -1045,6 +1045,7 @@ void coroutine_fn hmp_backup(Monitor *mon, const QDict *qdict)
NULL, NULL,
devlist, qdict_haskey(qdict, "speed"), speed,
false, 0, // BackupPerf max-workers
@@ -80,22 +80,18 @@ index 439a7a14c8..d0e7771dcc 100644
hmp_handle_error(mon, error);
diff --git a/pve-backup.c b/pve-backup.c
-index faa6a9b93c..4b0820c8a7 100644
+index 11ea4b5c56..257cd0b0e1 100644
--- a/pve-backup.c
+++ b/pve-backup.c
-@@ -7,9 +7,11 @@
- #include "sysemu/blockdev.h"
+@@ -7,6 +7,7 @@
+ #include "system/blockdev.h"
#include "block/block_int-global-state.h"
#include "block/blockjob.h"
+#include "block/copy-before-write.h"
#include "block/dirty-bitmap.h"
#include "block/graph-lock.h"
#include "qapi/qapi-commands-block.h"
-+#include "qapi/qmp/qdict.h"
- #include "qapi/qmp/qerror.h"
- #include "qemu/cutils.h"
-
-@@ -80,8 +82,15 @@ static void pvebackup_init(void)
+@@ -81,8 +82,15 @@ static void pvebackup_init(void)
// initialize PVEBackupState at startup
opts_init(pvebackup_init);
@@ -111,7 +107,7 @@ index faa6a9b93c..4b0820c8a7 100644
size_t size;
uint64_t block_size;
uint8_t dev_id;
-@@ -353,6 +362,22 @@ static void pvebackup_complete_cb(void *opaque, int ret)
+@@ -354,6 +362,22 @@ static void pvebackup_complete_cb(void *opaque, int ret)
PVEBackupDevInfo *di = opaque;
di->completed_ret = ret;
@@ -134,7 +130,7 @@ index faa6a9b93c..4b0820c8a7 100644
/*
* Needs to happen outside of coroutine, because it takes the graph write lock.
*/
-@@ -519,9 +544,77 @@ static void create_backup_jobs_bh(void *opaque) {
+@@ -520,9 +544,77 @@ static void create_backup_jobs_bh(void *opaque) {
}
bdrv_drained_begin(di->bs);
@@ -214,7 +210,7 @@ index faa6a9b93c..4b0820c8a7 100644
BLOCKDEV_ON_ERROR_REPORT, JOB_DEFAULT, pvebackup_complete_cb, di, backup_state.txn,
&local_err);
-@@ -577,6 +670,14 @@ static void create_backup_jobs_bh(void *opaque) {
+@@ -578,6 +670,14 @@ static void create_backup_jobs_bh(void *opaque) {
aio_co_enter(data->ctx, data->co);
}
@@ -229,7 +225,7 @@ index faa6a9b93c..4b0820c8a7 100644
/*
* Returns a list of device infos, which needs to be freed by the caller. In
* case of an error, errp will be set, but the returned value might still be a
-@@ -584,6 +685,7 @@ static void create_backup_jobs_bh(void *opaque) {
+@@ -585,6 +685,7 @@ static void create_backup_jobs_bh(void *opaque) {
*/
static GList coroutine_fn GRAPH_RDLOCK *get_device_info(
const char *devlist,
@@ -237,7 +233,7 @@ index faa6a9b93c..4b0820c8a7 100644
Error **errp)
{
gchar **devs = NULL;
-@@ -607,6 +709,31 @@ static GList coroutine_fn GRAPH_RDLOCK *get_device_info(
+@@ -608,6 +709,31 @@ static GList coroutine_fn GRAPH_RDLOCK *get_device_info(
}
PVEBackupDevInfo *di = g_new0(PVEBackupDevInfo, 1);
di->bs = bs;
@@ -269,7 +265,7 @@ index faa6a9b93c..4b0820c8a7 100644
di_list = g_list_append(di_list, di);
d++;
}
-@@ -656,6 +783,7 @@ UuidInfo coroutine_fn *qmp_backup(
+@@ -657,6 +783,7 @@ UuidInfo coroutine_fn *qmp_backup(
const char *devlist,
bool has_speed, int64_t speed,
bool has_max_workers, int64_t max_workers,
@@ -277,7 +273,7 @@ index faa6a9b93c..4b0820c8a7 100644
Error **errp)
{
assert(qemu_in_coroutine());
-@@ -684,7 +812,7 @@ UuidInfo coroutine_fn *qmp_backup(
+@@ -685,7 +812,7 @@ UuidInfo coroutine_fn *qmp_backup(
format = has_format ? format : BACKUP_FORMAT_VMA;
bdrv_graph_co_rdlock();
@@ -286,7 +282,7 @@ index faa6a9b93c..4b0820c8a7 100644
bdrv_graph_co_rdunlock();
if (local_err) {
error_propagate(errp, local_err);
-@@ -1087,5 +1215,6 @@ ProxmoxSupportStatus *qmp_query_proxmox_support(Error **errp)
+@@ -1088,5 +1215,6 @@ ProxmoxSupportStatus *qmp_query_proxmox_support(Error **errp)
ret->query_bitmap_info = true;
ret->pbs_masterkey = true;
ret->backup_max_workers = true;
@@ -294,10 +290,10 @@ index faa6a9b93c..4b0820c8a7 100644
return ret;
}
diff --git a/qapi/block-core.json b/qapi/block-core.json
-index 9795247c1f..c581f1f238 100644
+index 6838187607..9bdcfa31ea 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
-@@ -948,6 +948,10 @@
+@@ -952,6 +952,10 @@
#
# @max-workers: see @BackupPerf for details. Default 16.
#
@@ -308,7 +304,7 @@ index 9795247c1f..c581f1f238 100644
# Returns: the uuid of the backup job
#
##
-@@ -968,7 +972,8 @@
+@@ -972,7 +976,8 @@
'*firewall-file': 'str',
'*devlist': 'str',
'*speed': 'int',
@@ -318,7 +314,7 @@ index 9795247c1f..c581f1f238 100644
'returns': 'UuidInfo', 'coroutine': true }
##
-@@ -1014,6 +1019,8 @@
+@@ -1018,6 +1023,8 @@
#
# @pbs-library-version: Running version of libproxmox-backup-qemu0 library.
#
@@ -327,7 +323,7 @@ index 9795247c1f..c581f1f238 100644
# @backup-max-workers: Whether the 'max-workers' @BackupPerf setting is
# supported or not.
#
-@@ -1025,6 +1032,7 @@
+@@ -1029,6 +1036,7 @@
'pbs-dirty-bitmap-migration': 'bool',
'pbs-masterkey': 'bool',
'pbs-library-version': 'str',
diff --git a/debian/patches/pve/0045-PVE-backup-improve-error-when-copy-before-write-fail.patch b/debian/patches/pve/0045-PVE-backup-improve-error-when-copy-before-write-fail.patch
index dbbf64a..e6cecc4 100644
--- a/debian/patches/pve/0045-PVE-backup-improve-error-when-copy-before-write-fail.patch
+++ b/debian/patches/pve/0045-PVE-backup-improve-error-when-copy-before-write-fail.patch
@@ -21,13 +21,13 @@ Tested-by: Friedrich Weber <f.weber@proxmox.com>
3 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
-index 81afeff1c7..fdf9cdc0cd 100644
+index fd470f5f92..5c23b578ef 100644
--- a/block/copy-before-write.c
+++ b/block/copy-before-write.c
@@ -27,6 +27,7 @@
- #include "qapi/qmp/qjson.h"
+ #include "qobject/qjson.h"
- #include "sysemu/block-backend.h"
+ #include "system/block-backend.h"
+#include "qemu/atomic.h"
#include "qemu/cutils.h"
#include "qapi/error.h"
@@ -96,7 +96,7 @@ index 2a5d4ba693..969da3620f 100644
#endif /* COPY_BEFORE_WRITE_H */
diff --git a/pve-backup.c b/pve-backup.c
-index 4b0820c8a7..81697d9bf9 100644
+index 257cd0b0e1..ffcfaa649d 100644
--- a/pve-backup.c
+++ b/pve-backup.c
@@ -374,6 +374,15 @@ static void pvebackup_complete_cb(void *opaque, int ret)
diff --git a/debian/patches/pve/0046-PVE-backup-fixup-error-handling-for-fleecing.patch b/debian/patches/pve/0046-PVE-backup-fixup-error-handling-for-fleecing.patch
index 1b4fdd2..49a2256 100644
--- a/debian/patches/pve/0046-PVE-backup-fixup-error-handling-for-fleecing.patch
+++ b/debian/patches/pve/0046-PVE-backup-fixup-error-handling-for-fleecing.patch
@@ -18,7 +18,7 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
1 file changed, 25 insertions(+), 13 deletions(-)
diff --git a/pve-backup.c b/pve-backup.c
-index 81697d9bf9..320c660589 100644
+index ffcfaa649d..718a31e4ca 100644
--- a/pve-backup.c
+++ b/pve-backup.c
@@ -357,22 +357,23 @@ static void coroutine_fn pvebackup_co_complete_stream(void *opaque)
diff --git a/debian/patches/pve/0047-PVE-backup-factor-out-setting-up-snapshot-access-for.patch b/debian/patches/pve/0047-PVE-backup-factor-out-setting-up-snapshot-access-for.patch
index ebd47dc..af8e0dd 100644
--- a/debian/patches/pve/0047-PVE-backup-factor-out-setting-up-snapshot-access-for.patch
+++ b/debian/patches/pve/0047-PVE-backup-factor-out-setting-up-snapshot-access-for.patch
@@ -15,7 +15,7 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
1 file changed, 58 insertions(+), 37 deletions(-)
diff --git a/pve-backup.c b/pve-backup.c
-index 320c660589..d8d0c04b0f 100644
+index 718a31e4ca..3551bd6c92 100644
--- a/pve-backup.c
+++ b/pve-backup.c
@@ -525,6 +525,62 @@ static int coroutine_fn pvebackup_co_add_config(
diff --git a/debian/patches/pve/0048-PVE-backup-save-device-name-in-device-info-structure.patch b/debian/patches/pve/0048-PVE-backup-save-device-name-in-device-info-structure.patch
index 891e584..3523164 100644
--- a/debian/patches/pve/0048-PVE-backup-save-device-name-in-device-info-structure.patch
+++ b/debian/patches/pve/0048-PVE-backup-save-device-name-in-device-info-structure.patch
@@ -17,7 +17,7 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
1 file changed, 15 insertions(+), 14 deletions(-)
diff --git a/pve-backup.c b/pve-backup.c
-index d8d0c04b0f..e2110ce0db 100644
+index 3551bd6c92..25f65952a0 100644
--- a/pve-backup.c
+++ b/pve-backup.c
@@ -94,6 +94,7 @@ typedef struct PVEBackupDevInfo {
diff --git a/debian/patches/pve/0049-PVE-backup-include-device-name-in-error-when-setting.patch b/debian/patches/pve/0049-PVE-backup-include-device-name-in-error-when-setting.patch
index 807609a..477beca 100644
--- a/debian/patches/pve/0049-PVE-backup-include-device-name-in-error-when-setting.patch
+++ b/debian/patches/pve/0049-PVE-backup-include-device-name-in-error-when-setting.patch
@@ -10,7 +10,7 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/pve-backup.c b/pve-backup.c
-index e2110ce0db..32352fb5ec 100644
+index 25f65952a0..b411d58a9a 100644
--- a/pve-backup.c
+++ b/pve-backup.c
@@ -626,7 +626,8 @@ static void create_backup_jobs_bh(void *opaque) {
diff --git a/debian/patches/pve/0050-adapt-machine-version-deprecation-for-Proxmox-VE.patch b/debian/patches/pve/0050-adapt-machine-version-deprecation-for-Proxmox-VE.patch
index f80b21c..6e587fa 100644
--- a/debian/patches/pve/0050-adapt-machine-version-deprecation-for-Proxmox-VE.patch
+++ b/debian/patches/pve/0050-adapt-machine-version-deprecation-for-Proxmox-VE.patch
@@ -22,10 +22,10 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
1 file changed, 51 insertions(+), 27 deletions(-)
diff --git a/include/hw/boards.h b/include/hw/boards.h
-index d1741ea121..3f9befda14 100644
+index 8ada4d5832..f9f3b75284 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
-@@ -631,42 +631,66 @@ struct MachineState {
+@@ -636,42 +636,66 @@ struct MachineState {
/*
@@ -117,7 +117,7 @@ index d1741ea121..3f9befda14 100644
/*
* Evaluates true when a machine type with (major, minor)
-@@ -675,7 +699,7 @@ struct MachineState {
+@@ -680,7 +704,7 @@ struct MachineState {
* lifecycle rules
*/
#define MACHINE_VER_IS_DEPRECATED(...) \
@@ -126,7 +126,7 @@ index d1741ea121..3f9befda14 100644
/*
* Evaluates true when a machine type with (major, minor)
-@@ -684,7 +708,7 @@ struct MachineState {
+@@ -689,7 +713,7 @@ struct MachineState {
* lifecycle rules
*/
#define MACHINE_VER_SHOULD_DELETE(...) \
diff --git a/debian/patches/pve/0051-Revert-hpet-avoid-timer-storms-on-periodic-timers.patch b/debian/patches/pve/0051-Revert-hpet-avoid-timer-storms-on-periodic-timers.patch
index 3ff1ee4..e4bbb4b 100644
--- a/debian/patches/pve/0051-Revert-hpet-avoid-timer-storms-on-periodic-timers.patch
+++ b/debian/patches/pve/0051-Revert-hpet-avoid-timer-storms-on-periodic-timers.patch
@@ -11,10 +11,10 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
1 file changed, 2 insertions(+), 11 deletions(-)
diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
-index 5399f1b2a3..8ccc421cbb 100644
+index ccb97b6806..0f45af8bbe 100644
--- a/hw/timer/hpet.c
+++ b/hw/timer/hpet.c
-@@ -59,7 +59,6 @@ typedef struct HPETTimer { /* timers */
+@@ -61,7 +61,6 @@ typedef struct HPETTimer { /* timers */
uint8_t wrap_flag; /* timer pop will indicate wrap for one-shot 32-bit
* mode. Next pop will be actual timer expiration.
*/
@@ -22,7 +22,7 @@ index 5399f1b2a3..8ccc421cbb 100644
} HPETTimer;
struct HPETState {
-@@ -267,7 +266,6 @@ static int hpet_post_load(void *opaque, int version_id)
+@@ -262,7 +261,6 @@ static int hpet_post_load(void *opaque, int version_id)
for (i = 0; i < s->num_timers; i++) {
HPETTimer *t = &s->timer[i];
t->cmp64 = hpet_calculate_cmp64(t, s->hpet_counter, t->cmp);
@@ -30,7 +30,7 @@ index 5399f1b2a3..8ccc421cbb 100644
}
/* Recalculate the offset between the main counter and guest time */
if (!s->hpet_offset_saved) {
-@@ -366,15 +364,8 @@ static const VMStateDescription vmstate_hpet = {
+@@ -350,15 +348,8 @@ static const VMStateDescription vmstate_hpet = {
static void hpet_arm(HPETTimer *t, uint64_t tick)
{
diff --git a/debian/patches/pve/0052-Revert-hpet-store-full-64-bit-target-value-of-the-co.patch b/debian/patches/pve/0052-Revert-hpet-store-full-64-bit-target-value-of-the-co.patch
index 482940c..c366356 100644
--- a/debian/patches/pve/0052-Revert-hpet-store-full-64-bit-target-value-of-the-co.patch
+++ b/debian/patches/pve/0052-Revert-hpet-store-full-64-bit-target-value-of-the-co.patch
@@ -7,14 +7,14 @@ This reverts commit 242d665396407f83a6acbffc804882eeb21cfdad.
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
---
- hw/timer/hpet.c | 111 +++++++++++++++++++++++++++---------------------
- 1 file changed, 62 insertions(+), 49 deletions(-)
+ hw/timer/hpet.c | 109 +++++++++++++++++++++++++++---------------------
+ 1 file changed, 61 insertions(+), 48 deletions(-)
diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
-index 8ccc421cbb..415a9433f1 100644
+index 0f45af8bbe..635a060d38 100644
--- a/hw/timer/hpet.c
+++ b/hw/timer/hpet.c
-@@ -54,7 +54,6 @@ typedef struct HPETTimer { /* timers */
+@@ -56,7 +56,6 @@ typedef struct HPETTimer { /* timers */
uint64_t cmp; /* comparator */
uint64_t fsb; /* FSB route */
/* Hidden register state */
@@ -22,7 +22,7 @@ index 8ccc421cbb..415a9433f1 100644
uint64_t period; /* Last value written to comparator */
uint8_t wrap_flag; /* timer pop will indicate wrap for one-shot 32-bit
* mode. Next pop will be actual timer expiration.
-@@ -116,6 +115,11 @@ static uint32_t timer_enabled(HPETTimer *t)
+@@ -119,6 +118,11 @@ static uint32_t timer_enabled(HPETTimer *t)
}
static uint32_t hpet_time_after(uint64_t a, uint64_t b)
@@ -34,7 +34,7 @@ index 8ccc421cbb..415a9433f1 100644
{
return ((int64_t)(b - a) < 0);
}
-@@ -152,32 +156,27 @@ static uint64_t hpet_get_ticks(HPETState *s)
+@@ -155,32 +159,27 @@ static uint64_t hpet_get_ticks(HPETState *s)
return ns_to_ticks(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->hpet_offset);
}
@@ -82,7 +82,7 @@ index 8ccc421cbb..415a9433f1 100644
}
static void update_irq(struct HPETTimer *timer, int set)
-@@ -261,12 +260,7 @@ static bool hpet_validate_num_timers(void *opaque, int version_id)
+@@ -256,12 +255,7 @@ static bool hpet_validate_num_timers(void *opaque, int version_id)
static int hpet_post_load(void *opaque, int version_id)
{
HPETState *s = opaque;
@@ -95,7 +95,7 @@ index 8ccc421cbb..415a9433f1 100644
/* Recalculate the offset between the main counter and guest time */
if (!s->hpet_offset_saved) {
s->hpet_offset = ticks_to_ns(s->hpet_counter)
-@@ -362,10 +356,14 @@ static const VMStateDescription vmstate_hpet = {
+@@ -346,10 +340,14 @@ static const VMStateDescription vmstate_hpet = {
}
};
@@ -113,7 +113,7 @@ index 8ccc421cbb..415a9433f1 100644
}
/*
-@@ -374,44 +372,54 @@ static void hpet_arm(HPETTimer *t, uint64_t tick)
+@@ -358,44 +356,54 @@ static void hpet_arm(HPETTimer *t, uint64_t tick)
static void hpet_timer(void *opaque)
{
HPETTimer *t = opaque;
@@ -163,13 +163,12 @@ index 8ccc421cbb..415a9433f1 100644
t->wrap_flag = 0;
- t->cmp64 = hpet_calculate_cmp64(t, cur_tick, t->cmp);
- if (t->config & HPET_TN_32BIT) {
--
++ diff = hpet_calculate_diff(t, cur_tick);
+
- /* hpet spec says in one-shot 32-bit mode, generate an interrupt when
- * counter wraps in addition to an interrupt with comparator match.
- */
- if (!timer_is_periodic(t) && t->cmp64 > hpet_next_wrap(cur_tick)) {
-+ diff = hpet_calculate_diff(t, cur_tick);
-+
+ /* hpet spec says in one-shot 32-bit mode, generate an interrupt when
+ * counter wraps in addition to an interrupt with comparator match.
+ */
@@ -187,7 +186,7 @@ index 8ccc421cbb..415a9433f1 100644
}
static void hpet_del_timer(HPETTimer *t)
-@@ -542,7 +550,12 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
+@@ -526,7 +534,12 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
timer->cmp = deposit64(timer->cmp, shift, len, value);
}
if (timer_is_periodic(timer)) {
diff --git a/debian/patches/pve/0053-Revert-hpet-accept-64-bit-reads-and-writes.patch b/debian/patches/pve/0053-Revert-hpet-accept-64-bit-reads-and-writes.patch
index b47b823..37d8d3a 100644
--- a/debian/patches/pve/0053-Revert-hpet-accept-64-bit-reads-and-writes.patch
+++ b/debian/patches/pve/0053-Revert-hpet-accept-64-bit-reads-and-writes.patch
@@ -12,10 +12,10 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
2 files changed, 96 insertions(+), 44 deletions(-)
diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
-index 415a9433f1..e1ac877759 100644
+index 635a060d38..5f4bb5667d 100644
--- a/hw/timer/hpet.c
+++ b/hw/timer/hpet.c
-@@ -437,7 +437,6 @@ static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
+@@ -421,7 +421,6 @@ static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
unsigned size)
{
HPETState *s = opaque;
@@ -23,7 +23,7 @@ index 415a9433f1..e1ac877759 100644
uint64_t cur_tick;
trace_hpet_ram_read(addr);
-@@ -452,33 +451,52 @@ static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
+@@ -436,33 +435,52 @@ static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
return 0;
}
@@ -88,7 +88,7 @@ index 415a9433f1..e1ac877759 100644
default:
trace_hpet_ram_read_invalid();
break;
-@@ -492,11 +510,11 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
+@@ -476,11 +494,11 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
{
int i;
HPETState *s = opaque;
@@ -102,7 +102,7 @@ index 415a9433f1..e1ac877759 100644
/*address range of all TN regs*/
if (addr >= 0x100 && addr <= 0x3ff) {
-@@ -508,12 +526,9 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
+@@ -492,12 +510,9 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
trace_hpet_timer_id_out_of_range(timer_id);
return;
}
@@ -117,7 +117,7 @@ index 415a9433f1..e1ac877759 100644
if (deactivating_bit(old_val, new_val, HPET_TN_TYPE_LEVEL)) {
/*
* Do this before changing timer->config; otherwise, if
-@@ -521,7 +536,8 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
+@@ -505,7 +520,8 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
*/
update_irq(timer, 0);
}
@@ -127,7 +127,7 @@ index 415a9433f1..e1ac877759 100644
if (activating_bit(old_val, new_val, HPET_TN_ENABLE)
&& (s->isr & (1 << timer_id))) {
update_irq(timer, 1);
-@@ -534,28 +550,56 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
+@@ -518,28 +534,56 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
hpet_set_timer(timer);
}
break;
@@ -194,7 +194,7 @@ index 415a9433f1..e1ac877759 100644
}
timer->config &= ~HPET_TN_SETVAL;
if (hpet_enabled(s)) {
-@@ -563,7 +607,10 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
+@@ -547,7 +591,10 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
}
break;
case HPET_TN_ROUTE:
@@ -206,7 +206,7 @@ index 415a9433f1..e1ac877759 100644
break;
default:
trace_hpet_ram_write_invalid();
-@@ -571,14 +618,12 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
+@@ -555,14 +602,12 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
}
return;
} else {
@@ -223,7 +223,7 @@ index 415a9433f1..e1ac877759 100644
if (activating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
/* Enable main counter and interrupt generation. */
s->hpet_offset =
-@@ -608,8 +653,10 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
+@@ -592,8 +637,10 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
qemu_set_irq(s->irqs[RTC_ISA_IRQ], s->rtc_irq_level);
}
break;
@@ -235,7 +235,7 @@ index 415a9433f1..e1ac877759 100644
cleared = new_val & s->isr;
for (i = 0; i < s->num_timers; i++) {
if (cleared & (1 << i)) {
-@@ -621,7 +668,15 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
+@@ -605,7 +652,15 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
if (hpet_enabled(s)) {
trace_hpet_ram_write_counter_write_while_enabled();
}
@@ -252,7 +252,7 @@ index 415a9433f1..e1ac877759 100644
break;
default:
trace_hpet_ram_write_invalid();
-@@ -635,11 +690,7 @@ static const MemoryRegionOps hpet_ram_ops = {
+@@ -619,11 +674,7 @@ static const MemoryRegionOps hpet_ram_ops = {
.write = hpet_ram_write,
.valid = {
.min_access_size = 4,
@@ -266,7 +266,7 @@ index 415a9433f1..e1ac877759 100644
.endianness = DEVICE_NATIVE_ENDIAN,
};
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
-index 5cfc369fba..219747df2f 100644
+index c5b6db49f5..dd8a53c690 100644
--- a/hw/timer/trace-events
+++ b/hw/timer/trace-events
@@ -114,7 +114,8 @@ hpet_ram_read_reading_counter(uint8_t reg_off, uint64_t cur_tick) "reading count
diff --git a/debian/patches/pve/0054-Revert-hpet-place-read-only-bits-directly-in-new_val.patch b/debian/patches/pve/0054-Revert-hpet-place-read-only-bits-directly-in-new_val.patch
index 85b0989..8742f85 100644
--- a/debian/patches/pve/0054-Revert-hpet-place-read-only-bits-directly-in-new_val.patch
+++ b/debian/patches/pve/0054-Revert-hpet-place-read-only-bits-directly-in-new_val.patch
@@ -11,10 +11,10 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
-index e1ac877759..b12bbaf10d 100644
+index 5f4bb5667d..5e3bf1f153 100644
--- a/hw/timer/hpet.c
+++ b/hw/timer/hpet.c
-@@ -510,7 +510,7 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
+@@ -494,7 +494,7 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
{
int i;
HPETState *s = opaque;
@@ -23,7 +23,7 @@ index e1ac877759..b12bbaf10d 100644
trace_hpet_ram_write(addr, value);
old_val = hpet_ram_read(opaque, addr, 4);
-@@ -536,12 +536,13 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
+@@ -520,12 +520,13 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
*/
update_irq(timer, 0);
}
@@ -39,7 +39,7 @@ index e1ac877759..b12bbaf10d 100644
if (new_val & HPET_TN_32BIT) {
timer->cmp = (uint32_t)timer->cmp;
timer->period = (uint32_t)timer->period;
-@@ -622,8 +623,8 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
+@@ -606,8 +607,8 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
case HPET_ID:
return;
case HPET_CFG:
@@ -50,7 +50,7 @@ index e1ac877759..b12bbaf10d 100644
if (activating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
/* Enable main counter and interrupt generation. */
s->hpet_offset =
-@@ -657,9 +658,9 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
+@@ -641,9 +642,9 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
trace_hpet_invalid_hpet_cfg(4);
break;
case HPET_STATUS:
diff --git a/debian/patches/pve/0055-Revert-hpet-remove-unnecessary-variable-index.patch b/debian/patches/pve/0055-Revert-hpet-remove-unnecessary-variable-index.patch
index c8aa6ad..d962aeb 100644
--- a/debian/patches/pve/0055-Revert-hpet-remove-unnecessary-variable-index.patch
+++ b/debian/patches/pve/0055-Revert-hpet-remove-unnecessary-variable-index.patch
@@ -11,10 +11,10 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
-index b12bbaf10d..6f83d88516 100644
+index 5e3bf1f153..daef12c8cf 100644
--- a/hw/timer/hpet.c
+++ b/hw/timer/hpet.c
-@@ -437,12 +437,12 @@ static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
+@@ -421,12 +421,12 @@ static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
unsigned size)
{
HPETState *s = opaque;
@@ -30,7 +30,7 @@ index b12bbaf10d..6f83d88516 100644
uint8_t timer_id = (addr - 0x100) / 0x20;
HPETTimer *timer = &s->timer[timer_id];
-@@ -469,7 +469,7 @@ static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
+@@ -453,7 +453,7 @@ static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
break;
}
} else {
@@ -39,7 +39,7 @@ index b12bbaf10d..6f83d88516 100644
case HPET_ID:
return s->capability;
case HPET_PERIOD:
-@@ -510,14 +510,15 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
+@@ -494,14 +494,15 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
{
int i;
HPETState *s = opaque;
@@ -57,7 +57,7 @@ index b12bbaf10d..6f83d88516 100644
uint8_t timer_id = (addr - 0x100) / 0x20;
HPETTimer *timer = &s->timer[timer_id];
-@@ -619,7 +620,7 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
+@@ -603,7 +604,7 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
}
return;
} else {
diff --git a/debian/patches/pve/0056-Revert-hpet-ignore-high-bits-of-comparator-in-32-bit.patch b/debian/patches/pve/0056-Revert-hpet-ignore-high-bits-of-comparator-in-32-bit.patch
index 0fde8dd..e09c8ba 100644
--- a/debian/patches/pve/0056-Revert-hpet-ignore-high-bits-of-comparator-in-32-bit.patch
+++ b/debian/patches/pve/0056-Revert-hpet-ignore-high-bits-of-comparator-in-32-bit.patch
@@ -12,10 +12,10 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
2 files changed, 5 deletions(-)
diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
-index 6f83d88516..509986c0a9 100644
+index daef12c8cf..927263e2ff 100644
--- a/hw/timer/hpet.c
+++ b/hw/timer/hpet.c
-@@ -585,10 +585,6 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
+@@ -569,10 +569,6 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
}
break;
case HPET_TN_CMP + 4: // comparator register high order
@@ -27,7 +27,7 @@ index 6f83d88516..509986c0a9 100644
if (!timer_is_periodic(timer)
|| (timer->config & HPET_TN_SETVAL)) {
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
-index 219747df2f..b86870fb22 100644
+index dd8a53c690..2b81ee0812 100644
--- a/hw/timer/trace-events
+++ b/hw/timer/trace-events
@@ -117,7 +117,6 @@ hpet_ram_write_timer_id(uint64_t timer_id) "hpet_ram_writel timer_id = 0x%" PRIx
diff --git a/debian/patches/pve/0057-Revert-hpet-fix-and-cleanup-persistence-of-interrupt.patch b/debian/patches/pve/0057-Revert-hpet-fix-and-cleanup-persistence-of-interrupt.patch
index 0c58bae..312df20 100644
--- a/debian/patches/pve/0057-Revert-hpet-fix-and-cleanup-persistence-of-interrupt.patch
+++ b/debian/patches/pve/0057-Revert-hpet-fix-and-cleanup-persistence-of-interrupt.patch
@@ -12,10 +12,10 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
1 file changed, 19 insertions(+), 41 deletions(-)
diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
-index 509986c0a9..402cc960f0 100644
+index 927263e2ff..5aae09f166 100644
--- a/hw/timer/hpet.c
+++ b/hw/timer/hpet.c
-@@ -196,31 +196,21 @@ static void update_irq(struct HPETTimer *timer, int set)
+@@ -199,31 +199,21 @@ static void update_irq(struct HPETTimer *timer, int set)
}
s = timer->state;
mask = 1 << timer->tn;
@@ -58,7 +58,7 @@ index 509986c0a9..402cc960f0 100644
}
}
-@@ -424,13 +414,8 @@ static void hpet_set_timer(HPETTimer *t)
+@@ -408,13 +398,8 @@ static void hpet_set_timer(HPETTimer *t)
static void hpet_del_timer(HPETTimer *t)
{
@@ -73,7 +73,7 @@ index 509986c0a9..402cc960f0 100644
}
static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
-@@ -530,26 +515,20 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
+@@ -514,26 +499,20 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
switch ((addr - 0x100) % 0x20) {
case HPET_TN_CFG:
trace_hpet_ram_write_tn_cfg();
@@ -105,7 +105,7 @@ index 509986c0a9..402cc960f0 100644
}
break;
case HPET_TN_CFG + 4: // Interrupt capabilities
-@@ -627,10 +606,9 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
+@@ -611,10 +590,9 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
s->hpet_offset =
ticks_to_ns(s->hpet_counter) - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
for (i = 0; i < s->num_timers; i++) {
diff --git a/debian/patches/pve/0058-savevm-async-improve-setting-state-of-snapshot-opera.patch b/debian/patches/pve/0058-savevm-async-improve-setting-state-of-snapshot-opera.patch
index 30c1e45..8751ede 100644
--- a/debian/patches/pve/0058-savevm-async-improve-setting-state-of-snapshot-opera.patch
+++ b/debian/patches/pve/0058-savevm-async-improve-setting-state-of-snapshot-opera.patch
@@ -28,10 +28,10 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
1 file changed, 15 insertions(+), 18 deletions(-)
diff --git a/migration/savevm-async.c b/migration/savevm-async.c
-index 1e79fce9ba..e63dc6d8a3 100644
+index fbcf74f9e2..2163bf50b1 100644
--- a/migration/savevm-async.c
+++ b/migration/savevm-async.c
-@@ -450,23 +450,22 @@ static void coroutine_fn wait_for_close_co(void *opaque)
+@@ -451,23 +451,22 @@ static void coroutine_fn wait_for_close_co(void *opaque)
{
int64_t timeout;
@@ -70,7 +70,7 @@ index 1e79fce9ba..e63dc6d8a3 100644
}
// File closed and no other error, so ensure next snapshot can be started.
-@@ -497,8 +496,6 @@ void qmp_savevm_end(Error **errp)
+@@ -498,8 +497,6 @@ void qmp_savevm_end(Error **errp)
snap_state.saved_vm_running = false;
}
diff --git a/debian/patches/pve/0059-savevm-async-rename-saved_vm_running-to-vm_needs_sta.patch b/debian/patches/pve/0059-savevm-async-rename-saved_vm_running-to-vm_needs_sta.patch
index c313b95..706089c 100644
--- a/debian/patches/pve/0059-savevm-async-rename-saved_vm_running-to-vm_needs_sta.patch
+++ b/debian/patches/pve/0059-savevm-async-rename-saved_vm_running-to-vm_needs_sta.patch
@@ -12,10 +12,10 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/migration/savevm-async.c b/migration/savevm-async.c
-index e63dc6d8a3..1e34c31e8b 100644
+index 2163bf50b1..657a4ec9f6 100644
--- a/migration/savevm-async.c
+++ b/migration/savevm-async.c
-@@ -51,7 +51,7 @@ static struct SnapshotState {
+@@ -52,7 +52,7 @@ static struct SnapshotState {
int state;
Error *error;
Error *blocker;
@@ -24,7 +24,7 @@ index e63dc6d8a3..1e34c31e8b 100644
QEMUFile *file;
int64_t total_time;
QEMUBH *finalize_bh;
-@@ -224,9 +224,9 @@ static void process_savevm_finalize(void *opaque)
+@@ -225,9 +225,9 @@ static void process_savevm_finalize(void *opaque)
save_snapshot_error("process_savevm_cleanup: invalid state: %d",
snap_state.state);
}
@@ -36,7 +36,7 @@ index e63dc6d8a3..1e34c31e8b 100644
}
DPRINTF("timing: process_savevm_finalize (full) took %ld ms\n",
-@@ -352,7 +352,7 @@ void qmp_savevm_start(const char *statefile, Error **errp)
+@@ -353,7 +353,7 @@ void qmp_savevm_start(const char *statefile, Error **errp)
}
/* initialize snapshot info */
@@ -45,7 +45,7 @@ index e63dc6d8a3..1e34c31e8b 100644
snap_state.bs_pos = 0;
snap_state.total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
snap_state.blocker = NULL;
-@@ -440,9 +440,9 @@ restart:
+@@ -441,9 +441,9 @@ restart:
save_snapshot_error("setup failed");
@@ -57,7 +57,7 @@ index e63dc6d8a3..1e34c31e8b 100644
}
}
-@@ -491,9 +491,9 @@ void qmp_savevm_end(Error **errp)
+@@ -492,9 +492,9 @@ void qmp_savevm_end(Error **errp)
return;
}
diff --git a/debian/patches/pve/0060-savevm-async-improve-runstate-preservation-cleanup-e.patch b/debian/patches/pve/0060-savevm-async-improve-runstate-preservation-cleanup-e.patch
index 0487c02..8afd450 100644
--- a/debian/patches/pve/0060-savevm-async-improve-runstate-preservation-cleanup-e.patch
+++ b/debian/patches/pve/0060-savevm-async-improve-runstate-preservation-cleanup-e.patch
@@ -23,10 +23,10 @@ Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
1 file changed, 10 insertions(+), 15 deletions(-)
diff --git a/migration/savevm-async.c b/migration/savevm-async.c
-index 1e34c31e8b..d8d2c80475 100644
+index 657a4ec9f6..d70ae737bd 100644
--- a/migration/savevm-async.c
+++ b/migration/savevm-async.c
-@@ -178,6 +178,7 @@ static void process_savevm_finalize(void *opaque)
+@@ -179,6 +179,7 @@ static void process_savevm_finalize(void *opaque)
*/
blk_set_aio_context(snap_state.target, qemu_get_aio_context(), NULL);
@@ -34,7 +34,7 @@ index 1e34c31e8b..d8d2c80475 100644
ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
if (ret < 0) {
save_snapshot_error("vm_stop_force_state error %d", ret);
-@@ -352,7 +353,6 @@ void qmp_savevm_start(const char *statefile, Error **errp)
+@@ -353,7 +354,6 @@ void qmp_savevm_start(const char *statefile, Error **errp)
}
/* initialize snapshot info */
@@ -42,7 +42,7 @@ index 1e34c31e8b..d8d2c80475 100644
snap_state.bs_pos = 0;
snap_state.total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
snap_state.blocker = NULL;
-@@ -364,13 +364,14 @@ void qmp_savevm_start(const char *statefile, Error **errp)
+@@ -365,13 +365,14 @@ void qmp_savevm_start(const char *statefile, Error **errp)
}
if (!statefile) {
@@ -58,7 +58,7 @@ index 1e34c31e8b..d8d2c80475 100644
}
/* Open the image */
-@@ -380,12 +381,12 @@ void qmp_savevm_start(const char *statefile, Error **errp)
+@@ -381,12 +382,12 @@ void qmp_savevm_start(const char *statefile, Error **errp)
snap_state.target = blk_new_open(statefile, NULL, options, bdrv_oflags, &local_err);
if (!snap_state.target) {
error_setg(errp, "failed to open '%s'", statefile);
@@ -73,7 +73,7 @@ index 1e34c31e8b..d8d2c80475 100644
}
QIOChannel *ioc = QIO_CHANNEL(qio_channel_savevm_async_new(snap_state.target,
-@@ -394,7 +395,7 @@ void qmp_savevm_start(const char *statefile, Error **errp)
+@@ -395,7 +396,7 @@ void qmp_savevm_start(const char *statefile, Error **errp)
if (!snap_state.file) {
error_setg(errp, "failed to open '%s'", statefile);
@@ -82,7 +82,7 @@ index 1e34c31e8b..d8d2c80475 100644
}
/*
-@@ -402,8 +403,8 @@ void qmp_savevm_start(const char *statefile, Error **errp)
+@@ -403,8 +404,8 @@ void qmp_savevm_start(const char *statefile, Error **errp)
* State is cleared in process_savevm_co, but has to be initialized
* here (blocking main thread, from QMP) to avoid race conditions.
*/
@@ -93,7 +93,7 @@ index 1e34c31e8b..d8d2c80475 100644
}
memset(&mig_stats, 0, sizeof(mig_stats));
ms->to_dst_file = snap_state.file;
-@@ -418,7 +419,7 @@ void qmp_savevm_start(const char *statefile, Error **errp)
+@@ -419,7 +420,7 @@ void qmp_savevm_start(const char *statefile, Error **errp)
if (ret != 0) {
error_setg_errno(errp, -ret, "savevm state setup failed: %s",
local_err ? error_get_pretty(local_err) : "unknown error");
@@ -102,7 +102,7 @@ index 1e34c31e8b..d8d2c80475 100644
}
/* Async processing from here on out happens in iohandler context, so let
-@@ -436,14 +437,8 @@ void qmp_savevm_start(const char *statefile, Error **errp)
+@@ -437,14 +438,8 @@ void qmp_savevm_start(const char *statefile, Error **errp)
return;
diff --git a/debian/patches/pve/0061-savevm-async-use-dedicated-iothread-for-state-file.patch b/debian/patches/pve/0061-savevm-async-use-dedicated-iothread-for-state-file.patch
index 2b9c9ed..1e2c9e1 100644
--- a/debian/patches/pve/0061-savevm-async-use-dedicated-iothread-for-state-file.patch
+++ b/debian/patches/pve/0061-savevm-async-use-dedicated-iothread-for-state-file.patch
@@ -66,22 +66,14 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
[WB: update to the changed error handling in the previous commit]
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
---
- migration/savevm-async.c | 42 ++++++++++++++++++++++++++++------------
- 1 file changed, 30 insertions(+), 12 deletions(-)
+ migration/savevm-async.c | 41 ++++++++++++++++++++++++++++------------
+ 1 file changed, 29 insertions(+), 12 deletions(-)
diff --git a/migration/savevm-async.c b/migration/savevm-async.c
-index d8d2c80475..11ea4c601d 100644
+index d70ae737bd..2236f32784 100644
--- a/migration/savevm-async.c
+++ b/migration/savevm-async.c
-@@ -25,6 +25,7 @@
- #include "qemu/main-loop.h"
- #include "qemu/rcu.h"
- #include "qemu/yank.h"
-+#include "sysemu/iothread.h"
-
- /* #define DEBUG_SAVEVM_STATE */
-
-@@ -57,6 +58,7 @@ static struct SnapshotState {
+@@ -58,6 +58,7 @@ static struct SnapshotState {
QEMUBH *finalize_bh;
Coroutine *co;
QemuCoSleep target_close_wait;
@@ -89,7 +81,7 @@ index d8d2c80475..11ea4c601d 100644
} snap_state;
static bool savevm_aborted(void)
-@@ -256,16 +258,13 @@ static void coroutine_fn process_savevm_co(void *opaque)
+@@ -257,16 +258,13 @@ static void coroutine_fn process_savevm_co(void *opaque)
uint64_t threshold = 400 * 1000;
/*
@@ -108,7 +100,7 @@ index d8d2c80475..11ea4c601d 100644
pending_size = pend_precopy + pend_postcopy;
/*
-@@ -332,11 +331,17 @@ static void coroutine_fn process_savevm_co(void *opaque)
+@@ -333,11 +331,17 @@ static void coroutine_fn process_savevm_co(void *opaque)
qemu_bh_schedule(snap_state.finalize_bh);
}
@@ -127,7 +119,7 @@ index d8d2c80475..11ea4c601d 100644
BlockDriverState *target_bs = NULL;
int ret = 0;
-@@ -374,6 +379,19 @@ void qmp_savevm_start(const char *statefile, Error **errp)
+@@ -375,6 +379,19 @@ void qmp_savevm_start(const char *statefile, Error **errp)
goto fail;
}
@@ -147,7 +139,7 @@ index d8d2c80475..11ea4c601d 100644
/* Open the image */
QDict *options = NULL;
options = qdict_new();
-@@ -422,22 +440,20 @@ void qmp_savevm_start(const char *statefile, Error **errp)
+@@ -423,22 +440,20 @@ void qmp_savevm_start(const char *statefile, Error **errp)
goto fail;
}
@@ -174,7 +166,7 @@ index d8d2c80475..11ea4c601d 100644
save_snapshot_error("setup failed");
}
-@@ -463,6 +479,8 @@ static void coroutine_fn wait_for_close_co(void *opaque)
+@@ -464,6 +479,8 @@ static void coroutine_fn wait_for_close_co(void *opaque)
DPRINTF("savevm-end: no target file open\n");
}
diff --git a/debian/patches/pve/0062-savevm-async-treat-failure-to-set-iothread-context-a.patch b/debian/patches/pve/0062-savevm-async-treat-failure-to-set-iothread-context-a.patch
index 7d431fd..1def7ac 100644
--- a/debian/patches/pve/0062-savevm-async-treat-failure-to-set-iothread-context-a.patch
+++ b/debian/patches/pve/0062-savevm-async-treat-failure-to-set-iothread-context-a.patch
@@ -15,7 +15,7 @@ Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/migration/savevm-async.c b/migration/savevm-async.c
-index 11ea4c601d..f2b10b5519 100644
+index 2236f32784..730b815494 100644
--- a/migration/savevm-async.c
+++ b/migration/savevm-async.c
@@ -442,9 +442,9 @@ void qmp_savevm_start(const char *statefile, Error **errp)
diff --git a/debian/patches/pve/0063-PVE-backup-clean-up-directly-in-setup_snapshot_acces.patch b/debian/patches/pve/0063-PVE-backup-clean-up-directly-in-setup_snapshot_acces.patch
index d92c06c..a5582bd 100644
--- a/debian/patches/pve/0063-PVE-backup-clean-up-directly-in-setup_snapshot_acces.patch
+++ b/debian/patches/pve/0063-PVE-backup-clean-up-directly-in-setup_snapshot_acces.patch
@@ -18,7 +18,7 @@ Reviewed-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/pve-backup.c b/pve-backup.c
-index 32352fb5ec..2408f182bc 100644
+index b411d58a9a..9b66788ab5 100644
--- a/pve-backup.c
+++ b/pve-backup.c
@@ -576,6 +576,9 @@ static int setup_snapshot_access(PVEBackupDevInfo *di, Error **errp)
diff --git a/debian/patches/pve/0064-PVE-backup-factor-out-helper-to-clear-backup-state-s.patch b/debian/patches/pve/0064-PVE-backup-factor-out-helper-to-clear-backup-state-s.patch
index 8829ab3..83aa736 100644
--- a/debian/patches/pve/0064-PVE-backup-factor-out-helper-to-clear-backup-state-s.patch
+++ b/debian/patches/pve/0064-PVE-backup-factor-out-helper-to-clear-backup-state-s.patch
@@ -12,7 +12,7 @@ Reviewed-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
1 file changed, 18 insertions(+), 10 deletions(-)
diff --git a/pve-backup.c b/pve-backup.c
-index 2408f182bc..915649b5f9 100644
+index 9b66788ab5..588ee98ffc 100644
--- a/pve-backup.c
+++ b/pve-backup.c
@@ -811,6 +811,23 @@ err:
diff --git a/debian/patches/pve/0065-PVE-backup-factor-out-helper-to-initialize-backup-st.patch b/debian/patches/pve/0065-PVE-backup-factor-out-helper-to-initialize-backup-st.patch
index 3fc1e85..8cebc9f 100644
--- a/debian/patches/pve/0065-PVE-backup-factor-out-helper-to-initialize-backup-st.patch
+++ b/debian/patches/pve/0065-PVE-backup-factor-out-helper-to-initialize-backup-st.patch
@@ -12,7 +12,7 @@ Reviewed-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
1 file changed, 38 insertions(+), 24 deletions(-)
diff --git a/pve-backup.c b/pve-backup.c
-index 915649b5f9..88a981f81c 100644
+index 588ee98ffc..3be9930ad3 100644
--- a/pve-backup.c
+++ b/pve-backup.c
@@ -828,6 +828,43 @@ static void clear_backup_state_bitmap_list(void) {
diff --git a/debian/patches/pve/0066-PVE-backup-add-target-ID-in-backup-state.patch b/debian/patches/pve/0066-PVE-backup-add-target-ID-in-backup-state.patch
index 48c925d..b7d3a2c 100644
--- a/debian/patches/pve/0066-PVE-backup-add-target-ID-in-backup-state.patch
+++ b/debian/patches/pve/0066-PVE-backup-add-target-ID-in-backup-state.patch
@@ -15,7 +15,7 @@ Reviewed-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/pve-backup.c b/pve-backup.c
-index 88a981f81c..8789a0667a 100644
+index 3be9930ad3..87778f7e76 100644
--- a/pve-backup.c
+++ b/pve-backup.c
@@ -70,6 +70,7 @@ static struct PVEBackupState {
diff --git a/debian/patches/pve/0067-PVE-backup-get-device-info-allow-caller-to-specify-f.patch b/debian/patches/pve/0067-PVE-backup-get-device-info-allow-caller-to-specify-f.patch
index 85240aa..6011524 100644
--- a/debian/patches/pve/0067-PVE-backup-get-device-info-allow-caller-to-specify-f.patch
+++ b/debian/patches/pve/0067-PVE-backup-get-device-info-allow-caller-to-specify-f.patch
@@ -15,7 +15,7 @@ Reviewed-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/pve-backup.c b/pve-backup.c
-index 8789a0667a..755f1abcf1 100644
+index 87778f7e76..bd81621d51 100644
--- a/pve-backup.c
+++ b/pve-backup.c
@@ -719,7 +719,7 @@ static void create_backup_jobs_bh(void *opaque) {
diff --git a/debian/patches/pve/0068-PVE-backup-implement-backup-access-setup-and-teardow.patch b/debian/patches/pve/0068-PVE-backup-implement-backup-access-setup-and-teardow.patch
index ed39fa4..9e665ca 100644
--- a/debian/patches/pve/0068-PVE-backup-implement-backup-access-setup-and-teardow.patch
+++ b/debian/patches/pve/0068-PVE-backup-implement-backup-access-setup-and-teardow.patch
@@ -47,7 +47,7 @@ Reviewed-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
create mode 100644 pve-backup.h
diff --git a/pve-backup.c b/pve-backup.c
-index 755f1abcf1..091b5bd231 100644
+index bd81621d51..78ed6c980c 100644
--- a/pve-backup.c
+++ b/pve-backup.c
@@ -1,4 +1,5 @@
@@ -396,10 +396,10 @@ index 0000000000..4033bc848f
+
+#endif /* PVE_BACKUP_H */
diff --git a/qapi/block-core.json b/qapi/block-core.json
-index c581f1f238..3f092221ce 100644
+index 9bdcfa31ea..8d499650a8 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
-@@ -1019,6 +1019,9 @@
+@@ -1023,6 +1023,9 @@
#
# @pbs-library-version: Running version of libproxmox-backup-qemu0 library.
#
@@ -409,7 +409,7 @@ index c581f1f238..3f092221ce 100644
# @backup-fleecing: Whether backup fleecing is supported or not.
#
# @backup-max-workers: Whether the 'max-workers' @BackupPerf setting is
-@@ -1032,6 +1035,7 @@
+@@ -1036,6 +1039,7 @@
'pbs-dirty-bitmap-migration': 'bool',
'pbs-masterkey': 'bool',
'pbs-library-version': 'str',
@@ -417,7 +417,7 @@ index c581f1f238..3f092221ce 100644
'backup-fleecing': 'bool',
'backup-max-workers': 'bool' } }
-@@ -1098,6 +1102,51 @@
+@@ -1102,6 +1106,51 @@
##
{ 'command': 'query-pbs-bitmap-info', 'returns': ['PBSBitmapInfo'] }
@@ -470,18 +470,18 @@ index c581f1f238..3f092221ce 100644
# @BlockDeviceTimedStats:
#
diff --git a/system/runstate.c b/system/runstate.c
-index c2c9afa905..6f93d7c2fb 100644
+index 272801d307..73026a3884 100644
--- a/system/runstate.c
+++ b/system/runstate.c
@@ -60,6 +60,7 @@
- #include "sysemu/sysemu.h"
- #include "sysemu/tpm.h"
+ #include "system/system.h"
+ #include "system/tpm.h"
#include "trace.h"
+#include "pve-backup.h"
static NotifierList exit_notifiers =
NOTIFIER_LIST_INITIALIZER(exit_notifiers);
-@@ -920,6 +921,11 @@ void qemu_cleanup(int status)
+@@ -921,6 +922,11 @@ void qemu_cleanup(int status)
* requests happening from here on anyway.
*/
bdrv_drain_all_begin();
diff --git a/debian/patches/pve/0069-PVE-backup-factor-out-get_single_device_info-helper.patch b/debian/patches/pve/0069-PVE-backup-factor-out-get_single_device_info-helper.patch
index 367f78d..85346c3 100644
--- a/debian/patches/pve/0069-PVE-backup-factor-out-get_single_device_info-helper.patch
+++ b/debian/patches/pve/0069-PVE-backup-factor-out-get_single_device_info-helper.patch
@@ -11,7 +11,7 @@ Sigend-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
1 file changed, 53 insertions(+), 37 deletions(-)
diff --git a/pve-backup.c b/pve-backup.c
-index 091b5bd231..8b7414f057 100644
+index 78ed6c980c..681d25b97e 100644
--- a/pve-backup.c
+++ b/pve-backup.c
@@ -760,6 +760,57 @@ static bool fleecing_all(const char *device_id)
diff --git a/debian/patches/pve/0070-PVE-backup-implement-bitmap-support-for-external-bac.patch b/debian/patches/pve/0070-PVE-backup-implement-bitmap-support-for-external-bac.patch
index ea810af..597eabe 100644
--- a/debian/patches/pve/0070-PVE-backup-implement-bitmap-support-for-external-bac.patch
+++ b/debian/patches/pve/0070-PVE-backup-implement-bitmap-support-for-external-bac.patch
@@ -52,11 +52,11 @@ Reviewed-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
4 files changed, 220 insertions(+), 16 deletions(-)
diff --git a/pve-backup.c b/pve-backup.c
-index 8b7414f057..0490d1f421 100644
+index 681d25b97e..bd4d5e2579 100644
--- a/pve-backup.c
+++ b/pve-backup.c
@@ -15,6 +15,7 @@
- #include "qapi/qmp/qdict.h"
+ #include "qobject/qdict.h"
#include "qapi/qmp/qerror.h"
#include "qemu/cutils.h"
+#include "qemu/error-report.h"
@@ -387,10 +387,10 @@ index 4033bc848f..9ebeef7c8f 100644
#endif /* PVE_BACKUP_H */
diff --git a/qapi/block-core.json b/qapi/block-core.json
-index 3f092221ce..873db3f276 100644
+index 8d499650a8..61307ed1d7 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
-@@ -1114,9 +1114,33 @@
+@@ -1118,9 +1118,33 @@
#
# @size: the size of the block device in bytes.
#
@@ -425,7 +425,7 @@ index 3f092221ce..873db3f276 100644
##
# @backup-access-setup:
-@@ -1126,14 +1150,13 @@
+@@ -1130,14 +1154,13 @@
#
# @target-id: the unique ID of the backup target.
#
@@ -442,7 +442,7 @@ index 3f092221ce..873db3f276 100644
'returns': [ 'BackupAccessInfo' ], 'coroutine': true }
##
-@@ -1143,8 +1166,11 @@
+@@ -1147,8 +1170,11 @@
#
# @target-id: the ID of the backup target.
#
@@ -456,10 +456,10 @@ index 3f092221ce..873db3f276 100644
##
diff --git a/system/runstate.c b/system/runstate.c
-index 6f93d7c2fb..ef3277930f 100644
+index 73026a3884..cf775213bd 100644
--- a/system/runstate.c
+++ b/system/runstate.c
-@@ -925,7 +925,7 @@ void qemu_cleanup(int status)
+@@ -926,7 +926,7 @@ void qemu_cleanup(int status)
* The backup access is set up by a QMP command, but is neither owned by a monitor nor
* associated to a BlockBackend. Need to tear it down manually here.
*/
diff --git a/debian/patches/pve/0071-PVE-backup-backup-access-api-indicate-situation-wher.patch b/debian/patches/pve/0071-PVE-backup-backup-access-api-indicate-situation-wher.patch
index 3c182e0..d33d173 100644
--- a/debian/patches/pve/0071-PVE-backup-backup-access-api-indicate-situation-wher.patch
+++ b/debian/patches/pve/0071-PVE-backup-backup-access-api-indicate-situation-wher.patch
@@ -17,7 +17,7 @@ Reviewed-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/pve-backup.c b/pve-backup.c
-index 0490d1f421..8909842292 100644
+index bd4d5e2579..788647a22d 100644
--- a/pve-backup.c
+++ b/pve-backup.c
@@ -1119,7 +1119,11 @@ BackupAccessInfoList *coroutine_fn qmp_backup_access_setup(
@@ -34,10 +34,10 @@ index 0490d1f421..8909842292 100644
/* track clean chunks as reused */
dirty = MIN(bdrv_get_dirty_count(bitmap), di->size);
diff --git a/qapi/block-core.json b/qapi/block-core.json
-index 873db3f276..58586170d9 100644
+index 61307ed1d7..d94c856160 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
-@@ -1067,9 +1067,16 @@
+@@ -1071,9 +1071,16 @@
# base snapshot did not match the base given for the current job or
# the crypt mode has changed.
#
diff --git a/debian/patches/pve/0072-PVE-backup-backup-access-api-explicit-bitmap-mode-pa.patch b/debian/patches/pve/0072-PVE-backup-backup-access-api-explicit-bitmap-mode-pa.patch
index b9346e4..5d38ad2 100644
--- a/debian/patches/pve/0072-PVE-backup-backup-access-api-explicit-bitmap-mode-pa.patch
+++ b/debian/patches/pve/0072-PVE-backup-backup-access-api-explicit-bitmap-mode-pa.patch
@@ -15,7 +15,7 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
2 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/pve-backup.c b/pve-backup.c
-index 8909842292..18bcf29533 100644
+index 788647a22d..f657aba68d 100644
--- a/pve-backup.c
+++ b/pve-backup.c
@@ -1043,7 +1043,16 @@ BackupAccessInfoList *coroutine_fn qmp_backup_access_setup(
@@ -50,10 +50,10 @@ index 8909842292..18bcf29533 100644
BdrvDirtyBitmap *old_bitmap = bdrv_find_dirty_bitmap(di->bs, old_bitmap_name);
if (!old_bitmap) {
diff --git a/qapi/block-core.json b/qapi/block-core.json
-index 58586170d9..09beb3217c 100644
+index d94c856160..cde92071a1 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
-@@ -1145,9 +1145,27 @@
+@@ -1149,9 +1149,27 @@
# in the result to see if you can actually re-use the bitmap or if it had to
# be newly created.
#
diff --git a/debian/patches/pve/0073-PVE-backup-backup-access-api-simplify-bitmap-logic.patch b/debian/patches/pve/0073-PVE-backup-backup-access-api-simplify-bitmap-logic.patch
index ac22dc1..1074469 100644
--- a/debian/patches/pve/0073-PVE-backup-backup-access-api-simplify-bitmap-logic.patch
+++ b/debian/patches/pve/0073-PVE-backup-backup-access-api-simplify-bitmap-logic.patch
@@ -20,7 +20,7 @@ Reviewed-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
2 files changed, 26 insertions(+), 61 deletions(-)
diff --git a/pve-backup.c b/pve-backup.c
-index 18bcf29533..0ea0343b22 100644
+index f657aba68d..0450303017 100644
--- a/pve-backup.c
+++ b/pve-backup.c
@@ -74,7 +74,6 @@ static struct PVEBackupState {
@@ -168,10 +168,10 @@ index 18bcf29533..0ea0343b22 100644
}
g_list_free(backup_state.di_list);
diff --git a/qapi/block-core.json b/qapi/block-core.json
-index 09beb3217c..02c043f0f7 100644
+index cde92071a1..2fb51215f2 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
-@@ -1140,18 +1140,12 @@
+@@ -1144,18 +1144,12 @@
#
# @device: the block device name.
#
@@ -192,7 +192,7 @@ index 09beb3217c..02c043f0f7 100644
##
# @BackupAccessSetupBitmapMode:
-@@ -1175,7 +1169,10 @@
+@@ -1179,7 +1173,10 @@
#
# @target-id: the unique ID of the backup target.
#
diff --git a/debian/patches/series b/debian/patches/series
index 18cd6ba..fd151eb 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,14 +1,5 @@
extra/0001-monitor-qmp-fix-race-with-clients-disconnecting-earl.patch
extra/0002-ide-avoid-potential-deadlock-when-draining-during-tr.patch
-extra/0003-tcg-Reset-free_temps-before-tcg_optimize.patch
-extra/0004-target-i386-Reset-TSCs-of-parked-vCPUs-too-on-VM-res.patch
-extra/0005-i386-cpu-Mark-avx10_version-filtered-when-prefix-is-.patch
-extra/0006-net-Fix-announce_self.patch
-extra/0007-net-dump-Correctly-compute-Ethernet-packet-offset.patch
-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
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
diff --git a/qemu b/qemu
index ae35f03..ff3419c 160000
--- a/qemu
+++ b/qemu
@@ -1 +1 @@
-Subproject commit ae35f033b874c627d81d51070187fbf55f0bf1a7
+Subproject commit ff3419cbacdc9ad0715c716afeed65bb21a2bbbc
--
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] 4+ messages in thread
* [pve-devel] [PATCH qemu 2/2] squash some related patches
2025-06-02 10:22 [pve-devel] [PATCH-SERIES qemu 0/2] update submodule and patches to QEMU 10.0.2 Fiona Ebner
2025-06-02 10:22 ` [pve-devel] [PATCH qemu 1/2] " Fiona Ebner
@ 2025-06-02 10:22 ` Fiona Ebner
2025-06-17 6:48 ` [pve-devel] applied: [PATCH-SERIES qemu 0/2] update submodule and patches to QEMU 10.0.2 Thomas Lamprecht
2 siblings, 0 replies; 4+ messages in thread
From: Fiona Ebner @ 2025-06-02 10:22 UTC (permalink / raw)
To: pve-devel
In particular for backup and savevm-async, a lot can be grouped
together, many patches were just later fixups/improvements. Backup
patches are still grouped in three: original, addition of fleecing
and addition of external backup API (preparatory patches there
could be split and squashed too, but they're relatively new, so that
is something for next time).
The code with all patches applied is still the same.
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
---
...async-for-background-state-snapshots.patch | 128 +--
...add-optional-buffer-size-to-QEMUFile.patch | 6 +-
...ckup-Proxmox-backup-patches-for-QEMU.patch | 33 +-
...igrate-dirty-bitmap-state-via-savevm.patch | 4 +-
.../0038-block-add-alloc-track-driver.patch | 46 +-
...0042-PVE-backup-add-fleecing-option.patch} | 267 ++++--
...rror-out-when-auto-remove-is-not-set.patch | 43 -
...-version-deprecation-for-Proxmox-VE.patch} | 0
...d-seemingly-superfluous-child-permis.patch | 84 --
...oid-timer-storms-on-periodic-timers.patch} | 0
...ve-error-when-copy-before-write-fail.patch | 117 ---
...-full-64-bit-target-value-of-the-co.patch} | 0
...up-fixup-error-handling-for-fleecing.patch | 103 --
...hpet-accept-64-bit-reads-and-writes.patch} | 0
...r-out-setting-up-snapshot-access-for.patch | 135 ---
...-read-only-bits-directly-in-new_val.patch} | 0
...device-name-in-device-info-structure.patch | 135 ---
...t-remove-unnecessary-variable-index.patch} | 0
...de-device-name-in-error-when-setting.patch | 25 -
...e-high-bits-of-comparator-in-32-bit.patch} | 0
...nd-cleanup-persistence-of-interrupt.patch} | 0
...-out-helper-to-clear-backup-state-s.patch} | 0
...-out-helper-to-initialize-backup-st.patch} | 0
...ackup-add-target-ID-in-backup-state.patch} | 0
...vice-info-allow-caller-to-specify-f.patch} | 0
...ment-backup-access-setup-and-teardow.patch | 898 ++++++++++++++++++
...rove-setting-state-of-snapshot-opera.patch | 81 --
...ame-saved_vm_running-to-vm_needs_sta.patch | 71 --
...rove-runstate-preservation-cleanup-e.patch | 120 ---
...se-dedicated-iothread-for-state-file.patch | 177 ----
...at-failure-to-set-iothread-context-a.patch | 33 -
...-up-directly-in-setup_snapshot_acces.patch | 41 -
...ment-backup-access-setup-and-teardow.patch | 495 ----------
...or-out-get_single_device_info-helper.patch | 122 ---
...ment-bitmap-support-for-external-bac.patch | 470 ---------
...p-access-api-indicate-situation-wher.patch | 57 --
...p-access-api-explicit-bitmap-mode-pa.patch | 84 --
...kup-access-api-simplify-bitmap-logic.patch | 206 ----
debian/patches/series | 46 +-
39 files changed, 1221 insertions(+), 2806 deletions(-)
rename debian/patches/pve/{0044-PVE-backup-add-fleecing-option.patch => 0042-PVE-backup-add-fleecing-option.patch} (59%)
delete mode 100644 debian/patches/pve/0042-alloc-track-error-out-when-auto-remove-is-not-set.patch
rename debian/patches/pve/{0050-adapt-machine-version-deprecation-for-Proxmox-VE.patch => 0043-adapt-machine-version-deprecation-for-Proxmox-VE.patch} (100%)
delete mode 100644 debian/patches/pve/0043-alloc-track-avoid-seemingly-superfluous-child-permis.patch
rename debian/patches/pve/{0051-Revert-hpet-avoid-timer-storms-on-periodic-timers.patch => 0044-Revert-hpet-avoid-timer-storms-on-periodic-timers.patch} (100%)
delete mode 100644 debian/patches/pve/0045-PVE-backup-improve-error-when-copy-before-write-fail.patch
rename debian/patches/pve/{0052-Revert-hpet-store-full-64-bit-target-value-of-the-co.patch => 0045-Revert-hpet-store-full-64-bit-target-value-of-the-co.patch} (100%)
delete mode 100644 debian/patches/pve/0046-PVE-backup-fixup-error-handling-for-fleecing.patch
rename debian/patches/pve/{0053-Revert-hpet-accept-64-bit-reads-and-writes.patch => 0046-Revert-hpet-accept-64-bit-reads-and-writes.patch} (100%)
delete mode 100644 debian/patches/pve/0047-PVE-backup-factor-out-setting-up-snapshot-access-for.patch
rename debian/patches/pve/{0054-Revert-hpet-place-read-only-bits-directly-in-new_val.patch => 0047-Revert-hpet-place-read-only-bits-directly-in-new_val.patch} (100%)
delete mode 100644 debian/patches/pve/0048-PVE-backup-save-device-name-in-device-info-structure.patch
rename debian/patches/pve/{0055-Revert-hpet-remove-unnecessary-variable-index.patch => 0048-Revert-hpet-remove-unnecessary-variable-index.patch} (100%)
delete mode 100644 debian/patches/pve/0049-PVE-backup-include-device-name-in-error-when-setting.patch
rename debian/patches/pve/{0056-Revert-hpet-ignore-high-bits-of-comparator-in-32-bit.patch => 0049-Revert-hpet-ignore-high-bits-of-comparator-in-32-bit.patch} (100%)
rename debian/patches/pve/{0057-Revert-hpet-fix-and-cleanup-persistence-of-interrupt.patch => 0050-Revert-hpet-fix-and-cleanup-persistence-of-interrupt.patch} (100%)
rename debian/patches/pve/{0064-PVE-backup-factor-out-helper-to-clear-backup-state-s.patch => 0051-PVE-backup-factor-out-helper-to-clear-backup-state-s.patch} (100%)
rename debian/patches/pve/{0065-PVE-backup-factor-out-helper-to-initialize-backup-st.patch => 0052-PVE-backup-factor-out-helper-to-initialize-backup-st.patch} (100%)
rename debian/patches/pve/{0066-PVE-backup-add-target-ID-in-backup-state.patch => 0053-PVE-backup-add-target-ID-in-backup-state.patch} (100%)
rename debian/patches/pve/{0067-PVE-backup-get-device-info-allow-caller-to-specify-f.patch => 0054-PVE-backup-get-device-info-allow-caller-to-specify-f.patch} (100%)
create mode 100644 debian/patches/pve/0055-PVE-backup-implement-backup-access-setup-and-teardow.patch
delete mode 100644 debian/patches/pve/0058-savevm-async-improve-setting-state-of-snapshot-opera.patch
delete mode 100644 debian/patches/pve/0059-savevm-async-rename-saved_vm_running-to-vm_needs_sta.patch
delete mode 100644 debian/patches/pve/0060-savevm-async-improve-runstate-preservation-cleanup-e.patch
delete mode 100644 debian/patches/pve/0061-savevm-async-use-dedicated-iothread-for-state-file.patch
delete mode 100644 debian/patches/pve/0062-savevm-async-treat-failure-to-set-iothread-context-a.patch
delete mode 100644 debian/patches/pve/0063-PVE-backup-clean-up-directly-in-setup_snapshot_acces.patch
delete mode 100644 debian/patches/pve/0068-PVE-backup-implement-backup-access-setup-and-teardow.patch
delete mode 100644 debian/patches/pve/0069-PVE-backup-factor-out-get_single_device_info-helper.patch
delete mode 100644 debian/patches/pve/0070-PVE-backup-implement-bitmap-support-for-external-bac.patch
delete mode 100644 debian/patches/pve/0071-PVE-backup-backup-access-api-indicate-situation-wher.patch
delete mode 100644 debian/patches/pve/0072-PVE-backup-backup-access-api-explicit-bitmap-mode-pa.patch
delete mode 100644 debian/patches/pve/0073-PVE-backup-backup-access-api-simplify-bitmap-logic.patch
diff --git a/debian/patches/pve/0017-PVE-add-savevm-async-for-background-state-snapshots.patch b/debian/patches/pve/0017-PVE-add-savevm-async-for-background-state-snapshots.patch
index 6e19c3d..622191d 100644
--- a/debian/patches/pve/0017-PVE-add-savevm-async-for-background-state-snapshots.patch
+++ b/debian/patches/pve/0017-PVE-add-savevm-async-for-background-state-snapshots.patch
@@ -30,21 +30,24 @@ Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
adapt to QAPI and other changes for 8.2
make sure to not call vm_start() from coroutine
stop CPU throttling after finishing
- force raw format when loading state as suggested by Friedrich Weber]
+ force raw format when loading state as suggested by Friedrich Weber
+ improve setting state in savevm-end handler
+ improve runstate preservation
+ use dedicated iothread for state file to avoid deadlock, bug #6262]
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
---
hmp-commands-info.hx | 13 +
- hmp-commands.hx | 17 ++
+ hmp-commands.hx | 17 +
include/migration/snapshot.h | 2 +
include/monitor/hmp.h | 3 +
migration/meson.build | 1 +
- migration/savevm-async.c | 572 +++++++++++++++++++++++++++++++++++
+ migration/savevm-async.c | 581 +++++++++++++++++++++++++++++++++++
monitor/hmp-cmds.c | 38 +++
- qapi/migration.json | 34 +++
+ qapi/migration.json | 34 ++
qapi/misc.json | 18 ++
qemu-options.hx | 12 +
system/vl.c | 10 +
- 11 files changed, 720 insertions(+)
+ 11 files changed, 729 insertions(+)
create mode 100644 migration/savevm-async.c
diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
@@ -142,10 +145,10 @@ index cf66c78681..46e92249a1 100644
'threadinfo.c',
diff --git a/migration/savevm-async.c b/migration/savevm-async.c
new file mode 100644
-index 0000000000..7c0e857519
+index 0000000000..56e0fa6c69
--- /dev/null
+++ b/migration/savevm-async.c
-@@ -0,0 +1,572 @@
+@@ -0,0 +1,581 @@
+#include "qemu/osdep.h"
+#include "migration/channel-savevm-async.h"
+#include "migration/migration.h"
@@ -200,12 +203,13 @@ index 0000000000..7c0e857519
+ int state;
+ Error *error;
+ Error *blocker;
-+ int saved_vm_running;
++ int vm_needs_start;
+ QEMUFile *file;
+ int64_t total_time;
+ QEMUBH *finalize_bh;
+ Coroutine *co;
+ QemuCoSleep target_close_wait;
++ IOThread *iothread;
+} snap_state;
+
+static bool savevm_aborted(void)
@@ -327,6 +331,7 @@ index 0000000000..7c0e857519
+ */
+ blk_set_aio_context(snap_state.target, qemu_get_aio_context(), NULL);
+
++ snap_state.vm_needs_start = runstate_is_running();
+ ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
+ if (ret < 0) {
+ save_snapshot_error("vm_stop_force_state error %d", ret);
@@ -373,9 +378,9 @@ index 0000000000..7c0e857519
+ save_snapshot_error("process_savevm_cleanup: invalid state: %d",
+ snap_state.state);
+ }
-+ if (snap_state.saved_vm_running) {
++ if (snap_state.vm_needs_start) {
+ vm_start();
-+ snap_state.saved_vm_running = false;
++ snap_state.vm_needs_start = false;
+ }
+
+ DPRINTF("timing: process_savevm_finalize (full) took %ld ms\n",
@@ -404,16 +409,13 @@ index 0000000000..7c0e857519
+ uint64_t threshold = 400 * 1000;
+
+ /*
-+ * pending_{estimate,exact} are expected to be called without iothread
-+ * lock. Similar to what is done in migration.c, call the exact variant
-+ * only once pend_precopy in the estimate is below the threshold.
++ * Similar to what is done in migration.c, call the exact variant only
++ * once pend_precopy in the estimate is below the threshold.
+ */
-+ bql_unlock();
+ qemu_savevm_state_pending_estimate(&pend_precopy, &pend_postcopy);
+ if (pend_precopy <= threshold) {
+ qemu_savevm_state_pending_exact(&pend_precopy, &pend_postcopy);
+ }
-+ bql_lock();
+ pending_size = pend_precopy + pend_postcopy;
+
+ /*
@@ -480,11 +482,17 @@ index 0000000000..7c0e857519
+ qemu_bh_schedule(snap_state.finalize_bh);
+}
+
++static void savevm_cleanup_iothread(void) {
++ if (snap_state.iothread) {
++ iothread_destroy(snap_state.iothread);
++ snap_state.iothread = NULL;
++ }
++}
++
+void qmp_savevm_start(const char *statefile, Error **errp)
+{
+ Error *local_err = NULL;
+ MigrationState *ms = migrate_get_current();
-+ AioContext *iohandler_ctx = iohandler_get_aio_context();
+ BlockDriverState *target_bs = NULL;
+ int ret = 0;
+
@@ -501,7 +509,6 @@ index 0000000000..7c0e857519
+ }
+
+ /* initialize snapshot info */
-+ snap_state.saved_vm_running = runstate_is_running();
+ snap_state.bs_pos = 0;
+ snap_state.total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
+ snap_state.blocker = NULL;
@@ -513,13 +520,27 @@ index 0000000000..7c0e857519
+ }
+
+ if (!statefile) {
++ snap_state.vm_needs_start = runstate_is_running();
+ vm_stop(RUN_STATE_SAVE_VM);
+ snap_state.state = SAVE_STATE_COMPLETED;
+ return;
+ }
+
+ if (qemu_savevm_state_blocked(errp)) {
-+ return;
++ goto fail;
++ }
++
++ if (snap_state.iothread) {
++ /* This is not expected, so warn about it, but no point in re-creating a new iothread. */
++ warn_report("iothread for snapshot already exists - re-using");
++ } else {
++ snap_state.iothread =
++ iothread_create("__proxmox_savevm_async_iothread__", &local_err);
++ if (!snap_state.iothread) {
++ error_setg(errp, "creating iothread failed: %s",
++ local_err ? error_get_pretty(local_err) : "unknown error");
++ goto fail;
++ }
+ }
+
+ /* Open the image */
@@ -529,12 +550,12 @@ index 0000000000..7c0e857519
+ snap_state.target = blk_new_open(statefile, NULL, options, bdrv_oflags, &local_err);
+ if (!snap_state.target) {
+ error_setg(errp, "failed to open '%s'", statefile);
-+ goto restart;
++ goto fail;
+ }
+ target_bs = blk_bs(snap_state.target);
+ if (!target_bs) {
+ error_setg(errp, "failed to open '%s' - no block driver state", statefile);
-+ goto restart;
++ goto fail;
+ }
+
+ QIOChannel *ioc = QIO_CHANNEL(qio_channel_savevm_async_new(snap_state.target,
@@ -543,7 +564,7 @@ index 0000000000..7c0e857519
+
+ if (!snap_state.file) {
+ error_setg(errp, "failed to open '%s'", statefile);
-+ goto restart;
++ goto fail;
+ }
+
+ /*
@@ -551,8 +572,8 @@ index 0000000000..7c0e857519
+ * State is cleared in process_savevm_co, but has to be initialized
+ * here (blocking main thread, from QMP) to avoid race conditions.
+ */
-+ if (migrate_init(ms, errp)) {
-+ return;
++ if (migrate_init(ms, errp) != 0) {
++ goto fail;
+ }
+ memset(&mig_stats, 0, sizeof(mig_stats));
+ ms->to_dst_file = snap_state.file;
@@ -567,56 +588,49 @@ index 0000000000..7c0e857519
+ if (ret != 0) {
+ error_setg_errno(errp, -ret, "savevm state setup failed: %s",
+ local_err ? error_get_pretty(local_err) : "unknown error");
-+ return;
++ goto fail;
+ }
+
-+ /* Async processing from here on out happens in iohandler context, so let
-+ * the target bdrv have its home there.
-+ */
-+ ret = blk_set_aio_context(snap_state.target, iohandler_ctx, &local_err);
++ ret = blk_set_aio_context(snap_state.target, snap_state.iothread->ctx, &local_err);
+ if (ret != 0) {
-+ warn_report("failed to set iohandler context for VM state target: %s %s",
-+ local_err ? error_get_pretty(local_err) : "unknown error",
-+ strerror(-ret));
++ error_setg_errno(errp, -ret, "failed to set iothread context for VM state target: %s",
++ local_err ? error_get_pretty(local_err) : "unknown error");
++ goto fail;
+ }
+
+ snap_state.co = qemu_coroutine_create(&process_savevm_co, NULL);
-+ aio_co_schedule(iohandler_ctx, snap_state.co);
++ aio_co_schedule(snap_state.iothread->ctx, snap_state.co);
+
+ return;
+
-+restart:
-+
++fail:
++ savevm_cleanup_iothread();
+ save_snapshot_error("setup failed");
-+
-+ if (snap_state.saved_vm_running) {
-+ vm_start();
-+ snap_state.saved_vm_running = false;
-+ }
+}
+
+static void coroutine_fn wait_for_close_co(void *opaque)
+{
+ int64_t timeout;
+
-+ if (!snap_state.target) {
++ if (snap_state.target) {
++ /* wait until cleanup is done before returning, this ensures that after this
++ * call exits the statefile will be closed and can be removed immediately */
++ DPRINTF("savevm-end: waiting for cleanup\n");
++ timeout = 30L * 1000 * 1000 * 1000;
++ qemu_co_sleep_ns_wakeable(&snap_state.target_close_wait,
++ QEMU_CLOCK_REALTIME, timeout);
++ if (snap_state.target) {
++ save_snapshot_error("timeout waiting for target file close in "
++ "qmp_savevm_end");
++ /* we cannot assume the snapshot finished in this case, so leave the
++ * state alone - caller has to figure something out */
++ return;
++ }
++ } else {
+ DPRINTF("savevm-end: no target file open\n");
-+ return;
+ }
+
-+ /* wait until cleanup is done before returning, this ensures that after this
-+ * call exits the statefile will be closed and can be removed immediately */
-+ DPRINTF("savevm-end: waiting for cleanup\n");
-+ timeout = 30L * 1000 * 1000 * 1000;
-+ qemu_co_sleep_ns_wakeable(&snap_state.target_close_wait,
-+ QEMU_CLOCK_REALTIME, timeout);
-+ if (snap_state.target) {
-+ save_snapshot_error("timeout waiting for target file close in "
-+ "qmp_savevm_end");
-+ /* we cannot assume the snapshot finished in this case, so leave the
-+ * state alone - caller has to figure something out */
-+ return;
-+ }
++ savevm_cleanup_iothread();
+
+ // File closed and no other error, so ensure next snapshot can be started.
+ if (snap_state.state != SAVE_STATE_ERROR) {
@@ -641,13 +655,11 @@ index 0000000000..7c0e857519
+ return;
+ }
+
-+ if (snap_state.saved_vm_running) {
++ if (snap_state.vm_needs_start) {
+ vm_start();
-+ snap_state.saved_vm_running = false;
++ snap_state.vm_needs_start = false;
+ }
+
-+ snap_state.state = SAVE_STATE_DONE;
-+
+ qemu_coroutine_enter(wait_for_close);
+}
+
diff --git a/debian/patches/pve/0018-PVE-add-optional-buffer-size-to-QEMUFile.patch b/debian/patches/pve/0018-PVE-add-optional-buffer-size-to-QEMUFile.patch
index 13d522a..f5a0d96 100644
--- a/debian/patches/pve/0018-PVE-add-optional-buffer-size-to-QEMUFile.patch
+++ b/debian/patches/pve/0018-PVE-add-optional-buffer-size-to-QEMUFile.patch
@@ -184,10 +184,10 @@ index f5b9f430e0..0179b90698 100644
G_DEFINE_AUTOPTR_CLEANUP_FUNC(QEMUFile, qemu_fclose)
diff --git a/migration/savevm-async.c b/migration/savevm-async.c
-index 7c0e857519..fbcf74f9e2 100644
+index 56e0fa6c69..730b815494 100644
--- a/migration/savevm-async.c
+++ b/migration/savevm-async.c
-@@ -391,7 +391,7 @@ void qmp_savevm_start(const char *statefile, Error **errp)
+@@ -409,7 +409,7 @@ void qmp_savevm_start(const char *statefile, Error **errp)
QIOChannel *ioc = QIO_CHANNEL(qio_channel_savevm_async_new(snap_state.target,
&snap_state.bs_pos));
@@ -196,7 +196,7 @@ index 7c0e857519..fbcf74f9e2 100644
if (!snap_state.file) {
error_setg(errp, "failed to open '%s'", statefile);
-@@ -535,7 +535,8 @@ int load_snapshot_from_blockdev(const char *filename, Error **errp)
+@@ -544,7 +544,8 @@ int load_snapshot_from_blockdev(const char *filename, Error **errp)
bdrv_op_block_all(bs, blocker);
/* restore the VM state */
diff --git a/debian/patches/pve/0030-PVE-Backup-Proxmox-backup-patches-for-QEMU.patch b/debian/patches/pve/0030-PVE-Backup-Proxmox-backup-patches-for-QEMU.patch
index 060525f..3a4ca0f 100644
--- a/debian/patches/pve/0030-PVE-Backup-Proxmox-backup-patches-for-QEMU.patch
+++ b/debian/patches/pve/0030-PVE-Backup-Proxmox-backup-patches-for-QEMU.patch
@@ -94,11 +94,11 @@ Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
monitor/hmp-cmds.c | 72 +++
proxmox-backup-client.c | 146 +++++
proxmox-backup-client.h | 60 ++
- pve-backup.c | 1091 ++++++++++++++++++++++++++++++++
+ pve-backup.c | 1096 ++++++++++++++++++++++++++++++++
qapi/block-core.json | 233 +++++++
qapi/common.json | 14 +
qapi/machine.json | 16 +-
- 14 files changed, 1710 insertions(+), 14 deletions(-)
+ 14 files changed, 1715 insertions(+), 14 deletions(-)
create mode 100644 proxmox-backup-client.c
create mode 100644 proxmox-backup-client.h
create mode 100644 pve-backup.c
@@ -586,10 +586,10 @@ index 0000000000..8cbf645b2c
+#endif /* PROXMOX_BACKUP_CLIENT_H */
diff --git a/pve-backup.c b/pve-backup.c
new file mode 100644
-index 0000000000..36e5042860
+index 0000000000..e931cb9203
--- /dev/null
+++ b/pve-backup.c
-@@ -0,0 +1,1091 @@
+@@ -0,0 +1,1096 @@
+#include "proxmox-backup-client.h"
+#include "vma.h"
+
@@ -678,6 +678,7 @@ index 0000000000..36e5042860
+ size_t size;
+ uint64_t block_size;
+ uint8_t dev_id;
++ char* device_name;
+ int completed_ret; // INT_MAX if not completed
+ BdrvDirtyBitmap *bitmap;
+ BlockDriverState *target;
@@ -911,6 +912,8 @@ index 0000000000..36e5042860
+ }
+
+ di->bs = NULL;
++ g_free(di->device_name);
++ di->device_name = NULL;
+
+ assert(di->target == NULL);
+
@@ -1200,6 +1203,8 @@ index 0000000000..36e5042860
+ }
+ PVEBackupDevInfo *di = g_new0(PVEBackupDevInfo, 1);
+ di->bs = bs;
++ di->device_name = g_strdup(bdrv_get_device_name(bs));
++
+ di_list = g_list_append(di_list, di);
+ d++;
+ }
@@ -1213,6 +1218,7 @@ index 0000000000..36e5042860
+
+ PVEBackupDevInfo *di = g_new0(PVEBackupDevInfo, 1);
+ di->bs = bs;
++ di->device_name = g_strdup(bdrv_get_device_name(bs));
+ di_list = g_list_append(di_list, di);
+ }
+ }
@@ -1379,9 +1385,6 @@ index 0000000000..36e5042860
+
+ di->block_size = dump_cb_block_size;
+
-+ bdrv_graph_co_rdlock();
-+ const char *devname = bdrv_get_device_name(di->bs);
-+ bdrv_graph_co_rdunlock();
+ PBSBitmapAction action = PBS_BITMAP_ACTION_NOT_USED;
+ size_t dirty = di->size;
+
@@ -1396,7 +1399,8 @@ index 0000000000..36e5042860
+ }
+ action = PBS_BITMAP_ACTION_NEW;
+ } else {
-+ expect_only_dirty = proxmox_backup_check_incremental(pbs, devname, di->size) != 0;
++ expect_only_dirty =
++ proxmox_backup_check_incremental(pbs, di->device_name, di->size) != 0;
+ }
+
+ if (expect_only_dirty) {
@@ -1420,7 +1424,8 @@ index 0000000000..36e5042860
+ }
+ }
+
-+ int dev_id = proxmox_backup_co_register_image(pbs, devname, di->size, expect_only_dirty, errp);
++ int dev_id = proxmox_backup_co_register_image(pbs, di->device_name, di->size,
++ expect_only_dirty, errp);
+ if (dev_id < 0) {
+ goto err_mutex;
+ }
@@ -1432,7 +1437,7 @@ index 0000000000..36e5042860
+ di->dev_id = dev_id;
+
+ PBSBitmapInfo *info = g_malloc(sizeof(*info));
-+ info->drive = g_strdup(devname);
++ info->drive = g_strdup(di->device_name);
+ info->action = action;
+ info->size = di->size;
+ info->dirty = dirty;
@@ -1455,10 +1460,7 @@ index 0000000000..36e5042860
+ goto err_mutex;
+ }
+
-+ bdrv_graph_co_rdlock();
-+ const char *devname = bdrv_get_device_name(di->bs);
-+ bdrv_graph_co_rdunlock();
-+ di->dev_id = vma_writer_register_stream(vmaw, devname, di->size);
++ di->dev_id = vma_writer_register_stream(vmaw, di->device_name, di->size);
+ if (di->dev_id <= 0) {
+ error_set(errp, ERROR_CLASS_GENERIC_ERROR,
+ "register_stream failed");
@@ -1569,6 +1571,9 @@ index 0000000000..36e5042860
+ bdrv_co_unref(di->target);
+ }
+
++ g_free(di->device_name);
++ di->device_name = NULL;
++
+ g_free(di);
+ }
+ g_list_free(di_list);
diff --git a/debian/patches/pve/0034-PVE-Migrate-dirty-bitmap-state-via-savevm.patch b/debian/patches/pve/0034-PVE-Migrate-dirty-bitmap-state-via-savevm.patch
index 45a968b..cf3897f 100644
--- a/debian/patches/pve/0034-PVE-Migrate-dirty-bitmap-state-via-savevm.patch
+++ b/debian/patches/pve/0034-PVE-Migrate-dirty-bitmap-state-via-savevm.patch
@@ -180,10 +180,10 @@ index 0000000000..a97187e4d7
+ NULL);
+}
diff --git a/pve-backup.c b/pve-backup.c
-index 36e5042860..11ea4b5c56 100644
+index e931cb9203..366b015589 100644
--- a/pve-backup.c
+++ b/pve-backup.c
-@@ -1084,6 +1084,7 @@ ProxmoxSupportStatus *qmp_query_proxmox_support(Error **errp)
+@@ -1089,6 +1089,7 @@ ProxmoxSupportStatus *qmp_query_proxmox_support(Error **errp)
ret->pbs_library_version = g_strdup(proxmox_backup_qemu_version());
ret->pbs_dirty_bitmap = true;
ret->pbs_dirty_bitmap_savevm = true;
diff --git a/debian/patches/pve/0038-block-add-alloc-track-driver.patch b/debian/patches/pve/0038-block-add-alloc-track-driver.patch
index 5a527e4..5def145 100644
--- a/debian/patches/pve/0038-block-add-alloc-track-driver.patch
+++ b/debian/patches/pve/0038-block-add-alloc-track-driver.patch
@@ -31,21 +31,22 @@ Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
[FE: adapt to changed function signatures
make error return value consistent with QEMU
avoid premature break during read
- adhere to block graph lock requirements]
+ adhere to block graph lock requirements
+ avoid superfluous child permission update]
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
---
- block/alloc-track.c | 366 ++++++++++++++++++++++++++++++++++++++++++++
+ block/alloc-track.c | 343 ++++++++++++++++++++++++++++++++++++++++++++
block/meson.build | 1 +
- block/stream.c | 34 ++++
- 3 files changed, 401 insertions(+)
+ block/stream.c | 34 +++++
+ 3 files changed, 378 insertions(+)
create mode 100644 block/alloc-track.c
diff --git a/block/alloc-track.c b/block/alloc-track.c
new file mode 100644
-index 0000000000..cb9829ae36
+index 0000000000..718aaabf2a
--- /dev/null
+++ b/block/alloc-track.c
-@@ -0,0 +1,366 @@
+@@ -0,0 +1,343 @@
+/*
+ * Node to allow backing images to be applied to any node. Assumes a blank
+ * image to begin with, only new writes are tracked as allocated, thus this
@@ -73,16 +74,9 @@ index 0000000000..cb9829ae36
+
+#define TRACK_OPT_AUTO_REMOVE "auto-remove"
+
-+typedef enum DropState {
-+ DropNone,
-+ DropInProgress,
-+} DropState;
-+
+typedef struct {
+ BdrvDirtyBitmap *bitmap;
+ uint64_t granularity;
-+ DropState drop_state;
-+ bool auto_remove;
+} BDRVAllocTrackState;
+
+static QemuOptsList runtime_opts = {
@@ -134,7 +128,11 @@ index 0000000000..cb9829ae36
+ goto fail;
+ }
+
-+ s->auto_remove = qemu_opt_get_bool(opts, TRACK_OPT_AUTO_REMOVE, false);
++ if (!qemu_opt_get_bool(opts, TRACK_OPT_AUTO_REMOVE, false)) {
++ error_setg(errp, "alloc-track: requires auto-remove option to be set to on");
++ ret = -EINVAL;
++ goto fail;
++ }
+
+ /* open the target (write) node, backing will be attached by block layer */
+ file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
@@ -182,8 +180,6 @@ index 0000000000..cb9829ae36
+ goto fail;
+ }
+
-+ s->drop_state = DropNone;
-+
+fail:
+ if (ret < 0) {
+ bdrv_graph_wrlock();
@@ -334,18 +330,8 @@ index 0000000000..cb9829ae36
+ BlockReopenQueue *reopen_queue, uint64_t perm, uint64_t shared,
+ uint64_t *nperm, uint64_t *nshared)
+{
-+ BDRVAllocTrackState *s = bs->opaque;
-+
+ *nshared = BLK_PERM_ALL;
+
-+ /* in case we're currently dropping ourselves, claim to not use any
-+ * permissions at all - which is fine, since from this point on we will
-+ * never issue a read or write anymore */
-+ if (s->drop_state == DropInProgress) {
-+ *nperm = 0;
-+ return;
-+ }
-+
+ if (role & BDRV_CHILD_DATA) {
+ *nperm = perm & DEFAULT_PERM_PASSTHROUGH;
+ } else {
@@ -371,14 +357,6 @@ index 0000000000..cb9829ae36
+ * kinda fits better, but in the long-term, a special parameter would be
+ * nice (or done via qemu-server via upcoming blockdev-replace QMP command).
+ */
-+ if (backing_file == NULL) {
-+ BDRVAllocTrackState *s = bs->opaque;
-+ bdrv_drained_begin(bs);
-+ s->drop_state = DropInProgress;
-+ bdrv_child_refresh_perms(bs, bs->file, &error_abort);
-+ bdrv_drained_end(bs);
-+ }
-+
+ return 0;
+}
+
diff --git a/debian/patches/pve/0044-PVE-backup-add-fleecing-option.patch b/debian/patches/pve/0042-PVE-backup-add-fleecing-option.patch
similarity index 59%
rename from debian/patches/pve/0044-PVE-backup-add-fleecing-option.patch
rename to debian/patches/pve/0042-PVE-backup-add-fleecing-option.patch
index b6eaade..1fadfa5 100644
--- a/debian/patches/pve/0044-PVE-backup-add-fleecing-option.patch
+++ b/debian/patches/pve/0042-PVE-backup-add-fleecing-option.patch
@@ -61,12 +61,91 @@ it has no parent, so just pass the one from the original bs.
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
+[FE: improve error when cbw fails as reported by Friedrich Weber]
+Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
---
+ block/copy-before-write.c | 18 ++--
+ block/copy-before-write.h | 1 +
block/monitor/block-hmp-cmds.c | 1 +
- pve-backup.c | 134 ++++++++++++++++++++++++++++++++-
- qapi/block-core.json | 10 ++-
- 3 files changed, 141 insertions(+), 4 deletions(-)
+ pve-backup.c | 175 ++++++++++++++++++++++++++++++++-
+ qapi/block-core.json | 10 +-
+ 5 files changed, 195 insertions(+), 10 deletions(-)
+diff --git a/block/copy-before-write.c b/block/copy-before-write.c
+index fd470f5f92..5c23b578ef 100644
+--- a/block/copy-before-write.c
++++ b/block/copy-before-write.c
+@@ -27,6 +27,7 @@
+ #include "qobject/qjson.h"
+
+ #include "system/block-backend.h"
++#include "qemu/atomic.h"
+ #include "qemu/cutils.h"
+ #include "qapi/error.h"
+ #include "block/block_int.h"
+@@ -75,7 +76,8 @@ typedef struct BDRVCopyBeforeWriteState {
+ * @snapshot_error is normally zero. But on first copy-before-write failure
+ * when @on_cbw_error == ON_CBW_ERROR_BREAK_SNAPSHOT, @snapshot_error takes
+ * value of this error (<0). After that all in-flight and further
+- * snapshot-API requests will fail with that error.
++ * snapshot-API requests will fail with that error. To be accessed with
++ * atomics.
+ */
+ int snapshot_error;
+ } BDRVCopyBeforeWriteState;
+@@ -115,7 +117,7 @@ static coroutine_fn int cbw_do_copy_before_write(BlockDriverState *bs,
+ return 0;
+ }
+
+- if (s->snapshot_error) {
++ if (qatomic_read(&s->snapshot_error)) {
+ return 0;
+ }
+
+@@ -139,9 +141,7 @@ static coroutine_fn int cbw_do_copy_before_write(BlockDriverState *bs,
+ WITH_QEMU_LOCK_GUARD(&s->lock) {
+ if (ret < 0) {
+ assert(s->on_cbw_error == ON_CBW_ERROR_BREAK_SNAPSHOT);
+- if (!s->snapshot_error) {
+- s->snapshot_error = ret;
+- }
++ qatomic_cmpxchg(&s->snapshot_error, 0, ret);
+ } else {
+ bdrv_set_dirty_bitmap(s->done_bitmap, off, end - off);
+ }
+@@ -215,7 +215,7 @@ cbw_snapshot_read_lock(BlockDriverState *bs, int64_t offset, int64_t bytes,
+
+ QEMU_LOCK_GUARD(&s->lock);
+
+- if (s->snapshot_error) {
++ if (qatomic_read(&s->snapshot_error)) {
+ g_free(req);
+ return NULL;
+ }
+@@ -595,6 +595,12 @@ void bdrv_cbw_drop(BlockDriverState *bs)
+ bdrv_unref(bs);
+ }
+
++int bdrv_cbw_snapshot_error(BlockDriverState *bs)
++{
++ BDRVCopyBeforeWriteState *s = bs->opaque;
++ return qatomic_read(&s->snapshot_error);
++}
++
+ static void cbw_init(void)
+ {
+ bdrv_register(&bdrv_cbw_filter);
+diff --git a/block/copy-before-write.h b/block/copy-before-write.h
+index 2a5d4ba693..969da3620f 100644
+--- a/block/copy-before-write.h
++++ b/block/copy-before-write.h
+@@ -44,5 +44,6 @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
+ BlockCopyState **bcs,
+ Error **errp);
+ void bdrv_cbw_drop(BlockDriverState *bs);
++int bdrv_cbw_snapshot_error(BlockDriverState *bs);
+
+ #endif /* COPY_BEFORE_WRITE_H */
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
index 4f30f99644..66d16d342f 100644
--- a/block/monitor/block-hmp-cmds.c
@@ -80,7 +159,7 @@ index 4f30f99644..66d16d342f 100644
hmp_handle_error(mon, error);
diff --git a/pve-backup.c b/pve-backup.c
-index 11ea4b5c56..257cd0b0e1 100644
+index 366b015589..9b66788ab5 100644
--- a/pve-backup.c
+++ b/pve-backup.c
@@ -7,6 +7,7 @@
@@ -107,17 +186,12 @@ index 11ea4b5c56..257cd0b0e1 100644
size_t size;
uint64_t block_size;
uint8_t dev_id;
-@@ -354,6 +362,22 @@ static void pvebackup_complete_cb(void *opaque, int ret)
- PVEBackupDevInfo *di = opaque;
- di->completed_ret = ret;
+@@ -352,11 +360,44 @@ static void coroutine_fn pvebackup_co_complete_stream(void *opaque)
+ qemu_co_mutex_unlock(&backup_state.backup_mutex);
+ }
-+ /*
-+ * Handle block-graph specific cleanup (for fleecing) outside of the coroutine, because the work
-+ * won't be done as a coroutine anyways:
-+ * - For snapshot_access, allows doing bdrv_unref() directly. Doing it via bdrv_co_unref() would
-+ * just spawn a BH calling bdrv_unref().
-+ * - For cbw, draining would need to spawn a BH.
-+ */
++static void cleanup_snapshot_access(PVEBackupDevInfo *di)
++{
+ if (di->fleecing.snapshot_access) {
+ bdrv_unref(di->fleecing.snapshot_access);
+ di->fleecing.snapshot_access = NULL;
@@ -126,11 +200,104 @@ index 11ea4b5c56..257cd0b0e1 100644
+ bdrv_cbw_drop(di->fleecing.cbw);
+ di->fleecing.cbw = NULL;
+ }
++}
++
+ static void pvebackup_complete_cb(void *opaque, int ret)
+ {
+ PVEBackupDevInfo *di = opaque;
+ di->completed_ret = ret;
+
++ if (di->fleecing.cbw) {
++ /*
++ * With fleecing, failure for cbw does not fail the guest write, but only sets the snapshot
++ * error, making further requests to the snapshot fail with EACCES, which then also fail the
++ * job. But that code is not the root cause and just confusing, so update it.
++ */
++ int snapshot_error = bdrv_cbw_snapshot_error(di->fleecing.cbw);
++ if (di->completed_ret == -EACCES && snapshot_error) {
++ di->completed_ret = snapshot_error;
++ }
++ }
++
++ /*
++ * Handle block-graph specific cleanup (for fleecing) outside of the coroutine, because the work
++ * won't be done as a coroutine anyways:
++ * - For snapshot_access, allows doing bdrv_unref() directly. Doing it via bdrv_co_unref() would
++ * just spawn a BH calling bdrv_unref().
++ * - For cbw, draining would need to spawn a BH.
++ */
++ cleanup_snapshot_access(di);
+
/*
* Needs to happen outside of coroutine, because it takes the graph write lock.
*/
-@@ -520,9 +544,77 @@ static void create_backup_jobs_bh(void *opaque) {
+@@ -487,6 +528,65 @@ static int coroutine_fn pvebackup_co_add_config(
+ goto out;
+ }
+
++/*
++ * Setup a snapshot-access block node for a device with associated fleecing image.
++ */
++static int setup_snapshot_access(PVEBackupDevInfo *di, Error **errp)
++{
++ Error *local_err = NULL;
++
++ if (!di->fleecing.bs) {
++ error_setg(errp, "no associated fleecing image");
++ return -1;
++ }
++
++ QDict *cbw_opts = qdict_new();
++ qdict_put_str(cbw_opts, "driver", "copy-before-write");
++ qdict_put_str(cbw_opts, "file", bdrv_get_node_name(di->bs));
++ qdict_put_str(cbw_opts, "target", bdrv_get_node_name(di->fleecing.bs));
++
++ if (di->bitmap) {
++ /*
++ * Only guest writes to parts relevant for the backup need to be intercepted with
++ * old data being copied to the fleecing image.
++ */
++ qdict_put_str(cbw_opts, "bitmap.node", bdrv_get_node_name(di->bs));
++ qdict_put_str(cbw_opts, "bitmap.name", bdrv_dirty_bitmap_name(di->bitmap));
++ }
++ /*
++ * Fleecing storage is supposed to be fast and it's better to break backup than guest
++ * writes. Certain guest drivers like VirtIO-win have 60 seconds timeout by default, so
++ * abort a bit before that.
++ */
++ qdict_put_str(cbw_opts, "on-cbw-error", "break-snapshot");
++ qdict_put_int(cbw_opts, "cbw-timeout", 45);
++
++ di->fleecing.cbw = bdrv_insert_node(di->bs, cbw_opts, BDRV_O_RDWR, &local_err);
++
++ if (!di->fleecing.cbw) {
++ error_setg(errp, "appending cbw node for fleecing failed: %s",
++ local_err ? error_get_pretty(local_err) : "unknown error");
++ return -1;
++ }
++
++ QDict *snapshot_access_opts = qdict_new();
++ qdict_put_str(snapshot_access_opts, "driver", "snapshot-access");
++ qdict_put_str(snapshot_access_opts, "file", bdrv_get_node_name(di->fleecing.cbw));
++
++ di->fleecing.snapshot_access =
++ bdrv_open(NULL, NULL, snapshot_access_opts, BDRV_O_RDWR | BDRV_O_UNMAP, &local_err);
++ if (!di->fleecing.snapshot_access) {
++ bdrv_cbw_drop(di->fleecing.cbw);
++ di->fleecing.cbw = NULL;
++
++ error_setg(errp, "setting up snapshot access for fleecing failed: %s",
++ local_err ? error_get_pretty(local_err) : "unknown error");
++ return -1;
++ }
++
++ return 0;
++}
++
+ /*
+ * backup_job_create can *not* be run from a coroutine, so this can't either.
+ * The caller is responsible that backup_mutex is held nonetheless.
+@@ -523,9 +623,42 @@ static void create_backup_jobs_bh(void *opaque) {
}
bdrv_drained_begin(di->bs);
@@ -138,50 +305,15 @@ index 11ea4b5c56..257cd0b0e1 100644
+
+ BlockDriverState *source_bs = di->bs;
+ bool discard_source = false;
-+ bdrv_graph_co_rdlock();
-+ const char *job_id = bdrv_get_device_name(di->bs);
-+ bdrv_graph_co_rdunlock();
+ if (di->fleecing.bs) {
-+ QDict *cbw_opts = qdict_new();
-+ qdict_put_str(cbw_opts, "driver", "copy-before-write");
-+ qdict_put_str(cbw_opts, "file", bdrv_get_node_name(di->bs));
-+ qdict_put_str(cbw_opts, "target", bdrv_get_node_name(di->fleecing.bs));
-+
-+ if (di->bitmap) {
-+ /*
-+ * Only guest writes to parts relevant for the backup need to be intercepted with
-+ * old data being copied to the fleecing image.
-+ */
-+ qdict_put_str(cbw_opts, "bitmap.node", bdrv_get_node_name(di->bs));
-+ qdict_put_str(cbw_opts, "bitmap.name", bdrv_dirty_bitmap_name(di->bitmap));
-+ }
-+ /*
-+ * Fleecing storage is supposed to be fast and it's better to break backup than guest
-+ * writes. Certain guest drivers like VirtIO-win have 60 seconds timeout by default, so
-+ * abort a bit before that.
-+ */
-+ qdict_put_str(cbw_opts, "on-cbw-error", "break-snapshot");
-+ qdict_put_int(cbw_opts, "cbw-timeout", 45);
-+
-+ di->fleecing.cbw = bdrv_insert_node(di->bs, cbw_opts, BDRV_O_RDWR, &local_err);
-+
-+ if (!di->fleecing.cbw) {
-+ error_setg(errp, "appending cbw node for fleecing failed: %s",
++ if (setup_snapshot_access(di, &local_err) < 0) {
++ error_setg(errp, "%s - setting up snapshot access for fleecing failed: %s",
++ di->device_name,
+ local_err ? error_get_pretty(local_err) : "unknown error");
++ bdrv_drained_end(di->bs);
+ break;
+ }
+
-+ QDict *snapshot_access_opts = qdict_new();
-+ qdict_put_str(snapshot_access_opts, "driver", "snapshot-access");
-+ qdict_put_str(snapshot_access_opts, "file", bdrv_get_node_name(di->fleecing.cbw));
-+
-+ di->fleecing.snapshot_access =
-+ bdrv_open(NULL, NULL, snapshot_access_opts, BDRV_O_RDWR | BDRV_O_UNMAP, &local_err);
-+ if (!di->fleecing.snapshot_access) {
-+ error_setg(errp, "setting up snapshot access for fleecing failed: %s",
-+ local_err ? error_get_pretty(local_err) : "unknown error");
-+ break;
-+ }
+ source_bs = di->fleecing.snapshot_access;
+ discard_source = true;
+
@@ -205,12 +337,20 @@ index 11ea4b5c56..257cd0b0e1 100644
BlockJob *job = backup_job_create(
- NULL, di->bs, di->target, backup_state.speed, sync_mode, di->bitmap,
- bitmap_mode, false, NULL, &backup_state.perf, BLOCKDEV_ON_ERROR_REPORT,
-+ job_id, source_bs, di->target, backup_state.speed, sync_mode, di->bitmap,
++ di->device_name, source_bs, di->target, backup_state.speed, sync_mode, di->bitmap,
+ bitmap_mode, false, discard_source, NULL, &perf, BLOCKDEV_ON_ERROR_REPORT,
BLOCKDEV_ON_ERROR_REPORT, JOB_DEFAULT, pvebackup_complete_cb, di, backup_state.txn,
&local_err);
-@@ -578,6 +670,14 @@ static void create_backup_jobs_bh(void *opaque) {
+@@ -539,6 +672,7 @@ static void create_backup_jobs_bh(void *opaque) {
+ }
+
+ if (!job || local_err) {
++ cleanup_snapshot_access(di);
+ error_setg(errp, "backup_job_create failed: %s",
+ local_err ? error_get_pretty(local_err) : "null");
+ break;
+@@ -581,6 +715,14 @@ static void create_backup_jobs_bh(void *opaque) {
aio_co_enter(data->ctx, data->co);
}
@@ -225,7 +365,7 @@ index 11ea4b5c56..257cd0b0e1 100644
/*
* Returns a list of device infos, which needs to be freed by the caller. In
* case of an error, errp will be set, but the returned value might still be a
-@@ -585,6 +685,7 @@ static void create_backup_jobs_bh(void *opaque) {
+@@ -588,6 +730,7 @@ static void create_backup_jobs_bh(void *opaque) {
*/
static GList coroutine_fn GRAPH_RDLOCK *get_device_info(
const char *devlist,
@@ -233,11 +373,10 @@ index 11ea4b5c56..257cd0b0e1 100644
Error **errp)
{
gchar **devs = NULL;
-@@ -608,6 +709,31 @@ static GList coroutine_fn GRAPH_RDLOCK *get_device_info(
- }
- PVEBackupDevInfo *di = g_new0(PVEBackupDevInfo, 1);
+@@ -613,6 +756,30 @@ static GList coroutine_fn GRAPH_RDLOCK *get_device_info(
di->bs = bs;
-+
+ di->device_name = g_strdup(bdrv_get_device_name(bs));
+
+ if (fleecing && device_uses_fleecing(*d)) {
+ g_autofree gchar *fleecing_devid = g_strconcat(*d, "-fleecing", NULL);
+ BlockBackend *fleecing_blk = blk_by_name(fleecing_devid);
@@ -265,7 +404,7 @@ index 11ea4b5c56..257cd0b0e1 100644
di_list = g_list_append(di_list, di);
d++;
}
-@@ -657,6 +783,7 @@ UuidInfo coroutine_fn *qmp_backup(
+@@ -663,6 +830,7 @@ UuidInfo coroutine_fn *qmp_backup(
const char *devlist,
bool has_speed, int64_t speed,
bool has_max_workers, int64_t max_workers,
@@ -273,7 +412,7 @@ index 11ea4b5c56..257cd0b0e1 100644
Error **errp)
{
assert(qemu_in_coroutine());
-@@ -685,7 +812,7 @@ UuidInfo coroutine_fn *qmp_backup(
+@@ -691,7 +859,7 @@ UuidInfo coroutine_fn *qmp_backup(
format = has_format ? format : BACKUP_FORMAT_VMA;
bdrv_graph_co_rdlock();
@@ -282,7 +421,7 @@ index 11ea4b5c56..257cd0b0e1 100644
bdrv_graph_co_rdunlock();
if (local_err) {
error_propagate(errp, local_err);
-@@ -1088,5 +1215,6 @@ ProxmoxSupportStatus *qmp_query_proxmox_support(Error **errp)
+@@ -1093,5 +1261,6 @@ ProxmoxSupportStatus *qmp_query_proxmox_support(Error **errp)
ret->query_bitmap_info = true;
ret->pbs_masterkey = true;
ret->backup_max_workers = true;
diff --git a/debian/patches/pve/0042-alloc-track-error-out-when-auto-remove-is-not-set.patch b/debian/patches/pve/0042-alloc-track-error-out-when-auto-remove-is-not-set.patch
deleted file mode 100644
index c65479d..0000000
--- a/debian/patches/pve/0042-alloc-track-error-out-when-auto-remove-is-not-set.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Fiona Ebner <f.ebner@proxmox.com>
-Date: Tue, 26 Mar 2024 14:57:51 +0100
-Subject: [PATCH] alloc-track: error out when auto-remove is not set
-
-Since replacing the node now happens in the stream job, where the
-option cannot be read from (it's internal to the driver), it will
-always be treated as on.
-
-qemu-server will always set it, make sure to have other users notice
-the change (should they even exist). The option can be fully dropped
-in the future while adding a version guard in qemu-server.
-
-Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
----
- block/alloc-track.c | 7 +++++--
- 1 file changed, 5 insertions(+), 2 deletions(-)
-
-diff --git a/block/alloc-track.c b/block/alloc-track.c
-index cb9829ae36..30fac992fa 100644
---- a/block/alloc-track.c
-+++ b/block/alloc-track.c
-@@ -34,7 +34,6 @@ typedef struct {
- BdrvDirtyBitmap *bitmap;
- uint64_t granularity;
- DropState drop_state;
-- bool auto_remove;
- } BDRVAllocTrackState;
-
- static QemuOptsList runtime_opts = {
-@@ -86,7 +85,11 @@ static int track_open(BlockDriverState *bs, QDict *options, int flags,
- goto fail;
- }
-
-- s->auto_remove = qemu_opt_get_bool(opts, TRACK_OPT_AUTO_REMOVE, false);
-+ if (!qemu_opt_get_bool(opts, TRACK_OPT_AUTO_REMOVE, false)) {
-+ error_setg(errp, "alloc-track: requires auto-remove option to be set to on");
-+ ret = -EINVAL;
-+ goto fail;
-+ }
-
- /* open the target (write) node, backing will be attached by block layer */
- file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
diff --git a/debian/patches/pve/0050-adapt-machine-version-deprecation-for-Proxmox-VE.patch b/debian/patches/pve/0043-adapt-machine-version-deprecation-for-Proxmox-VE.patch
similarity index 100%
rename from debian/patches/pve/0050-adapt-machine-version-deprecation-for-Proxmox-VE.patch
rename to debian/patches/pve/0043-adapt-machine-version-deprecation-for-Proxmox-VE.patch
diff --git a/debian/patches/pve/0043-alloc-track-avoid-seemingly-superfluous-child-permis.patch b/debian/patches/pve/0043-alloc-track-avoid-seemingly-superfluous-child-permis.patch
deleted file mode 100644
index 5113d34..0000000
--- a/debian/patches/pve/0043-alloc-track-avoid-seemingly-superfluous-child-permis.patch
+++ /dev/null
@@ -1,84 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Fiona Ebner <f.ebner@proxmox.com>
-Date: Wed, 27 Mar 2024 11:15:39 +0100
-Subject: [PATCH] alloc-track: avoid seemingly superfluous child permission
- update
-
-Doesn't seem necessary nowadays (maybe after commit "alloc-track: fix
-deadlock during drop" where the dropping is not rescheduled and delayed
-anymore or some upstream change). Should there really be some issue,
-instead of having a drop state, this could also be just based off the
-fact whether there is still a backing child.
-
-Dumping the cumulative (shared) permissions for the BDS with a debug
-print yields the same values after this patch and with QEMU 8.1,
-namely 3 and 5.
-
-Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
----
- block/alloc-track.c | 26 --------------------------
- 1 file changed, 26 deletions(-)
-
-diff --git a/block/alloc-track.c b/block/alloc-track.c
-index 30fac992fa..718aaabf2a 100644
---- a/block/alloc-track.c
-+++ b/block/alloc-track.c
-@@ -25,15 +25,9 @@
-
- #define TRACK_OPT_AUTO_REMOVE "auto-remove"
-
--typedef enum DropState {
-- DropNone,
-- DropInProgress,
--} DropState;
--
- typedef struct {
- BdrvDirtyBitmap *bitmap;
- uint64_t granularity;
-- DropState drop_state;
- } BDRVAllocTrackState;
-
- static QemuOptsList runtime_opts = {
-@@ -137,8 +131,6 @@ static int track_open(BlockDriverState *bs, QDict *options, int flags,
- goto fail;
- }
-
-- s->drop_state = DropNone;
--
- fail:
- if (ret < 0) {
- bdrv_graph_wrlock();
-@@ -289,18 +281,8 @@ track_child_perm(BlockDriverState *bs, BdrvChild *c, BdrvChildRole role,
- BlockReopenQueue *reopen_queue, uint64_t perm, uint64_t shared,
- uint64_t *nperm, uint64_t *nshared)
- {
-- BDRVAllocTrackState *s = bs->opaque;
--
- *nshared = BLK_PERM_ALL;
-
-- /* in case we're currently dropping ourselves, claim to not use any
-- * permissions at all - which is fine, since from this point on we will
-- * never issue a read or write anymore */
-- if (s->drop_state == DropInProgress) {
-- *nperm = 0;
-- return;
-- }
--
- if (role & BDRV_CHILD_DATA) {
- *nperm = perm & DEFAULT_PERM_PASSTHROUGH;
- } else {
-@@ -326,14 +308,6 @@ track_co_change_backing_file(BlockDriverState *bs, const char *backing_file,
- * kinda fits better, but in the long-term, a special parameter would be
- * nice (or done via qemu-server via upcoming blockdev-replace QMP command).
- */
-- if (backing_file == NULL) {
-- BDRVAllocTrackState *s = bs->opaque;
-- bdrv_drained_begin(bs);
-- s->drop_state = DropInProgress;
-- bdrv_child_refresh_perms(bs, bs->file, &error_abort);
-- bdrv_drained_end(bs);
-- }
--
- return 0;
- }
-
diff --git a/debian/patches/pve/0051-Revert-hpet-avoid-timer-storms-on-periodic-timers.patch b/debian/patches/pve/0044-Revert-hpet-avoid-timer-storms-on-periodic-timers.patch
similarity index 100%
rename from debian/patches/pve/0051-Revert-hpet-avoid-timer-storms-on-periodic-timers.patch
rename to debian/patches/pve/0044-Revert-hpet-avoid-timer-storms-on-periodic-timers.patch
diff --git a/debian/patches/pve/0045-PVE-backup-improve-error-when-copy-before-write-fail.patch b/debian/patches/pve/0045-PVE-backup-improve-error-when-copy-before-write-fail.patch
deleted file mode 100644
index e6cecc4..0000000
--- a/debian/patches/pve/0045-PVE-backup-improve-error-when-copy-before-write-fail.patch
+++ /dev/null
@@ -1,117 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Fiona Ebner <f.ebner@proxmox.com>
-Date: Mon, 29 Apr 2024 14:43:58 +0200
-Subject: [PATCH] PVE backup: improve error when copy-before-write fails for
- fleecing
-
-With fleecing, failure for copy-before-write does not fail the guest
-write, but only sets the snapshot error that is associated to the
-copy-before-write filter, making further requests to the snapshot
-access fail with EACCES, which then also fails the job. But that error
-code is not the root cause of why the backup failed, so bubble up the
-original snapshot error instead.
-
-Reported-by: Friedrich Weber <f.weber@proxmox.com>
-Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
-Tested-by: Friedrich Weber <f.weber@proxmox.com>
----
- block/copy-before-write.c | 18 ++++++++++++------
- block/copy-before-write.h | 1 +
- pve-backup.c | 9 +++++++++
- 3 files changed, 22 insertions(+), 6 deletions(-)
-
-diff --git a/block/copy-before-write.c b/block/copy-before-write.c
-index fd470f5f92..5c23b578ef 100644
---- a/block/copy-before-write.c
-+++ b/block/copy-before-write.c
-@@ -27,6 +27,7 @@
- #include "qobject/qjson.h"
-
- #include "system/block-backend.h"
-+#include "qemu/atomic.h"
- #include "qemu/cutils.h"
- #include "qapi/error.h"
- #include "block/block_int.h"
-@@ -75,7 +76,8 @@ typedef struct BDRVCopyBeforeWriteState {
- * @snapshot_error is normally zero. But on first copy-before-write failure
- * when @on_cbw_error == ON_CBW_ERROR_BREAK_SNAPSHOT, @snapshot_error takes
- * value of this error (<0). After that all in-flight and further
-- * snapshot-API requests will fail with that error.
-+ * snapshot-API requests will fail with that error. To be accessed with
-+ * atomics.
- */
- int snapshot_error;
- } BDRVCopyBeforeWriteState;
-@@ -115,7 +117,7 @@ static coroutine_fn int cbw_do_copy_before_write(BlockDriverState *bs,
- return 0;
- }
-
-- if (s->snapshot_error) {
-+ if (qatomic_read(&s->snapshot_error)) {
- return 0;
- }
-
-@@ -139,9 +141,7 @@ static coroutine_fn int cbw_do_copy_before_write(BlockDriverState *bs,
- WITH_QEMU_LOCK_GUARD(&s->lock) {
- if (ret < 0) {
- assert(s->on_cbw_error == ON_CBW_ERROR_BREAK_SNAPSHOT);
-- if (!s->snapshot_error) {
-- s->snapshot_error = ret;
-- }
-+ qatomic_cmpxchg(&s->snapshot_error, 0, ret);
- } else {
- bdrv_set_dirty_bitmap(s->done_bitmap, off, end - off);
- }
-@@ -215,7 +215,7 @@ cbw_snapshot_read_lock(BlockDriverState *bs, int64_t offset, int64_t bytes,
-
- QEMU_LOCK_GUARD(&s->lock);
-
-- if (s->snapshot_error) {
-+ if (qatomic_read(&s->snapshot_error)) {
- g_free(req);
- return NULL;
- }
-@@ -595,6 +595,12 @@ void bdrv_cbw_drop(BlockDriverState *bs)
- bdrv_unref(bs);
- }
-
-+int bdrv_cbw_snapshot_error(BlockDriverState *bs)
-+{
-+ BDRVCopyBeforeWriteState *s = bs->opaque;
-+ return qatomic_read(&s->snapshot_error);
-+}
-+
- static void cbw_init(void)
- {
- bdrv_register(&bdrv_cbw_filter);
-diff --git a/block/copy-before-write.h b/block/copy-before-write.h
-index 2a5d4ba693..969da3620f 100644
---- a/block/copy-before-write.h
-+++ b/block/copy-before-write.h
-@@ -44,5 +44,6 @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
- BlockCopyState **bcs,
- Error **errp);
- void bdrv_cbw_drop(BlockDriverState *bs);
-+int bdrv_cbw_snapshot_error(BlockDriverState *bs);
-
- #endif /* COPY_BEFORE_WRITE_H */
-diff --git a/pve-backup.c b/pve-backup.c
-index 257cd0b0e1..ffcfaa649d 100644
---- a/pve-backup.c
-+++ b/pve-backup.c
-@@ -374,6 +374,15 @@ static void pvebackup_complete_cb(void *opaque, int ret)
- di->fleecing.snapshot_access = NULL;
- }
- if (di->fleecing.cbw) {
-+ /*
-+ * With fleecing, failure for cbw does not fail the guest write, but only sets the snapshot
-+ * error, making further requests to the snapshot fail with EACCES, which then also fail the
-+ * job. But that code is not the root cause and just confusing, so update it.
-+ */
-+ int snapshot_error = bdrv_cbw_snapshot_error(di->fleecing.cbw);
-+ if (di->completed_ret == -EACCES && snapshot_error) {
-+ di->completed_ret = snapshot_error;
-+ }
- bdrv_cbw_drop(di->fleecing.cbw);
- di->fleecing.cbw = NULL;
- }
diff --git a/debian/patches/pve/0052-Revert-hpet-store-full-64-bit-target-value-of-the-co.patch b/debian/patches/pve/0045-Revert-hpet-store-full-64-bit-target-value-of-the-co.patch
similarity index 100%
rename from debian/patches/pve/0052-Revert-hpet-store-full-64-bit-target-value-of-the-co.patch
rename to debian/patches/pve/0045-Revert-hpet-store-full-64-bit-target-value-of-the-co.patch
diff --git a/debian/patches/pve/0046-PVE-backup-fixup-error-handling-for-fleecing.patch b/debian/patches/pve/0046-PVE-backup-fixup-error-handling-for-fleecing.patch
deleted file mode 100644
index 49a2256..0000000
--- a/debian/patches/pve/0046-PVE-backup-fixup-error-handling-for-fleecing.patch
+++ /dev/null
@@ -1,103 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Fiona Ebner <f.ebner@proxmox.com>
-Date: Thu, 7 Nov 2024 17:51:14 +0100
-Subject: [PATCH] PVE backup: fixup error handling for fleecing
-
-The drained section needs to be terminated before breaking out of the
-loop in the error scenarios. Otherwise, guest IO on the drive would
-become stuck.
-
-If the job is created successfully, then the job completion callback
-will clean up the snapshot access block nodes. In case failure
-happened before the job is created, there was no cleanup for the
-snapshot access block nodes yet. Add it.
-
-Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
----
- pve-backup.c | 38 +++++++++++++++++++++++++-------------
- 1 file changed, 25 insertions(+), 13 deletions(-)
-
-diff --git a/pve-backup.c b/pve-backup.c
-index ffcfaa649d..718a31e4ca 100644
---- a/pve-backup.c
-+++ b/pve-backup.c
-@@ -357,22 +357,23 @@ static void coroutine_fn pvebackup_co_complete_stream(void *opaque)
- qemu_co_mutex_unlock(&backup_state.backup_mutex);
- }
-
--static void pvebackup_complete_cb(void *opaque, int ret)
-+static void cleanup_snapshot_access(PVEBackupDevInfo *di)
- {
-- PVEBackupDevInfo *di = opaque;
-- di->completed_ret = ret;
--
-- /*
-- * Handle block-graph specific cleanup (for fleecing) outside of the coroutine, because the work
-- * won't be done as a coroutine anyways:
-- * - For snapshot_access, allows doing bdrv_unref() directly. Doing it via bdrv_co_unref() would
-- * just spawn a BH calling bdrv_unref().
-- * - For cbw, draining would need to spawn a BH.
-- */
- if (di->fleecing.snapshot_access) {
- bdrv_unref(di->fleecing.snapshot_access);
- di->fleecing.snapshot_access = NULL;
- }
-+ if (di->fleecing.cbw) {
-+ bdrv_cbw_drop(di->fleecing.cbw);
-+ di->fleecing.cbw = NULL;
-+ }
-+}
-+
-+static void pvebackup_complete_cb(void *opaque, int ret)
-+{
-+ PVEBackupDevInfo *di = opaque;
-+ di->completed_ret = ret;
-+
- if (di->fleecing.cbw) {
- /*
- * With fleecing, failure for cbw does not fail the guest write, but only sets the snapshot
-@@ -383,10 +384,17 @@ static void pvebackup_complete_cb(void *opaque, int ret)
- if (di->completed_ret == -EACCES && snapshot_error) {
- di->completed_ret = snapshot_error;
- }
-- bdrv_cbw_drop(di->fleecing.cbw);
-- di->fleecing.cbw = NULL;
- }
-
-+ /*
-+ * Handle block-graph specific cleanup (for fleecing) outside of the coroutine, because the work
-+ * won't be done as a coroutine anyways:
-+ * - For snapshot_access, allows doing bdrv_unref() directly. Doing it via bdrv_co_unref() would
-+ * just spawn a BH calling bdrv_unref().
-+ * - For cbw, draining would need to spawn a BH.
-+ */
-+ cleanup_snapshot_access(di);
-+
- /*
- * Needs to happen outside of coroutine, because it takes the graph write lock.
- */
-@@ -587,6 +595,7 @@ static void create_backup_jobs_bh(void *opaque) {
- if (!di->fleecing.cbw) {
- error_setg(errp, "appending cbw node for fleecing failed: %s",
- local_err ? error_get_pretty(local_err) : "unknown error");
-+ bdrv_drained_end(di->bs);
- break;
- }
-
-@@ -599,6 +608,8 @@ static void create_backup_jobs_bh(void *opaque) {
- if (!di->fleecing.snapshot_access) {
- error_setg(errp, "setting up snapshot access for fleecing failed: %s",
- local_err ? error_get_pretty(local_err) : "unknown error");
-+ cleanup_snapshot_access(di);
-+ bdrv_drained_end(di->bs);
- break;
- }
- source_bs = di->fleecing.snapshot_access;
-@@ -637,6 +648,7 @@ static void create_backup_jobs_bh(void *opaque) {
- }
-
- if (!job || local_err) {
-+ cleanup_snapshot_access(di);
- error_setg(errp, "backup_job_create failed: %s",
- local_err ? error_get_pretty(local_err) : "null");
- break;
diff --git a/debian/patches/pve/0053-Revert-hpet-accept-64-bit-reads-and-writes.patch b/debian/patches/pve/0046-Revert-hpet-accept-64-bit-reads-and-writes.patch
similarity index 100%
rename from debian/patches/pve/0053-Revert-hpet-accept-64-bit-reads-and-writes.patch
rename to debian/patches/pve/0046-Revert-hpet-accept-64-bit-reads-and-writes.patch
diff --git a/debian/patches/pve/0047-PVE-backup-factor-out-setting-up-snapshot-access-for.patch b/debian/patches/pve/0047-PVE-backup-factor-out-setting-up-snapshot-access-for.patch
deleted file mode 100644
index af8e0dd..0000000
--- a/debian/patches/pve/0047-PVE-backup-factor-out-setting-up-snapshot-access-for.patch
+++ /dev/null
@@ -1,135 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Fiona Ebner <f.ebner@proxmox.com>
-Date: Thu, 7 Nov 2024 17:51:15 +0100
-Subject: [PATCH] PVE backup: factor out setting up snapshot access for
- fleecing
-
-Avoids some line bloat in the create_backup_jobs_bh() function and is
-in preparation for setting up the snapshot access independently of
-fleecing, in particular that will be useful for providing access to
-the snapshot via NBD.
-
-Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
----
- pve-backup.c | 95 ++++++++++++++++++++++++++++++++--------------------
- 1 file changed, 58 insertions(+), 37 deletions(-)
-
-diff --git a/pve-backup.c b/pve-backup.c
-index 718a31e4ca..3551bd6c92 100644
---- a/pve-backup.c
-+++ b/pve-backup.c
-@@ -525,6 +525,62 @@ static int coroutine_fn pvebackup_co_add_config(
- goto out;
- }
-
-+/*
-+ * Setup a snapshot-access block node for a device with associated fleecing image.
-+ */
-+static int setup_snapshot_access(PVEBackupDevInfo *di, Error **errp)
-+{
-+ Error *local_err = NULL;
-+
-+ if (!di->fleecing.bs) {
-+ error_setg(errp, "no associated fleecing image");
-+ return -1;
-+ }
-+
-+ QDict *cbw_opts = qdict_new();
-+ qdict_put_str(cbw_opts, "driver", "copy-before-write");
-+ qdict_put_str(cbw_opts, "file", bdrv_get_node_name(di->bs));
-+ qdict_put_str(cbw_opts, "target", bdrv_get_node_name(di->fleecing.bs));
-+
-+ if (di->bitmap) {
-+ /*
-+ * Only guest writes to parts relevant for the backup need to be intercepted with
-+ * old data being copied to the fleecing image.
-+ */
-+ qdict_put_str(cbw_opts, "bitmap.node", bdrv_get_node_name(di->bs));
-+ qdict_put_str(cbw_opts, "bitmap.name", bdrv_dirty_bitmap_name(di->bitmap));
-+ }
-+ /*
-+ * Fleecing storage is supposed to be fast and it's better to break backup than guest
-+ * writes. Certain guest drivers like VirtIO-win have 60 seconds timeout by default, so
-+ * abort a bit before that.
-+ */
-+ qdict_put_str(cbw_opts, "on-cbw-error", "break-snapshot");
-+ qdict_put_int(cbw_opts, "cbw-timeout", 45);
-+
-+ di->fleecing.cbw = bdrv_insert_node(di->bs, cbw_opts, BDRV_O_RDWR, &local_err);
-+
-+ if (!di->fleecing.cbw) {
-+ error_setg(errp, "appending cbw node for fleecing failed: %s",
-+ local_err ? error_get_pretty(local_err) : "unknown error");
-+ return -1;
-+ }
-+
-+ QDict *snapshot_access_opts = qdict_new();
-+ qdict_put_str(snapshot_access_opts, "driver", "snapshot-access");
-+ qdict_put_str(snapshot_access_opts, "file", bdrv_get_node_name(di->fleecing.cbw));
-+
-+ di->fleecing.snapshot_access =
-+ bdrv_open(NULL, NULL, snapshot_access_opts, BDRV_O_RDWR | BDRV_O_UNMAP, &local_err);
-+ if (!di->fleecing.snapshot_access) {
-+ error_setg(errp, "setting up snapshot access for fleecing failed: %s",
-+ local_err ? error_get_pretty(local_err) : "unknown error");
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
- /*
- * backup_job_create can *not* be run from a coroutine, so this can't either.
- * The caller is responsible that backup_mutex is held nonetheless.
-@@ -569,49 +625,14 @@ static void create_backup_jobs_bh(void *opaque) {
- const char *job_id = bdrv_get_device_name(di->bs);
- bdrv_graph_co_rdunlock();
- if (di->fleecing.bs) {
-- QDict *cbw_opts = qdict_new();
-- qdict_put_str(cbw_opts, "driver", "copy-before-write");
-- qdict_put_str(cbw_opts, "file", bdrv_get_node_name(di->bs));
-- qdict_put_str(cbw_opts, "target", bdrv_get_node_name(di->fleecing.bs));
--
-- if (di->bitmap) {
-- /*
-- * Only guest writes to parts relevant for the backup need to be intercepted with
-- * old data being copied to the fleecing image.
-- */
-- qdict_put_str(cbw_opts, "bitmap.node", bdrv_get_node_name(di->bs));
-- qdict_put_str(cbw_opts, "bitmap.name", bdrv_dirty_bitmap_name(di->bitmap));
-- }
-- /*
-- * Fleecing storage is supposed to be fast and it's better to break backup than guest
-- * writes. Certain guest drivers like VirtIO-win have 60 seconds timeout by default, so
-- * abort a bit before that.
-- */
-- qdict_put_str(cbw_opts, "on-cbw-error", "break-snapshot");
-- qdict_put_int(cbw_opts, "cbw-timeout", 45);
--
-- di->fleecing.cbw = bdrv_insert_node(di->bs, cbw_opts, BDRV_O_RDWR, &local_err);
--
-- if (!di->fleecing.cbw) {
-- error_setg(errp, "appending cbw node for fleecing failed: %s",
-- local_err ? error_get_pretty(local_err) : "unknown error");
-- bdrv_drained_end(di->bs);
-- break;
-- }
--
-- QDict *snapshot_access_opts = qdict_new();
-- qdict_put_str(snapshot_access_opts, "driver", "snapshot-access");
-- qdict_put_str(snapshot_access_opts, "file", bdrv_get_node_name(di->fleecing.cbw));
--
-- di->fleecing.snapshot_access =
-- bdrv_open(NULL, NULL, snapshot_access_opts, BDRV_O_RDWR | BDRV_O_UNMAP, &local_err);
-- if (!di->fleecing.snapshot_access) {
-+ if (setup_snapshot_access(di, &local_err) < 0) {
- error_setg(errp, "setting up snapshot access for fleecing failed: %s",
- local_err ? error_get_pretty(local_err) : "unknown error");
- cleanup_snapshot_access(di);
- bdrv_drained_end(di->bs);
- break;
- }
-+
- source_bs = di->fleecing.snapshot_access;
- discard_source = true;
-
diff --git a/debian/patches/pve/0054-Revert-hpet-place-read-only-bits-directly-in-new_val.patch b/debian/patches/pve/0047-Revert-hpet-place-read-only-bits-directly-in-new_val.patch
similarity index 100%
rename from debian/patches/pve/0054-Revert-hpet-place-read-only-bits-directly-in-new_val.patch
rename to debian/patches/pve/0047-Revert-hpet-place-read-only-bits-directly-in-new_val.patch
diff --git a/debian/patches/pve/0048-PVE-backup-save-device-name-in-device-info-structure.patch b/debian/patches/pve/0048-PVE-backup-save-device-name-in-device-info-structure.patch
deleted file mode 100644
index 3523164..0000000
--- a/debian/patches/pve/0048-PVE-backup-save-device-name-in-device-info-structure.patch
+++ /dev/null
@@ -1,135 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Fiona Ebner <f.ebner@proxmox.com>
-Date: Thu, 7 Nov 2024 17:51:16 +0100
-Subject: [PATCH] PVE backup: save device name in device info structure
-
-The device name needs to be queried while holding the graph read lock
-and since it doesn't change during the whole operation, just get it
-once during setup and avoid the need to query it again in different
-places.
-
-Also in preparation to use it more often in error messages and for the
-upcoming external backup access API.
-
-Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
----
- pve-backup.c | 29 +++++++++++++++--------------
- 1 file changed, 15 insertions(+), 14 deletions(-)
-
-diff --git a/pve-backup.c b/pve-backup.c
-index 3551bd6c92..25f65952a0 100644
---- a/pve-backup.c
-+++ b/pve-backup.c
-@@ -94,6 +94,7 @@ typedef struct PVEBackupDevInfo {
- size_t size;
- uint64_t block_size;
- uint8_t dev_id;
-+ char* device_name;
- int completed_ret; // INT_MAX if not completed
- BdrvDirtyBitmap *bitmap;
- BlockDriverState *target;
-@@ -327,6 +328,8 @@ static void coroutine_fn pvebackup_co_complete_stream(void *opaque)
- }
-
- di->bs = NULL;
-+ g_free(di->device_name);
-+ di->device_name = NULL;
-
- assert(di->target == NULL);
-
-@@ -621,9 +624,6 @@ static void create_backup_jobs_bh(void *opaque) {
-
- BlockDriverState *source_bs = di->bs;
- bool discard_source = false;
-- bdrv_graph_co_rdlock();
-- const char *job_id = bdrv_get_device_name(di->bs);
-- bdrv_graph_co_rdunlock();
- if (di->fleecing.bs) {
- if (setup_snapshot_access(di, &local_err) < 0) {
- error_setg(errp, "setting up snapshot access for fleecing failed: %s",
-@@ -654,7 +654,7 @@ static void create_backup_jobs_bh(void *opaque) {
- }
-
- BlockJob *job = backup_job_create(
-- job_id, source_bs, di->target, backup_state.speed, sync_mode, di->bitmap,
-+ di->device_name, source_bs, di->target, backup_state.speed, sync_mode, di->bitmap,
- bitmap_mode, false, discard_source, NULL, &perf, BLOCKDEV_ON_ERROR_REPORT,
- BLOCKDEV_ON_ERROR_REPORT, JOB_DEFAULT, pvebackup_complete_cb, di, backup_state.txn,
- &local_err);
-@@ -751,6 +751,7 @@ static GList coroutine_fn GRAPH_RDLOCK *get_device_info(
- }
- PVEBackupDevInfo *di = g_new0(PVEBackupDevInfo, 1);
- di->bs = bs;
-+ di->device_name = g_strdup(bdrv_get_device_name(bs));
-
- if (fleecing && device_uses_fleecing(*d)) {
- g_autofree gchar *fleecing_devid = g_strconcat(*d, "-fleecing", NULL);
-@@ -789,6 +790,7 @@ static GList coroutine_fn GRAPH_RDLOCK *get_device_info(
-
- PVEBackupDevInfo *di = g_new0(PVEBackupDevInfo, 1);
- di->bs = bs;
-+ di->device_name = g_strdup(bdrv_get_device_name(bs));
- di_list = g_list_append(di_list, di);
- }
- }
-@@ -956,9 +958,6 @@ UuidInfo coroutine_fn *qmp_backup(
-
- di->block_size = dump_cb_block_size;
-
-- bdrv_graph_co_rdlock();
-- const char *devname = bdrv_get_device_name(di->bs);
-- bdrv_graph_co_rdunlock();
- PBSBitmapAction action = PBS_BITMAP_ACTION_NOT_USED;
- size_t dirty = di->size;
-
-@@ -973,7 +972,8 @@ UuidInfo coroutine_fn *qmp_backup(
- }
- action = PBS_BITMAP_ACTION_NEW;
- } else {
-- expect_only_dirty = proxmox_backup_check_incremental(pbs, devname, di->size) != 0;
-+ expect_only_dirty =
-+ proxmox_backup_check_incremental(pbs, di->device_name, di->size) != 0;
- }
-
- if (expect_only_dirty) {
-@@ -997,7 +997,8 @@ UuidInfo coroutine_fn *qmp_backup(
- }
- }
-
-- int dev_id = proxmox_backup_co_register_image(pbs, devname, di->size, expect_only_dirty, errp);
-+ int dev_id = proxmox_backup_co_register_image(pbs, di->device_name, di->size,
-+ expect_only_dirty, errp);
- if (dev_id < 0) {
- goto err_mutex;
- }
-@@ -1009,7 +1010,7 @@ UuidInfo coroutine_fn *qmp_backup(
- di->dev_id = dev_id;
-
- PBSBitmapInfo *info = g_malloc(sizeof(*info));
-- info->drive = g_strdup(devname);
-+ info->drive = g_strdup(di->device_name);
- info->action = action;
- info->size = di->size;
- info->dirty = dirty;
-@@ -1032,10 +1033,7 @@ UuidInfo coroutine_fn *qmp_backup(
- goto err_mutex;
- }
-
-- bdrv_graph_co_rdlock();
-- const char *devname = bdrv_get_device_name(di->bs);
-- bdrv_graph_co_rdunlock();
-- di->dev_id = vma_writer_register_stream(vmaw, devname, di->size);
-+ di->dev_id = vma_writer_register_stream(vmaw, di->device_name, di->size);
- if (di->dev_id <= 0) {
- error_set(errp, ERROR_CLASS_GENERIC_ERROR,
- "register_stream failed");
-@@ -1146,6 +1144,9 @@ err:
- bdrv_co_unref(di->target);
- }
-
-+ g_free(di->device_name);
-+ di->device_name = NULL;
-+
- g_free(di);
- }
- g_list_free(di_list);
diff --git a/debian/patches/pve/0055-Revert-hpet-remove-unnecessary-variable-index.patch b/debian/patches/pve/0048-Revert-hpet-remove-unnecessary-variable-index.patch
similarity index 100%
rename from debian/patches/pve/0055-Revert-hpet-remove-unnecessary-variable-index.patch
rename to debian/patches/pve/0048-Revert-hpet-remove-unnecessary-variable-index.patch
diff --git a/debian/patches/pve/0049-PVE-backup-include-device-name-in-error-when-setting.patch b/debian/patches/pve/0049-PVE-backup-include-device-name-in-error-when-setting.patch
deleted file mode 100644
index 477beca..0000000
--- a/debian/patches/pve/0049-PVE-backup-include-device-name-in-error-when-setting.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Fiona Ebner <f.ebner@proxmox.com>
-Date: Thu, 7 Nov 2024 17:51:17 +0100
-Subject: [PATCH] PVE backup: include device name in error when setting up
- snapshot access fails
-
-Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
----
- pve-backup.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/pve-backup.c b/pve-backup.c
-index 25f65952a0..b411d58a9a 100644
---- a/pve-backup.c
-+++ b/pve-backup.c
-@@ -626,7 +626,8 @@ static void create_backup_jobs_bh(void *opaque) {
- bool discard_source = false;
- if (di->fleecing.bs) {
- if (setup_snapshot_access(di, &local_err) < 0) {
-- error_setg(errp, "setting up snapshot access for fleecing failed: %s",
-+ error_setg(errp, "%s - setting up snapshot access for fleecing failed: %s",
-+ di->device_name,
- local_err ? error_get_pretty(local_err) : "unknown error");
- cleanup_snapshot_access(di);
- bdrv_drained_end(di->bs);
diff --git a/debian/patches/pve/0056-Revert-hpet-ignore-high-bits-of-comparator-in-32-bit.patch b/debian/patches/pve/0049-Revert-hpet-ignore-high-bits-of-comparator-in-32-bit.patch
similarity index 100%
rename from debian/patches/pve/0056-Revert-hpet-ignore-high-bits-of-comparator-in-32-bit.patch
rename to debian/patches/pve/0049-Revert-hpet-ignore-high-bits-of-comparator-in-32-bit.patch
diff --git a/debian/patches/pve/0057-Revert-hpet-fix-and-cleanup-persistence-of-interrupt.patch b/debian/patches/pve/0050-Revert-hpet-fix-and-cleanup-persistence-of-interrupt.patch
similarity index 100%
rename from debian/patches/pve/0057-Revert-hpet-fix-and-cleanup-persistence-of-interrupt.patch
rename to debian/patches/pve/0050-Revert-hpet-fix-and-cleanup-persistence-of-interrupt.patch
diff --git a/debian/patches/pve/0064-PVE-backup-factor-out-helper-to-clear-backup-state-s.patch b/debian/patches/pve/0051-PVE-backup-factor-out-helper-to-clear-backup-state-s.patch
similarity index 100%
rename from debian/patches/pve/0064-PVE-backup-factor-out-helper-to-clear-backup-state-s.patch
rename to debian/patches/pve/0051-PVE-backup-factor-out-helper-to-clear-backup-state-s.patch
diff --git a/debian/patches/pve/0065-PVE-backup-factor-out-helper-to-initialize-backup-st.patch b/debian/patches/pve/0052-PVE-backup-factor-out-helper-to-initialize-backup-st.patch
similarity index 100%
rename from debian/patches/pve/0065-PVE-backup-factor-out-helper-to-initialize-backup-st.patch
rename to debian/patches/pve/0052-PVE-backup-factor-out-helper-to-initialize-backup-st.patch
diff --git a/debian/patches/pve/0066-PVE-backup-add-target-ID-in-backup-state.patch b/debian/patches/pve/0053-PVE-backup-add-target-ID-in-backup-state.patch
similarity index 100%
rename from debian/patches/pve/0066-PVE-backup-add-target-ID-in-backup-state.patch
rename to debian/patches/pve/0053-PVE-backup-add-target-ID-in-backup-state.patch
diff --git a/debian/patches/pve/0067-PVE-backup-get-device-info-allow-caller-to-specify-f.patch b/debian/patches/pve/0054-PVE-backup-get-device-info-allow-caller-to-specify-f.patch
similarity index 100%
rename from debian/patches/pve/0067-PVE-backup-get-device-info-allow-caller-to-specify-f.patch
rename to debian/patches/pve/0054-PVE-backup-get-device-info-allow-caller-to-specify-f.patch
diff --git a/debian/patches/pve/0055-PVE-backup-implement-backup-access-setup-and-teardow.patch b/debian/patches/pve/0055-PVE-backup-implement-backup-access-setup-and-teardow.patch
new file mode 100644
index 0000000..c4273a1
--- /dev/null
+++ b/debian/patches/pve/0055-PVE-backup-implement-backup-access-setup-and-teardow.patch
@@ -0,0 +1,898 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Fiona Ebner <f.ebner@proxmox.com>
+Date: Thu, 3 Apr 2025 14:30:46 +0200
+Subject: [PATCH] PVE backup: implement backup access setup and teardown API
+ for external providers
+
+For external backup providers, the state of the VM's disk images at
+the time the backup is started is preserved via a snapshot-access
+block node. Old data is moved to the fleecing image when new guest
+writes come in. The snapshot-access block node, as well as the
+associated bitmap in case of incremental backup, will be exported via
+NBD to the external provider. The NBD export will be done by the
+management layer, the missing functionality is setting up and tearing
+down the snapshot-access block nodes, which this patch adds.
+
+It is necessary to also set up fleecing for EFI and TPM disks, so that
+old data can be moved out of the way when a new guest write comes in.
+
+There can only be one regular backup or one active backup access at
+a time, because both require replacing the original block node of the
+drive. Thus the backup state is re-used, and checks are added to
+prohibit regular backup while snapshot access is active and vice
+versa.
+
+The block nodes added by the backup-access-setup QMP call are not
+tracked anywhere else (there is no job they are associated to like for
+regular backup). This requires adding a callback for teardown when
+QEMU exits, i.e. in qemu_cleanup(). Otherwise, there will be an
+assertion failure that the block graph is not empty when QEMU exits
+before the backup-access-teardown QMP command is called.
+
+The code for the qmp_backup_access_setup() was based on the existing
+qmp_backup() routine.
+
+The return value for the setup QMP command contains information about
+the snapshot-access block nodes that can be used by the management
+layer to set up the NBD exports.
+
+There can be one dirty bitmap for each backup target ID for each
+device (which are tracked in the backup_access_bitmaps hash table).
+The QMP user can specify the ID of the bitmap it likes to use. This ID
+is then compared to the current one for the given target and device.
+If they match, the bitmap is re-used (should it still exist on the
+drive, otherwise re-created). If there is a mismatch, the old bitmap
+is removed and a new one is created.
+
+The return value of the QMP command includes information about what
+bitmap action was taken. Similar to what the query-backup QMP command
+returns for regular backup. It also includes the bitmap name and
+associated block node, so the management layer can then set up an NBD
+export with the bitmap.
+
+While the backup access is active, a background bitmap is also
+required. This is necessary to implement bitmap handling according to
+the original reference [0]. In particular:
+
+- in the error case, new writes since the backup access was set up are
+ in the background bitmap. Because of failure, the previously tracked
+ writes from the backup access bitmap are still required too. Thus,
+ the bitmap is merged with the background bitmap to get all new
+ writes since the last backup.
+
+- in the success case, continue tracking for the next incremental
+ backup in the backup access bitmap. New writes since the backup
+ access was set up are in the background bitmap. Because the backup
+ was successfully, clear the backup access bitmap and merge back the
+ background bitmap to get only the new writes.
+
+Since QEMU cannot know if the backup was successful or not (except if
+failure already happens during the setup QMP command), the management
+layer needs to tell it via the teardown QMP command.
+
+The bitmap action is also recorded in the device info now.
+
+The backup-access api keeps track of what bitmap names got used for
+which devices and thus knows when a bitmap went missing. Propagate
+this information to the QMP user with a new 'missing-recreated'
+variant for the taken bitmap action.
+
+[0]: https://lore.kernel.org/qemu-devel/b68833dd-8864-4d72-7c61-c134a9835036@ya.ru/
+
+Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
+Reviewed-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
+---
+ pve-backup.c | 519 +++++++++++++++++++++++++++++++++++++++----
+ pve-backup.h | 16 ++
+ qapi/block-core.json | 99 ++++++++-
+ system/runstate.c | 6 +
+ 4 files changed, 596 insertions(+), 44 deletions(-)
+ create mode 100644 pve-backup.h
+
+diff --git a/pve-backup.c b/pve-backup.c
+index bd81621d51..0450303017 100644
+--- a/pve-backup.c
++++ b/pve-backup.c
+@@ -1,4 +1,5 @@
+ #include "proxmox-backup-client.h"
++#include "pve-backup.h"
+ #include "vma.h"
+
+ #include "qemu/osdep.h"
+@@ -14,6 +15,7 @@
+ #include "qobject/qdict.h"
+ #include "qapi/qmp/qerror.h"
+ #include "qemu/cutils.h"
++#include "qemu/error-report.h"
+
+ #if defined(CONFIG_MALLOC_TRIM)
+ #include <malloc.h>
+@@ -40,6 +42,7 @@
+ */
+
+ const char *PBS_BITMAP_NAME = "pbs-incremental-dirty-bitmap";
++const char *BACKGROUND_BITMAP_NAME = "backup-access-background-bitmap";
+
+ static struct PVEBackupState {
+ struct {
+@@ -98,8 +101,11 @@ typedef struct PVEBackupDevInfo {
+ char* device_name;
+ int completed_ret; // INT_MAX if not completed
+ BdrvDirtyBitmap *bitmap;
++ BdrvDirtyBitmap *background_bitmap; // used for external backup access
++ PBSBitmapAction bitmap_action;
+ BlockDriverState *target;
+ BlockJob *job;
++ BackupAccessSetupBitmapMode requested_bitmap_mode;
+ } PVEBackupDevInfo;
+
+ static void pvebackup_propagate_error(Error *err)
+@@ -361,6 +367,67 @@ static void coroutine_fn pvebackup_co_complete_stream(void *opaque)
+ qemu_co_mutex_unlock(&backup_state.backup_mutex);
+ }
+
++/*
++ * New writes since the backup access was set up are in the background bitmap. Because of failure,
++ * the previously tracked writes in di->bitmap are still required too. Thus, merge with the
++ * background bitmap to get all new writes since the last backup.
++ */
++static void handle_backup_access_bitmaps_in_error_case(PVEBackupDevInfo *di)
++{
++ Error *local_err = NULL;
++
++ if (di->bs && di->background_bitmap) {
++ bdrv_drained_begin(di->bs);
++ if (di->bitmap) {
++ bdrv_enable_dirty_bitmap(di->bitmap);
++ if (!bdrv_merge_dirty_bitmap(di->bitmap, di->background_bitmap, NULL, &local_err)) {
++ warn_report("backup access: %s - could not merge bitmaps in error path - %s",
++ di->device_name,
++ local_err ? error_get_pretty(local_err) : "unknown error");
++ /*
++ * Could not merge, drop original bitmap too.
++ */
++ bdrv_release_dirty_bitmap(di->bitmap);
++ }
++ } else {
++ warn_report("backup access: %s - expected bitmap not present", di->device_name);
++ }
++ bdrv_release_dirty_bitmap(di->background_bitmap);
++ bdrv_drained_end(di->bs);
++ }
++}
++
++/*
++ * Continue tracking for next incremental backup in di->bitmap. New writes since the backup access
++ * was set up are in the background bitmap. Because the backup was successful, clear di->bitmap and
++ * merge back the background bitmap to get only the new writes.
++ */
++static void handle_backup_access_bitmaps_after_success(PVEBackupDevInfo *di)
++{
++ Error *local_err = NULL;
++
++ if (di->bs && di->background_bitmap) {
++ bdrv_drained_begin(di->bs);
++ if (di->bitmap) {
++ bdrv_enable_dirty_bitmap(di->bitmap);
++ bdrv_clear_dirty_bitmap(di->bitmap, NULL);
++ if (!bdrv_merge_dirty_bitmap(di->bitmap, di->background_bitmap, NULL, &local_err)) {
++ warn_report("backup access: %s - could not merge bitmaps after backup - %s",
++ di->device_name,
++ local_err ? error_get_pretty(local_err) : "unknown error");
++ /*
++ * Could not merge, drop original bitmap too.
++ */
++ bdrv_release_dirty_bitmap(di->bitmap);
++ }
++ } else {
++ warn_report("backup access: %s - expected bitmap not present", di->device_name);
++ }
++ bdrv_release_dirty_bitmap(di->background_bitmap);
++ bdrv_drained_end(di->bs);
++ }
++}
++
+ static void cleanup_snapshot_access(PVEBackupDevInfo *di)
+ {
+ if (di->fleecing.snapshot_access) {
+@@ -588,6 +655,51 @@ static int setup_snapshot_access(PVEBackupDevInfo *di, Error **errp)
+ return 0;
+ }
+
++static void setup_all_snapshot_access_bh(void *opaque)
++{
++ assert(!qemu_in_coroutine());
++
++ CoCtxData *data = (CoCtxData*)opaque;
++ Error **errp = (Error**)data->data;
++
++ Error *local_err = NULL;
++
++ GList *l = backup_state.di_list;
++ while (l) {
++ PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
++ l = g_list_next(l);
++
++ bdrv_drained_begin(di->bs);
++
++ if (di->bitmap) {
++ BdrvDirtyBitmap *background_bitmap =
++ bdrv_create_dirty_bitmap(di->bs, PROXMOX_BACKUP_DEFAULT_CHUNK_SIZE,
++ BACKGROUND_BITMAP_NAME, &local_err);
++ if (!background_bitmap) {
++ error_setg(errp, "%s - creating background bitmap for backup access failed: %s",
++ di->device_name,
++ local_err ? error_get_pretty(local_err) : "unknown error");
++ bdrv_drained_end(di->bs);
++ break;
++ }
++ di->background_bitmap = background_bitmap;
++ bdrv_disable_dirty_bitmap(di->bitmap);
++ }
++
++ if (setup_snapshot_access(di, &local_err) < 0) {
++ bdrv_drained_end(di->bs);
++ error_setg(errp, "%s - setting up snapshot access failed: %s", di->device_name,
++ local_err ? error_get_pretty(local_err) : "unknown error");
++ break;
++ }
++
++ bdrv_drained_end(di->bs);
++ }
++
++ /* return */
++ aio_co_enter(data->ctx, data->co);
++}
++
+ /*
+ * backup_job_create can *not* be run from a coroutine, so this can't either.
+ * The caller is responsible that backup_mutex is held nonetheless.
+@@ -724,6 +836,62 @@ static bool fleecing_no_efi_tpm(const char *device_id)
+ return strncmp(device_id, "drive-efidisk", 13) && strncmp(device_id, "drive-tpmstate", 14);
+ }
+
++static bool fleecing_all(const char *device_id)
++{
++ return true;
++}
++
++static PVEBackupDevInfo coroutine_fn GRAPH_RDLOCK *get_single_device_info(
++ const char *device,
++ bool (*device_uses_fleecing)(const char*),
++ Error **errp)
++{
++ BlockBackend *blk = blk_by_name(device);
++ if (!blk) {
++ error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
++ "Device '%s' not found", device);
++ return NULL;
++ }
++ BlockDriverState *bs = blk_bs(blk);
++ if (!bdrv_co_is_inserted(bs)) {
++ error_setg(errp, "Device '%s' has no medium", device);
++ return NULL;
++ }
++ PVEBackupDevInfo *di = g_new0(PVEBackupDevInfo, 1);
++ di->bs = bs;
++ di->device_name = g_strdup(bdrv_get_device_name(bs));
++
++ if (device_uses_fleecing && device_uses_fleecing(device)) {
++ g_autofree gchar *fleecing_devid = g_strconcat(device, "-fleecing", NULL);
++ BlockBackend *fleecing_blk = blk_by_name(fleecing_devid);
++ if (!fleecing_blk) {
++ error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
++ "Device '%s' not found", fleecing_devid);
++ goto fail;
++ }
++ BlockDriverState *fleecing_bs = blk_bs(fleecing_blk);
++ if (!bdrv_co_is_inserted(fleecing_bs)) {
++ error_setg(errp, "Device '%s' has no medium", fleecing_devid);
++ goto fail;
++ }
++ /*
++ * Fleecing image needs to be the same size to act as a cbw target.
++ */
++ if (bs->total_sectors != fleecing_bs->total_sectors) {
++ error_setg(errp, "Size mismatch for '%s' - sector count %ld != %ld",
++ fleecing_devid, fleecing_bs->total_sectors, bs->total_sectors);
++ goto fail;
++ }
++ di->fleecing.bs = fleecing_bs;
++ }
++
++ return di;
++fail:
++ g_free(di->device_name);
++ g_free(di);
++ return NULL;
++}
++
+ /*
+ * Returns a list of device infos, which needs to be freed by the caller. In
+ * case of an error, errp will be set, but the returned value might still be a
+@@ -742,45 +910,10 @@ static GList coroutine_fn GRAPH_RDLOCK *get_device_info(
+
+ gchar **d = devs;
+ while (d && *d) {
+- BlockBackend *blk = blk_by_name(*d);
+- if (!blk) {
+- error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
+- "Device '%s' not found", *d);
+- goto err;
+- }
+- BlockDriverState *bs = blk_bs(blk);
+- if (!bdrv_co_is_inserted(bs)) {
+- error_setg(errp, "Device '%s' has no medium", *d);
++ PVEBackupDevInfo *di = get_single_device_info(*d, device_uses_fleecing, errp);
++ if (!di) {
+ goto err;
+ }
+- PVEBackupDevInfo *di = g_new0(PVEBackupDevInfo, 1);
+- di->bs = bs;
+- di->device_name = g_strdup(bdrv_get_device_name(bs));
+-
+- if (device_uses_fleecing && device_uses_fleecing(*d)) {
+- g_autofree gchar *fleecing_devid = g_strconcat(*d, "-fleecing", NULL);
+- BlockBackend *fleecing_blk = blk_by_name(fleecing_devid);
+- if (!fleecing_blk) {
+- error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
+- "Device '%s' not found", fleecing_devid);
+- goto err;
+- }
+- BlockDriverState *fleecing_bs = blk_bs(fleecing_blk);
+- if (!bdrv_co_is_inserted(fleecing_bs)) {
+- error_setg(errp, "Device '%s' has no medium", fleecing_devid);
+- goto err;
+- }
+- /*
+- * Fleecing image needs to be the same size to act as a cbw target.
+- */
+- if (bs->total_sectors != fleecing_bs->total_sectors) {
+- error_setg(errp, "Size mismatch for '%s' - sector count %ld != %ld",
+- fleecing_devid, fleecing_bs->total_sectors, bs->total_sectors);
+- goto err;
+- }
+- di->fleecing.bs = fleecing_bs;
+- }
+-
+ di_list = g_list_append(di_list, di);
+ d++;
+ }
+@@ -839,8 +972,9 @@ static void clear_backup_state_bitmap_list(void) {
+ */
+ static void initialize_backup_state_stat(
+ const char *backup_file,
+- uuid_t uuid,
+- size_t total)
++ uuid_t *uuid,
++ size_t total,
++ bool starting)
+ {
+ if (backup_state.stat.error) {
+ error_free(backup_state.stat.error);
+@@ -855,15 +989,19 @@ static void initialize_backup_state_stat(
+ }
+ backup_state.stat.backup_file = g_strdup(backup_file);
+
+- uuid_copy(backup_state.stat.uuid, uuid);
+- uuid_unparse_lower(uuid, backup_state.stat.uuid_str);
++ if (uuid) {
++ uuid_copy(backup_state.stat.uuid, *uuid);
++ uuid_unparse_lower(*uuid, backup_state.stat.uuid_str);
++ } else {
++ backup_state.stat.uuid_str[0] = '\0';
++ }
+
+ backup_state.stat.total = total;
+ backup_state.stat.dirty = total - backup_state.stat.reused;
+ backup_state.stat.transferred = 0;
+ backup_state.stat.zero_bytes = 0;
+ backup_state.stat.finishing = false;
+- backup_state.stat.starting = true;
++ backup_state.stat.starting = starting;
+ }
+
+ /*
+@@ -876,6 +1014,299 @@ static void backup_state_set_target_id(const char *target_id) {
+ backup_state.target_id = g_strdup(target_id);
+ }
+
++BackupAccessInfoList *coroutine_fn qmp_backup_access_setup(
++ const char *target_id,
++ BackupAccessSourceDeviceList *devices,
++ Error **errp)
++{
++ assert(qemu_in_coroutine());
++
++ qemu_co_mutex_lock(&backup_state.backup_mutex);
++
++ Error *local_err = NULL;
++ GList *di_list = NULL;
++ GList *l;
++
++ if (backup_state.di_list) {
++ error_set(errp, ERROR_CLASS_GENERIC_ERROR,
++ "previous backup for target '%s' not finished", backup_state.target_id);
++ qemu_co_mutex_unlock(&backup_state.backup_mutex);
++ return NULL;
++ }
++
++ bdrv_graph_co_rdlock();
++ for (BackupAccessSourceDeviceList *it = devices; it; it = it->next) {
++ PVEBackupDevInfo *di = get_single_device_info(it->value->device, fleecing_all, &local_err);
++ if (!di) {
++ bdrv_graph_co_rdunlock();
++ error_propagate(errp, local_err);
++ goto err;
++ }
++ di->requested_bitmap_mode = it->value->bitmap_mode;
++ di_list = g_list_append(di_list, di);
++ }
++ bdrv_graph_co_rdunlock();
++ assert(di_list);
++
++ size_t total = 0;
++
++ l = di_list;
++ while (l) {
++ PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
++ l = g_list_next(l);
++
++ ssize_t size = bdrv_getlength(di->bs);
++ if (size < 0) {
++ error_setg_errno(errp, -size, "bdrv_getlength failed");
++ goto err;
++ }
++ di->size = size;
++ total += size;
++
++ di->completed_ret = INT_MAX;
++ }
++
++ qemu_mutex_lock(&backup_state.stat.lock);
++ backup_state.stat.reused = 0;
++
++ /* clear previous backup's bitmap_list */
++ clear_backup_state_bitmap_list();
++
++ const char *bitmap_name = target_id;
++
++ /* create bitmaps if requested */
++ l = di_list;
++ while (l) {
++ PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
++ l = g_list_next(l);
++
++ di->block_size = PROXMOX_BACKUP_DEFAULT_CHUNK_SIZE;
++
++ PBSBitmapAction action = PBS_BITMAP_ACTION_NOT_USED;
++ size_t dirty = di->size;
++
++ if (di->requested_bitmap_mode == BACKUP_ACCESS_SETUP_BITMAP_MODE_NONE ||
++ di->requested_bitmap_mode == BACKUP_ACCESS_SETUP_BITMAP_MODE_NEW) {
++ BdrvDirtyBitmap *old_bitmap = bdrv_find_dirty_bitmap(di->bs, bitmap_name);
++ if (old_bitmap) {
++ bdrv_release_dirty_bitmap(old_bitmap);
++ action = PBS_BITMAP_ACTION_NOT_USED_REMOVED; // set below for new
++ }
++ }
++
++ BdrvDirtyBitmap *bitmap = NULL;
++ if (di->requested_bitmap_mode == BACKUP_ACCESS_SETUP_BITMAP_MODE_NEW ||
++ di->requested_bitmap_mode == BACKUP_ACCESS_SETUP_BITMAP_MODE_USE) {
++ bitmap = bdrv_find_dirty_bitmap(di->bs, bitmap_name);
++ if (!bitmap) {
++ bitmap = bdrv_create_dirty_bitmap(di->bs, PROXMOX_BACKUP_DEFAULT_CHUNK_SIZE,
++ bitmap_name, errp);
++ if (!bitmap) {
++ qemu_mutex_unlock(&backup_state.stat.lock);
++ goto err;
++ }
++ bdrv_set_dirty_bitmap(bitmap, 0, di->size);
++ if (di->requested_bitmap_mode == BACKUP_ACCESS_SETUP_BITMAP_MODE_USE) {
++ action = PBS_BITMAP_ACTION_MISSING_RECREATED;
++ } else {
++ action = PBS_BITMAP_ACTION_NEW;
++ }
++ } else {
++ if (di->requested_bitmap_mode == BACKUP_ACCESS_SETUP_BITMAP_MODE_NEW) {
++ qemu_mutex_unlock(&backup_state.stat.lock);
++ error_setg(errp, "internal error - removed old bitmap still present");
++ goto err;
++ }
++ /* track clean chunks as reused */
++ dirty = MIN(bdrv_get_dirty_count(bitmap), di->size);
++ backup_state.stat.reused += di->size - dirty;
++ action = PBS_BITMAP_ACTION_USED;
++ }
++ }
++
++ PBSBitmapInfo *info = g_malloc(sizeof(*info));
++ info->drive = g_strdup(di->device_name);
++ info->action = action;
++ info->size = di->size;
++ info->dirty = dirty;
++ backup_state.stat.bitmap_list = g_list_append(backup_state.stat.bitmap_list, info);
++
++ di->bitmap = bitmap;
++ di->bitmap_action = action;
++ }
++
++ /* starting=false, because there is no associated QEMU job */
++ initialize_backup_state_stat(NULL, NULL, total, false);
++
++ qemu_mutex_unlock(&backup_state.stat.lock);
++
++ backup_state_set_target_id(target_id);
++
++ backup_state.vmaw = NULL;
++ backup_state.pbs = NULL;
++
++ backup_state.di_list = di_list;
++
++ /* Run setup_all_snapshot_access_bh outside of coroutine (in BH) but keep
++ * backup_mutex locked. This is fine, a CoMutex can be held across yield
++ * points, and we'll release it as soon as the BH reschedules us.
++ */
++ CoCtxData waker = {
++ .co = qemu_coroutine_self(),
++ .ctx = qemu_get_current_aio_context(),
++ .data = &local_err,
++ };
++ aio_bh_schedule_oneshot(waker.ctx, setup_all_snapshot_access_bh, &waker);
++ qemu_coroutine_yield();
++
++ if (local_err) {
++ error_propagate(errp, local_err);
++ goto err;
++ }
++
++ qemu_co_mutex_unlock(&backup_state.backup_mutex);
++
++ BackupAccessInfoList *bai_head = NULL, **p_bai_next = &bai_head;
++
++ l = di_list;
++ while (l) {
++ PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
++ l = g_list_next(l);
++
++ BackupAccessInfoList *info = g_malloc0(sizeof(*info));
++ info->value = g_malloc0(sizeof(*info->value));
++ info->value->node_name = g_strdup(bdrv_get_node_name(di->fleecing.snapshot_access));
++ info->value->device = g_strdup(di->device_name);
++ info->value->size = di->size;
++ if (di->bitmap) {
++ info->value->bitmap_node_name = g_strdup(bdrv_get_node_name(di->bs));
++ info->value->bitmap_name = g_strdup(bitmap_name);
++ info->value->bitmap_action = di->bitmap_action;
++ info->value->has_bitmap_action = true;
++ }
++
++ *p_bai_next = info;
++ p_bai_next = &info->next;
++ }
++
++ return bai_head;
++
++err:
++
++ l = di_list;
++ while (l) {
++ PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
++ l = g_list_next(l);
++
++ handle_backup_access_bitmaps_in_error_case(di);
++
++ g_free(di->device_name);
++ di->device_name = NULL;
++
++ g_free(di);
++ }
++ g_list_free(di_list);
++ backup_state.di_list = NULL;
++
++ qemu_co_mutex_unlock(&backup_state.backup_mutex);
++ return NULL;
++}
++
++/*
++ * Caller needs to hold the backup mutex or the BQL.
++ */
++void backup_access_teardown(bool success)
++{
++ GList *l = backup_state.di_list;
++
++ qemu_mutex_lock(&backup_state.stat.lock);
++ backup_state.stat.finishing = true;
++ qemu_mutex_unlock(&backup_state.stat.lock);
++
++ while (l) {
++ PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
++ l = g_list_next(l);
++
++ if (di->fleecing.snapshot_access) {
++ bdrv_unref(di->fleecing.snapshot_access);
++ di->fleecing.snapshot_access = NULL;
++ }
++ if (di->fleecing.cbw) {
++ bdrv_cbw_drop(di->fleecing.cbw);
++ di->fleecing.cbw = NULL;
++ }
++
++ if (success) {
++ handle_backup_access_bitmaps_after_success(di);
++ } else {
++ handle_backup_access_bitmaps_in_error_case(di);
++ }
++
++ g_free(di->device_name);
++ di->device_name = NULL;
++
++ g_free(di);
++ }
++ g_list_free(backup_state.di_list);
++ backup_state.di_list = NULL;
++
++ qemu_mutex_lock(&backup_state.stat.lock);
++ backup_state.stat.end_time = time(NULL);
++ backup_state.stat.finishing = false;
++ qemu_mutex_unlock(&backup_state.stat.lock);
++}
++
++// Not done in a coroutine, because bdrv_co_unref() and cbw_drop() would just spawn BHs anyways.
++// Caller needs to hold the backup_state.backup_mutex lock
++static void backup_access_teardown_bh(void *opaque)
++{
++ CoCtxData *data = (CoCtxData*)opaque;
++
++ backup_access_teardown(*((bool*)data->data));
++
++ /* return */
++ aio_co_enter(data->ctx, data->co);
++}
++
++void coroutine_fn qmp_backup_access_teardown(const char *target_id, bool success, Error **errp)
++{
++ assert(qemu_in_coroutine());
++
++ qemu_co_mutex_lock(&backup_state.backup_mutex);
++
++ if (!backup_state.target_id) { // nothing to do
++ qemu_co_mutex_unlock(&backup_state.backup_mutex);
++ return;
++ }
++
++ /*
++ * Continue with target_id == NULL, used by the callback registered for qemu_cleanup()
++ */
++ if (target_id && strcmp(backup_state.target_id, target_id)) {
++ error_setg(errp, "cannot teardown backup access - got target %s instead of %s",
++ target_id, backup_state.target_id);
++ qemu_co_mutex_unlock(&backup_state.backup_mutex);
++ return;
++ }
++
++ if (!strcmp(backup_state.target_id, "Proxmox VE")) {
++ error_setg(errp, "cannot teardown backup access for PVE - use backup-cancel instead");
++ qemu_co_mutex_unlock(&backup_state.backup_mutex);
++ return;
++ }
++
++ CoCtxData waker = {
++ .co = qemu_coroutine_self(),
++ .ctx = qemu_get_current_aio_context(),
++ .data = &success,
++ };
++ aio_bh_schedule_oneshot(waker.ctx, backup_access_teardown_bh, &waker);
++ qemu_coroutine_yield();
++
++ qemu_co_mutex_unlock(&backup_state.backup_mutex);
++ return;
++}
++
+ UuidInfo coroutine_fn *qmp_backup(
+ const char *backup_file,
+ const char *password,
+@@ -1068,6 +1499,7 @@ UuidInfo coroutine_fn *qmp_backup(
+ }
+
+ di->dev_id = dev_id;
++ di->bitmap_action = action;
+
+ PBSBitmapInfo *info = g_malloc(sizeof(*info));
+ info->drive = g_strdup(di->device_name);
+@@ -1119,7 +1551,7 @@ UuidInfo coroutine_fn *qmp_backup(
+ }
+ }
+ /* initialize global backup_state now */
+- initialize_backup_state_stat(backup_file, uuid, total);
++ initialize_backup_state_stat(backup_file, &uuid, total, true);
+ char *uuid_str = g_strdup(backup_state.stat.uuid_str);
+
+ qemu_mutex_unlock(&backup_state.stat.lock);
+@@ -1298,5 +1730,6 @@ ProxmoxSupportStatus *qmp_query_proxmox_support(Error **errp)
+ ret->pbs_masterkey = true;
+ ret->backup_max_workers = true;
+ ret->backup_fleecing = true;
++ ret->backup_access_api = true;
+ return ret;
+ }
+diff --git a/pve-backup.h b/pve-backup.h
+new file mode 100644
+index 0000000000..9ebeef7c8f
+--- /dev/null
++++ b/pve-backup.h
+@@ -0,0 +1,16 @@
++/*
++ * Bacup code used by Proxmox VE
++ *
++ * Copyright (C) Proxmox Server Solutions
++ *
++ * This work is licensed under the terms of the GNU GPL, version 2 or later.
++ * See the COPYING file in the top-level directory.
++ *
++ */
++
++#ifndef PVE_BACKUP_H
++#define PVE_BACKUP_H
++
++void backup_access_teardown(bool success);
++
++#endif /* PVE_BACKUP_H */
+diff --git a/qapi/block-core.json b/qapi/block-core.json
+index 9bdcfa31ea..2fb51215f2 100644
+--- a/qapi/block-core.json
++++ b/qapi/block-core.json
+@@ -1023,6 +1023,9 @@
+ #
+ # @pbs-library-version: Running version of libproxmox-backup-qemu0 library.
+ #
++# @backup-access-api: Whether backup access API for external providers is
++# supported or not.
++#
+ # @backup-fleecing: Whether backup fleecing is supported or not.
+ #
+ # @backup-max-workers: Whether the 'max-workers' @BackupPerf setting is
+@@ -1036,6 +1039,7 @@
+ 'pbs-dirty-bitmap-migration': 'bool',
+ 'pbs-masterkey': 'bool',
+ 'pbs-library-version': 'str',
++ 'backup-access-api': 'bool',
+ 'backup-fleecing': 'bool',
+ 'backup-max-workers': 'bool' } }
+
+@@ -1067,9 +1071,16 @@
+ # base snapshot did not match the base given for the current job or
+ # the crypt mode has changed.
+ #
++# @missing-recreated: A bitmap for incremental backup was expected to be
++# present, but was missing and thus got recreated. For example, this can
++# happen if the drive was re-attached or if the bitmap was deleted for some
++# other reason. PBS does not currently keep track of this; the backup-access
++# mechanism does.
++#
+ ##
+ { 'enum': 'PBSBitmapAction',
+- 'data': ['not-used', 'not-used-removed', 'new', 'used', 'invalid'] }
++ 'data': ['not-used', 'not-used-removed', 'new', 'used', 'invalid',
++ 'missing-recreated'] }
+
+ ##
+ # @PBSBitmapInfo:
+@@ -1102,6 +1113,92 @@
+ ##
+ { 'command': 'query-pbs-bitmap-info', 'returns': ['PBSBitmapInfo'] }
+
++##
++# @BackupAccessInfo:
++#
++# Info associated to a snapshot access for backup. For more information about
++# the bitmap see @BackupAccessBitmapMode.
++#
++# @node-name: the block node name of the snapshot-access node.
++#
++# @device: the device on top of which the snapshot access was created.
++#
++# @size: the size of the block device in bytes.
++#
++# @bitmap-node-name: the block node name the dirty bitmap is associated to.
++#
++# @bitmap-name: the name of the dirty bitmap associated to the backup access.
++#
++# @bitmap-action: the action taken on the dirty bitmap.
++#
++##
++{ 'struct': 'BackupAccessInfo',
++ 'data': { 'node-name': 'str', 'device': 'str', 'size': 'size',
++ '*bitmap-node-name': 'str', '*bitmap-name': 'str',
++ '*bitmap-action': 'PBSBitmapAction' } }
++
++##
++# @BackupAccessSourceDevice:
++#
++# Source block device information for creating a backup access.
++#
++# @device: the block device name.
++#
++# @bitmap-mode: used to control whether the bitmap should be reused or
++# recreated or not used. Default is not using a bitmap.
++#
++##
++{ 'struct': 'BackupAccessSourceDevice',
++ 'data': { 'device': 'str', '*bitmap-mode': 'BackupAccessSetupBitmapMode' } }
++
++##
++# @BackupAccessSetupBitmapMode:
++#
++# How to setup a bitmap for a device for @backup-access-setup.
++#
++# @none: do not use a bitmap. Removes an existing bitmap if present.
++#
++# @new: create and use a new bitmap.
++#
++# @use: try to re-use an existing bitmap. Create a new one if it doesn't exist.
++##
++{ 'enum': 'BackupAccessSetupBitmapMode',
++ 'data': ['none', 'new', 'use' ] }
++
++##
++# @backup-access-setup:
++#
++# Set up snapshot access to VM drives for an external backup provider. No other
++# backup or backup access can be done before tearing down the backup access.
++#
++# @target-id: the unique ID of the backup target.
++#
++# @devices: list of devices for which to create the backup access. Also
++# controls whether to use/create a bitmap for the device. Check the
++# @bitmap-action in the result to see what action was actually taken for the
++# bitmap. Each target controls its own bitmaps.
++#
++# Returns: a list of @BackupAccessInfo, one for each device.
++#
++##
++{ 'command': 'backup-access-setup',
++ 'data': { 'target-id': 'str', 'devices': [ 'BackupAccessSourceDevice' ] },
++ 'returns': [ 'BackupAccessInfo' ], 'coroutine': true }
++
++##
++# @backup-access-teardown:
++#
++# Tear down previously setup snapshot access for the same target.
++#
++# @target-id: the ID of the backup target.
++#
++# @success: whether the backup done by the external provider was successful.
++#
++##
++{ 'command': 'backup-access-teardown',
++ 'data': { 'target-id': 'str', 'success': 'bool' },
++ 'coroutine': true }
++
+ ##
+ # @BlockDeviceTimedStats:
+ #
+diff --git a/system/runstate.c b/system/runstate.c
+index 272801d307..cf775213bd 100644
+--- a/system/runstate.c
++++ b/system/runstate.c
+@@ -60,6 +60,7 @@
+ #include "system/system.h"
+ #include "system/tpm.h"
+ #include "trace.h"
++#include "pve-backup.h"
+
+ static NotifierList exit_notifiers =
+ NOTIFIER_LIST_INITIALIZER(exit_notifiers);
+@@ -921,6 +922,11 @@ void qemu_cleanup(int status)
+ * requests happening from here on anyway.
+ */
+ bdrv_drain_all_begin();
++ /*
++ * The backup access is set up by a QMP command, but is neither owned by a monitor nor
++ * associated to a BlockBackend. Need to tear it down manually here.
++ */
++ backup_access_teardown(false);
+ job_cancel_sync_all();
+ bdrv_close_all();
+
diff --git a/debian/patches/pve/0058-savevm-async-improve-setting-state-of-snapshot-opera.patch b/debian/patches/pve/0058-savevm-async-improve-setting-state-of-snapshot-opera.patch
deleted file mode 100644
index 8751ede..0000000
--- a/debian/patches/pve/0058-savevm-async-improve-setting-state-of-snapshot-opera.patch
+++ /dev/null
@@ -1,81 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Fiona Ebner <f.ebner@proxmox.com>
-Date: Mon, 31 Mar 2025 16:55:02 +0200
-Subject: [PATCH] savevm-async: improve setting state of snapshot operation in
- savevm-end handler
-
-One of the callers of wait_for_close_co() already sets the state to
-SAVE_STATE_DONE before, but that is not fully correct, because at that
-moment, the operation is not fully done. In particular, if closing the
-target later fails, the state would even be set to SAVE_STATE_ERROR
-afterwards. DONE -> ERROR is not a valid state transition. Although,
-it should not matter in practice as long as the relevant QMP commands
-are sequential.
-
-The other caller does not set the state and so there seems to be a
-race that could lead to the state not getting set at all. This is
-because before this commit, the wait_for_close_co() function could
-return early when there is no target file anymore. This can only
-happen when canceling and needs to happen right around the time when
-the snapshot is already finishing and closing the target.
-
-Simply avoid the early return and always set the state within the
-wait_for_close_co() function rather than at the call site.
-
-Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
----
- migration/savevm-async.c | 33 +++++++++++++++------------------
- 1 file changed, 15 insertions(+), 18 deletions(-)
-
-diff --git a/migration/savevm-async.c b/migration/savevm-async.c
-index fbcf74f9e2..2163bf50b1 100644
---- a/migration/savevm-async.c
-+++ b/migration/savevm-async.c
-@@ -451,23 +451,22 @@ static void coroutine_fn wait_for_close_co(void *opaque)
- {
- int64_t timeout;
-
-- if (!snap_state.target) {
-- DPRINTF("savevm-end: no target file open\n");
-- return;
-- }
--
-- /* wait until cleanup is done before returning, this ensures that after this
-- * call exits the statefile will be closed and can be removed immediately */
-- DPRINTF("savevm-end: waiting for cleanup\n");
-- timeout = 30L * 1000 * 1000 * 1000;
-- qemu_co_sleep_ns_wakeable(&snap_state.target_close_wait,
-- QEMU_CLOCK_REALTIME, timeout);
- if (snap_state.target) {
-- save_snapshot_error("timeout waiting for target file close in "
-- "qmp_savevm_end");
-- /* we cannot assume the snapshot finished in this case, so leave the
-- * state alone - caller has to figure something out */
-- return;
-+ /* wait until cleanup is done before returning, this ensures that after this
-+ * call exits the statefile will be closed and can be removed immediately */
-+ DPRINTF("savevm-end: waiting for cleanup\n");
-+ timeout = 30L * 1000 * 1000 * 1000;
-+ qemu_co_sleep_ns_wakeable(&snap_state.target_close_wait,
-+ QEMU_CLOCK_REALTIME, timeout);
-+ if (snap_state.target) {
-+ save_snapshot_error("timeout waiting for target file close in "
-+ "qmp_savevm_end");
-+ /* we cannot assume the snapshot finished in this case, so leave the
-+ * state alone - caller has to figure something out */
-+ return;
-+ }
-+ } else {
-+ DPRINTF("savevm-end: no target file open\n");
- }
-
- // File closed and no other error, so ensure next snapshot can be started.
-@@ -498,8 +497,6 @@ void qmp_savevm_end(Error **errp)
- snap_state.saved_vm_running = false;
- }
-
-- snap_state.state = SAVE_STATE_DONE;
--
- qemu_coroutine_enter(wait_for_close);
- }
-
diff --git a/debian/patches/pve/0059-savevm-async-rename-saved_vm_running-to-vm_needs_sta.patch b/debian/patches/pve/0059-savevm-async-rename-saved_vm_running-to-vm_needs_sta.patch
deleted file mode 100644
index 706089c..0000000
--- a/debian/patches/pve/0059-savevm-async-rename-saved_vm_running-to-vm_needs_sta.patch
+++ /dev/null
@@ -1,71 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Fiona Ebner <f.ebner@proxmox.com>
-Date: Mon, 31 Mar 2025 16:55:03 +0200
-Subject: [PATCH] savevm-async: rename saved_vm_running to vm_needs_start
-
-This is what the variable actually expresses. Otherwise, setting it
-to false after starting the VM doesn't make sense.
-
-Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
----
- migration/savevm-async.c | 16 ++++++++--------
- 1 file changed, 8 insertions(+), 8 deletions(-)
-
-diff --git a/migration/savevm-async.c b/migration/savevm-async.c
-index 2163bf50b1..657a4ec9f6 100644
---- a/migration/savevm-async.c
-+++ b/migration/savevm-async.c
-@@ -52,7 +52,7 @@ static struct SnapshotState {
- int state;
- Error *error;
- Error *blocker;
-- int saved_vm_running;
-+ int vm_needs_start;
- QEMUFile *file;
- int64_t total_time;
- QEMUBH *finalize_bh;
-@@ -225,9 +225,9 @@ static void process_savevm_finalize(void *opaque)
- save_snapshot_error("process_savevm_cleanup: invalid state: %d",
- snap_state.state);
- }
-- if (snap_state.saved_vm_running) {
-+ if (snap_state.vm_needs_start) {
- vm_start();
-- snap_state.saved_vm_running = false;
-+ snap_state.vm_needs_start = false;
- }
-
- DPRINTF("timing: process_savevm_finalize (full) took %ld ms\n",
-@@ -353,7 +353,7 @@ void qmp_savevm_start(const char *statefile, Error **errp)
- }
-
- /* initialize snapshot info */
-- snap_state.saved_vm_running = runstate_is_running();
-+ snap_state.vm_needs_start = runstate_is_running();
- snap_state.bs_pos = 0;
- snap_state.total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
- snap_state.blocker = NULL;
-@@ -441,9 +441,9 @@ restart:
-
- save_snapshot_error("setup failed");
-
-- if (snap_state.saved_vm_running) {
-+ if (snap_state.vm_needs_start) {
- vm_start();
-- snap_state.saved_vm_running = false;
-+ snap_state.vm_needs_start = false;
- }
- }
-
-@@ -492,9 +492,9 @@ void qmp_savevm_end(Error **errp)
- return;
- }
-
-- if (snap_state.saved_vm_running) {
-+ if (snap_state.vm_needs_start) {
- vm_start();
-- snap_state.saved_vm_running = false;
-+ snap_state.vm_needs_start = false;
- }
-
- qemu_coroutine_enter(wait_for_close);
diff --git a/debian/patches/pve/0060-savevm-async-improve-runstate-preservation-cleanup-e.patch b/debian/patches/pve/0060-savevm-async-improve-runstate-preservation-cleanup-e.patch
deleted file mode 100644
index 8afd450..0000000
--- a/debian/patches/pve/0060-savevm-async-improve-runstate-preservation-cleanup-e.patch
+++ /dev/null
@@ -1,120 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Fiona Ebner <f.ebner@proxmox.com>
-Date: Mon, 31 Mar 2025 16:55:04 +0200
-Subject: [PATCH] savevm-async: improve runstate preservation, cleanup error
- handling
-
-Determine if VM needs to be started after finishing right before
-actually stopping the VM instead of at the beginning.
-
-In qmp_savevm_start(), the only path stopping the VM returns right
-aftwards, so there is no need for the vm_start() handling after
-errors.
-
-Lastly, improve the code style for checking whether migrate_init()
-failed by explicitly comparing against 0.
-
-Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
-[WB: squashed error handling commits, rename goto branch instead of
- inlining it]
-Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
----
- migration/savevm-async.c | 25 ++++++++++---------------
- 1 file changed, 10 insertions(+), 15 deletions(-)
-
-diff --git a/migration/savevm-async.c b/migration/savevm-async.c
-index 657a4ec9f6..d70ae737bd 100644
---- a/migration/savevm-async.c
-+++ b/migration/savevm-async.c
-@@ -179,6 +179,7 @@ static void process_savevm_finalize(void *opaque)
- */
- blk_set_aio_context(snap_state.target, qemu_get_aio_context(), NULL);
-
-+ snap_state.vm_needs_start = runstate_is_running();
- ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
- if (ret < 0) {
- save_snapshot_error("vm_stop_force_state error %d", ret);
-@@ -353,7 +354,6 @@ void qmp_savevm_start(const char *statefile, Error **errp)
- }
-
- /* initialize snapshot info */
-- snap_state.vm_needs_start = runstate_is_running();
- snap_state.bs_pos = 0;
- snap_state.total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
- snap_state.blocker = NULL;
-@@ -365,13 +365,14 @@ void qmp_savevm_start(const char *statefile, Error **errp)
- }
-
- if (!statefile) {
-+ snap_state.vm_needs_start = runstate_is_running();
- vm_stop(RUN_STATE_SAVE_VM);
- snap_state.state = SAVE_STATE_COMPLETED;
- return;
- }
-
- if (qemu_savevm_state_blocked(errp)) {
-- return;
-+ goto fail;
- }
-
- /* Open the image */
-@@ -381,12 +382,12 @@ void qmp_savevm_start(const char *statefile, Error **errp)
- snap_state.target = blk_new_open(statefile, NULL, options, bdrv_oflags, &local_err);
- if (!snap_state.target) {
- error_setg(errp, "failed to open '%s'", statefile);
-- goto restart;
-+ goto fail;
- }
- target_bs = blk_bs(snap_state.target);
- if (!target_bs) {
- error_setg(errp, "failed to open '%s' - no block driver state", statefile);
-- goto restart;
-+ goto fail;
- }
-
- QIOChannel *ioc = QIO_CHANNEL(qio_channel_savevm_async_new(snap_state.target,
-@@ -395,7 +396,7 @@ void qmp_savevm_start(const char *statefile, Error **errp)
-
- if (!snap_state.file) {
- error_setg(errp, "failed to open '%s'", statefile);
-- goto restart;
-+ goto fail;
- }
-
- /*
-@@ -403,8 +404,8 @@ void qmp_savevm_start(const char *statefile, Error **errp)
- * State is cleared in process_savevm_co, but has to be initialized
- * here (blocking main thread, from QMP) to avoid race conditions.
- */
-- if (migrate_init(ms, errp)) {
-- return;
-+ if (migrate_init(ms, errp) != 0) {
-+ goto fail;
- }
- memset(&mig_stats, 0, sizeof(mig_stats));
- ms->to_dst_file = snap_state.file;
-@@ -419,7 +420,7 @@ void qmp_savevm_start(const char *statefile, Error **errp)
- if (ret != 0) {
- error_setg_errno(errp, -ret, "savevm state setup failed: %s",
- local_err ? error_get_pretty(local_err) : "unknown error");
-- return;
-+ goto fail;
- }
-
- /* Async processing from here on out happens in iohandler context, so let
-@@ -437,14 +438,8 @@ void qmp_savevm_start(const char *statefile, Error **errp)
-
- return;
-
--restart:
--
-+fail:
- save_snapshot_error("setup failed");
--
-- if (snap_state.vm_needs_start) {
-- vm_start();
-- snap_state.vm_needs_start = false;
-- }
- }
-
- static void coroutine_fn wait_for_close_co(void *opaque)
diff --git a/debian/patches/pve/0061-savevm-async-use-dedicated-iothread-for-state-file.patch b/debian/patches/pve/0061-savevm-async-use-dedicated-iothread-for-state-file.patch
deleted file mode 100644
index 1e2c9e1..0000000
--- a/debian/patches/pve/0061-savevm-async-use-dedicated-iothread-for-state-file.patch
+++ /dev/null
@@ -1,177 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Fiona Ebner <f.ebner@proxmox.com>
-Date: Mon, 31 Mar 2025 16:55:06 +0200
-Subject: [PATCH] savevm-async: use dedicated iothread for state file
-
-Having the state file be in the iohandler context means that a
-blk_drain_all() call in the main thread or vCPU thread that happens
-while the snapshot is running will result in a deadlock.
-
-For example, the main thread might be stuck in:
-
-> 0 0x00007300ac9552d6 in __ppoll (fds=0x64bd5a411a50, nfds=2, timeout=<optimized out>, timeout@entry=0x0, sigmask=sigmask@entry=0x0) at ../sysdeps/unix/sysv/linux/ppoll.c:42
-> 1 0x000064bd51af3cad in ppoll (__ss=0x0, __timeout=0x0, __nfds=<optimized out>, __fds=<optimized out>) at /usr/include/x86_64-linux-gnu/bits/poll2.h:64
-> 2 0x000064bd51ad8799 in fdmon_poll_wait (ctx=0x64bd58d968a0, ready_list=0x7ffcfcc15558, timeout=-1) at ../util/fdmon-poll.c:79
-> 3 0x000064bd51ad7c3d in aio_poll (ctx=0x64bd58d968a0, blocking=blocking@entry=true) at ../util/aio-posix.c:671
-> 4 0x000064bd519a0b5d in bdrv_drain_all_begin () at ../block/io.c:531
-> 5 bdrv_drain_all_begin () at ../block/io.c:510
-> 6 0x000064bd519943c4 in blk_drain_all () at ../block/block-backend.c:2085
-> 7 0x000064bd5160fc5a in virtio_scsi_dataplane_stop (vdev=0x64bd5a215190) at ../hw/scsi/virtio-scsi-dataplane.c:213
-> 8 0x000064bd51664e90 in virtio_bus_stop_ioeventfd (bus=0x64bd5a215110) at ../hw/virtio/virtio-bus.c:259
-> 9 0x000064bd5166511b in virtio_bus_stop_ioeventfd (bus=<optimized out>) at ../hw/virtio/virtio-bus.c:251
-> 10 virtio_bus_reset (bus=<optimized out>) at ../hw/virtio/virtio-bus.c:107
-> 11 0x000064bd51667431 in virtio_pci_reset (qdev=<optimized out>) at ../hw/virtio/virtio-pci.c:2296
-...
-> 34 0x000064bd517aa951 in pc_machine_reset (machine=<optimized out>, type=<optimized out>) at ../hw/i386/pc.c:1722
-> 35 0x000064bd516aa4c4 in qemu_system_reset (reason=reason@entry=SHUTDOWN_CAUSE_GUEST_RESET) at ../system/runstate.c:525
-> 36 0x000064bd516aaeb9 in main_loop_should_exit (status=<synthetic pointer>) at ../system/runstate.c:801
-> 37 qemu_main_loop () at ../system/runstate.c:834
-
-which is in block/io.c:
-
-> /* Now poll the in-flight requests */
-> AIO_WAIT_WHILE_UNLOCKED(NULL, bdrv_drain_all_poll());
-
-The working theory is: The deadlock happens because the IO is issued
-from the process_savevm_co() coroutine, which doesn't get scheduled
-again to complete in-flight requests when the main thread is stuck
-there polling. The main thread itself is the one that would need to
-schedule it. In case of a vCPU triggering the VirtIO SCSI dataplane
-stop, which happens during (Linux) boot, the vCPU thread will hold the
-big QEMU lock (BQL) blocking the main thread from making progress
-scheduling the process_savevm_co() coroutine.
-
-This change should also help in general to reduce load on the main
-thread and for it to get stuck on IO, i.e. same benefits as using a
-dedicated IO thread for regular drives. This is particularly
-interesting when the VM state storage is a network storage like NFS.
-
-With some luck, it could also help with bug #6262 [0]. The failure
-there happens while issuing/right after the savevm-start QMP command,
-so the most likely coroutine is the process_savevm_co() that was
-previously scheduled to the iohandler context. Likely someone polls
-the iohandler context and wants to enter the already scheduled
-coroutine leading to the abort():
-> qemu_aio_coroutine_enter: Co-routine was already scheduled in 'aio_co_schedule'
-With a dedicated iothread, there hopefully is no such race.
-
-The comment above querying the pending bytes wrongly talked about the
-"iothread lock", but should've been "iohandler lock". This was even
-renamed to BQL (big QEMU lock) a few releases ago. Even if that was
-not a typo to begin with, there are no AioContext locks anymore.
-
-[0]: https://bugzilla.proxmox.com/show_bug.cgi?id=6262
-
-Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
-[WB: update to the changed error handling in the previous commit]
-Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
----
- migration/savevm-async.c | 41 ++++++++++++++++++++++++++++------------
- 1 file changed, 29 insertions(+), 12 deletions(-)
-
-diff --git a/migration/savevm-async.c b/migration/savevm-async.c
-index d70ae737bd..2236f32784 100644
---- a/migration/savevm-async.c
-+++ b/migration/savevm-async.c
-@@ -58,6 +58,7 @@ static struct SnapshotState {
- QEMUBH *finalize_bh;
- Coroutine *co;
- QemuCoSleep target_close_wait;
-+ IOThread *iothread;
- } snap_state;
-
- static bool savevm_aborted(void)
-@@ -257,16 +258,13 @@ static void coroutine_fn process_savevm_co(void *opaque)
- uint64_t threshold = 400 * 1000;
-
- /*
-- * pending_{estimate,exact} are expected to be called without iothread
-- * lock. Similar to what is done in migration.c, call the exact variant
-- * only once pend_precopy in the estimate is below the threshold.
-+ * Similar to what is done in migration.c, call the exact variant only
-+ * once pend_precopy in the estimate is below the threshold.
- */
-- bql_unlock();
- qemu_savevm_state_pending_estimate(&pend_precopy, &pend_postcopy);
- if (pend_precopy <= threshold) {
- qemu_savevm_state_pending_exact(&pend_precopy, &pend_postcopy);
- }
-- bql_lock();
- pending_size = pend_precopy + pend_postcopy;
-
- /*
-@@ -333,11 +331,17 @@ static void coroutine_fn process_savevm_co(void *opaque)
- qemu_bh_schedule(snap_state.finalize_bh);
- }
-
-+static void savevm_cleanup_iothread(void) {
-+ if (snap_state.iothread) {
-+ iothread_destroy(snap_state.iothread);
-+ snap_state.iothread = NULL;
-+ }
-+}
-+
- void qmp_savevm_start(const char *statefile, Error **errp)
- {
- Error *local_err = NULL;
- MigrationState *ms = migrate_get_current();
-- AioContext *iohandler_ctx = iohandler_get_aio_context();
- BlockDriverState *target_bs = NULL;
- int ret = 0;
-
-@@ -375,6 +379,19 @@ void qmp_savevm_start(const char *statefile, Error **errp)
- goto fail;
- }
-
-+ if (snap_state.iothread) {
-+ /* This is not expected, so warn about it, but no point in re-creating a new iothread. */
-+ warn_report("iothread for snapshot already exists - re-using");
-+ } else {
-+ snap_state.iothread =
-+ iothread_create("__proxmox_savevm_async_iothread__", &local_err);
-+ if (!snap_state.iothread) {
-+ error_setg(errp, "creating iothread failed: %s",
-+ local_err ? error_get_pretty(local_err) : "unknown error");
-+ goto fail;
-+ }
-+ }
-+
- /* Open the image */
- QDict *options = NULL;
- options = qdict_new();
-@@ -423,22 +440,20 @@ void qmp_savevm_start(const char *statefile, Error **errp)
- goto fail;
- }
-
-- /* Async processing from here on out happens in iohandler context, so let
-- * the target bdrv have its home there.
-- */
-- ret = blk_set_aio_context(snap_state.target, iohandler_ctx, &local_err);
-+ ret = blk_set_aio_context(snap_state.target, snap_state.iothread->ctx, &local_err);
- if (ret != 0) {
-- warn_report("failed to set iohandler context for VM state target: %s %s",
-+ warn_report("failed to set iothread context for VM state target: %s %s",
- local_err ? error_get_pretty(local_err) : "unknown error",
- strerror(-ret));
- }
-
- snap_state.co = qemu_coroutine_create(&process_savevm_co, NULL);
-- aio_co_schedule(iohandler_ctx, snap_state.co);
-+ aio_co_schedule(snap_state.iothread->ctx, snap_state.co);
-
- return;
-
- fail:
-+ savevm_cleanup_iothread();
- save_snapshot_error("setup failed");
- }
-
-@@ -464,6 +479,8 @@ static void coroutine_fn wait_for_close_co(void *opaque)
- DPRINTF("savevm-end: no target file open\n");
- }
-
-+ savevm_cleanup_iothread();
-+
- // File closed and no other error, so ensure next snapshot can be started.
- if (snap_state.state != SAVE_STATE_ERROR) {
- snap_state.state = SAVE_STATE_DONE;
diff --git a/debian/patches/pve/0062-savevm-async-treat-failure-to-set-iothread-context-a.patch b/debian/patches/pve/0062-savevm-async-treat-failure-to-set-iothread-context-a.patch
deleted file mode 100644
index 1def7ac..0000000
--- a/debian/patches/pve/0062-savevm-async-treat-failure-to-set-iothread-context-a.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Fiona Ebner <f.ebner@proxmox.com>
-Date: Mon, 31 Mar 2025 16:55:07 +0200
-Subject: [PATCH] savevm-async: treat failure to set iothread context as a hard
- failure
-
-This is not expected to ever fail and there might be assumptions about
-having the expected context down the line.
-
-Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
-[WB: update to changed error handling]
-Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
----
- migration/savevm-async.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/migration/savevm-async.c b/migration/savevm-async.c
-index 2236f32784..730b815494 100644
---- a/migration/savevm-async.c
-+++ b/migration/savevm-async.c
-@@ -442,9 +442,9 @@ void qmp_savevm_start(const char *statefile, Error **errp)
-
- ret = blk_set_aio_context(snap_state.target, snap_state.iothread->ctx, &local_err);
- if (ret != 0) {
-- warn_report("failed to set iothread context for VM state target: %s %s",
-- local_err ? error_get_pretty(local_err) : "unknown error",
-- strerror(-ret));
-+ error_setg_errno(errp, -ret, "failed to set iothread context for VM state target: %s",
-+ local_err ? error_get_pretty(local_err) : "unknown error");
-+ goto fail;
- }
-
- snap_state.co = qemu_coroutine_create(&process_savevm_co, NULL);
diff --git a/debian/patches/pve/0063-PVE-backup-clean-up-directly-in-setup_snapshot_acces.patch b/debian/patches/pve/0063-PVE-backup-clean-up-directly-in-setup_snapshot_acces.patch
deleted file mode 100644
index a5582bd..0000000
--- a/debian/patches/pve/0063-PVE-backup-clean-up-directly-in-setup_snapshot_acces.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Fiona Ebner <f.ebner@proxmox.com>
-Date: Thu, 3 Apr 2025 14:30:41 +0200
-Subject: [PATCH] PVE backup: clean up directly in setup_snapshot_access() when
- it fails
-
-The only thing that might need to be cleaned up after
-setup_snapshot_access() failed is dropping the cbw filter. Do so in
-the single branch it matters inside setup_snapshot_access() itself.
-This avoids the need that callers of setup_snapshot_access() use
-cleanup_snapshot_access() when the call failed.
-
-Suggested-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
-Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
-Reviewed-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
----
- pve-backup.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/pve-backup.c b/pve-backup.c
-index b411d58a9a..9b66788ab5 100644
---- a/pve-backup.c
-+++ b/pve-backup.c
-@@ -576,6 +576,9 @@ static int setup_snapshot_access(PVEBackupDevInfo *di, Error **errp)
- di->fleecing.snapshot_access =
- bdrv_open(NULL, NULL, snapshot_access_opts, BDRV_O_RDWR | BDRV_O_UNMAP, &local_err);
- if (!di->fleecing.snapshot_access) {
-+ bdrv_cbw_drop(di->fleecing.cbw);
-+ di->fleecing.cbw = NULL;
-+
- error_setg(errp, "setting up snapshot access for fleecing failed: %s",
- local_err ? error_get_pretty(local_err) : "unknown error");
- return -1;
-@@ -629,7 +632,6 @@ static void create_backup_jobs_bh(void *opaque) {
- error_setg(errp, "%s - setting up snapshot access for fleecing failed: %s",
- di->device_name,
- local_err ? error_get_pretty(local_err) : "unknown error");
-- cleanup_snapshot_access(di);
- bdrv_drained_end(di->bs);
- break;
- }
diff --git a/debian/patches/pve/0068-PVE-backup-implement-backup-access-setup-and-teardow.patch b/debian/patches/pve/0068-PVE-backup-implement-backup-access-setup-and-teardow.patch
deleted file mode 100644
index 9e665ca..0000000
--- a/debian/patches/pve/0068-PVE-backup-implement-backup-access-setup-and-teardow.patch
+++ /dev/null
@@ -1,495 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Fiona Ebner <f.ebner@proxmox.com>
-Date: Thu, 3 Apr 2025 14:30:46 +0200
-Subject: [PATCH] PVE backup: implement backup access setup and teardown API
- for external providers
-
-For external backup providers, the state of the VM's disk images at
-the time the backup is started is preserved via a snapshot-access
-block node. Old data is moved to the fleecing image when new guest
-writes come in. The snapshot-access block node, as well as the
-associated bitmap in case of incremental backup, will be exported via
-NBD to the external provider. The NBD export will be done by the
-management layer, the missing functionality is setting up and tearing
-down the snapshot-access block nodes, which this patch adds.
-
-It is necessary to also set up fleecing for EFI and TPM disks, so that
-old data can be moved out of the way when a new guest write comes in.
-
-There can only be one regular backup or one active backup access at
-a time, because both require replacing the original block node of the
-drive. Thus the backup state is re-used, and checks are added to
-prohibit regular backup while snapshot access is active and vice
-versa.
-
-The block nodes added by the backup-access-setup QMP call are not
-tracked anywhere else (there is no job they are associated to like for
-regular backup). This requires adding a callback for teardown when
-QEMU exits, i.e. in qemu_cleanup(). Otherwise, there will be an
-assertion failure that the block graph is not empty when QEMU exits
-before the backup-access-teardown QMP command is called.
-
-The code for the qmp_backup_access_setup() was based on the existing
-qmp_backup() routine.
-
-The return value for the setup QMP command contains information about
-the snapshot-access block nodes that can be used by the management
-layer to set up the NBD exports.
-
-Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
-Reviewed-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
----
- pve-backup.c | 264 ++++++++++++++++++++++++++++++++++++++++++-
- pve-backup.h | 16 +++
- qapi/block-core.json | 49 ++++++++
- system/runstate.c | 6 +
- 4 files changed, 329 insertions(+), 6 deletions(-)
- create mode 100644 pve-backup.h
-
-diff --git a/pve-backup.c b/pve-backup.c
-index bd81621d51..78ed6c980c 100644
---- a/pve-backup.c
-+++ b/pve-backup.c
-@@ -1,4 +1,5 @@
- #include "proxmox-backup-client.h"
-+#include "pve-backup.h"
- #include "vma.h"
-
- #include "qemu/osdep.h"
-@@ -588,6 +589,36 @@ static int setup_snapshot_access(PVEBackupDevInfo *di, Error **errp)
- return 0;
- }
-
-+static void setup_all_snapshot_access_bh(void *opaque)
-+{
-+ assert(!qemu_in_coroutine());
-+
-+ CoCtxData *data = (CoCtxData*)opaque;
-+ Error **errp = (Error**)data->data;
-+
-+ Error *local_err = NULL;
-+
-+ GList *l = backup_state.di_list;
-+ while (l) {
-+ PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
-+ l = g_list_next(l);
-+
-+ bdrv_drained_begin(di->bs);
-+
-+ if (setup_snapshot_access(di, &local_err) < 0) {
-+ bdrv_drained_end(di->bs);
-+ error_setg(errp, "%s - setting up snapshot access failed: %s", di->device_name,
-+ local_err ? error_get_pretty(local_err) : "unknown error");
-+ break;
-+ }
-+
-+ bdrv_drained_end(di->bs);
-+ }
-+
-+ /* return */
-+ aio_co_enter(data->ctx, data->co);
-+}
-+
- /*
- * backup_job_create can *not* be run from a coroutine, so this can't either.
- * The caller is responsible that backup_mutex is held nonetheless.
-@@ -724,6 +755,11 @@ static bool fleecing_no_efi_tpm(const char *device_id)
- return strncmp(device_id, "drive-efidisk", 13) && strncmp(device_id, "drive-tpmstate", 14);
- }
-
-+static bool fleecing_all(const char *device_id)
-+{
-+ return true;
-+}
-+
- /*
- * Returns a list of device infos, which needs to be freed by the caller. In
- * case of an error, errp will be set, but the returned value might still be a
-@@ -839,8 +875,9 @@ static void clear_backup_state_bitmap_list(void) {
- */
- static void initialize_backup_state_stat(
- const char *backup_file,
-- uuid_t uuid,
-- size_t total)
-+ uuid_t *uuid,
-+ size_t total,
-+ bool starting)
- {
- if (backup_state.stat.error) {
- error_free(backup_state.stat.error);
-@@ -855,15 +892,19 @@ static void initialize_backup_state_stat(
- }
- backup_state.stat.backup_file = g_strdup(backup_file);
-
-- uuid_copy(backup_state.stat.uuid, uuid);
-- uuid_unparse_lower(uuid, backup_state.stat.uuid_str);
-+ if (uuid) {
-+ uuid_copy(backup_state.stat.uuid, *uuid);
-+ uuid_unparse_lower(*uuid, backup_state.stat.uuid_str);
-+ } else {
-+ backup_state.stat.uuid_str[0] = '\0';
-+ }
-
- backup_state.stat.total = total;
- backup_state.stat.dirty = total - backup_state.stat.reused;
- backup_state.stat.transferred = 0;
- backup_state.stat.zero_bytes = 0;
- backup_state.stat.finishing = false;
-- backup_state.stat.starting = true;
-+ backup_state.stat.starting = starting;
- }
-
- /*
-@@ -876,6 +917,216 @@ static void backup_state_set_target_id(const char *target_id) {
- backup_state.target_id = g_strdup(target_id);
- }
-
-+BackupAccessInfoList *coroutine_fn qmp_backup_access_setup(
-+ const char *target_id,
-+ const char *devlist,
-+ Error **errp)
-+{
-+ assert(qemu_in_coroutine());
-+
-+ qemu_co_mutex_lock(&backup_state.backup_mutex);
-+
-+ Error *local_err = NULL;
-+ GList *di_list = NULL;
-+ GList *l;
-+
-+ if (backup_state.di_list) {
-+ error_set(errp, ERROR_CLASS_GENERIC_ERROR,
-+ "previous backup for target '%s' not finished", backup_state.target_id);
-+ qemu_co_mutex_unlock(&backup_state.backup_mutex);
-+ return NULL;
-+ }
-+
-+ bdrv_graph_co_rdlock();
-+ di_list = get_device_info(devlist, fleecing_all, &local_err);
-+ bdrv_graph_co_rdunlock();
-+ if (local_err) {
-+ error_propagate(errp, local_err);
-+ goto err;
-+ }
-+ assert(di_list);
-+
-+ size_t total = 0;
-+
-+ l = di_list;
-+ while (l) {
-+ PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
-+ l = g_list_next(l);
-+
-+ ssize_t size = bdrv_getlength(di->bs);
-+ if (size < 0) {
-+ error_setg_errno(errp, -size, "bdrv_getlength failed");
-+ goto err;
-+ }
-+ di->size = size;
-+ total += size;
-+
-+ di->completed_ret = INT_MAX;
-+ }
-+
-+ qemu_mutex_lock(&backup_state.stat.lock);
-+ backup_state.stat.reused = 0;
-+
-+ /* clear previous backup's bitmap_list */
-+ clear_backup_state_bitmap_list();
-+
-+ /* starting=false, because there is no associated QEMU job */
-+ initialize_backup_state_stat(NULL, NULL, total, false);
-+
-+ qemu_mutex_unlock(&backup_state.stat.lock);
-+
-+ backup_state_set_target_id(target_id);
-+
-+ backup_state.vmaw = NULL;
-+ backup_state.pbs = NULL;
-+
-+ backup_state.di_list = di_list;
-+
-+ /* Run setup_all_snapshot_access_bh outside of coroutine (in BH) but keep
-+ * backup_mutex locked. This is fine, a CoMutex can be held across yield
-+ * points, and we'll release it as soon as the BH reschedules us.
-+ */
-+ CoCtxData waker = {
-+ .co = qemu_coroutine_self(),
-+ .ctx = qemu_get_current_aio_context(),
-+ .data = &local_err,
-+ };
-+ aio_bh_schedule_oneshot(waker.ctx, setup_all_snapshot_access_bh, &waker);
-+ qemu_coroutine_yield();
-+
-+ if (local_err) {
-+ error_propagate(errp, local_err);
-+ goto err;
-+ }
-+
-+ qemu_co_mutex_unlock(&backup_state.backup_mutex);
-+
-+ BackupAccessInfoList *bai_head = NULL, **p_bai_next = &bai_head;
-+
-+ l = di_list;
-+ while (l) {
-+ PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
-+ l = g_list_next(l);
-+
-+ BackupAccessInfoList *info = g_malloc0(sizeof(*info));
-+ info->value = g_malloc0(sizeof(*info->value));
-+ info->value->node_name = g_strdup(bdrv_get_node_name(di->fleecing.snapshot_access));
-+ info->value->device = g_strdup(di->device_name);
-+ info->value->size = di->size;
-+
-+ *p_bai_next = info;
-+ p_bai_next = &info->next;
-+ }
-+
-+ return bai_head;
-+
-+err:
-+
-+ l = di_list;
-+ while (l) {
-+ PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
-+ l = g_list_next(l);
-+
-+ g_free(di->device_name);
-+ di->device_name = NULL;
-+
-+ g_free(di);
-+ }
-+ g_list_free(di_list);
-+ backup_state.di_list = NULL;
-+
-+ qemu_co_mutex_unlock(&backup_state.backup_mutex);
-+ return NULL;
-+}
-+
-+/*
-+ * Caller needs to hold the backup mutex or the BQL.
-+ */
-+void backup_access_teardown(void)
-+{
-+ GList *l = backup_state.di_list;
-+
-+ qemu_mutex_lock(&backup_state.stat.lock);
-+ backup_state.stat.finishing = true;
-+ qemu_mutex_unlock(&backup_state.stat.lock);
-+
-+ while (l) {
-+ PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
-+ l = g_list_next(l);
-+
-+ if (di->fleecing.snapshot_access) {
-+ bdrv_unref(di->fleecing.snapshot_access);
-+ di->fleecing.snapshot_access = NULL;
-+ }
-+ if (di->fleecing.cbw) {
-+ bdrv_cbw_drop(di->fleecing.cbw);
-+ di->fleecing.cbw = NULL;
-+ }
-+
-+ g_free(di->device_name);
-+ di->device_name = NULL;
-+
-+ g_free(di);
-+ }
-+ g_list_free(backup_state.di_list);
-+ backup_state.di_list = NULL;
-+
-+ qemu_mutex_lock(&backup_state.stat.lock);
-+ backup_state.stat.end_time = time(NULL);
-+ backup_state.stat.finishing = false;
-+ qemu_mutex_unlock(&backup_state.stat.lock);
-+}
-+
-+// Not done in a coroutine, because bdrv_co_unref() and cbw_drop() would just spawn BHs anyways.
-+// Caller needs to hold the backup_state.backup_mutex lock
-+static void backup_access_teardown_bh(void *opaque)
-+{
-+ CoCtxData *data = (CoCtxData*)opaque;
-+
-+ backup_access_teardown();
-+
-+ /* return */
-+ aio_co_enter(data->ctx, data->co);
-+}
-+
-+void coroutine_fn qmp_backup_access_teardown(const char *target_id, Error **errp)
-+{
-+ assert(qemu_in_coroutine());
-+
-+ qemu_co_mutex_lock(&backup_state.backup_mutex);
-+
-+ if (!backup_state.target_id) { // nothing to do
-+ qemu_co_mutex_unlock(&backup_state.backup_mutex);
-+ return;
-+ }
-+
-+ /*
-+ * Continue with target_id == NULL, used by the callback registered for qemu_cleanup()
-+ */
-+ if (target_id && strcmp(backup_state.target_id, target_id)) {
-+ error_setg(errp, "cannot teardown backup access - got target %s instead of %s",
-+ target_id, backup_state.target_id);
-+ qemu_co_mutex_unlock(&backup_state.backup_mutex);
-+ return;
-+ }
-+
-+ if (!strcmp(backup_state.target_id, "Proxmox VE")) {
-+ error_setg(errp, "cannot teardown backup access for PVE - use backup-cancel instead");
-+ qemu_co_mutex_unlock(&backup_state.backup_mutex);
-+ return;
-+ }
-+
-+ CoCtxData waker = {
-+ .co = qemu_coroutine_self(),
-+ .ctx = qemu_get_current_aio_context(),
-+ };
-+ aio_bh_schedule_oneshot(waker.ctx, backup_access_teardown_bh, &waker);
-+ qemu_coroutine_yield();
-+
-+ qemu_co_mutex_unlock(&backup_state.backup_mutex);
-+ return;
-+}
-+
- UuidInfo coroutine_fn *qmp_backup(
- const char *backup_file,
- const char *password,
-@@ -1119,7 +1370,7 @@ UuidInfo coroutine_fn *qmp_backup(
- }
- }
- /* initialize global backup_state now */
-- initialize_backup_state_stat(backup_file, uuid, total);
-+ initialize_backup_state_stat(backup_file, &uuid, total, true);
- char *uuid_str = g_strdup(backup_state.stat.uuid_str);
-
- qemu_mutex_unlock(&backup_state.stat.lock);
-@@ -1298,5 +1549,6 @@ ProxmoxSupportStatus *qmp_query_proxmox_support(Error **errp)
- ret->pbs_masterkey = true;
- ret->backup_max_workers = true;
- ret->backup_fleecing = true;
-+ ret->backup_access_api = true;
- return ret;
- }
-diff --git a/pve-backup.h b/pve-backup.h
-new file mode 100644
-index 0000000000..4033bc848f
---- /dev/null
-+++ b/pve-backup.h
-@@ -0,0 +1,16 @@
-+/*
-+ * Bacup code used by Proxmox VE
-+ *
-+ * Copyright (C) Proxmox Server Solutions
-+ *
-+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
-+ * See the COPYING file in the top-level directory.
-+ *
-+ */
-+
-+#ifndef PVE_BACKUP_H
-+#define PVE_BACKUP_H
-+
-+void backup_access_teardown(void);
-+
-+#endif /* PVE_BACKUP_H */
-diff --git a/qapi/block-core.json b/qapi/block-core.json
-index 9bdcfa31ea..8d499650a8 100644
---- a/qapi/block-core.json
-+++ b/qapi/block-core.json
-@@ -1023,6 +1023,9 @@
- #
- # @pbs-library-version: Running version of libproxmox-backup-qemu0 library.
- #
-+# @backup-access-api: Whether backup access API for external providers is
-+# supported or not.
-+#
- # @backup-fleecing: Whether backup fleecing is supported or not.
- #
- # @backup-max-workers: Whether the 'max-workers' @BackupPerf setting is
-@@ -1036,6 +1039,7 @@
- 'pbs-dirty-bitmap-migration': 'bool',
- 'pbs-masterkey': 'bool',
- 'pbs-library-version': 'str',
-+ 'backup-access-api': 'bool',
- 'backup-fleecing': 'bool',
- 'backup-max-workers': 'bool' } }
-
-@@ -1102,6 +1106,51 @@
- ##
- { 'command': 'query-pbs-bitmap-info', 'returns': ['PBSBitmapInfo'] }
-
-+##
-+# @BackupAccessInfo:
-+#
-+# Info associated to a snapshot access for backup. For more information about
-+# the bitmap see @BackupAccessBitmapMode.
-+#
-+# @node-name: the block node name of the snapshot-access node.
-+#
-+# @device: the device on top of which the snapshot access was created.
-+#
-+# @size: the size of the block device in bytes.
-+#
-+##
-+{ 'struct': 'BackupAccessInfo',
-+ 'data': { 'node-name': 'str', 'device': 'str', 'size': 'size' } }
-+
-+##
-+# @backup-access-setup:
-+#
-+# Set up snapshot access to VM drives for an external backup provider. No other
-+# backup or backup access can be done before tearing down the backup access.
-+#
-+# @target-id: the unique ID of the backup target.
-+#
-+# @devlist: list of block device names (separated by ',', ';' or ':'). By
-+# default the backup includes all writable block devices.
-+#
-+# Returns: a list of @BackupAccessInfo, one for each device.
-+#
-+##
-+{ 'command': 'backup-access-setup',
-+ 'data': { 'target-id': 'str', '*devlist': 'str' },
-+ 'returns': [ 'BackupAccessInfo' ], 'coroutine': true }
-+
-+##
-+# @backup-access-teardown:
-+#
-+# Tear down previously setup snapshot access for the same target.
-+#
-+# @target-id: the ID of the backup target.
-+#
-+##
-+{ 'command': 'backup-access-teardown', 'data': { 'target-id': 'str' },
-+ 'coroutine': true }
-+
- ##
- # @BlockDeviceTimedStats:
- #
-diff --git a/system/runstate.c b/system/runstate.c
-index 272801d307..73026a3884 100644
---- a/system/runstate.c
-+++ b/system/runstate.c
-@@ -60,6 +60,7 @@
- #include "system/system.h"
- #include "system/tpm.h"
- #include "trace.h"
-+#include "pve-backup.h"
-
- static NotifierList exit_notifiers =
- NOTIFIER_LIST_INITIALIZER(exit_notifiers);
-@@ -921,6 +922,11 @@ void qemu_cleanup(int status)
- * requests happening from here on anyway.
- */
- bdrv_drain_all_begin();
-+ /*
-+ * The backup access is set up by a QMP command, but is neither owned by a monitor nor
-+ * associated to a BlockBackend. Need to tear it down manually here.
-+ */
-+ backup_access_teardown();
- job_cancel_sync_all();
- bdrv_close_all();
-
diff --git a/debian/patches/pve/0069-PVE-backup-factor-out-get_single_device_info-helper.patch b/debian/patches/pve/0069-PVE-backup-factor-out-get_single_device_info-helper.patch
deleted file mode 100644
index 85346c3..0000000
--- a/debian/patches/pve/0069-PVE-backup-factor-out-get_single_device_info-helper.patch
+++ /dev/null
@@ -1,122 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Fiona Ebner <f.ebner@proxmox.com>
-Date: Thu, 3 Apr 2025 14:30:47 +0200
-Subject: [PATCH] PVE backup: factor out get_single_device_info() helper
-
-Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
-[WB: free di and di->device_name on error]
-Sigend-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
----
- pve-backup.c | 90 +++++++++++++++++++++++++++++++---------------------
- 1 file changed, 53 insertions(+), 37 deletions(-)
-
-diff --git a/pve-backup.c b/pve-backup.c
-index 78ed6c980c..681d25b97e 100644
---- a/pve-backup.c
-+++ b/pve-backup.c
-@@ -760,6 +760,57 @@ static bool fleecing_all(const char *device_id)
- return true;
- }
-
-+static PVEBackupDevInfo coroutine_fn GRAPH_RDLOCK *get_single_device_info(
-+ const char *device,
-+ bool (*device_uses_fleecing)(const char*),
-+ Error **errp)
-+{
-+ BlockBackend *blk = blk_by_name(device);
-+ if (!blk) {
-+ error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
-+ "Device '%s' not found", device);
-+ return NULL;
-+ }
-+ BlockDriverState *bs = blk_bs(blk);
-+ if (!bdrv_co_is_inserted(bs)) {
-+ error_setg(errp, "Device '%s' has no medium", device);
-+ return NULL;
-+ }
-+ PVEBackupDevInfo *di = g_new0(PVEBackupDevInfo, 1);
-+ di->bs = bs;
-+ di->device_name = g_strdup(bdrv_get_device_name(bs));
-+
-+ if (device_uses_fleecing && device_uses_fleecing(device)) {
-+ g_autofree gchar *fleecing_devid = g_strconcat(device, "-fleecing", NULL);
-+ BlockBackend *fleecing_blk = blk_by_name(fleecing_devid);
-+ if (!fleecing_blk) {
-+ error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
-+ "Device '%s' not found", fleecing_devid);
-+ goto fail;
-+ }
-+ BlockDriverState *fleecing_bs = blk_bs(fleecing_blk);
-+ if (!bdrv_co_is_inserted(fleecing_bs)) {
-+ error_setg(errp, "Device '%s' has no medium", fleecing_devid);
-+ goto fail;
-+ }
-+ /*
-+ * Fleecing image needs to be the same size to act as a cbw target.
-+ */
-+ if (bs->total_sectors != fleecing_bs->total_sectors) {
-+ error_setg(errp, "Size mismatch for '%s' - sector count %ld != %ld",
-+ fleecing_devid, fleecing_bs->total_sectors, bs->total_sectors);
-+ goto fail;
-+ }
-+ di->fleecing.bs = fleecing_bs;
-+ }
-+
-+ return di;
-+fail:
-+ g_free(di->device_name);
-+ g_free(di);
-+ return NULL;
-+}
-+
- /*
- * Returns a list of device infos, which needs to be freed by the caller. In
- * case of an error, errp will be set, but the returned value might still be a
-@@ -778,45 +829,10 @@ static GList coroutine_fn GRAPH_RDLOCK *get_device_info(
-
- gchar **d = devs;
- while (d && *d) {
-- BlockBackend *blk = blk_by_name(*d);
-- if (!blk) {
-- error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
-- "Device '%s' not found", *d);
-+ PVEBackupDevInfo *di = get_single_device_info(*d, device_uses_fleecing, errp);
-+ if (!di) {
- goto err;
- }
-- BlockDriverState *bs = blk_bs(blk);
-- if (!bdrv_co_is_inserted(bs)) {
-- error_setg(errp, "Device '%s' has no medium", *d);
-- goto err;
-- }
-- PVEBackupDevInfo *di = g_new0(PVEBackupDevInfo, 1);
-- di->bs = bs;
-- di->device_name = g_strdup(bdrv_get_device_name(bs));
--
-- if (device_uses_fleecing && device_uses_fleecing(*d)) {
-- g_autofree gchar *fleecing_devid = g_strconcat(*d, "-fleecing", NULL);
-- BlockBackend *fleecing_blk = blk_by_name(fleecing_devid);
-- if (!fleecing_blk) {
-- error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
-- "Device '%s' not found", fleecing_devid);
-- goto err;
-- }
-- BlockDriverState *fleecing_bs = blk_bs(fleecing_blk);
-- if (!bdrv_co_is_inserted(fleecing_bs)) {
-- error_setg(errp, "Device '%s' has no medium", fleecing_devid);
-- goto err;
-- }
-- /*
-- * Fleecing image needs to be the same size to act as a cbw target.
-- */
-- if (bs->total_sectors != fleecing_bs->total_sectors) {
-- error_setg(errp, "Size mismatch for '%s' - sector count %ld != %ld",
-- fleecing_devid, fleecing_bs->total_sectors, bs->total_sectors);
-- goto err;
-- }
-- di->fleecing.bs = fleecing_bs;
-- }
--
- di_list = g_list_append(di_list, di);
- d++;
- }
diff --git a/debian/patches/pve/0070-PVE-backup-implement-bitmap-support-for-external-bac.patch b/debian/patches/pve/0070-PVE-backup-implement-bitmap-support-for-external-bac.patch
deleted file mode 100644
index 597eabe..0000000
--- a/debian/patches/pve/0070-PVE-backup-implement-bitmap-support-for-external-bac.patch
+++ /dev/null
@@ -1,470 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Fiona Ebner <f.ebner@proxmox.com>
-Date: Thu, 3 Apr 2025 14:30:48 +0200
-Subject: [PATCH] PVE backup: implement bitmap support for external backup
- access
-
-There can be one dirty bitmap for each backup target ID for each
-device (which are tracked in the backup_access_bitmaps hash table).
-The QMP user can specify the ID of the bitmap it likes to use. This ID
-is then compared to the current one for the given target and device.
-If they match, the bitmap is re-used (should it still exist on the
-drive, otherwise re-created). If there is a mismatch, the old bitmap
-is removed and a new one is created.
-
-The return value of the QMP command includes information about what
-bitmap action was taken. Similar to what the query-backup QMP command
-returns for regular backup. It also includes the bitmap name and
-associated block node, so the management layer can then set up an NBD
-export with the bitmap.
-
-While the backup access is active, a background bitmap is also
-required. This is necessary to implement bitmap handling according to
-the original reference [0]. In particular:
-
-- in the error case, new writes since the backup access was set up are
- in the background bitmap. Because of failure, the previously tracked
- writes from the backup access bitmap are still required too. Thus,
- the bitmap is merged with the background bitmap to get all new
- writes since the last backup.
-
-- in the success case, continue tracking for the next incremental
- backup in the backup access bitmap. New writes since the backup
- access was set up are in the background bitmap. Because the backup
- was successfully, clear the backup access bitmap and merge back the
- background bitmap to get only the new writes.
-
-Since QEMU cannot know if the backup was successful or not (except if
-failure already happens during the setup QMP command), the management
-layer needs to tell it via the teardown QMP command.
-
-The bitmap action is also recorded in the device info now.
-
-[0]: https://lore.kernel.org/qemu-devel/b68833dd-8864-4d72-7c61-c134a9835036@ya.ru/
-
-Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
-Reviewed-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
----
- pve-backup.c | 196 +++++++++++++++++++++++++++++++++++++++++--
- pve-backup.h | 2 +-
- qapi/block-core.json | 36 ++++++--
- system/runstate.c | 2 +-
- 4 files changed, 220 insertions(+), 16 deletions(-)
-
-diff --git a/pve-backup.c b/pve-backup.c
-index 681d25b97e..bd4d5e2579 100644
---- a/pve-backup.c
-+++ b/pve-backup.c
-@@ -15,6 +15,7 @@
- #include "qobject/qdict.h"
- #include "qapi/qmp/qerror.h"
- #include "qemu/cutils.h"
-+#include "qemu/error-report.h"
-
- #if defined(CONFIG_MALLOC_TRIM)
- #include <malloc.h>
-@@ -41,6 +42,7 @@
- */
-
- const char *PBS_BITMAP_NAME = "pbs-incremental-dirty-bitmap";
-+const char *BACKGROUND_BITMAP_NAME = "backup-access-background-bitmap";
-
- static struct PVEBackupState {
- struct {
-@@ -72,6 +74,7 @@ static struct PVEBackupState {
- CoMutex backup_mutex;
- CoMutex dump_callback_mutex;
- char *target_id;
-+ GHashTable *backup_access_bitmaps; // key=target_id, value=bitmap_name
- } backup_state;
-
- static void pvebackup_init(void)
-@@ -99,8 +102,11 @@ typedef struct PVEBackupDevInfo {
- char* device_name;
- int completed_ret; // INT_MAX if not completed
- BdrvDirtyBitmap *bitmap;
-+ BdrvDirtyBitmap *background_bitmap; // used for external backup access
-+ PBSBitmapAction bitmap_action;
- BlockDriverState *target;
- BlockJob *job;
-+ char *requested_bitmap_name; // used by external backup access during initialization
- } PVEBackupDevInfo;
-
- static void pvebackup_propagate_error(Error *err)
-@@ -362,6 +368,67 @@ static void coroutine_fn pvebackup_co_complete_stream(void *opaque)
- qemu_co_mutex_unlock(&backup_state.backup_mutex);
- }
-
-+/*
-+ * New writes since the backup access was set up are in the background bitmap. Because of failure,
-+ * the previously tracked writes in di->bitmap are still required too. Thus, merge with the
-+ * background bitmap to get all new writes since the last backup.
-+ */
-+static void handle_backup_access_bitmaps_in_error_case(PVEBackupDevInfo *di)
-+{
-+ Error *local_err = NULL;
-+
-+ if (di->bs && di->background_bitmap) {
-+ bdrv_drained_begin(di->bs);
-+ if (di->bitmap) {
-+ bdrv_enable_dirty_bitmap(di->bitmap);
-+ if (!bdrv_merge_dirty_bitmap(di->bitmap, di->background_bitmap, NULL, &local_err)) {
-+ warn_report("backup access: %s - could not merge bitmaps in error path - %s",
-+ di->device_name,
-+ local_err ? error_get_pretty(local_err) : "unknown error");
-+ /*
-+ * Could not merge, drop original bitmap too.
-+ */
-+ bdrv_release_dirty_bitmap(di->bitmap);
-+ }
-+ } else {
-+ warn_report("backup access: %s - expected bitmap not present", di->device_name);
-+ }
-+ bdrv_release_dirty_bitmap(di->background_bitmap);
-+ bdrv_drained_end(di->bs);
-+ }
-+}
-+
-+/*
-+ * Continue tracking for next incremental backup in di->bitmap. New writes since the backup access
-+ * was set up are in the background bitmap. Because the backup was successful, clear di->bitmap and
-+ * merge back the background bitmap to get only the new writes.
-+ */
-+static void handle_backup_access_bitmaps_after_success(PVEBackupDevInfo *di)
-+{
-+ Error *local_err = NULL;
-+
-+ if (di->bs && di->background_bitmap) {
-+ bdrv_drained_begin(di->bs);
-+ if (di->bitmap) {
-+ bdrv_enable_dirty_bitmap(di->bitmap);
-+ bdrv_clear_dirty_bitmap(di->bitmap, NULL);
-+ if (!bdrv_merge_dirty_bitmap(di->bitmap, di->background_bitmap, NULL, &local_err)) {
-+ warn_report("backup access: %s - could not merge bitmaps after backup - %s",
-+ di->device_name,
-+ local_err ? error_get_pretty(local_err) : "unknown error");
-+ /*
-+ * Could not merge, drop original bitmap too.
-+ */
-+ bdrv_release_dirty_bitmap(di->bitmap);
-+ }
-+ } else {
-+ warn_report("backup access: %s - expected bitmap not present", di->device_name);
-+ }
-+ bdrv_release_dirty_bitmap(di->background_bitmap);
-+ bdrv_drained_end(di->bs);
-+ }
-+}
-+
- static void cleanup_snapshot_access(PVEBackupDevInfo *di)
- {
- if (di->fleecing.snapshot_access) {
-@@ -605,6 +672,21 @@ static void setup_all_snapshot_access_bh(void *opaque)
-
- bdrv_drained_begin(di->bs);
-
-+ if (di->bitmap) {
-+ BdrvDirtyBitmap *background_bitmap =
-+ bdrv_create_dirty_bitmap(di->bs, PROXMOX_BACKUP_DEFAULT_CHUNK_SIZE,
-+ BACKGROUND_BITMAP_NAME, &local_err);
-+ if (!background_bitmap) {
-+ error_setg(errp, "%s - creating background bitmap for backup access failed: %s",
-+ di->device_name,
-+ local_err ? error_get_pretty(local_err) : "unknown error");
-+ bdrv_drained_end(di->bs);
-+ break;
-+ }
-+ di->background_bitmap = background_bitmap;
-+ bdrv_disable_dirty_bitmap(di->bitmap);
-+ }
-+
- if (setup_snapshot_access(di, &local_err) < 0) {
- bdrv_drained_end(di->bs);
- error_setg(errp, "%s - setting up snapshot access failed: %s", di->device_name,
-@@ -935,7 +1017,7 @@ static void backup_state_set_target_id(const char *target_id) {
-
- BackupAccessInfoList *coroutine_fn qmp_backup_access_setup(
- const char *target_id,
-- const char *devlist,
-+ BackupAccessSourceDeviceList *devices,
- Error **errp)
- {
- assert(qemu_in_coroutine());
-@@ -954,12 +1036,17 @@ BackupAccessInfoList *coroutine_fn qmp_backup_access_setup(
- }
-
- bdrv_graph_co_rdlock();
-- di_list = get_device_info(devlist, fleecing_all, &local_err);
-- bdrv_graph_co_rdunlock();
-- if (local_err) {
-- error_propagate(errp, local_err);
-- goto err;
-+ for (BackupAccessSourceDeviceList *it = devices; it; it = it->next) {
-+ PVEBackupDevInfo *di = get_single_device_info(it->value->device, fleecing_all, &local_err);
-+ if (!di) {
-+ bdrv_graph_co_rdunlock();
-+ error_propagate(errp, local_err);
-+ goto err;
-+ }
-+ di->requested_bitmap_name = g_strdup(it->value->bitmap_name);
-+ di_list = g_list_append(di_list, di);
- }
-+ bdrv_graph_co_rdunlock();
- assert(di_list);
-
- size_t total = 0;
-@@ -986,6 +1073,78 @@ BackupAccessInfoList *coroutine_fn qmp_backup_access_setup(
- /* clear previous backup's bitmap_list */
- clear_backup_state_bitmap_list();
-
-+ if (!backup_state.backup_access_bitmaps) {
-+ backup_state.backup_access_bitmaps =
-+ g_hash_table_new_full(g_str_hash, g_str_equal, free, free);
-+ }
-+
-+ /* create bitmaps if requested */
-+ l = di_list;
-+ while (l) {
-+ PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
-+ l = g_list_next(l);
-+
-+ di->block_size = PROXMOX_BACKUP_DEFAULT_CHUNK_SIZE;
-+
-+ PBSBitmapAction action = PBS_BITMAP_ACTION_NOT_USED;
-+ size_t dirty = di->size;
-+
-+ const char *old_bitmap_name =
-+ (const char*)g_hash_table_lookup(backup_state.backup_access_bitmaps, target_id);
-+
-+ bool same_bitmap_name = old_bitmap_name
-+ && di->requested_bitmap_name
-+ && strcmp(di->requested_bitmap_name, old_bitmap_name) == 0;
-+
-+ if (old_bitmap_name && !same_bitmap_name) {
-+ BdrvDirtyBitmap *old_bitmap = bdrv_find_dirty_bitmap(di->bs, old_bitmap_name);
-+ if (!old_bitmap) {
-+ warn_report("setup backup access: expected old bitmap '%s' not found for drive "
-+ "'%s'", old_bitmap_name, di->device_name);
-+ } else {
-+ g_hash_table_remove(backup_state.backup_access_bitmaps, target_id);
-+ bdrv_release_dirty_bitmap(old_bitmap);
-+ action = PBS_BITMAP_ACTION_NOT_USED_REMOVED;
-+ }
-+ }
-+
-+ BdrvDirtyBitmap *bitmap = NULL;
-+ if (di->requested_bitmap_name) {
-+ bitmap = bdrv_find_dirty_bitmap(di->bs, di->requested_bitmap_name);
-+ if (!bitmap) {
-+ bitmap = bdrv_create_dirty_bitmap(di->bs, PROXMOX_BACKUP_DEFAULT_CHUNK_SIZE,
-+ di->requested_bitmap_name, errp);
-+ if (!bitmap) {
-+ qemu_mutex_unlock(&backup_state.stat.lock);
-+ goto err;
-+ }
-+ bdrv_set_dirty_bitmap(bitmap, 0, di->size);
-+ action = PBS_BITMAP_ACTION_NEW;
-+ } else {
-+ /* track clean chunks as reused */
-+ dirty = MIN(bdrv_get_dirty_count(bitmap), di->size);
-+ backup_state.stat.reused += di->size - dirty;
-+ action = PBS_BITMAP_ACTION_USED;
-+ }
-+
-+ if (!same_bitmap_name) {
-+ g_hash_table_insert(backup_state.backup_access_bitmaps,
-+ strdup(target_id), strdup(di->requested_bitmap_name));
-+ }
-+
-+ }
-+
-+ PBSBitmapInfo *info = g_malloc(sizeof(*info));
-+ info->drive = g_strdup(di->device_name);
-+ info->action = action;
-+ info->size = di->size;
-+ info->dirty = dirty;
-+ backup_state.stat.bitmap_list = g_list_append(backup_state.stat.bitmap_list, info);
-+
-+ di->bitmap = bitmap;
-+ di->bitmap_action = action;
-+ }
-+
- /* starting=false, because there is no associated QEMU job */
- initialize_backup_state_stat(NULL, NULL, total, false);
-
-@@ -1029,6 +1188,12 @@ BackupAccessInfoList *coroutine_fn qmp_backup_access_setup(
- info->value->node_name = g_strdup(bdrv_get_node_name(di->fleecing.snapshot_access));
- info->value->device = g_strdup(di->device_name);
- info->value->size = di->size;
-+ if (di->requested_bitmap_name) {
-+ info->value->bitmap_node_name = g_strdup(bdrv_get_node_name(di->bs));
-+ info->value->bitmap_name = g_strdup(di->requested_bitmap_name);
-+ info->value->bitmap_action = di->bitmap_action;
-+ info->value->has_bitmap_action = true;
-+ }
-
- *p_bai_next = info;
- p_bai_next = &info->next;
-@@ -1043,6 +1208,8 @@ err:
- PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
- l = g_list_next(l);
-
-+ handle_backup_access_bitmaps_in_error_case(di);
-+
- g_free(di->device_name);
- di->device_name = NULL;
-
-@@ -1058,7 +1225,7 @@ err:
- /*
- * Caller needs to hold the backup mutex or the BQL.
- */
--void backup_access_teardown(void)
-+void backup_access_teardown(bool success)
- {
- GList *l = backup_state.di_list;
-
-@@ -1079,9 +1246,18 @@ void backup_access_teardown(void)
- di->fleecing.cbw = NULL;
- }
-
-+ if (success) {
-+ handle_backup_access_bitmaps_after_success(di);
-+ } else {
-+ handle_backup_access_bitmaps_in_error_case(di);
-+ }
-+
- g_free(di->device_name);
- di->device_name = NULL;
-
-+ g_free(di->requested_bitmap_name);
-+ di->requested_bitmap_name = NULL;
-+
- g_free(di);
- }
- g_list_free(backup_state.di_list);
-@@ -1099,13 +1275,13 @@ static void backup_access_teardown_bh(void *opaque)
- {
- CoCtxData *data = (CoCtxData*)opaque;
-
-- backup_access_teardown();
-+ backup_access_teardown(*((bool*)data->data));
-
- /* return */
- aio_co_enter(data->ctx, data->co);
- }
-
--void coroutine_fn qmp_backup_access_teardown(const char *target_id, Error **errp)
-+void coroutine_fn qmp_backup_access_teardown(const char *target_id, bool success, Error **errp)
- {
- assert(qemu_in_coroutine());
-
-@@ -1135,6 +1311,7 @@ void coroutine_fn qmp_backup_access_teardown(const char *target_id, Error **errp
- CoCtxData waker = {
- .co = qemu_coroutine_self(),
- .ctx = qemu_get_current_aio_context(),
-+ .data = &success,
- };
- aio_bh_schedule_oneshot(waker.ctx, backup_access_teardown_bh, &waker);
- qemu_coroutine_yield();
-@@ -1335,6 +1512,7 @@ UuidInfo coroutine_fn *qmp_backup(
- }
-
- di->dev_id = dev_id;
-+ di->bitmap_action = action;
-
- PBSBitmapInfo *info = g_malloc(sizeof(*info));
- info->drive = g_strdup(di->device_name);
-diff --git a/pve-backup.h b/pve-backup.h
-index 4033bc848f..9ebeef7c8f 100644
---- a/pve-backup.h
-+++ b/pve-backup.h
-@@ -11,6 +11,6 @@
- #ifndef PVE_BACKUP_H
- #define PVE_BACKUP_H
-
--void backup_access_teardown(void);
-+void backup_access_teardown(bool success);
-
- #endif /* PVE_BACKUP_H */
-diff --git a/qapi/block-core.json b/qapi/block-core.json
-index 8d499650a8..61307ed1d7 100644
---- a/qapi/block-core.json
-+++ b/qapi/block-core.json
-@@ -1118,9 +1118,33 @@
- #
- # @size: the size of the block device in bytes.
- #
-+# @bitmap-node-name: the block node name the dirty bitmap is associated to.
-+#
-+# @bitmap-name: the name of the dirty bitmap associated to the backup access.
-+#
-+# @bitmap-action: the action taken on the dirty bitmap.
-+#
- ##
- { 'struct': 'BackupAccessInfo',
-- 'data': { 'node-name': 'str', 'device': 'str', 'size': 'size' } }
-+ 'data': { 'node-name': 'str', 'device': 'str', 'size': 'size',
-+ '*bitmap-node-name': 'str', '*bitmap-name': 'str',
-+ '*bitmap-action': 'PBSBitmapAction' } }
-+
-+##
-+# @BackupAccessSourceDevice:
-+#
-+# Source block device information for creating a backup access.
-+#
-+# @device: the block device name.
-+#
-+# @bitmap-name: use/create a bitmap with this name for the device. Re-using the
-+# same name allows for making incremental backups. Check the @bitmap-action
-+# in the result to see if you can actually re-use the bitmap or if it had to
-+# be newly created.
-+#
-+##
-+{ 'struct': 'BackupAccessSourceDevice',
-+ 'data': { 'device': 'str', '*bitmap-name': 'str' } }
-
- ##
- # @backup-access-setup:
-@@ -1130,14 +1154,13 @@
- #
- # @target-id: the unique ID of the backup target.
- #
--# @devlist: list of block device names (separated by ',', ';' or ':'). By
--# default the backup includes all writable block devices.
-+# @devices: list of devices for which to create the backup access.
- #
- # Returns: a list of @BackupAccessInfo, one for each device.
- #
- ##
- { 'command': 'backup-access-setup',
-- 'data': { 'target-id': 'str', '*devlist': 'str' },
-+ 'data': { 'target-id': 'str', 'devices': [ 'BackupAccessSourceDevice' ] },
- 'returns': [ 'BackupAccessInfo' ], 'coroutine': true }
-
- ##
-@@ -1147,8 +1170,11 @@
- #
- # @target-id: the ID of the backup target.
- #
-+# @success: whether the backup done by the external provider was successful.
-+#
- ##
--{ 'command': 'backup-access-teardown', 'data': { 'target-id': 'str' },
-+{ 'command': 'backup-access-teardown',
-+ 'data': { 'target-id': 'str', 'success': 'bool' },
- 'coroutine': true }
-
- ##
-diff --git a/system/runstate.c b/system/runstate.c
-index 73026a3884..cf775213bd 100644
---- a/system/runstate.c
-+++ b/system/runstate.c
-@@ -926,7 +926,7 @@ void qemu_cleanup(int status)
- * The backup access is set up by a QMP command, but is neither owned by a monitor nor
- * associated to a BlockBackend. Need to tear it down manually here.
- */
-- backup_access_teardown();
-+ backup_access_teardown(false);
- job_cancel_sync_all();
- bdrv_close_all();
-
diff --git a/debian/patches/pve/0071-PVE-backup-backup-access-api-indicate-situation-wher.patch b/debian/patches/pve/0071-PVE-backup-backup-access-api-indicate-situation-wher.patch
deleted file mode 100644
index d33d173..0000000
--- a/debian/patches/pve/0071-PVE-backup-backup-access-api-indicate-situation-wher.patch
+++ /dev/null
@@ -1,57 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Fiona Ebner <f.ebner@proxmox.com>
-Date: Thu, 3 Apr 2025 14:30:49 +0200
-Subject: [PATCH] PVE backup: backup-access api: indicate situation where a
- bitmap was recreated
-
-The backup-access api keeps track of what bitmap names got used for
-which devices and thus knows when a bitmap went missing. Propagate
-this information to the QMP user with a new 'missing-recreated'
-variant for the taken bitmap action.
-
-Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
-Reviewed-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
----
- pve-backup.c | 6 +++++-
- qapi/block-core.json | 9 ++++++++-
- 2 files changed, 13 insertions(+), 2 deletions(-)
-
-diff --git a/pve-backup.c b/pve-backup.c
-index bd4d5e2579..788647a22d 100644
---- a/pve-backup.c
-+++ b/pve-backup.c
-@@ -1119,7 +1119,11 @@ BackupAccessInfoList *coroutine_fn qmp_backup_access_setup(
- goto err;
- }
- bdrv_set_dirty_bitmap(bitmap, 0, di->size);
-- action = PBS_BITMAP_ACTION_NEW;
-+ if (same_bitmap_name) {
-+ action = PBS_BITMAP_ACTION_MISSING_RECREATED;
-+ } else {
-+ action = PBS_BITMAP_ACTION_NEW;
-+ }
- } else {
- /* track clean chunks as reused */
- dirty = MIN(bdrv_get_dirty_count(bitmap), di->size);
-diff --git a/qapi/block-core.json b/qapi/block-core.json
-index 61307ed1d7..d94c856160 100644
---- a/qapi/block-core.json
-+++ b/qapi/block-core.json
-@@ -1071,9 +1071,16 @@
- # base snapshot did not match the base given for the current job or
- # the crypt mode has changed.
- #
-+# @missing-recreated: A bitmap for incremental backup was expected to be
-+# present, but was missing and thus got recreated. For example, this can
-+# happen if the drive was re-attached or if the bitmap was deleted for some
-+# other reason. PBS does not currently keep track of this; the backup-access
-+# mechanism does.
-+#
- ##
- { 'enum': 'PBSBitmapAction',
-- 'data': ['not-used', 'not-used-removed', 'new', 'used', 'invalid'] }
-+ 'data': ['not-used', 'not-used-removed', 'new', 'used', 'invalid',
-+ 'missing-recreated'] }
-
- ##
- # @PBSBitmapInfo:
diff --git a/debian/patches/pve/0072-PVE-backup-backup-access-api-explicit-bitmap-mode-pa.patch b/debian/patches/pve/0072-PVE-backup-backup-access-api-explicit-bitmap-mode-pa.patch
deleted file mode 100644
index 5d38ad2..0000000
--- a/debian/patches/pve/0072-PVE-backup-backup-access-api-explicit-bitmap-mode-pa.patch
+++ /dev/null
@@ -1,84 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Wolfgang Bumiller <w.bumiller@proxmox.com>
-Date: Thu, 3 Apr 2025 14:30:50 +0200
-Subject: [PATCH] PVE backup: backup-access-api: explicit bitmap-mode parameter
-
-This allows to explicitly request to re-create a bitmap under the same
-name.
-
-Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
- [TL: fix trailing whitespace error]
-Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
----
- pve-backup.c | 17 ++++++++++++++++-
- qapi/block-core.json | 20 +++++++++++++++++++-
- 2 files changed, 35 insertions(+), 2 deletions(-)
-
-diff --git a/pve-backup.c b/pve-backup.c
-index 788647a22d..f657aba68d 100644
---- a/pve-backup.c
-+++ b/pve-backup.c
-@@ -1043,7 +1043,16 @@ BackupAccessInfoList *coroutine_fn qmp_backup_access_setup(
- error_propagate(errp, local_err);
- goto err;
- }
-- di->requested_bitmap_name = g_strdup(it->value->bitmap_name);
-+ if (it->value->bitmap_mode == BACKUP_ACCESS_SETUP_BITMAP_MODE_NONE) {
-+ di->bitmap_action = PBS_BITMAP_ACTION_NOT_USED;
-+ } else {
-+ di->requested_bitmap_name = g_strdup(it->value->bitmap_name);
-+ if (it->value->bitmap_mode == BACKUP_ACCESS_SETUP_BITMAP_MODE_NEW) {
-+ di->bitmap_action = PBS_BITMAP_ACTION_NEW;
-+ } else if (it->value->bitmap_mode == BACKUP_ACCESS_SETUP_BITMAP_MODE_USE) {
-+ di->bitmap_action = PBS_BITMAP_ACTION_USED;
-+ }
-+ }
- di_list = g_list_append(di_list, di);
- }
- bdrv_graph_co_rdunlock();
-@@ -1096,6 +1105,12 @@ BackupAccessInfoList *coroutine_fn qmp_backup_access_setup(
- && di->requested_bitmap_name
- && strcmp(di->requested_bitmap_name, old_bitmap_name) == 0;
-
-+ /* special case: if we explicitly requested a *new* bitmap, treat an
-+ * existing bitmap as having a different name */
-+ if (di->bitmap_action == PBS_BITMAP_ACTION_NEW) {
-+ same_bitmap_name = false;
-+ }
-+
- if (old_bitmap_name && !same_bitmap_name) {
- BdrvDirtyBitmap *old_bitmap = bdrv_find_dirty_bitmap(di->bs, old_bitmap_name);
- if (!old_bitmap) {
-diff --git a/qapi/block-core.json b/qapi/block-core.json
-index d94c856160..cde92071a1 100644
---- a/qapi/block-core.json
-+++ b/qapi/block-core.json
-@@ -1149,9 +1149,27 @@
- # in the result to see if you can actually re-use the bitmap or if it had to
- # be newly created.
- #
-+# @bitmap-mode: used to control whether the bitmap should be reused or
-+# recreated.
-+#
- ##
- { 'struct': 'BackupAccessSourceDevice',
-- 'data': { 'device': 'str', '*bitmap-name': 'str' } }
-+ 'data': { 'device': 'str', '*bitmap-name': 'str',
-+ '*bitmap-mode': 'BackupAccessSetupBitmapMode' } }
-+
-+##
-+# @BackupAccessSetupBitmapMode:
-+#
-+# How to setup a bitmap for a device for @backup-access-setup.
-+#
-+# @none: do not use a bitmap. Removes an existing bitmap if present.
-+#
-+# @new: create and use a new bitmap.
-+#
-+# @use: try to re-use an existing bitmap. Create a new one if it doesn't exist.
-+##
-+{ 'enum': 'BackupAccessSetupBitmapMode',
-+ 'data': ['none', 'new', 'use' ] }
-
- ##
- # @backup-access-setup:
diff --git a/debian/patches/pve/0073-PVE-backup-backup-access-api-simplify-bitmap-logic.patch b/debian/patches/pve/0073-PVE-backup-backup-access-api-simplify-bitmap-logic.patch
deleted file mode 100644
index 1074469..0000000
--- a/debian/patches/pve/0073-PVE-backup-backup-access-api-simplify-bitmap-logic.patch
+++ /dev/null
@@ -1,206 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Fiona Ebner <f.ebner@proxmox.com>
-Date: Fri, 4 Apr 2025 15:31:36 +0200
-Subject: [PATCH] PVE backup: backup-access api: simplify bitmap logic
-
-Currently, only one bitmap name per target is planned to be used.
-Simply use the target ID itself as the bitmap name. This allows to
-simplify the logic quite a bit and there also is no need for the
-backup_access_bitmaps hash table anymore.
-
-For the return value, the bitmap names are still passed along for
-convenience in the caller.
-
-Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
-Tested-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
-Reviewed-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
----
- pve-backup.c | 72 ++++++++++++--------------------------------
- qapi/block-core.json | 15 ++++-----
- 2 files changed, 26 insertions(+), 61 deletions(-)
-
-diff --git a/pve-backup.c b/pve-backup.c
-index f657aba68d..0450303017 100644
---- a/pve-backup.c
-+++ b/pve-backup.c
-@@ -74,7 +74,6 @@ static struct PVEBackupState {
- CoMutex backup_mutex;
- CoMutex dump_callback_mutex;
- char *target_id;
-- GHashTable *backup_access_bitmaps; // key=target_id, value=bitmap_name
- } backup_state;
-
- static void pvebackup_init(void)
-@@ -106,7 +105,7 @@ typedef struct PVEBackupDevInfo {
- PBSBitmapAction bitmap_action;
- BlockDriverState *target;
- BlockJob *job;
-- char *requested_bitmap_name; // used by external backup access during initialization
-+ BackupAccessSetupBitmapMode requested_bitmap_mode;
- } PVEBackupDevInfo;
-
- static void pvebackup_propagate_error(Error *err)
-@@ -1043,16 +1042,7 @@ BackupAccessInfoList *coroutine_fn qmp_backup_access_setup(
- error_propagate(errp, local_err);
- goto err;
- }
-- if (it->value->bitmap_mode == BACKUP_ACCESS_SETUP_BITMAP_MODE_NONE) {
-- di->bitmap_action = PBS_BITMAP_ACTION_NOT_USED;
-- } else {
-- di->requested_bitmap_name = g_strdup(it->value->bitmap_name);
-- if (it->value->bitmap_mode == BACKUP_ACCESS_SETUP_BITMAP_MODE_NEW) {
-- di->bitmap_action = PBS_BITMAP_ACTION_NEW;
-- } else if (it->value->bitmap_mode == BACKUP_ACCESS_SETUP_BITMAP_MODE_USE) {
-- di->bitmap_action = PBS_BITMAP_ACTION_USED;
-- }
-- }
-+ di->requested_bitmap_mode = it->value->bitmap_mode;
- di_list = g_list_append(di_list, di);
- }
- bdrv_graph_co_rdunlock();
-@@ -1082,10 +1072,7 @@ BackupAccessInfoList *coroutine_fn qmp_backup_access_setup(
- /* clear previous backup's bitmap_list */
- clear_backup_state_bitmap_list();
-
-- if (!backup_state.backup_access_bitmaps) {
-- backup_state.backup_access_bitmaps =
-- g_hash_table_new_full(g_str_hash, g_str_equal, free, free);
-- }
-+ const char *bitmap_name = target_id;
-
- /* create bitmaps if requested */
- l = di_list;
-@@ -1098,59 +1085,43 @@ BackupAccessInfoList *coroutine_fn qmp_backup_access_setup(
- PBSBitmapAction action = PBS_BITMAP_ACTION_NOT_USED;
- size_t dirty = di->size;
-
-- const char *old_bitmap_name =
-- (const char*)g_hash_table_lookup(backup_state.backup_access_bitmaps, target_id);
--
-- bool same_bitmap_name = old_bitmap_name
-- && di->requested_bitmap_name
-- && strcmp(di->requested_bitmap_name, old_bitmap_name) == 0;
--
-- /* special case: if we explicitly requested a *new* bitmap, treat an
-- * existing bitmap as having a different name */
-- if (di->bitmap_action == PBS_BITMAP_ACTION_NEW) {
-- same_bitmap_name = false;
-- }
--
-- if (old_bitmap_name && !same_bitmap_name) {
-- BdrvDirtyBitmap *old_bitmap = bdrv_find_dirty_bitmap(di->bs, old_bitmap_name);
-- if (!old_bitmap) {
-- warn_report("setup backup access: expected old bitmap '%s' not found for drive "
-- "'%s'", old_bitmap_name, di->device_name);
-- } else {
-- g_hash_table_remove(backup_state.backup_access_bitmaps, target_id);
-+ if (di->requested_bitmap_mode == BACKUP_ACCESS_SETUP_BITMAP_MODE_NONE ||
-+ di->requested_bitmap_mode == BACKUP_ACCESS_SETUP_BITMAP_MODE_NEW) {
-+ BdrvDirtyBitmap *old_bitmap = bdrv_find_dirty_bitmap(di->bs, bitmap_name);
-+ if (old_bitmap) {
- bdrv_release_dirty_bitmap(old_bitmap);
-- action = PBS_BITMAP_ACTION_NOT_USED_REMOVED;
-+ action = PBS_BITMAP_ACTION_NOT_USED_REMOVED; // set below for new
- }
- }
-
- BdrvDirtyBitmap *bitmap = NULL;
-- if (di->requested_bitmap_name) {
-- bitmap = bdrv_find_dirty_bitmap(di->bs, di->requested_bitmap_name);
-+ if (di->requested_bitmap_mode == BACKUP_ACCESS_SETUP_BITMAP_MODE_NEW ||
-+ di->requested_bitmap_mode == BACKUP_ACCESS_SETUP_BITMAP_MODE_USE) {
-+ bitmap = bdrv_find_dirty_bitmap(di->bs, bitmap_name);
- if (!bitmap) {
- bitmap = bdrv_create_dirty_bitmap(di->bs, PROXMOX_BACKUP_DEFAULT_CHUNK_SIZE,
-- di->requested_bitmap_name, errp);
-+ bitmap_name, errp);
- if (!bitmap) {
- qemu_mutex_unlock(&backup_state.stat.lock);
- goto err;
- }
- bdrv_set_dirty_bitmap(bitmap, 0, di->size);
-- if (same_bitmap_name) {
-+ if (di->requested_bitmap_mode == BACKUP_ACCESS_SETUP_BITMAP_MODE_USE) {
- action = PBS_BITMAP_ACTION_MISSING_RECREATED;
- } else {
- action = PBS_BITMAP_ACTION_NEW;
- }
- } else {
-+ if (di->requested_bitmap_mode == BACKUP_ACCESS_SETUP_BITMAP_MODE_NEW) {
-+ qemu_mutex_unlock(&backup_state.stat.lock);
-+ error_setg(errp, "internal error - removed old bitmap still present");
-+ goto err;
-+ }
- /* track clean chunks as reused */
- dirty = MIN(bdrv_get_dirty_count(bitmap), di->size);
- backup_state.stat.reused += di->size - dirty;
- action = PBS_BITMAP_ACTION_USED;
- }
--
-- if (!same_bitmap_name) {
-- g_hash_table_insert(backup_state.backup_access_bitmaps,
-- strdup(target_id), strdup(di->requested_bitmap_name));
-- }
--
- }
-
- PBSBitmapInfo *info = g_malloc(sizeof(*info));
-@@ -1207,9 +1178,9 @@ BackupAccessInfoList *coroutine_fn qmp_backup_access_setup(
- info->value->node_name = g_strdup(bdrv_get_node_name(di->fleecing.snapshot_access));
- info->value->device = g_strdup(di->device_name);
- info->value->size = di->size;
-- if (di->requested_bitmap_name) {
-+ if (di->bitmap) {
- info->value->bitmap_node_name = g_strdup(bdrv_get_node_name(di->bs));
-- info->value->bitmap_name = g_strdup(di->requested_bitmap_name);
-+ info->value->bitmap_name = g_strdup(bitmap_name);
- info->value->bitmap_action = di->bitmap_action;
- info->value->has_bitmap_action = true;
- }
-@@ -1274,9 +1245,6 @@ void backup_access_teardown(bool success)
- g_free(di->device_name);
- di->device_name = NULL;
-
-- g_free(di->requested_bitmap_name);
-- di->requested_bitmap_name = NULL;
--
- g_free(di);
- }
- g_list_free(backup_state.di_list);
-diff --git a/qapi/block-core.json b/qapi/block-core.json
-index cde92071a1..2fb51215f2 100644
---- a/qapi/block-core.json
-+++ b/qapi/block-core.json
-@@ -1144,18 +1144,12 @@
- #
- # @device: the block device name.
- #
--# @bitmap-name: use/create a bitmap with this name for the device. Re-using the
--# same name allows for making incremental backups. Check the @bitmap-action
--# in the result to see if you can actually re-use the bitmap or if it had to
--# be newly created.
--#
- # @bitmap-mode: used to control whether the bitmap should be reused or
--# recreated.
-+# recreated or not used. Default is not using a bitmap.
- #
- ##
- { 'struct': 'BackupAccessSourceDevice',
-- 'data': { 'device': 'str', '*bitmap-name': 'str',
-- '*bitmap-mode': 'BackupAccessSetupBitmapMode' } }
-+ 'data': { 'device': 'str', '*bitmap-mode': 'BackupAccessSetupBitmapMode' } }
-
- ##
- # @BackupAccessSetupBitmapMode:
-@@ -1179,7 +1173,10 @@
- #
- # @target-id: the unique ID of the backup target.
- #
--# @devices: list of devices for which to create the backup access.
-+# @devices: list of devices for which to create the backup access. Also
-+# controls whether to use/create a bitmap for the device. Check the
-+# @bitmap-action in the result to see what action was actually taken for the
-+# bitmap. Each target controls its own bitmaps.
- #
- # Returns: a list of @BackupAccessInfo, one for each device.
- #
diff --git a/debian/patches/series b/debian/patches/series
index fd151eb..88c3144 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -47,35 +47,17 @@ pve/0038-block-add-alloc-track-driver.patch
pve/0039-Revert-block-rbd-workaround-for-ceph-issue-53784.patch
pve/0040-Revert-block-rbd-fix-handling-of-holes-in-.bdrv_co_b.patch
pve/0041-Revert-block-rbd-implement-bdrv_co_block_status.patch
-pve/0042-alloc-track-error-out-when-auto-remove-is-not-set.patch
-pve/0043-alloc-track-avoid-seemingly-superfluous-child-permis.patch
-pve/0044-PVE-backup-add-fleecing-option.patch
-pve/0045-PVE-backup-improve-error-when-copy-before-write-fail.patch
-pve/0046-PVE-backup-fixup-error-handling-for-fleecing.patch
-pve/0047-PVE-backup-factor-out-setting-up-snapshot-access-for.patch
-pve/0048-PVE-backup-save-device-name-in-device-info-structure.patch
-pve/0049-PVE-backup-include-device-name-in-error-when-setting.patch
-pve/0050-adapt-machine-version-deprecation-for-Proxmox-VE.patch
-pve/0051-Revert-hpet-avoid-timer-storms-on-periodic-timers.patch
-pve/0052-Revert-hpet-store-full-64-bit-target-value-of-the-co.patch
-pve/0053-Revert-hpet-accept-64-bit-reads-and-writes.patch
-pve/0054-Revert-hpet-place-read-only-bits-directly-in-new_val.patch
-pve/0055-Revert-hpet-remove-unnecessary-variable-index.patch
-pve/0056-Revert-hpet-ignore-high-bits-of-comparator-in-32-bit.patch
-pve/0057-Revert-hpet-fix-and-cleanup-persistence-of-interrupt.patch
-pve/0058-savevm-async-improve-setting-state-of-snapshot-opera.patch
-pve/0059-savevm-async-rename-saved_vm_running-to-vm_needs_sta.patch
-pve/0060-savevm-async-improve-runstate-preservation-cleanup-e.patch
-pve/0061-savevm-async-use-dedicated-iothread-for-state-file.patch
-pve/0062-savevm-async-treat-failure-to-set-iothread-context-a.patch
-pve/0063-PVE-backup-clean-up-directly-in-setup_snapshot_acces.patch
-pve/0064-PVE-backup-factor-out-helper-to-clear-backup-state-s.patch
-pve/0065-PVE-backup-factor-out-helper-to-initialize-backup-st.patch
-pve/0066-PVE-backup-add-target-ID-in-backup-state.patch
-pve/0067-PVE-backup-get-device-info-allow-caller-to-specify-f.patch
-pve/0068-PVE-backup-implement-backup-access-setup-and-teardow.patch
-pve/0069-PVE-backup-factor-out-get_single_device_info-helper.patch
-pve/0070-PVE-backup-implement-bitmap-support-for-external-bac.patch
-pve/0071-PVE-backup-backup-access-api-indicate-situation-wher.patch
-pve/0072-PVE-backup-backup-access-api-explicit-bitmap-mode-pa.patch
-pve/0073-PVE-backup-backup-access-api-simplify-bitmap-logic.patch
+pve/0042-PVE-backup-add-fleecing-option.patch
+pve/0043-adapt-machine-version-deprecation-for-Proxmox-VE.patch
+pve/0044-Revert-hpet-avoid-timer-storms-on-periodic-timers.patch
+pve/0045-Revert-hpet-store-full-64-bit-target-value-of-the-co.patch
+pve/0046-Revert-hpet-accept-64-bit-reads-and-writes.patch
+pve/0047-Revert-hpet-place-read-only-bits-directly-in-new_val.patch
+pve/0048-Revert-hpet-remove-unnecessary-variable-index.patch
+pve/0049-Revert-hpet-ignore-high-bits-of-comparator-in-32-bit.patch
+pve/0050-Revert-hpet-fix-and-cleanup-persistence-of-interrupt.patch
+pve/0051-PVE-backup-factor-out-helper-to-clear-backup-state-s.patch
+pve/0052-PVE-backup-factor-out-helper-to-initialize-backup-st.patch
+pve/0053-PVE-backup-add-target-ID-in-backup-state.patch
+pve/0054-PVE-backup-get-device-info-allow-caller-to-specify-f.patch
+pve/0055-PVE-backup-implement-backup-access-setup-and-teardow.patch
--
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] 4+ messages in thread
* [pve-devel] applied: [PATCH-SERIES qemu 0/2] update submodule and patches to QEMU 10.0.2
2025-06-02 10:22 [pve-devel] [PATCH-SERIES qemu 0/2] update submodule and patches to QEMU 10.0.2 Fiona Ebner
2025-06-02 10:22 ` [pve-devel] [PATCH qemu 1/2] " Fiona Ebner
2025-06-02 10:22 ` [pve-devel] [PATCH qemu 2/2] squash some related patches Fiona Ebner
@ 2025-06-17 6:48 ` Thomas Lamprecht
2 siblings, 0 replies; 4+ messages in thread
From: Thomas Lamprecht @ 2025-06-17 6:48 UTC (permalink / raw)
To: pve-devel, Fiona Ebner
On Mon, 02 Jun 2025 12:22:25 +0200, Fiona Ebner wrote:
> Only minor changes this time:
>
> Adapt to changed include paths:
> 32cad1ffb8 ("include: Rename sysemu/ -> system/")
> 407bc4bf90 ("qapi: Move include/qapi/qmp/ to include/qobject/")
>
> Adapt to a function signature change:
> 4822128693 ("migration: Drop inactivate_disk param in
> qemu_savevm_state_complete*")
>
> [...]
Applied, thanks!
[1/2] update submodule and patches to QEMU 10.0.2
commit: b73923535f7ba06aab1f0f87368e89cda49d36d4
[2/2] squash some related patches
commit: bd931f0f04f7739e1b0173b8109804034f92365f
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-06-17 6:48 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-06-02 10:22 [pve-devel] [PATCH-SERIES qemu 0/2] update submodule and patches to QEMU 10.0.2 Fiona Ebner
2025-06-02 10:22 ` [pve-devel] [PATCH qemu 1/2] " Fiona Ebner
2025-06-02 10:22 ` [pve-devel] [PATCH qemu 2/2] squash some related patches Fiona Ebner
2025-06-17 6:48 ` [pve-devel] applied: [PATCH-SERIES qemu 0/2] update submodule and patches to QEMU 10.0.2 Thomas Lamprecht
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