]> git.proxmox.com Git - pve-qemu-kvm.git/blob - debian/patches/pve/0033-block-add-the-zeroinit-block-driver-filter.patch
fix backup jobs for multiple disks
[pve-qemu-kvm.git] / debian / patches / pve / 0033-block-add-the-zeroinit-block-driver-filter.patch
1 From 35facc3a3549baf4cccaef27afa9c35a25abe91c Mon Sep 17 00:00:00 2001
2 From: Wolfgang Bumiller <w.bumiller@proxmox.com>
3 Date: Thu, 17 Mar 2016 11:33:37 +0100
4 Subject: [PATCH 33/47] block: add the zeroinit block driver filter
5
6 ---
7 block/Makefile.objs | 1 +
8 block/zeroinit.c | 219 ++++++++++++++++++++++++++++++++++++++++++++++++++++
9 2 files changed, 220 insertions(+)
10 create mode 100644 block/zeroinit.c
11
12 diff --git a/block/Makefile.objs b/block/Makefile.objs
13 index de96f8e..8cdac08 100644
14 --- a/block/Makefile.objs
15 +++ b/block/Makefile.objs
16 @@ -4,6 +4,7 @@ block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o
17 block-obj-y += qed-check.o
18 block-obj-y += vhdx.o vhdx-endian.o vhdx-log.o
19 block-obj-y += quorum.o
20 +block-obj-y += zeroinit.o
21 block-obj-y += parallels.o blkdebug.o blkverify.o blkreplay.o
22 block-obj-y += block-backend.o snapshot.o qapi.o
23 block-obj-$(CONFIG_WIN32) += file-win32.o win32-aio.o
24 diff --git a/block/zeroinit.c b/block/zeroinit.c
25 new file mode 100644
26 index 0000000..0a8c7f9
27 --- /dev/null
28 +++ b/block/zeroinit.c
29 @@ -0,0 +1,219 @@
30 +/*
31 + * Filter to fake a zero-initialized block device.
32 + *
33 + * Copyright (c) 2016 Wolfgang Bumiller <w.bumiller@proxmox.com>
34 + * Copyright (c) 2016 Proxmox Server Solutions GmbH
35 + *
36 + * This work is licensed under the terms of the GNU GPL, version 2 or later.
37 + * See the COPYING file in the top-level directory.
38 + */
39 +
40 +#include "qemu/osdep.h"
41 +#include "qapi/error.h"
42 +#include "block/block_int.h"
43 +#include "qapi/qmp/qdict.h"
44 +#include "qapi/qmp/qstring.h"
45 +#include "qemu/cutils.h"
46 +
47 +typedef struct {
48 + bool has_zero_init;
49 + int64_t extents;
50 +} BDRVZeroinitState;
51 +
52 +/* Valid blkverify filenames look like blkverify:path/to/raw_image:path/to/image */
53 +static void zeroinit_parse_filename(const char *filename, QDict *options,
54 + Error **errp)
55 +{
56 + QString *raw_path;
57 +
58 + /* Parse the blkverify: prefix */
59 + if (!strstart(filename, "zeroinit:", &filename)) {
60 + /* There was no prefix; therefore, all options have to be already
61 + present in the QDict (except for the filename) */
62 + return;
63 + }
64 +
65 + raw_path = qstring_from_str(filename);
66 + qdict_put(options, "x-next", raw_path);
67 +}
68 +
69 +static QemuOptsList runtime_opts = {
70 + .name = "zeroinit",
71 + .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
72 + .desc = {
73 + {
74 + .name = "x-next",
75 + .type = QEMU_OPT_STRING,
76 + .help = "[internal use only, will be removed]",
77 + },
78 + {
79 + .name = "x-zeroinit",
80 + .type = QEMU_OPT_BOOL,
81 + .help = "set has_initialized_zero flag",
82 + },
83 + { /* end of list */ }
84 + },
85 +};
86 +
87 +static int zeroinit_open(BlockDriverState *bs, QDict *options, int flags,
88 + Error **errp)
89 +{
90 + BDRVZeroinitState *s = bs->opaque;
91 + QemuOpts *opts;
92 + Error *local_err = NULL;
93 + int ret;
94 +
95 + s->extents = 0;
96 +
97 + opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
98 + qemu_opts_absorb_qdict(opts, options, &local_err);
99 + if (local_err) {
100 + error_propagate(errp, local_err);
101 + ret = -EINVAL;
102 + goto fail;
103 + }
104 +
105 + /* Open the raw file */
106 + bs->file = bdrv_open_child(qemu_opt_get(opts, "x-next"), options, "next",
107 + bs, &child_file, false, &local_err);
108 + if (local_err) {
109 + ret = -EINVAL;
110 + error_propagate(errp, local_err);
111 + goto fail;
112 + }
113 +
114 + /* set the options */
115 + s->has_zero_init = qemu_opt_get_bool(opts, "x-zeroinit", true);
116 +
117 + ret = 0;
118 +fail:
119 + if (ret < 0) {
120 + bdrv_unref_child(bs, bs->file);
121 + }
122 + qemu_opts_del(opts);
123 + return ret;
124 +}
125 +
126 +static void zeroinit_close(BlockDriverState *bs)
127 +{
128 + BDRVZeroinitState *s = bs->opaque;
129 + (void)s;
130 +}
131 +
132 +static int64_t zeroinit_getlength(BlockDriverState *bs)
133 +{
134 + return bdrv_getlength(bs->file->bs);
135 +}
136 +
137 +static BlockAIOCB *zeroinit_aio_readv(BlockDriverState *bs,
138 + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
139 + BlockCompletionFunc *cb, void *opaque)
140 +{
141 + return bdrv_aio_readv(bs->file, sector_num, qiov, nb_sectors,
142 + cb, opaque);
143 +}
144 +
145 +static int coroutine_fn zeroinit_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
146 + int count, BdrvRequestFlags flags)
147 +{
148 + BDRVZeroinitState *s = bs->opaque;
149 + if (offset >= s->extents)
150 + return 0;
151 + return bdrv_pwrite_zeroes(bs->file, offset, count, flags);
152 +}
153 +
154 +static BlockAIOCB *zeroinit_aio_writev(BlockDriverState *bs,
155 + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
156 + BlockCompletionFunc *cb, void *opaque)
157 +{
158 + BDRVZeroinitState *s = bs->opaque;
159 + int64_t extents = (sector_num << BDRV_SECTOR_BITS) + ((nb_sectors + 1) << BDRV_SECTOR_BITS);
160 + if (extents > s->extents)
161 + s->extents = extents;
162 + return bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors,
163 + cb, opaque);
164 +}
165 +
166 +static BlockAIOCB *zeroinit_aio_flush(BlockDriverState *bs,
167 + BlockCompletionFunc *cb,
168 + void *opaque)
169 +{
170 + return bdrv_aio_flush(bs->file->bs, cb, opaque);
171 +}
172 +
173 +static bool zeroinit_recurse_is_first_non_filter(BlockDriverState *bs,
174 + BlockDriverState *candidate)
175 +{
176 + return bdrv_recurse_is_first_non_filter(bs->file->bs, candidate);
177 +}
178 +
179 +static coroutine_fn int zeroinit_co_flush(BlockDriverState *bs)
180 +{
181 + return bdrv_co_flush(bs->file->bs);
182 +}
183 +
184 +static int zeroinit_has_zero_init(BlockDriverState *bs)
185 +{
186 + BDRVZeroinitState *s = bs->opaque;
187 + return s->has_zero_init;
188 +}
189 +
190 +static int64_t coroutine_fn zeroinit_co_get_block_status(BlockDriverState *bs,
191 + int64_t sector_num,
192 + int nb_sectors, int *pnum,
193 + BlockDriverState **file)
194 +{
195 + return bdrv_get_block_status(bs->file->bs, sector_num, nb_sectors, pnum, file);
196 +}
197 +
198 +static int coroutine_fn zeroinit_co_pdiscard(BlockDriverState *bs,
199 + int64_t offset, int count)
200 +{
201 + return bdrv_co_pdiscard(bs->file->bs, offset, count);
202 +}
203 +
204 +static int zeroinit_truncate(BlockDriverState *bs, int64_t offset)
205 +{
206 + return bdrv_truncate(bs->file, offset);
207 +}
208 +
209 +static int zeroinit_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
210 +{
211 + return bdrv_get_info(bs->file->bs, bdi);
212 +}
213 +
214 +static BlockDriver bdrv_zeroinit = {
215 + .format_name = "zeroinit",
216 + .protocol_name = "zeroinit",
217 + .instance_size = sizeof(BDRVZeroinitState),
218 +
219 + .bdrv_parse_filename = zeroinit_parse_filename,
220 + .bdrv_file_open = zeroinit_open,
221 + .bdrv_close = zeroinit_close,
222 + .bdrv_getlength = zeroinit_getlength,
223 + .bdrv_co_flush_to_disk = zeroinit_co_flush,
224 +
225 + .bdrv_co_pwrite_zeroes = zeroinit_co_pwrite_zeroes,
226 + .bdrv_aio_writev = zeroinit_aio_writev,
227 + .bdrv_aio_readv = zeroinit_aio_readv,
228 + .bdrv_aio_flush = zeroinit_aio_flush,
229 +
230 + .is_filter = true,
231 + .bdrv_recurse_is_first_non_filter = zeroinit_recurse_is_first_non_filter,
232 +
233 + .bdrv_has_zero_init = zeroinit_has_zero_init,
234 +
235 + .bdrv_co_get_block_status = zeroinit_co_get_block_status,
236 +
237 + .bdrv_co_pdiscard = zeroinit_co_pdiscard,
238 +
239 + .bdrv_truncate = zeroinit_truncate,
240 + .bdrv_get_info = zeroinit_get_info,
241 +};
242 +
243 +static void bdrv_zeroinit_init(void)
244 +{
245 + bdrv_register(&bdrv_zeroinit);
246 +}
247 +
248 +block_init(bdrv_zeroinit_init);
249 --
250 2.1.4
251