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
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>
10 block/meson.build | 1 +
11 block/zeroinit.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++
12 2 files changed, 201 insertions(+)
13 create mode 100644 block/zeroinit.c
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(
24 ), zstd, zlib, gnutls)
26 system_ss.add(when: 'CONFIG_TCG', if_true: files('blkreplay.c'))
27 diff --git a/block/zeroinit.c b/block/zeroinit.c
29 index 0000000000..1257342724
31 +++ b/block/zeroinit.c
34 + * Filter to fake a zero-initialized block device.
36 + * Copyright (c) 2016 Wolfgang Bumiller <w.bumiller@proxmox.com>
37 + * Copyright (c) 2016 Proxmox Server Solutions GmbH
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.
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"
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,
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) */
71 + raw_path = qstring_from_str(filename);
72 + qdict_put(options, "x-next", raw_path);
75 +static QemuOptsList runtime_opts = {
77 + .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
81 + .type = QEMU_OPT_STRING,
82 + .help = "[internal use only, will be removed]",
85 + .name = "x-zeroinit",
86 + .type = QEMU_OPT_BOOL,
87 + .help = "set has_initialized_zero flag",
89 + { /* end of list */ }
93 +static int zeroinit_open(BlockDriverState *bs, QDict *options, int flags,
96 + BDRVZeroinitState *s = bs->opaque;
98 + Error *local_err = NULL;
103 + opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
104 + qemu_opts_absorb_qdict(opts, options, &local_err);
106 + error_propagate(errp, local_err);
111 + /* Open the raw file */
112 + bs->file = bdrv_open_child(qemu_opt_get(opts, "x-next"), options, "next",
114 + BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
115 + false, &local_err);
118 + error_propagate(errp, local_err);
122 + /* set the options */
123 + s->has_zero_init = qemu_opt_get_bool(opts, "x-zeroinit", true);
128 + bdrv_unref_child(bs, bs->file);
130 + qemu_opts_del(opts);
134 +static void zeroinit_close(BlockDriverState *bs)
136 + BDRVZeroinitState *s = bs->opaque;
140 +static coroutine_fn int64_t zeroinit_co_getlength(BlockDriverState *bs)
142 + return bdrv_co_getlength(bs->file->bs);
145 +static int coroutine_fn zeroinit_co_preadv(BlockDriverState *bs,
146 + int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
148 + return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
151 +static int coroutine_fn zeroinit_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
152 + int64_t bytes, BdrvRequestFlags flags)
154 + BDRVZeroinitState *s = bs->opaque;
155 + if (offset >= s->extents)
157 + return bdrv_pwrite_zeroes(bs->file, offset, bytes, flags);
160 +static int coroutine_fn zeroinit_co_pwritev(BlockDriverState *bs,
161 + int64_t offset, int64_t bytes, QEMUIOVector *qiov, BdrvRequestFlags flags)
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);
170 +static coroutine_fn int zeroinit_co_flush(BlockDriverState *bs)
172 + return bdrv_co_flush(bs->file->bs);
175 +static int zeroinit_has_zero_init(BlockDriverState *bs)
177 + BDRVZeroinitState *s = bs->opaque;
178 + return s->has_zero_init;
181 +static int coroutine_fn zeroinit_co_pdiscard(BlockDriverState *bs,
182 + int64_t offset, int64_t bytes)
184 + return bdrv_co_pdiscard(bs->file, offset, bytes);
187 +static int zeroinit_co_truncate(BlockDriverState *bs, int64_t offset,
188 + _Bool exact, PreallocMode prealloc,
189 + BdrvRequestFlags req_flags, Error **errp)
191 + return bdrv_co_truncate(bs->file, offset, exact, prealloc, req_flags, errp);
194 +static coroutine_fn int zeroinit_co_get_info(BlockDriverState *bs,
195 + BlockDriverInfo *bdi)
197 + return bdrv_co_get_info(bs->file->bs, bdi);
200 +static BlockDriver bdrv_zeroinit = {
201 + .format_name = "zeroinit",
202 + .protocol_name = "zeroinit",
203 + .instance_size = sizeof(BDRVZeroinitState),
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,
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,
219 + .bdrv_has_zero_init = zeroinit_has_zero_init,
221 + .bdrv_co_pdiscard = zeroinit_co_pdiscard,
223 + .bdrv_co_truncate = zeroinit_co_truncate,
224 + .bdrv_co_get_info = zeroinit_co_get_info,
227 +static void bdrv_zeroinit_init(void)
229 + bdrv_register(&bdrv_zeroinit);
232 +block_init(bdrv_zeroinit_init);