]> git.proxmox.com Git - pve-qemu.git/blob - debian/patches/pve/0027-PVE-Backup-add-backup-dump-block-driver.patch
ea3bb8414a232ee06649a0b0d21c102127262797
[pve-qemu.git] / debian / patches / pve / 0027-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 | 168 +++++++++++++++++++++++++++++++
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, 214 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..93d7f46950
24 --- /dev/null
25 +++ b/block/backup-dump.c
26 @@ -0,0 +1,168 @@
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 "qemu-common.h"
39 +#include "qom/object_interfaces.h"
40 +#include "block/block_int.h"
41 +
42 +typedef struct {
43 + int dump_cb_block_size;
44 + uint64_t byte_size;
45 + BackupDumpFunc *dump_cb;
46 + void *dump_cb_data;
47 +} BDRVBackupDumpState;
48 +
49 +static int qemu_backup_dump_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
50 +{
51 + BDRVBackupDumpState *s = bs->opaque;
52 +
53 + bdi->cluster_size = s->dump_cb_block_size;
54 + return 0;
55 +}
56 +
57 +static int qemu_backup_dump_check_perm(
58 + BlockDriverState *bs,
59 + uint64_t perm,
60 + uint64_t shared,
61 + Error **errp)
62 +{
63 + /* Nothing to do. */
64 + return 0;
65 +}
66 +
67 +static void qemu_backup_dump_set_perm(
68 + BlockDriverState *bs,
69 + uint64_t perm,
70 + uint64_t shared)
71 +{
72 + /* Nothing to do. */
73 +}
74 +
75 +static void qemu_backup_dump_abort_perm_update(BlockDriverState *bs)
76 +{
77 + /* Nothing to do. */
78 +}
79 +
80 +static void qemu_backup_dump_refresh_limits(BlockDriverState *bs, Error **errp)
81 +{
82 + bs->bl.request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O */
83 +}
84 +
85 +static void qemu_backup_dump_close(BlockDriverState *bs)
86 +{
87 + /* Nothing to do. */
88 +}
89 +
90 +static int64_t qemu_backup_dump_getlength(BlockDriverState *bs)
91 +{
92 + BDRVBackupDumpState *s = bs->opaque;
93 +
94 + return s->byte_size;
95 +}
96 +
97 +static coroutine_fn int qemu_backup_dump_co_writev(
98 + BlockDriverState *bs,
99 + int64_t sector_num,
100 + int nb_sectors,
101 + QEMUIOVector *qiov,
102 + int flags)
103 +{
104 + /* flags can be only values we set in supported_write_flags */
105 + assert(flags == 0);
106 +
107 + BDRVBackupDumpState *s = bs->opaque;
108 + off_t offset = sector_num * BDRV_SECTOR_SIZE;
109 +
110 + uint64_t written = 0;
111 +
112 + for (int i = 0; i < qiov->niov; ++i) {
113 + const struct iovec *v = &qiov->iov[i];
114 +
115 + int rc = s->dump_cb(s->dump_cb_data, offset, v->iov_len, v->iov_base);
116 + if (rc < 0) {
117 + return rc;
118 + }
119 +
120 + if (rc != v->iov_len) {
121 + return -EIO;
122 + }
123 +
124 + written += v->iov_len;
125 + offset += v->iov_len;
126 + }
127 +
128 + return written;
129 +}
130 +
131 +static void qemu_backup_dump_child_perm(
132 + BlockDriverState *bs,
133 + BdrvChild *c,
134 + BdrvChildRole role,
135 + BlockReopenQueue *reopen_queue,
136 + uint64_t perm, uint64_t shared,
137 + uint64_t *nperm, uint64_t *nshared)
138 +{
139 + *nperm = BLK_PERM_ALL;
140 + *nshared = BLK_PERM_ALL;
141 +}
142 +
143 +static BlockDriver bdrv_backup_dump_drive = {
144 + .format_name = "backup-dump-drive",
145 + .protocol_name = "backup-dump",
146 + .instance_size = sizeof(BDRVBackupDumpState),
147 +
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,
152 +
153 + .bdrv_co_writev = qemu_backup_dump_co_writev,
154 +
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,
160 +};
161 +
162 +static void bdrv_backup_dump_init(void)
163 +{
164 + bdrv_register(&bdrv_backup_dump_drive);
165 +}
166 +
167 +block_init(bdrv_backup_dump_init);
168 +
169 +
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,
175 + Error **errp)
176 +{
177 + BDRVBackupDumpState *state;
178 + BlockDriverState *bs = bdrv_new_open_driver(
179 + &bdrv_backup_dump_drive, NULL, BDRV_O_RDWR, errp);
180 +
181 + if (!bs) {
182 + return NULL;
183 + }
184 +
185 + bs->total_sectors = byte_size / BDRV_SECTOR_SIZE;
186 + bs->opaque = state = g_new0(BDRVBackupDumpState, 1);
187 +
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;
192 +
193 + return bs;
194 +}
195 diff --git a/block/backup.c b/block/backup.c
196 index 07b899035c..7b5d02f580 100644
197 --- a/block/backup.c
198 +++ b/block/backup.c
199 @@ -29,28 +29,6 @@
200
201 #include "block/copy-before-write.h"
202
203 -typedef struct BackupBlockJob {
204 - BlockJob common;
205 - BlockDriverState *cbw;
206 - BlockDriverState *source_bs;
207 - BlockDriverState *target_bs;
208 -
209 - BdrvDirtyBitmap *sync_bitmap;
210 -
211 - MirrorSyncMode sync_mode;
212 - BitmapSyncMode bitmap_mode;
213 - BlockdevOnError on_source_error;
214 - BlockdevOnError on_target_error;
215 - uint64_t len;
216 - int64_t cluster_size;
217 - BackupPerf perf;
218 -
219 - BlockCopyState *bcs;
220 -
221 - bool wait;
222 - BlockCopyCallState *bg_bcs_call;
223 -} BackupBlockJob;
224 -
225 static const BlockJobDriver backup_job_driver;
226
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,
229 }
230
231 cluster_size = block_copy_cluster_size(bcs);
232 + if (cluster_size < 0) {
233 + goto error;
234 + }
235 +
236 + BlockDriverInfo bdi;
237 + if (bdrv_get_info(bs, &bdi) == 0) {
238 + cluster_size = MAX(cluster_size, bdi.cluster_size);
239 + }
240
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(
248 'aio_task.c',
249 'amend.c',
250 'backup.c',
251 + 'backup-dump.c',
252 'copy-before-write.c',
253 'blkdebug.c',
254 'blklogwrites.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
259 @@ -26,6 +26,7 @@
260
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"
267 @@ -64,6 +65,40 @@
268
269 #define BLOCK_PROBE_BUF_SIZE 512
270
271 +typedef int BackupDumpFunc(void *opaque, uint64_t offset, uint64_t bytes, const void *buf);
272 +
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,
278 + Error **errp);
279 +
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 {
284 + BlockJob common;
285 + BlockDriverState *cbw;
286 + BlockDriverState *source_bs;
287 + BlockDriverState *target_bs;
288 +
289 + BdrvDirtyBitmap *sync_bitmap;
290 +
291 + MirrorSyncMode sync_mode;
292 + BitmapSyncMode bitmap_mode;
293 + BlockdevOnError on_source_error;
294 + BlockdevOnError on_target_error;
295 + uint64_t len;
296 + int64_t cluster_size;
297 + BackupPerf perf;
298 +
299 + BlockCopyState *bcs;
300 +
301 + bool wait;
302 + BlockCopyCallState *bg_bcs_call;
303 +} BackupBlockJob;
304 +
305 enum BdrvTrackedRequestType {
306 BDRV_TRACKED_READ,
307 BDRV_TRACKED_WRITE,
308 diff --git a/job.c b/job.c
309 index 075c6f3a20..e5699ad200 100644
310 --- a/job.c
311 +++ b/job.c
312 @@ -276,7 +276,8 @@ static bool job_started(Job *job)
313 return job->co;
314 }
315
316 -static bool job_should_pause(Job *job)
317 +bool job_should_pause(Job *job);
318 +bool job_should_pause(Job *job)
319 {
320 return job->pause_count > 0;
321 }