27199bd753
This is necessary for multi-disk backups where not all jobs are immediately started after they are created. QEMU commit 06e0a9c16405c0a4c1eca33cf286cc04c42066a2 did already part of the work, ensuring that new writes after job creation don't pass through to the backup, but not yet for the MIRROR_SYNC_MODE_BITMAP case which is used for PBS. Signed-off-by: Fabian Ebner <f.ebner@proxmox.com> Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
220 lines
7.7 KiB
Diff
220 lines
7.7 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Dietmar Maurer <dietmar@proxmox.com>
|
|
Date: Thu, 9 Jul 2020 12:53:08 +0200
|
|
Subject: [PATCH] PVE: various PBS fixes
|
|
|
|
pbs: fix crypt and compress parameters
|
|
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
|
|
|
PVE: handle PBS write callback with big blocks correctly
|
|
Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
|
|
|
|
PVE: add zero block handling to PBS dump callback
|
|
Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
|
|
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
|
|
---
|
|
block/monitor/block-hmp-cmds.c | 4 ++-
|
|
pve-backup.c | 59 ++++++++++++++++++++++++++--------
|
|
qapi/block-core.json | 6 ++++
|
|
3 files changed, 55 insertions(+), 14 deletions(-)
|
|
|
|
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
|
|
index 3c06734e6d..4481b60a5c 100644
|
|
--- a/block/monitor/block-hmp-cmds.c
|
|
+++ b/block/monitor/block-hmp-cmds.c
|
|
@@ -1042,7 +1042,9 @@ void hmp_backup(Monitor *mon, const QDict *qdict)
|
|
false, NULL, // PBS fingerprint
|
|
false, NULL, // PBS backup-id
|
|
false, 0, // PBS backup-time
|
|
- false, false, // PBS incremental
|
|
+ false, false, // PBS use-dirty-bitmap
|
|
+ false, false, // PBS compress
|
|
+ false, false, // PBS encrypt
|
|
true, dir ? BACKUP_FORMAT_DIR : BACKUP_FORMAT_VMA,
|
|
false, NULL, false, NULL, !!devlist,
|
|
devlist, qdict_haskey(qdict, "speed"), speed, &error);
|
|
diff --git a/pve-backup.c b/pve-backup.c
|
|
index 1c49cd178d..c15abefdda 100644
|
|
--- a/pve-backup.c
|
|
+++ b/pve-backup.c
|
|
@@ -8,6 +8,7 @@
|
|
#include "block/blockjob.h"
|
|
#include "qapi/qapi-commands-block.h"
|
|
#include "qapi/qmp/qerror.h"
|
|
+#include "qemu/cutils.h"
|
|
|
|
/* PVE backup state and related function */
|
|
|
|
@@ -67,6 +68,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];
|
|
@@ -135,10 +137,13 @@ pvebackup_co_dump_pbs_cb(
|
|
PVEBackupDevInfo *di = opaque;
|
|
|
|
assert(backup_state.pbs);
|
|
+ assert(buf);
|
|
|
|
Error *local_err = NULL;
|
|
int pbs_res = -1;
|
|
|
|
+ bool is_zero_block = size == di->block_size && buffer_is_zero(buf, size);
|
|
+
|
|
qemu_co_mutex_lock(&backup_state.dump_callback_mutex);
|
|
|
|
// avoid deadlock if job is cancelled
|
|
@@ -147,16 +152,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);
|
|
+ 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;
|
|
+
|
|
+ pbs_res = proxmox_backup_co_write_data(backup_state.pbs, di->dev_id,
|
|
+ is_zero_block ? NULL : buf + transferred, 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);
|
|
-
|
|
- 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);
|
|
- }
|
|
+ pvebackup_add_transfered_bytes(size, is_zero_block ? size : 0, reused);
|
|
|
|
return size;
|
|
}
|
|
@@ -178,6 +195,7 @@ pvebackup_co_dump_vma_cb(
|
|
int ret = -1;
|
|
|
|
assert(backup_state.vmaw);
|
|
+ assert(buf);
|
|
|
|
uint64_t remaining = size;
|
|
|
|
@@ -204,9 +222,7 @@ pvebackup_co_dump_vma_cb(
|
|
qemu_co_mutex_unlock(&backup_state.dump_callback_mutex);
|
|
|
|
++cluster_num;
|
|
- if (buf) {
|
|
- buf += VMA_CLUSTER_SIZE;
|
|
- }
|
|
+ buf += VMA_CLUSTER_SIZE;
|
|
if (ret < 0) {
|
|
Error *local_err = NULL;
|
|
vma_writer_error_propagate(backup_state.vmaw, &local_err);
|
|
@@ -569,6 +585,10 @@ typedef struct QmpBackupTask {
|
|
const char *firewall_file;
|
|
bool has_devlist;
|
|
const char *devlist;
|
|
+ bool has_compress;
|
|
+ bool compress;
|
|
+ bool has_encrypt;
|
|
+ bool encrypt;
|
|
bool has_speed;
|
|
int64_t speed;
|
|
Error **errp;
|
|
@@ -692,6 +712,7 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque)
|
|
|
|
bool use_dirty_bitmap = task->has_use_dirty_bitmap && task->use_dirty_bitmap;
|
|
|
|
+
|
|
char *pbs_err = NULL;
|
|
pbs = proxmox_backup_new(
|
|
task->backup_file,
|
|
@@ -701,8 +722,10 @@ static void coroutine_fn pvebackup_co_prepare(void *opaque)
|
|
task->has_password ? task->password : NULL,
|
|
task->has_keyfile ? task->keyfile : NULL,
|
|
task->has_key_password ? task->key_password : NULL,
|
|
+ task->has_compress ? task->compress : true,
|
|
+ task->has_encrypt ? task->encrypt : task->has_keyfile,
|
|
task->has_fingerprint ? task->fingerprint : NULL,
|
|
- &pbs_err);
|
|
+ &pbs_err);
|
|
|
|
if (!pbs) {
|
|
error_set(task->errp, ERROR_CLASS_GENERIC_ERROR,
|
|
@@ -721,6 +744,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);
|
|
@@ -941,6 +966,8 @@ UuidInfo *qmp_backup(
|
|
bool has_backup_id, const char *backup_id,
|
|
bool has_backup_time, int64_t backup_time,
|
|
bool has_use_dirty_bitmap, bool use_dirty_bitmap,
|
|
+ bool has_compress, bool compress,
|
|
+ bool has_encrypt, bool encrypt,
|
|
bool has_format, BackupFormat format,
|
|
bool has_config_file, const char *config_file,
|
|
bool has_firewall_file, const char *firewall_file,
|
|
@@ -951,6 +978,8 @@ UuidInfo *qmp_backup(
|
|
.backup_file = backup_file,
|
|
.has_password = has_password,
|
|
.password = password,
|
|
+ .has_keyfile = has_keyfile,
|
|
+ .keyfile = keyfile,
|
|
.has_key_password = has_key_password,
|
|
.key_password = key_password,
|
|
.has_fingerprint = has_fingerprint,
|
|
@@ -961,6 +990,10 @@ UuidInfo *qmp_backup(
|
|
.backup_time = backup_time,
|
|
.has_use_dirty_bitmap = has_use_dirty_bitmap,
|
|
.use_dirty_bitmap = use_dirty_bitmap,
|
|
+ .has_compress = has_compress,
|
|
+ .compress = compress,
|
|
+ .has_encrypt = has_encrypt,
|
|
+ .encrypt = encrypt,
|
|
.has_format = has_format,
|
|
.format = format,
|
|
.has_config_file = has_config_file,
|
|
diff --git a/qapi/block-core.json b/qapi/block-core.json
|
|
index 379a8dd147..88835ebcf6 100644
|
|
--- a/qapi/block-core.json
|
|
+++ b/qapi/block-core.json
|
|
@@ -822,6 +822,10 @@
|
|
#
|
|
# @use-dirty-bitmap: use dirty bitmap to detect incremental changes since last job (optional for format 'pbs')
|
|
#
|
|
+# @compress: use compression (optional for format 'pbs', defaults to true)
|
|
+#
|
|
+# @encrypt: use encryption ((optional for format 'pbs', defaults to true if there is a keyfile)
|
|
+#
|
|
# Returns: the uuid of the backup job
|
|
#
|
|
##
|
|
@@ -833,6 +837,8 @@
|
|
'*backup-id': 'str',
|
|
'*backup-time': 'int',
|
|
'*use-dirty-bitmap': 'bool',
|
|
+ '*compress': 'bool',
|
|
+ '*encrypt': 'bool',
|
|
'*format': 'BackupFormat',
|
|
'*config-file': 'str',
|
|
'*firewall-file': 'str',
|