]> git.proxmox.com Git - pve-qemu-kvm.git/blob - debian/patches/pve/0044-block-add-zeroinit.patch
03fc92a27320f37b8c770855d51e080094262155
[pve-qemu-kvm.git] / debian / patches / pve / 0044-block-add-zeroinit.patch
1 From 8b996ca2740d40027652ea63f52bed8f9271331b 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] block: add the zeroinit block driver filter
5
6 ---
7 block/Makefile.objs | 1 +
8 block/zeroinit.c | 216 ++++++++++++++++++++++++++++++++++++++++++++++++++++
9 2 files changed, 217 insertions(+)
10 create mode 100644 block/zeroinit.c
11
12 diff --git a/block/Makefile.objs b/block/Makefile.objs
13 index 58ef2ef..5bb55b0 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-$(CONFIG_VHDX) += 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
22 block-obj-y += block-backend.o snapshot.o qapi.o
23 block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o
24 diff --git a/block/zeroinit.c b/block/zeroinit.c
25 new file mode 100644
26 index 0000000..04a9bd0
27 --- /dev/null
28 +++ b/block/zeroinit.c
29 @@ -0,0 +1,216 @@
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 "block/block_int.h"
41 +#include "qapi/qmp/qdict.h"
42 +#include "qapi/qmp/qstring.h"
43 +
44 +typedef struct {
45 + bool has_zero_init;
46 + int64_t extents;
47 +} BDRVZeroinitState;
48 +
49 +/* Valid blkverify filenames look like blkverify:path/to/raw_image:path/to/image */
50 +static void zeroinit_parse_filename(const char *filename, QDict *options,
51 + Error **errp)
52 +{
53 + QString *raw_path;
54 +
55 + /* Parse the blkverify: prefix */
56 + if (!strstart(filename, "zeroinit:", &filename)) {
57 + /* There was no prefix; therefore, all options have to be already
58 + present in the QDict (except for the filename) */
59 + return;
60 + }
61 +
62 + raw_path = qstring_from_str(filename);
63 + qdict_put(options, "x-next", raw_path);
64 +}
65 +
66 +static QemuOptsList runtime_opts = {
67 + .name = "zeroinit",
68 + .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
69 + .desc = {
70 + {
71 + .name = "x-next",
72 + .type = QEMU_OPT_STRING,
73 + .help = "[internal use only, will be removed]",
74 + },
75 + {
76 + .name = "x-zeroinit",
77 + .type = QEMU_OPT_BOOL,
78 + .help = "set has_initialized_zero flag",
79 + },
80 + { /* end of list */ }
81 + },
82 +};
83 +
84 +static int zeroinit_open(BlockDriverState *bs, QDict *options, int flags,
85 + Error **errp)
86 +{
87 + BDRVZeroinitState *s = bs->opaque;
88 + QemuOpts *opts;
89 + Error *local_err = NULL;
90 + int ret;
91 +
92 + s->extents = 0;
93 +
94 + opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
95 + qemu_opts_absorb_qdict(opts, options, &local_err);
96 + if (local_err) {
97 + error_propagate(errp, local_err);
98 + ret = -EINVAL;
99 + goto fail;
100 + }
101 +
102 + /* Open the raw file */
103 + bs->file = bdrv_open_child(qemu_opt_get(opts, "x-next"), options, "next",
104 + bs, &child_file, false, &local_err);
105 + if (local_err) {
106 + ret = -EINVAL;
107 + error_propagate(errp, local_err);
108 + goto fail;
109 + }
110 +
111 + /* set the options */
112 + s->has_zero_init = qemu_opt_get_bool(opts, "x-zeroinit", true);
113 +
114 + ret = 0;
115 +fail:
116 + if (ret < 0) {
117 + bdrv_unref_child(bs, bs->file);
118 + }
119 + qemu_opts_del(opts);
120 + return ret;
121 +}
122 +
123 +static void zeroinit_close(BlockDriverState *bs)
124 +{
125 + BDRVZeroinitState *s = bs->opaque;
126 + (void)s;
127 +}
128 +
129 +static int64_t zeroinit_getlength(BlockDriverState *bs)
130 +{
131 + return bdrv_getlength(bs->file->bs);
132 +}
133 +
134 +static BlockAIOCB *zeroinit_aio_readv(BlockDriverState *bs,
135 + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
136 + BlockCompletionFunc *cb, void *opaque)
137 +{
138 + return bdrv_aio_readv(bs->file->bs, sector_num, qiov, nb_sectors,
139 + cb, opaque);
140 +}
141 +
142 +static int coroutine_fn zeroinit_co_write_zeroes(BlockDriverState *bs, int64_t sector_num,
143 + int nb_sectors, BdrvRequestFlags flags)
144 +{
145 + BDRVZeroinitState *s = bs->opaque;
146 + if (sector_num >= s->extents)
147 + return 0;
148 + return bdrv_write_zeroes(bs->file->bs, sector_num, nb_sectors, flags);
149 +}
150 +
151 +static BlockAIOCB *zeroinit_aio_writev(BlockDriverState *bs,
152 + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
153 + BlockCompletionFunc *cb, void *opaque)
154 +{
155 + BDRVZeroinitState *s = bs->opaque;
156 + int64_t extents = sector_num + nb_sectors + 1;
157 + if (extents > s->extents)
158 + s->extents = extents;
159 + return bdrv_aio_writev(bs->file->bs, sector_num, qiov, nb_sectors,
160 + cb, opaque);
161 +}
162 +
163 +static BlockAIOCB *zeroinit_aio_flush(BlockDriverState *bs,
164 + BlockCompletionFunc *cb,
165 + void *opaque)
166 +{
167 + return bdrv_aio_flush(bs->file->bs, cb, opaque);
168 +}
169 +
170 +static bool zeroinit_recurse_is_first_non_filter(BlockDriverState *bs,
171 + BlockDriverState *candidate)
172 +{
173 + return bdrv_recurse_is_first_non_filter(bs->file->bs, candidate);
174 +}
175 +
176 +static coroutine_fn int zeroinit_co_flush(BlockDriverState *bs)
177 +{
178 + return bdrv_co_flush(bs->file->bs);
179 +}
180 +
181 +static int zeroinit_has_zero_init(BlockDriverState *bs)
182 +{
183 + BDRVZeroinitState *s = bs->opaque;
184 + return s->has_zero_init;
185 +}
186 +
187 +static int64_t coroutine_fn zeroinit_co_get_block_status(BlockDriverState *bs,
188 + int64_t sector_num,
189 + int nb_sectors, int *pnum)
190 +{
191 + return bdrv_get_block_status(bs->file->bs, sector_num, nb_sectors, pnum);
192 +}
193 +
194 +static coroutine_fn BlockAIOCB *zeroinit_aio_discard(BlockDriverState *bs,
195 + int64_t sector_num, int nb_sectors,
196 + BlockCompletionFunc *cb, void *opaque)
197 +{
198 + return bdrv_aio_discard(bs->file->bs, sector_num, nb_sectors, cb, opaque);
199 +}
200 +
201 +static int zeroinit_truncate(BlockDriverState *bs, int64_t offset)
202 +{
203 + return bdrv_truncate(bs->file->bs, offset);
204 +}
205 +
206 +static int zeroinit_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
207 +{
208 + return bdrv_get_info(bs->file->bs, bdi);
209 +}
210 +
211 +static BlockDriver bdrv_zeroinit = {
212 + .format_name = "zeroinit",
213 + .protocol_name = "zeroinit",
214 + .instance_size = sizeof(BDRVZeroinitState),
215 +
216 + .bdrv_parse_filename = zeroinit_parse_filename,
217 + .bdrv_file_open = zeroinit_open,
218 + .bdrv_close = zeroinit_close,
219 + .bdrv_getlength = zeroinit_getlength,
220 + .bdrv_co_flush_to_disk = zeroinit_co_flush,
221 +
222 + .bdrv_co_write_zeroes = zeroinit_co_write_zeroes,
223 + .bdrv_aio_writev = zeroinit_aio_writev,
224 + .bdrv_aio_readv = zeroinit_aio_readv,
225 + .bdrv_aio_flush = zeroinit_aio_flush,
226 +
227 + .is_filter = true,
228 + .bdrv_recurse_is_first_non_filter = zeroinit_recurse_is_first_non_filter,
229 +
230 + .bdrv_has_zero_init = zeroinit_has_zero_init,
231 +
232 + .bdrv_co_get_block_status = zeroinit_co_get_block_status,
233 +
234 + .bdrv_aio_discard = zeroinit_aio_discard,
235 +
236 + .bdrv_truncate = zeroinit_truncate,
237 + .bdrv_get_info = zeroinit_get_info,
238 +};
239 +
240 +static void bdrv_zeroinit_init(void)
241 +{
242 + bdrv_register(&bdrv_zeroinit);
243 +}
244 +
245 +block_init(bdrv_zeroinit_init);
246 --
247 2.1.4
248