]> git.proxmox.com Git - pve-qemu.git/blob - debian/patches/pve/0019-PVE-block-add-the-zeroinit-block-driver-filter.patch
backup: improve error when copy-before-write fails for fleecing
[pve-qemu.git] / debian / patches / pve / 0019-PVE-block-add-the-zeroinit-block-driver-filter.patch
1 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 From: Wolfgang Bumiller <w.bumiller@proxmox.com>
3 Date: Mon, 6 Apr 2020 12:16:47 +0200
4 Subject: [PATCH] PVE: block: add the zeroinit block driver filter
5
6 Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
7 [FE: adapt to changed function signatures]
8 Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
9 ---
10 block/meson.build | 1 +
11 block/zeroinit.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++
12 2 files changed, 201 insertions(+)
13 create mode 100644 block/zeroinit.c
14
15 diff --git a/block/meson.build b/block/meson.build
16 index 529fc172c6..1833c71ce9 100644
17 --- a/block/meson.build
18 +++ b/block/meson.build
19 @@ -40,6 +40,7 @@ block_ss.add(files(
20 'throttle-groups.c',
21 'throttle.c',
22 'write-threshold.c',
23 + 'zeroinit.c',
24 ), zstd, zlib, gnutls)
25
26 system_ss.add(when: 'CONFIG_TCG', if_true: files('blkreplay.c'))
27 diff --git a/block/zeroinit.c b/block/zeroinit.c
28 new file mode 100644
29 index 0000000000..1257342724
30 --- /dev/null
31 +++ b/block/zeroinit.c
32 @@ -0,0 +1,200 @@
33 +/*
34 + * Filter to fake a zero-initialized block device.
35 + *
36 + * Copyright (c) 2016 Wolfgang Bumiller <w.bumiller@proxmox.com>
37 + * Copyright (c) 2016 Proxmox Server Solutions GmbH
38 + *
39 + * This work is licensed under the terms of the GNU GPL, version 2 or later.
40 + * See the COPYING file in the top-level directory.
41 + */
42 +
43 +#include "qemu/osdep.h"
44 +#include "qapi/error.h"
45 +#include "block/block_int.h"
46 +#include "block/block-io.h"
47 +#include "qapi/qmp/qdict.h"
48 +#include "qapi/qmp/qstring.h"
49 +#include "qemu/cutils.h"
50 +#include "qemu/option.h"
51 +#include "qemu/module.h"
52 +
53 +typedef struct {
54 + bool has_zero_init;
55 + int64_t extents;
56 +} BDRVZeroinitState;
57 +
58 +/* Valid blkverify filenames look like blkverify:path/to/raw_image:path/to/image */
59 +static void zeroinit_parse_filename(const char *filename, QDict *options,
60 + Error **errp)
61 +{
62 + QString *raw_path;
63 +
64 + /* Parse the blkverify: prefix */
65 + if (!strstart(filename, "zeroinit:", &filename)) {
66 + /* There was no prefix; therefore, all options have to be already
67 + present in the QDict (except for the filename) */
68 + return;
69 + }
70 +
71 + raw_path = qstring_from_str(filename);
72 + qdict_put(options, "x-next", raw_path);
73 +}
74 +
75 +static QemuOptsList runtime_opts = {
76 + .name = "zeroinit",
77 + .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
78 + .desc = {
79 + {
80 + .name = "x-next",
81 + .type = QEMU_OPT_STRING,
82 + .help = "[internal use only, will be removed]",
83 + },
84 + {
85 + .name = "x-zeroinit",
86 + .type = QEMU_OPT_BOOL,
87 + .help = "set has_initialized_zero flag",
88 + },
89 + { /* end of list */ }
90 + },
91 +};
92 +
93 +static int zeroinit_open(BlockDriverState *bs, QDict *options, int flags,
94 + Error **errp)
95 +{
96 + BDRVZeroinitState *s = bs->opaque;
97 + QemuOpts *opts;
98 + Error *local_err = NULL;
99 + int ret;
100 +
101 + s->extents = 0;
102 +
103 + opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
104 + qemu_opts_absorb_qdict(opts, options, &local_err);
105 + if (local_err) {
106 + error_propagate(errp, local_err);
107 + ret = -EINVAL;
108 + goto fail;
109 + }
110 +
111 + /* Open the raw file */
112 + bs->file = bdrv_open_child(qemu_opt_get(opts, "x-next"), options, "next",
113 + bs, &child_of_bds,
114 + BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
115 + false, &local_err);
116 + if (local_err) {
117 + ret = -EINVAL;
118 + error_propagate(errp, local_err);
119 + goto fail;
120 + }
121 +
122 + /* set the options */
123 + s->has_zero_init = qemu_opt_get_bool(opts, "x-zeroinit", true);
124 +
125 + ret = 0;
126 +fail:
127 + if (ret < 0) {
128 + bdrv_unref_child(bs, bs->file);
129 + }
130 + qemu_opts_del(opts);
131 + return ret;
132 +}
133 +
134 +static void zeroinit_close(BlockDriverState *bs)
135 +{
136 + BDRVZeroinitState *s = bs->opaque;
137 + (void)s;
138 +}
139 +
140 +static coroutine_fn int64_t zeroinit_co_getlength(BlockDriverState *bs)
141 +{
142 + return bdrv_co_getlength(bs->file->bs);
143 +}
144 +
145 +static int coroutine_fn zeroinit_co_preadv(BlockDriverState *bs,
146 + int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
147 +{
148 + return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
149 +}
150 +
151 +static int coroutine_fn zeroinit_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
152 + int64_t bytes, BdrvRequestFlags flags)
153 +{
154 + BDRVZeroinitState *s = bs->opaque;
155 + if (offset >= s->extents)
156 + return 0;
157 + return bdrv_pwrite_zeroes(bs->file, offset, bytes, flags);
158 +}
159 +
160 +static int coroutine_fn zeroinit_co_pwritev(BlockDriverState *bs,
161 + int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
162 +{
163 + BDRVZeroinitState *s = bs->opaque;
164 + int64_t extents = offset + bytes;
165 + if (extents > s->extents)
166 + s->extents = extents;
167 + return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
168 +}
169 +
170 +static coroutine_fn int zeroinit_co_flush(BlockDriverState *bs)
171 +{
172 + return bdrv_co_flush(bs->file->bs);
173 +}
174 +
175 +static int zeroinit_has_zero_init(BlockDriverState *bs)
176 +{
177 + BDRVZeroinitState *s = bs->opaque;
178 + return s->has_zero_init;
179 +}
180 +
181 +static int coroutine_fn zeroinit_co_pdiscard(BlockDriverState *bs,
182 + int64_t offset, int64_t bytes)
183 +{
184 + return bdrv_co_pdiscard(bs->file, offset, bytes);
185 +}
186 +
187 +static int zeroinit_co_truncate(BlockDriverState *bs, int64_t offset,
188 + _Bool exact, PreallocMode prealloc,
189 + BdrvRequestFlags req_flags, Error **errp)
190 +{
191 + return bdrv_co_truncate(bs->file, offset, exact, prealloc, req_flags, errp);
192 +}
193 +
194 +static coroutine_fn int zeroinit_co_get_info(BlockDriverState *bs,
195 + BlockDriverInfo *bdi)
196 +{
197 + return bdrv_co_get_info(bs->file->bs, bdi);
198 +}
199 +
200 +static BlockDriver bdrv_zeroinit = {
201 + .format_name = "zeroinit",
202 + .protocol_name = "zeroinit",
203 + .instance_size = sizeof(BDRVZeroinitState),
204 +
205 + .bdrv_parse_filename = zeroinit_parse_filename,
206 + .bdrv_file_open = zeroinit_open,
207 + .bdrv_close = zeroinit_close,
208 + .bdrv_co_getlength = zeroinit_co_getlength,
209 + .bdrv_child_perm = bdrv_default_perms,
210 + .bdrv_co_flush_to_disk = zeroinit_co_flush,
211 +
212 + .bdrv_co_pwrite_zeroes = zeroinit_co_pwrite_zeroes,
213 + .bdrv_co_pwritev = zeroinit_co_pwritev,
214 + .bdrv_co_preadv = zeroinit_co_preadv,
215 + .bdrv_co_flush = zeroinit_co_flush,
216 +
217 + .is_filter = true,
218 +
219 + .bdrv_has_zero_init = zeroinit_has_zero_init,
220 +
221 + .bdrv_co_pdiscard = zeroinit_co_pdiscard,
222 +
223 + .bdrv_co_truncate = zeroinit_co_truncate,
224 + .bdrv_co_get_info = zeroinit_co_get_info,
225 +};
226 +
227 +static void bdrv_zeroinit_init(void)
228 +{
229 + bdrv_register(&bdrv_zeroinit);
230 +}
231 +
232 +block_init(bdrv_zeroinit_init);