2020-03-10 17:12:50 +03:00
|
|
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
|
From: Dietmar Maurer <dietmar@proxmox.com>
|
2020-04-07 17:53:19 +03:00
|
|
|
Date: Mon, 6 Apr 2020 12:16:58 +0200
|
|
|
|
Subject: [PATCH] PVE-Backup: add backup-dump block driver
|
2020-03-10 17:12:50 +03:00
|
|
|
|
|
|
|
- add backup-dump block driver block/backup-dump.c
|
|
|
|
- move BackupBlockJob declaration from block/backup.c to include/block/block_int.h
|
|
|
|
- block/backup.c - backup-job-create: also consider source cluster size
|
|
|
|
- job.c: make job_should_pause non-static
|
|
|
|
---
|
|
|
|
block/Makefile.objs | 1 +
|
2020-08-20 11:42:45 +03:00
|
|
|
block/backup-dump.c | 168 ++++++++++++++++++++++++++++++++++++++
|
2020-03-10 17:12:50 +03:00
|
|
|
block/backup.c | 23 ++----
|
|
|
|
include/block/block_int.h | 30 +++++++
|
|
|
|
job.c | 3 +-
|
2020-08-20 11:42:45 +03:00
|
|
|
5 files changed, 206 insertions(+), 19 deletions(-)
|
2020-03-10 17:12:50 +03:00
|
|
|
create mode 100644 block/backup-dump.c
|
|
|
|
|
|
|
|
diff --git a/block/Makefile.objs b/block/Makefile.objs
|
2020-08-20 11:42:45 +03:00
|
|
|
index d1a9227b8f..9ea0477d0b 100644
|
2020-03-10 17:12:50 +03:00
|
|
|
--- a/block/Makefile.objs
|
|
|
|
+++ b/block/Makefile.objs
|
2020-08-20 11:42:45 +03:00
|
|
|
@@ -33,6 +33,7 @@ block-obj-$(CONFIG_CURL) += curl.o
|
|
|
|
block-obj-$(CONFIG_RBD) += rbd.o
|
2020-03-10 17:12:50 +03:00
|
|
|
block-obj-$(CONFIG_GLUSTERFS) += gluster.o
|
|
|
|
block-obj-$(CONFIG_LIBSSH) += ssh.o
|
|
|
|
+block-obj-y += backup-dump.o
|
|
|
|
block-obj-y += accounting.o dirty-bitmap.o
|
|
|
|
block-obj-y += write-threshold.o
|
|
|
|
block-obj-y += backup.o
|
|
|
|
diff --git a/block/backup-dump.c b/block/backup-dump.c
|
|
|
|
new file mode 100644
|
2020-08-20 11:42:45 +03:00
|
|
|
index 0000000000..93d7f46950
|
2020-03-10 17:12:50 +03:00
|
|
|
--- /dev/null
|
|
|
|
+++ b/block/backup-dump.c
|
2020-08-20 11:42:45 +03:00
|
|
|
@@ -0,0 +1,168 @@
|
2020-03-10 17:12:50 +03:00
|
|
|
+/*
|
|
|
|
+ * BlockDriver to send backup data stream to a callback function
|
|
|
|
+ *
|
|
|
|
+ * Copyright (C) 2020 Proxmox Server Solutions GmbH
|
|
|
|
+ *
|
|
|
|
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
|
|
|
|
+ * See the COPYING file in the top-level directory.
|
|
|
|
+ *
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+#include "qemu/osdep.h"
|
|
|
|
+#include "qemu-common.h"
|
|
|
|
+#include "qom/object_interfaces.h"
|
|
|
|
+#include "block/block_int.h"
|
|
|
|
+
|
|
|
|
+typedef struct {
|
|
|
|
+ int dump_cb_block_size;
|
|
|
|
+ uint64_t byte_size;
|
|
|
|
+ BackupDumpFunc *dump_cb;
|
|
|
|
+ void *dump_cb_data;
|
|
|
|
+} BDRVBackupDumpState;
|
|
|
|
+
|
|
|
|
+static int qemu_backup_dump_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
|
|
|
|
+{
|
|
|
|
+ BDRVBackupDumpState *s = bs->opaque;
|
|
|
|
+
|
|
|
|
+ bdi->cluster_size = s->dump_cb_block_size;
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int qemu_backup_dump_check_perm(
|
|
|
|
+ BlockDriverState *bs,
|
|
|
|
+ uint64_t perm,
|
|
|
|
+ uint64_t shared,
|
|
|
|
+ Error **errp)
|
|
|
|
+{
|
|
|
|
+ /* Nothing to do. */
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void qemu_backup_dump_set_perm(
|
|
|
|
+ BlockDriverState *bs,
|
|
|
|
+ uint64_t perm,
|
|
|
|
+ uint64_t shared)
|
|
|
|
+{
|
|
|
|
+ /* Nothing to do. */
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void qemu_backup_dump_abort_perm_update(BlockDriverState *bs)
|
|
|
|
+{
|
|
|
|
+ /* Nothing to do. */
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void qemu_backup_dump_refresh_limits(BlockDriverState *bs, Error **errp)
|
|
|
|
+{
|
|
|
|
+ bs->bl.request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O */
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void qemu_backup_dump_close(BlockDriverState *bs)
|
|
|
|
+{
|
|
|
|
+ /* Nothing to do. */
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int64_t qemu_backup_dump_getlength(BlockDriverState *bs)
|
|
|
|
+{
|
|
|
|
+ BDRVBackupDumpState *s = bs->opaque;
|
|
|
|
+
|
|
|
|
+ return s->byte_size;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static coroutine_fn int qemu_backup_dump_co_writev(
|
|
|
|
+ BlockDriverState *bs,
|
|
|
|
+ int64_t sector_num,
|
|
|
|
+ int nb_sectors,
|
|
|
|
+ QEMUIOVector *qiov,
|
|
|
|
+ int flags)
|
|
|
|
+{
|
|
|
|
+ /* flags can be only values we set in supported_write_flags */
|
|
|
|
+ assert(flags == 0);
|
|
|
|
+
|
|
|
|
+ BDRVBackupDumpState *s = bs->opaque;
|
|
|
|
+ off_t offset = sector_num * BDRV_SECTOR_SIZE;
|
|
|
|
+
|
|
|
|
+ uint64_t written = 0;
|
|
|
|
+
|
|
|
|
+ for (int i = 0; i < qiov->niov; ++i) {
|
|
|
|
+ const struct iovec *v = &qiov->iov[i];
|
|
|
|
+
|
|
|
|
+ int rc = s->dump_cb(s->dump_cb_data, offset, v->iov_len, v->iov_base);
|
|
|
|
+ if (rc < 0) {
|
|
|
|
+ return rc;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (rc != v->iov_len) {
|
|
|
|
+ return -EIO;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ written += v->iov_len;
|
|
|
|
+ offset += v->iov_len;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return written;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void qemu_backup_dump_child_perm(
|
|
|
|
+ BlockDriverState *bs,
|
|
|
|
+ BdrvChild *c,
|
2020-08-20 11:42:45 +03:00
|
|
|
+ BdrvChildRole role,
|
2020-03-10 17:12:50 +03:00
|
|
|
+ BlockReopenQueue *reopen_queue,
|
|
|
|
+ uint64_t perm, uint64_t shared,
|
|
|
|
+ uint64_t *nperm, uint64_t *nshared)
|
|
|
|
+{
|
|
|
|
+ *nperm = BLK_PERM_ALL;
|
|
|
|
+ *nshared = BLK_PERM_ALL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static BlockDriver bdrv_backup_dump_drive = {
|
|
|
|
+ .format_name = "backup-dump-drive",
|
|
|
|
+ .protocol_name = "backup-dump",
|
|
|
|
+ .instance_size = sizeof(BDRVBackupDumpState),
|
|
|
|
+
|
|
|
|
+ .bdrv_close = qemu_backup_dump_close,
|
|
|
|
+ .bdrv_has_zero_init = bdrv_has_zero_init_1,
|
|
|
|
+ .bdrv_getlength = qemu_backup_dump_getlength,
|
|
|
|
+ .bdrv_get_info = qemu_backup_dump_get_info,
|
|
|
|
+
|
|
|
|
+ .bdrv_co_writev = qemu_backup_dump_co_writev,
|
|
|
|
+
|
|
|
|
+ .bdrv_refresh_limits = qemu_backup_dump_refresh_limits,
|
|
|
|
+ .bdrv_check_perm = qemu_backup_dump_check_perm,
|
|
|
|
+ .bdrv_set_perm = qemu_backup_dump_set_perm,
|
|
|
|
+ .bdrv_abort_perm_update = qemu_backup_dump_abort_perm_update,
|
|
|
|
+ .bdrv_child_perm = qemu_backup_dump_child_perm,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static void bdrv_backup_dump_init(void)
|
|
|
|
+{
|
|
|
|
+ bdrv_register(&bdrv_backup_dump_drive);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+block_init(bdrv_backup_dump_init);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+BlockDriverState *bdrv_backup_dump_create(
|
|
|
|
+ int dump_cb_block_size,
|
|
|
|
+ uint64_t byte_size,
|
|
|
|
+ BackupDumpFunc *dump_cb,
|
|
|
|
+ void *dump_cb_data,
|
|
|
|
+ Error **errp)
|
|
|
|
+{
|
|
|
|
+ BDRVBackupDumpState *state;
|
|
|
|
+ BlockDriverState *bs = bdrv_new_open_driver(
|
|
|
|
+ &bdrv_backup_dump_drive, NULL, BDRV_O_RDWR, errp);
|
|
|
|
+
|
|
|
|
+ if (!bs) {
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ bs->total_sectors = byte_size / BDRV_SECTOR_SIZE;
|
|
|
|
+ bs->opaque = state = g_new0(BDRVBackupDumpState, 1);
|
|
|
|
+
|
|
|
|
+ state->dump_cb_block_size = dump_cb_block_size;
|
|
|
|
+ state->byte_size = byte_size;
|
|
|
|
+ state->dump_cb = dump_cb;
|
|
|
|
+ state->dump_cb_data = dump_cb_data;
|
|
|
|
+
|
|
|
|
+ return bs;
|
|
|
|
+}
|
|
|
|
diff --git a/block/backup.c b/block/backup.c
|
2020-08-20 11:42:45 +03:00
|
|
|
index 5f373a4f9b..1bcc7faa32 100644
|
2020-03-10 17:12:50 +03:00
|
|
|
--- a/block/backup.c
|
|
|
|
+++ b/block/backup.c
|
|
|
|
@@ -32,24 +32,6 @@
|
|
|
|
|
|
|
|
#define BACKUP_CLUSTER_SIZE_DEFAULT (1 << 16)
|
|
|
|
|
|
|
|
-typedef struct BackupBlockJob {
|
|
|
|
- BlockJob common;
|
|
|
|
- BlockDriverState *backup_top;
|
|
|
|
- BlockDriverState *source_bs;
|
|
|
|
-
|
|
|
|
- BdrvDirtyBitmap *sync_bitmap;
|
|
|
|
-
|
|
|
|
- MirrorSyncMode sync_mode;
|
|
|
|
- BitmapSyncMode bitmap_mode;
|
|
|
|
- BlockdevOnError on_source_error;
|
|
|
|
- BlockdevOnError on_target_error;
|
|
|
|
- uint64_t len;
|
|
|
|
- uint64_t bytes_read;
|
|
|
|
- int64_t cluster_size;
|
|
|
|
-
|
|
|
|
- BlockCopyState *bcs;
|
|
|
|
-} BackupBlockJob;
|
|
|
|
-
|
|
|
|
static const BlockJobDriver backup_job_driver;
|
|
|
|
|
|
|
|
static void backup_progress_bytes_callback(int64_t bytes, void *opaque)
|
2020-08-20 11:42:45 +03:00
|
|
|
@@ -423,6 +405,11 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
2020-03-10 17:12:50 +03:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ BlockDriverInfo bdi;
|
|
|
|
+ if (bdrv_get_info(bs, &bdi) == 0) {
|
|
|
|
+ cluster_size = MAX(cluster_size, bdi.cluster_size);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
/*
|
|
|
|
* If source is in backing chain of target assume that target is going to be
|
|
|
|
* used for "image fleecing", i.e. it should represent a kind of snapshot of
|
|
|
|
diff --git a/include/block/block_int.h b/include/block/block_int.h
|
2020-08-20 11:42:45 +03:00
|
|
|
index 5094ae1e95..dc72197388 100644
|
2020-03-10 17:12:50 +03:00
|
|
|
--- a/include/block/block_int.h
|
|
|
|
+++ b/include/block/block_int.h
|
2020-08-20 11:42:45 +03:00
|
|
|
@@ -62,6 +62,36 @@
|
2020-03-10 17:12:50 +03:00
|
|
|
|
|
|
|
#define BLOCK_PROBE_BUF_SIZE 512
|
|
|
|
|
|
|
|
+typedef int BackupDumpFunc(void *opaque, uint64_t offset, uint64_t bytes, const void *buf);
|
|
|
|
+
|
|
|
|
+BlockDriverState *bdrv_backuo_dump_create(
|
|
|
|
+ int dump_cb_block_size,
|
|
|
|
+ uint64_t byte_size,
|
|
|
|
+ BackupDumpFunc *dump_cb,
|
|
|
|
+ void *dump_cb_data,
|
|
|
|
+ Error **errp);
|
|
|
|
+
|
|
|
|
+// Needs to be defined here, since it's used in blockdev.c to detect PVE backup
|
|
|
|
+// jobs with source_bs
|
|
|
|
+typedef struct BlockCopyState BlockCopyState;
|
|
|
|
+typedef struct BackupBlockJob {
|
|
|
|
+ BlockJob common;
|
|
|
|
+ BlockDriverState *backup_top;
|
|
|
|
+ BlockDriverState *source_bs;
|
|
|
|
+
|
|
|
|
+ BdrvDirtyBitmap *sync_bitmap;
|
|
|
|
+
|
|
|
|
+ MirrorSyncMode sync_mode;
|
|
|
|
+ BitmapSyncMode bitmap_mode;
|
|
|
|
+ BlockdevOnError on_source_error;
|
|
|
|
+ BlockdevOnError on_target_error;
|
|
|
|
+ uint64_t len;
|
|
|
|
+ uint64_t bytes_read;
|
|
|
|
+ int64_t cluster_size;
|
|
|
|
+
|
|
|
|
+ BlockCopyState *bcs;
|
|
|
|
+} BackupBlockJob;
|
|
|
|
+
|
|
|
|
enum BdrvTrackedRequestType {
|
|
|
|
BDRV_TRACKED_READ,
|
|
|
|
BDRV_TRACKED_WRITE,
|
|
|
|
diff --git a/job.c b/job.c
|
2020-04-07 17:53:19 +03:00
|
|
|
index e82253e041..bcbbb0be02 100644
|
2020-03-10 17:12:50 +03:00
|
|
|
--- a/job.c
|
|
|
|
+++ b/job.c
|
2020-04-07 17:53:19 +03:00
|
|
|
@@ -269,7 +269,8 @@ static bool job_started(Job *job)
|
2020-03-10 17:12:50 +03:00
|
|
|
return job->co;
|
|
|
|
}
|
|
|
|
|
|
|
|
-static bool job_should_pause(Job *job)
|
|
|
|
+bool job_should_pause(Job *job);
|
|
|
|
+bool job_should_pause(Job *job)
|
|
|
|
{
|
|
|
|
return job->pause_count > 0;
|
|
|
|
}
|