1 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 From: Dietmar Maurer <dietmar@proxmox.com>
3 Date: Mon, 6 Apr 2020 12:16:58 +0200
4 Subject: [PATCH] PVE-Backup: add backup-dump block driver
6 - add backup-dump block driver block/backup-dump.c
7 - move BackupBlockJob declaration from block/backup.c to include/block/block_int.h
8 - block/backup.c - backup-job-create: also consider source cluster size
9 - job.c: make job_should_pause non-static
11 Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
13 block/backup-dump.c | 168 +++++++++++++++++++++++++++++++
14 block/backup.c | 30 ++----
15 block/meson.build | 1 +
16 include/block/block_int-common.h | 35 +++++++
18 5 files changed, 214 insertions(+), 23 deletions(-)
19 create mode 100644 block/backup-dump.c
21 diff --git a/block/backup-dump.c b/block/backup-dump.c
23 index 0000000000..93d7f46950
25 +++ b/block/backup-dump.c
28 + * BlockDriver to send backup data stream to a callback function
30 + * Copyright (C) 2020 Proxmox Server Solutions GmbH
32 + * This work is licensed under the terms of the GNU GPL, version 2 or later.
33 + * See the COPYING file in the top-level directory.
37 +#include "qemu/osdep.h"
38 +#include "qemu-common.h"
39 +#include "qom/object_interfaces.h"
40 +#include "block/block_int.h"
43 + int dump_cb_block_size;
45 + BackupDumpFunc *dump_cb;
47 +} BDRVBackupDumpState;
49 +static int qemu_backup_dump_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
51 + BDRVBackupDumpState *s = bs->opaque;
53 + bdi->cluster_size = s->dump_cb_block_size;
57 +static int qemu_backup_dump_check_perm(
58 + BlockDriverState *bs,
63 + /* Nothing to do. */
67 +static void qemu_backup_dump_set_perm(
68 + BlockDriverState *bs,
72 + /* Nothing to do. */
75 +static void qemu_backup_dump_abort_perm_update(BlockDriverState *bs)
77 + /* Nothing to do. */
80 +static void qemu_backup_dump_refresh_limits(BlockDriverState *bs, Error **errp)
82 + bs->bl.request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O */
85 +static void qemu_backup_dump_close(BlockDriverState *bs)
87 + /* Nothing to do. */
90 +static int64_t qemu_backup_dump_getlength(BlockDriverState *bs)
92 + BDRVBackupDumpState *s = bs->opaque;
94 + return s->byte_size;
97 +static coroutine_fn int qemu_backup_dump_co_writev(
98 + BlockDriverState *bs,
101 + QEMUIOVector *qiov,
104 + /* flags can be only values we set in supported_write_flags */
105 + assert(flags == 0);
107 + BDRVBackupDumpState *s = bs->opaque;
108 + off_t offset = sector_num * BDRV_SECTOR_SIZE;
110 + uint64_t written = 0;
112 + for (int i = 0; i < qiov->niov; ++i) {
113 + const struct iovec *v = &qiov->iov[i];
115 + int rc = s->dump_cb(s->dump_cb_data, offset, v->iov_len, v->iov_base);
120 + if (rc != v->iov_len) {
124 + written += v->iov_len;
125 + offset += v->iov_len;
131 +static void qemu_backup_dump_child_perm(
132 + BlockDriverState *bs,
134 + BdrvChildRole role,
135 + BlockReopenQueue *reopen_queue,
136 + uint64_t perm, uint64_t shared,
137 + uint64_t *nperm, uint64_t *nshared)
139 + *nperm = BLK_PERM_ALL;
140 + *nshared = BLK_PERM_ALL;
143 +static BlockDriver bdrv_backup_dump_drive = {
144 + .format_name = "backup-dump-drive",
145 + .protocol_name = "backup-dump",
146 + .instance_size = sizeof(BDRVBackupDumpState),
148 + .bdrv_close = qemu_backup_dump_close,
149 + .bdrv_has_zero_init = bdrv_has_zero_init_1,
150 + .bdrv_getlength = qemu_backup_dump_getlength,
151 + .bdrv_get_info = qemu_backup_dump_get_info,
153 + .bdrv_co_writev = qemu_backup_dump_co_writev,
155 + .bdrv_refresh_limits = qemu_backup_dump_refresh_limits,
156 + .bdrv_check_perm = qemu_backup_dump_check_perm,
157 + .bdrv_set_perm = qemu_backup_dump_set_perm,
158 + .bdrv_abort_perm_update = qemu_backup_dump_abort_perm_update,
159 + .bdrv_child_perm = qemu_backup_dump_child_perm,
162 +static void bdrv_backup_dump_init(void)
164 + bdrv_register(&bdrv_backup_dump_drive);
167 +block_init(bdrv_backup_dump_init);
170 +BlockDriverState *bdrv_backup_dump_create(
171 + int dump_cb_block_size,
172 + uint64_t byte_size,
173 + BackupDumpFunc *dump_cb,
174 + void *dump_cb_data,
177 + BDRVBackupDumpState *state;
178 + BlockDriverState *bs = bdrv_new_open_driver(
179 + &bdrv_backup_dump_drive, NULL, BDRV_O_RDWR, errp);
185 + bs->total_sectors = byte_size / BDRV_SECTOR_SIZE;
186 + bs->opaque = state = g_new0(BDRVBackupDumpState, 1);
188 + state->dump_cb_block_size = dump_cb_block_size;
189 + state->byte_size = byte_size;
190 + state->dump_cb = dump_cb;
191 + state->dump_cb_data = dump_cb_data;
195 diff --git a/block/backup.c b/block/backup.c
196 index 07b899035c..7b5d02f580 100644
201 #include "block/copy-before-write.h"
203 -typedef struct BackupBlockJob {
205 - BlockDriverState *cbw;
206 - BlockDriverState *source_bs;
207 - BlockDriverState *target_bs;
209 - BdrvDirtyBitmap *sync_bitmap;
211 - MirrorSyncMode sync_mode;
212 - BitmapSyncMode bitmap_mode;
213 - BlockdevOnError on_source_error;
214 - BlockdevOnError on_target_error;
216 - int64_t cluster_size;
219 - BlockCopyState *bcs;
222 - BlockCopyCallState *bg_bcs_call;
225 static const BlockJobDriver backup_job_driver;
227 static void backup_cleanup_sync_bitmap(BackupBlockJob *job, int ret)
228 @@ -456,6 +434,14 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
231 cluster_size = block_copy_cluster_size(bcs);
232 + if (cluster_size < 0) {
236 + BlockDriverInfo bdi;
237 + if (bdrv_get_info(bs, &bdi) == 0) {
238 + cluster_size = MAX(cluster_size, bdi.cluster_size);
241 if (perf->max_chunk && perf->max_chunk < cluster_size) {
242 error_setg(errp, "Required max-chunk (%" PRIi64 ") is less than backup "
243 diff --git a/block/meson.build b/block/meson.build
244 index 819eb80951..067708b7c0 100644
245 --- a/block/meson.build
246 +++ b/block/meson.build
247 @@ -4,6 +4,7 @@ block_ss.add(files(
252 'copy-before-write.c',
255 diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
256 index 8947abab76..f272d0d8dc 100644
257 --- a/include/block/block_int-common.h
258 +++ b/include/block/block_int-common.h
261 #include "block/accounting.h"
262 #include "block/block.h"
263 +#include "block/block-copy.h"
264 #include "block/aio-wait.h"
265 #include "qemu/queue.h"
266 #include "qemu/coroutine.h"
269 #define BLOCK_PROBE_BUF_SIZE 512
271 +typedef int BackupDumpFunc(void *opaque, uint64_t offset, uint64_t bytes, const void *buf);
273 +BlockDriverState *bdrv_backup_dump_create(
274 + int dump_cb_block_size,
275 + uint64_t byte_size,
276 + BackupDumpFunc *dump_cb,
277 + void *dump_cb_data,
280 +// Needs to be defined here, since it's used in blockdev.c to detect PVE backup
281 +// jobs with source_bs
282 +typedef struct BlockCopyState BlockCopyState;
283 +typedef struct BackupBlockJob {
285 + BlockDriverState *cbw;
286 + BlockDriverState *source_bs;
287 + BlockDriverState *target_bs;
289 + BdrvDirtyBitmap *sync_bitmap;
291 + MirrorSyncMode sync_mode;
292 + BitmapSyncMode bitmap_mode;
293 + BlockdevOnError on_source_error;
294 + BlockdevOnError on_target_error;
296 + int64_t cluster_size;
299 + BlockCopyState *bcs;
302 + BlockCopyCallState *bg_bcs_call;
305 enum BdrvTrackedRequestType {
308 diff --git a/job.c b/job.c
309 index 075c6f3a20..e5699ad200 100644
312 @@ -276,7 +276,8 @@ static bool job_started(Job *job)
316 -static bool job_should_pause(Job *job)
317 +bool job_should_pause(Job *job);
318 +bool job_should_pause(Job *job)
320 return job->pause_count > 0;