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>
12 [FE: adapt to coroutine changes]
13 Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
15 block/backup-dump.c | 168 +++++++++++++++++++++++++++++++
16 block/backup.c | 30 ++----
17 block/meson.build | 1 +
18 include/block/block_int-common.h | 35 +++++++
20 5 files changed, 214 insertions(+), 23 deletions(-)
21 create mode 100644 block/backup-dump.c
23 diff --git a/block/backup-dump.c b/block/backup-dump.c
25 index 0000000000..232a094426
27 +++ b/block/backup-dump.c
30 + * BlockDriver to send backup data stream to a callback function
32 + * Copyright (C) 2020 Proxmox Server Solutions GmbH
34 + * This work is licensed under the terms of the GNU GPL, version 2 or later.
35 + * See the COPYING file in the top-level directory.
39 +#include "qemu/osdep.h"
40 +#include "qom/object_interfaces.h"
41 +#include "block/block_int.h"
44 + int dump_cb_block_size;
46 + BackupDumpFunc *dump_cb;
48 +} BDRVBackupDumpState;
50 +static coroutine_fn int qemu_backup_dump_co_get_info(BlockDriverState *bs,
51 + BlockDriverInfo *bdi)
53 + BDRVBackupDumpState *s = bs->opaque;
55 + bdi->cluster_size = s->dump_cb_block_size;
59 +static int qemu_backup_dump_check_perm(
60 + BlockDriverState *bs,
65 + /* Nothing to do. */
69 +static void qemu_backup_dump_set_perm(
70 + BlockDriverState *bs,
74 + /* Nothing to do. */
77 +static void qemu_backup_dump_abort_perm_update(BlockDriverState *bs)
79 + /* Nothing to do. */
82 +static void qemu_backup_dump_refresh_limits(BlockDriverState *bs, Error **errp)
84 + bs->bl.request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O */
87 +static void qemu_backup_dump_close(BlockDriverState *bs)
89 + /* Nothing to do. */
92 +static coroutine_fn int64_t qemu_backup_dump_co_getlength(BlockDriverState *bs)
94 + BDRVBackupDumpState *s = bs->opaque;
96 + return s->byte_size;
99 +static coroutine_fn int qemu_backup_dump_co_writev(
100 + BlockDriverState *bs,
101 + int64_t sector_num,
103 + QEMUIOVector *qiov,
106 + /* flags can be only values we set in supported_write_flags */
107 + assert(flags == 0);
109 + BDRVBackupDumpState *s = bs->opaque;
110 + off_t offset = sector_num * BDRV_SECTOR_SIZE;
112 + uint64_t written = 0;
114 + for (int i = 0; i < qiov->niov; ++i) {
115 + const struct iovec *v = &qiov->iov[i];
117 + int rc = s->dump_cb(s->dump_cb_data, offset, v->iov_len, v->iov_base);
122 + if (rc != v->iov_len) {
126 + written += v->iov_len;
127 + offset += v->iov_len;
133 +static void qemu_backup_dump_child_perm(
134 + BlockDriverState *bs,
136 + BdrvChildRole role,
137 + BlockReopenQueue *reopen_queue,
138 + uint64_t perm, uint64_t shared,
139 + uint64_t *nperm, uint64_t *nshared)
141 + *nperm = BLK_PERM_ALL;
142 + *nshared = BLK_PERM_ALL;
145 +static BlockDriver bdrv_backup_dump_drive = {
146 + .format_name = "backup-dump-drive",
147 + .protocol_name = "backup-dump",
148 + .instance_size = sizeof(BDRVBackupDumpState),
150 + .bdrv_close = qemu_backup_dump_close,
151 + .bdrv_has_zero_init = bdrv_has_zero_init_1,
152 + .bdrv_co_getlength = qemu_backup_dump_co_getlength,
153 + .bdrv_co_get_info = qemu_backup_dump_co_get_info,
155 + .bdrv_co_writev = qemu_backup_dump_co_writev,
157 + .bdrv_refresh_limits = qemu_backup_dump_refresh_limits,
158 + .bdrv_check_perm = qemu_backup_dump_check_perm,
159 + .bdrv_set_perm = qemu_backup_dump_set_perm,
160 + .bdrv_abort_perm_update = qemu_backup_dump_abort_perm_update,
161 + .bdrv_child_perm = qemu_backup_dump_child_perm,
164 +static void bdrv_backup_dump_init(void)
166 + bdrv_register(&bdrv_backup_dump_drive);
169 +block_init(bdrv_backup_dump_init);
172 +BlockDriverState *bdrv_backup_dump_create(
173 + int dump_cb_block_size,
174 + uint64_t byte_size,
175 + BackupDumpFunc *dump_cb,
176 + void *dump_cb_data,
179 + BDRVBackupDumpState *state;
180 + BlockDriverState *bs = bdrv_new_open_driver(
181 + &bdrv_backup_dump_drive, NULL, BDRV_O_RDWR, errp);
187 + bs->total_sectors = byte_size / BDRV_SECTOR_SIZE;
188 + bs->opaque = state = g_new0(BDRVBackupDumpState, 1);
190 + state->dump_cb_block_size = dump_cb_block_size;
191 + state->byte_size = byte_size;
192 + state->dump_cb = dump_cb;
193 + state->dump_cb_data = dump_cb_data;
197 diff --git a/block/backup.c b/block/backup.c
198 index 39410dcf8d..af87fa6aa9 100644
203 #include "block/copy-before-write.h"
205 -typedef struct BackupBlockJob {
207 - BlockDriverState *cbw;
208 - BlockDriverState *source_bs;
209 - BlockDriverState *target_bs;
211 - BdrvDirtyBitmap *sync_bitmap;
213 - MirrorSyncMode sync_mode;
214 - BitmapSyncMode bitmap_mode;
215 - BlockdevOnError on_source_error;
216 - BlockdevOnError on_target_error;
218 - int64_t cluster_size;
221 - BlockCopyState *bcs;
224 - BlockCopyCallState *bg_bcs_call;
227 static const BlockJobDriver backup_job_driver;
229 static void backup_cleanup_sync_bitmap(BackupBlockJob *job, int ret)
230 @@ -457,6 +435,14 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
233 cluster_size = block_copy_cluster_size(bcs);
234 + if (cluster_size < 0) {
238 + BlockDriverInfo bdi;
239 + if (bdrv_get_info(bs, &bdi) == 0) {
240 + cluster_size = MAX(cluster_size, bdi.cluster_size);
243 if (perf->max_chunk && perf->max_chunk < cluster_size) {
244 error_setg(errp, "Required max-chunk (%" PRIi64 ") is less than backup "
245 diff --git a/block/meson.build b/block/meson.build
246 index 744b698a82..f580f95395 100644
247 --- a/block/meson.build
248 +++ b/block/meson.build
249 @@ -4,6 +4,7 @@ block_ss.add(files(
254 'copy-before-write.c',
257 diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
258 index f01bb8b617..d7ffd1826e 100644
259 --- a/include/block/block_int-common.h
260 +++ b/include/block/block_int-common.h
263 #include "block/aio.h"
264 #include "block/block-common.h"
265 +#include "block/block-copy.h"
266 #include "block/block-global-state.h"
267 #include "block/snapshot.h"
268 #include "qemu/iov.h"
271 #define BLOCK_PROBE_BUF_SIZE 512
273 +typedef int BackupDumpFunc(void *opaque, uint64_t offset, uint64_t bytes, const void *buf);
275 +BlockDriverState *bdrv_backup_dump_create(
276 + int dump_cb_block_size,
277 + uint64_t byte_size,
278 + BackupDumpFunc *dump_cb,
279 + void *dump_cb_data,
282 +// Needs to be defined here, since it's used in blockdev.c to detect PVE backup
283 +// jobs with source_bs
284 +typedef struct BlockCopyState BlockCopyState;
285 +typedef struct BackupBlockJob {
287 + BlockDriverState *cbw;
288 + BlockDriverState *source_bs;
289 + BlockDriverState *target_bs;
291 + BdrvDirtyBitmap *sync_bitmap;
293 + MirrorSyncMode sync_mode;
294 + BitmapSyncMode bitmap_mode;
295 + BlockdevOnError on_source_error;
296 + BlockdevOnError on_target_error;
298 + int64_t cluster_size;
301 + BlockCopyState *bcs;
304 + BlockCopyCallState *bg_bcs_call;
307 enum BdrvTrackedRequestType {
310 diff --git a/job.c b/job.c
311 index 72d57f0934..93e22d180b 100644
314 @@ -330,7 +330,8 @@ static bool job_started_locked(Job *job)
317 /* Called with job_mutex held. */
318 -static bool job_should_pause_locked(Job *job)
319 +bool job_should_pause_locked(Job *job);
320 +bool job_should_pause_locked(Job *job)
322 return job->pause_count > 0;