1 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 From: Stefan Reiter <s.reiter@proxmox.com>
3 Date: Wed, 19 Aug 2020 12:33:17 +0200
4 Subject: [PATCH] PVE: handle PBS write callback with big blocks correctly
6 Under certain conditions QEMU will push more than the given blocksize
7 into the callback at once. Handle it like VMA does, by iterating the
8 data until all is written.
10 The block size is stored per backup device to be used in the callback.
11 This avoids relying on PROXMOX_BACKUP_DEFAULT_CHUNK_SIZE, in case it is
12 made configurable in the future.
14 Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
16 pve-backup.c | 30 ++++++++++++++++++++++--------
17 1 file changed, 22 insertions(+), 8 deletions(-)
19 diff --git a/pve-backup.c b/pve-backup.c
20 index cd3a132d8b..f14273645a 100644
23 @@ -67,6 +67,7 @@ opts_init(pvebackup_init);
24 typedef struct PVEBackupDevInfo {
27 + uint64_t block_size;
30 char targetfile[PATH_MAX];
31 @@ -147,17 +148,28 @@ pvebackup_co_dump_pbs_cb(
35 - pbs_res = proxmox_backup_co_write_data(backup_state.pbs, di->dev_id, buf, start, size, &local_err);
36 - qemu_co_mutex_unlock(&backup_state.dump_callback_mutex);
37 + uint64_t transferred = 0;
38 + uint64_t reused = 0;
39 + while (transferred < size) {
40 + uint64_t left = size - transferred;
41 + uint64_t to_transfer = left < di->block_size ? left : di->block_size;
44 - pvebackup_propagate_error(local_err);
47 - size_t reused = (pbs_res == 0) ? size : 0;
48 - pvebackup_add_transfered_bytes(size, !buf ? size : 0, reused);
49 + pbs_res = proxmox_backup_co_write_data(backup_state.pbs, di->dev_id,
50 + buf ? buf + transferred : NULL, start + transferred, to_transfer, &local_err);
51 + transferred += to_transfer;
54 + pvebackup_propagate_error(local_err);
55 + qemu_co_mutex_unlock(&backup_state.dump_callback_mutex);
59 + reused += pbs_res == 0 ? to_transfer : 0;
62 + qemu_co_mutex_unlock(&backup_state.dump_callback_mutex);
63 + pvebackup_add_transfered_bytes(size, !buf ? size : 0, reused);
68 @@ -726,6 +738,8 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque)
69 PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
72 + di->block_size = dump_cb_block_size;
74 const char *devname = bdrv_get_device_name(di->bs);
76 BdrvDirtyBitmap *bitmap = bdrv_find_dirty_bitmap(di->bs, PBS_BITMAP_NAME);