]> git.proxmox.com Git - pve-qemu.git/blob - debian/patches/pve/0028-PVE-Backup-add-backup-dump-block-driver.patch
548ce20bd3dd3afaecdbce00f47c912ed8db5384
[pve-qemu.git] / debian / patches / pve / 0028-PVE-Backup-add-backup-dump-block-driver.patch
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
5
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
10
11 Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
12 ---
13 block/backup-dump.c | 167 +++++++++++++++++++++++++++++++
14 block/backup.c | 30 ++----
15 block/meson.build | 1 +
16 include/block/block_int-common.h | 35 +++++++
17 job.c | 3 +-
18 5 files changed, 213 insertions(+), 23 deletions(-)
19 create mode 100644 block/backup-dump.c
20
21 diff --git a/block/backup-dump.c b/block/backup-dump.c
22 new file mode 100644
23 index 0000000000..04718a94e2
24 --- /dev/null
25 +++ b/block/backup-dump.c
26 @@ -0,0 +1,167 @@
27 +/*
28 + * BlockDriver to send backup data stream to a callback function
29 + *
30 + * Copyright (C) 2020 Proxmox Server Solutions GmbH
31 + *
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.
34 + *
35 + */
36 +
37 +#include "qemu/osdep.h"
38 +#include "qom/object_interfaces.h"
39 +#include "block/block_int.h"
40 +
41 +typedef struct {
42 + int dump_cb_block_size;
43 + uint64_t byte_size;
44 + BackupDumpFunc *dump_cb;
45 + void *dump_cb_data;
46 +} BDRVBackupDumpState;
47 +
48 +static int qemu_backup_dump_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
49 +{
50 + BDRVBackupDumpState *s = bs->opaque;
51 +
52 + bdi->cluster_size = s->dump_cb_block_size;
53 + return 0;
54 +}
55 +
56 +static int qemu_backup_dump_check_perm(
57 + BlockDriverState *bs,
58 + uint64_t perm,
59 + uint64_t shared,
60 + Error **errp)
61 +{
62 + /* Nothing to do. */
63 + return 0;
64 +}
65 +
66 +static void qemu_backup_dump_set_perm(
67 + BlockDriverState *bs,
68 + uint64_t perm,
69 + uint64_t shared)
70 +{
71 + /* Nothing to do. */
72 +}
73 +
74 +static void qemu_backup_dump_abort_perm_update(BlockDriverState *bs)
75 +{
76 + /* Nothing to do. */
77 +}
78 +
79 +static void qemu_backup_dump_refresh_limits(BlockDriverState *bs, Error **errp)
80 +{
81 + bs->bl.request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O */
82 +}
83 +
84 +static void qemu_backup_dump_close(BlockDriverState *bs)
85 +{
86 + /* Nothing to do. */
87 +}
88 +
89 +static int64_t qemu_backup_dump_getlength(BlockDriverState *bs)
90 +{
91 + BDRVBackupDumpState *s = bs->opaque;
92 +
93 + return s->byte_size;
94 +}
95 +
96 +static coroutine_fn int qemu_backup_dump_co_writev(
97 + BlockDriverState *bs,
98 + int64_t sector_num,
99 + int nb_sectors,
100 + QEMUIOVector *qiov,
101 + int flags)
102 +{
103 + /* flags can be only values we set in supported_write_flags */
104 + assert(flags == 0);
105 +
106 + BDRVBackupDumpState *s = bs->opaque;
107 + off_t offset = sector_num * BDRV_SECTOR_SIZE;
108 +
109 + uint64_t written = 0;
110 +
111 + for (int i = 0; i < qiov->niov; ++i) {
112 + const struct iovec *v = &qiov->iov[i];
113 +
114 + int rc = s->dump_cb(s->dump_cb_data, offset, v->iov_len, v->iov_base);
115 + if (rc < 0) {
116 + return rc;
117 + }
118 +
119 + if (rc != v->iov_len) {
120 + return -EIO;
121 + }
122 +
123 + written += v->iov_len;
124 + offset += v->iov_len;
125 + }
126 +
127 + return written;
128 +}
129 +
130 +static void qemu_backup_dump_child_perm(
131 + BlockDriverState *bs,
132 + BdrvChild *c,
133 + BdrvChildRole role,
134 + BlockReopenQueue *reopen_queue,
135 + uint64_t perm, uint64_t shared,
136 + uint64_t *nperm, uint64_t *nshared)
137 +{
138 + *nperm = BLK_PERM_ALL;
139 + *nshared = BLK_PERM_ALL;
140 +}
141 +
142 +static BlockDriver bdrv_backup_dump_drive = {
143 + .format_name = "backup-dump-drive",
144 + .protocol_name = "backup-dump",
145 + .instance_size = sizeof(BDRVBackupDumpState),
146 +
147 + .bdrv_close = qemu_backup_dump_close,
148 + .bdrv_has_zero_init = bdrv_has_zero_init_1,
149 + .bdrv_getlength = qemu_backup_dump_getlength,
150 + .bdrv_get_info = qemu_backup_dump_get_info,
151 +
152 + .bdrv_co_writev = qemu_backup_dump_co_writev,
153 +
154 + .bdrv_refresh_limits = qemu_backup_dump_refresh_limits,
155 + .bdrv_check_perm = qemu_backup_dump_check_perm,
156 + .bdrv_set_perm = qemu_backup_dump_set_perm,
157 + .bdrv_abort_perm_update = qemu_backup_dump_abort_perm_update,
158 + .bdrv_child_perm = qemu_backup_dump_child_perm,
159 +};
160 +
161 +static void bdrv_backup_dump_init(void)
162 +{
163 + bdrv_register(&bdrv_backup_dump_drive);
164 +}
165 +
166 +block_init(bdrv_backup_dump_init);
167 +
168 +
169 +BlockDriverState *bdrv_backup_dump_create(
170 + int dump_cb_block_size,
171 + uint64_t byte_size,
172 + BackupDumpFunc *dump_cb,
173 + void *dump_cb_data,
174 + Error **errp)
175 +{
176 + BDRVBackupDumpState *state;
177 + BlockDriverState *bs = bdrv_new_open_driver(
178 + &bdrv_backup_dump_drive, NULL, BDRV_O_RDWR, errp);
179 +
180 + if (!bs) {
181 + return NULL;
182 + }
183 +
184 + bs->total_sectors = byte_size / BDRV_SECTOR_SIZE;
185 + bs->opaque = state = g_new0(BDRVBackupDumpState, 1);
186 +
187 + state->dump_cb_block_size = dump_cb_block_size;
188 + state->byte_size = byte_size;
189 + state->dump_cb = dump_cb;
190 + state->dump_cb_data = dump_cb_data;
191 +
192 + return bs;
193 +}
194 diff --git a/block/backup.c b/block/backup.c
195 index b6fa9e8a69..789f8b7799 100644
196 --- a/block/backup.c
197 +++ b/block/backup.c
198 @@ -29,28 +29,6 @@
199
200 #include "block/copy-before-write.h"
201
202 -typedef struct BackupBlockJob {
203 - BlockJob common;
204 - BlockDriverState *cbw;
205 - BlockDriverState *source_bs;
206 - BlockDriverState *target_bs;
207 -
208 - BdrvDirtyBitmap *sync_bitmap;
209 -
210 - MirrorSyncMode sync_mode;
211 - BitmapSyncMode bitmap_mode;
212 - BlockdevOnError on_source_error;
213 - BlockdevOnError on_target_error;
214 - uint64_t len;
215 - int64_t cluster_size;
216 - BackupPerf perf;
217 -
218 - BlockCopyState *bcs;
219 -
220 - bool wait;
221 - BlockCopyCallState *bg_bcs_call;
222 -} BackupBlockJob;
223 -
224 static const BlockJobDriver backup_job_driver;
225
226 static void backup_cleanup_sync_bitmap(BackupBlockJob *job, int ret)
227 @@ -454,6 +432,14 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
228 }
229
230 cluster_size = block_copy_cluster_size(bcs);
231 + if (cluster_size < 0) {
232 + goto error;
233 + }
234 +
235 + BlockDriverInfo bdi;
236 + if (bdrv_get_info(bs, &bdi) == 0) {
237 + cluster_size = MAX(cluster_size, bdi.cluster_size);
238 + }
239
240 if (perf->max_chunk && perf->max_chunk < cluster_size) {
241 error_setg(errp, "Required max-chunk (%" PRIi64 ") is less than backup "
242 diff --git a/block/meson.build b/block/meson.build
243 index 3a0b84bc11..7f22e7f177 100644
244 --- a/block/meson.build
245 +++ b/block/meson.build
246 @@ -4,6 +4,7 @@ block_ss.add(files(
247 'aio_task.c',
248 'amend.c',
249 'backup.c',
250 + 'backup-dump.c',
251 'copy-before-write.c',
252 'blkdebug.c',
253 'blklogwrites.c',
254 diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
255 index 8947abab76..f272d0d8dc 100644
256 --- a/include/block/block_int-common.h
257 +++ b/include/block/block_int-common.h
258 @@ -26,6 +26,7 @@
259
260 #include "block/accounting.h"
261 #include "block/block.h"
262 +#include "block/block-copy.h"
263 #include "block/aio-wait.h"
264 #include "qemu/queue.h"
265 #include "qemu/coroutine.h"
266 @@ -64,6 +65,40 @@
267
268 #define BLOCK_PROBE_BUF_SIZE 512
269
270 +typedef int BackupDumpFunc(void *opaque, uint64_t offset, uint64_t bytes, const void *buf);
271 +
272 +BlockDriverState *bdrv_backup_dump_create(
273 + int dump_cb_block_size,
274 + uint64_t byte_size,
275 + BackupDumpFunc *dump_cb,
276 + void *dump_cb_data,
277 + Error **errp);
278 +
279 +// Needs to be defined here, since it's used in blockdev.c to detect PVE backup
280 +// jobs with source_bs
281 +typedef struct BlockCopyState BlockCopyState;
282 +typedef struct BackupBlockJob {
283 + BlockJob common;
284 + BlockDriverState *cbw;
285 + BlockDriverState *source_bs;
286 + BlockDriverState *target_bs;
287 +
288 + BdrvDirtyBitmap *sync_bitmap;
289 +
290 + MirrorSyncMode sync_mode;
291 + BitmapSyncMode bitmap_mode;
292 + BlockdevOnError on_source_error;
293 + BlockdevOnError on_target_error;
294 + uint64_t len;
295 + int64_t cluster_size;
296 + BackupPerf perf;
297 +
298 + BlockCopyState *bcs;
299 +
300 + bool wait;
301 + BlockCopyCallState *bg_bcs_call;
302 +} BackupBlockJob;
303 +
304 enum BdrvTrackedRequestType {
305 BDRV_TRACKED_READ,
306 BDRV_TRACKED_WRITE,
307 diff --git a/job.c b/job.c
308 index 075c6f3a20..e5699ad200 100644
309 --- a/job.c
310 +++ b/job.c
311 @@ -276,7 +276,8 @@ static bool job_started(Job *job)
312 return job->co;
313 }
314
315 -static bool job_should_pause(Job *job)
316 +bool job_should_pause(Job *job);
317 +bool job_should_pause(Job *job)
318 {
319 return job->pause_count > 0;
320 }