f00a720d7e
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
77 lines
2.7 KiB
Diff
77 lines
2.7 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Stefan Reiter <s.reiter@proxmox.com>
|
|
Date: Wed, 19 Aug 2020 12:33:17 +0200
|
|
Subject: [PATCH] PVE: handle PBS write callback with big blocks correctly
|
|
|
|
Under certain conditions QEMU will push more than the given blocksize
|
|
into the callback at once. Handle it like VMA does, by iterating the
|
|
data until all is written.
|
|
|
|
The block size is stored per backup device to be used in the callback.
|
|
This avoids relying on PROXMOX_BACKUP_DEFAULT_CHUNK_SIZE, in case it is
|
|
made configurable in the future.
|
|
|
|
Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
|
|
---
|
|
pve-backup.c | 30 ++++++++++++++++++++++--------
|
|
1 file changed, 22 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/pve-backup.c b/pve-backup.c
|
|
index 77eb475563..40d8136f1a 100644
|
|
--- a/pve-backup.c
|
|
+++ b/pve-backup.c
|
|
@@ -67,6 +67,7 @@ opts_init(pvebackup_init);
|
|
typedef struct PVEBackupDevInfo {
|
|
BlockDriverState *bs;
|
|
size_t size;
|
|
+ uint64_t block_size;
|
|
uint8_t dev_id;
|
|
bool completed;
|
|
char targetfile[PATH_MAX];
|
|
@@ -147,17 +148,28 @@ pvebackup_co_dump_pbs_cb(
|
|
return -1;
|
|
}
|
|
|
|
- pbs_res = proxmox_backup_co_write_data(backup_state.pbs, di->dev_id, buf, start, size, &local_err);
|
|
- qemu_co_mutex_unlock(&backup_state.dump_callback_mutex);
|
|
+ uint64_t transferred = 0;
|
|
+ uint64_t reused = 0;
|
|
+ while (transferred < size) {
|
|
+ uint64_t left = size - transferred;
|
|
+ uint64_t to_transfer = left < di->block_size ? left : di->block_size;
|
|
|
|
- if (pbs_res < 0) {
|
|
- pvebackup_propagate_error(local_err);
|
|
- return pbs_res;
|
|
- } else {
|
|
- size_t reused = (pbs_res == 0) ? size : 0;
|
|
- pvebackup_add_transfered_bytes(size, !buf ? size : 0, reused);
|
|
+ pbs_res = proxmox_backup_co_write_data(backup_state.pbs, di->dev_id,
|
|
+ buf ? buf + transferred : NULL, start + transferred, to_transfer, &local_err);
|
|
+ transferred += to_transfer;
|
|
+
|
|
+ if (pbs_res < 0) {
|
|
+ pvebackup_propagate_error(local_err);
|
|
+ qemu_co_mutex_unlock(&backup_state.dump_callback_mutex);
|
|
+ return pbs_res;
|
|
+ }
|
|
+
|
|
+ reused += pbs_res == 0 ? to_transfer : 0;
|
|
}
|
|
|
|
+ qemu_co_mutex_unlock(&backup_state.dump_callback_mutex);
|
|
+ pvebackup_add_transfered_bytes(size, !buf ? size : 0, reused);
|
|
+
|
|
return size;
|
|
}
|
|
|
|
@@ -730,6 +742,8 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque)
|
|
PVEBackupDevInfo *di = (PVEBackupDevInfo *)l->data;
|
|
l = g_list_next(l);
|
|
|
|
+ di->block_size = dump_cb_block_size;
|
|
+
|
|
const char *devname = bdrv_get_device_name(di->bs);
|
|
|
|
BdrvDirtyBitmap *bitmap = bdrv_find_dirty_bitmap(di->bs, PBS_BITMAP_NAME);
|