From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Stefan Reiter 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 --- pve-backup.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/pve-backup.c b/pve-backup.c index cd3a132d8b..f14273645a 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; } @@ -726,6 +738,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);